From c309af135dcd8eaf4c3bc99a63bc4685d91f32ac Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Fri, 18 Jul 2025 14:14:34 +0530 Subject: [PATCH 1/5] moveControls and other controls altered --- app/src/modules/builder/asset/assetsGroup.tsx | 4 +- .../asset/functions/assetBoundingBox.tsx | 54 +++- .../builder/asset/models/model/model.tsx | 32 ++- .../selection2D/moveControls2D.tsx | 4 +- .../selection3D/copyPasteControls3D.tsx | 233 ++++++++------- .../selection3D/duplicationControls3D.tsx | 247 +++++++++------- .../selection3D/moveControls3D.tsx | 267 ++++++++++-------- .../selection3D/rotateControls3D.tsx | 250 ++++++++-------- .../selection3D/selectionControls3D.tsx | 28 +- 9 files changed, 634 insertions(+), 485 deletions(-) diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx index a05e423..85c0f88 100644 --- a/app/src/modules/builder/asset/assetsGroup.tsx +++ b/app/src/modules/builder/asset/assetsGroup.tsx @@ -44,9 +44,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) { const loader = new GLTFLoader(); const dracoLoader = new DRACOLoader(); - dracoLoader.setDecoderPath( - "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/" - ); + dracoLoader.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/"); loader.setDRACOLoader(dracoLoader); useEffect(() => { diff --git a/app/src/modules/builder/asset/functions/assetBoundingBox.tsx b/app/src/modules/builder/asset/functions/assetBoundingBox.tsx index d74f37d..b26485d 100644 --- a/app/src/modules/builder/asset/functions/assetBoundingBox.tsx +++ b/app/src/modules/builder/asset/functions/assetBoundingBox.tsx @@ -1,20 +1,46 @@ -import { Box3, BoxGeometry, EdgesGeometry, Vector3 } from "three"; +import { Line } from "@react-three/drei"; +import { Box3, Vector3 } from "three"; +import { useMemo } from "react"; + +export const AssetBoundingBox = ({ name, boundingBox, color, lineWidth, }: { name: string; boundingBox: Box3 | null; color: string; lineWidth: number; }) => { + const { points } = useMemo(() => { + if (!boundingBox) return { points: [], center: new Vector3() }; + + const min = boundingBox.min; + const max = boundingBox.max; + const center = boundingBox.getCenter(new Vector3()); + + const edges: Array<[number, number, number]> = [ + [min.x, min.y, min.z], [max.x, min.y, min.z], + [max.x, min.y, min.z], [max.x, max.y, min.z], + [max.x, max.y, min.z], [min.x, max.y, min.z], + [min.x, max.y, min.z], [min.x, min.y, min.z], + + [min.x, min.y, max.z], [max.x, min.y, max.z], + [max.x, min.y, max.z], [max.x, max.y, max.z], + [max.x, max.y, max.z], [min.x, max.y, max.z], + [min.x, max.y, max.z], [min.x, min.y, max.z], + + [min.x, min.y, min.z], [min.x, min.y, max.z], + [max.x, min.y, min.z], [max.x, min.y, max.z], + [max.x, max.y, min.z], [max.x, max.y, max.z], + [min.x, max.y, min.z], [min.x, max.y, max.z], + ]; + + return { points: edges, center }; + }, [boundingBox]); -export const AssetBoundingBox = ({ boundingBox }: { boundingBox: Box3 | null }) => { if (!boundingBox) return null; - const size = boundingBox.getSize(new Vector3()); - const center = boundingBox.getCenter(new Vector3()); - - const boxGeometry = new BoxGeometry(size.x, size.y, size.z); - const edges = new EdgesGeometry(boxGeometry); - return ( - - - - - + + ); -}; \ No newline at end of file +}; diff --git a/app/src/modules/builder/asset/models/model/model.tsx b/app/src/modules/builder/asset/models/model/model.tsx index 6819cb4..429a9c3 100644 --- a/app/src/modules/builder/asset/models/model/model.tsx +++ b/app/src/modules/builder/asset/models/model/model.tsx @@ -4,7 +4,7 @@ import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils'; import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; import { ThreeEvent, useFrame, useThree } from '@react-three/fiber'; -import { useActiveTool, useDeletableFloorItem, useLimitDistance, useRenderDistance, useSelectedFloorItem, useSocketStore, useToggleView, useToolMode } from '../../../../../store/builder/store'; +import { useActiveTool, useDeletableFloorItem, useLimitDistance, useRenderDistance, useSelectedAssets, useSelectedFloorItem, useSocketStore, useToggleView, useToolMode } from '../../../../../store/builder/store'; import { AssetBoundingBox } from '../../functions/assetBoundingBox'; import { CameraControls } from '@react-three/drei'; import useModuleStore, { useSubModuleStore } from '../../../../../store/useModuleStore'; @@ -22,6 +22,7 @@ import { getAssetIksApi } from '../../../../../services/simulation/ik/getAssetIK function Model({ asset }: { readonly asset: Asset }) { const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; + const savedTheme: string = localStorage.getItem("theme") || "light"; const { camera, controls, gl } = useThree(); const { activeTool } = useActiveTool(); const { toolMode } = useToolMode(); @@ -51,6 +52,7 @@ function Model({ asset }: { readonly asset: Asset }) { const [isRendered, setIsRendered] = useState(false); const [gltfScene, setGltfScene] = useState(null); const [boundingBox, setBoundingBox] = useState(null); + const [isSelected, setIsSelected] = useState(false); const groupRef = useRef(null); const mixerRef = useRef(); const actions = useRef<{ [name: string]: THREE.AnimationAction }>({}); @@ -62,6 +64,7 @@ function Model({ asset }: { readonly asset: Asset }) { const { selectedVersion } = selectedVersionStore(); const { userId, organization } = getUserData(); const { projectId } = useParams(); + const { selectedAssets } = useSelectedAssets(); const updateBackend = ( productName: string, @@ -456,6 +459,18 @@ function Model({ asset }: { readonly asset: Asset }) { }, [gl]) + useEffect(() => { + if (selectedAssets.length > 0) { + if (selectedAssets.some((selectedAsset: THREE.Object3D) => selectedAsset.userData.modelUuid === asset.modelUuid)) { + setIsSelected(true); + } else { + setIsSelected(false); + } + } else { + setIsSelected(false); + } + }, [selectedAssets]) + return ( {gltfScene && ( - isRendered ? ( - - ) : ( - - ) + <> + {isRendered ? ( + + ) : ( + + )} + {isSelected && + + } + )} ); diff --git a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx index 790a330..d91cebb 100644 --- a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx @@ -83,7 +83,7 @@ function MoveControls2D({ if (keyCombination === "G") { if (selectedPoints.length > 0) { - moveAssets(); + movePoints(); } } @@ -164,7 +164,7 @@ function MoveControls2D({ return new THREE.Vector3().subVectors(pointPosition, hitPoint); }, []); - const moveAssets = useCallback(() => { + const movePoints = useCallback(() => { if (selectedPoints.length === 0) return; const states: Record = {}; diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx index fa3e8c7..8593758 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { useEffect, useMemo } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useFrame, useThree } from "@react-three/fiber"; import { SkeletonUtils } from "three-stdlib"; import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../../store/builder/store"; @@ -10,20 +10,16 @@ import { getUserData } from "../../../../../functions/getUserData"; import { useSceneContext } from "../../../sceneContext"; import { useVersionContext } from "../../../../builder/version/versionContext"; -// import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi'; - const CopyPasteControls3D = ({ copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, - selectionGroup, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, - boundingBoxRef }: any) => { const { camera, controls, gl, scene, pointer, raycaster } = useThree(); const { toggleView } = useToggleView(); @@ -33,31 +29,67 @@ const CopyPasteControls3D = ({ const { assetStore, eventStore } = useSceneContext(); const { addEvent } = eventStore(); const { projectId } = useParams(); - const { assets, addAsset } = assetStore(); + const { assets, addAsset, setPosition, updateAsset, removeAsset, getAssetById } = assetStore(); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); const { userId, organization } = getUserData(); + const [isPasting, setIsPasting] = useState(false); + const [relativePositions, setRelativePositions] = useState([]); + const [centerOffset, setCenterOffset] = useState(null); + const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ + left: false, + right: false, + }); + + const calculateRelativePositions = useCallback((objects: THREE.Object3D[]) => { + if (objects.length === 0) return { center: new THREE.Vector3(), relatives: [] }; + + const box = new THREE.Box3(); + objects.forEach(obj => box.expandByObject(obj)); + const center = new THREE.Vector3(); + box.getCenter(center); + + const relatives = objects.map(obj => { + const relativePos = new THREE.Vector3().subVectors(obj.position, center); + return relativePos; + }); + + return { center, relatives }; + }, []); + useEffect(() => { if (!camera || !scene || toggleView) return; const canvasElement = gl.domElement; canvasElement.tabIndex = 0; - let isMoving = false; + let isPointerMoving = false; - const onPointerDown = () => { - isMoving = false; + const onPointerDown = (event: PointerEvent) => { + isPointerMoving = false; + if (event.button === 0) mouseButtonsDown.current.left = true; + if (event.button === 2) mouseButtonsDown.current.right = true; }; const onPointerMove = () => { - isMoving = true; + isPointerMoving = true; }; const onPointerUp = (event: PointerEvent) => { - if (!isMoving && pastedObjects.length > 0 && event.button === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { + if (event.button === 0) mouseButtonsDown.current.left = false; + if (event.button === 2) mouseButtonsDown.current.right = false; + + if (!isPointerMoving && pastedObjects.length > 0 && event.button === 0) { event.preventDefault(); addPastedObjects(); } + if (!isPointerMoving && pastedObjects.length > 0 && event.button === 2) { + event.preventDefault(); + clearSelection(); + pastedObjects.forEach((obj: THREE.Object3D) => { + removeAsset(obj.userData.modelUuid); + }); + } }; const onKeyDown = (event: KeyboardEvent) => { @@ -69,6 +101,13 @@ const CopyPasteControls3D = ({ if (keyCombination === "Ctrl+V" && copiedObjects.length > 0 && pastedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { pasteCopiedObjects(); } + if (keyCombination === "ESCAPE" && pastedObjects.length > 0) { + event.preventDefault(); + clearSelection(); + pastedObjects.forEach((obj: THREE.Object3D) => { + removeAsset(obj.userData.modelUuid); + }); + } }; if (!toggleView) { @@ -84,27 +123,22 @@ const CopyPasteControls3D = ({ canvasElement.removeEventListener("pointerup", onPointerUp); canvasElement.removeEventListener("keydown", onKeyDown); }; - }, [assets, camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, movedObjects, socket, rotatedObjects]); useFrame(() => { - if (pastedObjects.length > 0) { - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - if (point) { - const position = new THREE.Vector3(); - if (boundingBoxRef.current) { - boundingBoxRef.current?.getWorldPosition(position) - selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); - } else { - const box = new THREE.Box3(); - pastedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone())); - const center = new THREE.Vector3(); - box.getCenter(center); - selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z)); - } - } + if (!isPasting || pastedObjects.length === 0) return; + if (mouseButtonsDown.current.left || mouseButtonsDown.current.right) return; + + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const hit = raycaster.ray.intersectPlane(plane, intersectionPoint); + + if (hit && centerOffset) { + pastedObjects.forEach((pastedObject: THREE.Object3D, index: number) => { + const newPos = new THREE.Vector3().addVectors(hit, relativePositions[index]); + setPosition(pastedObject.userData.modelUuid, [newPos.x, 0, newPos.z]); + }); + } }); @@ -122,31 +156,41 @@ const CopyPasteControls3D = ({ const pasteCopiedObjects = () => { if (copiedObjects.length > 0 && pastedObjects.length === 0) { - const newClones = copiedObjects.map((obj: THREE.Object3D) => { - const clone = obj.clone(); - clone.position.copy(obj.position); + const { center, relatives } = calculateRelativePositions(copiedObjects); + setRelativePositions(relatives); + + const newPastedObjects = copiedObjects.map((obj: any) => { + const clone = SkeletonUtils.clone(obj); + clone.userData.modelUuid = THREE.MathUtils.generateUUID(); return clone; }); - selectionGroup.current.add(...newClones); - setpastedObjects([...newClones]); - setSelectedAssets([...newClones]); - const intersectionPoint = new THREE.Vector3(); + setpastedObjects(newPastedObjects); + raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + const intersectionPoint = new THREE.Vector3(); + const hit = raycaster.ray.intersectPlane(plane, intersectionPoint); - if (point) { - const position = new THREE.Vector3(); - if (boundingBoxRef.current) { - boundingBoxRef.current?.getWorldPosition(position) - selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); - } else { - const box = new THREE.Box3(); - newClones.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone())); - const center = new THREE.Vector3(); - box.getCenter(center); - selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z)); - } + if (hit) { + const offset = new THREE.Vector3().subVectors(center, hit); + setCenterOffset(offset); + setIsPasting(true); + + newPastedObjects.forEach((obj: THREE.Object3D, index: number) => { + const initialPos = new THREE.Vector3().addVectors(hit, relatives[index]); + const asset: Asset = { + modelUuid: obj.userData.modelUuid, + modelName: obj.userData.modelName, + assetId: obj.userData.assetId, + position: initialPos.toArray(), + rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], + isLocked: false, + isVisible: true, + isCollidable: false, + opacity: 0.5, + }; + addAsset(asset); + }); } } }; @@ -154,33 +198,33 @@ const CopyPasteControls3D = ({ const addPastedObjects = () => { if (pastedObjects.length === 0) return; - pastedObjects.forEach(async (obj: THREE.Object3D) => { - if (obj) { - const worldPosition = new THREE.Vector3(); - obj.getWorldPosition(worldPosition); - obj.position.copy(worldPosition); + pastedObjects.forEach(async (pastedAsset: THREE.Object3D) => { + if (pastedAsset) { + const assetUuid = pastedAsset.userData.modelUuid; + const asset = getAssetById(assetUuid); + if (!asset) return; const newFloorItem: Types.FloorItemType = { - modelUuid: THREE.MathUtils.generateUUID(), - modelName: obj.userData.modelName, - assetId: obj.userData.assetId, - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, + modelUuid: pastedAsset.userData.modelUuid, + modelName: pastedAsset.userData.modelName, + assetId: pastedAsset.userData.assetId, + position: asset.position, + rotation: { x: asset.rotation[0], y: asset.rotation[1], z: asset.rotation[2] }, isLocked: false, isVisible: true, }; let updatedEventData = null; - if (obj.userData.eventData) { - updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData)); + if (pastedAsset.userData.eventData) { + updatedEventData = JSON.parse(JSON.stringify(pastedAsset.userData.eventData)); updatedEventData.modelUuid = newFloorItem.modelUuid; const eventData: any = { - type: obj.userData.eventData.type, + type: pastedAsset.userData.eventData.type, }; - if (obj.userData.eventData.type === "Conveyor") { + if (pastedAsset.userData.eventData.type === "Conveyor") { const ConveyorEvent: ConveyorEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -212,7 +256,7 @@ const CopyPasteControls3D = ({ rotation: point.rotation })); - } else if (obj.userData.eventData.type === "Vehicle") { + } else if (pastedAsset.userData.eventData.type === "Vehicle") { const vehicleEvent: VehicleEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -250,7 +294,7 @@ const CopyPasteControls3D = ({ rotation: vehicleEvent.point.rotation }; - } else if (obj.userData.eventData.type === "ArmBot") { + } else if (pastedAsset.userData.eventData.type === "ArmBot") { const roboticArmEvent: RoboticArmEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -284,7 +328,7 @@ const CopyPasteControls3D = ({ rotation: roboticArmEvent.point.rotation }; - } else if (obj.userData.eventData.type === "StaticMachine") { + } else if (pastedAsset.userData.eventData.type === "StaticMachine") { const machineEvent: MachineEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -312,7 +356,7 @@ const CopyPasteControls3D = ({ position: machineEvent.point.position, rotation: machineEvent.point.rotation }; - } else if (obj.userData.eventData.type === "Storage") { + } else if (pastedAsset.userData.eventData.type === "Storage") { const storageEvent: StorageEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -339,7 +383,7 @@ const CopyPasteControls3D = ({ position: storageEvent.point.position, rotation: storageEvent.point.rotation }; - } else if (obj.userData.eventData.type === "Human") { + } else if (pastedAsset.userData.eventData.type === "Human") { const humanEvent: HumanEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -374,15 +418,16 @@ const CopyPasteControls3D = ({ } newFloorItem.eventData = eventData; + //REST // await setAssetsApi( // organization, - // obj.uuid, - // obj.userData.name, + // pastedAsset.uuid, + // pastedAsset.userData.name, // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, - // obj.userData.modelId, + // { "x": pastedAsset.rotation.x, "y": pastedAsset.rotation.y, "z": pastedAsset.rotation.z }, + // pastedAsset.userData.modelId, // false, // true, // ); @@ -395,7 +440,7 @@ const CopyPasteControls3D = ({ modelName: newFloorItem.modelName, assetId: newFloorItem.assetId, position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + rotation: { x: pastedAsset.rotation.x, y: pastedAsset.rotation.y, z: pastedAsset.rotation.z }, isLocked: false, isVisible: true, socketId: socket.id, @@ -405,16 +450,8 @@ const CopyPasteControls3D = ({ projectId }; - // console.log('data: ', data); socket.emit("v1:model-asset:add", data); - obj.userData = { - name: newFloorItem.modelName, - modelId: newFloorItem.assetId, - modelUuid: newFloorItem.modelUuid, - eventData: JSON.parse(JSON.stringify(eventData)) - }; - const asset: Asset = { modelUuid: data.modelUuid, modelName: data.modelName, @@ -426,33 +463,17 @@ const CopyPasteControls3D = ({ isVisible: data.isVisible, opacity: 1, eventData: data.eventData - } - - addAsset(asset); + }; + updateAsset(asset.modelUuid, asset); } else { - - //REST - - // await setAssetsApi( - // organization, - // obj.uuid, - // obj.userData.name, - // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, - // obj.userData.modelId, - // false, - // true, - // ); - - //SOCKET const data = { organization, modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, assetId: newFloorItem.assetId, position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + rotation: { x: pastedAsset.rotation.x, y: pastedAsset.rotation.y, z: pastedAsset.rotation.z }, isLocked: false, isVisible: true, socketId: socket.id, @@ -461,7 +482,6 @@ const CopyPasteControls3D = ({ userId }; - // console.log('data: ', data); socket.emit("v1:model-asset:add", data); const asset: Asset = { @@ -474,9 +494,9 @@ const CopyPasteControls3D = ({ isCollidable: false, isVisible: data.isVisible, opacity: 1, - } + }; - addAsset(asset); + updateAsset(asset.modelUuid, asset); } } }); @@ -486,15 +506,14 @@ const CopyPasteControls3D = ({ }; const clearSelection = () => { - selectionGroup.current.children = []; - selectionGroup.current.position.set(0, 0, 0); - selectionGroup.current.rotation.set(0, 0, 0); setMovedObjects([]); setpastedObjects([]); setDuplicatedObjects([]); setRotatedObjects([]); setSelectedAssets([]); - } + setIsPasting(false); + setCenterOffset(null); + }; return null; }; diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx index ec92d6d..4f08cc7 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { useEffect, useMemo } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useFrame, useThree } from "@react-three/fiber"; import { SkeletonUtils } from "three-stdlib"; import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../../store/builder/store"; @@ -10,18 +10,14 @@ import { getUserData } from "../../../../../functions/getUserData"; import { useSceneContext } from "../../../sceneContext"; import { useVersionContext } from "../../../../builder/version/versionContext"; -// import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi'; - const DuplicationControls3D = ({ duplicatedObjects, setDuplicatedObjects, setpastedObjects, - selectionGroup, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, - boundingBoxRef }: any) => { const { camera, controls, gl, scene, pointer, raycaster } = useThree(); const { toggleView } = useToggleView(); @@ -31,39 +27,71 @@ const DuplicationControls3D = ({ const { assetStore, eventStore } = useSceneContext(); const { addEvent } = eventStore(); const { projectId } = useParams(); - const { assets, addAsset } = assetStore(); + const { assets, addAsset, setPosition, updateAsset, removeAsset, getAssetById } = assetStore(); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); const { userId, organization } = getUserData(); + const [dragOffset, setDragOffset] = useState(null); + const [initialPositions, setInitialPositions] = useState>({}); + const [isDuplicating, setIsDuplicating] = useState(false); + const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ + left: false, + right: false, + }); + + const calculateDragOffset = useCallback((point: THREE.Vector3, hitPoint: THREE.Vector3) => { + const pointPosition = new THREE.Vector3().copy(point); + return new THREE.Vector3().subVectors(pointPosition, hitPoint); + }, []); + useEffect(() => { if (!camera || !scene || toggleView) return; const canvasElement = gl.domElement; canvasElement.tabIndex = 0; - let isMoving = false; + let isPointerMoving = false; - const onPointerDown = () => { - isMoving = false; + const onPointerDown = (event: PointerEvent) => { + isPointerMoving = false; + if (event.button === 0) mouseButtonsDown.current.left = true; + if (event.button === 2) mouseButtonsDown.current.right = true; }; const onPointerMove = () => { - isMoving = true; + isPointerMoving = true; }; const onPointerUp = (event: PointerEvent) => { - if (!isMoving && duplicatedObjects.length > 0 && event.button === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { + if (event.button === 0) mouseButtonsDown.current.left = false; + if (event.button === 2) mouseButtonsDown.current.right = false; + + if (!isPointerMoving && duplicatedObjects.length > 0 && event.button === 0) { event.preventDefault(); addDuplicatedAssets(); } + if (!isPointerMoving && duplicatedObjects.length > 0 && event.button === 2) { + event.preventDefault(); + clearSelection(); + duplicatedObjects.forEach((obj: THREE.Object3D) => { + removeAsset(obj.userData.modelUuid); + }); + } }; const onKeyDown = (event: KeyboardEvent) => { const keyCombination = detectModifierKeys(event); - if (keyCombination === "Ctrl+D" && selectedAssets.length > 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { + if (keyCombination === "Ctrl+D" && movedObjects.length === 0 && rotatedObjects.length === 0) { duplicateSelection(); } + if (keyCombination === "ESCAPE" && duplicatedObjects.length > 0) { + event.preventDefault(); + clearSelection(); + duplicatedObjects.forEach((obj: THREE.Object3D) => { + removeAsset(obj.userData.modelUuid); + }); + } }; if (!toggleView) { @@ -79,82 +107,125 @@ const DuplicationControls3D = ({ canvasElement.removeEventListener("pointerup", onPointerUp); canvasElement.removeEventListener("keydown", onKeyDown); }; - }, [assets, camera, controls, scene, toggleView, selectedAssets, duplicatedObjects, movedObjects, socket, rotatedObjects]); useFrame(() => { - if (duplicatedObjects.length > 0) { - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); - if (point) { - const position = new THREE.Vector3(); - if (boundingBoxRef.current) { - boundingBoxRef.current?.getWorldPosition(position) - selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); - } else { - const box = new THREE.Box3(); - duplicatedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone())); - const center = new THREE.Vector3(); - box.getCenter(center); - selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z)); + if (!isDuplicating || duplicatedObjects.length === 0) return; + + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const hit = raycaster.ray.intersectPlane(plane, intersectionPoint); + + if (hit) { + if (mouseButtonsDown.current.left || mouseButtonsDown.current.right) { + const assetUuid = duplicatedObjects[0].userData.modelUuid; + const asset = getAssetById(assetUuid); + if (!asset) return; + if (duplicatedObjects[0]) { + const newOffset = calculateDragOffset(new THREE.Vector3(...asset.position), intersectionPoint); + setDragOffset(newOffset); } + return; + } + + if (dragOffset) { + const adjustedHit = new THREE.Vector3().addVectors(intersectionPoint, dragOffset); + + duplicatedObjects.forEach((duplicatedObject: THREE.Object3D) => { + if (duplicatedObject.userData.modelUuid) { + const initialPosition = initialPositions[duplicatedObject.userData.modelUuid]; + + if (initialPosition) { + + const relativeOffset = new THREE.Vector3().subVectors( + initialPosition, + initialPositions[duplicatedObjects[0].userData.modelUuid] + ); + + const newPosition = new THREE.Vector3().addVectors(adjustedHit, relativeOffset); + const positionArray: [number, number, number] = [newPosition.x, newPosition.y, newPosition.z]; + + setPosition(duplicatedObject.userData.modelUuid, positionArray); + } + } + }); } } }); - const duplicateSelection = () => { + const duplicateSelection = useCallback(() => { if (selectedAssets.length > 0 && duplicatedObjects.length === 0) { - const newClones = selectedAssets.map((asset: any) => { - const clone = SkeletonUtils.clone(asset); - clone.position.copy(asset.position); + const positions: Record = {}; + + const newDuplicatedObjects = selectedAssets.map((obj: any) => { + const clone = SkeletonUtils.clone(obj); + clone.userData.modelUuid = THREE.MathUtils.generateUUID(); + positions[clone.userData.modelUuid] = new THREE.Vector3().copy(obj.position); return clone; }); - selectionGroup.current.add(...newClones); - setDuplicatedObjects(newClones); + setDuplicatedObjects(newDuplicatedObjects); + setInitialPositions(positions); - const intersectionPoint = new THREE.Vector3(); raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + const intersectionPoint = new THREE.Vector3(); + const hit = raycaster.ray.intersectPlane(plane, intersectionPoint); - if (point) { - const position = new THREE.Vector3(); - boundingBoxRef.current?.getWorldPosition(position) - selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z)); + if (hit) { + const offset = calculateDragOffset(selectedAssets[0].position, hit); + setDragOffset(offset); } + + setIsDuplicating(true); + + newDuplicatedObjects.forEach((obj: THREE.Object3D) => { + const asset: Asset = { + modelUuid: obj.userData.modelUuid, + modelName: obj.userData.modelName, + assetId: obj.userData.assetId, + position: [obj.position.x, 0, obj.position.z], + rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], + isLocked: false, + isVisible: true, + isCollidable: false, + opacity: 0.5, + }; + addAsset(asset); + }); } - }; + }, [selectedAssets, duplicatedObjects]); + const addDuplicatedAssets = () => { if (duplicatedObjects.length === 0) return; - duplicatedObjects.forEach(async (obj: THREE.Object3D) => { - if (obj) { - const worldPosition = new THREE.Vector3(); - obj.getWorldPosition(worldPosition); - obj.position.copy(worldPosition); + duplicatedObjects.forEach(async (duplicatedAsset: THREE.Object3D) => { + if (duplicatedAsset) { + const assetUuid = duplicatedAsset.userData.modelUuid; + const asset = getAssetById(assetUuid); + if (!asset) return; const newFloorItem: Types.FloorItemType = { - modelUuid: THREE.MathUtils.generateUUID(), - modelName: obj.userData.modelName, - assetId: obj.userData.assetId, - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, + modelUuid: duplicatedAsset.userData.modelUuid, + modelName: duplicatedAsset.userData.modelName, + assetId: duplicatedAsset.userData.assetId, + position: asset.position, + rotation: { x: asset.rotation[0], y: asset.rotation[1], z: asset.rotation[2] }, isLocked: false, isVisible: true, }; let updatedEventData = null; - if (obj.userData.eventData) { - updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData)); + + if (duplicatedAsset.userData.eventData) { + updatedEventData = JSON.parse(JSON.stringify(duplicatedAsset.userData.eventData)); updatedEventData.modelUuid = newFloorItem.modelUuid; const eventData: any = { - type: obj.userData.eventData.type, + type: duplicatedAsset.userData.eventData.type, }; - if (obj.userData.eventData.type === "Conveyor") { + if (duplicatedAsset.userData.eventData.type === "Conveyor") { const ConveyorEvent: ConveyorEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -186,7 +257,7 @@ const DuplicationControls3D = ({ rotation: point.rotation })); - } else if (obj.userData.eventData.type === "Vehicle") { + } else if (duplicatedAsset.userData.eventData.type === "Vehicle") { const vehicleEvent: VehicleEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -224,7 +295,7 @@ const DuplicationControls3D = ({ rotation: vehicleEvent.point.rotation }; - } else if (obj.userData.eventData.type === "ArmBot") { + } else if (duplicatedAsset.userData.eventData.type === "ArmBot") { const roboticArmEvent: RoboticArmEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -258,7 +329,7 @@ const DuplicationControls3D = ({ rotation: roboticArmEvent.point.rotation }; - } else if (obj.userData.eventData.type === "StaticMachine") { + } else if (duplicatedAsset.userData.eventData.type === "StaticMachine") { const machineEvent: MachineEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -286,7 +357,7 @@ const DuplicationControls3D = ({ position: machineEvent.point.position, rotation: machineEvent.point.rotation }; - } else if (obj.userData.eventData.type === "Storage") { + } else if (duplicatedAsset.userData.eventData.type === "Storage") { const storageEvent: StorageEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -313,7 +384,7 @@ const DuplicationControls3D = ({ position: storageEvent.point.position, rotation: storageEvent.point.rotation }; - } else if (obj.userData.eventData.type === "Human") { + } else if (duplicatedAsset.userData.eventData.type === "Human") { const humanEvent: HumanEventSchema = { modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, @@ -353,11 +424,11 @@ const DuplicationControls3D = ({ // await setAssetsApi( // organization, - // obj.uuid, - // obj.userData.name, + // pastedAsset.uuid, + // pastedAsset.userData.name, // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, - // obj.userData.modelId, + // { "x": pastedAsset.rotation.x, "y": pastedAsset.rotation.y, "z": pastedAsset.rotation.z }, + // pastedAsset.userData.modelId, // false, // true, // ); @@ -370,17 +441,16 @@ const DuplicationControls3D = ({ modelName: newFloorItem.modelName, assetId: newFloorItem.assetId, position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + rotation: { x: duplicatedAsset.rotation.x, y: duplicatedAsset.rotation.y, z: duplicatedAsset.rotation.z }, isLocked: false, isVisible: true, socketId: socket.id, eventData: eventData, versionId: selectedVersion?.versionId || '', - projectId, - userId + userId, + projectId }; - // console.log('data: ', data); socket.emit("v1:model-asset:add", data); const asset: Asset = { @@ -394,43 +464,25 @@ const DuplicationControls3D = ({ isVisible: data.isVisible, opacity: 1, eventData: data.eventData - } - - addAsset(asset); + }; + updateAsset(asset.modelUuid, asset); } else { - - //REST - - // await setAssetsApi( - // organization, - // obj.uuid, - // obj.userData.name, - // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, - // obj.userData.modelId, - // false, - // true, - // ); - - //SOCKET - const data = { organization, modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, assetId: newFloorItem.assetId, position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + rotation: { x: duplicatedAsset.rotation.x, y: duplicatedAsset.rotation.y, z: duplicatedAsset.rotation.z }, isLocked: false, isVisible: true, socketId: socket.id, versionId: selectedVersion?.versionId || '', - userId, - projectId + projectId, + userId }; - // console.log('data: ', data);/ socket.emit("v1:model-asset:add", data); const asset: Asset = { @@ -443,27 +495,26 @@ const DuplicationControls3D = ({ isCollidable: false, isVisible: data.isVisible, opacity: 1, - } + }; - addAsset(asset); + updateAsset(asset.modelUuid, asset); } } }); echo.success("Object duplicated!"); clearSelection(); - } + }; const clearSelection = () => { - selectionGroup.current.children = []; - selectionGroup.current.position.set(0, 0, 0); - selectionGroup.current.rotation.set(0, 0, 0); setMovedObjects([]); setpastedObjects([]); setDuplicatedObjects([]); setRotatedObjects([]); setSelectedAssets([]); - } + setIsDuplicating(false); + setDragOffset(null); + }; return null; }; diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx index 6658f62..d6732b3 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useFrame, useThree } from "@react-three/fiber"; import { useSelectedAssets, useSocketStore, useToggleView, } from "../../../../../store/builder/store"; import * as Types from "../../../../../types/world/worldTypes"; @@ -22,7 +22,6 @@ function MoveControls3D({ setpastedObjects, duplicatedObjects, setDuplicatedObjects, - selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef, @@ -39,11 +38,19 @@ function MoveControls3D({ const { userId, organization } = getUserData(); const { projectId } = useParams(); const { assetStore, eventStore, productStore } = useSceneContext(); - const { updateAsset } = assetStore(); - const AssetGroup = useRef(undefined); + const { updateAsset, setPosition, getAssetById } = assetStore(); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); + const [dragOffset, setDragOffset] = useState(null); + const [initialPositions, setInitialPositions] = useState>({}); + const [initialStates, setInitialStates] = useState>({}); + const [isMoving, setIsMoving] = useState(false); + const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ + left: false, + right: false, + }); + const updateBackend = ( productName: string, productUuid: string, @@ -65,22 +72,10 @@ function MoveControls3D({ const canvasElement = gl.domElement; canvasElement.tabIndex = 0; - const itemsGroup: any = scene.getObjectByName("Asset Group"); - AssetGroup.current = itemsGroup; - - if (!AssetGroup.current) { - console.error("Asset Group not found in the scene."); - return; - } - - let isMoving = false; - - const onPointerDown = () => { - isMoving = false; - }; + let isPointerMoving = false; const onPointerMove = () => { - isMoving = true; + isPointerMoving = true; }; const onKeyUp = (event: KeyboardEvent) => { @@ -91,21 +86,25 @@ function MoveControls3D({ } }; + const onPointerDown = (event: PointerEvent) => { + isPointerMoving = false; + + if (event.button === 0) mouseButtonsDown.current.left = true; + if (event.button === 2) mouseButtonsDown.current.right = true; + }; + const onPointerUp = (event: PointerEvent) => { - if (!isMoving && movedObjects.length > 0 && event.button === 0) { + if (event.button === 0) mouseButtonsDown.current.left = false; + if (event.button === 2) mouseButtonsDown.current.right = false; + + if (!isPointerMoving && movedObjects.length > 0 && event.button === 0) { event.preventDefault(); placeMovedAssets(); } - if (!isMoving && movedObjects.length > 0 && event.button === 2) { + if (!isPointerMoving && movedObjects.length > 0 && event.button === 2) { event.preventDefault(); - + resetToInitialPositions(); clearSelection(); - movedObjects.forEach((asset: any) => { - if (AssetGroup.current) { - AssetGroup.current.attach(asset); - } - }); - setMovedObjects([]); } setKeyEvent(""); @@ -131,14 +130,8 @@ function MoveControls3D({ if (keyCombination === "ESCAPE") { event.preventDefault(); - + resetToInitialPositions(); clearSelection(); - movedObjects.forEach((asset: any) => { - if (AssetGroup.current) { - AssetGroup.current.attach(asset); - } - }); - setMovedObjects([]); } }; @@ -158,118 +151,154 @@ function MoveControls3D({ canvasElement.removeEventListener("keydown", onKeyDown); canvasElement?.removeEventListener("keyup", onKeyUp); }; - }, [camera, controls, scene, toggleView, selectedAssets, socket, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, keyEvent,]); + }, [camera, controls, scene, toggleView, selectedAssets, socket, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, keyEvent]); - let moveSpeed = keyEvent === "Ctrl" || "Ctrl+Shift" ? 1 : 0.25; + const calculateDragOffset = useCallback((point: THREE.Object3D, hitPoint: THREE.Vector3) => { + const pointPosition = new THREE.Vector3().copy(point.position); + return new THREE.Vector3().subVectors(pointPosition, hitPoint); + }, []); + + const resetToInitialPositions = useCallback(() => { + setTimeout(() => { + movedObjects.forEach((movedObject: THREE.Object3D) => { + if (movedObject.userData.modelUuid && initialStates[movedObject.uuid]) { + const initialState = initialStates[movedObject.uuid]; + const positionArray: [number, number, number] = [ + initialState.position.x, + initialState.position.y, + initialState.position.z + ]; + + updateAsset(movedObject.userData.modelUuid, { + position: positionArray, + rotation: [ + initialState.rotation?.x || 0, + initialState.rotation?.y || 0, + initialState.rotation?.z || 0 + ], + }); + + movedObject.position.copy(initialState.position); + if (initialState.rotation) { + movedObject.rotation.copy(initialState.rotation); + } + } + }); + }, 0) + }, [movedObjects, initialStates, updateAsset]); useFrame(() => { - if (movedObjects.length > 0) { - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - let point = raycaster.ray.intersectPlane(plane, intersectionPoint); - const floorsGroup = scene.getObjectByName("Floors-Group") as Types.Group | null; - const floorChildren = floorsGroup?.children ?? []; - const floorIntersections = raycaster.intersectObjects([...floorChildren], true); - const intersectedFloor = floorIntersections.find((intersect) => intersect.object.name.includes("Floor")); + if (!isMoving || movedObjects.length === 0) return; - if (intersectedFloor && selectedAssets.length === 1) { - if (intersectedFloor.object.userData.floorUuid) { - point = new THREE.Vector3(intersectedFloor.point.x, intersectedFloor.object.userData.floorDepth, intersectedFloor.point.z); + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const hit = raycaster.ray.intersectPlane(plane, intersectionPoint); + + if (hit) { + if (mouseButtonsDown.current.left || mouseButtonsDown.current.right) { + if (movedObjects[0]) { + const newOffset = calculateDragOffset(movedObjects[0], intersectionPoint); + setDragOffset(newOffset); } + return; } - if (point) { - let targetX = point.x; - let targetY = point.y; - let targetZ = point.z; + if (dragOffset) { + const baseNewPosition = new THREE.Vector3().addVectors(intersectionPoint, dragOffset); + + let moveSpeed = keyEvent === "Shift" || "Ctrl+Shift" ? 0.25 : 1; if (keyEvent === "Ctrl") { - targetX = snapControls(targetX, "Ctrl"); - targetZ = snapControls(targetZ, "Ctrl"); + baseNewPosition.x = snapControls(baseNewPosition.x, "Ctrl"); + baseNewPosition.z = snapControls(baseNewPosition.z, "Ctrl"); } - // else if (keyEvent === "Ctrl+Shift") { - // targetX = snapControls(targetX, "Ctrl+Shift"); - // targetZ = snapControls(targetZ, "Ctrl+Shift"); - // } else if (keyEvent === "Shift") { - // targetX = snapControls(targetX, "Shift"); - // targetZ = snapControls(targetZ, "Shift"); - // } else { - // } + movedObjects.forEach((movedAsset: THREE.Object3D) => { + if (movedAsset.userData.modelUuid) { + const initialPosition = initialPositions[movedAsset.userData.modelUuid]; + + if (initialPosition) { + const relativeOffset = new THREE.Vector3().subVectors( + initialPosition, + initialPositions[movedObjects[0].uuid] + ); + + const newPosition = new THREE.Vector3().addVectors(baseNewPosition, relativeOffset); + const positionArray: [number, number, number] = [newPosition.x, newPosition.y, newPosition.z]; + + setPosition(movedAsset.userData.modelUuid, positionArray); + } + } + }); const position = new THREE.Vector3(); - if (boundingBoxRef.current) { boundingBoxRef.current.getWorldPosition(position); - selectionGroup.current.position.lerp( - new THREE.Vector3( - targetX - (position.x - selectionGroup.current.position.x), - targetY - (position.y - selectionGroup.current.position.y), - targetZ - (position.z - selectionGroup.current.position.z) - ), - moveSpeed - ); } else { const box = new THREE.Box3(); - movedObjects.forEach((obj: THREE.Object3D) => - box.expandByObject(obj) - ); + movedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj)); const center = new THREE.Vector3(); box.getCenter(center); - - selectionGroup.current.position.lerp( - new THREE.Vector3( - targetX - (center.x - selectionGroup.current.position.x), - selectionGroup.current.position.y, - targetZ - (center.z - selectionGroup.current.position.z) - ), - moveSpeed - ); } } } }); const moveAssets = () => { - setMovedObjects(selectedAssets); - selectedAssets.forEach((asset: any) => { - selectionGroup.current.attach(asset); + const states: Record = {}; + const positions: Record = {}; + + selectedAssets.forEach((asset: THREE.Object3D) => { + states[asset.uuid] = { + position: new THREE.Vector3().copy(asset.position), + rotation: asset.rotation ? new THREE.Euler().copy(asset.rotation) : undefined + }; + positions[asset.uuid] = new THREE.Vector3().copy(asset.position); }); + + setInitialStates(states); + setInitialPositions(positions); + + raycaster.setFromCamera(pointer, camera); + const intersectionPoint = new THREE.Vector3(); + const hit = raycaster.ray.intersectPlane(plane, intersectionPoint); + + if (hit && selectedAssets[0]) { + const offset = calculateDragOffset(selectedAssets[0], hit); + setDragOffset(offset); + } + + setMovedObjects(selectedAssets); + setIsMoving(true); }; const placeMovedAssets = () => { if (movedObjects.length === 0) return; - movedObjects.forEach(async (obj: THREE.Object3D) => { - if (obj && AssetGroup.current) { - let worldPosition = new THREE.Vector3(); - obj.getWorldPosition(worldPosition); - - if (worldPosition.y < 0) { - worldPosition.y = 0; - } - - selectionGroup.current.remove(obj); - obj.position.copy(worldPosition); + movedObjects.forEach(async (movedAsset: THREE.Object3D) => { + if (movedAsset) { + const assetUuid = movedAsset.userData.modelUuid; + const asset = getAssetById(assetUuid); + if (!asset) return; const newFloorItem: Types.FloorItemType = { - modelUuid: obj.userData.modelUuid, - modelName: obj.userData.modelName, - assetId: obj.userData.assetId, - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + modelUuid: movedAsset.userData.modelUuid, + modelName: movedAsset.userData.modelName, + assetId: movedAsset.userData.assetId, + position: asset.position, + rotation: { x: movedAsset.rotation.x, y: movedAsset.rotation.y, z: movedAsset.rotation.z }, isLocked: false, isVisible: true, }; - if (obj.userData.eventData) { - const eventData = eventStore.getState().getEventByModelUuid(obj.userData.modelUuid); - const productData = productStore.getState().getEventByModelUuid(selectedProduct.productUuid, obj.userData.modelUuid); + if (movedAsset.userData.eventData) { + const eventData = eventStore.getState().getEventByModelUuid(movedAsset.userData.modelUuid); + const productData = productStore.getState().getEventByModelUuid(selectedProduct.productUuid, movedAsset.userData.modelUuid); if (eventData) { - eventStore.getState().updateEvent(obj.userData.modelUuid, { - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], + eventStore.getState().updateEvent(movedAsset.userData.modelUuid, { + position: asset.position, + rotation: [movedAsset.rotation.x, movedAsset.rotation.y, movedAsset.rotation.z], }); } @@ -278,10 +307,10 @@ function MoveControls3D({ .getState() .updateEvent( selectedProduct.productUuid, - obj.userData.modelUuid, + movedAsset.userData.modelUuid, { - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], + position: asset.position, + rotation: [movedAsset.rotation.x, movedAsset.rotation.y, movedAsset.rotation.z], } ); @@ -298,9 +327,9 @@ function MoveControls3D({ } } - updateAsset(obj.userData.modelUuid, { - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], + updateAsset(movedAsset.userData.modelUuid, { + position: asset.position, + rotation: [movedAsset.rotation.x, movedAsset.rotation.y, movedAsset.rotation.z], }); //REST @@ -324,7 +353,7 @@ function MoveControls3D({ modelName: newFloorItem.modelName, assetId: newFloorItem.assetId, position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + rotation: { x: movedAsset.rotation.x, y: movedAsset.rotation.y, z: movedAsset.rotation.z }, isLocked: false, isVisible: true, socketId: socket.id, @@ -333,22 +362,16 @@ function MoveControls3D({ userId }; - // console.log('data: ', data); socket.emit("v1:model-asset:add", data); - - AssetGroup.current.add(obj); } }); echo.success("Object moved!"); - + setIsMoving(false); clearSelection(); }; const clearSelection = () => { - selectionGroup.current.children = []; - selectionGroup.current.position.set(0, 0, 0); - selectionGroup.current.rotation.set(0, 0, 0); setpastedObjects([]); setDuplicatedObjects([]); setMovedObjects([]); @@ -365,4 +388,4 @@ function MoveControls3D({ ); } -export default MoveControls3D; +export default MoveControls3D; \ No newline at end of file diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx index fdde56a..f31bc9a 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx @@ -1,5 +1,5 @@ import * as THREE from "three"; -import { useEffect, useMemo, useRef } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useFrame, useThree } from "@react-three/fiber"; import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../../store/builder/store"; import * as Types from "../../../../../types/world/worldTypes"; @@ -20,11 +20,9 @@ function RotateControls3D({ pastedObjects, setpastedObjects, duplicatedObjects, - setDuplicatedObjects, - selectionGroup + setDuplicatedObjects }: any) { - - const { camera, controls, gl, scene, pointer, raycaster } = useThree(); + const { camera, gl, scene, pointer, raycaster } = useThree(); const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); const { toggleView } = useToggleView(); @@ -36,26 +34,33 @@ function RotateControls3D({ const { projectId } = useParams(); const { assetStore, eventStore, productStore } = useSceneContext(); const { updateAsset } = assetStore(); - const AssetGroup = useRef(undefined); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); - const updateBackend = ( + const [initialRotations, setInitialRotations] = useState>({}); + const [initialPositions, setInitialPositions] = useState>({}); + const [isRotating, setIsRotating] = useState(false); + const prevPointerPosition = useRef(null); + const rotationCenter = useRef(null); + const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ + left: false, + right: false, + }); + + const updateBackend = useCallback(( productName: string, productUuid: string, projectId: string, eventData: EventsSchema ) => { upsertProductOrEventApi({ - productName: productName, - productUuid: productUuid, - projectId: projectId, + productName, + productUuid, + projectId, eventDatas: eventData, versionId: selectedVersion?.versionId || '', - }) - } - - const prevPointerPosition = useRef(null); + }); + }, [selectedVersion]); useEffect(() => { if (!camera || !scene || toggleView) return; @@ -63,45 +68,37 @@ function RotateControls3D({ const canvasElement = gl.domElement; canvasElement.tabIndex = 0; - const itemsGroup: any = scene.getObjectByName("Asset Group"); - AssetGroup.current = itemsGroup; - - if (!AssetGroup.current) { - console.error("Asset Group not found in the scene."); - return; - } - - let isMoving = false; - - const onPointerDown = () => { - isMoving = false; - }; + let isPointerMoving = false; const onPointerMove = () => { - isMoving = true; + isPointerMoving = true; + }; + + const onPointerDown = (event: PointerEvent) => { + isPointerMoving = false; + if (event.button === 0) mouseButtonsDown.current.left = true; + if (event.button === 2) mouseButtonsDown.current.right = true; }; const onPointerUp = (event: PointerEvent) => { - if (!isMoving && rotatedObjects.length > 0 && event.button === 0) { + if (event.button === 0) mouseButtonsDown.current.left = false; + if (event.button === 2) mouseButtonsDown.current.right = false; + + if (!isPointerMoving && rotatedObjects.length > 0 && event.button === 0) { event.preventDefault(); placeRotatedAssets(); } - if (!isMoving && rotatedObjects.length > 0 && event.button === 2) { + if (!isPointerMoving && rotatedObjects.length > 0 && event.button === 2) { event.preventDefault(); - + resetToInitialRotations(); clearSelection(); - rotatedObjects.forEach((asset: any) => { - if (AssetGroup.current) { - AssetGroup.current.attach(asset); - } - }); - setRotatedObjects([]); } }; const onKeyDown = (event: KeyboardEvent) => { if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || movedObjects.length > 0) return; + if (event.key.toLowerCase() === "r") { if (selectedAssets.length > 0) { rotateAssets(); @@ -109,15 +106,8 @@ function RotateControls3D({ } if (event.key.toLowerCase() === "escape") { event.preventDefault(); - + resetToInitialRotations(); clearSelection(); - rotatedObjects.forEach((asset: any) => { - if (AssetGroup.current) { - AssetGroup.current.attach(asset); - } - }); - - setRotatedObjects([]); } }; @@ -135,41 +125,85 @@ function RotateControls3D({ canvasElement.removeEventListener("pointerup", onPointerUp); canvasElement.removeEventListener("keydown", onKeyDown); }; - }, [camera, controls, scene, toggleView, selectedAssets, socket, pastedObjects, duplicatedObjects, rotatedObjects, movedObjects]); + }, [camera, scene, toggleView, selectedAssets, rotatedObjects, pastedObjects, duplicatedObjects, movedObjects]); + + const resetToInitialRotations = useCallback(() => { + rotatedObjects.forEach((obj: THREE.Object3D) => { + const uuid = obj.uuid; + if (obj.userData.modelUuid) { + const initialRotation = initialRotations[uuid]; + const initialPosition = initialPositions[uuid]; + + if (initialRotation && initialPosition) { + const rotationArray: [number, number, number] = [initialRotation.x, initialRotation.y, initialRotation.z,]; + const positionArray: [number, number, number] = [initialPosition.x, initialPosition.y, initialPosition.z,]; + + updateAsset(obj.userData.modelUuid, { + rotation: rotationArray, + position: positionArray, + }); + + obj.rotation.copy(initialRotation); + obj.position.copy(initialPosition); + } + } + }); + }, [rotatedObjects, initialRotations, initialPositions, updateAsset]); useFrame(() => { - if (rotatedObjects.length > 0) { - const intersectionPoint = new THREE.Vector3(); - raycaster.setFromCamera(pointer, camera); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + if (!isRotating || rotatedObjects.length === 0) return; - if (point && prevPointerPosition.current) { - const box = new THREE.Box3(); - rotatedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj)); - const center = new THREE.Vector3(); - box.getCenter(center); - - const delta = new THREE.Vector3().subVectors(point, center); - const prevPointerPosition3D = new THREE.Vector3(prevPointerPosition.current.x, 0, prevPointerPosition.current.y); - - const angle = Math.atan2(delta.z, delta.x) - Math.atan2(prevPointerPosition3D.z - center.z, prevPointerPosition3D.x - center.x); - - selectionGroup.current.rotation.y += -angle; - - selectionGroup.current.position.sub(center); - selectionGroup.current.position.applyAxisAngle(new THREE.Vector3(0, 1, 0), -angle); - selectionGroup.current.position.add(center); + const intersectionPoint = new THREE.Vector3(); + raycaster.setFromCamera(pointer, camera); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + if (mouseButtonsDown.current.left || mouseButtonsDown.current.right) { + if (point) { prevPointerPosition.current = new THREE.Vector2(point.x, point.z); } + return; + } + + if (point && prevPointerPosition.current && rotationCenter.current) { + const center = rotationCenter.current; + + const currentAngle = Math.atan2(point.z - center.z, point.x - center.x); + const prevAngle = Math.atan2( + prevPointerPosition.current.y - center.z, + prevPointerPosition.current.x - center.x + ); + const angleDelta = prevAngle - currentAngle; + + rotatedObjects.forEach((obj: THREE.Object3D) => { + if (obj.userData.modelUuid) { + const relativePos = new THREE.Vector3().subVectors(obj.position, center); + relativePos.applyAxisAngle(new THREE.Vector3(0, 1, 0), angleDelta); + obj.position.copy(center).add(relativePos); + obj.rotation.y += angleDelta; + } + }); + + prevPointerPosition.current = new THREE.Vector2(point.x, point.z); } }); - const rotateAssets = () => { + const rotateAssets = useCallback(() => { + const rotations: Record = {}; + const positions: Record = {}; + const box = new THREE.Box3(); - selectedAssets.forEach((asset: any) => box.expandByObject(asset)); + selectedAssets.forEach((obj: THREE.Object3D) => box.expandByObject(obj)); const center = new THREE.Vector3(); box.getCenter(center); + rotationCenter.current = center; + + selectedAssets.forEach((obj: THREE.Object3D) => { + rotations[obj.uuid] = new THREE.Euler().copy(obj.rotation); + positions[obj.uuid] = new THREE.Vector3().copy(obj.position); + }); + + setInitialRotations(rotations); + setInitialPositions(positions); const intersectionPoint = new THREE.Vector3(); raycaster.setFromCamera(pointer, camera); @@ -179,56 +213,54 @@ function RotateControls3D({ prevPointerPosition.current = new THREE.Vector2(point.x, point.z); } - selectedAssets.forEach((asset: any) => { - selectionGroup.current.attach(asset); - }); - setRotatedObjects(selectedAssets); - }; + setIsRotating(true); + }, [selectedAssets, camera, pointer, raycaster, plane]); - const placeRotatedAssets = () => { + const placeRotatedAssets = useCallback(() => { if (rotatedObjects.length === 0) return; - rotatedObjects.forEach(async (obj: THREE.Object3D) => { - if (obj && AssetGroup.current) { - const worldPosition = new THREE.Vector3(); - const worldQuaternion = new THREE.Quaternion(); + rotatedObjects.forEach((obj: THREE.Object3D) => { + if (obj && obj.userData.modelUuid) { + const rotationArray: [number, number, number] = [obj.rotation.x, obj.rotation.y, obj.rotation.z]; - obj.getWorldPosition(worldPosition); - obj.getWorldQuaternion(worldQuaternion); - - selectionGroup.current.remove(obj); - - obj.position.copy(worldPosition); - obj.quaternion.copy(worldQuaternion); + const positionArray: [number, number, number] = [obj.position.x, obj.position.y, obj.position.z]; const newFloorItem: Types.FloorItemType = { modelUuid: obj.userData.modelUuid, modelName: obj.userData.modelName, assetId: obj.userData.assetId, - position: [worldPosition.x, worldPosition.y, worldPosition.z], + position: positionArray, rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, isLocked: false, - isVisible: true + isVisible: true, }; if (obj.userData.eventData) { const eventData = eventStore.getState().getEventByModelUuid(obj.userData.modelUuid); - const productData = productStore.getState().getEventByModelUuid(selectedProductStore.getState().selectedProduct.productUuid, obj.userData.modelUuid); + const productData = productStore.getState().getEventByModelUuid( + selectedProduct.productUuid, + obj.userData.modelUuid + ); if (eventData) { eventStore.getState().updateEvent(obj.userData.modelUuid, { - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], - }) + position: positionArray, + rotation: rotationArray, + }); } - if (productData) { - const event = productStore.getState().updateEvent(selectedProductStore.getState().selectedProduct.productUuid, obj.userData.modelUuid, { - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], - }) - if (event && organization) { + if (productData) { + const event = productStore.getState().updateEvent( + selectedProduct.productUuid, + obj.userData.modelUuid, + { + position: positionArray, + rotation: rotationArray, + } + ); + + if (event) { updateBackend( selectedProduct.productName, selectedProduct.productUuid, @@ -242,8 +274,8 @@ function RotateControls3D({ } updateAsset(obj.userData.modelUuid, { - position: [worldPosition.x, worldPosition.y, worldPosition.z], - rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], + position: positionArray, + rotation: rotationArray, }); //REST @@ -267,7 +299,11 @@ function RotateControls3D({ modelName: newFloorItem.modelName, assetId: newFloorItem.assetId, position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + rotation: { + x: obj.rotation.x, + y: obj.rotation.y, + z: obj.rotation.z + }, isLocked: false, isVisible: true, socketId: socket.id, @@ -276,29 +312,23 @@ function RotateControls3D({ userId }; - // console.log('data: ', data); socket.emit("v1:model-asset:add", data); - - AssetGroup.current.add(obj); } }); - echo.success("Object rotated!"); + setIsRotating(false); clearSelection(); - } + }, [rotatedObjects, eventStore, productStore, selectedProduct, updateBackend, projectId, updateAsset, organization, socket, selectedVersion, userId]); const clearSelection = () => { - selectionGroup.current.children = []; - selectionGroup.current.position.set(0, 0, 0); - selectionGroup.current.rotation.set(0, 0, 0); setpastedObjects([]); setDuplicatedObjects([]); setMovedObjects([]); setRotatedObjects([]); setSelectedAssets([]); - } + }; return null; } -export default RotateControls3D \ No newline at end of file +export default RotateControls3D; \ No newline at end of file diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx index 080a5d8..eb8bdae 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx @@ -1,9 +1,8 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import * as THREE from "three"; -import { useFrame, useThree } from "@react-three/fiber"; +import { useThree } from "@react-three/fiber"; import { SelectionHelper } from "../selectionHelper"; import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox"; -import * as Types from "../../../../../types/world/worldTypes"; import useModuleStore from "../../../../../store/useModuleStore"; import { useParams } from "react-router-dom"; @@ -13,7 +12,6 @@ import { useVersionContext } from "../../../../builder/version/versionContext"; import { useProductContext } from "../../../../simulation/products/productContext"; import { useSelectedAssets, useSocketStore, useToggleView, useToolMode, } from "../../../../../store/builder/store"; import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi"; -import BoundingBox from "./boundingBoxHelper3D"; import DuplicationControls3D from "./duplicationControls3D"; import CopyPasteControls3D from "./copyPasteControls3D"; import MoveControls3D from "./moveControls3D"; @@ -23,7 +21,6 @@ import RotateControls3D from "./rotateControls3D"; const SelectionControls3D: React.FC = () => { const { camera, controls, gl, scene, raycaster, pointer } = useThree(); - const selectionGroup = useRef() as Types.RefGroup; const { toggleView } = useToggleView(); const { selectedAssets, setSelectedAssets } = useSelectedAssets(); const [movedObjects, setMovedObjects] = useState([]); @@ -229,12 +226,6 @@ const SelectionControls3D: React.FC = () => { } }, [activeModule, toolMode, toggleView]); - useFrame(() => { - if (pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) { - selectionGroup.current.position.set(0, 0, 0); - } - }); - const selectAssets = useCallback(() => { selectionBox.endPoint.set(pointer.x, pointer.y, 0); if (controls) (controls as any).enabled = true; @@ -267,9 +258,6 @@ const SelectionControls3D: React.FC = () => { }, [selectionBox, pointer, controls, selectedAssets, setSelectedAssets]); const clearSelection = () => { - selectionGroup.current.children = []; - selectionGroup.current.position.set(0, 0, 0); - selectionGroup.current.rotation.set(0, 0, 0); setpastedObjects([]); setDuplicatedObjects([]); setSelectedAssets([]); @@ -345,19 +333,13 @@ const SelectionControls3D: React.FC = () => { return ( <> - - - - - + - + - + - - - + ); }; From 5ae8d8e27344576ae6570841aec445ff5b0141a9 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Fri, 18 Jul 2025 15:11:57 +0530 Subject: [PATCH 2/5] move speed control --- .../selection3D/moveControls3D.tsx | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx index d6732b3..d74c2da 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx @@ -116,10 +116,12 @@ function MoveControls3D({ if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0) return; - if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") { - setKeyEvent(keyCombination); - } else { - setKeyEvent(""); + if (keyCombination !== keyEvent) { + if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") { + setKeyEvent(keyCombination); + } else { + setKeyEvent(""); + } } if (keyCombination === "G") { @@ -204,11 +206,18 @@ function MoveControls3D({ } if (dragOffset) { - const baseNewPosition = new THREE.Vector3().addVectors(intersectionPoint, dragOffset); + const rawBasePosition = new THREE.Vector3().addVectors(intersectionPoint, dragOffset); - let moveSpeed = keyEvent === "Shift" || "Ctrl+Shift" ? 0.25 : 1; + let moveSpeed = keyEvent.includes("Shift") ? 0.25 : 1; - if (keyEvent === "Ctrl") { + const initialBasePosition = initialPositions[movedObjects[0].uuid]; + const positionDifference = new THREE.Vector3().subVectors(rawBasePosition, initialBasePosition); + + const adjustedDifference = positionDifference.multiplyScalar(moveSpeed); + + const baseNewPosition = new THREE.Vector3().addVectors(initialBasePosition, adjustedDifference); + + if (keyEvent.includes("Ctrl")) { baseNewPosition.x = snapControls(baseNewPosition.x, "Ctrl"); baseNewPosition.z = snapControls(baseNewPosition.z, "Ctrl"); } From c9dc6c864233d3a5c6fa54d25f52cdc6e0120dc0 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Fri, 18 Jul 2025 15:25:22 +0530 Subject: [PATCH 3/5] bug fix --- .../selection3D/copyPasteControls3D.tsx | 23 ++++++---------- .../selection3D/duplicationControls3D.tsx | 23 ++++++---------- .../selection3D/moveControls3D.tsx | 21 +++++---------- .../selection3D/rotateControls3D.tsx | 27 +++++-------------- 4 files changed, 29 insertions(+), 65 deletions(-) diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx index 8593758..0d7cf7e 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx @@ -10,6 +10,8 @@ import { getUserData } from "../../../../../functions/getUserData"; import { useSceneContext } from "../../../sceneContext"; import { useVersionContext } from "../../../../builder/version/versionContext"; +// import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi"; + const CopyPasteControls3D = ({ copiedObjects, setCopiedObjects, @@ -419,21 +421,6 @@ const CopyPasteControls3D = ({ newFloorItem.eventData = eventData; - //REST - - // await setAssetsApi( - // organization, - // pastedAsset.uuid, - // pastedAsset.userData.name, - // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": pastedAsset.rotation.x, "y": pastedAsset.rotation.y, "z": pastedAsset.rotation.z }, - // pastedAsset.userData.modelId, - // false, - // true, - // ); - - //SOCKET - const data = { organization, modelUuid: newFloorItem.modelUuid, @@ -450,6 +437,12 @@ const CopyPasteControls3D = ({ projectId }; + //REST + + // await setAssetsApi(data); + + //SOCKET + socket.emit("v1:model-asset:add", data); const asset: Asset = { diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx index 4f08cc7..f4f5048 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx @@ -10,6 +10,8 @@ import { getUserData } from "../../../../../functions/getUserData"; import { useSceneContext } from "../../../sceneContext"; import { useVersionContext } from "../../../../builder/version/versionContext"; +// import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi"; + const DuplicationControls3D = ({ duplicatedObjects, setDuplicatedObjects, @@ -420,21 +422,6 @@ const DuplicationControls3D = ({ newFloorItem.eventData = eventData; - //REST - - // await setAssetsApi( - // organization, - // pastedAsset.uuid, - // pastedAsset.userData.name, - // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": pastedAsset.rotation.x, "y": pastedAsset.rotation.y, "z": pastedAsset.rotation.z }, - // pastedAsset.userData.modelId, - // false, - // true, - // ); - - //SOCKET - const data = { organization, modelUuid: newFloorItem.modelUuid, @@ -451,6 +438,12 @@ const DuplicationControls3D = ({ projectId }; + //REST + + // await setAssetsApi(data); + + //SOCKET + socket.emit("v1:model-asset:add", data); const asset: Asset = { diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx index d74c2da..e58cc44 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx @@ -341,21 +341,6 @@ function MoveControls3D({ rotation: [movedAsset.rotation.x, movedAsset.rotation.y, movedAsset.rotation.z], }); - //REST - - // await setAssetsApi( - // organization, - // obj.uuid, - // obj.userData.name, - // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, - // obj.userData.modelId, - // false, - // true, - // ); - - //SOCKET - const data = { organization, modelUuid: newFloorItem.modelUuid, @@ -371,6 +356,12 @@ function MoveControls3D({ userId }; + //REST + + // await setAssetsApi(data); + + //SOCKET + socket.emit("v1:model-asset:add", data); } }); diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx index f31bc9a..83266fd 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx @@ -278,32 +278,13 @@ function RotateControls3D({ rotation: rotationArray, }); - //REST - - // await setAssetsApi( - // organization, - // obj.uuid, - // obj.userData.name, - // [worldPosition.x, worldPosition.y, worldPosition.z], - // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z }, - // obj.userData.modelId, - // false, - // true, - // ); - - //SOCKET - const data = { organization, modelUuid: newFloorItem.modelUuid, modelName: newFloorItem.modelName, assetId: newFloorItem.assetId, position: newFloorItem.position, - rotation: { - x: obj.rotation.x, - y: obj.rotation.y, - z: obj.rotation.z - }, + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, isLocked: false, isVisible: true, socketId: socket.id, @@ -312,6 +293,12 @@ function RotateControls3D({ userId }; + //REST + + // await setAssetsApi(data); + + //SOCKET + socket.emit("v1:model-asset:add", data); } }); From ccf64e0f970d257ba6218c5ab036b0aad7625951 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Fri, 18 Jul 2025 17:10:40 +0530 Subject: [PATCH 4/5] bug fix --- .../builder/asset/functions/assetBoundingBox.tsx | 13 +++++++++---- .../Instances/Instances/wallAssetInstance.tsx | 6 +++--- .../selection3D/moveControls3D.tsx | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/app/src/modules/builder/asset/functions/assetBoundingBox.tsx b/app/src/modules/builder/asset/functions/assetBoundingBox.tsx index b26485d..5923321 100644 --- a/app/src/modules/builder/asset/functions/assetBoundingBox.tsx +++ b/app/src/modules/builder/asset/functions/assetBoundingBox.tsx @@ -2,13 +2,14 @@ import { Line } from "@react-three/drei"; import { Box3, Vector3 } from "three"; import { useMemo } from "react"; -export const AssetBoundingBox = ({ name, boundingBox, color, lineWidth, }: { name: string; boundingBox: Box3 | null; color: string; lineWidth: number; }) => { - const { points } = useMemo(() => { - if (!boundingBox) return { points: [], center: new Vector3() }; +export const AssetBoundingBox = ({ name, boundingBox, color, lineWidth }: { name: string; boundingBox: Box3 | null; color: string; lineWidth: number; }) => { + const { points, size, center } = useMemo(() => { + if (!boundingBox) { return { points: [], center: new Vector3(), size: new Vector3(), }; } const min = boundingBox.min; const max = boundingBox.max; const center = boundingBox.getCenter(new Vector3()); + const size = boundingBox.getSize(new Vector3()); const edges: Array<[number, number, number]> = [ [min.x, min.y, min.z], [max.x, min.y, min.z], @@ -27,7 +28,7 @@ export const AssetBoundingBox = ({ name, boundingBox, color, lineWidth, }: { nam [min.x, max.y, min.z], [min.x, max.y, max.z], ]; - return { points: edges, center }; + return { points: edges, center, size }; }, [boundingBox]); if (!boundingBox) return null; @@ -41,6 +42,10 @@ export const AssetBoundingBox = ({ name, boundingBox, color, lineWidth, }: { nam color={color} lineWidth={lineWidth} /> + + + + ); }; diff --git a/app/src/modules/builder/wallAsset/Instances/Instances/wallAssetInstance.tsx b/app/src/modules/builder/wallAsset/Instances/Instances/wallAssetInstance.tsx index 1a674c7..203223d 100644 --- a/app/src/modules/builder/wallAsset/Instances/Instances/wallAssetInstance.tsx +++ b/app/src/modules/builder/wallAsset/Instances/Instances/wallAssetInstance.tsx @@ -242,7 +242,7 @@ function WallAssetInstance({ wallAsset }: { wallAsset: WallAsset }) { visible={wallAsset.isVisible} userData={wallAsset} > - + @@ -265,7 +265,7 @@ function WallAssetInstance({ wallAsset }: { wallAsset: WallAsset }) { e.stopPropagation(); let currentObject = e.object as THREE.Object3D; while (currentObject) { - if (currentObject.name === "Scene") { + if (currentObject.userData.wallUuid) { break; } currentObject = currentObject.parent as THREE.Object3D; @@ -286,7 +286,7 @@ function WallAssetInstance({ wallAsset }: { wallAsset: WallAsset }) { e.stopPropagation(); let currentObject = e.object as THREE.Object3D; while (currentObject) { - if (currentObject.name === "Scene") { + if (currentObject.userData.wallUuid) { break; } currentObject = currentObject.parent as THREE.Object3D; diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx index e58cc44..88b8bf6 100644 --- a/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx +++ b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx @@ -208,7 +208,7 @@ function MoveControls3D({ if (dragOffset) { const rawBasePosition = new THREE.Vector3().addVectors(intersectionPoint, dragOffset); - let moveSpeed = keyEvent.includes("Shift") ? 0.25 : 1; + let moveSpeed = keyEvent.includes("Shift") ? 0.05 : 1; const initialBasePosition = initialPositions[movedObjects[0].uuid]; const positionDifference = new THREE.Vector3().subVectors(rawBasePosition, initialBasePosition); From 88361b1623e9cce1eee199ad6ff646126dfa77fc Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Tue, 22 Jul 2025 10:19:49 +0530 Subject: [PATCH 5/5] human bug fix --- .../actions/conveyor/useConveyorActions.ts | 2 +- .../human/actionHandler/useWorkerHandler.ts | 3 +- .../actionHandler/useRetrieveHandler.ts | 3 +- .../eventManager/useHumanEventManager.ts | 139 +++++++++++------- .../triggerHandler/useTriggerHandler.ts | 31 ++-- .../instances/animator/vehicleAnimator.tsx | 1 - .../instances/instance/vehicleInstance.tsx | 3 +- app/src/store/simulation/useHumanStore.ts | 33 ----- app/src/types/simulationTypes.d.ts | 1 - 9 files changed, 104 insertions(+), 112 deletions(-) diff --git a/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts b/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts index 600fae5..f2dc047 100644 --- a/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts +++ b/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts @@ -37,7 +37,7 @@ export function useConveyorActions() { switch (action.actionType) { case 'default': - handleDefaultAction(action); + handleDefaultAction(action, materialId); break; case 'spawn': handleSpawnAction(action); diff --git a/app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts b/app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts index efefc39..67132e7 100644 --- a/app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts +++ b/app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts @@ -8,7 +8,7 @@ export function useWorkerHandler() { const { getModelUuidByActionUuid } = productStore(); const { selectedProductStore } = useProductContext(); const { selectedProduct } = selectedProductStore(); - const { incrementHumanLoad, incrementLoadCount, addCurrentMaterial, addCurrentAction } = humanStore(); + const { incrementHumanLoad, addCurrentMaterial, addCurrentAction } = humanStore(); const workerLogStatus = (materialUuid: string, status: string) => { echo.info(`${materialUuid}, ${status}`); @@ -24,7 +24,6 @@ export function useWorkerHandler() { if (!modelUuid) return; incrementHumanLoad(modelUuid, 1); - incrementLoadCount(modelUuid, 1); addCurrentAction(modelUuid, action.actionUuid); addCurrentMaterial(modelUuid, material.materialType, material.materialId); diff --git a/app/src/modules/simulation/actions/storageUnit/actionHandler/useRetrieveHandler.ts b/app/src/modules/simulation/actions/storageUnit/actionHandler/useRetrieveHandler.ts index 79d6401..03c7138 100644 --- a/app/src/modules/simulation/actions/storageUnit/actionHandler/useRetrieveHandler.ts +++ b/app/src/modules/simulation/actions/storageUnit/actionHandler/useRetrieveHandler.ts @@ -11,7 +11,7 @@ export function useRetrieveHandler() { const { getModelUuidByActionUuid, getPointUuidByActionUuid, getEventByModelUuid, getActionByUuid } = productStore(); const { getStorageUnitById, getLastMaterial, updateCurrentLoad, removeLastMaterial } = storageUnitStore(); const { getVehicleById, incrementVehicleLoad, addCurrentMaterial } = vehicleStore(); - const { getHumanById, incrementHumanLoad, incrementLoadCount, addCurrentMaterial: addCurrentMaterialToHuman } = humanStore(); + const { getHumanById, incrementHumanLoad, addCurrentMaterial: addCurrentMaterialToHuman } = humanStore(); const { getAssetById, setCurrentAnimation } = assetStore(); const { selectedProduct } = selectedProductStore(); const { getArmBotById, addCurrentAction } = armBotStore(); @@ -316,7 +316,6 @@ export function useRetrieveHandler() { removeLastMaterial(storageUnit.modelUuid); updateCurrentLoad(storageUnit.modelUuid, -1); incrementHumanLoad(human.modelUuid, 1); - incrementLoadCount(human.modelUuid, 1); addCurrentMaterialToHuman(human.modelUuid, material.materialType, material.materialId); retrieveLogStatus(material.materialName, `is picked by ${human.modelName}`); } diff --git a/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts b/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts index 2d2fc11..ac5a478 100644 --- a/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts +++ b/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts @@ -6,16 +6,21 @@ import { useProductContext } from '../../products/productContext'; export function useHumanEventManager() { const { humanStore, productStore, assetStore } = useSceneContext(); - const { getHumanById, clearLoadCount, setCurrentPhase } = humanStore(); + const { getHumanById, setCurrentPhase } = humanStore(); const { getAssetById } = assetStore(); const { getActionByUuid } = productStore(); const { selectedProductStore } = useProductContext(); const { selectedProduct } = selectedProductStore(); - const callbacksRef = useRef void)[]>>(new Map()); - const actionQueueRef = useRef>(new Map()); - const isCooldownRef = useRef>(new Map()); - const isMonitoringRef = useRef(false); + const stateRef = useRef({ + humanStates: new Map void)[], + actionQueue: { actionType: "worker" | "assembly", actionUuid: string, actionName: string }[], + isCooldown: boolean + }>(), + callbackCounts: new Map>(), + isMonitoring: false + }); const { isPlaying } = usePlayButtonStore(); const { isPaused } = usePauseButtonStore(); @@ -23,10 +28,9 @@ export function useHumanEventManager() { useEffect(() => { if (isReset) { - callbacksRef.current.clear(); - actionQueueRef.current.clear(); - isCooldownRef.current.clear(); - isMonitoringRef.current = false; + stateRef.current.humanStates.clear(); + stateRef.current.callbackCounts.clear(); + stateRef.current.isMonitoring = false; } }, [isReset]); @@ -38,34 +42,64 @@ export function useHumanEventManager() { const actionType = action.actionType; if (actionType !== "worker" && actionType !== "assembly") return; - if (!callbacksRef.current.has(humanId)) { - callbacksRef.current.set(humanId, []); - actionQueueRef.current.set(humanId, []); + if (!stateRef.current.callbackCounts.has(humanId)) { + stateRef.current.callbackCounts.set(humanId, new Map()); } - callbacksRef.current.get(humanId)!.push(callback); - actionQueueRef.current.get(humanId)!.push({ actionType, actionUuid }); + const actionCounts = stateRef.current.callbackCounts.get(humanId)!; + if (!actionCounts.has(actionUuid)) { + actionCounts.set(actionUuid, 0); + } - isMonitoringRef.current = true; + const currentCount = actionCounts.get(actionUuid)!; + if (actionType === 'worker' && currentCount >= action.loadCount) { + return; + } + + if (!stateRef.current.humanStates.has(humanId)) { + stateRef.current.humanStates.set(humanId, { + callbacks: [], + actionQueue: [], + isCooldown: false + }); + } + + const humanState = stateRef.current.humanStates.get(humanId)!; + humanState.callbacks.push(callback); + humanState.actionQueue.push({ actionType, actionUuid, actionName: action.actionName }); + + stateRef.current.isMonitoring = true; }; const removeHumanFromMonitor = (humanId: string) => { - callbacksRef.current.delete(humanId); - actionQueueRef.current.delete(humanId); - isCooldownRef.current.delete(humanId); + // stateRef.current.humanStates.delete(humanId); - if (callbacksRef.current.size === 0) { - isMonitoringRef.current = false; + if (stateRef.current.humanStates.size === 0) { + stateRef.current.isMonitoring = false; } }; + const getCallbackCount = (humanId: string, actionUuid: string) => { + if (!stateRef.current.callbackCounts.has(humanId)) return 0; + return stateRef.current.callbackCounts.get(humanId)!.get(actionUuid) || 0; + }; + + const incrementCallbackCount = (humanId: string, actionUuid: string) => { + if (!stateRef.current.callbackCounts.has(humanId)) { + stateRef.current.callbackCounts.set(humanId, new Map()); + } + const actionCounts = stateRef.current.callbackCounts.get(humanId)!; + const currentCount = actionCounts.get(actionUuid) || 0; + actionCounts.set(actionUuid, currentCount + 1); + }; + useFrame(() => { - if (!isMonitoringRef.current || !isPlaying || isPaused) return; + if (!stateRef.current.isMonitoring || !isPlaying || isPaused) return; - callbacksRef.current.forEach((queue, humanId) => { - if (queue.length === 0 || isCooldownRef.current.get(humanId)) return; + stateRef.current.humanStates.forEach((humanState, humanId) => { + if (humanState.callbacks.length === 0 || humanState.isCooldown) return; - const actionQueue = actionQueueRef.current.get(humanId); + const actionQueue = humanState.actionQueue; if (!actionQueue || actionQueue.length === 0) return; const { actionType: expectedActionType, actionUuid } = actionQueue[0]; @@ -75,11 +109,22 @@ export function useHumanEventManager() { if (!humanAsset || !human || !action || action.actionType !== expectedActionType) return; - let conditionMet = false; + const currentCount = getCallbackCount(humanId, actionUuid); const currentAction = getActionByUuid(selectedProduct.productUuid, human.currentAction?.actionUuid || '') as HumanAction | undefined; + let conditionMet = false; + if (expectedActionType === "worker") { + if (currentAction && currentAction.actionType === 'worker' && currentCount >= currentAction.loadCount) { + humanState.callbacks.shift(); + actionQueue.shift(); + if (humanState.callbacks.length === 0) { + removeHumanFromMonitor(humanId); + } + return; + } + if (currentAction && currentAction.actionType === 'worker') { conditionMet = ( !human.isActive && @@ -88,15 +133,6 @@ export function useHumanEventManager() { human.currentLoad < currentAction.loadCapacity ); - if (human.totalLoadCount >= currentAction.loadCount && actionUuid === human.currentAction?.actionUuid) { - queue.shift(); - actionQueue.shift(); - if (queue.length === 0) { - removeHumanFromMonitor(humanId); - } - return; - } - if (conditionMet && actionUuid !== human.currentAction?.actionUuid) { setCurrentPhase(human.modelUuid, 'init'); } @@ -104,8 +140,7 @@ export function useHumanEventManager() { conditionMet = ( !human.isActive && human.state === "idle" && - humanAsset.animationState?.current === 'idle' && - human.currentLoad < action.loadCapacity + humanAsset.animationState?.current === 'idle' ); if (conditionMet && actionUuid !== human.currentAction?.actionUuid) { setCurrentPhase(human.modelUuid, 'init'); @@ -127,44 +162,34 @@ export function useHumanEventManager() { conditionMet = ( !human.isActive && human.state === "idle" && - humanAsset.animationState?.current === 'idle' && - human.currentLoad < action.loadCapacity + humanAsset.animationState?.current === 'idle' ) } - if (conditionMet) { - clearLoadCount(human.modelUuid); - } } if (conditionMet) { - const callback = queue.shift(); + const callback = humanState.callbacks.shift(); actionQueue.shift(); - if (callback) callback(); + if (callback) { + callback(); + incrementCallbackCount(humanId, actionUuid); + } - if (queue.length === 0) { + if (humanState.callbacks.length === 0) { removeHumanFromMonitor(humanId); } else { - isCooldownRef.current.set(humanId, true); + humanState.isCooldown = true; setTimeout(() => { - isCooldownRef.current.set(humanId, false); + humanState.isCooldown = false; }, 1000); } } }); - }, 0); - - useEffect(() => { - return () => { - callbacksRef.current.clear(); - actionQueueRef.current.clear(); - isCooldownRef.current.clear(); - isMonitoringRef.current = false; - }; - }, []); + }); return { addHumanToMonitor, removeHumanFromMonitor, }; -} +} \ No newline at end of file diff --git a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts index 6a0ef6b..62582af 100644 --- a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts +++ b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts @@ -478,8 +478,10 @@ export function useTriggerHandler() { if (toEvent?.type === 'transfer') { // Vehicle to Transfer if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { + const conveyor = getConveyorById(toEvent.modelUuid); const material = getMaterialById(materialId); - if (material) { + + if (material && conveyor) { const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid); setPreviousLocation(material.materialId, { @@ -494,23 +496,29 @@ export function useTriggerHandler() { actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid, }); + setIsPaused(materialId, false); + setIsVisible(materialId, true); if (action && action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid && action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid ) { + setNextLocation(material.materialId, { - modelUuid: action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid, - pointUuid: action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid, + modelUuid: action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '', + pointUuid: action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid || '', }); - handleAction(action, materialId); - } + addConveyorToMonitor(conveyor.modelUuid, () => { + setIsPaused(materialId, false); + + handleAction(action, materialId); + }) + } } } - } else if (toEvent?.type === 'vehicle') { // Vehicle to Vehicle @@ -539,7 +547,6 @@ export function useTriggerHandler() { setNextLocation(material.materialId, null); - if (action && armBot) { if (armBot.isActive === false && armBot.state === 'idle') { @@ -1439,13 +1446,11 @@ export function useTriggerHandler() { const material = getMaterialById(materialId); if (material) { - setIsPaused(material.materialId, false); + setIsPaused(material.materialId, true); const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid); const vehicle = getVehicleById(trigger.triggeredAsset?.triggeredModel.modelUuid); - setNextLocation(material.materialId, null); - if (action) { if (vehicle) { @@ -1466,16 +1471,15 @@ export function useTriggerHandler() { actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid, }); + setNextLocation(material.materialId, null); + // Handle current action from vehicle handleAction(action, materialId); } else { - setIsPaused(materialId, true); - addVehicleToMonitor(vehicle.modelUuid, () => { - setIsPaused(materialId, false); setIsVisible(materialId, false); setPreviousLocation(material.materialId, { @@ -1493,6 +1497,7 @@ export function useTriggerHandler() { setNextLocation(material.materialId, null); // Handle current action from vehicle + console.log('action: ', action); handleAction(action, materialId); } ) diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index 59cd9da..5ea19f9 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -325,7 +325,6 @@ function DraggableLineSegment({ }; const onPointerMove = (e: ThreeEvent) => { - console.log('isAnyDragging: ', isAnyDragging); if (isAnyDragging !== "line" || activeTool !== 'pen') return; const intersect = new THREE.Vector3(); diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index 3d6d274..5de64cd 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -19,7 +19,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) const { materialStore, armBotStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, productStore, assetStore } = useSceneContext(); const { removeMaterial, setEndTime, setIsVisible } = materialStore(); const { getStorageUnitById } = storageUnitStore(); - const { getHumanById, addCurrentAction, addCurrentMaterial, incrementHumanLoad , incrementLoadCount } = humanStore(); + const { getHumanById, addCurrentAction, addCurrentMaterial, incrementHumanLoad } = humanStore(); const { getArmBotById } = armBotStore(); const { getConveyorById } = conveyorStore(); const { triggerPointActions } = useTriggerHandler(); @@ -302,7 +302,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) setIsVisible(material.materialId, false); addCurrentMaterial(humanId, material.materialType, material.materialId); incrementHumanLoad(humanId, 1); - incrementLoadCount(humanId, 1); } return; } diff --git a/app/src/store/simulation/useHumanStore.ts b/app/src/store/simulation/useHumanStore.ts index bcaf303..685970f 100644 --- a/app/src/store/simulation/useHumanStore.ts +++ b/app/src/store/simulation/useHumanStore.ts @@ -27,11 +27,6 @@ interface HumansStore { incrementHumanLoad: (modelUuid: string, incrementBy: number) => void; decrementHumanLoad: (modelUuid: string, decrementBy: number) => void; - incrementLoadCount: (modelUuid: string, incrementBy: number) => void; - decrementLoadCount: (modelUuid: string, decrementBy: number) => void; - - clearLoadCount: (modelUuid: string) => void; - addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void; setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string }[]) => void; removeLastMaterial: (modelUuid: string) => { materialType: string; materialId: string } | undefined; @@ -65,7 +60,6 @@ export const createHumanStore = () => { isScheduled: false, idleTime: 0, activeTime: 0, - totalLoadCount: 0, currentLoad: 0, currentMaterials: [], distanceTraveled: 0 @@ -182,33 +176,6 @@ export const createHumanStore = () => { }); }, - incrementLoadCount: (modelUuid, incrementBy) => { - set((state) => { - const human = state.humans.find(h => h.modelUuid === modelUuid); - if (human) { - human.totalLoadCount += incrementBy; - } - }); - }, - - decrementLoadCount: (modelUuid, decrementBy) => { - set((state) => { - const human = state.humans.find(h => h.modelUuid === modelUuid); - if (human) { - human.totalLoadCount -= decrementBy; - } - }); - }, - - clearLoadCount: (modelUuid) => { - set((state) => { - const human = state.humans.find(h => h.modelUuid === modelUuid); - if (human) { - human.totalLoadCount = 0; - } - }); - }, - addCurrentMaterial: (modelUuid, materialType, materialId) => { set((state) => { const human = state.humans.find(h => h.modelUuid === modelUuid); diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts index 5d6b21f..dcb9f49 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -252,7 +252,6 @@ interface HumanStatus extends HumanEventSchema { isScheduled: boolean; idleTime: number; activeTime: number; - totalLoadCount: number; currentLoad: number; currentMaterials: { materialType: string; materialId: string; }[]; distanceTraveled: number;