decal
This commit is contained in:
@ -9,14 +9,12 @@ function App() {
|
|||||||
return (
|
return (
|
||||||
<ChakraProvider>
|
<ChakraProvider>
|
||||||
<div className={"relative flex h-screen w-screen"}>
|
<div className={"relative flex h-screen w-screen"}>
|
||||||
{/*<ThreeDesigner />*/}
|
|
||||||
<div className={"flex-[5] shrink-0"}>
|
<div className={"flex-[5] shrink-0"}>
|
||||||
<ThreeScene />
|
<ThreeScene />
|
||||||
</div>
|
</div>
|
||||||
<div className={"flex-[2] shrink-0 bg-blue-50 p-4"}>
|
<div className={"flex-[2] shrink-0 bg-blue-50 p-4"}>
|
||||||
<RightPanel />
|
<RightPanel />
|
||||||
</div>
|
</div>
|
||||||
{/* <AreaIndicator /> */}
|
|
||||||
{modelLoading !== 0 && modelLoading !== 100 && (
|
{modelLoading !== 0 && modelLoading !== 100 && (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
import { Object3D, TextureLoader, Vector3 } from "three";
|
|
||||||
import useModelStore from "@/store/useModelStore.ts";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { models } from "@/constant/models.ts";
|
|
||||||
import { textures } from "@/constant/textures.ts";
|
|
||||||
|
|
||||||
const CapMesh = ({
|
|
||||||
areaIndex,
|
|
||||||
mesh,
|
|
||||||
}: {
|
|
||||||
areaIndex: number;
|
|
||||||
mesh: Object3D;
|
|
||||||
}) => {
|
|
||||||
const logo = useTexture("/textures/archlogo.png");
|
|
||||||
const activeModel = useModelStore((state) => state.activeModel);
|
|
||||||
const activeTextures = useModelStore((state) => state.activeTextures);
|
|
||||||
const [pos, setPos] = useState<Vector3>(new Vector3(0, 0, 0));
|
|
||||||
return (
|
|
||||||
<mesh
|
|
||||||
onClick={(ev) => {
|
|
||||||
const { x, y, z } = ev.point;
|
|
||||||
setPos(
|
|
||||||
new Vector3(
|
|
||||||
x / models[activeModel].scale,
|
|
||||||
y / models[activeModel].scale,
|
|
||||||
z / models[activeModel].scale,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
castShadow
|
|
||||||
receiveShadow
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-expect-error
|
|
||||||
geometry={mesh.geometry}
|
|
||||||
dispose={null}
|
|
||||||
>
|
|
||||||
{areaIndex > -1 ? (
|
|
||||||
<meshStandardMaterial
|
|
||||||
map={new TextureLoader().load(
|
|
||||||
textures[activeTextures[areaIndex]].path,
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<meshStandardMaterial color="gray" />
|
|
||||||
)}
|
|
||||||
<Decal position={pos} scale={0.05} rotation={Math.PI}>
|
|
||||||
<meshPhysicalMaterial
|
|
||||||
transparent
|
|
||||||
polygonOffset
|
|
||||||
polygonOffsetFactor={-10}
|
|
||||||
map={logo}
|
|
||||||
map-flipY={false}
|
|
||||||
map-anisotropy={16}
|
|
||||||
iridescence={1}
|
|
||||||
iridescenceIOR={1}
|
|
||||||
iridescenceThicknessRange={[0, 1400]}
|
|
||||||
roughness={1}
|
|
||||||
clearcoat={0.5}
|
|
||||||
metalness={0.75}
|
|
||||||
toneMapped={false}
|
|
||||||
/>
|
|
||||||
</Decal>
|
|
||||||
</mesh>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,9 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
const DebugPanel = () => {
|
const DebugPanel = () => {
|
||||||
return (
|
return <div>DebugPanel</div>;
|
||||||
<div>DebugPanel</div>
|
};
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DebugPanel
|
export default DebugPanel;
|
||||||
|
@ -7,11 +7,11 @@ import {
|
|||||||
ModalContent,
|
ModalContent,
|
||||||
ModalOverlay,
|
ModalOverlay,
|
||||||
Image,
|
Image,
|
||||||
IconButton
|
IconButton,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { pickFile } from "@/lib/upload";
|
import { pickFile } from "@/lib/upload";
|
||||||
import useModelStore, { StickerType } from "@/store/useModelStore";
|
import useModelStore, { StickerType } from "@/store/useModelStore";
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { Vector3 } from "three";
|
import { Vector3 } from "three";
|
||||||
|
|
||||||
const LogoPanel = () => {
|
const LogoPanel = () => {
|
||||||
@ -19,6 +19,7 @@ const LogoPanel = () => {
|
|||||||
const decals = useModelStore((state) => state.decals);
|
const decals = useModelStore((state) => state.decals);
|
||||||
const setDecals = useModelStore((state) => state.setDecals);
|
const setDecals = useModelStore((state) => state.setDecals);
|
||||||
const setActiveDecal = useModelStore((state) => state.setActiveDecal);
|
const setActiveDecal = useModelStore((state) => state.setActiveDecal);
|
||||||
|
const activeModel = useModelStore((state) => state.activeModel);
|
||||||
const activeDecal = useModelStore((state) => state.activeDecal);
|
const activeDecal = useModelStore((state) => state.activeDecal);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -28,35 +29,48 @@ const LogoPanel = () => {
|
|||||||
.map((decal) => (
|
.map((decal) => (
|
||||||
<li
|
<li
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveDecal(decal.id)
|
setActiveDecal(decal.id);
|
||||||
}}
|
}}
|
||||||
key={decal.id}
|
key={decal.id}
|
||||||
className={`mb-2 flex h-12 w-full cursor-pointer items-center justify-between rounded bg-white px-2 shadow ${decal.id === activeDecal ? "border-2 border-green-100 bg-blue-200" : ""
|
className={`mb-2 flex h-12 w-full cursor-pointer items-center justify-between rounded bg-white px-2 shadow ${
|
||||||
|
decal.id === activeDecal
|
||||||
|
? "border-2 border-green-100 bg-blue-200"
|
||||||
|
: ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Image className={"w-12 h-12 object-contain"} src={decal.url} />
|
<Image className={"h-12 w-12 object-contain"} src={decal.url} />
|
||||||
<IconButton icon={<DeleteIcon />} aria-label={""} colorScheme="red" size={"xs"} onClick={() => {
|
<IconButton
|
||||||
setDecals(decals.filter(el => el.id !== decal.id))
|
icon={<DeleteIcon />}
|
||||||
}} />
|
aria-label={""}
|
||||||
|
colorScheme="red"
|
||||||
|
size={"xs"}
|
||||||
|
onClick={() => {
|
||||||
|
setDecals(decals.filter((el) => el.id !== decal.id));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
<div className="flex justify-center mt-4">
|
<div className="mt-4 flex justify-center">
|
||||||
<Button
|
<Button
|
||||||
colorScheme="messenger"
|
colorScheme="messenger"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
pickFile({
|
pickFile({
|
||||||
accept: ["image/png"],
|
accept: ["image/png"],
|
||||||
}).then((files) => {
|
}).then((files) => {
|
||||||
if (!files.length) return
|
if (!files.length) return;
|
||||||
const id = uuidv4()
|
const id = uuidv4();
|
||||||
setDecals([...decals, {
|
setDecals([
|
||||||
|
...decals,
|
||||||
|
{
|
||||||
id,
|
id,
|
||||||
url: URL.createObjectURL(files[0]),
|
url: URL.createObjectURL(files[0]),
|
||||||
postion: new Vector3(0, 0, 0),
|
postion: new Vector3(0, 0, 0),
|
||||||
type: StickerType.logo
|
type: StickerType.logo,
|
||||||
}])
|
scale: activeModel ? 1.5 : 0.05,
|
||||||
setActiveDecal(id)
|
},
|
||||||
|
]);
|
||||||
|
setActiveDecal(id);
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
leftIcon={<AddIcon />}
|
leftIcon={<AddIcon />}
|
||||||
@ -76,7 +90,7 @@ const LogoPanel = () => {
|
|||||||
<ModalBody>
|
<ModalBody>
|
||||||
<div className="flex justify-center p-4">
|
<div className="flex justify-center p-4">
|
||||||
<div
|
<div
|
||||||
onClick={() => { }}
|
onClick={() => {}}
|
||||||
className={
|
className={
|
||||||
"flex aspect-square w-24 cursor-pointer items-center justify-center rounded-lg border-2 border-gray-300"
|
"flex aspect-square w-24 cursor-pointer items-center justify-center rounded-lg border-2 border-gray-300"
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,8 @@ const RightPanel = () => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActiveModel(index);
|
setActiveModel(index);
|
||||||
}}
|
}}
|
||||||
className={`${activeModel === index ? "border-2 border-green-300" : ""
|
className={`${
|
||||||
|
activeModel === index ? "border-2 border-green-300" : ""
|
||||||
} flex aspect-square items-center justify-center overflow-hidden rounded-xl bg-blue-100`}
|
} flex aspect-square items-center justify-center overflow-hidden rounded-xl bg-blue-100`}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import useModelStore, { DecalSticker } from "@/store/useModelStore";
|
import useModelStore, { DecalSticker } from "@/store/useModelStore";
|
||||||
import { Decal, useTexture } from "@react-three/drei";
|
import { Decal, useTexture } from "@react-three/drei";
|
||||||
import { useState } from "react";
|
import { Euler } from "three";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* logo 和文字标签
|
* logo 和文字标签
|
||||||
@ -9,32 +9,47 @@ import { useState } from "react";
|
|||||||
*/
|
*/
|
||||||
const Sticker = ({ decal }: { decal: DecalSticker }) => {
|
const Sticker = ({ decal }: { decal: DecalSticker }) => {
|
||||||
const sticker = useTexture(decal.url);
|
const sticker = useTexture(decal.url);
|
||||||
const [scale, setScale] = useState(0.05);
|
|
||||||
const setDecalDragging = useModelStore((state) => state.setDecalDragging);
|
const setDecalDragging = useModelStore((state) => state.setDecalDragging);
|
||||||
|
const setDecalScale = useModelStore((state) => state.setDecalScale);
|
||||||
const setActiveDecal = useModelStore((state) => state.setActiveDecal);
|
const setActiveDecal = useModelStore((state) => state.setActiveDecal);
|
||||||
|
// useInterval(() => {
|
||||||
|
// setRotation(state => state += 0.001 * Math.PI)
|
||||||
|
// }, 10)
|
||||||
return (
|
return (
|
||||||
<Decal
|
<Decal
|
||||||
|
debug={true}
|
||||||
position={decal.postion}
|
position={decal.postion}
|
||||||
scale={scale}
|
scale={decal.scale}
|
||||||
onPointerDown={(ev) => {
|
onPointerDown={(ev) => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
setActiveDecal(decal.id)
|
setActiveDecal(decal.id);
|
||||||
setDecalDragging(true);
|
setDecalDragging(true);
|
||||||
}}
|
}}
|
||||||
onPointerUp={(ev) => {
|
onPointerUp={(ev) => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
setDecalDragging(false);
|
setDecalDragging(false);
|
||||||
}}
|
}}
|
||||||
// onWheel={(ev) => {
|
onPointerEnter={(_ev) => {
|
||||||
// ev.stopPropagation()
|
// ev.ctrlKey
|
||||||
// setDecalDragging(true)
|
}}
|
||||||
// console.log(ev);
|
onWheel={(ev) => {
|
||||||
|
ev.stopPropagation();
|
||||||
// // setScale((state) => state += 1)
|
// setDecalDragging(true);
|
||||||
// }}
|
// setDecals()
|
||||||
|
if (!ev.altKey) return;
|
||||||
|
if (ev.deltaY > 0) {
|
||||||
|
// setScale(state => state += 0.01)
|
||||||
|
setDecalScale(decal.id, (decal.scale -= 0.01));
|
||||||
|
} else if (ev.deltaY < 0) {
|
||||||
|
setDecalScale(decal.id, (decal.scale += 0.01));
|
||||||
|
// setScale(state => state -= 0.01)
|
||||||
|
}
|
||||||
|
}}
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
rotation={Math.PI}
|
rotation={Math.PI}
|
||||||
|
// rotation={new Euler(Math.PI / 2, 0, 0)}
|
||||||
|
// rotation={[Math.PI * 1, Math.PI * 1, Math.PI * 1]}
|
||||||
>
|
>
|
||||||
<meshPhysicalMaterial
|
<meshPhysicalMaterial
|
||||||
transparent
|
transparent
|
||||||
|
@ -16,6 +16,7 @@ const TextLabelPanel = () => {
|
|||||||
const decals = useModelStore((state) => state.decals);
|
const decals = useModelStore((state) => state.decals);
|
||||||
const setDecals = useModelStore((state) => state.setDecals);
|
const setDecals = useModelStore((state) => state.setDecals);
|
||||||
const setActiveDecal = useModelStore((state) => state.setActiveDecal);
|
const setActiveDecal = useModelStore((state) => state.setActiveDecal);
|
||||||
|
const activeModel = useModelStore((state) => state.activeModel);
|
||||||
const activeDecal = useModelStore((state) => state.activeDecal);
|
const activeDecal = useModelStore((state) => state.activeDecal);
|
||||||
const [editing, setEditing] = useState(false);
|
const [editing, setEditing] = useState(false);
|
||||||
const [text, setText] = useState("");
|
const [text, setText] = useState("");
|
||||||
@ -70,6 +71,7 @@ const TextLabelPanel = () => {
|
|||||||
text,
|
text,
|
||||||
url: fabricCanvas.toDataURL(),
|
url: fabricCanvas.toDataURL(),
|
||||||
type: StickerType.text,
|
type: StickerType.text,
|
||||||
|
scale: activeModel ? 1.5 : 0.05,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
setText(() => "");
|
setText(() => "");
|
||||||
@ -91,7 +93,10 @@ const TextLabelPanel = () => {
|
|||||||
setActiveDecal(text.id);
|
setActiveDecal(text.id);
|
||||||
}}
|
}}
|
||||||
key={text.id}
|
key={text.id}
|
||||||
className={`mb-2 flex h-12 w-full cursor-pointer items-center justify-between rounded bg-white px-2 shadow ${activeDecal === text.id ? "border-2 border-green-100 bg-blue-200" : ""
|
className={`mb-2 flex h-12 w-full cursor-pointer items-center justify-between rounded bg-white px-2 shadow ${
|
||||||
|
activeDecal === text.id
|
||||||
|
? "border-2 border-green-100 bg-blue-200"
|
||||||
|
: ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span>{text.text}</span>
|
<span>{text.text}</span>
|
||||||
@ -108,7 +113,7 @@ const TextLabelPanel = () => {
|
|||||||
className={"ml-1"}
|
className={"ml-1"}
|
||||||
onClick={(ev) => {
|
onClick={(ev) => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
setDecals(decals.filter(el => el.id !== text.id))
|
setDecals(decals.filter((el) => el.id !== text.id));
|
||||||
}}
|
}}
|
||||||
size={"xs"}
|
size={"xs"}
|
||||||
icon={<DeleteIcon />}
|
icon={<DeleteIcon />}
|
||||||
|
@ -6,7 +6,7 @@ import { models } from "@/constant/models.ts";
|
|||||||
import { useGLTF } from "@react-three/drei/core/useGLTF";
|
import { useGLTF } from "@react-three/drei/core/useGLTF";
|
||||||
import { textures } from "@/constant/textures.ts";
|
import { textures } from "@/constant/textures.ts";
|
||||||
import Sticker from "./Sticker";
|
import Sticker from "./Sticker";
|
||||||
import { useWhyDidYouUpdate } from "ahooks";
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
const CapModel = () => {
|
const CapModel = () => {
|
||||||
const activeModel = useModelStore((state) => state.activeModel);
|
const activeModel = useModelStore((state) => state.activeModel);
|
||||||
@ -14,9 +14,33 @@ const CapModel = () => {
|
|||||||
const decalDragging = useModelStore((state) => state.decalDragging);
|
const decalDragging = useModelStore((state) => state.decalDragging);
|
||||||
const activeDecal = useModelStore((state) => state.activeDecal);
|
const activeDecal = useModelStore((state) => state.activeDecal);
|
||||||
const setDecalPositon = useModelStore((state) => state.setDecalPositon);
|
const setDecalPositon = useModelStore((state) => state.setDecalPositon);
|
||||||
useWhyDidYouUpdate('useWhyDidYouUpdateComponent', {
|
|
||||||
activeDecal, decalDragging, activeTextures, activeModel
|
const [isAltDown, setIsAltDown] = useState(false);
|
||||||
});
|
|
||||||
|
useEffect(() => {
|
||||||
|
function handleKeyDown(event: any) {
|
||||||
|
if (event.key === "Alt") {
|
||||||
|
setIsAltDown(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKeyUp(event: any) {
|
||||||
|
if (event.key === "Alt") {
|
||||||
|
setIsAltDown(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听键盘按下和释放事件
|
||||||
|
window.addEventListener("keydown", handleKeyDown);
|
||||||
|
window.addEventListener("keyup", handleKeyUp);
|
||||||
|
|
||||||
|
// 组件卸载时移除事件监听器
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("keydown", handleKeyDown);
|
||||||
|
window.removeEventListener("keyup", handleKeyUp);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const { nodes } = useGLTF(models[activeModel].path);
|
const { nodes } = useGLTF(models[activeModel].path);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -46,6 +70,7 @@ const CapModel = () => {
|
|||||||
key={keyName}
|
key={keyName}
|
||||||
onDoubleClick={(ev) => {
|
onDoubleClick={(ev) => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
|
||||||
if (activeDecal) {
|
if (activeDecal) {
|
||||||
const { x, y, z } = ev.point;
|
const { x, y, z } = ev.point;
|
||||||
const pos = new Vector3(
|
const pos = new Vector3(
|
||||||
@ -53,6 +78,18 @@ const CapModel = () => {
|
|||||||
y / models[activeModel].scale,
|
y / models[activeModel].scale,
|
||||||
z / models[activeModel].scale,
|
z / models[activeModel].scale,
|
||||||
);
|
);
|
||||||
|
// console.log(ev.point.transformDirection(ev.intersections[0].object.matrixWorld));
|
||||||
|
const normal = ev.face?.normal;
|
||||||
|
// normal?.transformDirection(ev.intersections[0].object.matrixWorld)
|
||||||
|
// normal?.applyQuaternion(ev.object.quaternion)
|
||||||
|
normal?.normalize();
|
||||||
|
console.log(normal);
|
||||||
|
console.log(normal?.angleTo(new Vector3(0, 1, 0)));
|
||||||
|
|
||||||
|
// const y_a = normal?.angleTo(new Vector3(0, 1, 0))
|
||||||
|
// const x_a = normal?.angleTo(new Vector3(1, 0, 0))
|
||||||
|
// const z_a = normal?.angleTo(new Vector3(0, 0, 1))
|
||||||
|
// console.log(x_a, y_a, z_a);
|
||||||
setDecalPositon(activeDecal, pos);
|
setDecalPositon(activeDecal, pos);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -80,13 +117,11 @@ const CapModel = () => {
|
|||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
</group>
|
</group>
|
||||||
<OrbitControls enabled={!decalDragging} />
|
<OrbitControls enabled={!decalDragging} enableZoom={!isAltDown} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const Stickers = () => {
|
export const Stickers = () => {
|
||||||
const decals = useModelStore((state) => state.decals);
|
const decals = useModelStore((state) => state.decals);
|
||||||
|
|
||||||
@ -96,19 +131,19 @@ export const Stickers = () => {
|
|||||||
<Sticker decal={decal} key={decal.id} />
|
<Sticker decal={decal} key={decal.id} />
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const ThreeScene = () => {
|
const ThreeScene = () => {
|
||||||
|
// const hdr = useTexture("/venice_sunset_1k.hdr")
|
||||||
return (
|
return (
|
||||||
<Canvas>
|
<Canvas>
|
||||||
<ambientLight></ambientLight>
|
<ambientLight></ambientLight>
|
||||||
<pointLight position={[10, 10, 10]}></pointLight>
|
<pointLight position={[10, 10, 10]}></pointLight>
|
||||||
<perspectiveCamera />
|
<perspectiveCamera />
|
||||||
<CapModel />
|
<CapModel />
|
||||||
<Environment preset={"city"} background={false} />
|
<axesHelper />
|
||||||
|
<Environment files={"/venice_sunset_1k.hdr"} background={false} />
|
||||||
</Canvas>
|
</Canvas>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@ import { create } from "zustand";
|
|||||||
import { models } from "@/constant/models.ts";
|
import { models } from "@/constant/models.ts";
|
||||||
import { Vector3 } from "three";
|
import { Vector3 } from "three";
|
||||||
import { devtools } from "zustand/middleware";
|
import { devtools } from "zustand/middleware";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
// import { v4 as uuidv4 } from "uuid";
|
||||||
export enum StickerType {
|
export enum StickerType {
|
||||||
text,
|
text,
|
||||||
logo,
|
logo,
|
||||||
@ -13,6 +13,7 @@ export interface DecalSticker {
|
|||||||
postion: Vector3;
|
postion: Vector3;
|
||||||
text?: string;
|
text?: string;
|
||||||
url: string;
|
url: string;
|
||||||
|
scale: number;
|
||||||
type: StickerType;
|
type: StickerType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,10 +33,14 @@ interface ModelState {
|
|||||||
decalDragging: boolean;
|
decalDragging: boolean;
|
||||||
setDecalDragging: (enable: boolean) => void;
|
setDecalDragging: (enable: boolean) => void;
|
||||||
|
|
||||||
|
decalZooming: boolean;
|
||||||
|
setDecalZooming: (enable: boolean) => void;
|
||||||
|
|
||||||
decals: DecalSticker[];
|
decals: DecalSticker[];
|
||||||
activeDecal?: string;
|
activeDecal?: string;
|
||||||
setDecalPositon: (id: string, postion: Vector3) => void;
|
setDecalPositon: (id: string, postion: Vector3) => void;
|
||||||
setDecals: (decals: DecalSticker[]) => void;
|
setDecals: (decals: DecalSticker[]) => void;
|
||||||
|
setDecalScale: (id: string, scale: number) => void;
|
||||||
setActiveDecal: (decalId: string) => void;
|
setActiveDecal: (decalId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +49,18 @@ const useModelStore = create<ModelState>()(
|
|||||||
modelLoading: 0,
|
modelLoading: 0,
|
||||||
setModelLoading: (progress: number) =>
|
setModelLoading: (progress: number) =>
|
||||||
set(() => ({ modelLoading: progress })),
|
set(() => ({ modelLoading: progress })),
|
||||||
|
setDecalScale: (id: string, scale: number) =>
|
||||||
|
set((state) => {
|
||||||
|
const _decals = state.decals.map((el) => {
|
||||||
|
if (el.id === id) {
|
||||||
|
el.scale = scale;
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
decals: _decals,
|
||||||
|
};
|
||||||
|
}),
|
||||||
activeModel: 0,
|
activeModel: 0,
|
||||||
setActiveModel: (index: number) =>
|
setActiveModel: (index: number) =>
|
||||||
set(() => ({
|
set(() => ({
|
||||||
@ -71,14 +87,11 @@ const useModelStore = create<ModelState>()(
|
|||||||
setDecalDragging: (enable: boolean) =>
|
setDecalDragging: (enable: boolean) =>
|
||||||
set(() => ({ decalDragging: enable })),
|
set(() => ({ decalDragging: enable })),
|
||||||
|
|
||||||
decals: [
|
// 是否正在缩放sticker
|
||||||
{
|
decalZooming: false,
|
||||||
id: uuidv4(),
|
setDecalZooming: (enable: boolean) => set(() => ({ decalZooming: enable })),
|
||||||
url: "/textures/archlogo.png",
|
|
||||||
postion: new Vector3(0, 0, 0),
|
decals: [],
|
||||||
type: StickerType.logo,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
activeDecal: undefined,
|
activeDecal: undefined,
|
||||||
setDecalPositon: (id: string, postion: Vector3) =>
|
setDecalPositon: (id: string, postion: Vector3) =>
|
||||||
set((state) => {
|
set((state) => {
|
||||||
@ -100,10 +113,17 @@ const useModelStore = create<ModelState>()(
|
|||||||
set(() => ({
|
set(() => ({
|
||||||
decals,
|
decals,
|
||||||
})),
|
})),
|
||||||
|
|
||||||
setActiveDecal: (decalId: string) =>
|
setActiveDecal: (decalId: string) =>
|
||||||
set(() => ({
|
set(() => ({
|
||||||
activeDecal: decalId,
|
activeDecal: decalId,
|
||||||
})),
|
})),
|
||||||
|
|
||||||
|
// // @ts-ignore
|
||||||
|
// setDecalScale: (id: string, scale: number) =>
|
||||||
|
// set(() => ({
|
||||||
|
// activeArea: 0
|
||||||
|
// })),
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user