import { CameraControls } from "@react-three/drei"; import { useRef, useEffect } from "react"; import { useThree } from "@react-three/fiber"; import * as THREE from "three"; import * as CONSTANTS from "../../../types/world/worldConstants"; import { useSocketStore, useToggleView, useResetCamera } from "../../../store/builder/store"; import { useSceneStore } from "../../../store/scene/useSceneStore"; import CamMode from "../camera/camMode"; import SwitchView from "../camera/switchView"; import SyncCam from "../camera/syncCam"; import ContextControls from "./contextControls/contextControls"; import TransformControl from "./transformControls/transformControls"; import SelectionControls2D from "./selectionControls/selection2D/selectionControls2D"; import SelectionControls3D from "./selectionControls/selection3D/selectionControls3D"; import UndoRedo2DControls from "./undoRedoControls/undoRedo2D/undoRedo2DControls"; import UndoRedo3DControls from "./undoRedoControls/undoRedo3D/undoRedo3DControls"; import CameraShortcutsControls from "../camera/shortcutsControls/cameraShortcutsControls"; import { useParams } from "react-router-dom"; import { getUserData } from "../../../functions/getUserData"; import { getCameraApi } from "../../../services/factoryBuilder/camera/getCameraApi"; import { setCameraApi } from "../../../services/factoryBuilder/camera/setCameraApi"; import updateCamPosition from "../camera/functions/updateCameraPosition"; export default function Controls() { const controlsRef = useRef(null); const state = useThree(); const { toggleView } = useToggleView(); const { resetCamera, setResetCamera } = useResetCamera(); const { camType } = useSceneStore(); const { socket } = useSocketStore(); const { projectId } = useParams(); const { userId, organization } = getUserData(); useEffect(() => { if (controlsRef.current) { (controlsRef.current as any).mouseButtons.left = CONSTANTS.thirdPersonControls.leftMouse; (controlsRef.current as any).mouseButtons.right = CONSTANTS.thirdPersonControls.rightMouse; } if (!projectId) return; getCameraApi(projectId) .then((data) => { if (data?.position && data?.target) { controlsRef.current?.setPosition(data.position.x, data.position.y, data.position.z); controlsRef.current?.setTarget(data.target.x, data.target.y, data.target.z); } else { controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition); controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget); } }) .catch((error) => console.error("Failed to fetch camera data:", error)); }, [projectId]); useEffect(() => { if (resetCamera && projectId) { controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition); controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget); controlsRef.current?.rotateAzimuthTo(CONSTANTS.threeDimension.defaultAzimuth); if (!socket?.connected) { setCameraApi( projectId, new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition), new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget), new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation) ); } else { const camData = { organization, userId: userId, position: new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition), target: new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget), rotation: new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation), socketId: socket.id, projectId, }; socket.emit("v1:Camera:set", camData); } setResetCamera(false); } }, [resetCamera]); useEffect(() => { controlsRef.current?.setBoundary(new THREE.Box3(new THREE.Vector3(...CONSTANTS.threeDimension.boundaryBottom), new THREE.Vector3(...CONSTANTS.threeDimension.boundaryTop))); // state.scene.add(new THREE.Box3Helper(new THREE.Box3(new THREE.Vector3(...CONSTANTS.threeDimension.boundaryBottom), new THREE.Vector3(...CONSTANTS.threeDimension.boundaryTop)), 0xffff00)); let hasInteracted = false; let intervalId: NodeJS.Timeout | null = null; const handleRest = () => { if (hasInteracted && controlsRef.current && state.camera.position && !toggleView && socket && camType === "perspective") { const position = state.camera.position; if (position.x === 0 && position.y === 0 && position.z === 0) return; updateCamPosition(controlsRef, socket, position, state.camera.rotation, projectId); stopInterval(); } }; const startInterval = () => { hasInteracted = true; if (!intervalId) { intervalId = setInterval(() => { if (controlsRef.current && !toggleView && camType === "perspective") { handleRest(); } }, CONSTANTS.camPositionUpdateInterval); } }; const stopInterval = () => { if (intervalId) { clearInterval(intervalId); intervalId = null; } }; const controls = controlsRef.current; if (controls && !toggleView && camType === "perspective") { controls.addEventListener("sleep", handleRest); controls.addEventListener("control", startInterval); controls.addEventListener("controlend", stopInterval); } return () => { if (controls) { controls.removeEventListener("sleep", handleRest); controls.removeEventListener("control", startInterval); controls.removeEventListener("controlend", stopInterval); } stopInterval(); }; }, [toggleView, state, socket, camType]); return ( <> ); }