From 1253473a5dc37c1c46e578f015545f426900e5bd Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Fri, 5 Sep 2025 18:31:00 +0530 Subject: [PATCH] refactor: enhance camera controls and improve scene project update logic --- .../eventHandlers/useModelEventHandlers.ts | 3 +- app/src/modules/scene/camera/syncCam.tsx | 20 ++++-- app/src/modules/scene/scene.tsx | 65 +++++++++++-------- 3 files changed, 52 insertions(+), 36 deletions(-) diff --git a/app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts b/app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts index 1a43120..c3ca6f5 100644 --- a/app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts +++ b/app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts @@ -97,6 +97,7 @@ export function useModelEventHandlers({ boundingBox, groupRef, asset }: { boundi } else { const collisionPos = new THREE.Vector3(); groupRef.current.getWorldPosition(collisionPos); + const size = boundingBox.getSize(new THREE.Vector3()); const currentPos = new THREE.Vector3().copy(camera.position); @@ -109,7 +110,7 @@ export function useModelEventHandlers({ boundingBox, groupRef, asset }: { boundi const newCameraPos = new THREE.Vector3().copy(collisionPos).sub(direction.multiplyScalar(offsetDistance)); camera.position.copy(newCameraPos); - (controls as CameraControls).setLookAt(newCameraPos.x, newCameraPos.y, newCameraPos.z, collisionPos.x, 0, collisionPos.z, true); + (controls as CameraControls).setLookAt(newCameraPos.x, size.y > newCameraPos.y ? size.y : newCameraPos.y, newCameraPos.z, collisionPos.x, 0, collisionPos.z, true); } setSelectedFloorAsset(groupRef.current); diff --git a/app/src/modules/scene/camera/syncCam.tsx b/app/src/modules/scene/camera/syncCam.tsx index 647ef28..3847a3b 100644 --- a/app/src/modules/scene/camera/syncCam.tsx +++ b/app/src/modules/scene/camera/syncCam.tsx @@ -1,11 +1,13 @@ -import { useFrame, useThree } from "@react-three/fiber"; -import { useSceneContext } from "../sceneContext"; -import { CameraControls } from "@react-three/drei"; -import { useIsComparing } from "../../../store/builder/store"; -import useModuleStore from "../../../store/ui/useModuleStore"; -import { useComparisonProduct } from "../../../store/simulation/useSimulationStore"; -import { useSceneStore } from "../../../store/scene/useSceneStore"; import { Vector3 } from "three"; +import { useFrame, useThree } from "@react-three/fiber"; +import { CameraControls } from "@react-three/drei"; +import { useSceneContext } from "../sceneContext"; +import { useIsComparing } from "../../../store/builder/store"; +import { useSceneStore } from "../../../store/scene/useSceneStore"; +import { useComparisonProduct } from "../../../store/simulation/useSimulationStore"; +import useModuleStore from "../../../store/ui/useModuleStore"; + +import * as CONSTANTS from "../../../types/world/worldConstants"; function SyncCam() { const { layout } = useSceneContext(); @@ -17,6 +19,10 @@ function SyncCam() { useFrame(() => { if (layout === "Comparison Layout" && controls && camState) { + (controls as any).mouseButtons.left = CONSTANTS.controlsTransition.leftMouse; + (controls as any).mouseButtons.right = CONSTANTS.controlsTransition.rightMouse; + (controls as any).mouseButtons.wheel = CONSTANTS.controlsTransition.wheelMouse; + (controls as any).mouseButtons.middle = CONSTANTS.controlsTransition.middleMouse; (controls as CameraControls).setLookAt(camState.position.x, camState.position.y, camState.position.z, camState.target.x, camState.target.y, camState.target.z, true); } if (layout === "Main Layout" && controls && isComparing && activeModule === "simulation" && comparisonProduct) { diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index e68ed00..52c9907 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -16,13 +16,16 @@ import { useLoadingProgress, useSocketStore } from "../../store/builder/store"; import { Color, SRGBColorSpace } from "three"; import { compressImage } from "../../utils/compressImage"; -export default function Scene({ layout }: { readonly layout: "Main Layout" | "Comparison Layout"; }) { - const map = useMemo(() => [ - { name: "forward", keys: ["ArrowUp", "w", "W"] }, - { name: "backward", keys: ["ArrowDown", "s", "S"] }, - { name: "left", keys: ["ArrowLeft", "a", "A"] }, - { name: "right", keys: ["ArrowRight", "d", "D"] }, - ], []); +export default function Scene({ layout }: { readonly layout: "Main Layout" | "Comparison Layout" }) { + const map = useMemo( + () => [ + { name: "forward", keys: ["ArrowUp", "w", "W"] }, + { name: "backward", keys: ["ArrowDown", "s", "S"] }, + { name: "left", keys: ["ArrowLeft", "a", "A"] }, + { name: "right", keys: ["ArrowRight", "d", "D"] }, + ], + [] + ); const { assetStore } = useSceneContext(); const { assets } = assetStore(); const { userId, organization } = getUserData(); @@ -33,26 +36,28 @@ export default function Scene({ layout }: { readonly layout: "Main Layout" | "Co useEffect(() => { if (!projectId || loadingProgress !== 0) return; - getAllProjects(userId, organization).then((projects) => { - if (!projects.Projects) return; - let project = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId); - const canvas = document.getElementById("sceneCanvas")?.getElementsByTagName("canvas")[0]; - if (!canvas) return; - compressImage(canvas.toDataURL("image/png")).then((screenshotDataUrl) => { - const updateProjects = { - projectId: project?._id, - organization, - userId, - projectName: project?.projectName, - thumbnail: screenshotDataUrl, - }; - if (projectSocket) { - projectSocket.emit("v1:project:update", updateProjects); - } + getAllProjects(userId, organization) + .then((projects) => { + if (!projects.Projects) return; + let project = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId); + const canvas = document.getElementById("sceneCanvas")?.getElementsByTagName("canvas")[0]; + if (!canvas) return; + compressImage(canvas.toDataURL("image/png")).then((screenshotDataUrl) => { + const updateProjects = { + projectId: project?._id, + organization, + userId, + projectName: project?.projectName, + thumbnail: screenshotDataUrl, + }; + if (projectSocket) { + projectSocket.emit("v1:project:update", updateProjects); + } + }); + }) + .catch((err) => { + console.error(err); }); - }).catch((err) => { - console.error(err); - }); // eslint-disable-next-line }, [activeModule, assets, loadingProgress]); @@ -63,9 +68,13 @@ export default function Scene({ layout }: { readonly layout: "Main Layout" | "Co shadows color="#aaaa" eventPrefix="client" - onContextMenu={(e) => { e.preventDefault(); }} + onContextMenu={(e) => { + e.preventDefault(); + }} performance={{ min: 0.9, max: 1.0 }} - onCreated={(e) => { e.scene.background = layout === "Main Layout" ? null : new Color(0x19191d); }} + onCreated={(e) => { + e.scene.background = layout === "Main Layout" ? null : new Color(0x19191d); + }} gl={{ outputColorSpace: SRGBColorSpace, powerPreference: "high-performance", antialias: true, preserveDrawingBuffer: true }} >