import { useFrame, useThree } from "@react-three/fiber"; import { useActiveTool, useCamMode, useDeletableFloorItem, useDeleteModels, useFloorItems, 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 } from "../geomentries/assets/assetManager"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; import DeletableHoveredFloorItems from "../geomentries/assets/deletableHoveredFloorItems"; import DeleteFloorItems from "../geomentries/assets/deleteFloorItems"; import loadInitialFloorItems from "../../scene/IntialLoad/loadInitialFloorItems"; import addAssetModel from "../geomentries/assets/addAssetModel"; // import { getFloorItems } from "../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi"; // import { retrieveGLTF } from "../../../utils/indexDB/idbUtils"; const assetManagerWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/assetManagerWorker.js', import.meta.url)); // const gltfLoaderWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js', import.meta.url)); const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject, floorGroup, tempLoader, isTempLoader, plane }: any) => { const state: Types.ThreeState = useThree(); const { raycaster, camera, controls, pointer }: any = state; const { renderDistance, setRenderDistance } = useRenderDistance(); const { toggleView, setToggleView } = useToggleView(); const { floorItems, setFloorItems } = useFloorItems(); const { camMode, setCamMode } = useCamMode(); const { deleteModels, setDeleteModels } = useDeleteModels(); const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem(); const { transformMode, setTransformMode } = useTransformMode(); const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem(); const { activeTool, setActiveTool } = useActiveTool(); const { selectedItem, setSelectedItem } = useSelectedItem(); const { socket } = useSocketStore(); const loader = new GLTFLoader(); const dracoLoader = new DRACOLoader(); dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/'); loader.setDRACOLoader(dracoLoader); useEffect(() => { // Load initial floor items // const email = localStorage.getItem('email'); // const organization = (email!.split("@")[1]).split(".")[0]; // getFloorItems(organization).then((data) => { // gltfLoaderWorker.postMessage({ FloorItems: data }) // }) // 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); // }); // } else if (event.data.message === "done") { // loadInitialFloorItems(itemsGroup, setFloorItems); // } // } loadInitialFloorItems(itemsGroup, setFloorItems); }, []); useEffect(() => { assetManagerWorker.onmessage = async (event) => { cancelOngoingTasks(); // Cancel the ongoing process await assetManager(event.data, itemsGroup, loader); }; }, [assetManagerWorker]); useEffect(() => { if (toggleView) return const uuids: string[] = []; itemsGroup.current?.children.forEach((child: any) => { uuids.push(child.uuid); }); const cameraPosition = state.camera.position; assetManagerWorker.postMessage({ floorItems, cameraPosition, uuids, renderDistance }); }, [camMode, renderDistance]); 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]); 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 = () => { 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 (deleteModels) { 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, plane); } } const onDragOver = (event: any) => { event.preventDefault(); }; canvasElement.addEventListener("mousedown", onMouseDown); canvasElement.addEventListener("mouseup", onMouseUp); canvasElement.addEventListener("mousemove", onMouseMove); canvasElement.addEventListener("dblclick", onDblClick); canvasElement.addEventListener("drop", onDrop); canvasElement.addEventListener("dragover", onDragOver); 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); }; }, [deleteModels, transformMode, controls, selectedItem, state.camera, state.pointer, activeTool]); useFrame(() => { if (controls) assetVisibility(itemsGroup, state.camera.position, renderDistance); if (deleteModels) { DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem); } else if (!deleteModels) { if (hoveredDeletableFloorItem.current) { hoveredDeletableFloorItem.current = undefined; setDeletableFloorItem(null); } } }) return ( ) } export default FloorItemsGroup;