From c52b6771ca23f96a1cf67b55a9a2655c985dcaa1 Mon Sep 17 00:00:00 2001 From: echo Date: Thu, 27 Jun 2024 17:23:14 +0900 Subject: [PATCH 1/4] =?UTF-8?q?remove:=20=EC=95=88=EC=93=B0=EB=8A=94=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Modal/atom/Test.jsx | 76 ------------------------------ 1 file changed, 76 deletions(-) delete mode 100644 src/components/Modal/atom/Test.jsx diff --git a/src/components/Modal/atom/Test.jsx b/src/components/Modal/atom/Test.jsx deleted file mode 100644 index 187ecee..0000000 --- a/src/components/Modal/atom/Test.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { useThree } from '@react-three/fiber'; -import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'; -import { Color, Box3, Vector3 } from 'three'; -import { useRecoilState } from 'recoil'; -import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader'; -import { LodingState } from '../../../store/modalState'; - -function TestOBJ({ objecturl, x, y, z }) { - const modelRef = useRef(); - const [loadingValue, setLoadingValue] = useRecoilState(LodingState); - const [object, setObject] = useState(null); - - const { scene } = useThree(); - - useEffect(() => { - scene.background = new Color('#FFFFFF'); - }, [scene]); - - useEffect(() => { - if (!objecturl?.obj) { - setLoadingValue(false); - setObject(null); - return; - } - setLoadingValue(true); - - const materialUrl = objecturl?.mtl || null; - const loadUrl = objecturl?.obj || null; - - const loadModel = () => { - const objLoader = new OBJLoader(); - const onLoad = (obj) => { - // 모델의 경계 계산 - const box = new Box3().setFromObject(obj); - const size = new Vector3(); - box.getSize(size); - const maxDimension = Math.max(size.x, size.y, size.z); - - const scale = 5 / maxDimension; - - obj.scale.set(scale, scale, scale); - - setObject(obj); - setLoadingValue(false); - }; - - if (materialUrl) { - const mtlLoader = new MTLLoader(); - mtlLoader.load(materialUrl, (materials) => { - materials.preload(); - objLoader.setMaterials(materials); - objLoader.load(loadUrl, onLoad); - }); - } else { - objLoader.load(loadUrl, onLoad); - } - }; - - loadModel(); - }, [objecturl, setLoadingValue]); - - useEffect(() => { - if (object) { - setLoadingValue(false); - } - }, [object, setLoadingValue]); - - return ( - - {object ? : null} - - ); -} - -export default TestOBJ; From ff411e53d0ccb823b481883acf27ca3e498bb2a2 Mon Sep 17 00:00:00 2001 From: echo Date: Fri, 12 Jul 2024 14:55:42 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=203D=20=EC=98=A4=EB=B8=8C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=A7=88=EC=9A=B0=EC=8A=A4=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=20Y=EC=B6=95=20=EA=B3=A0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EditPage/PageData/Edit3d/EditGltfLoader.jsx | 14 ++++++-------- src/hooks/AddItem/useObject.js | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx b/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx index 496d9ec..0bb40ba 100644 --- a/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx +++ b/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx @@ -1,7 +1,7 @@ import React, { useRef, useEffect, useState } from 'react'; import { useFrame, useThree } from '@react-three/fiber'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; -import { Color, Box3, Vector3, AxesHelper } from 'three'; +import { Color, Box3, Vector3 } from 'three'; import { useRecoilState } from 'recoil'; import { DragControls } from 'three/examples/jsm/controls/DragControls'; import { LodingState } from '../../../../store/modalState'; @@ -74,6 +74,10 @@ function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) { event.object.material.emissive.set(0xaaaaaa); setIsDragging(true); }); + controlsRef.current.addEventListener('drag', (event) => { + const { object } = event; + object.position.y = 0; // y축 고정 + }); controlsRef.current.addEventListener('dragend', (event) => { event.object.material.emissive.set(0x000000); @@ -86,13 +90,7 @@ function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) { } return undefined; }, [camera, gl]); - useEffect(() => { - const axesHelper = new AxesHelper(100); - scene.add(axesHelper); - return () => { - scene.remove(axesHelper); - }; - }, [scene]); + return ( {gltf ? ( diff --git a/src/hooks/AddItem/useObject.js b/src/hooks/AddItem/useObject.js index bf1e79a..1806fa5 100644 --- a/src/hooks/AddItem/useObject.js +++ b/src/hooks/AddItem/useObject.js @@ -30,7 +30,7 @@ const useObject = () => { textures: texturesUrl, size: 0.25, x: getRandomCoordinate(), - y: getRandomCoordinate(), + y: 0, z: getRandomCoordinate(), }; const updatedImages = { From a0be41f9d3d2a7d162654f98fbe8236ac7660213 Mon Sep 17 00:00:00 2001 From: echo Date: Fri, 12 Jul 2024 16:50:44 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EC=98=A4=EB=B8=8C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=A7=88=EC=9A=B0=EC=8A=A4=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EB=B3=80=ED=99=94=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/EditPage/PageData/Edit3d.jsx | 6 ++- .../PageData/Edit3d/EditGltfLoader.jsx | 46 ++++++++++++++++++- src/hooks/EditPage/useItemValue.js | 5 +- src/pages/EditPage.jsx | 7 ++- 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/components/EditPage/PageData/Edit3d.jsx b/src/components/EditPage/PageData/Edit3d.jsx index 61b4213..a6af864 100644 --- a/src/components/EditPage/PageData/Edit3d.jsx +++ b/src/components/EditPage/PageData/Edit3d.jsx @@ -7,7 +7,7 @@ import EditObjLoader from './Edit3d/EditObjLoader'; import EditGltfLoader from './Edit3d/EditGltfLoader'; import { objectSizeState } from '../../../store/toolState'; -function Edit3d({ objecturl }) { +function Edit3d({ objecturl, setObjectValue, pageRendering }) { const { camera } = useThree(); const dataSize = useRecoilValue(objectSizeState); @@ -50,7 +50,7 @@ function Edit3d({ objecturl }) { return ( <> - + ) : null, )} diff --git a/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx b/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx index 0bb40ba..1812009 100644 --- a/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx +++ b/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx @@ -7,7 +7,16 @@ import { DragControls } from 'three/examples/jsm/controls/DragControls'; import { LodingState } from '../../../../store/modalState'; import useKeyDown from '../../../../hooks/EditPage/Handlers/useKeyDown'; -function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) { +function EditGltfLoader({ + objecturl, + size, + x, + y, + z, + setIsDragging, + setObjectValue, + pageRendering, +}) { const modelRef = useRef(); const { camera, scene, gl } = useThree(); const [loadingValue, setLoadingValue] = useRecoilState(LodingState); @@ -16,6 +25,18 @@ function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) { const movement = useRef({ forward: 0, right: 0, up: 0 }); const gltfUrl = typeof objecturl === 'string' ? objecturl : objecturl.gltf; const controlsRef = useRef(); + const startPosition = useRef(new Vector3()); + const deltaPosition = useRef(new Vector3()); + const scaleFactor = 0.05; // 이동 축소 비율 + + const handlePositionChange = (id, axis, value) => { + setObjectValue((prev) => ({ + ...prev, + [pageRendering]: prev[pageRendering].map((obj) => + obj.id === id ? { ...obj, [axis]: value } : obj, + ), + })); + }; useEffect(() => { scene.background = new Color('#FFFFFF'); @@ -40,6 +61,8 @@ function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) { setGltf(loadedGltf); setInitialScale([scale, scale, scale]); + loadedGltf.scene.position.set(x, y, z); // 초기 위치 설정 + setLoadingValue(false); }, undefined, @@ -62,6 +85,7 @@ function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) { }); useKeyDown(movement, modelRef); + useEffect(() => { if (modelRef.current) { controlsRef.current = new DragControls( @@ -73,15 +97,35 @@ function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) { controlsRef.current.addEventListener('dragstart', (event) => { event.object.material.emissive.set(0xaaaaaa); setIsDragging(true); + startPosition.current.copy(event.object.position); }); + controlsRef.current.addEventListener('drag', (event) => { const { object } = event; object.position.y = 0; // y축 고정 + + deltaPosition.current.set( + (object.position.x - startPosition.current.x) * scaleFactor, + 0, + (object.position.z - startPosition.current.z) * scaleFactor, + ); + + object.position.x = startPosition.current.x + deltaPosition.current.x; + object.position.z = startPosition.current.z + deltaPosition.current.z; + + // 여기에서 실시간으로 위치를 저장 + handlePositionChange(objecturl.id, 'x', Math.round(object.position.x)); + handlePositionChange(objecturl.id, 'z', Math.round(object.position.z)); }); controlsRef.current.addEventListener('dragend', (event) => { + const { object } = event; + event.object.material.emissive.set(0x000000); setIsDragging(false); + // 드래그가 끝난 후 최종 위치를 저장 + handlePositionChange(objecturl.id, 'x', Math.round(object.position.x)); + handlePositionChange(objecturl.id, 'z', Math.round(object.position.z)); }); return () => { diff --git a/src/hooks/EditPage/useItemValue.js b/src/hooks/EditPage/useItemValue.js index 8545fa7..7093728 100644 --- a/src/hooks/EditPage/useItemValue.js +++ b/src/hooks/EditPage/useItemValue.js @@ -1,4 +1,4 @@ -import { useRecoilState, useRecoilValue } from 'recoil'; +import { useRecoilState } from 'recoil'; import { imageList, object3dState, @@ -7,13 +7,14 @@ import { } from '../../store/recoil'; const useItemValue = () => { - const objectValue = useRecoilValue(object3dState); + const [objectValue, setObjectValue] = useRecoilState(object3dState); const [shapeValue, setShapeValue] = useRecoilState(shapeList); const [textValue, setTextValue] = useRecoilState(textList); const [imgValue, setImgValue] = useRecoilState(imageList); return { objectValue, + setObjectValue, shapeValue, setShapeValue, textValue, diff --git a/src/pages/EditPage.jsx b/src/pages/EditPage.jsx index edc4fc9..124453c 100644 --- a/src/pages/EditPage.jsx +++ b/src/pages/EditPage.jsx @@ -36,6 +36,7 @@ function EditPage() { const { objectValue, + setObjectValue, shapeValue, setShapeValue, textValue, @@ -187,7 +188,11 @@ function EditPage() { } } > - + ); } From fbb488ee5a9986ab5b354a3c4d8886cf579bae54 Mon Sep 17 00:00:00 2001 From: echo Date: Fri, 12 Jul 2024 17:37:23 +0900 Subject: [PATCH 4/4] =?UTF-8?q?Refactor:=20=EC=98=A4=EB=B8=8C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EB=93=9C=EB=9E=98=EA=B7=B8=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=20=ED=9B=85=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/EditPage/PageData/Edit3d.jsx | 3 + .../PageData/Edit3d/EditGltfLoader.jsx | 73 +++------------ .../PageData/Edit3d/EditObjLoader.jsx | 33 +++++-- src/hooks/EditPage/useObjectDrag.js | 89 +++++++++++++++++++ 4 files changed, 127 insertions(+), 71 deletions(-) create mode 100644 src/hooks/EditPage/useObjectDrag.js diff --git a/src/components/EditPage/PageData/Edit3d.jsx b/src/components/EditPage/PageData/Edit3d.jsx index a6af864..2c0c0f7 100644 --- a/src/components/EditPage/PageData/Edit3d.jsx +++ b/src/components/EditPage/PageData/Edit3d.jsx @@ -69,6 +69,9 @@ function Edit3d({ objecturl, setObjectValue, pageRendering }) { x={url.x} y={url.y} z={url.z} + setIsDragging={setIsDragging} + setObjectValue={setObjectValue} + pageRendering={pageRendering} /> ) : url?.extension === 'gltf' ? ( { - setObjectValue((prev) => ({ - ...prev, - [pageRendering]: prev[pageRendering].map((obj) => - obj.id === id ? { ...obj, [axis]: value } : obj, - ), - })); - }; useEffect(() => { scene.background = new Color('#FFFFFF'); @@ -86,54 +74,15 @@ function EditGltfLoader({ useKeyDown(movement, modelRef); - useEffect(() => { - if (modelRef.current) { - controlsRef.current = new DragControls( - [modelRef.current], - camera, - gl.domElement, - ); - - controlsRef.current.addEventListener('dragstart', (event) => { - event.object.material.emissive.set(0xaaaaaa); - setIsDragging(true); - startPosition.current.copy(event.object.position); - }); - - controlsRef.current.addEventListener('drag', (event) => { - const { object } = event; - object.position.y = 0; // y축 고정 - - deltaPosition.current.set( - (object.position.x - startPosition.current.x) * scaleFactor, - 0, - (object.position.z - startPosition.current.z) * scaleFactor, - ); - - object.position.x = startPosition.current.x + deltaPosition.current.x; - object.position.z = startPosition.current.z + deltaPosition.current.z; - - // 여기에서 실시간으로 위치를 저장 - handlePositionChange(objecturl.id, 'x', Math.round(object.position.x)); - handlePositionChange(objecturl.id, 'z', Math.round(object.position.z)); - }); - - controlsRef.current.addEventListener('dragend', (event) => { - const { object } = event; - - event.object.material.emissive.set(0x000000); - setIsDragging(false); - // 드래그가 끝난 후 최종 위치를 저장 - handlePositionChange(objecturl.id, 'x', Math.round(object.position.x)); - handlePositionChange(objecturl.id, 'z', Math.round(object.position.z)); - }); - - return () => { - controlsRef.current.dispose(); - }; - } - return undefined; - }, [camera, gl]); + useObjectDrag({ + modelRef, + camera, + domElement: gl.domElement, + setIsDragging, + setObjectValue, + pageRendering, + objectId: objecturl.id, + }); return ( diff --git a/src/components/EditPage/PageData/Edit3d/EditObjLoader.jsx b/src/components/EditPage/PageData/Edit3d/EditObjLoader.jsx index 650164d..13860ea 100644 --- a/src/components/EditPage/PageData/Edit3d/EditObjLoader.jsx +++ b/src/components/EditPage/PageData/Edit3d/EditObjLoader.jsx @@ -6,10 +6,20 @@ import { useRecoilState } from 'recoil'; import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader'; import { LodingState } from '../../../../store/modalState'; import useKeyDown from '../../../../hooks/EditPage/Handlers/useKeyDown'; - -function EditObjLoader({ objecturl, size, x, y, z }) { +import useObjectDrag from '../../../../hooks/EditPage/useObjectDrag'; + +function EditObjLoader({ + objecturl, + size, + x, + y, + z, + setIsDragging, + setObjectValue, + pageRendering, +}) { const modelRef = useRef(); - const { camera } = useThree(); + const { camera, gl } = useThree(); const [loadingValue, setLoadingValue] = useRecoilState(LodingState); const [object, setObject] = useState(null); const [initialScale, setInitialScale] = useState([1, 1, 1]); @@ -27,6 +37,7 @@ function EditObjLoader({ objecturl, size, x, y, z }) { setObject(null); return; } + setLoadingValue(true); const materialUrl = objecturl?.mtl || null; @@ -63,12 +74,6 @@ function EditObjLoader({ objecturl, size, x, y, z }) { loadModel(); }, [objecturl, setLoadingValue]); - useEffect(() => { - if (object) { - setLoadingValue(false); - } - }, [object, setLoadingValue]); - useFrame(() => { if (!modelRef.current) return; const speed = 0.1; @@ -83,6 +88,16 @@ function EditObjLoader({ objecturl, size, x, y, z }) { useKeyDown(movement, modelRef); + useObjectDrag({ + modelRef, + camera, + domElement: gl.domElement, + setIsDragging, + setObjectValue, + pageRendering, + objectId: objecturl.id, + }); + return ( {object ? ( diff --git a/src/hooks/EditPage/useObjectDrag.js b/src/hooks/EditPage/useObjectDrag.js new file mode 100644 index 0000000..4e73521 --- /dev/null +++ b/src/hooks/EditPage/useObjectDrag.js @@ -0,0 +1,89 @@ +import { useRef, useEffect } from 'react'; +import { DragControls } from 'three/examples/jsm/controls/DragControls'; +import { Vector3 } from 'three'; + +const useObjectDrag = ({ + modelRef, + camera, + domElement, + setIsDragging, + setObjectValue, + pageRendering, + objectId, + scaleFactor = 0.05, +}) => { + const controlsRef = useRef(); + const startPosition = useRef(new Vector3()); + const deltaPosition = useRef(new Vector3()); + + const handlePositionChange = (id, axis, value) => { + setObjectValue((prev) => ({ + ...prev, + [pageRendering]: prev[pageRendering].map((obj) => + obj.id === id ? { ...obj, [axis]: value } : obj, + ), + })); + }; + + useEffect(() => { + if (modelRef.current) { + controlsRef.current = new DragControls( + [modelRef.current], + camera, + domElement, + ); + + controlsRef.current.addEventListener('dragstart', (event) => { + if (event.object.material && event.object.material.emissive) { + event.object.material.emissive.set(0xaaaaaa); + } + if (typeof setIsDragging === 'function') { + setIsDragging(true); + } + startPosition.current.copy(event.object.position); + }); + + controlsRef.current.addEventListener('drag', (event) => { + const { object } = event; + object.position.y = 0; // y축 고정 + + deltaPosition.current.set( + (object.position.x - startPosition.current.x) * scaleFactor, + 0, + (object.position.z - startPosition.current.z) * scaleFactor, + ); + + object.position.x = startPosition.current.x + deltaPosition.current.x; + object.position.z = startPosition.current.z + deltaPosition.current.z; + + // 여기에서 실시간으로 위치를 저장 + handlePositionChange(objectId, 'x', Math.round(object.position.x)); + handlePositionChange(objectId, 'z', Math.round(object.position.z)); + }); + + controlsRef.current.addEventListener('dragend', (event) => { + const { object } = event; + + if (object.material && object.material.emissive) { + object.material.emissive.set(0x000000); + } + if (typeof setIsDragging === 'function') { + setIsDragging(false); + } + // 드래그가 끝난 후 최종 위치를 저장 + handlePositionChange(objectId, 'x', Math.round(object.position.x)); + handlePositionChange(objectId, 'z', Math.round(object.position.z)); + }); + + return () => { + controlsRef.current.dispose(); + }; + } + // 명시적으로 undefined 반환 + return undefined; + }, [camera, domElement, modelRef]); + + return controlsRef; +}; + +export default useObjectDrag;