This commit is contained in:
2023-12-21 17:29:10 +08:00
parent ec316824b7
commit 18fd617a01
9 changed files with 367 additions and 348 deletions

View File

@ -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={

View File

@ -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>
);
};

View File

@ -1,9 +1,5 @@
const DebugPanel = () => { const DebugPanel = () => {
return ( return <div>DebugPanel</div>;
<div>DebugPanel</div> };
)
}
export default DebugPanel export default DebugPanel;

View File

@ -1,94 +1,108 @@
import { useState } from "react"; import { useState } from "react";
import { AddIcon, DeleteIcon } from "@chakra-ui/icons"; import { AddIcon, DeleteIcon } from "@chakra-ui/icons";
import { import {
Button, Button,
Modal, Modal,
ModalBody, ModalBody,
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 = () => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
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 activeDecal = useModelStore((state) => state.activeDecal); const activeModel = useModelStore((state) => state.activeModel);
return ( const activeDecal = useModelStore((state) => state.activeDecal);
<> return (
<ul> <>
{decals <ul>
.filter((el) => el.type === StickerType.logo) {decals
.map((decal) => ( .filter((el) => el.type === StickerType.logo)
<li .map((decal) => (
onClick={() => { <li
setActiveDecal(decal.id) onClick={() => {
}} setActiveDecal(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" : "" 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
<Image className={"w-12 h-12 object-contain"} src={decal.url} /> ? "border-2 border-green-100 bg-blue-200"
<IconButton icon={<DeleteIcon />} aria-label={""} colorScheme="red" size={"xs"} onClick={() => { : ""
setDecals(decals.filter(el => el.id !== decal.id)) }`}
}} />
</li>
))}
</ul>
<div className="flex justify-center mt-4">
<Button
colorScheme="messenger"
onClick={() => {
pickFile({
accept: ["image/png"],
}).then((files) => {
if (!files.length) return
const id = uuidv4()
setDecals([...decals, {
id,
url: URL.createObjectURL(files[0]),
postion: new Vector3(0, 0, 0),
type: StickerType.logo
}])
setActiveDecal(id)
});
}}
leftIcon={<AddIcon />}
>
LOGO
</Button>
</div>
<Modal
isOpen={open}
onClose={() => {
setOpen(() => false);
}}
> >
<ModalOverlay /> <Image className={"h-12 w-12 object-contain"} src={decal.url} />
<ModalContent> <IconButton
<ModalBody> icon={<DeleteIcon />}
<div className="flex justify-center p-4"> aria-label={""}
<div colorScheme="red"
onClick={() => { }} size={"xs"}
className={ onClick={() => {
"flex aspect-square w-24 cursor-pointer items-center justify-center rounded-lg border-2 border-gray-300" setDecals(decals.filter((el) => el.id !== decal.id));
} }}
> />
<AddIcon /> </li>
</div> ))}
</div> </ul>
</ModalBody> <div className="mt-4 flex justify-center">
</ModalContent> <Button
</Modal> colorScheme="messenger"
</> onClick={() => {
); pickFile({
accept: ["image/png"],
}).then((files) => {
if (!files.length) return;
const id = uuidv4();
setDecals([
...decals,
{
id,
url: URL.createObjectURL(files[0]),
postion: new Vector3(0, 0, 0),
type: StickerType.logo,
scale: activeModel ? 1.5 : 0.05,
},
]);
setActiveDecal(id);
});
}}
leftIcon={<AddIcon />}
>
LOGO
</Button>
</div>
<Modal
isOpen={open}
onClose={() => {
setOpen(() => false);
}}
>
<ModalOverlay />
<ModalContent>
<ModalBody>
<div className="flex justify-center p-4">
<div
onClick={() => {}}
className={
"flex aspect-square w-24 cursor-pointer items-center justify-center rounded-lg border-2 border-gray-300"
}
>
<AddIcon />
</div>
</div>
</ModalBody>
</ModalContent>
</Modal>
</>
);
}; };
export default LogoPanel; export default LogoPanel;

View File

@ -26,8 +26,9 @@ const RightPanel = () => {
onClick={() => { onClick={() => {
setActiveModel(index); setActiveModel(index);
}} }}
className={`${activeModel === index ? "border-2 border-green-300" : "" className={`${
} flex aspect-square items-center justify-center overflow-hidden rounded-xl bg-blue-100`} activeModel === index ? "border-2 border-green-300" : ""
} flex aspect-square items-center justify-center overflow-hidden rounded-xl bg-blue-100`}
> >
<img <img
className="h-full w-full object-cover" className="h-full w-full object-cover"

View File

@ -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 和文字标签
@ -8,51 +8,66 @@ import { useState } from "react";
* @returns * @returns
*/ */
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);
return ( // useInterval(() => {
<Decal // setRotation(state => state += 0.001 * Math.PI)
position={decal.postion} // }, 10)
scale={scale} return (
onPointerDown={(ev) => { <Decal
ev.stopPropagation(); debug={true}
setActiveDecal(decal.id) position={decal.postion}
setDecalDragging(true); scale={decal.scale}
}} onPointerDown={(ev) => {
onPointerUp={(ev) => { ev.stopPropagation();
ev.stopPropagation(); setActiveDecal(decal.id);
setDecalDragging(false); setDecalDragging(true);
}} }}
// onWheel={(ev) => { onPointerUp={(ev) => {
// ev.stopPropagation() ev.stopPropagation();
// setDecalDragging(true) setDecalDragging(false);
// console.log(ev); }}
onPointerEnter={(_ev) => {
// // setScale((state) => state += 1) // ev.ctrlKey
// }} }}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment onWheel={(ev) => {
// @ts-expect-error ev.stopPropagation();
rotation={Math.PI} // setDecalDragging(true);
> // setDecals()
<meshPhysicalMaterial if (!ev.altKey) return;
transparent if (ev.deltaY > 0) {
polygonOffset // setScale(state => state += 0.01)
polygonOffsetFactor={-10} setDecalScale(decal.id, (decal.scale -= 0.01));
map={sticker} } else if (ev.deltaY < 0) {
map-flipY={false} setDecalScale(decal.id, (decal.scale += 0.01));
map-anisotropy={16} // setScale(state => state -= 0.01)
iridescence={1} }
iridescenceIOR={1} }}
iridescenceThicknessRange={[0, 1400]} // eslint-disable-next-line @typescript-eslint/ban-ts-comment
roughness={1} // @ts-expect-error
clearcoat={0.5} rotation={Math.PI}
metalness={0.75} // rotation={new Euler(Math.PI / 2, 0, 0)}
toneMapped={false} // rotation={[Math.PI * 1, Math.PI * 1, Math.PI * 1]}
/> >
</Decal> <meshPhysicalMaterial
); transparent
polygonOffset
polygonOffsetFactor={-10}
map={sticker}
map-flipY={false}
map-anisotropy={16}
iridescence={1}
iridescenceIOR={1}
iridescenceThicknessRange={[0, 1400]}
roughness={1}
clearcoat={0.5}
metalness={0.75}
toneMapped={false}
/>
</Decal>
);
}; };
export default Sticker; export default Sticker;

View File

@ -1,11 +1,11 @@
import useModelStore, { StickerType } from "@/store/useModelStore"; import useModelStore, { StickerType } from "@/store/useModelStore";
import { AddIcon, DeleteIcon, EditIcon } from "@chakra-ui/icons"; import { AddIcon, DeleteIcon, EditIcon } from "@chakra-ui/icons";
import { import {
Button, Button,
FormControl, FormControl,
FormLabel, FormLabel,
IconButton, IconButton,
Input, Input,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { useState } from "react"; import { useState } from "react";
import { fabric } from "fabric"; import { fabric } from "fabric";
@ -13,126 +13,131 @@ import { Vector3 } from "three";
import { v4 } from "uuid"; import { v4 } from "uuid";
const TextLabelPanel = () => { 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 activeDecal = useModelStore((state) => state.activeDecal); const activeModel = useModelStore((state) => state.activeModel);
const [editing, setEditing] = useState(false); const activeDecal = useModelStore((state) => state.activeDecal);
const [text, setText] = useState(""); const [editing, setEditing] = useState(false);
const [color, setColor] = useState("#ffffff"); const [text, setText] = useState("");
return ( const [color, setColor] = useState("#ffffff");
<> return (
{editing ? ( <>
<div className={"rounded bg-white p-4"}> {editing ? (
<h2 className="font-bold"></h2> <div className={"rounded bg-white p-4"}>
<FormControl> <h2 className="font-bold"></h2>
<FormLabel></FormLabel> <FormControl>
<Input <FormLabel></FormLabel>
value={text} <Input
onInput={(ev) => { value={text}
setText(() => (ev.target as HTMLInputElement).value); onInput={(ev) => {
}} setText(() => (ev.target as HTMLInputElement).value);
/> }}
</FormControl> />
<FormControl> </FormControl>
<FormLabel></FormLabel> <FormControl>
<Input <FormLabel></FormLabel>
type="color" <Input
value={color} type="color"
onInput={(ev) => { value={color}
setColor(() => (ev.target as HTMLInputElement).value); onInput={(ev) => {
}} setColor(() => (ev.target as HTMLInputElement).value);
/> }}
</FormControl> />
<div className={"mt-2 flex justify-center"}> </FormControl>
<Button <div className={"mt-2 flex justify-center"}>
colorScheme="messenger" <Button
size={"sm"} colorScheme="messenger"
onClick={() => { size={"sm"}
const canvas = document.createElement("canvas"); onClick={() => {
const fabricText = new fabric.Text(text, { const canvas = document.createElement("canvas");
fill: color, const fabricText = new fabric.Text(text, {
// fontFamily: 'sans-serif' fill: color,
}); // fontFamily: 'sans-serif'
const fabricCanvas = new fabric.Canvas(canvas, { });
width: fabricText.width, const fabricCanvas = new fabric.Canvas(canvas, {
height: fabricText.height, width: fabricText.width,
}); height: fabricText.height,
});
fabricCanvas.add(fabricText); fabricCanvas.add(fabricText);
const id = v4(); const id = v4();
setActiveDecal(id); setActiveDecal(id);
setDecals([ setDecals([
...decals, ...decals,
{ {
id, id,
postion: new Vector3(0, 0, 0), postion: new Vector3(0, 0, 0),
text, text,
url: fabricCanvas.toDataURL(), url: fabricCanvas.toDataURL(),
type: StickerType.text, type: StickerType.text,
}, scale: activeModel ? 1.5 : 0.05,
]); },
setText(() => ""); ]);
setColor(() => "#ffffff"); setText(() => "");
setEditing(() => false); setColor(() => "#ffffff");
}} setEditing(() => false);
> }}
>
</Button>
</div> </Button>
</div> </div>
) : ( </div>
<ul> ) : (
{decals <ul>
.filter((el) => el.type === StickerType.text) {decals
.map((text) => ( .filter((el) => el.type === StickerType.text)
<li .map((text) => (
onClick={() => { <li
setActiveDecal(text.id); onClick={() => {
}} setActiveDecal(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" : "" 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
<span>{text.text}</span> ? "border-2 border-green-100 bg-blue-200"
<div className={"right"}> : ""
<IconButton }`}
onClick={(ev) => { >
ev.stopPropagation(); <span>{text.text}</span>
}} <div className={"right"}>
size={"xs"} <IconButton
icon={<EditIcon />} onClick={(ev) => {
aria-label={""} ev.stopPropagation();
/>
<IconButton
className={"ml-1"}
onClick={(ev) => {
ev.stopPropagation();
setDecals(decals.filter(el => el.id !== text.id))
}}
size={"xs"}
icon={<DeleteIcon />}
aria-label={""}
colorScheme="red"
/>
</div>
</li>
))}
</ul>
)}
<div className="mt-4 flex justify-center">
<Button
colorScheme="messenger"
onClick={() => {
setEditing(() => true);
}} }}
leftIcon={<AddIcon />} size={"xs"}
> icon={<EditIcon />}
aria-label={""}
</Button> />
</div> <IconButton
</> className={"ml-1"}
); onClick={(ev) => {
ev.stopPropagation();
setDecals(decals.filter((el) => el.id !== text.id));
}}
size={"xs"}
icon={<DeleteIcon />}
aria-label={""}
colorScheme="red"
/>
</div>
</li>
))}
</ul>
)}
<div className="mt-4 flex justify-center">
<Button
colorScheme="messenger"
onClick={() => {
setEditing(() => true);
}}
leftIcon={<AddIcon />}
>
</Button>
</div>
</>
);
}; };
export default TextLabelPanel; export default TextLabelPanel;

View File

@ -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>
); );
}; };

View File

@ -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
// })),
})), })),
); );