diff --git a/app/src/assets/gltf-glb/default.glb b/app/src/assets/gltf-glb/default.glb new file mode 100644 index 0000000..fd19420 Binary files /dev/null and b/app/src/assets/gltf-glb/default.glb differ diff --git a/app/src/assets/gltf-glb/material1.glb b/app/src/assets/gltf-glb/material1.glb new file mode 100644 index 0000000..405bdb0 Binary files /dev/null and b/app/src/assets/gltf-glb/material1.glb differ diff --git a/app/src/assets/gltf-glb/material2.glb b/app/src/assets/gltf-glb/material2.glb new file mode 100644 index 0000000..9123a7c Binary files /dev/null and b/app/src/assets/gltf-glb/material2.glb differ diff --git a/app/src/assets/gltf-glb/material3.glb b/app/src/assets/gltf-glb/material3.glb new file mode 100644 index 0000000..8e9c191 Binary files /dev/null and b/app/src/assets/gltf-glb/material3.glb differ diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx index d5ca04f..1ab9d59 100644 --- a/app/src/modules/builder/groups/floorItemsGroup.tsx +++ b/app/src/modules/builder/groups/floorItemsGroup.tsx @@ -1,25 +1,25 @@ import { useFrame, useThree } from "@react-three/fiber"; import { - useActiveTool, - useAsset3dWidget, - useCamMode, - useDeletableFloorItem, - useDeleteTool, - useFloorItems, - useLoadingProgress, - useRenderDistance, - useSelectedFloorItem, - useSelectedItem, - useSocketStore, - useToggleView, - useTransformMode, + useActiveTool, + useAsset3dWidget, + useCamMode, + useDeletableFloorItem, + useDeleteTool, + useFloorItems, + useLoadingProgress, + useRenderDistance, + useSelectedFloorItem, + useSelectedItem, + useSocketStore, + useToggleView, + useTransformMode, } from "../../../store/store"; import assetVisibility from "../geomentries/assets/assetVisibility"; import { useEffect } from "react"; import * as THREE from "three"; import * as Types from "../../../types/world/worldTypes"; import assetManager, { - cancelOngoingTasks, + cancelOngoingTasks, } from "../geomentries/assets/assetManager"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; @@ -33,421 +33,420 @@ import useModuleStore from "../../../store/useModuleStore"; import { useEventsStore } from "../../../store/simulation/useEventsStore"; const assetManagerWorker = new Worker( - new URL( - "../../../services/factoryBuilder/webWorkers/assetManagerWorker.js", - import.meta.url - ) + new URL( + "../../../services/factoryBuilder/webWorkers/assetManagerWorker.js", + import.meta.url + ) ); const gltfLoaderWorker = new Worker( - new URL( - "../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js", - import.meta.url - ) + new URL( + "../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js", + import.meta.url + ) ); const FloorItemsGroup = ({ - itemsGroup, - hoveredDeletableFloorItem, - AttachedObject, - floorGroup, - tempLoader, - isTempLoader, - plane, + itemsGroup, + hoveredDeletableFloorItem, + AttachedObject, + floorGroup, + tempLoader, + isTempLoader, + plane, }: any) => { - const state: Types.ThreeState = useThree(); - const { raycaster, controls }: any = state; - const { renderDistance } = useRenderDistance(); - const { toggleView } = useToggleView(); - const { floorItems, setFloorItems } = useFloorItems(); - const { camMode } = useCamMode(); - const { deleteTool } = useDeleteTool(); - const { setDeletableFloorItem } = useDeletableFloorItem(); - const { transformMode } = useTransformMode(); - const { setSelectedFloorItem } = useSelectedFloorItem(); - const { activeTool } = useActiveTool(); - const { selectedItem, setSelectedItem } = useSelectedItem(); - const { setLoadingProgress } = useLoadingProgress(); - const { activeModule } = useModuleStore(); - const { socket } = useSocketStore(); - const loader = new GLTFLoader(); - const dracoLoader = new DRACOLoader(); - const { addEvent } = useEventsStore(); + const state: Types.ThreeState = useThree(); + const { raycaster, controls }: any = state; + const { renderDistance } = useRenderDistance(); + const { toggleView } = useToggleView(); + const { floorItems, setFloorItems } = useFloorItems(); + const { camMode } = useCamMode(); + const { deleteTool } = useDeleteTool(); + const { setDeletableFloorItem } = useDeletableFloorItem(); + const { transformMode } = useTransformMode(); + const { setSelectedFloorItem } = useSelectedFloorItem(); + const { activeTool } = useActiveTool(); + const { selectedItem, setSelectedItem } = useSelectedItem(); + const { setLoadingProgress } = useLoadingProgress(); + const { activeModule } = useModuleStore(); + const { socket } = useSocketStore(); + const loader = new GLTFLoader(); + const dracoLoader = new DRACOLoader(); + const { addEvent } = useEventsStore(); - dracoLoader.setDecoderPath( - "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/" - ); - loader.setDRACOLoader(dracoLoader); + dracoLoader.setDecoderPath( + "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/" + ); + loader.setDRACOLoader(dracoLoader); - useEffect(() => { - const email = localStorage.getItem("email"); - const organization = email!.split("@")[1].split(".")[0]; + useEffect(() => { + const email = localStorage.getItem("email"); + const organization = email!.split("@")[1].split(".")[0]; - let totalAssets = 0; - let loadedAssets = 0; + let totalAssets = 0; + let loadedAssets = 0; - const updateLoadingProgress = (progress: number) => { - if (progress < 100) { - setLoadingProgress(progress); - } else if (progress === 100) { - setTimeout(() => { - setLoadingProgress(100); - setTimeout(() => { - setLoadingProgress(0); - }, 1500); - }, 1000); - } - }; + const updateLoadingProgress = (progress: number) => { + if (progress < 100) { + setLoadingProgress(progress); + } else if (progress === 100) { + setTimeout(() => { + setLoadingProgress(100); + setTimeout(() => { + setLoadingProgress(0); + }, 1500); + }, 1000); + } + }; - getFloorAssets(organization).then((data) => { - if (data.length > 0) { - const uniqueItems = (data as Types.FloorItems).filter( - (item, index, self) => - index === self.findIndex((t) => t.modelfileID === item.modelfileID) - ); - totalAssets = uniqueItems.length; - if (totalAssets === 0) { - updateLoadingProgress(100); - return; - } - gltfLoaderWorker.postMessage({ floorItems: data }); - } else { - gltfLoaderWorker.postMessage({ floorItems: [] }); - loadInitialFloorItems( - itemsGroup, - setFloorItems, - addEvent, - renderDistance - ); - updateLoadingProgress(100); - } - }); - - gltfLoaderWorker.onmessage = async (event) => { - if (event.data.message === "gltfLoaded" && event.data.modelBlob) { - const blobUrl = URL.createObjectURL(event.data.modelBlob); - - loader.load(blobUrl, (gltf) => { - URL.revokeObjectURL(blobUrl); - THREE.Cache.remove(blobUrl); - THREE.Cache.add(event.data.modelID, gltf); - - loadedAssets++; - const progress = Math.round((loadedAssets / totalAssets) * 100); - updateLoadingProgress(progress); - - if (loadedAssets === totalAssets) { - loadInitialFloorItems( - itemsGroup, - setFloorItems, - addEvent, - renderDistance - ); - updateLoadingProgress(100); - } + getFloorAssets(organization).then((data) => { + if (data.length > 0) { + const uniqueItems = (data as Types.FloorItems).filter( + (item, index, self) => + index === self.findIndex((t) => t.modelfileID === item.modelfileID) + ); + totalAssets = uniqueItems.length; + if (totalAssets === 0) { + updateLoadingProgress(100); + return; + } + gltfLoaderWorker.postMessage({ floorItems: data }); + } else { + gltfLoaderWorker.postMessage({ floorItems: [] }); + loadInitialFloorItems( + itemsGroup, + setFloorItems, + addEvent, + renderDistance + ); + updateLoadingProgress(100); + } }); - } - }; - }, []); - useEffect(() => { - assetManagerWorker.onmessage = async (event) => { - cancelOngoingTasks(); // Cancel the ongoing process - await assetManager(event.data, itemsGroup, loader); - }; - }, [assetManagerWorker]); + gltfLoaderWorker.onmessage = async (event) => { + if (event.data.message === "gltfLoaded" && event.data.modelBlob) { + const blobUrl = URL.createObjectURL(event.data.modelBlob); - useEffect(() => { - if (toggleView) return; + loader.load(blobUrl, (gltf) => { + URL.revokeObjectURL(blobUrl); + THREE.Cache.remove(blobUrl); + THREE.Cache.add(event.data.modelID, gltf); - const uuids: string[] = []; - itemsGroup.current?.children.forEach((child: any) => { - uuids.push(child.uuid); - }); - const cameraPosition = state.camera.position; + loadedAssets++; + const progress = Math.round((loadedAssets / totalAssets) * 100); + updateLoadingProgress(progress); - assetManagerWorker.postMessage({ - floorItems, - cameraPosition, - uuids, - renderDistance, - }); - }, [camMode, renderDistance]); + if (loadedAssets === totalAssets) { + loadInitialFloorItems( + itemsGroup, + setFloorItems, + addEvent, + renderDistance + ); + updateLoadingProgress(100); + } + }); + } + }; + }, []); - useEffect(() => { - const controls: any = state.controls; - const camera: any = state.camera; + useEffect(() => { + assetManagerWorker.onmessage = async (event) => { + cancelOngoingTasks(); // Cancel the ongoing process + await assetManager(event.data, itemsGroup, loader); + }; + }, [assetManagerWorker]); - if (controls) { - let intervalId: NodeJS.Timeout | null = null; - - const handleChange = () => { + useEffect(() => { if (toggleView) return; const uuids: string[] = []; itemsGroup.current?.children.forEach((child: any) => { - uuids.push(child.uuid); + uuids.push(child.uuid); }); - const cameraPosition = camera.position; + const cameraPosition = state.camera.position; assetManagerWorker.postMessage({ - floorItems, - cameraPosition, - uuids, - renderDistance, + floorItems, + cameraPosition, + uuids, + renderDistance, }); - }; + }, [camMode, renderDistance]); - const startInterval = () => { - if (!intervalId) { - intervalId = setInterval(handleChange, 50); + useEffect(() => { + const controls: any = state.controls; + const camera: any = state.camera; + + if (controls) { + let intervalId: NodeJS.Timeout | null = null; + + const handleChange = () => { + if (toggleView) return; + + const uuids: string[] = []; + itemsGroup.current?.children.forEach((child: any) => { + uuids.push(child.uuid); + }); + const cameraPosition = camera.position; + + assetManagerWorker.postMessage({ + floorItems, + cameraPosition, + uuids, + renderDistance, + }); + }; + + const startInterval = () => { + if (!intervalId) { + intervalId = setInterval(handleChange, 50); + } + }; + + const stopInterval = () => { + handleChange(); + if (intervalId) { + clearInterval(intervalId); + intervalId = null; + } + }; + + controls.addEventListener("rest", handleChange); + controls.addEventListener("rest", stopInterval); + controls.addEventListener("control", startInterval); + controls.addEventListener("controlend", stopInterval); + + return () => { + controls.removeEventListener("rest", handleChange); + controls.removeEventListener("rest", stopInterval); + controls.removeEventListener("control", startInterval); + controls.removeEventListener("controlend", stopInterval); + if (intervalId) { + clearInterval(intervalId); + } + }; } - }; + }, [state.controls, floorItems, toggleView, renderDistance]); - const stopInterval = () => { - handleChange(); - if (intervalId) { - clearInterval(intervalId); - intervalId = null; - } - }; + useEffect(() => { + const canvasElement = state.gl.domElement; + let drag = false; + let isLeftMouseDown = false; - controls.addEventListener("rest", handleChange); - controls.addEventListener("rest", stopInterval); - controls.addEventListener("control", startInterval); - controls.addEventListener("controlend", stopInterval); - - return () => { - controls.removeEventListener("rest", handleChange); - controls.removeEventListener("rest", stopInterval); - controls.removeEventListener("control", startInterval); - controls.removeEventListener("controlend", stopInterval); - if (intervalId) { - clearInterval(intervalId); - } - }; - } - }, [state.controls, floorItems, toggleView, renderDistance]); - - useEffect(() => { - const canvasElement = state.gl.domElement; - let drag = false; - let isLeftMouseDown = false; - - const onMouseDown = (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = true; - drag = false; - } - }; - - const onMouseMove = () => { - console.log('isLeftMouseDown: ', isLeftMouseDown); - if (isLeftMouseDown) { - drag = true; - } - }; - - const onMouseUp = async (evt: any) => { - if (controls) { - (controls as any).enabled = true; - } - if (evt.button === 0) { - isLeftMouseDown = false; - if (drag) return; - - if (deleteTool) { - DeleteFloorItems( - itemsGroup, - hoveredDeletableFloorItem, - setFloorItems, - socket - ); - } - const Mode = transformMode; - - if (Mode !== null || activeTool === "cursor") { - if (!itemsGroup.current) return; - let intersects = raycaster.intersectObjects( - itemsGroup.current.children, - true - ); - if ( - intersects.length > 0 && - intersects[0]?.object?.parent?.parent?.position && - intersects[0]?.object?.parent?.parent?.scale && - intersects[0]?.object?.parent?.parent?.rotation - ) { - // let currentObject = intersects[0].object; - // while (currentObject) { - // if (currentObject.name === "Scene") { - // break; - // } - // currentObject = currentObject.parent as THREE.Object3D; - // } - // if (currentObject) { - // AttachedObject.current = currentObject as any; - // setSelectedFloorItem(AttachedObject.current!); - // } - } else { - const target = controls.getTarget(new THREE.Vector3()); - await controls.setTarget(target.x, 0, target.z, true); - setSelectedFloorItem(null); - } - } - } - }; - - const onDblClick = async (evt: any) => { - if (evt.button === 0) { - isLeftMouseDown = false; - if (drag) return; - - const Mode = transformMode; - - if (Mode !== null || activeTool === "cursor") { - if (!itemsGroup.current) return; - let intersects = raycaster.intersectObjects( - itemsGroup.current.children, - true - ); - if ( - intersects.length > 0 && - intersects[0]?.object?.parent?.parent?.position && - intersects[0]?.object?.parent?.parent?.scale && - intersects[0]?.object?.parent?.parent?.rotation - ) { - let currentObject = intersects[0].object; - - while (currentObject) { - if (currentObject.name === "Scene") { - break; - } - currentObject = currentObject.parent as THREE.Object3D; + const onMouseDown = (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = true; + drag = false; } - if (currentObject) { - AttachedObject.current = currentObject as any; - // controls.fitToSphere(AttachedObject.current!, true); + }; - const bbox = new THREE.Box3().setFromObject( - AttachedObject.current - ); - const size = bbox.getSize(new THREE.Vector3()); - const center = bbox.getCenter(new THREE.Vector3()); - - const front = new THREE.Vector3(0, 0, 1); - AttachedObject.current.localToWorld(front); - front.sub(AttachedObject.current.position).normalize(); - - const distance = Math.max(size.x, size.y, size.z) * 2; - const newPosition = center - .clone() - .addScaledVector(front, distance); - - controls.setPosition( - newPosition.x, - newPosition.y, - newPosition.z, - true - ); - controls.setTarget(center.x, center.y, center.z, true); - controls.fitToBox(AttachedObject.current!, true, { - cover: true, - paddingTop: 5, - paddingLeft: 5, - paddingBottom: 5, - paddingRight: 5, - }); - - setSelectedFloorItem(AttachedObject.current!); + const onMouseMove = () => { + if (isLeftMouseDown) { + drag = true; + } + }; + + const onMouseUp = async (evt: any) => { + if (controls) { + (controls as any).enabled = true; + } + if (evt.button === 0) { + isLeftMouseDown = false; + if (drag) return; + + if (deleteTool) { + DeleteFloorItems( + itemsGroup, + hoveredDeletableFloorItem, + setFloorItems, + socket + ); + } + const Mode = transformMode; + + if (Mode !== null || activeTool === "cursor") { + if (!itemsGroup.current) return; + let intersects = raycaster.intersectObjects( + itemsGroup.current.children, + true + ); + if ( + intersects.length > 0 && + intersects[0]?.object?.parent?.parent?.position && + intersects[0]?.object?.parent?.parent?.scale && + intersects[0]?.object?.parent?.parent?.rotation + ) { + // let currentObject = intersects[0].object; + // while (currentObject) { + // if (currentObject.name === "Scene") { + // break; + // } + // currentObject = currentObject.parent as THREE.Object3D; + // } + // if (currentObject) { + // AttachedObject.current = currentObject as any; + // setSelectedFloorItem(AttachedObject.current!); + // } + } else { + const target = controls.getTarget(new THREE.Vector3()); + await controls.setTarget(target.x, 0, target.z, true); + setSelectedFloorItem(null); + } + } + } + }; + + const onDblClick = async (evt: any) => { + if (evt.button === 0) { + isLeftMouseDown = false; + if (drag) return; + + const Mode = transformMode; + + if (Mode !== null || activeTool === "cursor") { + if (!itemsGroup.current) return; + let intersects = raycaster.intersectObjects( + itemsGroup.current.children, + true + ); + if ( + intersects.length > 0 && + intersects[0]?.object?.parent?.parent?.position && + intersects[0]?.object?.parent?.parent?.scale && + intersects[0]?.object?.parent?.parent?.rotation + ) { + let currentObject = intersects[0].object; + + while (currentObject) { + if (currentObject.name === "Scene") { + break; + } + currentObject = currentObject.parent as THREE.Object3D; + } + if (currentObject) { + AttachedObject.current = currentObject as any; + // controls.fitToSphere(AttachedObject.current!, true); + + const bbox = new THREE.Box3().setFromObject( + AttachedObject.current + ); + const size = bbox.getSize(new THREE.Vector3()); + const center = bbox.getCenter(new THREE.Vector3()); + + const front = new THREE.Vector3(0, 0, 1); + AttachedObject.current.localToWorld(front); + front.sub(AttachedObject.current.position).normalize(); + + const distance = Math.max(size.x, size.y, size.z) * 2; + const newPosition = center + .clone() + .addScaledVector(front, distance); + + controls.setPosition( + newPosition.x, + newPosition.y, + newPosition.z, + true + ); + controls.setTarget(center.x, center.y, center.z, true); + controls.fitToBox(AttachedObject.current!, true, { + cover: true, + paddingTop: 5, + paddingLeft: 5, + paddingBottom: 5, + paddingRight: 5, + }); + + setSelectedFloorItem(AttachedObject.current!); + } + } else { + const target = controls.getTarget(new THREE.Vector3()); + await controls.setTarget(target.x, 0, target.z, true); + setSelectedFloorItem(null); + } + } + } + }; + + const onDrop = (event: any) => { + if (!event.dataTransfer?.files[0]) return; + + if (selectedItem.id !== "" && event.dataTransfer?.files[0]) { + addAssetModel( + raycaster, + state.camera, + state.pointer, + floorGroup, + setFloorItems, + itemsGroup, + isTempLoader, + tempLoader, + socket, + selectedItem, + setSelectedItem, + addEvent, + plane + ); + } + }; + + const onDragOver = (event: any) => { + event.preventDefault(); + }; + + if (activeModule === "builder") { + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + canvasElement.addEventListener("dblclick", onDblClick); + canvasElement.addEventListener("drop", onDrop); + canvasElement.addEventListener("dragover", onDragOver); + } else { + if (controls) { + const target = controls.getTarget(new THREE.Vector3()); + controls.setTarget(target.x, 0, target.z, true); + setSelectedFloorItem(null); } - } else { - const target = controls.getTarget(new THREE.Vector3()); - await controls.setTarget(target.x, 0, target.z, true); - setSelectedFloorItem(null); - } } - } - }; - const onDrop = (event: any) => { - if (!event.dataTransfer?.files[0]) return; + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + canvasElement.removeEventListener("dblclick", onDblClick); + canvasElement.removeEventListener("drop", onDrop); + canvasElement.removeEventListener("dragover", onDragOver); + }; + }, [ + deleteTool, + transformMode, + controls, + selectedItem, + state.camera, + state.pointer, + activeTool, + activeModule, + ]); - if (selectedItem.id !== "" && event.dataTransfer?.files[0]) { - addAssetModel( - raycaster, - state.camera, - state.pointer, - floorGroup, - setFloorItems, - itemsGroup, - isTempLoader, - tempLoader, - socket, - selectedItem, - setSelectedItem, - addEvent, - plane - ); - } - }; + useFrame(() => { + if (controls) + if (deleteTool && activeModule === "builder") { + // assetVisibility(itemsGroup, state.camera.position, renderDistance); + DeletableHoveredFloorItems( + state, + itemsGroup, + hoveredDeletableFloorItem, + setDeletableFloorItem + ); + } else if (!deleteTool) { + if (hoveredDeletableFloorItem.current) { + hoveredDeletableFloorItem.current = undefined; + setDeletableFloorItem(null); + } + } + }); - const onDragOver = (event: any) => { - event.preventDefault(); - }; - - if (activeModule === "builder") { - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - canvasElement.addEventListener("dblclick", onDblClick); - canvasElement.addEventListener("drop", onDrop); - canvasElement.addEventListener("dragover", onDragOver); - } else { - if (controls) { - const target = controls.getTarget(new THREE.Vector3()); - controls.setTarget(target.x, 0, target.z, true); - setSelectedFloorItem(null); - } - } - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - canvasElement.removeEventListener("dblclick", onDblClick); - canvasElement.removeEventListener("drop", onDrop); - canvasElement.removeEventListener("dragover", onDragOver); - }; - }, [ - deleteTool, - transformMode, - controls, - selectedItem, - state.camera, - state.pointer, - activeTool, - activeModule, - ]); - - useFrame(() => { - if (controls) - if (deleteTool && activeModule === "builder") { - // assetVisibility(itemsGroup, state.camera.position, renderDistance); - DeletableHoveredFloorItems( - state, - itemsGroup, - hoveredDeletableFloorItem, - setDeletableFloorItem - ); - } else if (!deleteTool) { - if (hoveredDeletableFloorItem.current) { - hoveredDeletableFloorItem.current = undefined; - setDeletableFloorItem(null); - } - } - }); - - return ; + return ; }; export default FloorItemsGroup;