From 4b4fe53ee483764581e90e4c58f432aad18727c7 Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Mon, 28 Apr 2025 18:51:16 +0530 Subject: [PATCH 01/14] play-pause-rest actions --- .../ui/simulation/simulationPlayer.tsx | 1 + .../armInstance/roboticArmInstance.tsx | 12 +- .../instances/animator/vehicleAnimator.tsx | 262 +++++++++--------- .../instances/instance/vehicleInstance.tsx | 20 +- .../modules/simulation/vehicle/vehicles.tsx | 9 +- 5 files changed, 160 insertions(+), 144 deletions(-) diff --git a/app/src/components/ui/simulation/simulationPlayer.tsx b/app/src/components/ui/simulation/simulationPlayer.tsx index 528fbc2..fb59d3a 100644 --- a/app/src/components/ui/simulation/simulationPlayer.tsx +++ b/app/src/components/ui/simulation/simulationPlayer.tsx @@ -21,6 +21,7 @@ const SimulationPlayer: React.FC = () => { // Button functions const handleReset = () => { setReset(true); + // setReset(!isReset); setSpeed(1); }; const handlePlayStop = () => { diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx index 86eee6a..399962e 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -66,7 +66,7 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { } //Waiting for trigger. else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "rest" && !robot.currentAction) { - console.log("trigger"); + setTimeout(() => { addCurrentAction(robot.modelUuid, 'action-003'); }, 3000); @@ -133,28 +133,28 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { const HandleCallback = () => { if (robot.isActive && robot.state == "running" && currentPhase == "init-to-rest") { - console.log("Callback triggered: rest"); + setArmBotActive(robot.modelUuid, false) setArmBotState(robot.modelUuid, "idle") setCurrentPhase("rest"); setPath([]) } else if (robot.isActive && robot.state == "running" && currentPhase == "rest-to-start") { - console.log("Callback triggered: pick."); + setArmBotActive(robot.modelUuid, false) setArmBotState(robot.modelUuid, "idle") setCurrentPhase("picking"); setPath([]) } else if (robot.isActive && robot.state == "running" && currentPhase == "start-to-end") { - console.log("Callback triggered: drop."); + setArmBotActive(robot.modelUuid, false) setArmBotState(robot.modelUuid, "idle") setCurrentPhase("dropping"); setPath([]) } else if (robot.isActive && robot.state == "running" && currentPhase == "end-to-rest") { - console.log("Callback triggered: rest, cycle completed."); + setArmBotActive(robot.modelUuid, false) setArmBotState(robot.modelUuid, "idle") setCurrentPhase("rest"); @@ -163,7 +163,7 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { } } const logStatus = (id: string, status: string) => { - console.log(id +","+ status); + } return ( diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index dbc5064..1d21468 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -1,10 +1,11 @@ import { useEffect, useRef, useState } from 'react' import { useFrame, useThree } from '@react-three/fiber'; -import { useFloorItems } from '../../../../../store/store'; +import { useActiveTool, useFloorItems } from '../../../../../store/store'; import * as THREE from 'three'; import { Line } from '@react-three/drei'; -import { useAnimationPlaySpeed, usePauseButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; +import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; +import useModuleStore from '../../../../../store/useModuleStore'; interface VehicleAnimatorProps { path: [number, number, number][]; @@ -18,8 +19,10 @@ interface VehicleAnimatorProps { function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset }: VehicleAnimatorProps) { const { decrementVehicleLoad, vehicles } = useVehicleStore(); const { isPaused } = usePauseButtonStore(); + const { isPlaying, setIsPlaying } = usePlayButtonStore(); + const { activeModule } = useModuleStore(); const { speed } = useAnimationPlaySpeed(); - const { isReset } = useResetButtonStore(); + const { isReset, setReset } = useResetButtonStore(); const [restRotation, setRestingRotation] = useState(true); const [progress, setProgress] = useState(0); const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); @@ -30,6 +33,12 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai let startTime: number; let pausedTime: number; let fixedInterval: number; + let coveredDistance = progressRef.current; + let accumulatedDistance = 0; + let index = 0; + const isPausedRef = useRef(false); + const pauseTimeRef = useRef(null); + useEffect(() => { if (currentPhase === 'stationed-pickup' && path.length > 0) { @@ -45,118 +54,52 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai setProgress(0); completedRef.current = false; }, [currentPath]); - // useEffect(() => { - // console.log('isReset: ', isReset); - // if (isReset) { - // reset(); - // setCurrentPath([]); - // setProgress(0); - // completedRef.current = false; - // decrementVehicleLoad(agvDetail.modelUuid, 0) - // } - // }, [isReset]) - - // useFrame((_, delta) => { - // const object = scene.getObjectByProperty('uuid', agvUuid); - // if (!object || currentPath.length < 2) return; - // if (isPaused) return; - - // let totalDistance = 0; - // const distances = []; - - // for (let i = 0; i < currentPath.length - 1; i++) { - // const start = new THREE.Vector3(...currentPath[i]); - // const end = new THREE.Vector3(...currentPath[i + 1]); - // const segmentDistance = start.distanceTo(end); - // distances.push(segmentDistance); - // totalDistance += segmentDistance; - // } - - // let coveredDistance = progressRef.current; - // let accumulatedDistance = 0; - // let index = 0; - - // while ( - // index < distances.length && - // coveredDistance > accumulatedDistance + distances[index] - // ) { - // accumulatedDistance += distances[index]; - // index++; - // } - - // if (index < distances.length) { - // const start = new THREE.Vector3(...currentPath[index]); - // const end = new THREE.Vector3(...currentPath[index + 1]); - // const segmentDistance = distances[index]; - - // const currentDirection = new THREE.Vector3().subVectors(end, start).normalize(); - // const targetAngle = Math.atan2(currentDirection.x, currentDirection.z); - // const rotationSpeed = 2.0; - // const currentAngle = object.rotation.y; - - // let angleDifference = targetAngle - currentAngle; - // if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI; - // if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI; - - // const maxRotationStep = rotationSpeed * delta; - // object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); - - // const isAligned = Math.abs(angleDifference) < 0.01; - - // if (isAligned) { - // progressRef.current += delta * (speed * agvDetail.speed); - // coveredDistance = progressRef.current; - - // const t = (coveredDistance - accumulatedDistance) / segmentDistance; - // const position = start.clone().lerp(end, t); - // object.position.copy(position); - // } - // } - - // if (progressRef.current >= totalDistance) { - // if (restRotation) { - // const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0)); - // object.quaternion.slerp(targetQuaternion, delta * 2); - // const angleDiff = object.quaternion.angleTo(targetQuaternion); - // if (angleDiff < 0.01) { - // let objectRotation = agvDetail.point.rotation - // object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); - // setRestingRotation(false); - // } - // return; - // } - // } - - // if (progressRef.current >= totalDistance) { - // setRestingRotation(true); - // progressRef.current = 0; - // movingForward.current = !movingForward.current; - // setCurrentPath([]); - // handleCallBack(); - // if (currentPhase === 'pickup-drop') { - // requestAnimationFrame(firstFrame); - // } - // } - // }); useEffect(() => { - console.log('isReset: ', isReset); if (isReset) { reset(); setCurrentPath([]); setProgress(0); - progressRef.current = 0; completedRef.current = false; movingForward.current = true; - setRestingRotation(false); + progressRef.current = 0; + startTime = 0; + coveredDistance = 0; + setReset(false); + setRestingRotation(true); decrementVehicleLoad(agvDetail.modelUuid, 0); - console.log('agvDetail: ', vehicles); + const object = scene.getObjectByProperty('uuid', agvUuid); + if (object) { + object.position.set(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]); + let objectRotation = agvDetail.point.rotation + object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); + } } - }, [isReset]); + }, [isReset]) + + useEffect(() => { + console.log('isPlaying: ', isPlaying); + if (!isPlaying) { + reset(); + setCurrentPath([]); + setProgress(0); + completedRef.current = false; + movingForward.current = true; + progressRef.current = 0; + startTime = 0; + coveredDistance = 0; + setReset(false); + setRestingRotation(true); + decrementVehicleLoad(agvDetail.modelUuid, 0); + const object = scene.getObjectByProperty('uuid', agvUuid); + if (object) { + object.position.set(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]) + let objectRotation = agvDetail.point.rotation + object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); + } + } + }, [isPlaying]) useFrame((_, delta) => { - // If reset is active, don't run anything in frame - if (isReset) return; - const object = scene.getObjectByProperty('uuid', agvUuid); if (!object || currentPath.length < 2) return; if (isPaused) return; @@ -172,11 +115,11 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai totalDistance += segmentDistance; } - let coveredDistance = progressRef.current; - let accumulatedDistance = 0; - let index = 0; - while (index < distances.length && coveredDistance > accumulatedDistance + distances[index]) { + while ( + index < distances.length && + coveredDistance > accumulatedDistance + distances[index] + ) { accumulatedDistance += distances[index]; index++; } @@ -188,17 +131,16 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai const currentDirection = new THREE.Vector3().subVectors(end, start).normalize(); const targetAngle = Math.atan2(currentDirection.x, currentDirection.z); + + const rotationSpeed = speed; const currentAngle = object.rotation.y; let angleDifference = targetAngle - currentAngle; if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI; if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI; - const rotationSpeed = 2.0; const maxRotationStep = rotationSpeed * delta; - const rotationStep = Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); - object.rotation.y += rotationStep; - + object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); const isAligned = Math.abs(angleDifference) < 0.01; if (isAligned) { @@ -217,46 +159,104 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai object.quaternion.slerp(targetQuaternion, delta * 2); const angleDiff = object.quaternion.angleTo(targetQuaternion); if (angleDiff < 0.01) { - const objectRotation = agvDetail.point.rotation; + let objectRotation = agvDetail.point.rotation object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); setRestingRotation(false); } - } else { - setRestingRotation(true); - progressRef.current = 0; - movingForward.current = !movingForward.current; - setCurrentPath([]); - handleCallBack(); - if (currentPhase === 'pickup-drop') { - requestAnimationFrame(firstFrame); - } + return; + } + } + + if (progressRef.current >= totalDistance) { + setRestingRotation(true); + progressRef.current = 0; + movingForward.current = !movingForward.current; + setCurrentPath([]); + handleCallBack(); + if (currentPhase === 'pickup-drop') { + requestAnimationFrame(firstFrame); } } }); + let pauseTime: number = 0; + + + useEffect(() => { + // Update the pause state in the ref + isPausedRef.current = isPaused; + }, [isPaused]); function firstFrame() { const unLoadDuration = agvDetail.point.action.unLoadDuration; const droppedMaterial = agvDetail.currentLoad; - fixedInterval = (unLoadDuration / droppedMaterial) * 1000; + fixedInterval = ((unLoadDuration / droppedMaterial) * 1000) / speed; + // fixedInterval = (unLoadDuration / droppedMaterial) * 1000; startTime = performance.now(); step(droppedMaterial); } function step(droppedMaterial: number) { - const elapsedTime = (performance.now() - startTime) * speed; + if (isPausedRef.current) { + // Handle pause logic + if (!pauseTimeRef.current) { + pauseTimeRef.current = performance.now(); // Set pause time only once + } + requestAnimationFrame(() => step(droppedMaterial)); // Continue calling step during pause + return; + } + + if (pauseTimeRef.current) { + // Adjust start time after resuming from pause + const pauseDuration = performance.now() - pauseTimeRef.current; + startTime += pauseDuration; + pauseTimeRef.current = null; // Clear pause time + } + + const elapsedTime = performance.now() - startTime; // Calculate elapsed time + if (elapsedTime >= fixedInterval) { - console.log('fixedInterval: ', fixedInterval); - console.log('elapsedTime: ', elapsedTime); + + let droppedMat = droppedMaterial - 1; - decrementVehicleLoad(agvDetail.modelUuid, 1); - if (droppedMat === 0) return; - startTime = performance.now(); - requestAnimationFrame(() => step(droppedMat)); + decrementVehicleLoad(agvDetail.modelUuid, 1); // Decrement vehicle load + + if (droppedMat > 0) { + // Reset start time for the next step + startTime = performance.now(); + requestAnimationFrame(() => step(droppedMat)); // Continue with the next step + } else { + + return; // Exit when all materials are dropped + } } else { - requestAnimationFrame(() => step(droppedMaterial)); + requestAnimationFrame(() => step(droppedMaterial)); // Continue animation } } + + // function firstFrame() { + // const unLoadDuration = agvDetail.point.action.unLoadDuration; + // const droppedMaterial = agvDetail.currentLoad; + // fixedInterval = (unLoadDuration / droppedMaterial) * 1000; + // startTime = performance.now(); + // step(droppedMaterial); + // } + + // function step(droppedMaterial: number) { + // const elapsedTime = (performance.now() - startTime) * speed; + // if (elapsedTime >= fixedInterval) { + // + // + // let droppedMat = droppedMaterial - 1; + // decrementVehicleLoad(agvDetail.modelUuid, 1); + // if (droppedMat === 0) return; + // startTime = performance.now(); + // requestAnimationFrame(() => step(droppedMat)); + // } else { + // requestAnimationFrame(() => step(droppedMaterial)); + // } + // } + return ( <> {currentPath.length > 0 && ( diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index 44a8ad8..a78101e 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -29,17 +29,27 @@ function VehicleInstance({ agvDetail }: any) { [navMesh] ); - function vehicleStatus(modelid: string, status: string) { - // console.log(`AGV ${modelid}: ${status}`); + function vehicleStatus(modelId: string, status: string) { + // console.log(`AGV ${modelId}: ${status}`); } + // Function to reset everything function reset() { - console.log("runs"); + setCurrentPhase('stationed'); setVehicleActive(agvDetail.modelUuid, false); setVehicleState(agvDetail.modelUuid, 'idle'); setPath([]); - setCurrentPhase('stationed') } + // useEffect(() => { + // console.log('isReset: ', isReset); + // if (isReset) { + // reset(); + // } + // }, [isReset]); + + + + useEffect(() => { if (isPlaying) { if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') { @@ -90,6 +100,8 @@ function VehicleInstance({ agvDetail }: any) { setCurrentPhase('drop-pickup'); vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point'); } + } else { + reset() } }, [vehicles, currentPhase, path, isPlaying, isReset]); diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx index f0b4d17..1b05888 100644 --- a/app/src/modules/simulation/vehicle/vehicles.tsx +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -2,11 +2,12 @@ import React, { useEffect } from 'react' import VehicleInstances from './instances/vehicleInstances'; import { useVehicleStore } from '../../../store/simulation/useVehicleStore'; import { useFloorItems } from '../../../store/store'; - +import { useSelectedEventSphere } from '../../../store/simulation/useSimulationStore'; +import * as THREE from "three" function Vehicles() { const { vehicles, addVehicle } = useVehicleStore(); - + const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere } = useSelectedEventSphere(); const { floorItems } = useFloorItems(); const vehicleStatusSample: VehicleEventSchema[] = [ @@ -95,7 +96,9 @@ function Vehicles() { ] } } - }, { + }, + + { modelUuid: "e729a4f1-11d2-4778-8d6a-468f1b4f6b79", modelName: "forklift", position: [98.85729337188162, 0, 38.36616546567653], From 979f71d43f8c8bdd7dafd6db822275d98e7ca15a Mon Sep 17 00:00:00 2001 From: Nalvazhuthi Date: Tue, 29 Apr 2025 10:18:05 +0530 Subject: [PATCH 02/14] Added vehicle UI --- app/package-lock.json | 66 +-- app/src/assets/gltf-glb/arrow_green.glb | Bin 0 -> 4580 bytes app/src/assets/gltf-glb/arrow_red.glb | Bin 0 -> 4580 bytes app/src/modules/scene/scene.tsx | 45 +- .../events/points/creator/pointsCreator.tsx | 392 ++++++++++-------- .../simulation/ui/vehicle/useDraggableGLTF.ts | 131 ++++++ .../simulation/ui/vehicle/vehicleUI.tsx | 283 +++++++++++++ .../modules/simulation/vehicle/vehicles.tsx | 286 ++++++------- 8 files changed, 817 insertions(+), 386 deletions(-) create mode 100644 app/src/assets/gltf-glb/arrow_green.glb create mode 100644 app/src/assets/gltf-glb/arrow_red.glb create mode 100644 app/src/modules/simulation/ui/vehicle/useDraggableGLTF.ts create mode 100644 app/src/modules/simulation/ui/vehicle/vehicleUI.tsx diff --git a/app/package-lock.json b/app/package-lock.json index fa04c9f..3d5aea4 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -30,7 +30,6 @@ "glob": "^11.0.0", "gsap": "^3.12.5", "html2canvas": "^1.4.1", - "immer": "^10.1.1", "leva": "^0.10.0", "mqtt": "^5.10.4", "postprocessing": "^6.36.4", @@ -2022,7 +2021,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "devOptional": true, + "dev": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -2034,7 +2033,7 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "devOptional": true, + "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -4137,26 +4136,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@testing-library/dom": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", - "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@testing-library/jest-dom": { "version": "5.17.0", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", @@ -4268,25 +4247,25 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "devOptional": true + "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "devOptional": true + "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "devOptional": true + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "devOptional": true + "dev": true }, "node_modules/@turf/along": { "version": "7.2.0", @@ -9040,7 +9019,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true + "dev": true }, "node_modules/cross-env": { "version": "7.0.3", @@ -9917,7 +9896,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.3.1" } @@ -12747,10 +12726,9 @@ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" }, "node_modules/immer": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", - "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", - "license": "MIT", + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -15281,7 +15259,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "devOptional": true + "dev": true }, "node_modules/makeerror": { "version": "1.0.12", @@ -18012,16 +17990,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/react-dev-utils/node_modules/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, "node_modules/react-dev-utils/node_modules/loader-utils": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", @@ -20759,7 +20727,7 @@ "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "devOptional": true, + "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -20802,7 +20770,7 @@ "version": "8.3.4", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "devOptional": true, + "dev": true, "dependencies": { "acorn": "^8.11.0" }, @@ -20814,7 +20782,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true + "dev": true }, "node_modules/tsconfig-paths": { "version": "3.15.0", @@ -21310,7 +21278,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "devOptional": true + "dev": true }, "node_modules/v8-to-istanbul": { "version": "8.1.1", @@ -22369,7 +22337,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true, + "dev": true, "engines": { "node": ">=6" } diff --git a/app/src/assets/gltf-glb/arrow_green.glb b/app/src/assets/gltf-glb/arrow_green.glb new file mode 100644 index 0000000000000000000000000000000000000000..8e02527b34c890ef80210fd869ef7fd103ac2cf4 GIT binary patch literal 4580 zcmc&%eOOdg8b5O{AHxj8hoVNJ&|M`L$MK%~eWw&q!7p$K(6x+UfU8Wx49*Nj;%p=7 zqGgHs=wi0XVzn-%rB>`_7{s$in^usmwryr6Nj_V-nps%RzITQZEG?~lp8bQlGv}Q5 z>-YP;@3|~0&(9HB zV3IVYT(Orb&ZLXK`&ODUzy3#i#M zatlkH))Gfyh2knJEOAs+Iu)1S%IM#$u(}ne&06j%R4Qz+u~aE^xt)rAk-Lm480;}u zSyE+l{-js1ag{(Bl$q}T=7KzGD7&=+)~G!Ho{_RUN)>g3HsS&g*aUyqP->oj<9>^r zaw~Wh@O)Mzl$!MNA7KEprmhNW5SiSd@YOX|2Fx45o!4(?B6*R(mNp{{Q9$^Rqvz4kmxt&$YrF^sd zc{b5BhO8@#o!N@pT3&7|$#qmMDzk$qR0S4WUCLBPxx<-hE%ECRfTLNFrda@t=Qs%q zvIxKlqDTueO-n2f+YAd!G|O-@%Sr-=MS&4nmIrPj!TvBohad}QFyf^(6Yo($zC!vz zRR)i$`N%Bh7@(2iG3I4KG-3$Puq+mMmSIJfVE zF$HQlgNGBe6syYN+Sro@;>(v8jOkxcG4nsD7^_wG&xyFmUMIMVhOazz;Jm&mE7mFMX9SmJ8V0~e;P&%3JM0eMi>SER8rL_m^hw+mjjWZ8IhMn8BpXvpa2ah zQ|5RX^hKLk39c0^Nt`HyNI_ngfaFaA4|)bQax&(?NQLnS9$?Myf`N;Q!!#U~uUCy~ z&esFu<>!AIMuvki_&qg3l>_%dpveQj{iC4xUbm7Jcr7&Z0*q>P!Lo3n|IHN!SMW0V z!C{VrK|1&_FGxRfT;RUv8-p6vYcr5be_n%38eI$Ge-GMq4J04)tkbeFUDN{*gX7jS$#qPy~q( zn8QOuYRCuzsm?Sgnv5_EwGyo%qr%sd*;?|m&~Jte+mrJ3*Ufb=#_j1;KHOl<=zRa4 zy{6i8so*Lh#Jf>z^=$OU%wKmd`>TNhkqSWE_@R>~P zz84*Pt^2SBCCpFoo;Vg36CI7b!-k`xNsrE38IIa?4^jvv{~DoV(^e#+hQ(c{Nz`y> z4ca}7MB2k;x1h@Csi8$RL%dNC+j~?_%Ng>Ip=j@X&jX*J_QzqdbpvweXpUsQukpTN z!N^_nHySk4I*iXX zr=aHMokZ`U7mLv&arzk=wEVvD=;`L2P0jIp;#u~c&Fq1uv$u`uS$z7%VN@*4BmHN87erM%&|h1a12gb&E^0ZlrU5PDhs;h%_lblQ>ha!V7ui$XY z@QW>vp4xf`@)6V0e8ib4>fbfVr9zu%2yG1`tz^YG-N7Bi!9Aaze{kuOFWh=zeeW$N zP@3mZJ&A_KLFjM4jgrxGe-}<5uV-2XiI$|i9F30L-5HC#Cu3y-b)Hz7h*rN2#7@6^ zBs#r3D;yQIfZh0Zy*F!<{X1P*rv_cn!pe}W>O^=P^}vVsyat611@qIl7HwY^PDL`(!6@toQljXFy|n~Y*M0C4L*pNxvmZ;C>TLtxV{f(uBl}`(m|92Sf{W5W0+@NHQZndY2}gk82GZrHhO;%O^^2GbKkX zh+Yx@X%hOEz8;+-ZwxOC?&EeQITC4s&DgdKh%x4| zz*Ef)7;HPIpQMI{;K1Nu{!(*@oLF?D&*!roo;=o*@@d}8t+V>_4^Ph6+GOea({_!& z^;@Rtd5Gt)A2ft+#7QXbQ1#KuFAcYU zY%rI0vfCT>f7Cl(K;yQDg~sn`WHRSAO>EJ$HP#NVGw4d(TwlyPSbwUx>8{YwS}DP^ z>!XH{C$V&A&d6=s4&Br6uq`KH=s9M4%$SF2m-U=&+Lu3X;{Cez$9|u_>X>1~p@*x) zb6uIs;`6ml*ziC}?yA1Zz3LY~wZ2h6Cd1nS8~U`Oq`t>m=KA)AvUDdq>pRt zD7Ezz4tqa-MMvb83v})IuBLx_kIek;+mAHbhOo^JU%@x#W9C+hEB zvhjg48_8e!UK9T^ci9ue+g_Nm=)+B`Q^mJB@}F!@>DC{eUUBmg-GK=gUlYq>ZDVQ+ z$;RD%)M^pkOzje0ChI)wd-v|v9yheDnemLlak3+|{mW0b+)UxSDt=e}?DC$rPTzkF z_Kl;@YmdKm@GSj3skTq#4I?9nP>ntcT^PM)(t@0xLhn0sd+%J?tWVQzkGUg;cx1hn a*iSUAU5SRP-R4)J`urv~9N-Adk^cgSWrJG) literal 0 HcmV?d00001 diff --git a/app/src/assets/gltf-glb/arrow_red.glb b/app/src/assets/gltf-glb/arrow_red.glb new file mode 100644 index 0000000000000000000000000000000000000000..02bfea4e3c8da0dde04aa66041f4817b7849bf37 GIT binary patch literal 4580 zcmc&%3s_WT8vbSucNh>C!&HP$XoN7H|J)C$Fd`y`fPm&DgK;>>xGCY4YLb^+XTLMU2vk(oKF^-#IdjhW&;Ngy z_kF+bKQpJgbi5t_PR0UcMFLDLDJ-a`%}%H4qBH90IjT){m|b=Uok8DR<*?iA&ZIfG zBx!85YO7EkNqHj+lNRts&d5u28ofYuIIVUYPG*e^?M|cBg)Y^m4LPSc)e1UeCVlgS z;<5^d*2kEofG4zr)}mM9HUEo@6u?Sy+YMqFll6#8`lJ$>uD`c-{P(n zMb&1TYGfD=6L#2LW|uExT*w$DMk0(T@`@}8BF`vk-Gj0$vkK3$zHrRd=z1n&B&@*l z0^t;fVP#z3^(^23r-+2~81v7WfGed9xjpRF}EB+G;7b*UqW3p$Ig^%{DvLY|Z(!YY%&!`)x z1e}!w6raIjTmhncK&XlDDj?K^s0mwBwx(yF)UVV)PespjSZk~w zd#tC63QO`z^9l=mw9CESV_ELTY;yvT_x$7sERumszLh;3J7 z6jl=CG-4EFMV1AL5K&YV>@Ks=f)zKjndxXk;1xyY6iH?!!eeJi_uJqZPUHkmW<`PJ z($digt8lzTWWuowQ5YVLxO~ykQ**L8+!O0D!e0*i_s?hhu#Yv-1q;g|E?o{vvQ7D> z;y#viBgvs!{74d`!b=kFO)}3aEP@w6QWA+EVn5^s7CSM5Km(8Wl<5kkwg=+ zC}O{sI3h42$IE>p$)gR1AQd7fbD}6+C6Zd$SA%5l`M-`NAyjswnkn{KL-{07Ay8W}s&5ON!&By6;|J)o0 zI$b}no=nhA%8M%iaGegqDF8Hq7agUe!u6mT)Ikj84*!!`-x}l&*G}qTYFONW!P8&w z7jxg?2M#Ro1Q&k~W3%b!VwPOUgolnA?&_SZ_jKs8`b|C95xjib=wYKmf$t25rU`Aq zS#RE}yVS00$gjH-;1To(<(q>6o=Q1ILF2%!i{R5e_!l9e4B(}gD5%~n!`?Ou%9nl~ z(sIY%jz{&-GIY`i<`W7=q)8167XrM{asrYM9nyg*DicopV-%dS=yCw^KWs>ZX_SPww*LIW<>*~gGege5KnY_V|7V}xn*l_O4(^IIvSn(((?SpZTq&= z!2UJS4UcnA?vh?!xotbQe`|9pG&gVF+T4-a`~-QDaNL9gE$JD<@`}ISUzJHevMk7R zE{Nd<8_IX@$5pA#&D-}y9UU`OfLC5wKxHK66z>SJkBFXrXR`i|O(p%Oo#*})<;4WN z7-fV;Pb9TeB)a&7P@)UHb*)T|@YYk%&@i8YHV6wXXS8Gng_jLkG5Ia+Ry({g{;U7D zAv3C%eufX%4-W>z;!PVbZ+ypFdZ_corIc4cF3YPwGgdo)lVlPi5)HwIV9F4@Yk1_5 z?K@^)bHnuiEP1XW11bEbE)hL{>V~Xc;~oGQ_2BBybujb(BO!32{h0({UhzaW{#lYJY0G?;?=5XtClxNTf4^i+v{*8p>)c`-7{_due;7L8|8+_FOZ*M#` z2Ff>GmkaQ8?#VDndgQ1Zl7=H_LpRod=R1-B4WFR>7lK9ttGtWjE3>1aJ=dTBW4c0q z`^3vTHS#kb-@cPNP#++F?WjaE6(rvu(+Fq+kIR~x5YwKVL{T}{#%$4r3URF=2@z2z zYtP&n&pkf&<0Fwv23|Mhvt8`)C}8ppJ@hc;N_R_*z0p6T>z&Bz8c zk~HL_CNTsy#E|)~H_793BU7uUEWKzuN(^%?03pKDa=ttJi}Q`q7fwf{uD7qgxZD6y z&897@LtZ5t$GW%u^|sK?CC`|Pwye1AgU9yyTsPffawkO(Zhv4=-Pyg%ZXeJd`WA_d zu(;Zr?wUGfUE#Kbmz(%ykdpGHO}@Co01^94;TrB*bGUxd0nd2y-j0G{Z968ANtyoU zka%OnfZ%tS2;tJ*qu=kiKV{A9rR$bQ96tmPuR3u4(!{#P+b7h;ouS%VuW!s{?^%AH z_89u#(0I$%<+PiOUjbQGX@y3}ml(TKmjAL_i^tX;kdTp5d zVEScd)GaU0=*(+8H~GH95e@Ghp5L~|_G;MBaPQqw$Ca;NuHNy++xJ#EH=J8my7|pZ zo@1xBT(fP(L3`eD=Y5$`2d8YB_@QXoV@RZW3D!Wpkv=+RaJZfd) [ - { name: "forward", keys: ["ArrowUp", "w", "W"] }, - { name: "backward", keys: ["ArrowDown", "s", "S"] }, - { name: "left", keys: ["ArrowLeft", "a", "A"] }, - { name: "right", keys: ["ArrowRight", "d", "D"] },], - []); + const map = useMemo( + () => [ + { name: "forward", keys: ["ArrowUp", "w", "W"] }, + { name: "backward", keys: ["ArrowDown", "s", "S"] }, + { name: "left", keys: ["ArrowLeft", "a", "A"] }, + { name: "right", keys: ["ArrowRight", "d", "D"] }, + ], + [] + ); - return ( - - { e.preventDefault(); }}> + return ( + + { + e.preventDefault(); + }} + > + - + - + - + - - - - - - - ); + + + + ); } diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx index bc2f4db..e503419 100644 --- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx +++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx @@ -1,173 +1,237 @@ -import React, { useEffect, useRef, useState } from 'react'; -import * as THREE from 'three'; -import { useEventsStore } from '../../../../../store/simulation/useEventsStore'; -import useModuleStore from '../../../../../store/useModuleStore'; -import { TransformControls } from '@react-three/drei'; -import { detectModifierKeys } from '../../../../../utils/shortcutkeys/detectModifierKeys'; -import { useSelectedEventSphere, useSelectedEventData } from '../../../../../store/simulation/useSimulationStore'; +import React, { useEffect, useRef, useState } from "react"; +import * as THREE from "three"; +import { useEventsStore } from "../../../../../store/simulation/useEventsStore"; +import useModuleStore from "../../../../../store/useModuleStore"; +import { TransformControls } from "@react-three/drei"; +import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys"; +import { + useSelectedEventSphere, + useSelectedEventData, +} from "../../../../../store/simulation/useSimulationStore"; function PointsCreator() { - const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore(); - const { activeModule } = useModuleStore(); - const transformRef = useRef(null); - const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null); - const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); - const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere } = useSelectedEventSphere(); - const { setSelectedEventData, clearSelectedEventData } = useSelectedEventData(); + const { events, updatePoint, getPointByUuid, getEventByModelUuid } = + useEventsStore(); + const { activeModule } = useModuleStore(); + const transformRef = useRef(null); + const [transformMode, setTransformMode] = useState< + "translate" | "rotate" | null + >(null); + const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); + const { + selectedEventSphere, + setSelectedEventSphere, + clearSelectedEventSphere, + } = useSelectedEventSphere(); + const { setSelectedEventData, clearSelectedEventData } = + useSelectedEventData(); - useEffect(() => { - if (selectedEventSphere) { - const eventData = getEventByModelUuid(selectedEventSphere.userData.modelUuid); - if (eventData) { - setSelectedEventData( - eventData, - selectedEventSphere.userData.pointUuid - ); - } else { - clearSelectedEventData(); - } - } else { - clearSelectedEventData(); - } - }, [selectedEventSphere]); - - useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - const keyCombination = detectModifierKeys(e); - if (!selectedEventSphere) return; - if (keyCombination === "G") { - setTransformMode((prev) => (prev === "translate" ? null : "translate")); - } - if (keyCombination === "R") { - setTransformMode((prev) => (prev === "rotate" ? null : "rotate")); - } - }; - - window.addEventListener("keydown", handleKeyDown); - return () => window.removeEventListener("keydown", handleKeyDown); - }, [selectedEventSphere]); - - const updatePointToState = (selectedEventSphere: THREE.Mesh) => { - let point = JSON.parse(JSON.stringify(getPointByUuid(selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid))); - if (point) { - point.position = [selectedEventSphere.position.x, selectedEventSphere.position.y, selectedEventSphere.position.z]; - updatePoint(selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid, point) - } + useEffect(() => { + if (selectedEventSphere) { + const eventData = getEventByModelUuid( + selectedEventSphere.userData.modelUuid + ); + if (eventData) { + setSelectedEventData(eventData, selectedEventSphere.userData.pointUuid); + } else { + clearSelectedEventData(); + } + } else { + clearSelectedEventData(); } + }, [selectedEventSphere]); - return ( - <> - {activeModule === 'simulation' && - <> - - {events.map((event, i) => { - if (event.type === 'transfer') { - return ( - - {event.points.map((point, j) => ( - (sphereRefs.current[point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere(sphereRefs.current[point.uuid]); - }} - onPointerMissed={() => { - clearSelectedEventSphere(); - setTransformMode(null); - }} - key={`${i}-${j}`} - position={new THREE.Vector3(...point.position)} - userData={{ modelUuid: event.modelUuid, pointUuid: point.uuid }} - > - - - - ))} - - ); - } else if (event.type === 'vehicle') { - return ( - - (sphereRefs.current[event.point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere(sphereRefs.current[event.point.uuid]); - }} - onPointerMissed={() => { - clearSelectedEventSphere(); - setTransformMode(null); - }} - position={new THREE.Vector3(...event.point.position)} - userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }} - > - - - - - ); - } else if (event.type === 'roboticArm') { - return ( - - (sphereRefs.current[event.point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere(sphereRefs.current[event.point.uuid]); - }} - onPointerMissed={() => { - clearSelectedEventSphere(); - setTransformMode(null); - }} - position={new THREE.Vector3(...event.point.position)} - userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }} - > - - - - - ); - } else if (event.type === 'machine') { - return ( - - (sphereRefs.current[event.point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere(sphereRefs.current[event.point.uuid]); - }} - onPointerMissed={() => { - clearSelectedEventSphere(); - setTransformMode(null); - }} - position={new THREE.Vector3(...event.point.position)} - userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }} - > - - - - - ); - } else { - return null; - } - })} - - {(selectedEventSphere && transformMode) && - { updatePointToState(selectedEventSphere) }} /> - } - - } - + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + const keyCombination = detectModifierKeys(e); + if (!selectedEventSphere) return; + if (keyCombination === "G") { + setTransformMode((prev) => (prev === "translate" ? null : "translate")); + } + if (keyCombination === "R") { + setTransformMode((prev) => (prev === "rotate" ? null : "rotate")); + } + }; + + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [selectedEventSphere]); + + const updatePointToState = (selectedEventSphere: THREE.Mesh) => { + let point = JSON.parse( + JSON.stringify( + getPointByUuid( + selectedEventSphere.userData.modelUuid, + selectedEventSphere.userData.pointUuid + ) + ) ); + if (point) { + point.position = [ + selectedEventSphere.position.x, + selectedEventSphere.position.y, + selectedEventSphere.position.z, + ]; + updatePoint( + selectedEventSphere.userData.modelUuid, + selectedEventSphere.userData.pointUuid, + point + ); + } + }; + + return ( + <> + {activeModule === "simulation" && ( + <> + + {events.map((event, i) => { + if (event.type === "transfer") { + return ( + + {event.points.map((point, j) => ( + (sphereRefs.current[point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[point.uuid] + ); + }} + onPointerMissed={() => { + // clearSelectedEventSphere(); + setTransformMode(null); + }} + key={`${i}-${j}`} + position={new THREE.Vector3(...point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: point.uuid, + }} + > + + + + ))} + + ); + } else if (event.type === "vehicle") { + return ( + + (sphereRefs.current[event.point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[event.point.uuid] + ); + }} + onPointerMissed={() => { + // clearSelectedEventSphere(); + setTransformMode(null); + }} + position={new THREE.Vector3(...event.point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: event.point.uuid, + }} + > + + + + + ); + } else if (event.type === "roboticArm") { + return ( + + (sphereRefs.current[event.point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[event.point.uuid] + ); + }} + onPointerMissed={() => { + // clearSelectedEventSphere(); + setTransformMode(null); + }} + position={new THREE.Vector3(...event.point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: event.point.uuid, + }} + > + + + + + ); + } else if (event.type === "machine") { + return ( + + (sphereRefs.current[event.point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[event.point.uuid] + ); + }} + onPointerMissed={() => { + // clearSelectedEventSphere(); + setTransformMode(null); + }} + position={new THREE.Vector3(...event.point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: event.point.uuid, + }} + > + + + + + ); + } else { + return null; + } + })} + + {selectedEventSphere && transformMode && ( + { + updatePointToState(selectedEventSphere); + }} + /> + )} + + )} + + ); } export default PointsCreator; diff --git a/app/src/modules/simulation/ui/vehicle/useDraggableGLTF.ts b/app/src/modules/simulation/ui/vehicle/useDraggableGLTF.ts new file mode 100644 index 0000000..b7e9272 --- /dev/null +++ b/app/src/modules/simulation/ui/vehicle/useDraggableGLTF.ts @@ -0,0 +1,131 @@ +import { useRef } from "react"; +import * as THREE from "three"; +import { ThreeEvent, useThree } from "@react-three/fiber"; + +type OnUpdateCallback = (object: THREE.Object3D) => void; + +export default function useDraggableGLTF(onUpdate: OnUpdateCallback) { + const { camera, gl, controls, scene } = useThree(); + const activeObjRef = useRef(null); + const planeRef = useRef( + new THREE.Plane(new THREE.Vector3(0, 1, 0), 0) + ); + const offsetRef = useRef(new THREE.Vector3()); + const initialPositionRef = useRef(new THREE.Vector3()); + + const raycaster = new THREE.Raycaster(); + const pointer = new THREE.Vector2(); + + const handlePointerDown = (e: ThreeEvent) => { + e.stopPropagation(); + + let obj: THREE.Object3D | null = e.object; + + // Traverse up until we find modelUuid in userData + while (obj && !obj.userData?.modelUuid) { + obj = obj.parent; + } + + if (!obj) return; + + // Disable orbit controls while dragging + if (controls) (controls as any).enabled = false; + + activeObjRef.current = obj; + initialPositionRef.current.copy(obj.position); + + // Get world position + const objectWorldPos = new THREE.Vector3(); + obj.getWorldPosition(objectWorldPos); + + // Set plane at the object's Y level + planeRef.current.set(new THREE.Vector3(0, 1, 0), -objectWorldPos.y); + + // Convert pointer to NDC + const rect = gl.domElement.getBoundingClientRect(); + pointer.x = ((e.clientX - rect.left) / rect.width) * 2 - 1; + pointer.y = -((e.clientY - rect.top) / rect.height) * 2 + 1; + + // Raycast to intersection + raycaster.setFromCamera(pointer, camera); + const intersection = new THREE.Vector3(); + raycaster.ray.intersectPlane(planeRef.current, intersection); + + // Calculate offset + offsetRef.current.copy(objectWorldPos).sub(intersection); + + // Start listening for drag + gl.domElement.addEventListener("pointermove", handlePointerMove); + gl.domElement.addEventListener("pointerup", handlePointerUp); + }; + + const handlePointerMove = (e: PointerEvent) => { + if (!activeObjRef.current) return; + + // Check if Shift key is pressed + const isShiftKeyPressed = e.shiftKey; + + // Get the mouse position relative to the canvas + const rect = gl.domElement.getBoundingClientRect(); + pointer.x = ((e.clientX - rect.left) / rect.width) * 2 - 1; + pointer.y = -((e.clientY - rect.top) / rect.height) * 2 + 1; + + // Update raycaster to point to the mouse position + raycaster.setFromCamera(pointer, camera); + + // Create a vector to store intersection point + const intersection = new THREE.Vector3(); + const intersects = raycaster.ray.intersectPlane(planeRef.current, intersection); + if (!intersects) return; + + // Add offset for dragging + intersection.add(offsetRef.current); + console.log('intersection: ', intersection); + + // Get the parent's world matrix if exists + const parent = activeObjRef.current.parent; + const targetPosition = new THREE.Vector3(); + + if (isShiftKeyPressed) { + console.log('isShiftKeyPressed: ', isShiftKeyPressed); + // For Y-axis only movement, maintain original X and Z + console.log('initialPositionRef: ', initialPositionRef); + console.log('intersection.y: ', intersection); + targetPosition.set( + initialPositionRef.current.x, + intersection.y, + initialPositionRef.current.z + ); + } else { + // For free movement + targetPosition.copy(intersection); + } + + // Convert world position to local if object is nested inside a parent + if (parent) { + parent.worldToLocal(targetPosition); + } + + // Update object position + activeObjRef.current.position.copy(targetPosition); + }; + + const handlePointerUp = () => { + if (controls) (controls as any).enabled = true; + + if (activeObjRef.current) { + // Pass the updated position to the onUpdate callback to persist it + onUpdate(activeObjRef.current); + } + + gl.domElement.removeEventListener("pointermove", handlePointerMove); + gl.domElement.removeEventListener("pointerup", handlePointerUp); + + activeObjRef.current = null; + }; + + return { handlePointerDown }; +} + + + diff --git a/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx b/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx new file mode 100644 index 0000000..f927c33 --- /dev/null +++ b/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx @@ -0,0 +1,283 @@ +import React, { useRef, useEffect, useState } from "react"; +import startPoint from "../../../../assets/gltf-glb/arrow_green.glb"; +import startEnd from "../../../../assets/gltf-glb/arrow_red.glb"; +import { useGLTF } from "@react-three/drei"; +import { useSelectedEventSphere } from "../../../../store/simulation/useSimulationStore"; +import * as THREE from "three"; +import { useThree } from "@react-three/fiber"; + +type VehicleUIProps = { + vehicleStatusSample: VehicleEventSchema[]; + setVehicleStatusSample: React.Dispatch< + React.SetStateAction + >; +}; + +const VehicleUI: React.FC = ({ + vehicleStatusSample, + setVehicleStatusSample, +}) => { + const { scene: startScene } = useGLTF(startPoint) as any; + const { scene: endScene } = useGLTF(startEnd) as any; + const { camera, gl, controls } = useThree(); + const { selectedEventSphere } = useSelectedEventSphere(); + + const startMarker = useRef(null); + const endMarker = useRef(null); + const hasInitialized = useRef(false); + + const [draggedMarker, setDraggedMarker] = useState<"start" | "end" | null>( + null + ); + const [dragOffset, setDragOffset] = useState(null); + const [isRotating, setIsRotating] = useState(false); + + const raycaster = useRef(new THREE.Raycaster()); + const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Y = 0 plane + const mouse = useRef(new THREE.Vector2()); + const prevMousePos = useRef({ x: 0, y: 0 }); + + // Initialize start/end markers + useEffect(() => { + if ( + selectedEventSphere && + startMarker.current && + endMarker.current && + !hasInitialized.current + ) { + startMarker.current.clear(); + endMarker.current.clear(); + + const startClone = startScene.clone(); + const endClone = endScene.clone(); + + startClone.name = "start-marker"; + endClone.name = "end-marker"; + + startClone.traverse((child: any) => { + if (child.isMesh && child.name.toLowerCase().includes("handle")) { + child.name = "handle"; + } + }); + endClone.traverse((child: any) => { + if (child.isMesh && child.name.toLowerCase().includes("handle")) { + child.name = "handle"; + } + }); + + startMarker.current.add(startClone); + endMarker.current.add(endClone); + + hasInitialized.current = true; + } + }, [selectedEventSphere, startScene, endScene]); + + // Position start/end markers + useEffect(() => { + if (!selectedEventSphere || !startMarker.current || !endMarker.current) + return; + + const selectedVehicle = vehicleStatusSample.find( + (vehicle) => vehicle.modelUuid === selectedEventSphere.userData.modelUuid + ); + + if (selectedVehicle?.point?.action) { + const { pickUpPoint, unLoadPoint } = selectedVehicle.point.action; + + // Update start marker position + if (pickUpPoint) { + const localPos = new THREE.Vector3( + pickUpPoint.x, + pickUpPoint.y, + pickUpPoint.z + ); + const worldPos = selectedEventSphere.localToWorld(localPos); + worldPos.y = 0; // Force y to 0 + startMarker.current.position.copy(worldPos); + } else { + const defaultLocal = new THREE.Vector3(0, 0, 1.5); + const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); + defaultWorld.y = 0; // Force y to 0 + startMarker.current.position.copy(defaultWorld); + } + + // Update end marker position + if (unLoadPoint) { + const localPos = new THREE.Vector3( + unLoadPoint.x, + unLoadPoint.y, + unLoadPoint.z + ); + const worldPos = selectedEventSphere.localToWorld(localPos); + worldPos.y = 0; // Force y to 0 + endMarker.current.position.copy(worldPos); + } else { + const defaultLocal = new THREE.Vector3(0, 0, -1.5); + const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); + defaultWorld.y = 0; // Force y to 0 + endMarker.current.position.copy(defaultWorld); + } + } + }, [selectedEventSphere, vehicleStatusSample]); + + // Handle dragging and rotation + const handlePointerDown = (e: any, markerType: "start" | "end") => { + if (!selectedEventSphere) return; + + if (e.object.name === "handle") { + setIsRotating(true); + prevMousePos.current = { x: e.clientX, y: e.clientY }; + if (controls) (controls as any).enabled = false; + e.stopPropagation(); + setDraggedMarker(markerType); + return; + } + + setDraggedMarker(markerType); + if (controls) (controls as any).enabled = false; + + const marker = + markerType === "start" ? startMarker.current : endMarker.current; + if (!marker) return; + + mouse.current.x = (e.clientX / gl.domElement.clientWidth) * 2 - 1; + mouse.current.y = -(e.clientY / gl.domElement.clientHeight) * 2 + 1; + + raycaster.current.setFromCamera(mouse.current, camera); + + const intersectPoint = new THREE.Vector3(); + raycaster.current.ray.intersectPlane(plane.current, intersectPoint); + + const offset = new THREE.Vector3().subVectors( + marker.position, + intersectPoint + ); + setDragOffset(offset); + }; + + const handlePointerMove = (e: PointerEvent) => { + if (!selectedEventSphere) return; + + if (isRotating) { + const deltaX = e.clientX - prevMousePos.current.x; + prevMousePos.current = { x: e.clientX, y: e.clientY }; + + const rotationSpeed = 0.01; + const marker = + draggedMarker === "start" ? startMarker.current : endMarker.current; + + if (marker) { + marker.rotation.y -= deltaX * rotationSpeed; + } + return; + } + + if (!draggedMarker || !dragOffset) return; + + mouse.current.x = (e.clientX / gl.domElement.clientWidth) * 2 - 1; + mouse.current.y = -(e.clientY / gl.domElement.clientHeight) * 2 + 1; + + raycaster.current.setFromCamera(mouse.current, camera); + + const intersectPoint = new THREE.Vector3(); + raycaster.current.ray.intersectPlane(plane.current, intersectPoint); + + if (!intersectPoint) return; + + const newPos = { + x: intersectPoint.x + dragOffset.x, + y: 0, + z: intersectPoint.z + dragOffset.z, + }; + + if (draggedMarker === "start" && startMarker.current) { + startMarker.current.position.set(newPos.x, newPos.y, newPos.z); + } else if (draggedMarker === "end" && endMarker.current) { + endMarker.current.position.set(newPos.x, newPos.y, newPos.z); + } + }; + + const handlePointerUp = () => { + if (isRotating) { + setIsRotating(false); + if (controls) (controls as any).enabled = true; + return; + } + + if (!selectedEventSphere || !draggedMarker || !dragOffset) { + if (controls) (controls as any).enabled = true; + return; + } + + if (controls) (controls as any).enabled = true; + + const marker = + draggedMarker === "start" ? startMarker.current : endMarker.current; + if (!marker) return; + + const worldPos = marker.position.clone(); + const localPos = selectedEventSphere.worldToLocal(worldPos); + + // Direct update (no snapping, ground level forced at y = 0) + const updatedLocalPos = { x: localPos.x, y: 0, z: localPos.z }; + + setVehicleStatusSample((prev) => + prev.map((vehicle) => { + if ( + vehicle.modelUuid === selectedEventSphere.userData.modelUuid && + selectedEventSphere + ) { + const updatedVehicle = { + ...vehicle, + point: { + ...vehicle.point, + action: { + ...vehicle.point?.action, + ...(draggedMarker === "start" + ? { pickUpPoint: updatedLocalPos } + : { unLoadPoint: updatedLocalPos }), + }, + }, + }; + return updatedVehicle; + } + return vehicle; + }) + ); + + setDraggedMarker(null); + setDragOffset(null); + }; + + useEffect(() => { + window.addEventListener("pointermove", handlePointerMove); + window.addEventListener("pointerup", handlePointerUp); + + return () => { + window.removeEventListener("pointermove", handlePointerMove); + window.removeEventListener("pointerup", handlePointerUp); + }; + }, [draggedMarker, dragOffset, isRotating]); + + if (!selectedEventSphere) { + hasInitialized.current = false; + return null; + } + + return ( + + handlePointerDown(e, "start")} + /> + handlePointerDown(e, "end")} + /> + + ); +}; + +export default VehicleUI; diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx index f0b4d17..65376f2 100644 --- a/app/src/modules/simulation/vehicle/vehicles.tsx +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -1,162 +1,140 @@ -import React, { useEffect } from 'react' -import VehicleInstances from './instances/vehicleInstances'; -import { useVehicleStore } from '../../../store/simulation/useVehicleStore'; -import { useFloorItems } from '../../../store/store'; - +import React, { useEffect, useState } from "react"; +import VehicleInstances from "./instances/vehicleInstances"; +import { useVehicleStore } from "../../../store/simulation/useVehicleStore"; +import { useFloorItems } from "../../../store/store"; +import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore"; +import VehicleUI from "../ui/vehicle/vehicleUI"; function Vehicles() { + const { vehicles, addVehicle } = useVehicleStore(); + const { selectedEventSphere } = useSelectedEventSphere(); - const { vehicles, addVehicle } = useVehicleStore(); + const { floorItems } = useFloorItems(); - const { floorItems } = useFloorItems(); - - const vehicleStatusSample: VehicleEventSchema[] = [ - { - modelUuid: "9356f710-4727-4b50-bdb2-9c1e747ecc74", - modelName: "AGV", - position: [97.9252965204558, 0, 37.96138815638661], - rotation: [0, 0, 0], - state: "idle", - type: "vehicle", - speed: 2.5, - point: { - uuid: "point-789", - position: [0, 1, 0], - rotation: [0, 0, 0], - action: { - actionUuid: "action-456", - actionName: "Deliver to Zone A", - actionType: "travel", - unLoadDuration: 10, - loadCapacity: 2, - pickUpPoint: { x: 98.71483985219794, y: 0, z: 28.66321267938962 }, - unLoadPoint: { x: 105.71483985219794, y: 0, z: 28.66321267938962 }, - triggers: [ - { - triggerUuid: "trig-001", - triggerName: "Start Travel", - triggerType: "onComplete", - delay: 0, - triggeredAsset: { - triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, - triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" }, - triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" } - } - }, - { - triggerUuid: "trig-002", - triggerName: "Complete Travel", - triggerType: "onComplete", - delay: 2, - triggeredAsset: null - } - ] - } - } + const [vehicleStatusSample, setVehicleStatusSample] = useState< + VehicleEventSchema[] + >([ + + { + modelUuid: "68f8dc55-7802-47fe-aa1c-eade54b4320a", + modelName: "AGV", + position: [89.61609306554463, 0, 33.634136622267356], + rotation: [0, 0, 0], + state: "idle", + type: "vehicle", + speed: 2.5, + point: { + uuid: "point-789", + position: [0, 1, 0], + rotation: [0, 0, 0], + action: { + actionUuid: "action-456", + actionName: "Deliver to Zone A", + actionType: "travel", + unLoadDuration: 10, + loadCapacity: 2, + pickUpPoint: null, + unLoadPoint: null, + triggers: [ + { + triggerUuid: "trig-001", + triggerName: "Start Travel", + triggerType: "onStart", + delay: 0, + triggeredAsset: { + triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, + triggeredPoint: { + pointName: "Pickup Arm Point", + pointUuid: "arm-point-01", + }, + triggeredAction: { + actionName: "Grab Widget", + actionUuid: "grab-001", + }, + }, + }, + { + triggerUuid: "trig-002", + triggerName: "Complete Travel", + triggerType: "onComplete", + delay: 2, + triggeredAsset: null, + }, + ], }, - { - modelUuid: "b06960bb-3d2e-41f7-a646-335f389c68b4", - modelName: "AGV", - position: [89.61609306554463, 0, 33.634136622267356], - rotation: [0, 0, 0], - state: "idle", - type: "vehicle", - speed: 2.5, - point: { - uuid: "point-789", - position: [0, 1, 0], - rotation: [0, 0, 0], - action: { - actionUuid: "action-456", - actionName: "Deliver to Zone A", - actionType: "travel", - unLoadDuration: 10, - loadCapacity: 2, - pickUpPoint: { x: 90, y: 0, z: 28 }, - unLoadPoint: { x: 20, y: 0, z: 10 }, - triggers: [ - { - triggerUuid: "trig-001", - triggerName: "Start Travel", - triggerType: "onStart", - delay: 0, - triggeredAsset: { - triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, - triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" }, - triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" } - } - }, - { - triggerUuid: "trig-002", - triggerName: "Complete Travel", - triggerType: "onComplete", - delay: 2, - triggeredAsset: null - } - ] - } - } - }, { - modelUuid: "e729a4f1-11d2-4778-8d6a-468f1b4f6b79", - modelName: "forklift", - position: [98.85729337188162, 0, 38.36616546567653], - rotation: [0, 0, 0], - state: "idle", - type: "vehicle", - speed: 2.5, - point: { - uuid: "point-789", - position: [0, 1, 0], - rotation: [0, 0, 0], - action: { - actionUuid: "action-456", - actionName: "Deliver to Zone A", - actionType: "travel", - unLoadDuration: 15, - loadCapacity: 5, - pickUpPoint: { x: 98.71483985219794, y: 0, z: 28.66321267938962 }, - unLoadPoint: { x: 20, y: 0, z: 10 }, - triggers: [ - { - triggerUuid: "trig-001", - triggerName: "Start Travel", - triggerType: "onStart", - delay: 0, - triggeredAsset: { - triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, - triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" }, - triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" } - } - }, - { - triggerUuid: "trig-002", - triggerName: "Complete Travel", - triggerType: "onComplete", - delay: 2, - triggeredAsset: null - } - ] - } - } - } - ]; + }, + }, + { + modelUuid: "3a8f6da6-da57-4ef5-91e3-b8daf89e5753", + modelName: "forklift", + position: [98.85729337188162, 0, 38.36616546567653], + rotation: [0, 0, 0], + state: "idle", + type: "vehicle", + speed: 2.5, + point: { + uuid: "point-789", + position: [0, 1, 0], + rotation: [0, 0, 0], + action: { + actionUuid: "action-456", + actionName: "Deliver to Zone A", + actionType: "travel", + unLoadDuration: 15, + loadCapacity: 5, + pickUpPoint: null, + unLoadPoint: null, + triggers: [ + { + triggerUuid: "trig-001", + triggerName: "Start Travel", + triggerType: "onStart", + delay: 0, + triggeredAsset: { + triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, + triggeredPoint: { + pointName: "Pickup Arm Point", + pointUuid: "arm-point-01", + }, + triggeredAction: { + actionName: "Grab Widget", + actionUuid: "grab-001", + }, + }, + }, + { + triggerUuid: "trig-002", + triggerName: "Complete Travel", + triggerType: "onComplete", + delay: 2, + triggeredAsset: null, + }, + ], + }, + }, + }, + ]); + // useEffect(()) + console.log("vehicleStatusSample", vehicleStatusSample); + useEffect(() => { + addVehicle("123", vehicleStatusSample[0]); + // addVehicle('123', vehicleStatusSample[1]); + // addVehicle('123', vehicleStatusSample[2]); + }, []); + useEffect(() => {}, [vehicles]); - useEffect(() => { - addVehicle('123', vehicleStatusSample[0]); - // addVehicle('123', vehicleStatusSample[1]); - // addVehicle('123', vehicleStatusSample[2]); - }, []) - - useEffect(() => { - console.log('vehicles: ', vehicles); - }, [vehicles]) - - - return ( - <> - - - ) + return ( + <> + + + + ); } -export default Vehicles; \ No newline at end of file +export default Vehicles; + + + From 3e1fc1c91909d5c81a099233f6a91a5f92795623 Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Tue, 29 Apr 2025 10:20:58 +0530 Subject: [PATCH 03/14] added pause-play-rest-exit functionality --- .../instances/animator/vehicleAnimator.tsx | 424 ++++++++---------- .../instances/instance/vehicleInstance.tsx | 239 +++++----- .../modules/simulation/vehicle/vehicles.tsx | 3 +- 3 files changed, 300 insertions(+), 366 deletions(-) diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index 1d21468..6e2093e 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -8,270 +8,212 @@ import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore import useModuleStore from '../../../../../store/useModuleStore'; interface VehicleAnimatorProps { - path: [number, number, number][]; - handleCallBack: () => void; - reset: () => void; - currentPhase: string; - agvUuid: number; - agvDetail: any; + path: [number, number, number][]; + handleCallBack: () => void; + reset: () => void; + currentPhase: string; + agvUuid: number; + agvDetail: any; } function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset }: VehicleAnimatorProps) { - const { decrementVehicleLoad, vehicles } = useVehicleStore(); - const { isPaused } = usePauseButtonStore(); - const { isPlaying, setIsPlaying } = usePlayButtonStore(); - const { activeModule } = useModuleStore(); - const { speed } = useAnimationPlaySpeed(); - const { isReset, setReset } = useResetButtonStore(); - const [restRotation, setRestingRotation] = useState(true); - const [progress, setProgress] = useState(0); - const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); - const { scene } = useThree(); - const progressRef = useRef(0); - const movingForward = useRef(true); - const completedRef = useRef(false); - let startTime: number; - let pausedTime: number; - let fixedInterval: number; - let coveredDistance = progressRef.current; - let accumulatedDistance = 0; - let index = 0; - const isPausedRef = useRef(false); - const pauseTimeRef = useRef(null); + const { decrementVehicleLoad } = useVehicleStore(); + const { isPaused } = usePauseButtonStore(); + const { isPlaying } = usePlayButtonStore(); + const { speed } = useAnimationPlaySpeed(); + const { isReset, setReset } = useResetButtonStore(); + const [restRotation, setRestingRotation] = useState(true); + const [progress, setProgress] = useState(0); + const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); + const { scene } = useThree(); + const progressRef = useRef(0); + const movingForward = useRef(true); + const completedRef = useRef(false); + let startTime: number; + let fixedInterval: number; + let coveredDistance = progressRef.current; + const isPausedRef = useRef(false); + const pauseTimeRef = useRef(null); - useEffect(() => { - if (currentPhase === 'stationed-pickup' && path.length > 0) { - setCurrentPath(path); - } else if (currentPhase === 'pickup-drop' && path.length > 0) { - setCurrentPath(path); - } else if (currentPhase === 'drop-pickup' && path.length > 0) { - setCurrentPath(path); - } - }, [currentPhase, path]); - - useEffect(() => { - setProgress(0); - completedRef.current = false; - }, [currentPath]); - useEffect(() => { - if (isReset) { - reset(); - setCurrentPath([]); - setProgress(0); - completedRef.current = false; - movingForward.current = true; - progressRef.current = 0; - startTime = 0; - coveredDistance = 0; - setReset(false); - setRestingRotation(true); - decrementVehicleLoad(agvDetail.modelUuid, 0); - const object = scene.getObjectByProperty('uuid', agvUuid); - if (object) { - object.position.set(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]); - let objectRotation = agvDetail.point.rotation - object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); - } - } - }, [isReset]) - - useEffect(() => { - console.log('isPlaying: ', isPlaying); - if (!isPlaying) { - reset(); - setCurrentPath([]); - setProgress(0); - completedRef.current = false; - movingForward.current = true; - progressRef.current = 0; - startTime = 0; - coveredDistance = 0; - setReset(false); - setRestingRotation(true); - decrementVehicleLoad(agvDetail.modelUuid, 0); - const object = scene.getObjectByProperty('uuid', agvUuid); - if (object) { - object.position.set(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]) - let objectRotation = agvDetail.point.rotation - object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); - } - } - }, [isPlaying]) - - useFrame((_, delta) => { - const object = scene.getObjectByProperty('uuid', agvUuid); - if (!object || currentPath.length < 2) return; - if (isPaused) return; - - let totalDistance = 0; - const distances = []; - - for (let i = 0; i < currentPath.length - 1; i++) { - const start = new THREE.Vector3(...currentPath[i]); - const end = new THREE.Vector3(...currentPath[i + 1]); - const segmentDistance = start.distanceTo(end); - distances.push(segmentDistance); - totalDistance += segmentDistance; - } - - - while ( - index < distances.length && - coveredDistance > accumulatedDistance + distances[index] - ) { - accumulatedDistance += distances[index]; - index++; - } - - if (index < distances.length) { - const start = new THREE.Vector3(...currentPath[index]); - const end = new THREE.Vector3(...currentPath[index + 1]); - const segmentDistance = distances[index]; - - const currentDirection = new THREE.Vector3().subVectors(end, start).normalize(); - const targetAngle = Math.atan2(currentDirection.x, currentDirection.z); - - const rotationSpeed = speed; - const currentAngle = object.rotation.y; - - let angleDifference = targetAngle - currentAngle; - if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI; - if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI; - - const maxRotationStep = rotationSpeed * delta; - object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); - const isAligned = Math.abs(angleDifference) < 0.01; - - if (isAligned) { - progressRef.current += delta * (speed * agvDetail.speed); - coveredDistance = progressRef.current; - - const t = (coveredDistance - accumulatedDistance) / segmentDistance; - const position = start.clone().lerp(end, t); - object.position.copy(position); - } - } - - if (progressRef.current >= totalDistance) { - if (restRotation) { - const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0)); - object.quaternion.slerp(targetQuaternion, delta * 2); - const angleDiff = object.quaternion.angleTo(targetQuaternion); - if (angleDiff < 0.01) { - let objectRotation = agvDetail.point.rotation - object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); - setRestingRotation(false); + useEffect(() => { + if (currentPhase === 'stationed-pickup' && path.length > 0) { + setCurrentPath(path); + } else if (currentPhase === 'pickup-drop' && path.length > 0) { + setCurrentPath(path); + } else if (currentPhase === 'drop-pickup' && path.length > 0) { + setCurrentPath(path); } - return; - } - } + }, [currentPhase, path]); - if (progressRef.current >= totalDistance) { - setRestingRotation(true); - progressRef.current = 0; - movingForward.current = !movingForward.current; - setCurrentPath([]); - handleCallBack(); - if (currentPhase === 'pickup-drop') { - requestAnimationFrame(firstFrame); - } - } - }); - let pauseTime: number = 0; + useEffect(() => { + setProgress(0); + completedRef.current = false; + }, [currentPath]); + + useEffect(() => { + if (isReset || !isPlaying) { + reset(); + setCurrentPath([]); + setProgress(0); + completedRef.current = false; + movingForward.current = true; + progressRef.current = 0; + startTime = 0; + coveredDistance = 0; + setReset(false); + setRestingRotation(true); + decrementVehicleLoad(agvDetail.modelUuid, 0); + const object = scene.getObjectByProperty('uuid', agvUuid); + if (object) { + object.position.set(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]); + let objectRotation = agvDetail.point.rotation + object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); + } + } + }, [isReset, isPlaying]) + useFrame((_, delta) => { + const object = scene.getObjectByProperty('uuid', agvUuid); + if (!object || currentPath.length < 2) return; + if (isPaused) return; - useEffect(() => { - // Update the pause state in the ref - isPausedRef.current = isPaused; - }, [isPaused]); - function firstFrame() { - const unLoadDuration = agvDetail.point.action.unLoadDuration; - const droppedMaterial = agvDetail.currentLoad; - fixedInterval = ((unLoadDuration / droppedMaterial) * 1000) / speed; - // fixedInterval = (unLoadDuration / droppedMaterial) * 1000; - startTime = performance.now(); - step(droppedMaterial); - } + let totalDistance = 0; + const distances = []; + let accumulatedDistance = 0; + let index = 0; - function step(droppedMaterial: number) { - if (isPausedRef.current) { - // Handle pause logic - if (!pauseTimeRef.current) { - pauseTimeRef.current = performance.now(); // Set pause time only once - } - requestAnimationFrame(() => step(droppedMaterial)); // Continue calling step during pause - return; - } + for (let i = 0; i < currentPath.length - 1; i++) { + const start = new THREE.Vector3(...currentPath[i]); + const end = new THREE.Vector3(...currentPath[i + 1]); + const segmentDistance = start.distanceTo(end); + distances.push(segmentDistance); + totalDistance += segmentDistance; + } - if (pauseTimeRef.current) { - // Adjust start time after resuming from pause - const pauseDuration = performance.now() - pauseTimeRef.current; - startTime += pauseDuration; - pauseTimeRef.current = null; // Clear pause time - } + while (index < distances.length && coveredDistance > accumulatedDistance + distances[index]) { + accumulatedDistance += distances[index]; + index++; + } - const elapsedTime = performance.now() - startTime; // Calculate elapsed time + if (index < distances.length) { + const start = new THREE.Vector3(...currentPath[index]); + const end = new THREE.Vector3(...currentPath[index + 1]); + const segmentDistance = distances[index]; - if (elapsedTime >= fixedInterval) { + const currentDirection = new THREE.Vector3().subVectors(end, start).normalize(); + const targetAngle = Math.atan2(currentDirection.x, currentDirection.z); + const rotationSpeed = speed; + const currentAngle = object.rotation.y; - let droppedMat = droppedMaterial - 1; - decrementVehicleLoad(agvDetail.modelUuid, 1); // Decrement vehicle load + let angleDifference = targetAngle - currentAngle; + if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI; + if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI; - if (droppedMat > 0) { - // Reset start time for the next step + const maxRotationStep = rotationSpeed * delta; + object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); + const isAligned = Math.abs(angleDifference) < 0.01; + + if (isAligned) { + progressRef.current += delta * (speed * agvDetail.speed); + coveredDistance = progressRef.current; + + const t = (coveredDistance - accumulatedDistance) / segmentDistance; + const position = start.clone().lerp(end, t); + object.position.copy(position); + } + } + + if (progressRef.current >= totalDistance) { + if (restRotation) { + const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0)); + object.quaternion.slerp(targetQuaternion, delta * 2); + const angleDiff = object.quaternion.angleTo(targetQuaternion); + if (angleDiff < 0.01) { + let objectRotation = agvDetail.point.rotation + object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); + setRestingRotation(false); + } + return; + } + } + + if (progressRef.current >= totalDistance) { + setRestingRotation(true); + progressRef.current = 0; + movingForward.current = !movingForward.current; + setCurrentPath([]); + handleCallBack(); + if (currentPhase === 'pickup-drop') { + requestAnimationFrame(firstFrame); + } + } + }); + + useEffect(() => { + isPausedRef.current = isPaused; + }, [isPaused]); + + function firstFrame() { + const droppedMaterial = agvDetail.currentLoad; startTime = performance.now(); - requestAnimationFrame(() => step(droppedMat)); // Continue with the next step - } else { - - return; // Exit when all materials are dropped - } - } else { - requestAnimationFrame(() => step(droppedMaterial)); // Continue animation + step(droppedMaterial); + } + + function step(droppedMaterial: number) { + if (isPausedRef.current) { + if (!pauseTimeRef.current) { + pauseTimeRef.current = performance.now(); + } + requestAnimationFrame(() => step(droppedMaterial)); + return; + } + + if (pauseTimeRef.current) { + const pauseDuration = performance.now() - pauseTimeRef.current; + startTime += pauseDuration; + pauseTimeRef.current = null; + } + + const elapsedTime = performance.now() - startTime; + const unLoadDuration = agvDetail.point.action.unLoadDuration; + fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / speed)); + + if (elapsedTime >= fixedInterval) { + console.log('elapsedTime: ', elapsedTime); + + let droppedMat = droppedMaterial - 1; + decrementVehicleLoad(agvDetail.modelUuid, 1); + + if (droppedMat > 0) { + startTime = performance.now(); + requestAnimationFrame(() => step(droppedMat)); + } else { + return; + } + } else { + requestAnimationFrame(() => step(droppedMaterial)); + } } - } - // function firstFrame() { - // const unLoadDuration = agvDetail.point.action.unLoadDuration; - // const droppedMaterial = agvDetail.currentLoad; - // fixedInterval = (unLoadDuration / droppedMaterial) * 1000; - // startTime = performance.now(); - // step(droppedMaterial); - // } - - // function step(droppedMaterial: number) { - // const elapsedTime = (performance.now() - startTime) * speed; - // if (elapsedTime >= fixedInterval) { - // - // - // let droppedMat = droppedMaterial - 1; - // decrementVehicleLoad(agvDetail.modelUuid, 1); - // if (droppedMat === 0) return; - // startTime = performance.now(); - // requestAnimationFrame(() => step(droppedMat)); - // } else { - // requestAnimationFrame(() => step(droppedMaterial)); - // } - // } - - return ( - <> - {currentPath.length > 0 && ( + return ( <> - - {currentPath.map((point, index) => ( - - - - - ))} + {currentPath.length > 0 && ( + <> + + {currentPath.map((point, index) => ( + + + + + ))} + + )} - )} - - ); + ); } export default VehicleAnimator; \ No newline at end of file diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index a78101e..3f692d9 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import VehicleAnimator from '../animator/vehicleAnimator'; import * as THREE from 'three'; import { NavMeshQuery } from '@recast-navigation/core'; @@ -7,138 +7,131 @@ import { usePlayButtonStore, useResetButtonStore } from '../../../../../store/us import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; function VehicleInstance({ agvDetail }: any) { - const { navMesh } = useNavMesh(); - const { isPlaying, setIsPlaying } = usePlayButtonStore(); - const { isReset } = useResetButtonStore(); - const { vehicles, setVehicleActive, setVehicleState, incrementVehicleLoad } = useVehicleStore(); - const [currentPhase, setCurrentPhase] = useState('stationed'); - const [path, setPath] = useState<[number, number, number][]>([]); + const { navMesh } = useNavMesh(); + const { isPlaying } = usePlayButtonStore(); + const { vehicles, setVehicleActive, setVehicleState, incrementVehicleLoad } = useVehicleStore(); + const [currentPhase, setCurrentPhase] = useState('stationed'); + const [path, setPath] = useState<[number, number, number][]>([]); + let isIncrememtable = useRef(true); - const computePath = useCallback( - (start: any, end: any) => { - try { - const navMeshQuery = new NavMeshQuery(navMesh); - const { path: segmentPath } = navMeshQuery.computePath(start, end); - return ( - segmentPath?.map(({ x, y, z }) => [x, y + 0.1, z] as [number, number, number]) || [] - ); - } catch { - return []; - } - }, - [navMesh] - ); + const computePath = useCallback( + (start: any, end: any) => { + try { + const navMeshQuery = new NavMeshQuery(navMesh); + const { path: segmentPath } = navMeshQuery.computePath(start, end); + return ( + segmentPath?.map(({ x, y, z }) => [x, y + 0.1, z] as [number, number, number]) || [] + ); + } catch { + return []; + } + }, + [navMesh] + ); - function vehicleStatus(modelId: string, status: string) { - // console.log(`AGV ${modelId}: ${status}`); - } - // Function to reset everything - function reset() { - setCurrentPhase('stationed'); - setVehicleActive(agvDetail.modelUuid, false); - setVehicleState(agvDetail.modelUuid, 'idle'); - setPath([]); - } + function vehicleStatus(modelId: string, status: string) { + console.log(`AGV ${modelId}: ${status}`); + } - // useEffect(() => { - // console.log('isReset: ', isReset); - // if (isReset) { - // reset(); - // } - // }, [isReset]); + // Function to reset everything + function reset() { + setCurrentPhase('stationed'); + setVehicleActive(agvDetail.modelUuid, false); + setVehicleState(agvDetail.modelUuid, 'idle'); + setPath([]); + } - - - useEffect(() => { - if (isPlaying) { - if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') { - const toPickupPath = computePath( - new THREE.Vector3(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]), - agvDetail.point.action.pickUpPoint - ); - setPath(toPickupPath); - setVehicleActive(agvDetail.modelUuid, true); - setVehicleState(agvDetail.modelUuid, 'running'); - setCurrentPhase('stationed-pickup'); - vehicleStatus(agvDetail.modelUuid, 'Started from station, heading to pickup'); - return; - } else if ( - !agvDetail.isActive && - agvDetail.state === 'idle' && - currentPhase === 'picking' - ) { - - setTimeout(() => { - incrementVehicleLoad(agvDetail.modelUuid, 2); - }, 5000); - - if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity) { - const toDrop = computePath( - agvDetail.point.action.pickUpPoint, - agvDetail.point.action.unLoadPoint - ); - setPath(toDrop); - setVehicleActive(agvDetail.modelUuid, true); - setVehicleState(agvDetail.modelUuid, 'running'); - setCurrentPhase('pickup-drop'); - vehicleStatus(agvDetail.modelUuid, 'Started from pickup point, heading to drop point'); + const increment = () => { + if (isIncrememtable.current) { + console.log('called'); + incrementVehicleLoad(agvDetail.modelUuid, 2); + isIncrememtable.current = false; } - } else if ( - !agvDetail.isActive && - agvDetail.state === 'idle' && - currentPhase === 'dropping' && - agvDetail.currentLoad === 0 - ) { - const dropToPickup = computePath( - agvDetail.point.action.unLoadPoint, - agvDetail.point.action.pickUpPoint - ); - setPath(dropToPickup); - setVehicleActive(agvDetail.modelUuid, true); - setVehicleState(agvDetail.modelUuid, 'running'); - setCurrentPhase('drop-pickup'); - vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point'); - } - } else { - reset() } - }, [vehicles, currentPhase, path, isPlaying, isReset]); - function handleCallBack() { - if (currentPhase === 'stationed-pickup') { - setVehicleActive(agvDetail.modelUuid, false); - setVehicleState(agvDetail.modelUuid, 'idle'); - setCurrentPhase('picking'); - vehicleStatus(agvDetail.modelUuid, 'Reached pickup point, waiting for material'); - setPath([]); - } else if (currentPhase === 'pickup-drop') { - setVehicleActive(agvDetail.modelUuid, false); - setVehicleState(agvDetail.modelUuid, 'idle'); - setCurrentPhase('dropping'); - vehicleStatus(agvDetail.modelUuid, 'Reached drop point'); - setPath([]); - } else if (currentPhase === 'drop-pickup') { - setVehicleActive(agvDetail.modelUuid, false); - setVehicleState(agvDetail.modelUuid, 'idle'); - setCurrentPhase('picking'); - setPath([]); - vehicleStatus(agvDetail.modelUuid, 'Reached pickup point again, cycle complete'); + useEffect(() => { + if (isPlaying) { + if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') { + const toPickupPath = computePath( + new THREE.Vector3(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]), + agvDetail.point.action.pickUpPoint + ); + setPath(toPickupPath); + setCurrentPhase('stationed-pickup'); + setVehicleState(agvDetail.modelUuid, 'running'); + setVehicleActive(agvDetail.modelUuid, true); + vehicleStatus(agvDetail.modelUuid, 'Started from station, heading to pickup'); + return; + } else if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'picking') { + + setTimeout(() => { + increment(); + }, 5000); + + if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity) { + const toDrop = computePath( + agvDetail.point.action.pickUpPoint, + agvDetail.point.action.unLoadPoint + ); + setPath(toDrop); + setCurrentPhase('pickup-drop'); + setVehicleState(agvDetail.modelUuid, 'running'); + setVehicleActive(agvDetail.modelUuid, true); + vehicleStatus(agvDetail.modelUuid, 'Started from pickup point, heading to drop point'); + } + } else if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'dropping' && agvDetail.currentLoad === 0) { + const dropToPickup = computePath( + agvDetail.point.action.unLoadPoint, + agvDetail.point.action.pickUpPoint + ); + setPath(dropToPickup); + setCurrentPhase('drop-pickup'); + setVehicleState(agvDetail.modelUuid, 'running'); + setVehicleActive(agvDetail.modelUuid, true); + vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point'); + + isIncrememtable.current = true; + } + } else { + reset() + } + }, [vehicles, currentPhase, path, isPlaying]); + + function handleCallBack() { + if (currentPhase === 'stationed-pickup') { + setCurrentPhase('picking'); + setVehicleState(agvDetail.modelUuid, 'idle'); + setVehicleActive(agvDetail.modelUuid, false); + vehicleStatus(agvDetail.modelUuid, 'Reached pickup point, waiting for material'); + setPath([]); + } else if (currentPhase === 'pickup-drop') { + setCurrentPhase('dropping'); + setVehicleState(agvDetail.modelUuid, 'idle'); + setVehicleActive(agvDetail.modelUuid, false); + vehicleStatus(agvDetail.modelUuid, 'Reached drop point'); + setPath([]); + } else if (currentPhase === 'drop-pickup') { + setCurrentPhase('picking'); + setVehicleState(agvDetail.modelUuid, 'idle'); + setVehicleActive(agvDetail.modelUuid, false); + setPath([]); + vehicleStatus(agvDetail.modelUuid, 'Reached pickup point again, cycle complete'); + } } - } - return ( - <> - - - ); + return ( + <> + + + ); } export default VehicleInstance; \ No newline at end of file diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx index 1b05888..7749bf8 100644 --- a/app/src/modules/simulation/vehicle/vehicles.tsx +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -97,7 +97,6 @@ function Vehicles() { } } }, - { modelUuid: "e729a4f1-11d2-4778-8d6a-468f1b4f6b79", modelName: "forklift", @@ -151,7 +150,7 @@ function Vehicles() { }, []) useEffect(() => { - console.log('vehicles: ', vehicles); + // console.log('vehicles: ', vehicles); }, [vehicles]) From fdf10589a7bac75fdf03f1b39aa71a54c7dacb8c Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Tue, 29 Apr 2025 12:56:20 +0530 Subject: [PATCH 04/14] Merged With AGV-UI --- .../simulation/ui/vehicle/vehicleUI.tsx | 99 +++--- .../instances/animator/vehicleAnimator.tsx | 25 +- .../instances/instance/vehicleInstance.tsx | 7 +- .../vehicle/instances/vehicleInstances.tsx | 22 +- .../modules/simulation/vehicle/vehicles.tsx | 317 +++++++++++------- 5 files changed, 287 insertions(+), 183 deletions(-) diff --git a/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx b/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx index f927c33..b26cfc9 100644 --- a/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx +++ b/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx @@ -5,37 +5,40 @@ import { useGLTF } from "@react-three/drei"; import { useSelectedEventSphere } from "../../../../store/simulation/useSimulationStore"; import * as THREE from "three"; import { useThree } from "@react-three/fiber"; +import { useVehicleStore } from "../../../../store/simulation/useVehicleStore"; type VehicleUIProps = { vehicleStatusSample: VehicleEventSchema[]; setVehicleStatusSample: React.Dispatch< React.SetStateAction >; + vehicle: any }; const VehicleUI: React.FC = ({ vehicleStatusSample, setVehicleStatusSample, + vehicle }) => { const { scene: startScene } = useGLTF(startPoint) as any; const { scene: endScene } = useGLTF(startEnd) as any; const { camera, gl, controls } = useThree(); const { selectedEventSphere } = useSelectedEventSphere(); - + const { updateVehicle } = useVehicleStore(); const startMarker = useRef(null); const endMarker = useRef(null); - const hasInitialized = useRef(false); + const hasInitialized = useRef(false); + const raycaster = useRef(new THREE.Raycaster()); + const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Y = 0 plane + const mouse = useRef(new THREE.Vector2()); + const prevMousePos = useRef({ x: 0, y: 0 }); const [draggedMarker, setDraggedMarker] = useState<"start" | "end" | null>( null ); const [dragOffset, setDragOffset] = useState(null); - const [isRotating, setIsRotating] = useState(false); + const [isRotating, setIsRotating] = useState(false); - const raycaster = useRef(new THREE.Raycaster()); - const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Y = 0 plane - const mouse = useRef(new THREE.Vector2()); - const prevMousePos = useRef({ x: 0, y: 0 }); // Initialize start/end markers useEffect(() => { @@ -91,9 +94,8 @@ const VehicleUI: React.FC = ({ pickUpPoint.y, pickUpPoint.z ); - const worldPos = selectedEventSphere.localToWorld(localPos); - worldPos.y = 0; // Force y to 0 - startMarker.current.position.copy(worldPos); + localPos.y = 0; // Force y to 0 + startMarker.current.position.copy(localPos); } else { const defaultLocal = new THREE.Vector3(0, 0, 1.5); const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); @@ -108,9 +110,10 @@ const VehicleUI: React.FC = ({ unLoadPoint.y, unLoadPoint.z ); - const worldPos = selectedEventSphere.localToWorld(localPos); - worldPos.y = 0; // Force y to 0 - endMarker.current.position.copy(worldPos); + + + localPos.y = 0; // Force y to 0 + endMarker.current.position.copy(localPos); } else { const defaultLocal = new THREE.Vector3(0, 0, -1.5); const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); @@ -190,6 +193,7 @@ const VehicleUI: React.FC = ({ z: intersectPoint.z + dragOffset.z, }; + if (draggedMarker === "start" && startMarker.current) { startMarker.current.position.set(newPos.x, newPos.y, newPos.z); } else if (draggedMarker === "end" && endMarker.current) { @@ -215,36 +219,51 @@ const VehicleUI: React.FC = ({ draggedMarker === "start" ? startMarker.current : endMarker.current; if (!marker) return; - const worldPos = marker.position.clone(); - const localPos = selectedEventSphere.worldToLocal(worldPos); + const worldPos = marker.position; - // Direct update (no snapping, ground level forced at y = 0) - const updatedLocalPos = { x: localPos.x, y: 0, z: localPos.z }; + const updatedLocalPos = { x: worldPos.x, y: 0, z: worldPos.z }; + console.log('updatedLocalPos: ', updatedLocalPos); - setVehicleStatusSample((prev) => - prev.map((vehicle) => { - if ( - vehicle.modelUuid === selectedEventSphere.userData.modelUuid && - selectedEventSphere - ) { - const updatedVehicle = { - ...vehicle, - point: { - ...vehicle.point, - action: { - ...vehicle.point?.action, - ...(draggedMarker === "start" - ? { pickUpPoint: updatedLocalPos } - : { unLoadPoint: updatedLocalPos }), - }, - }, - }; - return updatedVehicle; - } - return vehicle; - }) - ); + console.log('draggedMarker: ', draggedMarker); + // setVehicleStatusSample((prev) => + // prev.map((vehicle) => { + // if ( + // vehicle.modelUuid === selectedEventSphere.userData.modelUuid && + // selectedEventSphere + // ) { + // const updatedVehicle = { + // ...vehicle, + // point: { + // ...vehicle.point, + // action: { + // ...vehicle.point?.action, + // ...(draggedMarker === "start" + // ? { pickUpPoint: updatedLocalPos } + // : { unLoadPoint: updatedLocalPos }), + // }, + // }, + // }; + // return updatedVehicle; + // } + // return vehicle; + // }) + // ); + + updateVehicle(selectedEventSphere.userData.modelUuid, { + point: { + ...vehicle?.point, + action: { + ...vehicle?.point?.action, + ...(draggedMarker === "start" + ? { pickUpPoint: updatedLocalPos } + : { unLoadPoint: updatedLocalPos }), + }, + }, + }); + + + setDraggedMarker(null); setDragOffset(null); }; diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index 6e2093e..e4b2ef5 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -1,11 +1,9 @@ import { useEffect, useRef, useState } from 'react' import { useFrame, useThree } from '@react-three/fiber'; -import { useActiveTool, useFloorItems } from '../../../../../store/store'; import * as THREE from 'three'; import { Line } from '@react-three/drei'; import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; -import useModuleStore from '../../../../../store/useModuleStore'; interface VehicleAnimatorProps { path: [number, number, number][]; @@ -17,23 +15,24 @@ interface VehicleAnimatorProps { } function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset }: VehicleAnimatorProps) { + // console.log('path: ', path); const { decrementVehicleLoad } = useVehicleStore(); const { isPaused } = usePauseButtonStore(); const { isPlaying } = usePlayButtonStore(); const { speed } = useAnimationPlaySpeed(); const { isReset, setReset } = useResetButtonStore(); - const [restRotation, setRestingRotation] = useState(true); - const [progress, setProgress] = useState(0); - const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); - const { scene } = useThree(); const progressRef = useRef(0); const movingForward = useRef(true); const completedRef = useRef(false); + const isPausedRef = useRef(false); + const pauseTimeRef = useRef(null); + const [restRotation, setRestingRotation] = useState(true); + const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); + const [progress, setProgress] = useState(0); + const { scene } = useThree(); let startTime: number; let fixedInterval: number; let coveredDistance = progressRef.current; - const isPausedRef = useRef(false); - const pauseTimeRef = useRef(null); useEffect(() => { @@ -73,6 +72,9 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai } }, [isReset, isPlaying]) + useEffect(() => { + isPausedRef.current = isPaused; + }, [isPaused]); useFrame((_, delta) => { const object = scene.getObjectByProperty('uuid', agvUuid); @@ -152,10 +154,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai } }); - useEffect(() => { - isPausedRef.current = isPaused; - }, [isPaused]); - function firstFrame() { const droppedMaterial = agvDetail.currentLoad; startTime = performance.now(); @@ -182,11 +180,8 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / speed)); if (elapsedTime >= fixedInterval) { - console.log('elapsedTime: ', elapsedTime); - let droppedMat = droppedMaterial - 1; decrementVehicleLoad(agvDetail.modelUuid, 1); - if (droppedMat > 0) { startTime = performance.now(); requestAnimationFrame(() => step(droppedMat)); diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index 3f692d9..570c137 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -3,7 +3,7 @@ import VehicleAnimator from '../animator/vehicleAnimator'; import * as THREE from 'three'; import { NavMeshQuery } from '@recast-navigation/core'; import { useNavMesh } from '../../../../../store/store'; -import { usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; +import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; function VehicleInstance({ agvDetail }: any) { @@ -12,7 +12,7 @@ function VehicleInstance({ agvDetail }: any) { const { vehicles, setVehicleActive, setVehicleState, incrementVehicleLoad } = useVehicleStore(); const [currentPhase, setCurrentPhase] = useState('stationed'); const [path, setPath] = useState<[number, number, number][]>([]); - let isIncrememtable = useRef(true); + let isIncrememtable = useRef(true); const computePath = useCallback( (start: any, end: any) => { @@ -20,7 +20,7 @@ function VehicleInstance({ agvDetail }: any) { const navMeshQuery = new NavMeshQuery(navMesh); const { path: segmentPath } = navMeshQuery.computePath(start, end); return ( - segmentPath?.map(({ x, y, z }) => [x, y + 0.1, z] as [number, number, number]) || [] + segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [] ); } catch { return []; @@ -41,7 +41,6 @@ function VehicleInstance({ agvDetail }: any) { setPath([]); } - const increment = () => { if (isIncrememtable.current) { console.log('called'); diff --git a/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx b/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx index 2a0070b..aa482c0 100644 --- a/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx +++ b/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx @@ -1,14 +1,32 @@ import React from 'react' import VehicleInstance from './instance/vehicleInstance' import { useVehicleStore } from '../../../../store/simulation/useVehicleStore' +import VehicleUI from '../../ui/vehicle/vehicleUI'; +type VehicleUIProps = { + vehicleStatusSample: VehicleEventSchema[]; + setVehicleStatusSample: React.Dispatch< + React.SetStateAction + >; +}; +const VehicleInstances: React.FC = ({ + vehicleStatusSample, + setVehicleStatusSample, +}) => { -function VehicleInstances() { const { vehicles } = useVehicleStore(); + return ( <> {vehicles.map((val: any, i: any) => - + <> + + + )} diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx index 65376f2..3b811b3 100644 --- a/app/src/modules/simulation/vehicle/vehicles.tsx +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -5,133 +5,206 @@ import { useFloorItems } from "../../../store/store"; import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore"; import VehicleUI from "../ui/vehicle/vehicleUI"; function Vehicles() { - const { vehicles, addVehicle } = useVehicleStore(); - const { selectedEventSphere } = useSelectedEventSphere(); - const { floorItems } = useFloorItems(); + const { vehicles, addVehicle } = useVehicleStore(); - const [vehicleStatusSample, setVehicleStatusSample] = useState< - VehicleEventSchema[] - >([ - - { - modelUuid: "68f8dc55-7802-47fe-aa1c-eade54b4320a", - modelName: "AGV", - position: [89.61609306554463, 0, 33.634136622267356], - rotation: [0, 0, 0], - state: "idle", - type: "vehicle", - speed: 2.5, - point: { - uuid: "point-789", - position: [0, 1, 0], - rotation: [0, 0, 0], - action: { - actionUuid: "action-456", - actionName: "Deliver to Zone A", - actionType: "travel", - unLoadDuration: 10, - loadCapacity: 2, - pickUpPoint: null, - unLoadPoint: null, - triggers: [ - { - triggerUuid: "trig-001", - triggerName: "Start Travel", - triggerType: "onStart", - delay: 0, - triggeredAsset: { - triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, - triggeredPoint: { - pointName: "Pickup Arm Point", - pointUuid: "arm-point-01", - }, - triggeredAction: { - actionName: "Grab Widget", - actionUuid: "grab-001", - }, - }, - }, - { - triggerUuid: "trig-002", - triggerName: "Complete Travel", - triggerType: "onComplete", - delay: 2, - triggeredAsset: null, - }, - ], + const { floorItems } = useFloorItems() + + const [vehicleStatusSample, setVehicleStatusSample] = useState< + VehicleEventSchema[] + >([ + { + modelUuid: "9356f710-4727-4b50-bdb2-9c1e747ecc74", + modelName: "AGV", + position: [97.9252965204558, 0, 37.96138815638661], + rotation: [0, 0, 0], + state: "idle", + type: "vehicle", + speed: 2.5, + point: { + uuid: "point-789", + position: [0, 1, 0], + rotation: [0, 0, 0], + action: { + actionUuid: "action-456", + actionName: "Deliver to Zone A", + actionType: "travel", + unLoadDuration: 10, + loadCapacity: 2, + pickUpPoint: { x: 98.71483985219794, y: 0, z: 28.66321267938962 }, + unLoadPoint: { x: 105.71483985219794, y: 0, z: 28.66321267938962 }, + triggers: [ + { + triggerUuid: "trig-001", + triggerName: "Start Travel", + triggerType: "onComplete", + delay: 0, + triggeredAsset: { + triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, + triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" }, + triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" } + } + }, + { + triggerUuid: "trig-002", + triggerName: "Complete Travel", + triggerType: "onComplete", + delay: 2, + triggeredAsset: null + } + ] + } + } }, - }, - }, - { - modelUuid: "3a8f6da6-da57-4ef5-91e3-b8daf89e5753", - modelName: "forklift", - position: [98.85729337188162, 0, 38.36616546567653], - rotation: [0, 0, 0], - state: "idle", - type: "vehicle", - speed: 2.5, - point: { - uuid: "point-789", - position: [0, 1, 0], - rotation: [0, 0, 0], - action: { - actionUuid: "action-456", - actionName: "Deliver to Zone A", - actionType: "travel", - unLoadDuration: 15, - loadCapacity: 5, - pickUpPoint: null, - unLoadPoint: null, - triggers: [ - { - triggerUuid: "trig-001", - triggerName: "Start Travel", - triggerType: "onStart", - delay: 0, - triggeredAsset: { - triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, - triggeredPoint: { - pointName: "Pickup Arm Point", - pointUuid: "arm-point-01", - }, - triggeredAction: { - actionName: "Grab Widget", - actionUuid: "grab-001", - }, - }, - }, - { - triggerUuid: "trig-002", - triggerName: "Complete Travel", - triggerType: "onComplete", - delay: 2, - triggeredAsset: null, - }, - ], + { + modelUuid: "b06960bb-3d2e-41f7-a646-335f389c68b4", + modelName: "AGV", + position: [89.61609306554463, 0, 33.634136622267356], + rotation: [0, 0, 0], + state: "idle", + type: "vehicle", + speed: 2.5, + point: { + uuid: "point-789", + position: [0, 1, 0], + rotation: [0, 0, 0], + action: { + actionUuid: "action-456", + actionName: "Deliver to Zone A", + actionType: "travel", + unLoadDuration: 10, + loadCapacity: 2, + pickUpPoint: null, + unLoadPoint: null, + triggers: [ + { + triggerUuid: "trig-001", + triggerName: "Start Travel", + triggerType: "onStart", + delay: 0, + triggeredAsset: { + triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, + triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" }, + triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" } + } + }, + { + triggerUuid: "trig-002", + triggerName: "Complete Travel", + triggerType: "onComplete", + delay: 2, + triggeredAsset: null + } + ] + } + } }, - }, - }, - ]); - // useEffect(()) - console.log("vehicleStatusSample", vehicleStatusSample); - useEffect(() => { - addVehicle("123", vehicleStatusSample[0]); - // addVehicle('123', vehicleStatusSample[1]); - // addVehicle('123', vehicleStatusSample[2]); - }, []); + { + modelUuid: "cd7d0584-0684-42b4-b051-9e882c1914aa", + modelName: "AGV", + position: [105.90938758014703, 0, 31.584209911095215], + rotation: [0, 0, 0], + state: "idle", + type: "vehicle", + speed: 2.5, + point: { + uuid: "point-789", + position: [0, 1, 0], + rotation: [0, 0, 0], + action: { + actionUuid: "action-456", + actionName: "Deliver to Zone A", + actionType: "travel", + unLoadDuration: 10, + loadCapacity: 2, + pickUpPoint: null, + unLoadPoint: null, + triggers: [ + { + triggerUuid: "trig-001", + triggerName: "Start Travel", + triggerType: "onStart", + delay: 0, + triggeredAsset: { + triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, + triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" }, + triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" } + } + }, + { + triggerUuid: "trig-002", + triggerName: "Complete Travel", + triggerType: "onComplete", + delay: 2, + triggeredAsset: null + } + ] + } + } + }, + // { + // modelUuid: "e729a4f1-11d2-4778-8d6a-468f1b4f6b79", + // modelName: "forklift", + // position: [98.85729337188162, 0, 38.36616546567653], + // rotation: [0, 0, 0], + // state: "idle", + // type: "vehicle", + // speed: 2.5, + // point: { + // uuid: "point-789", + // position: [0, 1, 0], + // rotation: [0, 0, 0], + // action: { + // actionUuid: "action-456", + // actionName: "Deliver to Zone A", + // actionType: "travel", + // unLoadDuration: 15, + // loadCapacity: 5, + // pickUpPoint: null, + // unLoadPoint: null, + // triggers: [ + // { + // triggerUuid: "trig-001", + // triggerName: "Start Travel", + // triggerType: "onStart", + // delay: 0, + // triggeredAsset: { + // triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, + // triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" }, + // triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" } + // } + // }, + // { + // triggerUuid: "trig-002", + // triggerName: "Complete Travel", + // triggerType: "onComplete", + // delay: 2, + // triggeredAsset: null + // } + // ] + // } + // } + // } + ]); + useEffect(() => { + console.log("vehicles", vehicles); + }, [vehicles]) + useEffect(() => { + addVehicle("123", vehicleStatusSample[0]); + addVehicle('123', vehicleStatusSample[1]); + addVehicle('123', vehicleStatusSample[2]); + }, []); - useEffect(() => {}, [vehicles]); - - return ( - <> - - - - ); + return ( + <> + + {/* */} + + ); } export default Vehicles; From 882c81a385928bc4c137ff535fa878d020a61196 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Tue, 29 Apr 2025 19:15:17 +0530 Subject: [PATCH 05/14] Refactor asset model handling and event data management - Removed redundant data structure in handleModelLoad function. - Introduced eventData object to encapsulate event-related information for different asset types (Conveyor, Vehicle, ArmBot, StaticMachine). - Updated socket emission to include complete data with eventData. - Enhanced copy-paste and duplication controls to maintain eventData integrity during object duplication. - Integrated event data updates in move and rotate controls to reflect changes in the simulation state. - Improved PointsCreator component to handle rotation for event groups. - Updated handleAddEventToProduct function to support event data management. - Enhanced product management to fetch existing products from the server and handle new product creation. - Added new types for eventData in worldTypes and simulationTypes for better type safety. - Refactored IndexedDB utility functions for cleaner code. --- .../eventProperties/EventProperties.tsx | 218 +++++----- .../mechanics/conveyorMechanics.tsx | 348 ++++++++-------- .../mechanics/machineMechanics.tsx | 201 +++++----- .../mechanics/roboticArmMechanics.tsx | 300 +++++++------- .../mechanics/storageMechanics.tsx | 187 +++++---- .../sidebarRight/simulation/Simulations.tsx | 346 ++++++++-------- .../IntialLoad/loadInitialFloorItems.ts | 375 ++++++------------ .../geomentries/assets/addAssetModel.ts | 105 +++-- .../builder/groups/floorItemsGroup.tsx | 1 + .../selectionControls/copyPasteControls.tsx | 46 ++- .../selectionControls/duplicationControls.tsx | 46 ++- .../selectionControls/moveControls.tsx | 25 +- .../selectionControls/rotateControls.tsx | 26 +- .../events/points/creator/pointsCreator.tsx | 12 +- .../functions/handleAddEventToProduct.ts | 42 +- .../modules/simulation/products/products.tsx | 33 +- app/src/modules/simulation/simulation.tsx | 4 +- .../triggers/connector/triggerConnector.tsx | 197 +++++++-- app/src/store/simulation/useProductStore.ts | 7 + app/src/types/simulationTypes.d.ts | 2 +- app/src/types/world/worldTypes.d.ts | 13 + app/src/utils/indexDB/idbUtils.ts | 54 +-- 22 files changed, 1379 insertions(+), 1209 deletions(-) diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx index 87d3bf6..4fa9105 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx @@ -1,9 +1,8 @@ import React, { useEffect, useState } from "react"; import { - useSelectedAsset, - useSelectedEventData, - useSelectedEventSphere, - useSelectedProduct, + useSelectedEventData, + useSelectedEventSphere, + useSelectedProduct, } from "../../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../../store/simulation/useProductStore"; import ConveyorMechanics from "./mechanics/conveyorMechanics"; @@ -13,120 +12,117 @@ import MachineMechanics from "./mechanics/machineMechanics"; import StorageMechanics from "./mechanics/storageMechanics"; import { AddIcon } from "../../../../icons/ExportCommonIcons"; import { handleAddEventToProduct } from "../../../../../modules/simulation/events/points/functions/handleAddEventToProduct"; +import { useEventsStore } from "../../../../../store/simulation/useEventsStore"; const EventProperties: React.FC = () => { - const { selectedEventData } = useSelectedEventData(); - const { getEventByModelUuid } = useProductStore(); - const { selectedProduct } = useSelectedProduct(); - const [currentEventData, setCurrentEventData] = useState( - null - ); - const [assetType, setAssetType] = useState(null); - const { products, addEvent } = useProductStore(); - const { selectedEventSphere } = useSelectedEventSphere(); + const { selectedEventData } = useSelectedEventData(); + const { getEventByModelUuid } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); + const [currentEventData, setCurrentEventData] = useState(null); + const [assetType, setAssetType] = useState(null); + const { products, addEvent } = useProductStore(); + const { selectedEventSphere } = useSelectedEventSphere(); - const { selectedAsset, clearSelectedAsset } = useSelectedAsset(); - useEffect(() => { - const event = getCurrentEventData(); - setCurrentEventData(event); + useEffect(() => { + const event = getCurrentEventData(); + setCurrentEventData(event); - const type = determineAssetType(event); - setAssetType(type); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedEventData, selectedProduct]); + const type = determineAssetType(event); + setAssetType(type); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedEventData, selectedProduct]); + + const getCurrentEventData = () => { + if (!selectedEventData?.data || !selectedProduct) return null; + return ( + getEventByModelUuid( + selectedProduct.productId, + selectedEventData.data.modelUuid + ) ?? null + ); + }; + + const determineAssetType = (event: EventsSchema | null) => { + if (!event) return null; + + switch (event.type) { + case "transfer": + return "conveyor"; + case "vehicle": + return "vehicle"; + case "roboticArm": + return "roboticArm"; + case "machine": + return "machine"; + case "storageUnit": + return "storageUnit"; + default: + return null; + } + }; - const getCurrentEventData = () => { - if (!selectedEventData?.data || !selectedProduct) return null; return ( - getEventByModelUuid( - selectedProduct.productId, - selectedEventData.data.modelUuid - ) ?? null +
+ {currentEventData && ( + <> +
+
+ {selectedEventData?.data.modelName} +
+
+ {assetType === "conveyor" && } + {assetType === "vehicle" && } + {assetType === "roboticArm" && } + {assetType === "machine" && } + {assetType === "storageUnit" && } + + )} + {!currentEventData && selectedEventSphere && ( +
+

+ Oops! It looks like this object doesn't have an + event assigned yet. To continue, please link it to one of the + products below. +

+ +
+

+ Here are some products you can add it to: +

+
    + {products.map((product) => ( +
  • + +
  • + ))} +
+
+
+ ) + } + {!selectedEventSphere && ( +
+

+ Oops! It looks like you haven't selected an event + point yet. Please select an event to view its properties. +

+
+ )} +
); - }; - - const determineAssetType = (event: EventsSchema | null) => { - if (!event) return null; - - switch (event.type) { - case "transfer": - return "conveyor"; - case "vehicle": - return "vehicle"; - case "roboticArm": - return "roboticArm"; - case "machine": - return "machine"; - case "storageUnit": - return "storageUnit"; - default: - return null; - } - }; - - return ( -
- {currentEventData && ( - <> -
-
- {selectedEventData?.data.modelName} -
-
- {assetType === "conveyor" && } - {assetType === "vehicle" && } - {assetType === "roboticArm" && } - {assetType === "machine" && } - {assetType === "storageUnit" && } - - )} - {!currentEventData && selectedEventSphere && ( -
-

- Oops! It looks like this object doesn't have an - event assigned yet. To continue, please link it to one of the - products below. -

- -
-

- Here are some products you can add it to: -

-
    - {products.map((product) => ( -
  • - -
  • - ))} -
-
-
- )} - {!selectedEventSphere && ( -
-

- Oops! It looks like you haven't selected an event - point yet. Please select an event to view its properties. -

-
- )} -
- ); }; export default EventProperties; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx index b370b3e..61c9c6c 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx @@ -8,217 +8,193 @@ import SwapAction from "../actions/SwapAction"; import SpawnAction from "../actions/SpawnAction"; import DefaultAction from "../actions/DefaultAction"; import Trigger from "../trigger/Trigger"; -import { - useSelectedEventData, - useSelectedProduct, -} from "../../../../../../store/simulation/useSimulationStore"; +import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import ActionsList from "../components/ActionsList"; function ConveyorMechanics() { - const [activeOption, setActiveOption] = useState< - "default" | "spawn" | "swap" | "delay" | "despawn" - >("default"); - const [selectedPointData, setSelectedPointData] = useState< - ConveyorPointSchema | undefined - >(); - const { selectedEventData } = useSelectedEventData(); - const { getPointByUuid, updateEvent, updateAction } = useProductStore(); - const { selectedProduct } = useSelectedProduct(); + const [activeOption, setActiveOption] = useState<"default" | "spawn" | "swap" | "delay" | "despawn">("default"); + const [selectedPointData, setSelectedPointData] = useState(); + const { selectedEventData } = useSelectedEventData(); + const { getPointByUuid, updateEvent, updateAction } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); - useEffect(() => { - if (selectedEventData) { - const point = getPointByUuid( - selectedProduct.productId, - selectedEventData?.data.modelUuid, - selectedEventData?.selectedPoint - ) as ConveyorPointSchema | undefined; - if (point && "action" in point) { - setSelectedPointData(point); - setActiveOption( - point.action.actionType as - | "default" - | "spawn" - | "swap" - | "delay" - | "despawn" - ); - } - } - }, [selectedProduct, selectedEventData, getPointByUuid]); + useEffect(() => { + if (selectedEventData) { + const point = getPointByUuid( + selectedProduct.productId, + selectedEventData?.data.modelUuid, + selectedEventData?.selectedPoint + ) as ConveyorPointSchema | undefined; + if (point && "action" in point) { + setSelectedPointData(point); + setActiveOption(point.action.actionType as | "default" | "spawn" | "swap" | "delay" | "despawn"); + } + } + }, [selectedProduct, selectedEventData, getPointByUuid]); - const handleSpeedChange = (value: string) => { - if (!selectedEventData) return; - updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { - speed: parseFloat(value), - }); - }; + const handleSpeedChange = (value: string) => { + if (!selectedEventData) return; + updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { + speed: parseFloat(value), + }); + }; - const handleActionTypeChange = (option: string) => { - if (!selectedEventData || !selectedPointData) return; - const validOption = option as - | "default" - | "spawn" - | "swap" - | "delay" - | "despawn"; - setActiveOption(validOption); + const handleActionTypeChange = (option: string) => { + if (!selectedEventData || !selectedPointData) return; + const validOption = option as | "default" | "spawn" | "swap" | "delay" | "despawn"; + setActiveOption(validOption); - updateAction(selectedPointData.action.actionUuid, { - actionType: validOption, - }); - }; + updateAction(selectedPointData.action.actionUuid, { + actionType: validOption, + }); + }; - const handleRenameAction = (newName: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { actionName: newName }); - }; + const handleRenameAction = (newName: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { actionName: newName }); + }; - const handleSpawnCountChange = (value: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { - spawnCount: value === "inherit" ? "inherit" : parseFloat(value), - }); - }; + const handleSpawnCountChange = (value: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { + spawnCount: value === "inherit" ? "inherit" : parseFloat(value), + }); + }; - const handleSpawnIntervalChange = (value: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { - spawnInterval: value === "inherit" ? "inherit" : parseFloat(value), - }); - }; + const handleSpawnIntervalChange = (value: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { + spawnInterval: value === "inherit" ? "inherit" : parseFloat(value), + }); + }; - const handleMaterialSelect = (material: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { material }); - }; + const handleMaterialSelect = (material: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { material }); + }; - const handleDelayChange = (value: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { - delay: value === "inherit" ? "inherit" : parseFloat(value), - }); - }; + const handleDelayChange = (value: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { + delay: value === "inherit" ? "inherit" : parseFloat(value), + }); + }; - const availableActions = { - defaultOption: "default", - options: ["default", "spawn", "swap", "delay", "despawn"], - }; + const availableActions = { + defaultOption: "default", + options: ["default", "spawn", "swap", "delay", "despawn"], + }; - // Get current values from store - const currentSpeed = - selectedEventData?.data.type === "transfer" - ? selectedEventData.data.speed.toString() - : "0.5"; + // Get current values from store + const currentSpeed = selectedEventData?.data.type === "transfer" + ? selectedEventData.data.speed.toString() + : "0.5"; - const currentActionName = selectedPointData - ? selectedPointData.action.actionName - : "Action Name"; + const currentActionName = selectedPointData + ? selectedPointData.action.actionName + : "Action Name"; - const currentMaterial = selectedPointData - ? selectedPointData.action.material - : "Default material"; + const currentMaterial = selectedPointData + ? selectedPointData.action.material + : "Default material"; - const currentSpawnCount = selectedPointData - ? selectedPointData.action.spawnCount?.toString() || "1" - : "1"; + const currentSpawnCount = selectedPointData + ? selectedPointData.action.spawnCount?.toString() || "1" + : "1"; - const currentSpawnInterval = selectedPointData - ? selectedPointData.action.spawnInterval?.toString() || "1" - : "1"; + const currentSpawnInterval = selectedPointData + ? selectedPointData.action.spawnInterval?.toString() || "1" + : "1"; - const currentDelay = selectedPointData - ? selectedPointData.action.delay?.toString() || "0" - : "0"; + const currentDelay = selectedPointData + ? selectedPointData.action.delay?.toString() || "0" + : "0"; - return ( - <> - {selectedEventData && ( + return ( <> -
-
-
- {}} - onChange={handleSpeedChange} - /> -
-
-
+ {selectedEventData && ( + <> +
+
+
+ { }} + onChange={handleSpeedChange} + /> +
+
+
- + -
-
- -
-
- - {activeOption === "default" && } - {activeOption === "spawn" && ( - - )} - {activeOption === "swap" && ( - - )} - {activeOption === "despawn" && } - {activeOption === "delay" && ( - - )} -
-
-
- -
+
+
+ +
+
+ + {activeOption === "default" && } + {activeOption === "spawn" && ( + + )} + {activeOption === "swap" && ( + + )} + {activeOption === "despawn" && } + {activeOption === "delay" && ( + + )} +
+
+
+ +
+ + )} - )} - - ); + ); } export default ConveyorMechanics; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx index fa2cfdf..8d128af 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx @@ -2,128 +2,121 @@ import { useEffect, useState } from "react"; import RenameInput from "../../../../../ui/inputs/RenameInput"; import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; import Trigger from "../trigger/Trigger"; -import { - useSelectedEventData, - useSelectedProduct, -} from "../../../../../../store/simulation/useSimulationStore"; +import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import ProcessAction from "../actions/ProcessAction"; import ActionsList from "../components/ActionsList"; function MachineMechanics() { - const [activeOption, setActiveOption] = useState<"default" | "process">( - "default" - ); - const [selectedPointData, setSelectedPointData] = useState< - MachinePointSchema | undefined - >(); - const { selectedEventData } = useSelectedEventData(); - const { getPointByUuid, updateAction } = useProductStore(); - const { selectedProduct } = useSelectedProduct(); + const [activeOption, setActiveOption] = useState<"default" | "process">("default"); + const [selectedPointData, setSelectedPointData] = useState(); + const { selectedEventData } = useSelectedEventData(); + const { getPointByUuid, updateAction } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); - useEffect(() => { - if (selectedEventData) { - const point = getPointByUuid( - selectedProduct.productId, - selectedEventData?.data.modelUuid, - selectedEventData?.selectedPoint - ) as MachinePointSchema | undefined; - if (point && "action" in point) { - setSelectedPointData(point); - setActiveOption(point.action.actionType as "process"); - } - } - }, [selectedProduct, selectedEventData, getPointByUuid]); + useEffect(() => { + if (selectedEventData) { + const point = getPointByUuid( + selectedProduct.productId, + selectedEventData?.data.modelUuid, + selectedEventData?.selectedPoint + ) as MachinePointSchema | undefined; + if (point && "action" in point) { + setSelectedPointData(point); + setActiveOption(point.action.actionType as "process"); + } + } + }, [selectedProduct, selectedEventData, getPointByUuid]); - const handleActionTypeChange = (option: string) => { - if (!selectedEventData || !selectedPointData) return; - const validOption = option as "process"; - setActiveOption(validOption); + const handleActionTypeChange = (option: string) => { + if (!selectedEventData || !selectedPointData) return; + const validOption = option as "process"; + setActiveOption(validOption); - updateAction(selectedPointData.action.actionUuid, { - actionType: validOption, - }); - }; + updateAction(selectedPointData.action.actionUuid, { + actionType: validOption, + }); + }; - const handleRenameAction = (newName: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { actionName: newName }); - }; + const handleRenameAction = (newName: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { actionName: newName }); + }; - const handleProcessTimeChange = (value: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { - processTime: parseFloat(value), - }); - }; + const handleProcessTimeChange = (value: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { + processTime: parseFloat(value), + }); + }; - const handleMaterialSelect = (material: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { - swapMaterial: material, - }); - }; + const handleMaterialSelect = (material: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { + swapMaterial: material, + }); + }; - // Get current values from store - const currentActionName = selectedPointData - ? selectedPointData.action.actionName - : "Action Name"; + // Get current values from store + const currentActionName = selectedPointData + ? selectedPointData.action.actionName + : "Action Name"; - const currentProcessTime = selectedPointData - ? selectedPointData.action.processTime.toString() - : "1"; + const currentProcessTime = selectedPointData + ? selectedPointData.action.processTime.toString() + : "1"; - const currentMaterial = selectedPointData - ? selectedPointData.action.swapMaterial - : "Default material"; + const currentMaterial = selectedPointData + ? selectedPointData.action.swapMaterial + : "Default material"; - const availableActions = { - defaultOption: "process", - options: ["process"], - }; + const availableActions = { + defaultOption: "process", + options: ["process"], + }; - return ( - <> - {selectedEventData && ( + return ( <> -
-
- -
- -
- - {activeOption === "process" && ( - - )} -
-
-
- -
+ {selectedEventData && ( + <> +
+
+ +
+ +
+ + {activeOption === "process" && ( + + )} +
+
+
+ +
+ + )} - )} - - ); + ); } export default MachineMechanics; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx index 7c20ce5..811a676 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx @@ -3,192 +3,164 @@ import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown"; import RenameInput from "../../../../../ui/inputs/RenameInput"; import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; import Trigger from "../trigger/Trigger"; -import { - useSelectedEventData, - useSelectedProduct, - useSelectedAction, -} from "../../../../../../store/simulation/useSimulationStore"; +import { useSelectedEventData, useSelectedProduct, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import PickAndPlaceAction from "../actions/PickAndPlaceAction"; import ActionsList from "../components/ActionsList"; function RoboticArmMechanics() { - const [activeOption, setActiveOption] = useState<"default" | "pickAndPlace">( - "default" - ); - const [selectedPointData, setSelectedPointData] = useState< - RoboticArmPointSchema | undefined - >(); - const { selectedEventData } = useSelectedEventData(); - const { getPointByUuid, updateEvent, updateAction } = useProductStore(); - const { selectedProduct } = useSelectedProduct(); - const { selectedAction, setSelectedAction, clearSelectedAction } = - useSelectedAction(); + const [activeOption, setActiveOption] = useState<"default" | "pickAndPlace">("default"); + const [selectedPointData, setSelectedPointData] = useState(); + const { selectedEventData } = useSelectedEventData(); + const { getPointByUuid, updateEvent, updateAction } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); + const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction(); - useEffect(() => { - if (selectedEventData) { - const point = getPointByUuid( - selectedProduct.productId, - selectedEventData.data.modelUuid, - selectedEventData.selectedPoint - ) as RoboticArmPointSchema | undefined; - if (point?.actions) { - setSelectedPointData(point); - setActiveOption( - point.actions[0].actionType as "default" | "pickAndPlace" - ); - if (point.actions.length > 0 && !selectedAction.actionId) { - setSelectedAction( - point.actions[0].actionUuid, - point.actions[0].actionName - ); + useEffect(() => { + if (selectedEventData) { + const point = getPointByUuid( + selectedProduct.productId, + selectedEventData.data.modelUuid, + selectedEventData.selectedPoint + ) as RoboticArmPointSchema | undefined; + if (point?.actions) { + setSelectedPointData(point); + setActiveOption(point.actions[0].actionType as "default" | "pickAndPlace"); + if (point.actions.length > 0 && !selectedAction.actionId) { + setSelectedAction( + point.actions[0].actionUuid, + point.actions[0].actionName + ); + } + } + } else { + clearSelectedAction(); } - } - } else { - clearSelectedAction(); - } - }, [ - clearSelectedAction, - getPointByUuid, - selectedAction.actionId, - selectedEventData, - selectedProduct, - setSelectedAction, - ]); + }, [clearSelectedAction, getPointByUuid, selectedAction.actionId, selectedEventData, selectedProduct, setSelectedAction,]); - const handleRenameAction = (newName: string) => { - if (!selectedAction.actionId) return; - updateAction(selectedAction.actionId, { actionName: newName }); + const handleRenameAction = (newName: string) => { + if (!selectedAction.actionId) return; + updateAction(selectedAction.actionId, { actionName: newName }); - if (selectedPointData) { - const updatedActions = selectedPointData.actions.map((action) => - action.actionUuid === selectedAction.actionId - ? { ...action, actionName: newName } - : action - ); - setSelectedPointData({ - ...selectedPointData, - actions: updatedActions, - }); - } - }; + if (selectedPointData) { + const updatedActions = selectedPointData.actions.map((action) => + action.actionUuid === selectedAction.actionId ? { ...action, actionName: newName } : action + ); + setSelectedPointData({ + ...selectedPointData, + actions: updatedActions, + }); + } + }; - const handleSpeedChange = (value: string) => { - if (!selectedEventData) return; - updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { - speed: parseFloat(value), - }); - }; + const handleSpeedChange = (value: string) => { + if (!selectedEventData) return; + updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { + speed: parseFloat(value), + }); + }; - const handlePickPointChange = (value: string) => { - if (!selectedAction.actionId || !selectedPointData) return; - const [x, y, z] = value.split(",").map(Number); + const handlePickPointChange = (value: string) => { + if (!selectedAction.actionId || !selectedPointData) return; + const [x, y, z] = value.split(",").map(Number); - updateAction(selectedAction.actionId, { - process: { - startPoint: [x, y, z] as [number, number, number], - endPoint: - selectedPointData.actions.find( - (a) => a.actionUuid === selectedAction.actionId - )?.process.endPoint || null, - }, - }); - }; + updateAction(selectedAction.actionId, { + process: { + startPoint: [x, y, z] as [number, number, number], + endPoint: selectedPointData.actions.find((a) => a.actionUuid === selectedAction.actionId)?.process.endPoint || null, + }, + }); + }; - const handlePlacePointChange = (value: string) => { - if (!selectedAction.actionId || !selectedPointData) return; - const [x, y, z] = value.split(",").map(Number); + const handlePlacePointChange = (value: string) => { + if (!selectedAction.actionId || !selectedPointData) return; + const [x, y, z] = value.split(",").map(Number); - updateAction(selectedAction.actionId, { - process: { - startPoint: - selectedPointData.actions.find( - (a) => a.actionUuid === selectedAction.actionId - )?.process.startPoint || null, - endPoint: [x, y, z] as [number, number, number], - }, - }); - }; + updateAction(selectedAction.actionId, { + process: { + startPoint: selectedPointData.actions.find((a) => a.actionUuid === selectedAction.actionId)?.process.startPoint || null, + endPoint: [x, y, z] as [number, number, number], + }, + }); + }; - const availableActions = { - defaultOption: "pickAndPlace", - options: ["pickAndPlace"], - }; + const availableActions = { + defaultOption: "pickAndPlace", + options: ["pickAndPlace"], + }; - const currentSpeed = - selectedEventData?.data.type === "roboticArm" - ? selectedEventData.data.speed.toString() - : "0.5"; + const currentSpeed = selectedEventData?.data.type === "roboticArm" + ? selectedEventData.data.speed.toString() + : "0.5"; - const currentAction = selectedPointData?.actions.find( - (a) => a.actionUuid === selectedAction.actionId - ); - const currentPickPoint = currentAction?.process.startPoint - ? `${currentAction.process.startPoint[0]},${currentAction.process.startPoint[1]},${currentAction.process.startPoint[2]}` - : ""; - const currentPlacePoint = currentAction?.process.endPoint - ? `${currentAction.process.endPoint[0]},${currentAction.process.endPoint[1]},${currentAction.process.endPoint[2]}` - : ""; + const currentAction = selectedPointData?.actions.find((a) => a.actionUuid === selectedAction.actionId); - return ( - <> - {selectedEventData && selectedPointData && ( + const currentPickPoint = currentAction?.process.startPoint + ? `${currentAction.process.startPoint[0]},${currentAction.process.startPoint[1]},${currentAction.process.startPoint[2]}` + : ""; + const currentPlacePoint = currentAction?.process.endPoint + ? `${currentAction.process.endPoint[0]},${currentAction.process.endPoint[1]},${currentAction.process.endPoint[2]}` + : ""; + + return ( <> -
-
-
- {}} - onChange={handleSpeedChange} - /> -
-
-
+ {selectedEventData && selectedPointData && ( + <> +
+
+
+ { }} + onChange={handleSpeedChange} + /> +
+
+
- + - {selectedAction.actionId && currentAction && ( -
-
- -
-
- {}} - disabled={true} - /> - -
-
- -
-
- )} + {selectedAction.actionId && currentAction && ( +
+
+ +
+
+ { }} + disabled={true} + /> + +
+
+ +
+
+ )} + + )} - )} - - ); + ); } export default RoboticArmMechanics; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx index d92ed80..b295519 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx @@ -2,119 +2,112 @@ import { useEffect, useState } from "react"; import RenameInput from "../../../../../ui/inputs/RenameInput"; import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; import Trigger from "../trigger/Trigger"; -import { - useSelectedEventData, - useSelectedProduct, -} from "../../../../../../store/simulation/useSimulationStore"; +import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import StorageAction from "../actions/StorageAction"; import ActionsList from "../components/ActionsList"; function StorageMechanics() { - const [activeOption, setActiveOption] = useState< - "default" | "store" | "spawn" - >("default"); - const [selectedPointData, setSelectedPointData] = useState< - StoragePointSchema | undefined - >(); - const { selectedEventData } = useSelectedEventData(); - const { getPointByUuid, updateAction } = useProductStore(); - const { selectedProduct } = useSelectedProduct(); + const [activeOption, setActiveOption] = useState<"default" | "store" | "spawn">("default"); + const [selectedPointData, setSelectedPointData] = useState(); + const { selectedEventData } = useSelectedEventData(); + const { getPointByUuid, updateAction } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); - useEffect(() => { - if (selectedEventData) { - const point = getPointByUuid( - selectedProduct.productId, - selectedEventData?.data.modelUuid, - selectedEventData?.selectedPoint - ) as StoragePointSchema | undefined; - if (point && "action" in point) { - setSelectedPointData(point); - setActiveOption(point.action.actionType as "store" | "spawn"); - } - } - }, [selectedProduct, selectedEventData, getPointByUuid]); + useEffect(() => { + if (selectedEventData) { + const point = getPointByUuid( + selectedProduct.productId, + selectedEventData?.data.modelUuid, + selectedEventData?.selectedPoint + ) as StoragePointSchema | undefined; + if (point && "action" in point) { + setSelectedPointData(point); + setActiveOption(point.action.actionType as "store" | "spawn"); + } + } + }, [selectedProduct, selectedEventData, getPointByUuid]); - const handleActionTypeChange = (option: string) => { - if (!selectedEventData || !selectedPointData) return; - const validOption = option as "store" | "spawn"; - setActiveOption(validOption); + const handleActionTypeChange = (option: string) => { + if (!selectedEventData || !selectedPointData) return; + const validOption = option as "store" | "spawn"; + setActiveOption(validOption); - updateAction(selectedPointData.action.actionUuid, { - actionType: validOption, - }); - }; + updateAction(selectedPointData.action.actionUuid, { + actionType: validOption, + }); + }; - const handleRenameAction = (newName: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { actionName: newName }); - }; + const handleRenameAction = (newName: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { actionName: newName }); + }; - const handleCapacityChange = (value: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { - storageCapacity: parseInt(value), - }); - }; + const handleCapacityChange = (value: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { + storageCapacity: parseInt(value), + }); + }; - // Get current values from store - const currentActionName = selectedPointData - ? selectedPointData.action.actionName - : "Action Name"; + // Get current values from store + const currentActionName = selectedPointData + ? selectedPointData.action.actionName + : "Action Name"; - const currentCapacity = selectedPointData - ? selectedPointData.action.storageCapacity.toString() - : "0"; + const currentCapacity = selectedPointData + ? selectedPointData.action.storageCapacity.toString() + : "0"; - const availableActions = { - defaultOption: "store", - options: ["store", "spawn"], - }; + const availableActions = { + defaultOption: "store", + options: ["store", "spawn"], + }; - return ( - <> - {selectedEventData && ( + return ( <> - -
-
- -
-
- - {activeOption === "store" && ( - - )} - {activeOption === "spawn" && ( -
-

Spawn configuration options would go here

-
- )} -
-
-
- -
+ {selectedEventData && ( + <> + +
+
+ +
+
+ + {activeOption === "store" && ( + + )} + {activeOption === "spawn" && ( +
+

Spawn configuration options would go here

+
+ )} +
+
+
+ +
+ + )} - )} - - ); + ); } export default StorageMechanics; diff --git a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx index b037098..ca29087 100644 --- a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx +++ b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx @@ -1,216 +1,216 @@ -import React, { useEffect, useRef } from "react"; +import React, { useRef } from "react"; import { - AddIcon, - ArrowIcon, - RemoveIcon, - ResizeHeightIcon, + AddIcon, + ArrowIcon, + RemoveIcon, + ResizeHeightIcon, } from "../../../icons/ExportCommonIcons"; import RenameInput from "../../../ui/inputs/RenameInput"; import { handleResize } from "../../../../functions/handleResizePannel"; import { - useSelectedAsset, - useSelectedProduct, + useSelectedAsset, + useSelectedProduct, } from "../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../store/simulation/useProductStore"; import { generateUUID } from "three/src/math/MathUtils"; import RenderOverlay from "../../../templates/Overlay"; import EditWidgetOption from "../../../ui/menu/EditWidgetOption"; -import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi"; import { handleAddEventToProduct } from "../../../../modules/simulation/events/points/functions/handleAddEventToProduct"; +import { useEventsStore } from "../../../../store/simulation/useEventsStore"; +import { deleteEventDataApi } from "../../../../services/simulation/deleteEventDataApi"; interface Event { - pathName: string; + pathName: string; } interface ListProps { - val: Event; + val: Event; } const List: React.FC = ({ val }) => { - return ( -
-
{val.pathName}
-
- ); + return ( +
+
{val.pathName}
+
+ ); }; const Simulations: React.FC = () => { - const productsContainerRef = useRef(null); - const { - products, - addProduct, - removeProduct, - renameProduct, - addEvent, - removeEvent, - } = useProductStore(); - const { selectedProduct, setSelectedProduct } = useSelectedProduct(); - const { selectedAsset, clearSelectedAsset } = useSelectedAsset(); + const productsContainerRef = useRef(null); + const { products, addProduct, removeProduct, renameProduct, addEvent, removeEvent, } = useProductStore(); + const { selectedProduct, setSelectedProduct } = useSelectedProduct(); + const { getEventByModelUuid } = useEventsStore(); + const { selectedAsset, clearSelectedAsset } = useSelectedAsset(); - const handleAddProduct = () => { - addProduct(`Product ${products.length + 1}`, generateUUID()); - }; + const handleAddProduct = () => { + addProduct(`Product ${products.length + 1}`, generateUUID()); + }; - const handleRemoveProduct = (productId: string) => { - const currentIndex = products.findIndex((p) => p.productId === productId); - const isSelected = selectedProduct.productId === productId; + const handleRemoveProduct = (productId: string) => { + const currentIndex = products.findIndex((p) => p.productId === productId); + const isSelected = selectedProduct.productId === productId; - const updatedProducts = products.filter((p) => p.productId !== productId); + const updatedProducts = products.filter((p) => p.productId !== productId); - if (isSelected) { - if (updatedProducts.length > 0) { - let newSelectedIndex = currentIndex; - if (currentIndex >= updatedProducts.length) { - newSelectedIndex = updatedProducts.length - 1; + if (isSelected) { + if (updatedProducts.length > 0) { + let newSelectedIndex = currentIndex; + if (currentIndex >= updatedProducts.length) { + newSelectedIndex = updatedProducts.length - 1; + } + setSelectedProduct( + updatedProducts[newSelectedIndex].productId, + updatedProducts[newSelectedIndex].productName + ); + } else { + setSelectedProduct("", ""); + } } - setSelectedProduct( - updatedProducts[newSelectedIndex].productId, - updatedProducts[newSelectedIndex].productName - ); - } else { - setSelectedProduct("", ""); - } - } - removeProduct(productId); - }; + removeProduct(productId); + }; - const handleRenameProduct = (productId: string, newName: string) => { - renameProduct(productId, newName); - if (selectedProduct.productId === productId) { - setSelectedProduct(productId, newName); - } - }; + const handleRenameProduct = (productId: string, newName: string) => { + renameProduct(productId, newName); + if (selectedProduct.productId === productId) { + setSelectedProduct(productId, newName); + } + }; - const handleRemoveEventFromProduct = () => { - if (selectedAsset) { - removeEvent(selectedProduct.productId, selectedAsset.modelUuid); - clearSelectedAsset(); - } - }; + const handleRemoveEventFromProduct = () => { + if (selectedAsset) { + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + deleteEventDataApi({ + productId: selectedProduct.productId, + modelUuid: selectedAsset.modelUuid, + organization: organization + }); + removeEvent(selectedProduct.productId, selectedAsset.modelUuid); + clearSelectedAsset(); + } + }; - const selectedProductData = products.find( - (product) => product.productId === selectedProduct.productId - ); + const selectedProductData = products.find( + (product) => product.productId === selectedProduct.productId + ); - const events: Event[] = - selectedProductData?.eventDatas.map((event) => ({ - pathName: event.modelName, + const events: Event[] = selectedProductData?.eventDatas.map((event) => ({ + pathName: event.modelName, })) || []; - return ( -
-
Simulations
-
-
-
-
Products
-
- Add -
-
-
-
- {products.map((product, index) => ( -
-
- setSelectedProduct(product.productId, product.productName) - } - > - - - handleRenameProduct(product.productId, newName) - } - /> -
- {products.length > 1 && ( -
handleRemoveProduct(product.productId)} - > - + return ( +
+
Simulations
+
+
+
+
Products
+
+ Add +
+
+
+
+ {products.map((product, index) => ( +
+
+ setSelectedProduct(product.productId, product.productName) + } + > + + + handleRenameProduct(product.productId, newName) + } + /> +
+ {products.length > 1 && ( +
handleRemoveProduct(product.productId)} + > + +
+ )} +
+ ))} +
+
handleResize(e, productsContainerRef)} + > + +
- )}
- ))} -
-
handleResize(e, productsContainerRef)} - > - -
-
-
-
-
-
Events
-
- +
+
+
Events
+
+ +
+
+ {events.map((event, index) => ( + + ))} +
+ +
+
+ Need to Compare Layout? +
+
+ Click 'Compare' to review and analyze the layout + differences between them. +
+
+ +
+
-
- {events.map((event, index) => ( - - ))} -
-
-
- Need to Compare Layout? -
-
- Click 'Compare' to review and analyze the layout - differences between them. -
-
- -
+ {selectedAsset && ( + + { + if (option === "Add to Product") { + handleAddEventToProduct({ + event: getEventByModelUuid(selectedAsset.modelUuid), + addEvent, + selectedProduct, + clearSelectedAsset + }); + } else { + handleRemoveEventFromProduct(); + } + }} + /> + + )}
-
- - {selectedAsset && ( - - { - if (option === "Add to Product") { - handleAddEventToProduct({ - selectedAsset, - addEvent, - selectedProduct, - clearSelectedAsset, - }); - } else { - handleRemoveEventFromProduct(); - } - }} - /> - - )} -
- ); + ); }; export default Simulations; diff --git a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts index c46c0e7..f09f130 100644 --- a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts +++ b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts @@ -156,7 +156,7 @@ function processLoadedModel( const model = gltf.clone(); model.uuid = item.modeluuid; model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); - model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid }; + model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid, eventData: item.eventData }; model.position.set(...item.position); model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z); @@ -170,256 +170,141 @@ function processLoadedModel( } }); - itemsGroup?.current?.add(model); - setFloorItems((prevItems) => [ - ...(prevItems || []), - { - modeluuid: item.modeluuid, - modelname: item.modelname, - position: item.position, - rotation: item.rotation, - modelfileID: item.modelfileID, - isLocked: item.isLocked, - isVisible: item.isVisible, - }, - ]); + if (item.eventData) { + setFloorItems((prevItems) => [ + ...(prevItems || []), + { + modeluuid: item.modeluuid, + modelname: item.modelname, + position: item.position, + rotation: item.rotation, + modelfileID: item.modelfileID, + isLocked: item.isLocked, + isVisible: item.isVisible, + eventData: item.eventData, + }, + ]); - if (item.modelfileID === "a1ee92554935007b10b3eb05") { - const data = PointsCalculator( - 'Vehicle', - gltf.clone(), - new THREE.Vector3(...model.rotation) - ); - - if (!data || !data.points) return; - - const vehicleEvent: VehicleEventSchema = { - modelUuid: item.modeluuid, - modelName: item.modelname, - position: item.position, - rotation: [item.rotation.x, item.rotation.y, item.rotation.z], - state: "idle", - type: "vehicle", - speed: 1, - point: { - uuid: THREE.MathUtils.generateUUID(), - position: [data.points[0].x, data.points[0].y, data.points[0].z], - rotation: [0, 0, 0], - action: { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Vehicle Action", - actionType: "travel", - unLoadDuration: 5, - loadCapacity: 10, - pickUpPoint: null, - unLoadPoint: null, - triggers: [] - } - } - }; - addEvent(vehicleEvent); - } else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") { - const data = PointsCalculator( - 'Conveyor', - gltf.clone(), - new THREE.Vector3(...model.rotation) - ); - - if (!data || !data.points) return; - - const ConveyorEvent: ConveyorEventSchema = { - modelUuid: item.modeluuid, - modelName: item.modelname, - position: item.position, - rotation: [item.rotation.x, item.rotation.y, item.rotation.z], - state: "idle", - type: "transfer", - speed: 1, - points: data.points.map((point: THREE.Vector3, index: number) => ({ - uuid: THREE.MathUtils.generateUUID(), - position: [point.x, point.y, point.z], - rotation: [0, 0, 0], - action: { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: `Action ${index + 1}`, - actionType: 'default', - material: 'Default material', - delay: 0, - spawnInterval: 5, - spawnCount: 1, - triggers: [] - } - })) - }; - addEvent(ConveyorEvent); - } else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") { - // const data = PointsCalculator( - // 'Conveyor', - // gltf.clone(), - // new THREE.Vector3(...model.rotation) - // ); - - // if (!data || !data.points) return; - - // const points: ConveyorPointSchema[] = data.points.map((point: THREE.Vector3, index: number) => { - // const actionUuid = THREE.MathUtils.generateUUID(); - // return { - // uuid: THREE.MathUtils.generateUUID(), - // position: [point.x, point.y, point.z], - // rotation: [0, 0, 0], - // action: { - // actionUuid, - // actionName: `Action ${index}`, - // actionType: 'default', - // material: 'inherit', - // delay: 0, - // spawnInterval: 5, - // spawnCount: 1, - // triggers: [] - // } - // }; - // }); - - // points.forEach((point, index) => { - // if (index < points.length - 1) { - // const nextPoint = points[index + 1]; - // point.action.triggers.push({ - // triggerUuid: THREE.MathUtils.generateUUID(), - // triggerName: `Trigger 1`, - // triggerType: "onComplete", - // delay: 0, - // triggeredAsset: { - // triggeredModel: { - // modelName: item.modelname, - // modelUuid: item.modeluuid - // }, - // triggeredPoint: { - // pointName: `Point ${index + 1}`, - // pointUuid: nextPoint.uuid - // }, - // triggeredAction: { - // actionName: nextPoint.action.actionName, - // actionUuid: nextPoint.action.actionUuid - // } - // } - // }); - // } - // }); - - // const ConveyorEvent: ConveyorEventSchema = { - // modelUuid: item.modeluuid, - // modelName: item.modelname, - // position: item.position, - // rotation: [item.rotation.x, item.rotation.y, item.rotation.z], - // state: "idle", - // type: "transfer", - // speed: 1, - // points - // }; - // addEvent(ConveyorEvent); - } else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") { - const data = PointsCalculator( - 'Conveyor', - gltf.clone(), - new THREE.Vector3(...model.rotation) - ); - - if (!data || !data.points) return; - - const ConveyorEvent: ConveyorEventSchema = { - modelUuid: item.modeluuid, - modelName: item.modelname, - position: item.position, - rotation: [item.rotation.x, item.rotation.y, item.rotation.z], - state: "idle", - type: "transfer", - speed: 1, - points: data.points.map((point: THREE.Vector3, index: number) => ({ - uuid: THREE.MathUtils.generateUUID(), - position: [point.x, point.y, point.z], - rotation: [0, 0, 0], - action: { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: `Action ${index}`, - actionType: 'default', - material: 'inherit', - delay: 0, - spawnInterval: 5, - spawnCount: 1, - triggers: [] - } - })) - }; - addEvent(ConveyorEvent); - } else if (item.modelfileID === "29dee78715ad5b853f5c346d") { - const data = PointsCalculator( - 'StaticMachine', - gltf.clone(), - new THREE.Vector3(...model.rotation) - ); - - if (!data || !data.points) return; - - const machineEvent: MachineEventSchema = { - modelUuid: item.modeluuid, - modelName: item.modelname, - position: item.position, - rotation: [item.rotation.x, item.rotation.y, item.rotation.z], - state: "idle", - type: "machine", - point: { - uuid: THREE.MathUtils.generateUUID(), - position: [data.points[0].x, data.points[0].y, data.points[0].z], - rotation: [0, 0, 0], - action: { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Process Action", - actionType: "process", - processTime: 10, - swapMaterial: "material-id", - triggers: [] - } - } - }; - addEvent(machineEvent); - } else if (item.modelfileID === "52e6681fbb743a890d96c914") { - const data = PointsCalculator( - 'ArmBot', - gltf.clone(), - new THREE.Vector3(...model.rotation) - ); - - if (!data || !data.points) return; - - const roboticArmEvent: RoboticArmEventSchema = { - modelUuid: item.modeluuid, - modelName: item.modelname, - position: item.position, - rotation: [item.rotation.x, item.rotation.y, item.rotation.z], - state: "idle", - type: "roboticArm", - speed: 1, - point: { - uuid: THREE.MathUtils.generateUUID(), - position: [data.points[0].x, data.points[0].y, data.points[0].z], - rotation: [0, 0, 0], - actions: [ - { + if (item.eventData.type === "vehicle") { + const vehicleEvent: VehicleEventSchema = { + modelUuid: item.modeluuid, + modelName: item.modelname, + position: item.position, + rotation: [item.rotation.x, item.rotation.y, item.rotation.z], + state: "idle", + type: "vehicle", + speed: 1, + point: { + uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(), + position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0], + rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0], + action: { actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Pick and Place", - actionType: "pickAndPlace", - process: { - startPoint: [0, 0, 0], - endPoint: [0, 0, 0] - }, + actionName: "Vehicle Action", + actionType: "travel", + unLoadDuration: 5, + loadCapacity: 10, + pickUpPoint: null, + unLoadPoint: null, triggers: [] } - ] - } - }; - addEvent(roboticArmEvent); + } + }; + addEvent(vehicleEvent); + } else if (item.eventData.type === "Conveyor") { + const ConveyorEvent: ConveyorEventSchema = { + modelUuid: item.modeluuid, + modelName: item.modelname, + position: item.position, + rotation: [item.rotation.x, item.rotation.y, item.rotation.z], + state: "idle", + type: "transfer", + speed: 1, + points: item.eventData.points?.map((point: any, index: number) => ({ + uuid: point.uuid || THREE.MathUtils.generateUUID(), + position: [point.position[0], point.position[1], point.position[2]], + rotation: [point.rotation[0], point.rotation[1], point.rotation[2]], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: `Action ${index + 1}`, + actionType: 'default', + material: 'Default material', + delay: 0, + spawnInterval: 5, + spawnCount: 1, + triggers: [] + } + })) || [], + }; + addEvent(ConveyorEvent); + } else if (item.eventData.type === "StaticMachine") { + const machineEvent: MachineEventSchema = { + modelUuid: item.modeluuid, + modelName: item.modelname, + position: item.position, + rotation: [item.rotation.x, item.rotation.y, item.rotation.z], + state: "idle", + type: "machine", + point: { + uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(), + position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0], + rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Process Action", + actionType: "process", + processTime: 10, + swapMaterial: "material-id", + triggers: [] + } + } + }; + addEvent(machineEvent); + } else if (item.eventData.type === "ArmBot") { + const roboticArmEvent: RoboticArmEventSchema = { + modelUuid: item.modeluuid, + modelName: item.modelname, + position: item.position, + rotation: [item.rotation.x, item.rotation.y, item.rotation.z], + state: "idle", + type: "roboticArm", + speed: 1, + point: { + uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(), + position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0], + rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0], + actions: [ + { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Pick and Place", + actionType: "pickAndPlace", + process: { + startPoint: [0, 0, 0], + endPoint: [0, 0, 0] + }, + triggers: [] + } + ] + } + }; + addEvent(roboticArmEvent); + + } + } else { + setFloorItems((prevItems) => [ + ...(prevItems || []), + { + modeluuid: item.modeluuid, + modelname: item.modelname, + position: item.position, + rotation: item.rotation, + modelfileID: item.modelfileID, + isLocked: item.isLocked, + isVisible: item.isVisible, + }, + ]); } gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: 'power2.out' }); diff --git a/app/src/modules/builder/geomentries/assets/addAssetModel.ts b/app/src/modules/builder/geomentries/assets/addAssetModel.ts index d7c278c..ab9d90d 100644 --- a/app/src/modules/builder/geomentries/assets/addAssetModel.ts +++ b/app/src/modules/builder/geomentries/assets/addAssetModel.ts @@ -164,18 +164,6 @@ async function handleModelLoad( // SOCKET - const data = { - organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, - modelfileID: newFloorItem.modelfileID, - position: newFloorItem.position, - rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z }, - isLocked: false, - isVisible: true, - socketId: socket.id - }; - if (selectedItem.type) { const data = PointsCalculator( selectedItem.type, @@ -185,6 +173,10 @@ async function handleModelLoad( if (!data || !data.points) return; + const eventData: any = { + type: selectedItem.type, + }; + if (selectedItem.type === "Conveyor") { const ConveyorEvent: ConveyorEventSchema = { modelUuid: newFloorItem.modeluuid, @@ -209,8 +201,14 @@ async function handleModelLoad( triggers: [] } })) - } + }; addEvent(ConveyorEvent); + eventData.points = ConveyorEvent.points.map(point => ({ + uuid: point.uuid, + position: point.position, + rotation: point.rotation + })); + } else if (selectedItem.type === "Vehicle") { const vehicleEvent: VehicleEventSchema = { modelUuid: newFloorItem.modeluuid, @@ -237,6 +235,12 @@ async function handleModelLoad( } }; addEvent(vehicleEvent); + eventData.point = { + uuid: vehicleEvent.point.uuid, + position: vehicleEvent.point.position, + rotation: vehicleEvent.point.rotation + }; + } else if (selectedItem.type === "ArmBot") { const roboticArmEvent: RoboticArmEventSchema = { modelUuid: newFloorItem.modeluuid, @@ -265,6 +269,13 @@ async function handleModelLoad( } }; addEvent(roboticArmEvent); + console.log('roboticArmEvent: ', roboticArmEvent); + eventData.point = { + uuid: roboticArmEvent.point.uuid, + position: roboticArmEvent.point.position, + rotation: roboticArmEvent.point.rotation + }; + } else if (selectedItem.type === "StaticMachine") { const machineEvent: MachineEventSchema = { modelUuid: newFloorItem.modeluuid, @@ -288,19 +299,65 @@ async function handleModelLoad( } }; addEvent(machineEvent); + eventData.point = { + uuid: machineEvent.point.uuid, + position: machineEvent.point.position, + rotation: machineEvent.point.rotation + }; } + + const completeData = { + organization, + modeluuid: newFloorItem.modeluuid, + modelname: newFloorItem.modelname, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id, + eventData: eventData + }; + + model.userData.eventData = eventData; + + newFloorItem.eventData = eventData; + + setFloorItems((prevItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + socket.emit("v2:model-asset:add", completeData); + + gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" }); + gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } }); + } else { + + const data = { + organization, + modeluuid: newFloorItem.modeluuid, + modelname: newFloorItem.modelname, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id + }; + + setFloorItems((prevItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + socket.emit("v2:model-asset:add", data); + + gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" }); + gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } }); } - - setFloorItems((prevItems) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); - - socket.emit("v2:model-asset:add", data); - - gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" }); - gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } }); } export default addAssetModel; diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx index f3f5050..f1da0a4 100644 --- a/app/src/modules/builder/groups/floorItemsGroup.tsx +++ b/app/src/modules/builder/groups/floorItemsGroup.tsx @@ -65,6 +65,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject }; getFloorAssets(organization).then((data) => { + console.log('data: ', data); if (data.length > 0) { const uniqueItems = (data as Types.FloorItems).filter((item, index, self) => index === self.findIndex((t) => t.modelfileID === item.modelfileID)); totalAssets = uniqueItems.length; diff --git a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx b/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx index 9ca4dd0..c92c98f 100644 --- a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx @@ -137,6 +137,38 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas if (itemsGroupRef.current) { + let updatedEventData = null; + if (obj.userData.eventData) { + updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData)); + + updatedEventData.modelUuid = THREE.MathUtils.generateUUID(); + + if (updatedEventData.type === "Conveyor" && updatedEventData.points) { + updatedEventData.points = updatedEventData.points.map((point: any) => ({ + ...point, + uuid: THREE.MathUtils.generateUUID() + })); + } + else if (updatedEventData.type === "Vehicle" && updatedEventData.point) { + updatedEventData.point = { + ...updatedEventData.point, + uuid: THREE.MathUtils.generateUUID() + }; + } + else if (updatedEventData.type === "ArmBot" && updatedEventData.point) { + updatedEventData.point = { + ...updatedEventData.point, + uuid: THREE.MathUtils.generateUUID() + }; + } + else if (updatedEventData.type === "StaticMachine" && updatedEventData.point) { + updatedEventData.point = { + ...updatedEventData.point, + uuid: THREE.MathUtils.generateUUID() + }; + } + } + const newFloorItem: Types.FloorItemType = { modeluuid: obj.uuid, modelname: obj.userData.name, @@ -144,7 +176,8 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas position: [worldPosition.x, worldPosition.y, worldPosition.z], rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, isLocked: false, - isVisible: true + isVisible: true, + eventData: updatedEventData }; setFloorItems((prevItems: Types.FloorItems) => { @@ -181,11 +214,18 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas isLocked: false, isVisible: true, socketId: socket.id, + eventData: updatedEventData }; socket.emit("v2:model-asset:add", data); - obj.userData.modeluuid = newFloorItem.modeluuid; + obj.userData = { + name: newFloorItem.modelname, + modelId: newFloorItem.modelfileID, + modeluuid: newFloorItem.modeluuid, + eventData: updatedEventData + }; + itemsGroupRef.current.add(obj); } }); @@ -205,7 +245,7 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas setSelectedAssets([]); } - return null; // No visible output, but the component handles copy-paste functionality + return null; }; export default CopyPasteControls; \ No newline at end of file diff --git a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx index 39c3e49..c1f4a74 100644 --- a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx @@ -115,6 +115,38 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb if (itemsGroupRef.current) { + let updatedEventData = null; + if (obj.userData.eventData) { + updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData)); + + updatedEventData.modelUuid = THREE.MathUtils.generateUUID(); + + if (updatedEventData.type === "Conveyor" && updatedEventData.points) { + updatedEventData.points = updatedEventData.points.map((point: any) => ({ + ...point, + uuid: THREE.MathUtils.generateUUID() + })); + } + else if (updatedEventData.type === "Vehicle" && updatedEventData.point) { + updatedEventData.point = { + ...updatedEventData.point, + uuid: THREE.MathUtils.generateUUID() + }; + } + else if (updatedEventData.type === "ArmBot" && updatedEventData.point) { + updatedEventData.point = { + ...updatedEventData.point, + uuid: THREE.MathUtils.generateUUID() + }; + } + else if (updatedEventData.type === "StaticMachine" && updatedEventData.point) { + updatedEventData.point = { + ...updatedEventData.point, + uuid: THREE.MathUtils.generateUUID() + }; + } + } + const newFloorItem: Types.FloorItemType = { modeluuid: obj.uuid, modelname: obj.userData.name, @@ -122,7 +154,8 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb position: [worldPosition.x, worldPosition.y, worldPosition.z], rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, isLocked: false, - isVisible: true + isVisible: true, + eventData: updatedEventData }; setFloorItems((prevItems: Types.FloorItems) => { @@ -159,11 +192,18 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb isLocked: false, isVisible: true, socketId: socket.id, + eventData: updatedEventData }; socket.emit("v2:model-asset:add", data); - obj.userData.modeluuid = newFloorItem.modeluuid; + obj.userData = { + name: newFloorItem.modelname, + modelId: newFloorItem.modelfileID, + modeluuid: newFloorItem.modeluuid, + eventData: updatedEventData + }; + itemsGroupRef.current.add(obj); } }); @@ -183,7 +223,7 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb setSelectedAssets([]); } - return null; // This component does not render any UI + return null; }; export default DuplicationControls; \ No newline at end of file diff --git a/app/src/modules/scene/controls/selectionControls/moveControls.tsx b/app/src/modules/scene/controls/selectionControls/moveControls.tsx index 2cde3e4..f422d6e 100644 --- a/app/src/modules/scene/controls/selectionControls/moveControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/moveControls.tsx @@ -1,11 +1,14 @@ import * as THREE from "three"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef } from "react"; import { useFrame, useThree } from "@react-three/fiber"; import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; // import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; import { toast } from "react-toastify"; import * as Types from "../../../../types/world/worldTypes"; import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys"; +import { useEventsStore } from "../../../../store/simulation/useEventsStore"; +import { useProductStore } from "../../../../store/simulation/useProductStore"; +import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore"; function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) { const { camera, controls, gl, scene, pointer, raycaster } = useThree(); @@ -176,6 +179,24 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje isVisible: true }; + if (obj.userData.eventData) { + const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modeluuid); + const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid); + + if (eventData) { + useEventsStore.getState().updateEvent(obj.userData.modeluuid, { + position: [worldPosition.x, worldPosition.y, worldPosition.z], + rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], + }) + } + if (productData) { + useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid, { + position: [worldPosition.x, worldPosition.y, worldPosition.z], + rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], + }) + } + } + setFloorItems((prevItems: Types.FloorItems) => { const updatedItems = [...(prevItems || []), newFloorItem]; localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); @@ -234,7 +255,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje setSelectedAssets([]); } - return null; // No need to return anything, as this component is used for its side effects + return null; } export default MoveControls \ No newline at end of file diff --git a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx index 5dfaf08..cf66772 100644 --- a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx @@ -1,11 +1,13 @@ import * as THREE from "three"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef } from "react"; import { useFrame, useThree } from "@react-three/fiber"; import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; // import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; import { toast } from "react-toastify"; import * as Types from "../../../../types/world/worldTypes"; -import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi"; +import { useEventsStore } from "../../../../store/simulation/useEventsStore"; +import { useProductStore } from "../../../../store/simulation/useProductStore"; +import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore"; function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) { const { camera, controls, gl, scene, pointer, raycaster } = useThree(); @@ -177,6 +179,24 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo isVisible: true }; + if (obj.userData.eventData) { + const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modeluuid); + const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid); + + if (eventData) { + useEventsStore.getState().updateEvent(obj.userData.modeluuid, { + position: [worldPosition.x, worldPosition.y, worldPosition.z], + rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], + }) + } + if (productData) { + useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid, { + position: [worldPosition.x, worldPosition.y, worldPosition.z], + rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], + }) + } + } + setFloorItems((prevItems: Types.FloorItems) => { const updatedItems = [...(prevItems || []), newFloorItem]; localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); @@ -235,7 +255,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo setSelectedAssets([]); } - return null; // No need to return anything, as this component is used for its side effects + return null; } export default RotateControls \ No newline at end of file diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx index c5025dd..8e476d0 100644 --- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx +++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx @@ -62,7 +62,7 @@ function PointsCreator() { {events.map((event, i) => { if (event.type === 'transfer') { return ( - + {event.points.map((point, j) => ( @@ -88,7 +89,7 @@ function PointsCreator() { ); } else if (event.type === 'vehicle') { return ( - + @@ -111,7 +113,7 @@ function PointsCreator() { ); } else if (event.type === 'roboticArm') { return ( - + @@ -134,7 +137,7 @@ function PointsCreator() { ); } else if (event.type === 'machine') { return ( - + diff --git a/app/src/modules/simulation/events/points/functions/handleAddEventToProduct.ts b/app/src/modules/simulation/events/points/functions/handleAddEventToProduct.ts index 7943c1c..9928578 100644 --- a/app/src/modules/simulation/events/points/functions/handleAddEventToProduct.ts +++ b/app/src/modules/simulation/events/points/functions/handleAddEventToProduct.ts @@ -1,28 +1,38 @@ +import { upsertProductOrEventApi } from "../../../../../services/simulation/UpsertProductOrEventApi"; + interface HandleAddEventToProductParams { - selectedAsset: any; // Replace `any` with specific type if you have it - addEvent: (productId: string, asset: any) => void; + event: EventsSchema | undefined; + addEvent: (productId: string, event: EventsSchema) => void; selectedProduct: { productId: string; productName: string; - // Add other fields if needed - }; - clearSelectedAsset: () => void; + } + clearSelectedAsset?: () => void; } export const handleAddEventToProduct = ({ - selectedAsset, + event, addEvent, selectedProduct, - clearSelectedAsset, + clearSelectedAsset }: HandleAddEventToProductParams) => { - console.log('selectedProduct: ', selectedProduct); - if (selectedAsset) { - addEvent(selectedProduct.productId, selectedAsset); - // upsertProductOrEventApi({ - // productName: selectedProduct.productName, - // productId: selectedProduct.productId, - // eventDatas: selectedAsset - // }); - clearSelectedAsset(); + if (event && selectedProduct.productId) { + addEvent(selectedProduct.productId, event); + + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + + upsertProductOrEventApi({ + productName: selectedProduct.productName, + productId: selectedProduct.productId, + organization: organization, + eventDatas: event + }).then((data) => { + // console.log(data); + }) + + if (clearSelectedAsset) { + clearSelectedAsset(); + } } }; diff --git a/app/src/modules/simulation/products/products.tsx b/app/src/modules/simulation/products/products.tsx index 38175e2..ee1ac42 100644 --- a/app/src/modules/simulation/products/products.tsx +++ b/app/src/modules/simulation/products/products.tsx @@ -7,28 +7,27 @@ import { upsertProductOrEventApi } from '../../../services/simulation/UpsertProd import { getAllProductsApi } from '../../../services/simulation/getallProductsApi'; function Products() { - const { products, addProduct } = useProductStore(); + const { products, addProduct, setProducts } = useProductStore(); const { setSelectedProduct } = useSelectedProduct(); useEffect(() => { - if (products.length === 0) { - const id = THREE.MathUtils.generateUUID(); - const name = 'Product 1'; - addProduct(name, id); - // upsertProductOrEventApi({ productName: name, productId: id }).then((data) => { - // console.log('data: ', data); - // }); - setSelectedProduct(id, name); - } - }, [products]) + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + getAllProductsApi(organization).then((data) => { + if (data.length === 0) { + const id = THREE.MathUtils.generateUUID(); + const name = 'Product 1'; + addProduct(name, id); + upsertProductOrEventApi({ productName: name, productId: id, organization: organization }) + setSelectedProduct(id, name); + } else { + setProducts(data); + setSelectedProduct(data[0].productId, data[0].productName); + } + }) + }, []) useEffect(() => { - // const email = localStorage.getItem('email') - // const organization = (email!.split("@")[1]).split(".")[0]; - // console.log(organization); - // getAllProductsApi(organization).then((data) => { - // console.log('data: ', data); - // }) }, []) return ( diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx index 5ca0ec5..f2d208d 100644 --- a/app/src/modules/simulation/simulation.tsx +++ b/app/src/modules/simulation/simulation.tsx @@ -19,11 +19,11 @@ function Simulation() { const { products } = useProductStore(); useEffect(() => { - // console.log('events: ', events); + console.log('events: ', events); }, [events]) useEffect(() => { - // console.log('products: ', products); + console.log('products: ', products); }, [products]) return ( diff --git a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx index f836ea4..efefa0c 100644 --- a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx +++ b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx @@ -1,19 +1,85 @@ -import { useEffect } from "react"; +import { useEffect, useRef, useState } from "react"; import { useThree } from "@react-three/fiber"; +import * as THREE from "three"; import { useSubModuleStore } from "../../../../store/useModuleStore"; import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../store/simulation/useProductStore"; +import { useEventsStore } from "../../../../store/simulation/useEventsStore"; import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore"; +import { handleAddEventToProduct } from "../../events/points/functions/handleAddEventToProduct"; + +interface ConnectionLine { + id: string; + start: THREE.Vector3; + end: THREE.Vector3; + mid: THREE.Vector3; + trigger: TriggerSchema; +} function TriggerConnector() { const { gl, raycaster, scene } = useThree(); const { subModule } = useSubModuleStore(); - const { getPointByUuid, getIsEventInProduct } = useProductStore(); + const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, addEvent, getEventByModelUuid } = useProductStore(); const { selectedAsset, clearSelectedAsset } = useSelectedAsset(); const { selectedProduct } = useSelectedProduct(); - useEffect(() => { + const [firstSelectedPoint, setFirstSelectedPoint] = useState<{ + productId: string; + modelUuid: string; + pointUuid: string; + actionUuid?: string; + } | null>(null); + const [connections, setConnections] = useState([]); + + useEffect(() => { + const newConnections: ConnectionLine[] = []; + + products.forEach(product => { + product.eventDatas.forEach(event => { + if ('points' in event) { + event.points.forEach(point => { + if ('action' in point && point.action?.triggers) { + point.action.triggers.forEach(trigger => { + if (trigger.triggeredAsset) { + const targetPoint = getPointByUuid( + product.productId, + trigger.triggeredAsset.triggeredModel.modelUuid, + trigger.triggeredAsset.triggeredPoint.pointUuid + ); + + if (targetPoint) { + const startPos = new THREE.Vector3(...point.position); + const endPos = new THREE.Vector3(...targetPoint.position); + const midPos = new THREE.Vector3() + .addVectors(startPos, endPos) + .multiplyScalar(0.5) + .add(new THREE.Vector3(0, 2, 0)); + + newConnections.push({ + id: `${point.uuid}-${targetPoint.uuid}-${trigger.triggerUuid}`, + start: startPos, + end: endPos, + mid: midPos, + trigger + }); + } + } + }); + } + }); + } + }); + }); + + setConnections(newConnections); + }, [products]); + + useEffect(() => { + console.log('connections: ', connections); + }, connections) + + useEffect(() => { const canvasElement = gl.domElement; let drag = false; @@ -44,37 +110,114 @@ function TriggerConnector() { const handleRightClick = (evt: MouseEvent) => { if (drag) return; evt.preventDefault(); - const canvasElement = gl.domElement; - if (!canvasElement) return; - let intersects = raycaster.intersectObjects(scene.children, true); - if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) { - let currentObject = intersects[0].object; + const intersects = raycaster.intersectObjects(scene.children, true); + if (intersects.length === 0) return; - if (currentObject && currentObject.name === 'Event-Sphere') { + const currentObject = intersects[0].object; + if (!currentObject || currentObject.name !== 'Event-Sphere') return; - const isInProduct = getIsEventInProduct( - selectedProduct.productId, - currentObject.userData.modelUuid - ); + const modelUuid = currentObject.userData.modelUuid; + const pointUuid = currentObject.userData.pointUuid; - // You left Here + if (selectedProduct && getIsEventInProduct(selectedProduct.productId, modelUuid)) { - if (isInProduct) { + const point = getPointByUuid( + selectedProduct.productId, + modelUuid, + pointUuid + ); - const event = getPointByUuid( - selectedProduct.productId, - currentObject.userData.modelUuid, - currentObject.userData.pointUuid - ); - console.log('event: ', event); - } else { + if (!point) return; - } + let actionUuid: string | undefined; + if ('action' in point && point.action) { + actionUuid = point.action.actionUuid; + } else if ('actions' in point && point.actions.length === 1) { + actionUuid = point.actions[0].actionUuid; } - } else { + if (!firstSelectedPoint) { + setFirstSelectedPoint({ + productId: selectedProduct.productId, + modelUuid, + pointUuid, + actionUuid + }); + } else { + const trigger: TriggerSchema = { + triggerUuid: THREE.MathUtils.generateUUID(), + triggerName: `Trigger ${firstSelectedPoint.pointUuid.slice(0, 4)} → ${pointUuid.slice(0, 4)}`, + triggerType: "onComplete", + delay: 0, + triggeredAsset: { + triggeredModel: { + modelName: currentObject.parent?.parent?.name || 'Unknown', + modelUuid: modelUuid + }, + triggeredPoint: { + pointName: currentObject.name, + pointUuid: pointUuid + }, + triggeredAction: actionUuid ? { + actionName: getActionByUuid(selectedProduct.productId, actionUuid)?.actionName || 'Action', + actionUuid: actionUuid + } : null + } + }; + if (firstSelectedPoint.actionUuid) { + addTrigger(firstSelectedPoint.actionUuid, trigger); + } + setFirstSelectedPoint(null); + } + } else if (!getIsEventInProduct(selectedProduct.productId, modelUuid) && firstSelectedPoint) { + handleAddEventToProduct({ + event: useEventsStore.getState().getEventByModelUuid(modelUuid), + addEvent, + selectedProduct, + }) + + const point = getPointByUuid( + selectedProduct.productId, + modelUuid, + pointUuid + ); + + if (!point) return; + + let actionUuid: string | undefined; + if ('action' in point && point.action) { + actionUuid = point.action.actionUuid; + } else if ('actions' in point && point.actions.length === 1) { + actionUuid = point.actions[0].actionUuid; + } + + const trigger: TriggerSchema = { + triggerUuid: THREE.MathUtils.generateUUID(), + triggerName: `Trigger ${firstSelectedPoint.pointUuid.slice(0, 4)} → ${pointUuid.slice(0, 4)}`, + triggerType: "onComplete", + delay: 0, + triggeredAsset: { + triggeredModel: { + modelName: currentObject.parent?.parent?.name || 'Unknown', + modelUuid: modelUuid + }, + triggeredPoint: { + pointName: currentObject.name, + pointUuid: pointUuid + }, + triggeredAction: actionUuid ? { + actionName: getActionByUuid(selectedProduct.productId, actionUuid)?.actionName || 'Action', + actionUuid: actionUuid + } : null + } + }; + + if (firstSelectedPoint.actionUuid) { + addTrigger(firstSelectedPoint.actionUuid, trigger); + } + setFirstSelectedPoint(null); } }; @@ -92,12 +235,12 @@ function TriggerConnector() { canvasElement.removeEventListener('contextmenu', handleRightClick); }; - }, [gl, subModule]); + }, [gl, subModule, selectedProduct, firstSelectedPoint]); return ( <> - ) + ); } -export default TriggerConnector \ No newline at end of file +export default TriggerConnector; \ No newline at end of file diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts index 8ec74cf..de02551 100644 --- a/app/src/store/simulation/useProductStore.ts +++ b/app/src/store/simulation/useProductStore.ts @@ -6,6 +6,7 @@ type ProductsStore = { // Product-level actions addProduct: (productName: string, productId: string) => void; + setProducts: (products: productsSchema) => void; removeProduct: (productId: string) => void; updateProduct: (productId: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void; @@ -78,6 +79,12 @@ export const useProductStore = create()( }); }, + setProducts: (products) => { + set((state) => { + state.products = products; + }); + }, + removeProduct: (productId) => { set((state) => { state.products = state.products.filter(p => p.productId !== productId); diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts index 811812d..46093d6 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -14,7 +14,7 @@ interface TriggerSchema { triggeredAsset: { triggeredModel: { modelName: string, modelUuid: string }; triggeredPoint: { pointName: string, pointUuid: string }; - triggeredAction: { actionName: string, actionUuid: string }; + triggeredAction: { actionName: string, actionUuid: string } | null; } | null; } diff --git a/app/src/types/world/worldTypes.d.ts b/app/src/types/world/worldTypes.d.ts index fa6c129..20c44da 100644 --- a/app/src/types/world/worldTypes.d.ts +++ b/app/src/types/world/worldTypes.d.ts @@ -196,6 +196,19 @@ export type FloorItemType = { modelfileID: string; isLocked: boolean; isVisible: boolean; + eventData?: { + type: string; + point?: { + uuid: string; + position: [number, number, number]; + rotation: [number, number, number]; + } + points?: { + uuid: string; + position: [number, number, number]; + rotation: [number, number, number]; + }[]; + } }; // Array of floor items for managing multiple objects on the floor diff --git a/app/src/utils/indexDB/idbUtils.ts b/app/src/utils/indexDB/idbUtils.ts index c9228d3..24b1448 100644 --- a/app/src/utils/indexDB/idbUtils.ts +++ b/app/src/utils/indexDB/idbUtils.ts @@ -3,43 +3,43 @@ const STORE_NAME = 'models'; const DB_VERSION = 1; export function initializeDB(): Promise { - return new Promise((resolve, reject) => { - const request = indexedDB.open(DB_NAME, DB_VERSION); + return new Promise((resolve, reject) => { + const request = indexedDB.open(DB_NAME, DB_VERSION); - request.onupgradeneeded = () => { - const db = request.result; - if (!db.objectStoreNames.contains(STORE_NAME)) { - db.createObjectStore(STORE_NAME); - } - }; + request.onupgradeneeded = () => { + const db = request.result; + if (!db.objectStoreNames.contains(STORE_NAME)) { + db.createObjectStore(STORE_NAME); + } + }; - request.onsuccess = () => resolve(request.result); - request.onerror = () => reject(request.error); - }); + request.onsuccess = () => resolve(request.result); + request.onerror = () => reject(request.error); + }); } export async function storeGLTF(key: string, file: Blob): Promise { - const db = await initializeDB(); + const db = await initializeDB(); - return new Promise((resolve, reject) => { - const transaction = db.transaction(STORE_NAME, 'readwrite'); - const store = transaction.objectStore(STORE_NAME); - const request = store.put(file, key); + return new Promise((resolve, reject) => { + const transaction = db.transaction(STORE_NAME, 'readwrite'); + const store = transaction.objectStore(STORE_NAME); + const request = store.put(file, key); - request.onsuccess = () => resolve(); - request.onerror = () => reject(request.error); - }); + request.onsuccess = () => resolve(); + request.onerror = () => reject(request.error); + }); } export async function retrieveGLTF(key: string): Promise { - const db = await initializeDB(); + const db = await initializeDB(); - return new Promise((resolve, reject) => { - const transaction = db.transaction(STORE_NAME, 'readonly'); - const store = transaction.objectStore(STORE_NAME); - const request = store.get(key); + return new Promise((resolve, reject) => { + const transaction = db.transaction(STORE_NAME, 'readonly'); + const store = transaction.objectStore(STORE_NAME); + const request = store.get(key); - request.onsuccess = () => resolve(request.result as Blob | undefined); - request.onerror = () => reject(request.error); - }); + request.onsuccess = () => resolve(request.result as Blob | undefined); + request.onerror = () => reject(request.error); + }); } \ No newline at end of file From 4152e611a9f0081c8edaf3f5b1ff503190e96796 Mon Sep 17 00:00:00 2001 From: Vishnu Date: Wed, 30 Apr 2025 10:10:39 +0530 Subject: [PATCH 06/14] refactor: Update dropdown items to include active state, enhance List and DropDownList components, and improve sidebar styles for better layout and accessibility --- .../components/layout/sidebarLeft/Outline.tsx | 2 +- app/src/components/ui/list/DropDownList.tsx | 63 ++++---- app/src/components/ui/list/List.tsx | 74 ++++----- app/src/styles/abstracts/variables.scss | 6 +- app/src/styles/components/lists.scss | 26 ++-- app/src/styles/layout/sidebar.scss | 140 ++++++------------ 6 files changed, 139 insertions(+), 172 deletions(-) diff --git a/app/src/components/layout/sidebarLeft/Outline.tsx b/app/src/components/layout/sidebarLeft/Outline.tsx index 417f069..152c357 100644 --- a/app/src/components/layout/sidebarLeft/Outline.tsx +++ b/app/src/components/layout/sidebarLeft/Outline.tsx @@ -11,7 +11,7 @@ const Outline: React.FC = () => { }; const dropdownItems = [ - { id: "1", name: "Ground Floor" }, + { id: "1", name: "Ground Floor", active: true }, // { id: "2", name: "Floor 1" }, ]; // Example dropdown items diff --git a/app/src/components/ui/list/DropDownList.tsx b/app/src/components/ui/list/DropDownList.tsx index 0416a9e..20c6951 100644 --- a/app/src/components/ui/list/DropDownList.tsx +++ b/app/src/components/ui/list/DropDownList.tsx @@ -3,7 +3,6 @@ import List from "./List"; import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons"; import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect"; import { useFloorItems, useZones } from "../../../store/store"; -import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore"; interface DropDownListProps { value?: string; // Value to display in the DropDownList @@ -17,6 +16,17 @@ interface DropDownListProps { remove?: boolean; } +interface Zone { + zoneId: string; + zoneName: string; + points: [number, number, number][]; // polygon vertices +} +interface ZoneData { + id: string; + name: string; + assets: { id: string; name: string; position?: []; rotation?: {} }[]; +} + const DropDownList: React.FC = ({ value = "Dropdown", items = [], @@ -33,38 +43,30 @@ const DropDownList: React.FC = ({ remove, }) => { const [isOpen, setIsOpen] = useState(defaultOpen); - const { zones, setZones } = useZones(); + const { zones } = useZones(); const handleToggle = () => { setIsOpen((prev) => !prev); // Toggle the state }; - interface Asset { - id: string; - name: string; - position: [number, number, number]; // x, y, z - } - interface Zone { - zoneId: string; - zoneName: string; - points: [number, number, number][]; // polygon vertices - } - interface ZoneData { - id: string; - name: string; - assets: { id: string; name: string; position?: []; rotation?: {} }[]; - } const [zoneDataList, setZoneDataList] = useState([]); const { floorItems } = useFloorItems(); - const isPointInsidePolygon = (point: [number, number], polygon: [number, number][]) => { + const isPointInsidePolygon = ( + point: [number, number], + polygon: [number, number][] + ) => { let inside = false; for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { - const xi = polygon[i][0], zi = polygon[i][1]; - const xj = polygon[j][0], zj = polygon[j][1]; + const xi = polygon[i][0], + zi = polygon[i][1]; + const xj = polygon[j][0], + zj = polygon[j][1]; - const intersect = ((zi > point[1]) !== (zj > point[1])) && - (point[0] < (xj - xi) * (point[1] - zi) / (zj - zi + 0.000001) + xi); + const intersect = + // eslint-disable-next-line no-mixed-operators + zi > point[1] !== zj > point[1] && + point[0] < ((xj - xi) * (point[1] - zi)) / (zj - zi + 0.000001) + xi; if (intersect) inside = !inside; } @@ -73,18 +75,21 @@ const DropDownList: React.FC = ({ useEffect(() => { const updatedZoneList: ZoneData[] = zones?.map((zone: Zone) => { - const polygon2D = zone.points.map((p: [number, number, number]) => [p[0], p[2]]) as [number, number][]; + const polygon2D = zone.points.map((p: [number, number, number]) => [ + p[0], + p[2], + ]); const assetsInZone = floorItems .filter((item: any) => { const [x, , z] = item.position; - return isPointInsidePolygon([x, z], polygon2D); + return isPointInsidePolygon([x, z], polygon2D as [number, number][]); }) .map((item: any) => ({ id: item.modeluuid, name: item.modelname, position: item.position, - rotation: item.rotation + rotation: item.rotation, })); return { @@ -99,9 +104,9 @@ const DropDownList: React.FC = ({ return (
-
+
+
{showFocusIcon && (
@@ -118,13 +123,13 @@ const DropDownList: React.FC = ({
)} -
-
+
{isOpen && ( diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx index 06419af..bd8725b 100644 --- a/app/src/components/ui/list/List.tsx +++ b/app/src/components/ui/list/List.tsx @@ -12,7 +12,6 @@ import { LockIcon, RemoveIcon, } from "../../icons/ExportCommonIcons"; -import { useThree } from "@react-three/fiber"; import { useFloorItems, useZoneAssetId, useZones } from "../../../store/store"; import { zoneCameraUpdate } from "../../../services/visulization/zone/zoneCameraUpdation"; import { setFloorItemApi } from "../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi"; @@ -32,20 +31,19 @@ interface ZoneItem { interface ListProps { items?: ZoneItem[]; - placeholder?: string; remove?: boolean; } const List: React.FC = ({ items = [], remove }) => { - const { activeModule, setActiveModule } = useModuleStore(); + const { activeModule } = useModuleStore(); const { selectedZone, setSelectedZone } = useSelectedZoneStore(); const { zoneAssetId, setZoneAssetId } = useZoneAssetId(); - const { zones, setZones } = useZones(); + const { zones } = useZones(); const { setSubModule } = useSubModuleStore(); const [expandedZones, setExpandedZones] = useState>( {} ); - const { floorItems, setFloorItems } = useFloorItems(); + const { setFloorItems } = useFloorItems(); useEffect(() => { useSelectedZoneStore.getState().setSelectedZone({ @@ -70,39 +68,36 @@ const List: React.FC = ({ items = [], remove }) => { async function handleSelectZone(id: string) { try { if (selectedZone?.zoneId === id) { - return; } setSubModule("zoneProperties"); const email = localStorage.getItem("email"); - const organization = email?.split("@")[1]?.split(".")[0] || ""; + const organization = email?.split("@")[1]?.split(".")[0] ?? ""; let response = await getZoneData(id, organization); setSelectedZone({ zoneName: response?.zoneName, - activeSides: response?.activeSides || [], - panelOrder: response?.panelOrder || [], - lockedPanels: response?.lockedPanels || [], - widgets: response?.widgets || [], + activeSides: response?.activeSides ?? [], + panelOrder: response?.panelOrder ?? [], + lockedPanels: response?.lockedPanels ?? [], + widgets: response?.widgets ?? [], zoneId: response?.zoneId, - zoneViewPortTarget: response?.viewPortCenter || [], - zoneViewPortPosition: response?.viewPortposition || [], + zoneViewPortTarget: response?.viewPortCenter ?? [], + zoneViewPortPosition: response?.viewPortposition ?? [], }); - - } catch (error) { - + console.log(error); } } function handleAssetClick(asset: Asset) { - setZoneAssetId(asset) + setZoneAssetId(asset); } async function handleZoneNameChange(newName: string) { - const email = localStorage.getItem("email") || ""; + const email = localStorage.getItem("email") ?? ""; const organization = email?.split("@")[1]?.split(".")[0]; const isDuplicate = zones.some( @@ -128,12 +123,16 @@ const List: React.FC = ({ items = [], remove }) => { } async function handleZoneAssetName(newName: string) { - const email = localStorage.getItem("email") || ""; + const email = localStorage.getItem("email") ?? ""; const organization = email?.split("@")[1]?.split(".")[0]; if (zoneAssetId?.id) { - let response = await setFloorItemApi(organization, zoneAssetId.id, newName) - console.log('response: ', response); + let response = await setFloorItemApi( + organization, + zoneAssetId.id, + newName + ); + console.log("response: ", response); setFloorItems((prevFloorItems: any[]) => prevFloorItems.map((floorItems) => floorItems.modeluuid === zoneAssetId.id @@ -160,7 +159,7 @@ const List: React.FC = ({ items = [], remove }) => {
  • -
    handleSelectZone(item.id)} > @@ -169,8 +168,7 @@ const List: React.FC = ({ items = [], remove }) => { onRename={handleZoneNameChange} checkDuplicate={checkZoneNameDuplicate} /> - -
    +
    @@ -185,12 +183,12 @@ const List: React.FC = ({ items = [], remove }) => {
    )} {item.assets && item.assets.length > 0 && ( -
    toggleZoneExpansion(item.id)} > -
    + )}
    @@ -206,20 +204,26 @@ const List: React.FC = ({ items = [], remove }) => { className="list-container asset-item" >
    -
    handleAssetClick(asset)} > - -
    +
    -
    +
    -
    + +
    + {remove && ( -
    +
    + )}
    diff --git a/app/src/styles/abstracts/variables.scss b/app/src/styles/abstracts/variables.scss index 2913425..37d9971 100644 --- a/app/src/styles/abstracts/variables.scss +++ b/app/src/styles/abstracts/variables.scss @@ -16,7 +16,7 @@ $text-button-color: #f3f3fd; $text-color-dark: #f3f3fd; $text-disabled-dark: #6f6f7a; $input-text-color-dark: #b5b5c8; -$highlight-text-color-dark: #b392f0; +$highlight-text-color-dark: #d2baff; $text-button-color-dark: #f3f3fd; // background colors @@ -105,8 +105,8 @@ $color5: #c7a8ff; // old variables $accent-color: #6f42c1; $accent-color-dark: #c4abf1; -$highlight-accent-color: #e0dfff; -$highlight-accent-color-dark: #403e6a; +// $highlight-accent-color: #e0dfff; +// $highlight-accent-color-dark: #403e6a; // $background-color: #fcfdfd; // $background-color-dark: #19191d; diff --git a/app/src/styles/components/lists.scss b/app/src/styles/components/lists.scss index 3b52e69..894eac1 100644 --- a/app/src/styles/components/lists.scss +++ b/app/src/styles/components/lists.scss @@ -34,9 +34,8 @@ padding: 12px; } - .list-container { + li.list-container { padding: 2px; - // margin-left: 10px; overflow: hidden; .list-item { @@ -45,11 +44,13 @@ text-align: center; padding: 4px 8px; border-radius: #{$border-radius-large}; - - .value { - width: 100%; - text-align: start; - max-width: 180px; + .zone-header{ + @include flex-center; + .value { + width: 100%; + text-align: start; + max-width: 180px; + } } .options-container { @@ -61,11 +62,18 @@ cursor: pointer; } } + &:first-child{ + background: var(--highlight-accent-color); + .input-value{ + color: var(--highlight-text-color); + } + } } - .active { background: var(--highlight-accent-color); - color: var(--primary-color); + .input-value{ + color: var(--highlight-text-color); + } } } diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index 01715ec..583dc0a 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -434,7 +434,7 @@ button { path { stroke: var(--accent-color); - strokeWidth: 1.5px; + stroke-width: 1.5px; } color: var(--accent-color); &:before { @@ -456,6 +456,9 @@ .sidebar-right-content-container { .dataSideBar { .inputs-wrapper { + display: flex; + flex-direction: column; + gap: 6px; .datas { .input-value { padding: 5px 10px; @@ -487,6 +490,7 @@ .datas__class { display: flex; align-items: center; + gap: 12px; .multi-level-dropdown { width: 170px; @@ -496,22 +500,13 @@ justify-content: space-between; gap: 6px; } - } - } - - .datas__class { - display: flex; - gap: 12px; - - // .datas__separator { - // } - - .disable { - cursor: not-allowed; - pointer-events: none; - /* Disables all mouse interactions */ - opacity: 0.5; - /* Optional: Makes the button look visually disabled */ + .disable { + cursor: not-allowed; + pointer-events: none; + /* Disables all mouse interactions */ + opacity: 0.5; + /* Optional: Makes the button look visually disabled */ + } } } } @@ -522,12 +517,6 @@ padding-bottom: 6px; } - .inputs-wrapper { - display: flex; - flex-direction: column; - gap: 6px; - } - .selectedMain-container { display: flex; flex-direction: column; @@ -627,10 +616,8 @@ width: 100%; height: 150px; background: #f0f0f0; - // border-radius: 8px; display: flex; align-items: center; - // justify-content: center; } .optionsContainer { @@ -713,7 +700,7 @@ path { stroke: var(--accent-color); - strokeWidth: 1.5px; + stroke-width: 1.5px; } &:hover { @@ -742,14 +729,14 @@ .add-button { @include flex-center; padding: 2px 4px; - background: var(--accent-color); - color: var(--primary-color); + background: var(--background-color-button); + color: var(--text-button-color); border-radius: #{$border-radius-small}; cursor: pointer; outline: none; border: none; path { - stroke: var(--primary-color); + stroke: var(--text-button-color); } &:disabled { background: var(--text-disabled); @@ -804,11 +791,10 @@ } .lists-main-container { - margin: 2px 8px; - width: calc(100% - 12px); - margin-right: 4px; + margin: 2px; + width: calc(100% - 4px); background: var(--background-color-gray); - border-radius: #{$border-radius-small}; + border-radius: 8px; min-height: 120px; .list-container { @@ -818,10 +804,10 @@ .list-item { @include flex-space-between; - padding: 2px 12px; + padding: 4px 12px; width: 100%; margin: 2px 0; - border-radius: #{$border-radius-small}; + border-radius: #{$border-radius-medium}; .value { display: flex; justify-content: flex-start; @@ -1156,7 +1142,13 @@ } .assets-container { - padding: 0 6px; + width: 100%; + display: flex; + flex-direction: row; + flex-wrap: wrap; + height: 100%; + gap: 3px; + padding: 10px 0; .assets-wrapper { width: 100%; @@ -1175,14 +1167,16 @@ flex-direction: row; flex-wrap: wrap; height: 100%; - gap: 8px; + gap: 0px 4px; padding: 10px 0; .category { - width: 121px; + width: 123px; height: 95px; - border-radius: 3.59px; - background: var(--background-color-gray); + border-radius: #{$border-radius-large}; + background: var(--background-color); + outline: 1px solid var(--border-color); + outline-offset: -1px; padding: 8px; padding-top: 12px; font-weight: $bold-weight; @@ -1193,8 +1187,6 @@ position: relative; z-index: 3; font-size: var(--font-size-regular); - // -webkit-text-fill-color: transparent; - // -webkit-text-stroke: 1px black; } &::after { @@ -1260,7 +1252,6 @@ .category-image { position: absolute; - // top: 50%; bottom: 0; right: -10px; transform: translate(0, 0%) scale(0.8); @@ -1276,14 +1267,15 @@ flex-direction: row; flex-wrap: wrap; height: 100%; - gap: 3px; + gap: 0px 4px; padding: 10px 0; .assets { - width: 117px; + width: 123px; height: 95px; - border-radius: #{$border-radius-small}; - background: var(--background-color-gray); + border-radius: #{$border-radius-large}; + background: var(--background-color); + outline: 1px solid var(--border-color); font-weight: $medium-weight; position: relative; overflow: hidden; @@ -1301,18 +1293,16 @@ z-index: 3; padding: 8px; width: 100%; - max-height: 38px; + height: 100%; font-size: var(--font-size-regular); - background: color-mix( - in srgb, - var(--background-color) 40%, - transparent - ); - backdrop-filter: blur(5px); + background: linear-gradient(0deg,rgba(37, 24, 51, 0) 0%, rgba(78, 22, 128, 0.4) 100%); + pointer-events: none; + backdrop-filter: blur(8px); opacity: 0; transition: opacity 0.3s ease; display: -webkit-box; - -webkit-line-clamp: 2; + -webkit-line-clamp: 3; + line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; @@ -1337,46 +1327,6 @@ } } -.assets-container { - width: 100%; - display: flex; - flex-direction: row; - flex-wrap: wrap; - height: 100%; - gap: 3px; - padding: 10px 0; - - .assets { - width: 117px; - height: 95px; - border-radius: 3.59px; - background: var(--background-color-gray); - padding: 8px; - padding-top: 12px; - font-weight: $medium-weight; - position: relative; - overflow: hidden; - - .asset-name { - position: relative; - z-index: 3; - font-size: var(--font-size-regular); - } - - .asset-image { - height: 100%; - width: 100%; - position: absolute; - // top: 50%; - // right: 5px; - // transform: translate(0, -50%); - top: 0; - left: 0; - z-index: 2; - } - } -} - .assets-result { width: 100%; height: 100%; From 4b87650528633d089a260d53fe73ea27c4a1f755 Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Wed, 30 Apr 2025 11:32:13 +0530 Subject: [PATCH 07/14] added ui and its functionality for changing position of vehicles pickup-point and unloadPoint --- .../simulation/ui/vehicle/vehicleUI.tsx | 45 ++++++++++++------- .../instances/animator/vehicleAnimator.tsx | 13 +++--- .../instances/instance/vehicleInstance.tsx | 6 +-- .../modules/simulation/vehicle/vehicles.tsx | 3 +- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx b/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx index b498431..5dec724 100644 --- a/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx +++ b/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx @@ -46,18 +46,17 @@ const VehicleUI = () => { pickUpPoint.rotation.y, pickUpPoint.rotation.z ); - pickupPosition.y = 0; // Force y to 0 + pickupPosition.y = 0; setStartPosition([pickupPosition.x, 0, pickupPosition.z]); setStartRotation([pickupRotation.x, pickupRotation.y, pickupRotation.z]); } else { const defaultLocal = new THREE.Vector3(0, 0, 1.5); const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); - defaultWorld.y = 0; // Force y to 0 + defaultWorld.y = 0; setStartPosition([defaultWorld.x, 0, defaultWorld.z]); setStartRotation([0, 0, 0]); } - // Initialize end marker position and rotation if (unLoadPoint) { const unLoadPosition = new THREE.Vector3( unLoadPoint.position.x, @@ -109,8 +108,13 @@ const VehicleUI = () => { if (marker) { const rotationSpeed = 10; - marker.rotation.y -= deltaX * rotationSpeed; + marker.rotation.y += deltaX * rotationSpeed; + if (isRotating === 'start') { + setStartRotation([marker.rotation.x, marker.rotation.y, marker.rotation.z]) + } else { + setEndRotation([marker.rotation.x, marker.rotation.y, marker.rotation.z]) + } } }); @@ -133,7 +137,6 @@ const VehicleUI = () => { }; const handlePointerUp = () => { - console.log("nulll"); controls.enabled = true; setIsDragging(null); setIsRotating(null); @@ -180,7 +183,22 @@ const VehicleUI = () => { } }; + useEffect(() => { + const handleGlobalPointerUp = () => { + setIsDragging(null); + setIsRotating(null); + if (controls) controls.enabled = true; + handlePointerUp(); + }; + if (isDragging || isRotating) { + window.addEventListener("pointerup", handleGlobalPointerUp); + } + + return () => { + window.removeEventListener("pointerup", handleGlobalPointerUp); + }; + }, [isDragging, isRotating, startPosition, startRotation, endPosition, endRotation]); return ( startPosition.length > 0 && endPosition.length > 0 ? ( @@ -194,12 +212,10 @@ const VehicleUI = () => { e.stopPropagation(); handlePointerDown(e, "start", "start"); }} - onPointerUp={() => { - handlePointerUp(); - }} onPointerMissed={() => { - console.log("start pointermissed"); - handlePointerUp(); + controls.enabled = true; + setIsDragging(null); + setIsRotating(null); }} /> @@ -212,13 +228,10 @@ const VehicleUI = () => { e.stopPropagation(); handlePointerDown(e, "end", "end"); }} - onPointerUp={() => { - console.log("up"); - handlePointerUp(); - }} onPointerMissed={() => { - console.log("end pointermissed"); - handlePointerUp(); + controls.enabled = true; + setIsDragging(null); + setIsRotating(null); }} /> diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index d232734..2f0b235 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -32,14 +32,18 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai let startTime: number; let fixedInterval: number; let coveredDistance = progressRef.current; + let objectRotation = (agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 }) as { x: number; y: number; z: number }; useEffect(() => { if (currentPhase === 'stationed-pickup' && path.length > 0) { setCurrentPath(path); + objectRotation = agvDetail.point.action?.pickUpPoint?.rotation } else if (currentPhase === 'pickup-drop' && path.length > 0) { + objectRotation = agvDetail.point.action?.unLoadPoint?.rotation setCurrentPath(path); } else if (currentPhase === 'drop-pickup' && path.length > 0) { + objectRotation = agvDetail.point.action?.pickUpPoint?.rotation setCurrentPath(path); } }, [currentPhase, path]); @@ -63,10 +67,10 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai setRestingRotation(true); decrementVehicleLoad(agvDetail.modelUuid, 0); const object = scene.getObjectByProperty('uuid', agvUuid); + console.log('currentPhase: ', currentPhase); if (object) { object.position.set(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]); - let objectRotation = agvDetail.point.rotation - object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); + object.rotation.set(objectRotation.x, objectRotation.y, objectRotation.z); } } }, [isReset, isPlaying]) @@ -129,12 +133,11 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai if (progressRef.current >= totalDistance) { if (restRotation) { - const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0)); + const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(objectRotation.x, objectRotation.y, objectRotation.z)); object.quaternion.slerp(targetQuaternion, delta * 2); const angleDiff = object.quaternion.angleTo(targetQuaternion); if (angleDiff < 0.01) { - let objectRotation = agvDetail.point.rotation - object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); + object.rotation.set(objectRotation.x, objectRotation.y, objectRotation.z); setRestingRotation(false); } return; diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index b82c6cd..6a81d3a 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -30,7 +30,7 @@ function VehicleInstance({ agvDetail }: any) { ); function vehicleStatus(modelId: string, status: string) { - console.log(`AGV ${modelId}: ${status}`); + // console.log(`${modelId} , ${status}); } // Function to reset everything @@ -43,7 +43,7 @@ function VehicleInstance({ agvDetail }: any) { const increment = () => { if (isIncrememtable.current) { - console.log('called'); + incrementVehicleLoad(agvDetail.modelUuid, 2); isIncrememtable.current = false; } @@ -51,7 +51,7 @@ function VehicleInstance({ agvDetail }: any) { useEffect(() => { if (isPlaying) { - + if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') { const toPickupPath = computePath( new THREE.Vector3(agvDetail?.position[0], agvDetail?.position[1], agvDetail?.position[2]), diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx index e54539f..9646174 100644 --- a/app/src/modules/simulation/vehicle/vehicles.tsx +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -190,7 +190,8 @@ function Vehicles() { // } ]); useEffect(() => { - console.log("vehicles", vehicles); + console.log('vehicles: ', vehicles); + }, [vehicles]) useEffect(() => { From 014bc3a7cae153f0372f1266c71fe33940eb76d1 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Wed, 30 Apr 2025 11:46:20 +0530 Subject: [PATCH 08/14] Refactor model identifier naming conventions from 'modeluuid' and 'modelname' to 'modelUuid' and 'modelName' across multiple modules for consistency and clarity. Update related API calls and local storage handling to reflect these changes. Remove unused deleteProductDataApi service and implement deleteProductApi service for product data deletion. Introduce steeringAngle property in vehicle configurations. --- .../sidebarRight/simulation/Simulations.tsx | 10 +++- app/src/components/ui/list/DropDownList.tsx | 4 +- app/src/components/ui/list/List.tsx | 4 +- .../IntialLoad/loadInitialFloorItems.ts | 45 ++++++++-------- .../IntialLoad/loadInitialWallItems.ts | 6 +-- .../geomentries/assets/addAssetModel.ts | 35 ++++++------ .../geomentries/assets/assetManager.ts | 18 +++---- .../geomentries/assets/deleteFloorItems.ts | 17 +++--- .../builder/geomentries/walls/addWallItems.ts | 10 ++-- .../geomentries/walls/deleteWallItems.ts | 8 +-- .../builder/groups/floorItemsGroup.tsx | 1 - .../modules/builder/groups/wallItemsGroup.tsx | 8 +-- .../socket/socketResponses.dev.tsx | 54 +++++++++---------- .../selectionControls/copyPasteControls.tsx | 12 ++--- .../selectionControls/duplicationControls.tsx | 12 ++--- .../selectionControls/moveControls.tsx | 20 +++---- .../selectionControls/rotateControls.tsx | 20 +++---- .../selectionControls/selectionControls.tsx | 13 +++-- .../armInstance/roboticArmInstance.tsx | 4 +- app/src/modules/simulation/simulation.tsx | 4 +- .../modules/simulation/vehicle/vehicles.tsx | 3 ++ .../assest/floorAsset/deleteFloorItemApi.ts | 4 +- .../assest/floorAsset/setFloorItemApi.ts | 6 +-- .../assest/wallAsset/deleteWallItemApi.ts | 4 +- .../assest/wallAsset/setWallItemApi.ts | 6 +-- .../webWorkers/assetManagerWorker.js | 4 +- ...eProductDataApi.ts => deleteProductApi.ts} | 2 +- app/src/store/simulation/useProductStore.ts | 11 +++- app/src/store/simulation/useVehicleStore.ts | 10 ++++ app/src/types/simulationTypes.d.ts | 1 + app/src/types/world/worldTypes.d.ts | 8 +-- 31 files changed, 203 insertions(+), 161 deletions(-) rename app/src/services/simulation/{deleteProductDataApi.ts => deleteProductApi.ts} (89%) diff --git a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx index ca29087..bad955b 100644 --- a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx +++ b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx @@ -18,6 +18,8 @@ import EditWidgetOption from "../../../ui/menu/EditWidgetOption"; import { handleAddEventToProduct } from "../../../../modules/simulation/events/points/functions/handleAddEventToProduct"; import { useEventsStore } from "../../../../store/simulation/useEventsStore"; import { deleteEventDataApi } from "../../../../services/simulation/deleteEventDataApi"; +import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi"; +import { deleteProductApi } from "../../../../services/simulation/deleteProductApi"; interface Event { pathName: string; @@ -41,9 +43,14 @@ const Simulations: React.FC = () => { const { selectedProduct, setSelectedProduct } = useSelectedProduct(); const { getEventByModelUuid } = useEventsStore(); const { selectedAsset, clearSelectedAsset } = useSelectedAsset(); + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; const handleAddProduct = () => { - addProduct(`Product ${products.length + 1}`, generateUUID()); + const id = generateUUID(); + const name = `Product ${products.length + 1}`; + addProduct(name, id); + upsertProductOrEventApi({ productName: name, productId: id, organization: organization }); }; const handleRemoveProduct = (productId: string) => { @@ -68,6 +75,7 @@ const Simulations: React.FC = () => { } removeProduct(productId); + deleteProductApi(productId, organization); }; const handleRenameProduct = (productId: string, newName: string) => { diff --git a/app/src/components/ui/list/DropDownList.tsx b/app/src/components/ui/list/DropDownList.tsx index 0416a9e..d0b62e8 100644 --- a/app/src/components/ui/list/DropDownList.tsx +++ b/app/src/components/ui/list/DropDownList.tsx @@ -81,8 +81,8 @@ const DropDownList: React.FC = ({ return isPointInsidePolygon([x, z], polygon2D); }) .map((item: any) => ({ - id: item.modeluuid, - name: item.modelname, + id: item.modelUuid, + name: item.modelName, position: item.position, rotation: item.rotation })); diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx index 06419af..cdd2a53 100644 --- a/app/src/components/ui/list/List.tsx +++ b/app/src/components/ui/list/List.tsx @@ -136,8 +136,8 @@ const List: React.FC = ({ items = [], remove }) => { console.log('response: ', response); setFloorItems((prevFloorItems: any[]) => prevFloorItems.map((floorItems) => - floorItems.modeluuid === zoneAssetId.id - ? { ...floorItems, modelname: response.modelname } + floorItems.modelUuid === zoneAssetId.id + ? { ...floorItems, modelName: response.modelName } : floorItems ) ); diff --git a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts index f09f130..a351d73 100644 --- a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts +++ b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts @@ -72,7 +72,7 @@ async function loadInitialFloorItems( // Check Three.js Cache const cachedModel = THREE.Cache.get(item.modelfileID!); if (cachedModel) { - // console.log(`[Cache] Fetching ${item.modelname}`); + // console.log(`[Cache] Fetching ${item.modelName}`); processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems, addEvent); modelsLoaded++; checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve); @@ -82,7 +82,7 @@ async function loadInitialFloorItems( // Check IndexedDB const indexedDBModel = await retrieveGLTF(item.modelfileID!); if (indexedDBModel) { - // console.log(`[IndexedDB] Fetching ${item.modelname}`); + // console.log(`[IndexedDB] Fetching ${item.modelName}`); const blobUrl = URL.createObjectURL(indexedDBModel); loader.load(blobUrl, (gltf) => { URL.revokeObjectURL(blobUrl); @@ -94,7 +94,7 @@ async function loadInitialFloorItems( }, undefined, (error) => { - toast.error(`[IndexedDB] Error loading ${item.modelname}:`); + toast.error(`[IndexedDB] Error loading ${item.modelName}:`); URL.revokeObjectURL(blobUrl); resolve(); } @@ -103,7 +103,7 @@ async function loadInitialFloorItems( } // Fetch from Backend - // console.log(`[Backend] Fetching ${item.modelname}`); + // console.log(`[Backend] Fetching ${item.modelName}`); const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${item.modelfileID!}`; loader.load(modelUrl, async (gltf) => { const modelBlob = await fetch(modelUrl).then((res) => res.blob()); @@ -115,18 +115,18 @@ async function loadInitialFloorItems( }, undefined, (error) => { - toast.error(`[Backend] Error loading ${item.modelname}:`); + toast.error(`[Backend] Error loading ${item.modelName}:`); resolve(); } ); }); } else { - // console.log(`Item ${item.modelname} is not near`); + // console.log(`Item ${item.modelName} is not near`); setFloorItems((prevItems) => [ ...(prevItems || []), { - modeluuid: item.modeluuid, - modelname: item.modelname, + modelUuid: item.modelUuid, + modelName: item.modelName, position: item.position, rotation: item.rotation, modelfileID: item.modelfileID, @@ -154,9 +154,9 @@ function processLoadedModel( addEvent: (event: EventsSchema) => void, ) { const model = gltf.clone(); - model.uuid = item.modeluuid; + model.uuid = item.modelUuid; model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); - model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid, eventData: item.eventData }; + model.userData = { name: item.modelName, modelId: item.modelfileID, modelUuid: item.modelUuid, eventData: item.eventData }; model.position.set(...item.position); model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z); @@ -176,8 +176,8 @@ function processLoadedModel( setFloorItems((prevItems) => [ ...(prevItems || []), { - modeluuid: item.modeluuid, - modelname: item.modelname, + modelUuid: item.modelUuid, + modelName: item.modelName, position: item.position, rotation: item.rotation, modelfileID: item.modelfileID, @@ -189,8 +189,8 @@ function processLoadedModel( if (item.eventData.type === "vehicle") { const vehicleEvent: VehicleEventSchema = { - modelUuid: item.modeluuid, - modelName: item.modelname, + modelUuid: item.modelUuid, + modelName: item.modelName, position: item.position, rotation: [item.rotation.x, item.rotation.y, item.rotation.z], state: "idle", @@ -206,6 +206,7 @@ function processLoadedModel( actionType: "travel", unLoadDuration: 5, loadCapacity: 10, + steeringAngle:0, pickUpPoint: null, unLoadPoint: null, triggers: [] @@ -215,8 +216,8 @@ function processLoadedModel( addEvent(vehicleEvent); } else if (item.eventData.type === "Conveyor") { const ConveyorEvent: ConveyorEventSchema = { - modelUuid: item.modeluuid, - modelName: item.modelname, + modelUuid: item.modelUuid, + modelName: item.modelName, position: item.position, rotation: [item.rotation.x, item.rotation.y, item.rotation.z], state: "idle", @@ -241,8 +242,8 @@ function processLoadedModel( addEvent(ConveyorEvent); } else if (item.eventData.type === "StaticMachine") { const machineEvent: MachineEventSchema = { - modelUuid: item.modeluuid, - modelName: item.modelname, + modelUuid: item.modelUuid, + modelName: item.modelName, position: item.position, rotation: [item.rotation.x, item.rotation.y, item.rotation.z], state: "idle", @@ -264,8 +265,8 @@ function processLoadedModel( addEvent(machineEvent); } else if (item.eventData.type === "ArmBot") { const roboticArmEvent: RoboticArmEventSchema = { - modelUuid: item.modeluuid, - modelName: item.modelname, + modelUuid: item.modelUuid, + modelName: item.modelName, position: item.position, rotation: [item.rotation.x, item.rotation.y, item.rotation.z], state: "idle", @@ -296,8 +297,8 @@ function processLoadedModel( setFloorItems((prevItems) => [ ...(prevItems || []), { - modeluuid: item.modeluuid, - modelname: item.modelname, + modelUuid: item.modelUuid, + modelName: item.modelName, position: item.position, rotation: item.rotation, modelfileID: item.modelfileID, diff --git a/app/src/modules/builder/IntialLoad/loadInitialWallItems.ts b/app/src/modules/builder/IntialLoad/loadInitialWallItems.ts index 34273af..f9799a8 100644 --- a/app/src/modules/builder/IntialLoad/loadInitialWallItems.ts +++ b/app/src/modules/builder/IntialLoad/loadInitialWallItems.ts @@ -22,9 +22,9 @@ async function loadInitialWallItems( const loadedWallItems = await Promise.all(storedWallItems.map(async (item) => { const loader = new GLTFLoader(); return new Promise((resolve) => { - loader.load(AssetConfigurations[item.modelname!].modelUrl, (gltf) => { + loader.load(AssetConfigurations[item.modelName!].modelUrl, (gltf) => { const model = gltf.scene; - model.uuid = item.modeluuid!; + model.uuid = item.modelUuid!; model.children[0].children.forEach((child: any) => { if (child.name !== "CSG_REF") { @@ -36,7 +36,7 @@ async function loadInitialWallItems( resolve({ type: item.type, model: model, - modelname: item.modelname, + modelName: item.modelName, scale: item.scale, csgscale: item.csgscale, csgposition: item.csgposition, diff --git a/app/src/modules/builder/geomentries/assets/addAssetModel.ts b/app/src/modules/builder/geomentries/assets/addAssetModel.ts index ab9d90d..0bc7352 100644 --- a/app/src/modules/builder/geomentries/assets/addAssetModel.ts +++ b/app/src/modules/builder/geomentries/assets/addAssetModel.ts @@ -117,7 +117,7 @@ async function handleModelLoad( socket: Socket ) { const model = gltf.scene.clone(); - model.userData = { name: selectedItem.name, modelId: selectedItem.id, modeluuid: model.uuid }; + model.userData = { name: selectedItem.name, modelId: selectedItem.id, modelUuid: model.uuid }; model.position.set(intersectPoint!.x, 3 + intersectPoint!.y, intersectPoint!.z); model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); @@ -137,8 +137,8 @@ async function handleModelLoad( } const newFloorItem: Types.FloorItemType = { - modeluuid: model.uuid, - modelname: selectedItem.name, + modelUuid: model.uuid, + modelName: selectedItem.name, modelfileID: selectedItem.id, position: [intersectPoint!.x, intersectPoint!.y, intersectPoint!.z], rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z }, @@ -153,8 +153,8 @@ async function handleModelLoad( // await setFloorItemApi( // organization, - // newFloorItem.modeluuid, - // newFloorItem.modelname, + // newFloorItem.modelUuid, + // newFloorItem.modelName, // newFloorItem.modelfileID, // newFloorItem.position, // { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z }, @@ -179,8 +179,8 @@ async function handleModelLoad( if (selectedItem.type === "Conveyor") { const ConveyorEvent: ConveyorEventSchema = { - modelUuid: newFloorItem.modeluuid, - modelName: newFloorItem.modelname, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, position: newFloorItem.position, rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], state: "idle", @@ -211,8 +211,8 @@ async function handleModelLoad( } else if (selectedItem.type === "Vehicle") { const vehicleEvent: VehicleEventSchema = { - modelUuid: newFloorItem.modeluuid, - modelName: newFloorItem.modelname, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, position: newFloorItem.position, rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], state: "idle", @@ -228,6 +228,7 @@ async function handleModelLoad( actionType: "travel", unLoadDuration: 5, loadCapacity: 10, + steeringAngle:0, pickUpPoint: null, unLoadPoint: null, triggers: [] @@ -243,8 +244,8 @@ async function handleModelLoad( } else if (selectedItem.type === "ArmBot") { const roboticArmEvent: RoboticArmEventSchema = { - modelUuid: newFloorItem.modeluuid, - modelName: newFloorItem.modelname, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, position: newFloorItem.position, rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], state: "idle", @@ -278,8 +279,8 @@ async function handleModelLoad( } else if (selectedItem.type === "StaticMachine") { const machineEvent: MachineEventSchema = { - modelUuid: newFloorItem.modeluuid, - modelName: newFloorItem.modelname, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, position: newFloorItem.position, rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], state: "idle", @@ -308,8 +309,8 @@ async function handleModelLoad( const completeData = { organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, modelfileID: newFloorItem.modelfileID, position: newFloorItem.position, rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z }, @@ -337,8 +338,8 @@ async function handleModelLoad( const data = { organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, modelfileID: newFloorItem.modelfileID, position: newFloorItem.position, rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z }, diff --git a/app/src/modules/builder/geomentries/assets/assetManager.ts b/app/src/modules/builder/geomentries/assets/assetManager.ts index 5ff75a3..5f7798e 100644 --- a/app/src/modules/builder/geomentries/assets/assetManager.ts +++ b/app/src/modules/builder/geomentries/assets/assetManager.ts @@ -58,7 +58,7 @@ export default async function assetManager( // Check Three.js Cache const cachedModel = THREE.Cache.get(item.modelfileID!); if (cachedModel) { - // console.log(`[Cache] Fetching ${item.modelname}`); + // console.log(`[Cache] Fetching ${item.modelName}`); processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, resolve); return; } @@ -66,7 +66,7 @@ export default async function assetManager( // Check IndexedDB const indexedDBModel = await retrieveGLTF(item.modelfileID!); if (indexedDBModel) { - // console.log(`[IndexedDB] Fetching ${item.modelname}`); + // console.log(`[IndexedDB] Fetching ${item.modelName}`); const blobUrl = URL.createObjectURL(indexedDBModel); loader.load( blobUrl, @@ -78,7 +78,7 @@ export default async function assetManager( }, undefined, (error) => { - toast.error(`[IndexedDB] Error loading ${item.modelname}:`); + toast.error(`[IndexedDB] Error loading ${item.modelName}:`); resolve(); } ); @@ -86,7 +86,7 @@ export default async function assetManager( } // Fetch from Backend - // console.log(`[Backend] Fetching ${item.modelname}`); + // console.log(`[Backend] Fetching ${item.modelName}`); loader.load( modelUrl, async (gltf) => { @@ -97,7 +97,7 @@ export default async function assetManager( }, undefined, (error) => { - toast.error(`[Backend] Error loading ${item.modelname}:`); + toast.error(`[Backend] Error loading ${item.modelName}:`); resolve(); } ); @@ -112,16 +112,16 @@ export default async function assetManager( ) { if (!activePromises.get(taskId)) return; // Stop processing if task is canceled - const existingModel = itemsGroup?.current?.getObjectByProperty("uuid", item.modeluuid); + const existingModel = itemsGroup?.current?.getObjectByProperty("uuid", item.modelUuid); if (existingModel) { - // console.log(`Model ${item.modelname} already exists in the scene.`); + // console.log(`Model ${item.modelName} already exists in the scene.`); resolve(); return; } const model = gltf; - model.uuid = item.modeluuid; - model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid }; + model.uuid = item.modelUuid; + model.userData = { name: item.modelName, modelId: item.modelfileID, modelUuid: item.modelUuid }; model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); model.position.set(...item.position); model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z); diff --git a/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts b/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts index 18136b3..f13ebee 100644 --- a/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts +++ b/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts @@ -5,6 +5,8 @@ import * as Types from "../../../../types/world/worldTypes"; // import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi'; import { Socket } from 'socket.io-client'; import { getFloorAssets } from '../../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi'; +import { useEventsStore } from "../../../../store/simulation/useEventsStore"; +import { useProductStore } from "../../../../store/simulation/useProductStore"; async function DeleteFloorItems( itemsGroup: Types.RefGroup, @@ -22,7 +24,7 @@ async function DeleteFloorItems( const items = await getFloorAssets(organization); const removedItem = items.find( - (item: { modeluuid: string }) => item.modeluuid === hoveredDeletableFloorItem.current?.uuid + (item: { modelUuid: string }) => item.modelUuid === hoveredDeletableFloorItem.current?.uuid ); if (!removedItem) { @@ -31,26 +33,29 @@ async function DeleteFloorItems( //REST - // const response = await deleteFloorItem(organization, removedItem.modeluuid, removedItem.modelname); + // const response = await deleteFloorItem(organization, removedItem.modelUuid, removedItem.modelName); //SOCKET const data = { organization: organization, - modeluuid: removedItem.modeluuid, - modelname: removedItem.modelname, + modelUuid: removedItem.modelUuid, + modelName: removedItem.modelName, socketId: socket.id } const response = socket.emit('v2:model-asset:delete', data) + useEventsStore.getState().removeEvent(removedItem.modelUuid); + useProductStore.getState().deleteEvent(removedItem.modelUuid); + if (response) { const updatedItems = items.filter( - (item: { modeluuid: string }) => item.modeluuid !== hoveredDeletableFloorItem.current?.uuid + (item: { modelUuid: string }) => item.modelUuid !== hoveredDeletableFloorItem.current?.uuid ); const storedItems = JSON.parse(localStorage.getItem("FloorItems") || '[]'); - const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => item.modeluuid !== hoveredDeletableFloorItem.current?.uuid); + const updatedStoredItems = storedItems.filter((item: { modelUuid: string }) => item.modelUuid !== hoveredDeletableFloorItem.current?.uuid); localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); if (hoveredDeletableFloorItem.current) { diff --git a/app/src/modules/builder/geomentries/walls/addWallItems.ts b/app/src/modules/builder/geomentries/walls/addWallItems.ts index 9c578aa..fd9eb48 100644 --- a/app/src/modules/builder/geomentries/walls/addWallItems.ts +++ b/app/src/modules/builder/geomentries/walls/addWallItems.ts @@ -43,7 +43,7 @@ async function AddWallItems( const newWallItem = { type: config.type, model: model, - modelname: selected, + modelName: selected, scale: config.scale, csgscale: config.csgscale, csgposition: config.csgposition, @@ -59,7 +59,7 @@ async function AddWallItems( // await setWallItem( // organization, // model.uuid, - // newWallItem.modelname, + // newWallItem.modelName, // newWallItem.type!, // newWallItem.csgposition!, // newWallItem.csgscale!, @@ -72,8 +72,8 @@ async function AddWallItems( const data = { organization: organization, - modeluuid: model.uuid, - modelname: newWallItem.modelname, + modelUuid: model.uuid, + modelName: newWallItem.modelName, type: newWallItem.type!, csgposition: newWallItem.csgposition!, csgscale: newWallItem.csgscale!, @@ -92,7 +92,7 @@ async function AddWallItems( const { model, ...rest } = item; return { ...rest, - modeluuid: model?.uuid, + modelUuid: model?.uuid, }; }); diff --git a/app/src/modules/builder/geomentries/walls/deleteWallItems.ts b/app/src/modules/builder/geomentries/walls/deleteWallItems.ts index abbf0c8..b5d40f4 100644 --- a/app/src/modules/builder/geomentries/walls/deleteWallItems.ts +++ b/app/src/modules/builder/geomentries/walls/deleteWallItems.ts @@ -28,14 +28,14 @@ function DeleteWallItems( //REST - // await deleteWallItem(organization, removedItem?.model?.uuid!, removedItem?.modelname!) + // await deleteWallItem(organization, removedItem?.model?.uuid!, removedItem?.modelName!) //SOCKET const data = { organization: organization, - modeluuid: removedItem?.model?.uuid!, - modelname: removedItem?.modelname!, + modelUuid: removedItem?.model?.uuid!, + modelName: removedItem?.modelName!, socketId: socket.id } @@ -45,7 +45,7 @@ function DeleteWallItems( const { model, ...rest } = item; return { ...rest, - modeluuid: model?.uuid, + modelUuid: model?.uuid, }; }); diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx index f1da0a4..f3f5050 100644 --- a/app/src/modules/builder/groups/floorItemsGroup.tsx +++ b/app/src/modules/builder/groups/floorItemsGroup.tsx @@ -65,7 +65,6 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject }; getFloorAssets(organization).then((data) => { - console.log('data: ', data); if (data.length > 0) { const uniqueItems = (data as Types.FloorItems).filter((item, index, self) => index === self.findIndex((t) => t.modelfileID === item.modelfileID)); totalAssets = uniqueItems.length; diff --git a/app/src/modules/builder/groups/wallItemsGroup.tsx b/app/src/modules/builder/groups/wallItemsGroup.tsx index 43845e7..f993754 100644 --- a/app/src/modules/builder/groups/wallItemsGroup.tsx +++ b/app/src/modules/builder/groups/wallItemsGroup.tsx @@ -91,7 +91,7 @@ const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletable const { model, ...rest } = item; return { ...rest, - modeluuid: model?.uuid, + modelUuid: model?.uuid, }; }); @@ -110,7 +110,7 @@ const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletable // await setWallItem( // organization, // currentItem?.model?.uuid, - // currentItem.modelname, + // currentItem.modelName, // currentItem.type!, // currentItem.csgposition!, // currentItem.csgscale!, @@ -123,8 +123,8 @@ const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletable const data = { organization: organization, - modeluuid: currentItem.model?.uuid!, - modelname: currentItem.modelname!, + modelUuid: currentItem.model?.uuid!, + modelName: currentItem.modelName!, type: currentItem.type!, csgposition: currentItem.csgposition!, csgscale: currentItem.csgscale!, diff --git a/app/src/modules/collaboration/socket/socketResponses.dev.tsx b/app/src/modules/collaboration/socket/socketResponses.dev.tsx index 3d9cddf..86e41c2 100644 --- a/app/src/modules/collaboration/socket/socketResponses.dev.tsx +++ b/app/src/modules/collaboration/socket/socketResponses.dev.tsx @@ -99,13 +99,13 @@ export default function SocketResponses({ try { isTempLoader.current = true; - const cachedModel = THREE.Cache.get(data.data.modelname); + const cachedModel = THREE.Cache.get(data.data.modelName); let url; if (cachedModel) { - // console.log(`Getting ${data.data.modelname} from cache`); + // console.log(`Getting ${data.data.modelName} from cache`); const model = cachedModel.scene.clone(); - model.uuid = data.data.modeluuid; - model.userData = { name: data.data.modelname, modelId: data.data.modelfileID, modeluuid: data.data.modeluuid }; + model.uuid = data.data.modelUuid; + model.userData = { name: data.data.modelName, modelId: data.data.modelfileID, modelUuid: data.data.modelUuid }; model.position.set(...data.data.position as [number, number, number]); model.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); @@ -130,8 +130,8 @@ export default function SocketResponses({ } const newFloorItem: Types.FloorItemType = { - modeluuid: data.data.modeluuid, - modelname: data.data.modelname, + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, modelfileID: data.data.modelfileID, position: [...data.data.position as [number, number, number]], rotation: { @@ -153,12 +153,12 @@ export default function SocketResponses({ gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out', onComplete: () => { toast.success("Model Added!") } }); } else { - const indexedDBModel = await retrieveGLTF(data.data.modelname); + const indexedDBModel = await retrieveGLTF(data.data.modelName); if (indexedDBModel) { - // console.log(`Getting ${data.data.modelname} from IndexedDB`); + // console.log(`Getting ${data.data.modelName} from IndexedDB`); url = URL.createObjectURL(indexedDBModel); } else { - // console.log(`Getting ${data.data.modelname} from Backend`); + // console.log(`Getting ${data.data.modelName} from Backend`); url = `${url_Backend_dwinzo}/api/v2/AssetFile/${data.data.modelfileID}`; const modelBlob = await fetch(url).then((res) => res.blob()); await storeGLTF(data.data.modelfileID, modelBlob); @@ -178,8 +178,8 @@ export default function SocketResponses({ URL.revokeObjectURL(url); THREE.Cache.remove(url); const model = gltf.scene; - model.uuid = data.data.modeluuid; - model.userData = { name: data.data.modelname, modelId: data.data.modelfileID, modeluuid: data.data.modeluuid }; + model.uuid = data.data.modelUuid; + model.userData = { name: data.data.modelName, modelId: data.data.modelfileID, modelUuid: data.data.modelUuid }; model.position.set(...data.data.position as [number, number, number]); model.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); @@ -204,8 +204,8 @@ export default function SocketResponses({ } const newFloorItem: Types.FloorItemType = { - modeluuid: data.data.modeluuid, - modelname: data.data.modelname, + modelUuid: data.data.modelUuid, + modelName: data.data.modelName, modelfileID: data.data.modelfileID, position: [...data.data.position as [number, number, number]], rotation: { @@ -226,7 +226,7 @@ export default function SocketResponses({ gsap.to(model.position, { y: data.data.position[1], duration: 1.5, ease: 'power2.out' }); gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out', onComplete: () => { toast.success("Model Added!") } }); - THREE.Cache.add(data.data.modelname, gltf); + THREE.Cache.add(data.data.modelName, gltf); }, () => { TempLoader(new THREE.Vector3(...data.data.position), isTempLoader, tempLoader, itemsGroup); }); @@ -234,7 +234,7 @@ export default function SocketResponses({ } else if (data.message === "Model updated successfully") { itemsGroup.current?.children.forEach((item: THREE.Group) => { - if (item.uuid === data.data.modeluuid) { + if (item.uuid === data.data.modelUuid) { item.position.set(...data.data.position as [number, number, number]); item.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z); } @@ -246,7 +246,7 @@ export default function SocketResponses({ } let updatedItem: any = null; const updatedItems = prevItems.map((item) => { - if (item.modeluuid === data.data.modeluuid) { + if (item.modelUuid === data.data.modelUuid) { updatedItem = { ...item, position: [...data.data.position] as [number, number, number], @@ -269,15 +269,15 @@ export default function SocketResponses({ return } if (data.message === "Model deleted successfully") { - const deletedUUID = data.data.modeluuid; + const deletedUUID = data.data.modelUuid; let items = JSON.parse(localStorage.getItem("FloorItems")!); const updatedItems = items.filter( - (item: { modeluuid: string }) => item.modeluuid !== deletedUUID + (item: { modelUuid: string }) => item.modelUuid !== deletedUUID ); const storedItems = JSON.parse(localStorage.getItem("FloorItems") || '[]'); - const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => item.modeluuid !== deletedUUID); + const updatedStoredItems = storedItems.filter((item: { modelUuid: string }) => item.modelUuid !== deletedUUID); localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); itemsGroup.current.children.forEach((item: any) => { @@ -519,7 +519,7 @@ export default function SocketResponses({ return } if (data.message === "wallitem deleted") { - const deletedUUID = data.data.modeluuid; + const deletedUUID = data.data.modelUuid; let WallItemsRef = wallItems; const Items = WallItemsRef.filter((item: any) => item.model?.uuid !== deletedUUID); @@ -531,7 +531,7 @@ export default function SocketResponses({ const { model, ...rest } = item; return { ...rest, - modeluuid: model?.uuid, + modelUuid: model?.uuid, }; }); @@ -550,9 +550,9 @@ export default function SocketResponses({ } if (data.message === "wallIitem created") { const loader = new GLTFLoader(); - loader.load(AssetConfigurations[data.data.modelname].modelUrl, async (gltf) => { + loader.load(AssetConfigurations[data.data.modelName].modelUrl, async (gltf) => { const model = gltf.scene; - model.uuid = data.data.modeluuid; + model.uuid = data.data.modelUuid; model.children[0].children.forEach((child) => { if (child.name !== "CSG_REF") { child.castShadow = true; @@ -563,7 +563,7 @@ export default function SocketResponses({ const newWallItem = { type: data.data.type, model: model, - modelname: data.data.modelname, + modelName: data.data.modelName, scale: data.data.scale, csgscale: data.data.csgscale, csgposition: data.data.csgposition, @@ -578,7 +578,7 @@ export default function SocketResponses({ const { model, ...rest } = item; return { ...rest, - modeluuid: model?.uuid, + modelUuid: model?.uuid, }; }); @@ -589,7 +589,7 @@ export default function SocketResponses({ }); }); } else if (data.message === "wallIitem updated") { - const updatedUUID = data.data.modeluuid; + const updatedUUID = data.data.modelUuid; setWallItems((prevItems: any) => { const updatedItems = prevItems.map((item: any) => { @@ -610,7 +610,7 @@ export default function SocketResponses({ const { model, ...rest } = item; return { ...rest, - modeluuid: model?.uuid, + modelUuid: model?.uuid, }; }); diff --git a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx b/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx index c92c98f..613fe43 100644 --- a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx @@ -170,8 +170,8 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas } const newFloorItem: Types.FloorItemType = { - modeluuid: obj.uuid, - modelname: obj.userData.name, + modelUuid: obj.uuid, + modelName: obj.userData.name, modelfileID: obj.userData.modelId, position: [worldPosition.x, worldPosition.y, worldPosition.z], rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, @@ -206,8 +206,8 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas const data = { organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, modelfileID: newFloorItem.modelfileID, position: newFloorItem.position, rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, @@ -220,9 +220,9 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas socket.emit("v2:model-asset:add", data); obj.userData = { - name: newFloorItem.modelname, + name: newFloorItem.modelName, modelId: newFloorItem.modelfileID, - modeluuid: newFloorItem.modeluuid, + modelUuid: newFloorItem.modelUuid, eventData: updatedEventData }; diff --git a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx index c1f4a74..733e4ac 100644 --- a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx @@ -148,8 +148,8 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb } const newFloorItem: Types.FloorItemType = { - modeluuid: obj.uuid, - modelname: obj.userData.name, + modelUuid: obj.uuid, + modelName: obj.userData.name, modelfileID: obj.userData.modelId, position: [worldPosition.x, worldPosition.y, worldPosition.z], rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, @@ -184,8 +184,8 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb const data = { organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, modelfileID: newFloorItem.modelfileID, position: newFloorItem.position, rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, @@ -198,9 +198,9 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb socket.emit("v2:model-asset:add", data); obj.userData = { - name: newFloorItem.modelname, + name: newFloorItem.modelName, modelId: newFloorItem.modelfileID, - modeluuid: newFloorItem.modeluuid, + modelUuid: newFloorItem.modelUuid, eventData: updatedEventData }; diff --git a/app/src/modules/scene/controls/selectionControls/moveControls.tsx b/app/src/modules/scene/controls/selectionControls/moveControls.tsx index f422d6e..d371806 100644 --- a/app/src/modules/scene/controls/selectionControls/moveControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/moveControls.tsx @@ -65,7 +65,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje if (keyCombination === "G") { if (selectedAssets.length > 0) { moveAssets(); - itemsData.current = floorItems.filter((item: { modeluuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); + itemsData.current = floorItems.filter((item: { modelUuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modelUuid)); } } if (keyCombination === "ESCAPE") { @@ -151,7 +151,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje const moveAssets = () => { - const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); + const updatedItems = floorItems.filter((item: { modelUuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modelUuid)); setFloorItems(updatedItems); setMovedObjects(selectedAssets); selectedAssets.forEach((asset: any) => { selectionGroup.current.attach(asset); }); @@ -170,8 +170,8 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje if (itemsGroupRef.current) { const newFloorItem: Types.FloorItemType = { - modeluuid: obj.uuid, - modelname: obj.userData.name, + modelUuid: obj.uuid, + modelName: obj.userData.name, modelfileID: obj.userData.modelId, position: [worldPosition.x, worldPosition.y, worldPosition.z], rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, @@ -180,17 +180,17 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje }; if (obj.userData.eventData) { - const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modeluuid); - const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid); + const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modelUuid); + const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid); if (eventData) { - useEventsStore.getState().updateEvent(obj.userData.modeluuid, { + useEventsStore.getState().updateEvent(obj.userData.modelUuid, { position: [worldPosition.x, worldPosition.y, worldPosition.z], rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], }) } if (productData) { - useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid, { + useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, { position: [worldPosition.x, worldPosition.y, worldPosition.z], rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], }) @@ -223,8 +223,8 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje const data = { organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, modelfileID: newFloorItem.modelfileID, position: newFloorItem.position, rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, diff --git a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx index cf66772..08667b4 100644 --- a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx @@ -64,7 +64,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo if (event.key.toLowerCase() === "r") { if (selectedAssets.length > 0) { rotateAssets(); - itemsData.current = floorItems.filter((item: { modeluuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); + itemsData.current = floorItems.filter((item: { modelUuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modelUuid)); } } if (event.key.toLowerCase() === "escape") { @@ -128,7 +128,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo }); const rotateAssets = () => { - const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modeluuid)); + const updatedItems = floorItems.filter((item: { modelUuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modelUuid)); setFloorItems(updatedItems); const box = new THREE.Box3(); @@ -170,8 +170,8 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo if (itemsGroupRef.current) { const newFloorItem: Types.FloorItemType = { - modeluuid: obj.uuid, - modelname: obj.userData.name, + modelUuid: obj.uuid, + modelName: obj.userData.name, modelfileID: obj.userData.modelId, position: [worldPosition.x, worldPosition.y, worldPosition.z], rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, @@ -180,17 +180,17 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo }; if (obj.userData.eventData) { - const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modeluuid); - const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid); + const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modelUuid); + const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid); if (eventData) { - useEventsStore.getState().updateEvent(obj.userData.modeluuid, { + useEventsStore.getState().updateEvent(obj.userData.modelUuid, { position: [worldPosition.x, worldPosition.y, worldPosition.z], rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], }) } if (productData) { - useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid, { + useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, { position: [worldPosition.x, worldPosition.y, worldPosition.z], rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z], }) @@ -223,8 +223,8 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo const data = { organization, - modeluuid: newFloorItem.modeluuid, - modelname: newFloorItem.modelname, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, modelfileID: newFloorItem.modelfileID, position: newFloorItem.position, rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, diff --git a/app/src/modules/scene/controls/selectionControls/selectionControls.tsx b/app/src/modules/scene/controls/selectionControls/selectionControls.tsx index 49b86d2..33a35c9 100644 --- a/app/src/modules/scene/controls/selectionControls/selectionControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/selectionControls.tsx @@ -14,6 +14,8 @@ import CopyPasteControls from "./copyPasteControls"; import MoveControls from "./moveControls"; import RotateControls from "./rotateControls"; import useModuleStore from "../../../../store/useModuleStore"; +import { useEventsStore } from "../../../../store/simulation/useEventsStore"; +import { useProductStore } from "../../../../store/simulation/useProductStore"; const SelectionControls: React.FC = () => { const { camera, controls, gl, scene, pointer } = useThree(); @@ -206,7 +208,7 @@ const SelectionControls: React.FC = () => { const storedItems = JSON.parse(localStorage.getItem("FloorItems") || "[]"); const selectedUUIDs = selectedAssets.map((mesh: THREE.Object3D) => mesh.uuid); - const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid)); + const updatedStoredItems = storedItems.filter((item: { modelUuid: string }) => !selectedUUIDs.includes(item.modelUuid)); localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems)); selectedAssets.forEach((selectedMesh: THREE.Object3D) => { @@ -218,13 +220,16 @@ const SelectionControls: React.FC = () => { const data = { organization: organization, - modeluuid: selectedMesh.uuid, - modelname: selectedMesh.userData.name, + modelUuid: selectedMesh.uuid, + modelName: selectedMesh.userData.name, socketId: socket.id, }; socket.emit("v2:model-asset:delete", data); + useEventsStore.getState().removeEvent(selectedMesh.uuid); + useProductStore.getState().deleteEvent(selectedMesh.uuid); + selectedMesh.traverse((child: THREE.Object3D) => { if (child instanceof THREE.Mesh) { if (child.geometry) child.geometry.dispose(); @@ -243,7 +248,7 @@ const SelectionControls: React.FC = () => { itemsGroupRef.current?.remove(selectedMesh); }); - const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid)); + const updatedItems = floorItems.filter((item: { modelUuid: string }) => !selectedUUIDs.includes(item.modelUuid)); setFloorItems(updatedItems); } toast.success("Selected models removed!"); diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx index 3fe8af1..6bde587 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -36,12 +36,12 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { useEffect(() => { let armItems = floorItems?.filter((val: any) => - val.modeluuid === "3abf5d46-b59e-4e6b-9c02-a4634b64b82d" + val.modelUuid === "3abf5d46-b59e-4e6b-9c02-a4634b64b82d" ); // Get the first matching item let armItem = armItems?.[0]; if (armItem) { - const targetMesh = scene?.getObjectByProperty("uuid", armItem.modeluuid); + const targetMesh = scene?.getObjectByProperty("uuid", armItem.modelUuid); if (targetMesh) { targetMesh.visible = activeModule !== "simulation" } diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx index f2d208d..5ca0ec5 100644 --- a/app/src/modules/simulation/simulation.tsx +++ b/app/src/modules/simulation/simulation.tsx @@ -19,11 +19,11 @@ function Simulation() { const { products } = useProductStore(); useEffect(() => { - console.log('events: ', events); + // console.log('events: ', events); }, [events]) useEffect(() => { - console.log('products: ', products); + // console.log('products: ', products); }, [products]) return ( diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx index eaf12a3..c7fd4b6 100644 --- a/app/src/modules/simulation/vehicle/vehicles.tsx +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -28,6 +28,7 @@ function Vehicles() { actionType: "travel", unLoadDuration: 10, loadCapacity: 2, + steeringAngle:0, pickUpPoint: { position: { x: 98.71483985219794, y: 0, z: 28.66321267938962 }, rotation: { x: 0, y: 0, z: 0 } }, unLoadPoint: { position: { x: 105.71483985219794, y: 0, z: 28.66321267938962 }, rotation: { x: 0, y: 0, z: 0 } }, triggers: [ @@ -71,6 +72,7 @@ function Vehicles() { actionType: "travel", unLoadDuration: 10, loadCapacity: 2, + steeringAngle:0, pickUpPoint: { position: { x: 90, y: 0, z: 28 }, rotation: { x: 0, y: 0, z: 0 } }, unLoadPoint: { position: { x: 20, y: 0, z: 10 }, rotation: { x: 0, y: 0, z: 0 } }, triggers: [ @@ -114,6 +116,7 @@ function Vehicles() { actionType: "travel", unLoadDuration: 15, loadCapacity: 5, + steeringAngle:0, pickUpPoint: { position: { x: 98.71483985219794, y: 0, z: 28.66321267938962 }, rotation: { x: 0, y: 0, z: 0 } }, unLoadPoint: { position: { x: 20, y: 0, z: 10 }, rotation: { x: 0, y: 0, z: 0 } }, triggers: [ diff --git a/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts index fbbb042..908319b 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts @@ -1,13 +1,13 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const deleteFloorItem = async (organization: string, modeluuid: string, modelname: string) => { +export const deleteFloorItem = async (organization: string, modelUuid: string, modelName: string) => { try { const response = await fetch(`${url_Backend_dwinzo}/api/v1/deletefloorItem`, { method: "DELETE", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ organization, modeluuid, modelname }), + body: JSON.stringify({ organization, modelUuid, modelName }), }); if (!response.ok) { diff --git a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts index d587f06..3d7c921 100644 --- a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts +++ b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts @@ -1,8 +1,8 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const setFloorItemApi = async ( organization: string, - modeluuid?: string, - modelname?: string, + modelUuid?: string, + modelName?: string, modelfileID?: string, position?: Object, rotation?: Object, @@ -10,7 +10,7 @@ export const setFloorItemApi = async ( isVisible?: boolean, ) => { try { - const body: any = { organization, modeluuid, modelname, position, rotation, modelfileID, isLocked, isVisible }; + const body: any = { organization, modelUuid, modelName, position, rotation, modelfileID, isLocked, isVisible }; const response = await fetch(`${url_Backend_dwinzo}/api/v2/setasset`, { method: "POST", diff --git a/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts index 58f179d..da50167 100644 --- a/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts +++ b/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts @@ -1,13 +1,13 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const deleteWallItem = async (organization: string, modeluuid: string, modelname: string) => { +export const deleteWallItem = async (organization: string, modelUuid: string, modelName: string) => { try { const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteWallItem`, { method: "DELETE", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ organization, modeluuid, modelname }), + body: JSON.stringify({ organization, modelUuid, modelName }), }); if (!response.ok) { diff --git a/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts index 79bed55..984adf5 100644 --- a/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts +++ b/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts @@ -2,8 +2,8 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_UR export const setWallItem = async ( organization: string, - modeluuid: string, - modelname: string, + modelUuid: string, + modelName: string, type: string, csgposition: Object, csgscale: Object, @@ -17,7 +17,7 @@ export const setWallItem = async ( headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ organization, modeluuid, modelname, position, type, csgposition, csgscale, quaternion, scale }), + body: JSON.stringify({ organization, modelUuid, modelName, position, type, csgposition, csgscale, quaternion, scale }), }); if (!response.ok) { diff --git a/app/src/services/factoryBuilder/webWorkers/assetManagerWorker.js b/app/src/services/factoryBuilder/webWorkers/assetManagerWorker.js index 4ccdbf5..50dac3f 100644 --- a/app/src/services/factoryBuilder/webWorkers/assetManagerWorker.js +++ b/app/src/services/factoryBuilder/webWorkers/assetManagerWorker.js @@ -21,7 +21,7 @@ onmessage = (event) => { const itemPosition = new THREE.Vector3(...item.position); const distance = cameraPos.distanceTo(itemPosition); - if (distance <= renderDistance && !uuids.includes(item.modeluuid)) { + if (distance <= renderDistance && !uuids.includes(item.modelUuid)) { toAdd.push(item); } }); @@ -35,7 +35,7 @@ onmessage = (event) => { // Check for items to be removed uuids.forEach((uuid) => { - const floorItem = floorItems.find((item) => item.modeluuid === uuid); + const floorItem = floorItems.find((item) => item.modelUuid === uuid); if (floorItem) { const itemPosition = new THREE.Vector3(...floorItem.position); const distance = cameraPos.distanceTo(itemPosition); diff --git a/app/src/services/simulation/deleteProductDataApi.ts b/app/src/services/simulation/deleteProductApi.ts similarity index 89% rename from app/src/services/simulation/deleteProductDataApi.ts rename to app/src/services/simulation/deleteProductApi.ts index 06718f8..2987a53 100644 --- a/app/src/services/simulation/deleteProductDataApi.ts +++ b/app/src/services/simulation/deleteProductApi.ts @@ -1,6 +1,6 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const deleteProductDataApi = async (productId: string, organization: string) => { +export const deleteProductApi = async (productId: string, organization: string) => { try { const response = await fetch(`${url_Backend_dwinzo}/api/v2/productDataDelete?productId=${productId}&organization=${organization}`, { method: "PATCH", diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts index de02551..e6f6ae0 100644 --- a/app/src/store/simulation/useProductStore.ts +++ b/app/src/store/simulation/useProductStore.ts @@ -13,6 +13,7 @@ type ProductsStore = { // Event-level actions addEvent: (productId: string, event: EventsSchema) => void; removeEvent: (productId: string, modelUuid: string) => void; + deleteEvent: (modelUuid: string) => void; updateEvent: (productId: string, modelUuid: string, updates: Partial) => void; // Point-level actions @@ -119,6 +120,14 @@ export const useProductStore = create()( }); }, + deleteEvent: (modelUuid: string) => { + set((state) => { + for (const product of state.products) { + product.eventDatas = product.eventDatas.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid); + } + }); + }, + updateEvent: (productId, modelUuid, updates) => { set((state) => { const product = state.products.find(p => p.productId === productId); @@ -440,7 +449,7 @@ export const useProductStore = create()( getPointByUuid: (productId, modelUuid, pointUuid) => { const event = get().getEventByModelUuid(productId, modelUuid); if (!event) return undefined; - + if ('points' in event) { return (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid); } else if ('point' in event && (event as any).point.uuid === pointUuid) { diff --git a/app/src/store/simulation/useVehicleStore.ts b/app/src/store/simulation/useVehicleStore.ts index 449ceb7..a5ea3be 100644 --- a/app/src/store/simulation/useVehicleStore.ts +++ b/app/src/store/simulation/useVehicleStore.ts @@ -22,6 +22,7 @@ interface VehiclesStore { ) => void; setVehicleActive: (modelUuid: string, isActive: boolean) => void; + updateSteeringAngle: (modelUuid: string, steeringAngle: number) => void; incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void; decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void; setVehicleState: (modelUuid: string, newState: VehicleStatus['state']) => void; @@ -76,6 +77,15 @@ export const useVehicleStore = create()( }); }, + updateSteeringAngle: (modelUuid, steeringAngle) => { + set((state) => { + const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); + if (vehicle) { + vehicle.point.action.steeringAngle = steeringAngle; + } + }); + }, + incrementVehicleLoad: (modelUuid, incrementBy) => { set((state) => { const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid); diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts index 46093d6..cb71864 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -44,6 +44,7 @@ interface VehiclePointSchema { actionType: "travel"; unLoadDuration: number; loadCapacity: number; + steeringAngle: number; pickUpPoint: { position: { x: number; y: number, z: number }, rotation: { x: number; y: number, z: number } } | null; unLoadPoint: { position: { x: number; y: number, z: number }, rotation: { x: number; y: number, z: number } } | null; triggers: TriggerSchema[]; diff --git a/app/src/types/world/worldTypes.d.ts b/app/src/types/world/worldTypes.d.ts index 20c44da..c148038 100644 --- a/app/src/types/world/worldTypes.d.ts +++ b/app/src/types/world/worldTypes.d.ts @@ -189,8 +189,8 @@ export type RefTubeGeometry = React.MutableRefObject; // Type for individual items placed on the floor, with positioning and rotation metadata export type FloorItemType = { - modeluuid: string; - modelname: string; + modelUuid: string; + modelName: string; position: [number, number, number]; rotation: { x: number; y: number; z: number }; modelfileID: string; @@ -238,8 +238,8 @@ export type AssetConfigurations = { [key: string]: AssetConfiguration; }; interface WallItem { type: "Fixed-Move" | "Free-Move" | undefined; model?: THREE.Group; - modeluuid?: string; - modelname?: string; + modelUuid?: string; + modelName?: string; scale?: [number, number, number]; csgscale?: [number, number, number]; csgposition?: [number, number, number]; From a20170f69e08d085e555fc95988f36fbbfd77da7 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Wed, 30 Apr 2025 11:49:58 +0530 Subject: [PATCH 09/14] Remove commented console log for vehicles in Vehicles component --- app/src/modules/simulation/vehicle/vehicles.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx index d5798db..7badec5 100644 --- a/app/src/modules/simulation/vehicle/vehicles.tsx +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -194,8 +194,7 @@ function Vehicles() { // } ]); useEffect(() => { - console.log('vehicles: ', vehicles); - + // console.log('vehicles: ', vehicles); }, [vehicles]) useEffect(() => { From 304d6689c1f64730e5ca997d17f542fce64bf04e Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Wed, 30 Apr 2025 12:46:00 +0530 Subject: [PATCH 10/14] Refactor Simulations component layout: streamline event handling and add comparison functionality --- .../sidebarRight/simulation/Simulations.tsx | 101 +++++++++++------- 1 file changed, 60 insertions(+), 41 deletions(-) diff --git a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx index 5b375a7..1280693 100644 --- a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx +++ b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx @@ -153,54 +153,73 @@ const Simulations: React.FC = () => { />
  • {products.length > 1 && ( - <> -
    handleRemoveProduct(product.productId)} - > - -
    - -
    - - {openObjects && events.map((event, index) => )} -
    - - )} - - {selectedAsset && ( - - { - if (option === "Add to Product") { - handleAddEventToProduct({ - event: getEventByModelUuid(selectedAsset.modelUuid), - addEvent, - selectedProduct, - clearSelectedAsset - }); - } else { - handleRemoveEventFromProduct(); - } - }} - /> - +
    handleRemoveProduct(product.productId)} + > + +
    )}
    ))}
    +
    handleResize(e, productsContainerRef)} + > + +
    +
    +
    + +
    + + {openObjects && + events.map((event, index) => )} +
    + +
    +
    + Need to Compare Layout? +
    +
    + Click 'Compare' to review and analyze the layout + differences between them. +
    +
    +
    + + {selectedAsset && ( + + { + if (option === "Add to Product") { + handleAddEventToProduct({ + event: getEventByModelUuid(selectedAsset.modelUuid), + addEvent, + selectedProduct, + clearSelectedAsset + }); + } else { + handleRemoveEventFromProduct(); + } + }} + /> + + )} ) }; From a704be77d3aa3ffa5a0bbe1e3840315c19bb5e6c Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Wed, 30 Apr 2025 15:58:23 +0530 Subject: [PATCH 11/14] Refactor VehicleMechanics component for improved state management and event handling - Simplified state initialization and effect hooks for better readability. - Enhanced event handling functions for speed, action type, and action renaming. - Updated current values retrieval logic to utilize getEventByModelUuid. - Cleaned up JSX structure for better maintainability. Update addAssetModel to remove unnecessary console log - Removed debug logging for roboticArmEvent in addAssetModel. Enhance copyPasteControls and duplicationControls with event handling - Integrated useEventsStore to manage events during copy and paste operations. - Updated event data structure for Conveyor, Vehicle, ArmBot, and StaticMachine types. - Ensured proper UUID generation for new events and actions. Refactor PointsCreator to ensure event sphere clearing - Re-enabled clearSelectedEventSphere on pointer miss events for better UX. Add logging in Products component for debugging - Added console log to inspect data fetched from getAllProductsApi. Update useProductStore to return updated events after modifications - Modified updateEvent, addAction, removeAction, updateAction, and renameAction to return updated event data. - Ensured consistency in event handling across the product store. --- .../components/ActionsList.tsx | 293 +++++++---------- .../mechanics/conveyorMechanics.tsx | 114 ++++++- .../mechanics/machineMechanics.tsx | 1 - .../mechanics/roboticArmMechanics.tsx | 147 ++++++++- .../mechanics/storageMechanics.tsx | 1 - .../mechanics/vehicleMechanics.tsx | 301 +++++++++-------- .../geomentries/assets/addAssetModel.ts | 1 - .../selectionControls/copyPasteControls.tsx | 305 +++++++++++++----- .../selectionControls/duplicationControls.tsx | 303 ++++++++++++----- .../events/points/creator/pointsCreator.tsx | 8 +- app/src/store/simulation/useProductStore.ts | 42 ++- 11 files changed, 1004 insertions(+), 512 deletions(-) diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/components/ActionsList.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/components/ActionsList.tsx index 6d2c3de..09017de 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/components/ActionsList.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/components/ActionsList.tsx @@ -1,202 +1,149 @@ import React, { useRef } from "react"; import { - AddIcon, - RemoveIcon, - ResizeHeightIcon, + AddIcon, + RemoveIcon, + ResizeHeightIcon, } from "../../../../../icons/ExportCommonIcons"; import RenameInput from "../../../../../ui/inputs/RenameInput"; import { handleResize } from "../../../../../../functions/handleResizePannel"; -import { - useSelectedAction, - useSelectedEventData, - useSelectedProduct, -} from "../../../../../../store/simulation/useSimulationStore"; -import { MathUtils } from "three"; +import { useSelectedAction, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore"; +import { upsertProductOrEventApi } from "../../../../../../services/simulation/UpsertProductOrEventApi"; interface ActionsListProps { - setSelectedPointData: (data: any) => void; // You can replace `any` with a more specific type if you have one - selectedPointData: any; // You can replace `any` with a more specific type if you have one - // ui control props - multipleAction?: boolean; + selectedPointData: any; + multipleAction?: boolean; + handleAddAction?: () => void; + handleDeleteAction?: (actionUuid: string) => void; } const ActionsList: React.FC = ({ - setSelectedPointData, - selectedPointData, - multipleAction = false, + selectedPointData, + multipleAction = false, + handleAddAction, + handleDeleteAction, }) => { - const actionsContainerRef = useRef(null); + const actionsContainerRef = useRef(null); - // store - const { selectedEventData } = useSelectedEventData(); - const { updateAction, addAction, removeAction } = useProductStore(); - const { selectedProduct } = useSelectedProduct(); - const { selectedAction, setSelectedAction, clearSelectedAction } = - useSelectedAction(); + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; - const handleAddAction = () => { - if (!selectedEventData || !selectedPointData) return; + // store + const { renameAction } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); + const { selectedAction, setSelectedAction } = useSelectedAction(); - const newAction = { - actionUuid: MathUtils.generateUUID(), - actionName: `Action ${selectedPointData.actions.length + 1}`, - actionType: "pickAndPlace" as const, - process: { - startPoint: null, - endPoint: null, - }, - triggers: [] as TriggerSchema[], + const handleRenameAction = (newName: string) => { + if (!selectedAction.actionId) return; + const event = renameAction(selectedAction.actionId, newName); + + if (event) { + upsertProductOrEventApi({ + productName: selectedProduct.productName, + productId: selectedProduct.productId, + organization: organization, + eventDatas: event + }) + } }; - addAction( - selectedProduct.productId, - selectedEventData.data.modelUuid, - selectedEventData.selectedPoint, - newAction - ); - - const updatedPoint = { - ...selectedPointData, - actions: [...selectedPointData.actions, newAction], + const handleActionSelect = (actionUuid: string, actionName: string) => { + setSelectedAction(actionUuid, actionName); }; - setSelectedPointData(updatedPoint); - setSelectedAction(newAction.actionUuid, newAction.actionName); - }; - const handleDeleteAction = (actionUuid: string) => { - if (!selectedPointData) return; + return ( +
    +
    +
    +
    Actions
    - removeAction(actionUuid); - const newActions = selectedPointData.actions.filter( - (a: any) => a.actionUuid !== actionUuid - ); - - const updatedPoint = { - ...selectedPointData, - actions: newActions, - }; - setSelectedPointData(updatedPoint); - - if (selectedAction.actionId === actionUuid) { - if (newActions.length > 0) { - setSelectedAction(newActions[0].actionUuid, newActions[0].actionName); - } else { - clearSelectedAction(); - } - } - }; - - const handleRenameAction = (newName: string) => { - if (!selectedAction.actionId) return; - updateAction(selectedAction.actionId, { actionName: newName }); - - if (selectedPointData?.actions) { - const updatedActions = selectedPointData.actions.map((action: any) => - action.actionUuid === selectedAction.actionId - ? { ...action, actionName: newName } - : action - ); - setSelectedPointData({ - ...selectedPointData, - actions: updatedActions, - }); - } else { - // write logic for single action - return; - } - }; - - const handleActionSelect = (actionUuid: string, actionName: string) => { - setSelectedAction(actionUuid, actionName); - }; - - return ( -
    -
    -
    -
    Actions
    - - -
    -
    -
    - {multipleAction && - selectedPointData.actions.map((action: any) => ( -
    - - {selectedPointData.actions.length > 1 && ( - )}
    - ))} - {!multipleAction && selectedPointData && ( -
    - -
    - )} -
    - {multipleAction && ( - - )} +
    + {multipleAction && selectedPointData && + selectedPointData.actions.map((action: any) => ( +
    + + {selectedPointData.actions.length > 1 && ( + + )} +
    + ))} + {!multipleAction && selectedPointData && ( +
    + +
    + )} +
    + {multipleAction && ( + + )} +
    +
    -
    -
    - ); + ); }; export default ActionsList; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx index 6437311..f68b6b8 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx @@ -11,14 +11,18 @@ import Trigger from "../trigger/Trigger"; import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import ActionsList from "../components/ActionsList"; +import { upsertProductOrEventApi } from "../../../../../../services/simulation/UpsertProductOrEventApi"; function ConveyorMechanics() { const [activeOption, setActiveOption] = useState<"default" | "spawn" | "swap" | "delay" | "despawn">("default"); const [selectedPointData, setSelectedPointData] = useState(); const { selectedEventData } = useSelectedEventData(); - const { getPointByUuid, updateEvent, updateAction } = useProductStore(); + const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction } = useProductStore(); const { selectedProduct } = useSelectedProduct(); + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + useEffect(() => { if (selectedEventData) { const point = getPointByUuid( @@ -33,11 +37,34 @@ function ConveyorMechanics() { } }, [selectedProduct, selectedEventData, getPointByUuid]); + const updateBackend = ( + productName: string, + productId: string, + organization: string, + eventData: EventsSchema + ) => { + upsertProductOrEventApi({ + productName: productName, + productId: productId, + organization: organization, + eventDatas: eventData + }) + } + const handleSpeedChange = (value: string) => { if (!selectedEventData) return; - updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { + const event = updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { speed: parseFloat(value), }); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } }; const handleActionTypeChange = (option: string) => { @@ -45,40 +72,94 @@ function ConveyorMechanics() { const validOption = option as | "default" | "spawn" | "swap" | "delay" | "despawn"; setActiveOption(validOption); - updateAction(selectedPointData.action.actionUuid, { + const event = updateAction(selectedPointData.action.actionUuid, { actionType: validOption, }); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } }; const handleRenameAction = (newName: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { actionName: newName }); + if (!selectedEventData || !selectedPointData) return; + const event = updateAction(selectedPointData.action.actionUuid, { actionName: newName }); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } }; const handleSpawnCountChange = (value: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { + if (!selectedEventData || !selectedPointData) return; + const event = updateAction(selectedPointData.action.actionUuid, { spawnCount: value === "inherit" ? "inherit" : parseFloat(value), }); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } }; const handleSpawnIntervalChange = (value: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { + if (!selectedEventData || !selectedPointData) return; + const event = updateAction(selectedPointData.action.actionUuid, { spawnInterval: value === "inherit" ? "inherit" : parseFloat(value), }); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } }; const handleMaterialSelect = (material: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { material }); + if (!selectedEventData || !selectedPointData) return; + const event = updateAction(selectedPointData.action.actionUuid, { material }); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } }; const handleDelayChange = (value: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { + if (!selectedEventData || !selectedPointData) return; + const event = updateAction(selectedPointData.action.actionUuid, { delay: value === "inherit" ? "inherit" : parseFloat(value), }); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } }; const availableActions = { @@ -87,9 +168,9 @@ function ConveyorMechanics() { }; // Get current values from store - const currentSpeed = selectedEventData?.data.type === "transfer" - ? selectedEventData.data.speed.toString() - : "0.5"; + const currentSpeed = (getEventByModelUuid( + selectedProduct.productId, selectedEventData?.data.modelUuid || "" + ) as ConveyorEventSchema | undefined)?.speed?.toString() || "0.5"; const currentActionName = selectedPointData ? selectedPointData.action.actionName @@ -132,7 +213,6 @@ function ConveyorMechanics() {
    diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx index 266eb39..993c46b 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx @@ -87,7 +87,6 @@ function MachineMechanics() { />
    diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx index faea93d..e56741f 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { MathUtils } from "three"; import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown"; import RenameInput from "../../../../../ui/inputs/RenameInput"; import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; @@ -7,15 +8,19 @@ import { useSelectedEventData, useSelectedProduct, useSelectedAction } from "../ import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import PickAndPlaceAction from "../actions/PickAndPlaceAction"; import ActionsList from "../components/ActionsList"; +import { upsertProductOrEventApi } from "../../../../../../services/simulation/UpsertProductOrEventApi"; function RoboticArmMechanics() { const [activeOption, setActiveOption] = useState<"default" | "pickAndPlace">("default"); const [selectedPointData, setSelectedPointData] = useState(); const { selectedEventData } = useSelectedEventData(); - const { getPointByUuid, updateEvent, updateAction } = useProductStore(); + const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction } = useProductStore(); const { selectedProduct } = useSelectedProduct(); const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction(); + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + useEffect(() => { if (selectedEventData) { const point = getPointByUuid( @@ -38,9 +43,23 @@ function RoboticArmMechanics() { } }, [clearSelectedAction, getPointByUuid, selectedAction.actionId, selectedEventData, selectedProduct, setSelectedAction,]); + const updateBackend = ( + productName: string, + productId: string, + organization: string, + eventData: EventsSchema + ) => { + upsertProductOrEventApi({ + productName: productName, + productId: productId, + organization: organization, + eventDatas: eventData + }) + } + const handleRenameAction = (newName: string) => { if (!selectedAction.actionId) return; - updateAction(selectedAction.actionId, { actionName: newName }); + const event = updateAction(selectedAction.actionId, { actionName: newName }); if (selectedPointData) { const updatedActions = selectedPointData.actions.map((action) => @@ -51,37 +70,145 @@ function RoboticArmMechanics() { actions: updatedActions, }); } + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } }; const handleSpeedChange = (value: string) => { if (!selectedEventData) return; - updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { + const event = updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { speed: parseFloat(value), }); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } }; const handlePickPointChange = (value: string) => { if (!selectedAction.actionId || !selectedPointData) return; const [x, y, z] = value.split(",").map(Number); - updateAction(selectedAction.actionId, { + const event = updateAction(selectedAction.actionId, { process: { startPoint: [x, y, z] as [number, number, number], endPoint: selectedPointData.actions.find((a) => a.actionUuid === selectedAction.actionId)?.process.endPoint || null, }, }); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } }; const handlePlacePointChange = (value: string) => { if (!selectedAction.actionId || !selectedPointData) return; const [x, y, z] = value.split(",").map(Number); - updateAction(selectedAction.actionId, { + const event = updateAction(selectedAction.actionId, { process: { startPoint: selectedPointData.actions.find((a) => a.actionUuid === selectedAction.actionId)?.process.startPoint || null, endPoint: [x, y, z] as [number, number, number], }, }); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } + }; + + + const handleAddAction = () => { + if (!selectedEventData || !selectedPointData) return; + + const newAction = { + actionUuid: MathUtils.generateUUID(), + actionName: `Action ${selectedPointData.actions.length + 1}`, + actionType: "pickAndPlace" as const, + process: { + startPoint: null, + endPoint: null, + }, + triggers: [] as TriggerSchema[], + }; + + const event = addAction( + selectedProduct.productId, + selectedEventData.data.modelUuid, + selectedEventData.selectedPoint, + newAction + ); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } + + const updatedPoint = { + ...selectedPointData, + actions: [...selectedPointData.actions, newAction], + }; + setSelectedPointData(updatedPoint); + setSelectedAction(newAction.actionUuid, newAction.actionName); + }; + + const handleDeleteAction = (actionUuid: string) => { + if (!selectedPointData) return; + + const event = removeAction(actionUuid); + + if (event) { + updateBackend( + selectedProduct.productName, + selectedProduct.productId, + organization, + event + ); + } + + const newActions = selectedPointData.actions.filter( + (a: any) => a.actionUuid !== actionUuid + ); + + const updatedPoint = { + ...selectedPointData, + actions: newActions, + }; + setSelectedPointData(updatedPoint); + + if (selectedAction.actionId === actionUuid) { + if (newActions.length > 0) { + setSelectedAction(newActions[0].actionUuid, newActions[0].actionName); + } else { + clearSelectedAction(); + } + } }; const availableActions = { @@ -89,9 +216,9 @@ function RoboticArmMechanics() { options: ["pickAndPlace"], }; - const currentSpeed = selectedEventData?.data.type === "roboticArm" - ? selectedEventData.data.speed.toString() - : "0.5"; + const currentSpeed = (getEventByModelUuid( + selectedProduct.productId, selectedEventData?.data.modelUuid || "" + ) as RoboticArmEventSchema | undefined)?.speed?.toString() || "0.5"; const currentAction = selectedPointData?.actions.find((a) => a.actionUuid === selectedAction.actionId); @@ -122,10 +249,12 @@ function RoboticArmMechanics() {
    + {selectedAction.actionId && currentAction && ( diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx index f22ec37..c85da9f 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx @@ -69,7 +69,6 @@ function StorageMechanics() { {selectedEventData && (
    diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx index d8456e5..28eb61f 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx @@ -4,186 +4,181 @@ import RenameInput from "../../../../../ui/inputs/RenameInput"; import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; import Trigger from "../trigger/Trigger"; import { - useSelectedEventData, - useSelectedProduct, + useSelectedEventData, + useSelectedProduct, } from "../../../../../../store/simulation/useSimulationStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import TravelAction from "../actions/TravelAction"; import ActionsList from "../components/ActionsList"; function VehicleMechanics() { - const [activeOption, setActiveOption] = useState<"default" | "travel">( - "default" - ); - const [selectedPointData, setSelectedPointData] = useState< - VehiclePointSchema | undefined - >(); - const { selectedEventData } = useSelectedEventData(); - const { getPointByUuid, updateEvent, updateAction } = useProductStore(); - const { selectedProduct } = useSelectedProduct(); + const [activeOption, setActiveOption] = useState<"default" | "travel">("default"); + const [selectedPointData, setSelectedPointData] = useState(); + const { selectedEventData } = useSelectedEventData(); + const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); - useEffect(() => { - if (selectedEventData) { - const point = getPointByUuid( - selectedProduct.productId, - selectedEventData.data.modelUuid, - selectedEventData.selectedPoint - ) as VehiclePointSchema | undefined; + useEffect(() => { + if (selectedEventData) { + const point = getPointByUuid( + selectedProduct.productId, + selectedEventData.data.modelUuid, + selectedEventData.selectedPoint + ) as VehiclePointSchema | undefined; - if (point) { - setSelectedPointData(point); - setActiveOption(point.action.actionType as "travel"); - } - } - }, [selectedProduct, selectedEventData, getPointByUuid]); + if (point) { + setSelectedPointData(point); + setActiveOption(point.action.actionType as "travel"); + } + } + }, [selectedProduct, selectedEventData, getPointByUuid]); - const handleSpeedChange = (value: string) => { - if (!selectedEventData) return; - updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { - speed: parseFloat(value), - }); - }; + const handleSpeedChange = (value: string) => { + if (!selectedEventData) return; + updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { + speed: parseFloat(value), + }); + }; - const handleActionTypeChange = (option: string) => { - if (!selectedEventData || !selectedPointData) return; - const validOption = option as "travel"; - setActiveOption(validOption); + const handleActionTypeChange = (option: string) => { + if (!selectedEventData || !selectedPointData) return; + const validOption = option as "travel"; + setActiveOption(validOption); - updateAction(selectedPointData.action.actionUuid, { - actionType: validOption, - }); - }; + updateAction(selectedPointData.action.actionUuid, { + actionType: validOption, + }); + }; - const handleRenameAction = (newName: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { actionName: newName }); - }; + const handleRenameAction = (newName: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { actionName: newName }); + }; - const handleLoadCapacityChange = (value: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { - loadCapacity: parseFloat(value), - }); - }; + const handleLoadCapacityChange = (value: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { + loadCapacity: parseFloat(value), + }); + }; - const handleUnloadDurationChange = (value: string) => { - if (!selectedPointData) return; - updateAction(selectedPointData.action.actionUuid, { - unLoadDuration: parseFloat(value), - }); - }; + const handleUnloadDurationChange = (value: string) => { + if (!selectedPointData) return; + updateAction(selectedPointData.action.actionUuid, { + unLoadDuration: parseFloat(value), + }); + }; - const handlePickPointChange = (value: string) => { - if (!selectedPointData) return; - }; + const handlePickPointChange = (value: string) => { + if (!selectedPointData) return; + }; - const handleUnloadPointChange = (value: string) => { - if (!selectedPointData) return; - }; + const handleUnloadPointChange = (value: string) => { + if (!selectedPointData) return; + }; - // Get current values from store - const currentSpeed = - selectedEventData?.data.type === "vehicle" - ? selectedEventData.data.speed.toString() - : "0.5"; + // Get current values from store - const currentActionName = selectedPointData - ? selectedPointData.action.actionName - : "Action Name"; + const currentSpeed = (getEventByModelUuid( + selectedProduct.productId, selectedEventData?.data.modelUuid || "" + ) as VehicleEventSchema | undefined)?.speed?.toString() || "0.5"; - const currentLoadCapacity = selectedPointData - ? selectedPointData.action.loadCapacity.toString() - : "1"; + const currentActionName = selectedPointData + ? selectedPointData.action.actionName + : "Action Name"; - const currentUnloadDuration = selectedPointData - ? selectedPointData.action.unLoadDuration.toString() - : "1"; + const currentLoadCapacity = selectedPointData + ? selectedPointData.action.loadCapacity.toString() + : "1"; - const currentPickPoint = selectedPointData?.action.pickUpPoint; + const currentUnloadDuration = selectedPointData + ? selectedPointData.action.unLoadDuration.toString() + : "1"; - const currentUnloadPoint = selectedPointData?.action.unLoadPoint; + const currentPickPoint = selectedPointData?.action.pickUpPoint; - const availableActions = { - defaultOption: "travel", - options: ["travel"], - }; + const currentUnloadPoint = selectedPointData?.action.unLoadPoint; - return ( - <> - {selectedEventData && ( + const availableActions = { + defaultOption: "travel", + options: ["travel"], + }; + + return ( <> -
    -
    -
    - {}} - onChange={handleSpeedChange} - /> -
    -
    -
    -
    - -
    -
    - -
    -
    - + {selectedEventData && ( + <> +
    +
    +
    + { }} + onChange={handleSpeedChange} + /> +
    +
    +
    +
    + +
    +
    + +
    +
    + - {activeOption === "travel" && ( - - )} -
    -
    -
    - -
    -
    + {activeOption === "travel" && ( + + )} +
    +
    +
    + +
    +
    + + )} - )} - - ); + ); } export default VehicleMechanics; diff --git a/app/src/modules/builder/geomentries/assets/addAssetModel.ts b/app/src/modules/builder/geomentries/assets/addAssetModel.ts index 0bc7352..c718ec3 100644 --- a/app/src/modules/builder/geomentries/assets/addAssetModel.ts +++ b/app/src/modules/builder/geomentries/assets/addAssetModel.ts @@ -270,7 +270,6 @@ async function handleModelLoad( } }; addEvent(roboticArmEvent); - console.log('roboticArmEvent: ', roboticArmEvent); eventData.point = { uuid: roboticArmEvent.point.uuid, position: roboticArmEvent.point.position, diff --git a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx b/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx index 613fe43..fa6ec16 100644 --- a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx @@ -6,6 +6,7 @@ import { toast } from "react-toastify"; // import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; import * as Types from "../../../../types/world/worldTypes"; import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys"; +import { useEventsStore } from "../../../../store/simulation/useEventsStore"; const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, selectionGroup, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => { const { camera, controls, gl, scene, pointer, raycaster } = useThree(); @@ -13,7 +14,8 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas const { selectedAssets, setSelectedAssets } = useSelectedAssets(); const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); const { floorItems, setFloorItems } = useFloorItems(); - const { socket } = useSocketStore() + const { socket } = useSocketStore(); + const { addEvent } = useEventsStore(); useEffect(() => { if (!camera || !scene || toggleView) return; @@ -137,38 +139,6 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas if (itemsGroupRef.current) { - let updatedEventData = null; - if (obj.userData.eventData) { - updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData)); - - updatedEventData.modelUuid = THREE.MathUtils.generateUUID(); - - if (updatedEventData.type === "Conveyor" && updatedEventData.points) { - updatedEventData.points = updatedEventData.points.map((point: any) => ({ - ...point, - uuid: THREE.MathUtils.generateUUID() - })); - } - else if (updatedEventData.type === "Vehicle" && updatedEventData.point) { - updatedEventData.point = { - ...updatedEventData.point, - uuid: THREE.MathUtils.generateUUID() - }; - } - else if (updatedEventData.type === "ArmBot" && updatedEventData.point) { - updatedEventData.point = { - ...updatedEventData.point, - uuid: THREE.MathUtils.generateUUID() - }; - } - else if (updatedEventData.type === "StaticMachine" && updatedEventData.point) { - updatedEventData.point = { - ...updatedEventData.point, - uuid: THREE.MathUtils.generateUUID() - }; - } - } - const newFloorItem: Types.FloorItemType = { modelUuid: obj.uuid, modelName: obj.userData.name, @@ -177,56 +147,245 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, isLocked: false, isVisible: true, - eventData: updatedEventData }; - setFloorItems((prevItems: Types.FloorItems) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); + let updatedEventData = null; + if (obj.userData.eventData) { + updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData)); + updatedEventData.modelUuid = newFloorItem.modelUuid; - const email = localStorage.getItem("email"); - const organization = email ? email.split("@")[1].split(".")[0] : "default"; + const eventData: any = { + type: obj.userData.eventData.type, + }; - //REST + if (obj.userData.eventData.type === "Conveyor") { + const ConveyorEvent: ConveyorEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], + state: "idle", + type: 'transfer', + speed: 1, + points: updatedEventData.points.map((point: any, index: number) => ({ + uuid: THREE.MathUtils.generateUUID(), + position: [point.position[0], point.position[1], point.position[2]], + rotation: [point.rotation[0], point.rotation[1], point.rotation[2]], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: `Action ${index}`, + actionType: 'default', + material: 'Default Material', + delay: 0, + spawnInterval: 5, + spawnCount: 1, + triggers: [] + } + })) + }; + addEvent(ConveyorEvent); + eventData.points = ConveyorEvent.points.map(point => ({ + uuid: point.uuid, + position: point.position, + rotation: point.rotation + })); - // await setFloorItemApi( - // 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, - // ); + } else if (obj.userData.eventData.type === "Vehicle") { + const vehicleEvent: VehicleEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], + state: "idle", + type: "vehicle", + speed: 1, + point: { + uuid: THREE.MathUtils.generateUUID(), + position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]], + rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "travel", + unLoadDuration: 5, + loadCapacity: 10, + steeringAngle: 0, + pickUpPoint: null, + unLoadPoint: null, + triggers: [] + } + } + }; + addEvent(vehicleEvent); + eventData.point = { + uuid: vehicleEvent.point.uuid, + position: vehicleEvent.point.position, + rotation: vehicleEvent.point.rotation + }; - //SOCKET + } else if (obj.userData.eventData.type === "ArmBot") { + const roboticArmEvent: RoboticArmEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], + state: "idle", + type: "roboticArm", + speed: 1, + point: { + uuid: THREE.MathUtils.generateUUID(), + position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]], + rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]], + actions: [ + { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "pickAndPlace", + process: { + startPoint: null, + endPoint: null + }, + triggers: [] + } + ] + } + }; + addEvent(roboticArmEvent); + eventData.point = { + uuid: roboticArmEvent.point.uuid, + position: roboticArmEvent.point.position, + rotation: roboticArmEvent.point.rotation + }; - const data = { - organization, - modelUuid: newFloorItem.modelUuid, - modelName: newFloorItem.modelName, - modelfileID: newFloorItem.modelfileID, - position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, - isLocked: false, - isVisible: true, - socketId: socket.id, - eventData: updatedEventData - }; + } else if (obj.userData.eventData.type === "StaticMachine") { + const machineEvent: MachineEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], + state: "idle", + type: "machine", + point: { + uuid: THREE.MathUtils.generateUUID(), + position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]], + rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "process", + processTime: 10, + swapMaterial: "Default Material", + triggers: [] + } + } + }; + addEvent(machineEvent); + eventData.point = { + uuid: machineEvent.point.uuid, + position: machineEvent.point.position, + rotation: machineEvent.point.rotation + }; + } - socket.emit("v2:model-asset:add", data); + obj.userData.eventData = eventData; - obj.userData = { - name: newFloorItem.modelName, - modelId: newFloorItem.modelfileID, - modelUuid: newFloorItem.modelUuid, - eventData: updatedEventData - }; + newFloorItem.eventData = eventData; - itemsGroupRef.current.add(obj); + + setFloorItems((prevItems: Types.FloorItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + const email = localStorage.getItem("email"); + const organization = email ? email.split("@")[1].split(".")[0] : "default"; + + //REST + + // await setFloorItemApi( + // 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, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id, + eventData: eventData, + }; + + socket.emit("v2:model-asset:add", data); + + obj.userData = { + name: newFloorItem.modelName, + modelId: newFloorItem.modelfileID, + modelUuid: newFloorItem.modelUuid, + }; + + itemsGroupRef.current.add(obj); + + } else { + setFloorItems((prevItems: Types.FloorItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + const email = localStorage.getItem("email"); + const organization = email ? email.split("@")[1].split(".")[0] : "default"; + + //REST + + // await setFloorItemApi( + // 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, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id, + }; + + socket.emit("v2:model-asset:add", data); + + obj.userData = { + name: newFloorItem.modelName, + modelId: newFloorItem.modelfileID, + modelUuid: newFloorItem.modelUuid, + }; + + itemsGroupRef.current.add(obj); + } } }); diff --git a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx index 733e4ac..ffe560c 100644 --- a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx @@ -7,6 +7,7 @@ import { toast } from "react-toastify"; import * as Types from "../../../../types/world/worldTypes"; import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi"; import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys"; +import { useEventsStore } from "../../../../store/simulation/useEventsStore"; const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedObjects, setpastedObjects, selectionGroup, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => { const { camera, controls, gl, scene, pointer, raycaster } = useThree(); @@ -15,6 +16,7 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); const { floorItems, setFloorItems } = useFloorItems(); const { socket } = useSocketStore(); + const { addEvent } = useEventsStore(); useEffect(() => { if (!camera || !scene || toggleView) return; @@ -115,38 +117,6 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb if (itemsGroupRef.current) { - let updatedEventData = null; - if (obj.userData.eventData) { - updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData)); - - updatedEventData.modelUuid = THREE.MathUtils.generateUUID(); - - if (updatedEventData.type === "Conveyor" && updatedEventData.points) { - updatedEventData.points = updatedEventData.points.map((point: any) => ({ - ...point, - uuid: THREE.MathUtils.generateUUID() - })); - } - else if (updatedEventData.type === "Vehicle" && updatedEventData.point) { - updatedEventData.point = { - ...updatedEventData.point, - uuid: THREE.MathUtils.generateUUID() - }; - } - else if (updatedEventData.type === "ArmBot" && updatedEventData.point) { - updatedEventData.point = { - ...updatedEventData.point, - uuid: THREE.MathUtils.generateUUID() - }; - } - else if (updatedEventData.type === "StaticMachine" && updatedEventData.point) { - updatedEventData.point = { - ...updatedEventData.point, - uuid: THREE.MathUtils.generateUUID() - }; - } - } - const newFloorItem: Types.FloorItemType = { modelUuid: obj.uuid, modelName: obj.userData.name, @@ -155,56 +125,245 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, isLocked: false, isVisible: true, - eventData: updatedEventData }; - setFloorItems((prevItems: Types.FloorItems) => { - const updatedItems = [...(prevItems || []), newFloorItem]; - localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); - return updatedItems; - }); + let updatedEventData = null; + if (obj.userData.eventData) { + updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData)); + updatedEventData.modelUuid = newFloorItem.modelUuid; - const email = localStorage.getItem("email"); - const organization = email ? email.split("@")[1].split(".")[0] : "default"; + const eventData: any = { + type: obj.userData.eventData.type, + }; - //REST + if (obj.userData.eventData.type === "Conveyor") { + const ConveyorEvent: ConveyorEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], + state: "idle", + type: 'transfer', + speed: 1, + points: updatedEventData.points.map((point: any, index: number) => ({ + uuid: THREE.MathUtils.generateUUID(), + position: [point.position[0], point.position[1], point.position[2]], + rotation: [point.rotation[0], point.rotation[1], point.rotation[2]], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: `Action ${index}`, + actionType: 'default', + material: 'Default Material', + delay: 0, + spawnInterval: 5, + spawnCount: 1, + triggers: [] + } + })) + }; + addEvent(ConveyorEvent); + eventData.points = ConveyorEvent.points.map(point => ({ + uuid: point.uuid, + position: point.position, + rotation: point.rotation + })); - // await setFloorItemApi( - // 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, - // ); + } else if (obj.userData.eventData.type === "Vehicle") { + const vehicleEvent: VehicleEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], + state: "idle", + type: "vehicle", + speed: 1, + point: { + uuid: THREE.MathUtils.generateUUID(), + position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]], + rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "travel", + unLoadDuration: 5, + loadCapacity: 10, + steeringAngle: 0, + pickUpPoint: null, + unLoadPoint: null, + triggers: [] + } + } + }; + addEvent(vehicleEvent); + eventData.point = { + uuid: vehicleEvent.point.uuid, + position: vehicleEvent.point.position, + rotation: vehicleEvent.point.rotation + }; - //SOCKET + } else if (obj.userData.eventData.type === "ArmBot") { + const roboticArmEvent: RoboticArmEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], + state: "idle", + type: "roboticArm", + speed: 1, + point: { + uuid: THREE.MathUtils.generateUUID(), + position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]], + rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]], + actions: [ + { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "pickAndPlace", + process: { + startPoint: null, + endPoint: null + }, + triggers: [] + } + ] + } + }; + addEvent(roboticArmEvent); + eventData.point = { + uuid: roboticArmEvent.point.uuid, + position: roboticArmEvent.point.position, + rotation: roboticArmEvent.point.rotation + }; - const data = { - organization, - modelUuid: newFloorItem.modelUuid, - modelName: newFloorItem.modelName, - modelfileID: newFloorItem.modelfileID, - position: newFloorItem.position, - rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, - isLocked: false, - isVisible: true, - socketId: socket.id, - eventData: updatedEventData - }; + } else if (obj.userData.eventData.type === "StaticMachine") { + const machineEvent: MachineEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z], + state: "idle", + type: "machine", + point: { + uuid: THREE.MathUtils.generateUUID(), + position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]], + rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "process", + processTime: 10, + swapMaterial: "Default Material", + triggers: [] + } + } + }; + addEvent(machineEvent); + eventData.point = { + uuid: machineEvent.point.uuid, + position: machineEvent.point.position, + rotation: machineEvent.point.rotation + }; + } - socket.emit("v2:model-asset:add", data); + obj.userData.eventData = eventData; - obj.userData = { - name: newFloorItem.modelName, - modelId: newFloorItem.modelfileID, - modelUuid: newFloorItem.modelUuid, - eventData: updatedEventData - }; + newFloorItem.eventData = eventData; - itemsGroupRef.current.add(obj); + + setFloorItems((prevItems: Types.FloorItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + const email = localStorage.getItem("email"); + const organization = email ? email.split("@")[1].split(".")[0] : "default"; + + //REST + + // await setFloorItemApi( + // 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, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id, + eventData: eventData, + }; + + socket.emit("v2:model-asset:add", data); + + obj.userData = { + name: newFloorItem.modelName, + modelId: newFloorItem.modelfileID, + modelUuid: newFloorItem.modelUuid, + }; + + itemsGroupRef.current.add(obj); + + } else { + setFloorItems((prevItems: Types.FloorItems) => { + const updatedItems = [...(prevItems || []), newFloorItem]; + localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); + return updatedItems; + }); + + const email = localStorage.getItem("email"); + const organization = email ? email.split("@")[1].split(".")[0] : "default"; + + //REST + + // await setFloorItemApi( + // 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, + modelfileID: newFloorItem.modelfileID, + position: newFloorItem.position, + rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z }, + isLocked: false, + isVisible: true, + socketId: socket.id, + }; + + socket.emit("v2:model-asset:add", data); + + obj.userData = { + name: newFloorItem.modelName, + modelId: newFloorItem.modelfileID, + modelUuid: newFloorItem.modelUuid, + }; + + itemsGroupRef.current.add(obj); + } } }); diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx index 9d32063..c6ec316 100644 --- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx +++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx @@ -94,7 +94,7 @@ function PointsCreator() { }} onPointerMissed={() => { if (selectedEventData?.data.type !== 'vehicle') { - // clearSelectedEventSphere(); + clearSelectedEventSphere(); } setTransformMode(null); }} @@ -123,7 +123,7 @@ function PointsCreator() { ); }} onPointerMissed={() => { - // clearSelectedEventSphere(); + clearSelectedEventSphere(); setTransformMode(null); }} position={new THREE.Vector3(...event.point.position)} @@ -149,7 +149,7 @@ function PointsCreator() { ); }} onPointerMissed={() => { - // clearSelectedEventSphere(); + clearSelectedEventSphere(); setTransformMode(null); }} position={new THREE.Vector3(...event.point.position)} @@ -175,7 +175,7 @@ function PointsCreator() { ); }} onPointerMissed={() => { - // clearSelectedEventSphere(); + clearSelectedEventSphere(); setTransformMode(null); }} position={new THREE.Vector3(...event.point.position)} diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts index e6f6ae0..4f2b546 100644 --- a/app/src/store/simulation/useProductStore.ts +++ b/app/src/store/simulation/useProductStore.ts @@ -14,7 +14,7 @@ type ProductsStore = { addEvent: (productId: string, event: EventsSchema) => void; removeEvent: (productId: string, modelUuid: string) => void; deleteEvent: (modelUuid: string) => void; - updateEvent: (productId: string, modelUuid: string, updates: Partial) => void; + updateEvent: (productId: string, modelUuid: string, updates: Partial) => EventsSchema | undefined; // Point-level actions addPoint: (productId: string, modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema) => void; @@ -32,12 +32,12 @@ type ProductsStore = { modelUuid: string, pointUuid: string, action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] - ) => void; - removeAction: (actionUuid: string) => void; + ) => EventsSchema | undefined; + removeAction: (actionUuid: string) => EventsSchema | undefined; updateAction: ( actionUuid: string, updates: Partial - ) => void; + ) => EventsSchema | undefined; // Trigger-level actions addTrigger: ( @@ -52,7 +52,7 @@ type ProductsStore = { // Renaming functions renameProduct: (productId: string, newName: string) => void; - renameAction: (actionUuid: string, newName: string) => void; + renameAction: (actionUuid: string, newName: string) => EventsSchema | undefined; renameTrigger: (triggerUuid: string, newName: string) => void; // Helper functions @@ -129,15 +129,18 @@ export const useProductStore = create()( }, updateEvent: (productId, modelUuid, updates) => { + let updatedEvent: EventsSchema | undefined; set((state) => { const product = state.products.find(p => p.productId === productId); if (product) { const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); if (event) { Object.assign(event, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); } } }); + return updatedEvent; }, // Point-level actions @@ -188,6 +191,7 @@ export const useProductStore = create()( // Action-level actions addAction: (productId, modelUuid, pointUuid, action) => { + let updatedEvent: EventsSchema | undefined; set((state) => { const product = state.products.find(p => p.productId === productId); if (product) { @@ -196,19 +200,24 @@ export const useProductStore = create()( const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid); if (point) { point.action = action as any; + updatedEvent = JSON.parse(JSON.stringify(event)); } } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) { if ('action' in (event as any).point) { (event as any).point.action = action; + updatedEvent = JSON.parse(JSON.stringify(event)); } else if ('actions' in (event as any).point) { (event as any).point.actions.push(action); + updatedEvent = JSON.parse(JSON.stringify(event)); } } } }); + return updatedEvent; }, removeAction: (actionUuid: string) => { + let updatedEvent: EventsSchema | undefined; set((state) => { for (const product of state.products) { for (const event of product.eventDatas) { @@ -219,20 +228,28 @@ export const useProductStore = create()( } else if ('point' in event) { const point = (event as any).point; if (event.type === "roboticArm") { - // Handle RoboticArmEventSchema if ('actions' in point) { - point.actions = point.actions.filter((a: any) => a.actionUuid !== actionUuid); + const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid); + if (index !== -1) { + point.actions.splice(index, 1); + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } } } else if ('action' in point && point.action?.actionUuid === actionUuid) { - // For other schemas with a single 'action' + point.action = undefined; + updatedEvent = JSON.parse(JSON.stringify(event)); + return; } } } } }); + return updatedEvent; }, updateAction: (actionUuid, updates) => { + let updatedEvent: EventsSchema | undefined; set((state) => { for (const product of state.products) { for (const event of product.eventDatas) { @@ -240,6 +257,7 @@ export const useProductStore = create()( for (const point of (event as ConveyorEventSchema).points) { if (point.action && point.action.actionUuid === actionUuid) { Object.assign(point.action, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); return; } } @@ -247,11 +265,13 @@ export const useProductStore = create()( const point = (event as any).point; if ('action' in point && point.action.actionUuid === actionUuid) { Object.assign(point.action, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); return; } else if ('actions' in point) { const action = point.actions.find((a: any) => a.actionUuid === actionUuid); if (action) { Object.assign(action, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); return; } } @@ -259,6 +279,7 @@ export const useProductStore = create()( } } }); + return updatedEvent; }, // Trigger-level actions @@ -368,6 +389,7 @@ export const useProductStore = create()( }, renameAction: (actionUuid, newName) => { + let updatedEvent: EventsSchema | undefined; set((state) => { for (const product of state.products) { for (const event of product.eventDatas) { @@ -375,6 +397,7 @@ export const useProductStore = create()( for (const point of (event as ConveyorEventSchema).points) { if (point.action && point.action.actionUuid === actionUuid) { point.action.actionName = newName; + updatedEvent = JSON.parse(JSON.stringify(event)); return; } } @@ -382,11 +405,13 @@ export const useProductStore = create()( const point = (event as any).point; if ('action' in point && point.action.actionUuid === actionUuid) { point.action.actionName = newName; + updatedEvent = JSON.parse(JSON.stringify(event)); return; } else if ('actions' in point) { const action = point.actions.find((a: any) => a.actionUuid === actionUuid); if (action) { action.actionName = newName; + updatedEvent = JSON.parse(JSON.stringify(event)); return; } } @@ -394,6 +419,7 @@ export const useProductStore = create()( } } }); + return updatedEvent; }, renameTrigger: (triggerUuid, newName) => { From 5119b014b711a3db7ebd61f39b0b399714fdd088 Mon Sep 17 00:00:00 2001 From: Vishnu Date: Wed, 30 Apr 2025 16:23:24 +0530 Subject: [PATCH 12/14] Refactor Assets component layout and styling; enhance Trigger dropdowns with labels; update MenuBar theme retrieval; fix icon import in AssetPreview; adjust Card component star rating display; modify AddButtons styles and functionality; improve variable definitions in SCSS files; streamline input component styles; refine marketplace card layout; enhance menu dropdown styles; update module toggle styles; adjust tools component styles; improve visualization floating styles; clean up sidebar styles; optimize realTimeViz styles for better responsiveness. --- app/src/components/icons/ContextMenuIcons.tsx | 35 +-- app/src/components/icons/DashboardIcon.tsx | 86 +++---- .../components/icons/ExportCommonIcons.tsx | 93 +++---- .../components/icons/ExportModuleIcons.tsx | 38 +-- app/src/components/icons/HeaderIcons.tsx | 10 +- .../icons/RealTimeVisulationIcons.tsx | 14 +- app/src/components/icons/marketPlaceIcons.tsx | 8 +- .../components/layout/sidebarLeft/Assets.tsx | 230 +++++++++--------- .../eventProperties/trigger/Trigger.tsx | 64 +++-- app/src/components/ui/menu/menu.tsx | 2 +- app/src/modules/market/AssetPreview.tsx | 4 +- app/src/modules/market/Card.tsx | 9 +- .../widgets/panel/AddButtons.tsx | 6 +- app/src/styles/abstracts/variables.scss | 13 +- app/src/styles/base/base.scss | 2 + app/src/styles/components/input.scss | 82 +++---- .../components/marketPlace/marketPlace.scss | 16 +- app/src/styles/components/menu/menu.scss | 32 +-- app/src/styles/components/moduleToggle.scss | 2 +- app/src/styles/components/tools.scss | 33 ++- .../visualization/floating/common.scss | 3 +- app/src/styles/layout/sidebar.scss | 122 +++++----- app/src/styles/pages/realTimeViz.scss | 65 ++--- 23 files changed, 470 insertions(+), 499 deletions(-) diff --git a/app/src/components/icons/ContextMenuIcons.tsx b/app/src/components/icons/ContextMenuIcons.tsx index f48cf3b..e249bad 100644 --- a/app/src/components/icons/ContextMenuIcons.tsx +++ b/app/src/components/icons/ContextMenuIcons.tsx @@ -9,31 +9,31 @@ export function FlipXAxisIcon() { > @@ -52,37 +52,38 @@ export function FlipYAxisIcon() { > ); } + export function FlipZAxisIcon() { return ( ); diff --git a/app/src/components/icons/DashboardIcon.tsx b/app/src/components/icons/DashboardIcon.tsx index 314a3c8..f1f4d7d 100644 --- a/app/src/components/icons/DashboardIcon.tsx +++ b/app/src/components/icons/DashboardIcon.tsx @@ -9,13 +9,13 @@ export function NotificationIcon() { > @@ -34,7 +34,7 @@ export function HomeIcon() { > ); @@ -51,7 +51,7 @@ export function ProjectsIcon() { > ); @@ -70,103 +70,103 @@ export function TutorialsIcon() { cx="8.157" cy="8.35866" r="6.17928" - stroke="var(--icon-default-color)" + stroke="var(--text-color)" strokeWidth="0.562865" /> @@ -184,12 +184,12 @@ export function DocumentationIcon() { > @@ -208,7 +208,7 @@ export function HelpIcon() { @@ -236,17 +236,17 @@ export function LogoutIcon() { > diff --git a/app/src/components/icons/ExportCommonIcons.tsx b/app/src/components/icons/ExportCommonIcons.tsx index c78261e..9a9d96c 100644 --- a/app/src/components/icons/ExportCommonIcons.tsx +++ b/app/src/components/icons/ExportCommonIcons.tsx @@ -24,7 +24,7 @@ export function ArrowIcon() { fill="none" xmlns="http://www.w3.org/2000/svg" > - + ); } @@ -40,14 +40,14 @@ export function FocusIcon() { > @@ -65,7 +65,7 @@ export function LockIcon({ isLocked }: { isLocked: boolean }) { > @@ -80,7 +80,7 @@ export function LockIcon({ isLocked }: { isLocked: boolean }) { > @@ -100,7 +100,7 @@ export function EyeIcon({ isClosed }: { isClosed: boolean }) { @@ -119,13 +119,13 @@ export function EyeIcon({ isClosed }: { isClosed: boolean }) { > @@ -142,9 +142,9 @@ export function KebebIcon() { fill="none" xmlns="http://www.w3.org/2000/svg" > - - - + + + ); } @@ -160,7 +160,7 @@ export function AddIcon() { > @@ -179,12 +179,12 @@ export function CloseIcon() { > @@ -203,11 +203,11 @@ export function SettingsIcon() { @@ -255,7 +255,7 @@ export function TrashIcon() { @@ -280,32 +280,32 @@ export function FilterIcon() { > @@ -324,7 +324,7 @@ export function EyeDroperIcon({ isActive }: { isActive: boolean }) { @@ -442,7 +442,7 @@ export function RemoveIcon() { fill="none" xmlns="http://www.w3.org/2000/svg" > - + ); } @@ -462,7 +462,7 @@ export function InfoIcon() { /> { cy="1.35112" rx="1.4993" ry="1.27477" - fill="var(--icon-default-color)" + fill="var(--text-color)" /> ); @@ -562,31 +562,31 @@ export const DeleteIcon = () => { > @@ -784,21 +784,4 @@ export const SpeedIcon = () => { ); }; -// export const DublicateIcon = () => { -// return ( -// -// -// -// ); -// }; + diff --git a/app/src/components/icons/ExportModuleIcons.tsx b/app/src/components/icons/ExportModuleIcons.tsx index 1dda323..c1a8432 100644 --- a/app/src/components/icons/ExportModuleIcons.tsx +++ b/app/src/components/icons/ExportModuleIcons.tsx @@ -10,7 +10,7 @@ export function BuilderIcon({ isActive }: { isActive: boolean }) { > @@ -29,41 +29,41 @@ export function SimulationIcon({ isActive }: { isActive: boolean }) { > @@ -81,19 +81,19 @@ export function VisualizationIcon({ isActive }: { isActive: boolean }) { > @@ -112,20 +112,20 @@ export function CartIcon({ isActive }: { isActive: boolean }) { > diff --git a/app/src/components/icons/HeaderIcons.tsx b/app/src/components/icons/HeaderIcons.tsx index ef02f02..c2a0f62 100644 --- a/app/src/components/icons/HeaderIcons.tsx +++ b/app/src/components/icons/HeaderIcons.tsx @@ -9,7 +9,7 @@ export function ProjectIcon() { > @@ -31,26 +31,26 @@ export function ToggleSidebarIcon() { width="17" height="13.7273" rx="3.59091" - stroke="var(--accent-color)" + stroke="var(--text-color)" /> ); diff --git a/app/src/components/icons/RealTimeVisulationIcons.tsx b/app/src/components/icons/RealTimeVisulationIcons.tsx index d418247..84d8cca 100644 --- a/app/src/components/icons/RealTimeVisulationIcons.tsx +++ b/app/src/components/icons/RealTimeVisulationIcons.tsx @@ -10,43 +10,43 @@ export function CleanPannel() { diff --git a/app/src/components/icons/marketPlaceIcons.tsx b/app/src/components/icons/marketPlaceIcons.tsx index 6952ae1..5a9f293 100644 --- a/app/src/components/icons/marketPlaceIcons.tsx +++ b/app/src/components/icons/marketPlaceIcons.tsx @@ -52,13 +52,13 @@ export function EyeIconBig() { > @@ -80,7 +80,7 @@ export function CommentsIcon() { fillRule="evenodd" clipRule="evenodd" d="M8 13C7.416 13 6.852 12.932 6.31 12.8165L3.956 14.2315L3.9875 11.912C2.183 10.827 1 9.033 1 7C1 3.6865 4.134 1 8 1C11.866 1 15 3.6865 15 7C15 10.314 11.866 13 8 13ZM8 0C3.582 0 0 3.1345 0 7C0 9.2095 1.1725 11.177 3 12.4595V16L6.5045 13.8735C6.9895 13.9535 7.4885 14 8 14C12.418 14 16 10.866 16 7C16 3.1345 12.418 0 8 0ZM11.5 5.5H4.5C4.224 5.5 4 5.724 4 6C4 6.2765 4.224 6.5 4.5 6.5H11.5C11.776 6.5 12 6.2765 12 6C12 5.724 11.776 5.5 11.5 5.5ZM10.5 8.5H5.5C5.224 8.5 5 8.7235 5 9C5 9.2765 5.224 9.5 5.5 9.5H10.5C10.776 9.5 11 9.2765 11 9C11 8.7235 10.776 8.5 10.5 8.5Z" - fill="var(--icon-default-color)" + fill="var(--text-color)" /> @@ -131,7 +131,7 @@ export function StarsIconSmall() { ); } -export function FiileedStarsIconSmall() { +export function FilledStarsIconSmall() { return ( { } }; return ( -
    +
    - {searchValue ? ( -
    -
    -
    -

    Results for {searchValue}

    +
    +
    + {searchValue ? ( +
    +
    +
    +

    Results for {searchValue}

    +
    +
    + {categoryAssets && + categoryAssets?.map((asset: any, index: number) => ( +
    + {asset.filename} + +
    + {asset.filename + .split("_") + .map( + (word: any) => + word.charAt(0).toUpperCase() + word.slice(1) + ) + .join(" ")} +
    +
    + ))} +
    +
    -
    -
    - {categoryAssets && - categoryAssets?.map((asset: any, index: number) => ( + ) : selectedCategory ? ( +
    +

    + {selectedCategory}{" "}
    { + setSelectedCategory(null); + setCategoryAssets([]); + }} > - {asset.filename} + ← Back +
    +

    +
    + {categoryAssets && + categoryAssets?.map((asset: any, index: number) => ( +
    + {asset.filename} { + setSelectedItem({ + name: asset.filename, + id: asset.AssetID, + type: + asset.type === "undefined" + ? undefined + : asset.type, + }); + }} + /> -
    - {asset.filename - .split("_") - .map( - (word: any) => - word.charAt(0).toUpperCase() + word.slice(1) - ) - .join(" ")} -
    -
    - ))} -
    -
    - ) : selectedCategory ? ( -
    -
    { - setSelectedCategory(null); - setCategoryAssets([]); - }} - > - ← Back -
    -

    {selectedCategory}

    -
    - {categoryAssets && - categoryAssets?.map((asset: any, index: number) => ( -
    - {asset.filename} { - setSelectedItem({ - name: asset.filename, - id: asset.AssetID, - type: - asset.type === "undefined" ? undefined : asset.type, - }); - }} - /> - -
    - {asset.filename - .split("_") - .map( - (word: any) => - word.charAt(0).toUpperCase() + word.slice(1) - ) - .join(" ")} -
    -
    - ))} -
    -
    - ) : ( -
    -

    Categories

    -
    - {Array.from( - new Set(categoryList.map((asset) => asset.category)) - ).map((category, index) => { - const categoryInfo = categoryList.find( - (asset) => asset.category === category - ); - return ( -
    fetchCategoryAssets(category)} - > - {category} -
    {category}
    -
    - ); - })} -
    -
    - )} +
    + {asset.filename + .split("_") + .map( + (word: any) => + word.charAt(0).toUpperCase() + word.slice(1) + ) + .join(" ")} +
    +
    + ))} +
    +
    + ) : ( +
    +

    Categories

    +
    + {Array.from( + new Set(categoryList.map((asset) => asset.category)) + ).map((category, index) => { + const categoryInfo = categoryList.find( + (asset) => asset.category === category + ); + return ( +
    fetchCategoryAssets(category)} + > + {category} +
    {category}
    +
    + ); + })} +
    +
    + )} +
    + ); }; diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx index 3b2549a..1434446 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx @@ -91,44 +91,42 @@ const Trigger: React.FC = () => {
    {selectedTrigger}
    setActiveOption(option)} />
    -
    - { - const newModel = [...triggeredModel]; - newModel[0] = option; - setTriggeredModel(newModel); - }} - /> -
    -
    - { - const newPoint = [...triggeredPoint]; - newPoint[0] = option; - setTriggeredPoint(newPoint); - }} - /> -
    -
    - { - const newAction = [...triggeredAction]; - newAction[0] = option; - setTriggeredAction(newAction); - }} - /> -
    + { + const newModel = [...triggeredModel]; + newModel[0] = option; + setTriggeredModel(newModel); + }} + /> + { + const newPoint = [...triggeredPoint]; + newPoint[0] = option; + setTriggeredPoint(newPoint); + }} + /> + { + const newAction = [...triggeredAction]; + newAction[0] = option; + setTriggeredAction(newAction); + }} + />
    diff --git a/app/src/components/ui/menu/menu.tsx b/app/src/components/ui/menu/menu.tsx index a416c2c..39508b6 100644 --- a/app/src/components/ui/menu/menu.tsx +++ b/app/src/components/ui/menu/menu.tsx @@ -28,7 +28,7 @@ const MenuBar: React.FC = ({ setOpenMenu }) => { window.location.reload(); } - const savedTheme: string | null = localStorage.getItem("theme") || "light"; + const savedTheme: string | null = localStorage.getItem("theme") ?? "light"; return (
    = ({
    - + {selectedCard.rating}
    {selectedCard.views} views
    diff --git a/app/src/modules/market/Card.tsx b/app/src/modules/market/Card.tsx index ec9db06..a7010cc 100644 --- a/app/src/modules/market/Card.tsx +++ b/app/src/modules/market/Card.tsx @@ -3,6 +3,7 @@ import { CommentsIcon, DownloadIcon, EyeIconBig, + FilledStarsIconSmall, StarsIconSmall, VerifiedIcon, } from "../../components/icons/marketPlaceIcons"; @@ -80,7 +81,13 @@ const Card: React.FC = ({
    {[...Array(5)].map((_, index) => ( - + <> + {index < 3 ? ( + + ) : ( + + )} + ))}
    diff --git a/app/src/modules/visualization/widgets/panel/AddButtons.tsx b/app/src/modules/visualization/widgets/panel/AddButtons.tsx index 4877824..963f44d 100644 --- a/app/src/modules/visualization/widgets/panel/AddButtons.tsx +++ b/app/src/modules/visualization/widgets/panel/AddButtons.tsx @@ -6,8 +6,6 @@ import { } from "../../../../components/icons/RealTimeVisulationIcons"; import { AddIcon } from "../../../../components/icons/ExportCommonIcons"; import { useSocketStore } from "../../../../store/store"; -import { clearPanel } from "../../../../services/visulization/zone/clearPanel"; -import { lockPanel } from "../../../../services/visulization/zone/lockPanel"; // Define the type for `Side` type Side = "top" | "bottom" | "left" | "right"; @@ -305,7 +303,7 @@ const AddButtons: React.FC = ({ fill={ hiddenPanels[selectedZone.zoneId]?.includes(side) ? "var(--icon-default-color-active)" - : "var(--icon-default-color)" + : "var(--text-color)" } />
    @@ -342,7 +340,7 @@ const AddButtons: React.FC = ({ fill={ selectedZone.lockedPanels.includes(side) ? "var(--icon-default-color-active)" - : "var(--icon-default-color)" + : "var(--text-color)" } />
    diff --git a/app/src/styles/abstracts/variables.scss b/app/src/styles/abstracts/variables.scss index 37d9971..f4a6495 100644 --- a/app/src/styles/abstracts/variables.scss +++ b/app/src/styles/abstracts/variables.scss @@ -21,7 +21,8 @@ $text-button-color-dark: #f3f3fd; // background colors // ---------- light mode ---------- -$background-color: linear-gradient(-45deg, #fcfdfdcc 0%, #fcfdfd99 100%); +$background-color: linear-gradient(-45deg, #fcfdfd71 0%, #fcfdfd79 100%); +$background-color-solid-gradient: linear-gradient(-45deg, #fcfdfd 0%, #fcfdfd 100%); $background-color-solid: #fcfdfd; $background-color-secondary: #fcfdfd4d; $background-color-accent: #6f42c1; @@ -44,6 +45,7 @@ $background-radial-gray-gradient: radial-gradient( // ---------- dark mode ---------- $background-color-dark: linear-gradient(-45deg, #333333b3 0%, #2d2437b3 100%); +$background-color-solid-gradient-dark: linear-gradient(-45deg, #333333 0%, #2d2437 100%); $background-color-solid-dark: #19191d; $background-color-secondary-dark: #19191d99; $background-color-accent-dark: #6f42c1; @@ -105,19 +107,10 @@ $color5: #c7a8ff; // old variables $accent-color: #6f42c1; $accent-color-dark: #c4abf1; -// $highlight-accent-color: #e0dfff; -// $highlight-accent-color-dark: #403e6a; -// $background-color: #fcfdfd; -// $background-color-dark: #19191d; -// $background-color-secondary: #e1e0ff80; -// $background-color-secondary-dark: #39394f99; $background-color-gray: #f3f3f3; $background-color-gray-dark: #232323; -// $border-color: #e0dfff; -// $border-color-dark: #403e6a; - $shadow-color: #3c3c431a; $shadow-color-dark: #8f8f8f1a; diff --git a/app/src/styles/base/base.scss b/app/src/styles/base/base.scss index 10fb87c..bf53164 100644 --- a/app/src/styles/base/base.scss +++ b/app/src/styles/base/base.scss @@ -11,6 +11,7 @@ // background colors --background-color: #{$background-color}; --background-color-solid: #{$background-color-solid}; + --background-color-solid-gradient: #{$background-color-solid-gradient}; --background-color-secondary: #{$background-color-secondary}; --background-color-accent: #{$background-color-accent}; --background-color-button: #{$background-color-button}; @@ -61,6 +62,7 @@ // background colors --background-color: #{$background-color-dark}; + --background-color-solid-gradient: #{$background-color-solid-gradient-dark}; --background-color-solid: #{$background-color-solid-dark}; --background-color-secondary: #{$background-color-secondary-dark}; --background-color-accent: #{$background-color-accent-dark}; diff --git a/app/src/styles/components/input.scss b/app/src/styles/components/input.scss index b4e7651..e3b9585 100644 --- a/app/src/styles/components/input.scss +++ b/app/src/styles/components/input.scss @@ -51,9 +51,6 @@ input[type="number"] { -webkit-appearance: none; margin: 0; } - - // Firefox - -moz-appearance: textfield; } .input-value { @@ -105,7 +102,7 @@ input[type="number"] { .search-wrapper { position: sticky; top: 0; - padding: 8px 10px; + padding: 0px 10px; width: 100%; z-index: 1; @@ -140,15 +137,16 @@ input[type="number"] { .clear-button { @include flex-center; position: absolute; + top: 4px; right: 4px; - width: 24px; - height: 24px; + width: 21px; + height: 21px; border: none; + border-radius: #{$border-radius-large}; cursor: pointer; background: transparent; - &:hover { - background: var(--highlight-accent-color); + background: var(--background-color-secondary); } } } @@ -219,9 +217,9 @@ input[type="number"] { .regularDropdown-container { width: 100%; min-width: 80px; - padding: 2px 4px; + padding: 4px 8px; border: 1px solid var(--border-color); - border-radius: 6px; + border-radius: #{$border-radius-large}; position: relative; cursor: pointer; @@ -230,7 +228,7 @@ input[type="number"] { display: flex; justify-content: space-between; cursor: pointer; - border-radius: 6px; + border-radius: #{$border-radius-large}; } .dropdown-options { @@ -238,7 +236,7 @@ input[type="number"] { width: 100%; background: var(--background-color); border: 1px solid var(--border-color); - border-radius: #{$border-radius-small}; + border-radius: #{$border-radius-large}; z-index: 10; max-height: 200px; overflow-y: auto; @@ -255,7 +253,7 @@ input[type="number"] { padding: 2px 4px; cursor: pointer; flex-direction: row !important; - border-radius: #{$border-radius-small}; + border-radius: #{$border-radius-medium}; &:hover { color: var(--highlight-text-color); @@ -272,17 +270,19 @@ input[type="number"] { .input.default { width: 100%; position: relative; + @include flex-center; + gap: 6px; .dropdown { - top: 2px; - right: 2px; - position: absolute; - background: var(--highlight-accent-color); - border-radius: #{$border-radius-small}; - padding: 1px 4px; + height: 100%; + background: var(--background-color-drop-down-gradient); + border-radius: #{$border-radius-extra-large}; + padding: 1px 8px; + outline: 1px solid var(--border-color); .active-option { - color: var(--accent-color); + line-height: 22px; + color: var(--text-color); font-size: var(--font-size-small); } } @@ -304,10 +304,10 @@ input[type="number"] { .eye-picker-button { height: 24px; - min-width: 24px; + min-width: 36px; @include flex-center; - border-radius: #{$border-radius-small}; - background: var(--background-color-secondary); + border-radius: #{$border-radius-large}; + background: var(--background-color-drop-down-gradient); cursor: pointer; } @@ -326,6 +326,9 @@ input[type="number"] { background: var(--background-color) !important; border: 1px solid var(--border-color) !important; padding: 5px 10px; + cursor: pointer; + border-radius: #{$border-radius-extra-large}; + transition: background-color 0.3s ease; .label { white-space: nowrap; @@ -333,12 +336,6 @@ input[type="number"] { max-width: 80%; text-overflow: ellipsis; } - - // font-size: 12px; - cursor: pointer; - border-radius: 5px; - transition: background-color 0.3s ease; - &:hover { background: #333333; } @@ -354,7 +351,8 @@ input[type="number"] { right: -16px; background: var(--background-color); border: 1px solid var(--border-color); - border-radius: 5px; + border-radius: #{$border-radius-large}; + backdrop-filter: blur(18px); box-shadow: #{$box-shadow-medium}; z-index: 1000; min-width: 200px; @@ -364,13 +362,11 @@ input[type="number"] { .dropdown-content { display: flex; flex-direction: column; - gap: 6px; + padding: 2px; .nested-dropdown { margin-left: 0; } - - padding: 10px; } .loading { @@ -409,15 +405,16 @@ input[type="number"] { .dropdown-item { display: block; - padding: 5px 10px; + padding: 4px 10px; text-decoration: none; color: var(--text-color); font-size: var(--font-size-regular); cursor: pointer; transition: background-color 0.3s ease; - + border-radius: #{$border-radius-large}; &:hover { - background: var(--background-color); + color: var(--accent-color); + background: var(--highlight-accent-color); } } @@ -428,24 +425,25 @@ input[type="number"] { display: flex; align-items: center; justify-content: space-between; - padding: 5px 10px; + padding: 4px 10px; cursor: pointer; font-size: var(--font-size-regular); color: var(--text-color); transition: background-color 0.3s ease; - border-radius: #{$border-radius-small}; + border-radius: #{$border-radius-large}; .arrow-container { @include flex-center; } &:hover { - background: var(--background-color); + color: var(--accent-color); + background: var(--highlight-accent-color); } &.open { - color: var(--accent-color); - background: var(--highlight-accent-color); + color: var(--text-button-color); + background: var(--background-color-accent); } .icon { @@ -649,7 +647,7 @@ input[type="number"] { padding: 2px 32px; border: none; border-radius: #{$border-radius-large}; - color: var(--text-color); + color: var(--text-button-color); background: var(--background-color-button); transition: all 0.2s; cursor: pointer; diff --git a/app/src/styles/components/marketPlace/marketPlace.scss b/app/src/styles/components/marketPlace/marketPlace.scss index b84a252..23b14b7 100644 --- a/app/src/styles/components/marketPlace/marketPlace.scss +++ b/app/src/styles/components/marketPlace/marketPlace.scss @@ -9,8 +9,8 @@ position: absolute; left: 0; top: 0; - padding: 100px 50px; - padding-bottom: 32px; + padding: 10px; + padding-top: 100px; .marketplace-container { position: relative; @@ -59,8 +59,9 @@ .regularDropdown-container { max-width: 159px; height: 100%; - border-radius: #{$border-radius-large}; + border-radius: #{$border-radius-extra-large}; border: 1px solid var(--border-color); + padding: 0 10px; .dropdown-header { align-items: center; } @@ -68,8 +69,9 @@ .button { padding: 5px 20px; - border: 1px solid var(--accent-color); border-radius: 14px; + background: var(--background-color-button); + color: var(--text-button-color); } .rating-container { @@ -106,14 +108,14 @@ .cards-wrapper-container { display: flex; flex-wrap: wrap; - gap: 28px; + gap: 18px; .card-container { - width: calc(25% - 23px); + width: calc(25% - 14px); border-radius: 18px; padding: 12px; box-shadow: 0px 2px 10.5px 0px #0000000d; - background: var(--background-color); + background: var(--background-color-solid-gradient); border: 1px solid var(--border-color); position: relative; display: flex; diff --git a/app/src/styles/components/menu/menu.scss b/app/src/styles/components/menu/menu.scss index be9e17f..dffc6a4 100644 --- a/app/src/styles/components/menu/menu.scss +++ b/app/src/styles/components/menu/menu.scss @@ -7,7 +7,7 @@ gap: 2px; position: relative; border-radius: #{$border-radius-extra-large}; - background: var(--background-color-drop-down); + background: var(--background-color-drop-down-gradient); padding: 3px 8px; width: fit-content; max-width: 100%; @@ -25,11 +25,12 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + color: var(--text-color); } } .more-options-button { @include flex-center; - border-radius: #{$border-radius-small}; + border-radius: #{$border-radius-medium}; height: 22px; position: relative; &:hover { @@ -52,7 +53,7 @@ top: 32px; left: 0; z-index: 5; - background: var(--background-color); + background: var(--background-color-solid); color: var(--text-color); box-shadow: var(--box-shadow-light); border-radius: 8px; @@ -69,7 +70,7 @@ position: relative; height: 100%; padding: 4px 8px 4px 12px; - border-radius: #{$border-radius-small}; + border-radius: #{$border-radius-medium}; .menu-button { width: 100%; cursor: pointer; @@ -89,19 +90,21 @@ .dropdown-menu { position: absolute; top: 0; - left: 100%; - background: var(--background-color); + left: 103%; + background: var(--background-color-solid); min-width: 220px; - border-radius: 4px; + border-radius: #{$border-radius-medium}; box-shadow: var(--box-shadow-light); - border: 1px solid var(--background-color); + outline: 1px solid var(--border-color); + backdrop-filter: blur(20px); + outline-offset: -1px; z-index: 100; padding: 4px; .menu-item-container { position: relative; .menu-item { padding: 4px 8px 4px 12px; - border-radius: #{$border-radius-small}; + border-radius: #{$border-radius-medium}; display: flex; justify-content: space-between; align-items: center; @@ -138,18 +141,19 @@ .submenu { position: absolute; - left: 100%; + left: 102%; top: 0; - background: var(--background-color); + background: var(--background-color-solid); min-width: 200px; - border-radius: 0 4px 4px 4px; + border-radius: #{$border-radius-medium}; box-shadow: var(--box-shadow-light); - border: 1px solid var(--background-color); + outline: 1px solid var(--border-color); + outline-offset: -1px; z-index: 101; padding: 4px; .submenu-item { padding: 4px 8px 4px 12px; - border-radius: #{$border-radius-small}; + border-radius: #{$border-radius-medium}; display: flex; justify-content: space-between; align-items: center; diff --git a/app/src/styles/components/moduleToggle.scss b/app/src/styles/components/moduleToggle.scss index c864cbf..7e5b727 100644 --- a/app/src/styles/components/moduleToggle.scss +++ b/app/src/styles/components/moduleToggle.scss @@ -38,7 +38,7 @@ left: 0; width: 0%; height: 100%; - background: var(--highlight-accent-color); + background: var(--background-color-solid-gradient); transition: width 0.2s; border-radius: #{$border-radius-extra-large}; } diff --git a/app/src/styles/components/tools.scss b/app/src/styles/components/tools.scss index abea736..54c21e7 100644 --- a/app/src/styles/components/tools.scss +++ b/app/src/styles/components/tools.scss @@ -16,6 +16,8 @@ background: var(--background-color); backdrop-filter: blur(8px); z-index: #{$z-index-default}; + outline: 1px solid var(--border-color); + outline-offset: -1px; .split { height: 20px; @@ -39,7 +41,7 @@ height: 28px; width: 28px; cursor: pointer; - border-radius: #{$border-radius-small}; + border-radius: #{$border-radius-medium}; &:hover { background: color-mix(in srgb, @@ -116,10 +118,10 @@ .toggle-threed-button { @include flex-center; - padding: 3px; - border-radius: #{$border-radius-small}; - background: var(--highlight-accent-color); - gap: 2px; + padding: 4px; + border-radius: #{$border-radius-medium}; + background: var(--background-color); + gap: 5px; position: relative; .toggle-option { @@ -132,30 +134,25 @@ &::after { content: ""; position: absolute; - background: var(--accent-color); - left: 3px; - top: 3px; - height: 18px; - width: 18px; - border-radius: #{$border-radius-small}; + background: var(--background-color-accent); + left: 2px; + top: 2px; + height: 23px; + width: 23px; + border-radius: #{$border-radius-medium}; transition: all 0.2s; } .active { - color: var(--highlight-accent-color); + color: var(--text-button-color); } } .toggled { &::after { - left: 24px; + left: 25px; } } - - - - - } .exitPlay { diff --git a/app/src/styles/components/visualization/floating/common.scss b/app/src/styles/components/visualization/floating/common.scss index 0084e7a..0bbbdc9 100644 --- a/app/src/styles/components/visualization/floating/common.scss +++ b/app/src/styles/components/visualization/floating/common.scss @@ -182,7 +182,6 @@ background: var(--background-color-secondary); border-radius: 20px; color: var(--text-color); - background: #252525cc; .header-wrapper { width: 100%; @@ -276,7 +275,7 @@ .icon { width: 45px; height: 45px; - background: var(--accent-color); + background: var(--background-color-accent); display: flex; justify-content: center; align-items: center; diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index 583dc0a..70d3a5d 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -7,7 +7,7 @@ top: 32px; left: 8px; background: var(--background-color); - backdrop-filter: blur(150px); + backdrop-filter: blur(15px); border-radius: #{$border-radius-extra-large}; outline: 1px solid var(--border-color); box-shadow: #{$box-shadow-medium}; @@ -30,10 +30,6 @@ padding: 0 8px; width: 100%; max-width: calc(100% - 32px); - - .input-value { - color: var(--accent-color); - } } } @@ -235,7 +231,6 @@ .outline-container { height: 100%; - .outline-content-container { position: relative; height: 100%; @@ -256,7 +251,7 @@ top: 32px; right: 8px; background: var(--background-color); - backdrop-filter: blur(150px); + backdrop-filter: blur(15px); border-radius: #{$border-radius-extra-large}; outline: 1px solid var(--border-color); box-shadow: #{$box-shadow-medium}; @@ -276,7 +271,7 @@ .share-button { padding: 4px 12px; - color: var(--text-color); + color: var(--text-button-color); background: var(--background-color-button); font-weight: var(--font-weight-regular); border-radius: #{$border-radius-large}; @@ -750,7 +745,7 @@ .value-field-container { margin: 0; input { - padding: 5px 4px; + padding: 5px 10px; } .dropdown { top: 4px; @@ -772,8 +767,8 @@ padding: 6px 12px; .regularDropdown-container { padding: 5px 8px; - outline: 2px solid var(--border-color); - outline-offset: -2px; + outline: 1px solid var(--border-color); + outline-offset: -1px; border: none; } } @@ -806,7 +801,6 @@ @include flex-space-between; padding: 4px 12px; width: 100%; - margin: 2px 0; border-radius: #{$border-radius-medium}; .value { display: flex; @@ -939,6 +933,18 @@ } } + .trigger-wrapper { + .trigger-item { + .trigger-name { + padding: 8px; + margin-top: 4px; + } + .value-field-container { + margin: 0; + } + } + } + .footer { @include flex-center; justify-content: flex-start; @@ -948,10 +954,9 @@ } .compare-simulations-container { - margin: 6px; background: var(--background-color-gray); padding: 12px; - border-radius: #{$border-radius-medium}; + border-radius: #{$border-radius-large}; .compare-simulations-header { font-weight: var(--font-weight-medium); @@ -973,10 +978,12 @@ input { width: fit-content; - background: var(--accent-color); - color: var(--highlight-accent-color); - padding: 2px 8px; + background: var(--background-color-button); + color: var(--text-button-color); + padding: 3px 10px; cursor: pointer; + border: none; + outline: none; } } } @@ -1084,24 +1091,24 @@ input { border: none; + outline: none; cursor: pointer; - transition: all 0.2s; &:hover { - transform: translateY(-2px); box-shadow: #{$box-shadow-medium}; - outline: 1px solid var(--accent-color); + outline: 1px solid var(--input-border-color); } } .cancel { background: transparent; - color: var(--accent-color); + background: var(--background-color-secondary); + color: var(--text-color); } .submit { - background: var(--accent-color); - color: var(--highlight-accent-color); + background: var(--background-color-button); + color: var(--text-button-color); } } @@ -1109,7 +1116,7 @@ margin: 6px; background: var(--background-color-gray); padding: 12px; - border-radius: #{$border-radius-medium}; + border-radius: #{$border-radius-large}; .custom-analysis-header { font-weight: var(--font-weight-medium); @@ -1131,34 +1138,53 @@ input { width: fit-content; - background: var(--accent-color); - color: var(--highlight-accent-color); - padding: 2px 8px; + background: var(--background-color-button); + color: var(--text-button-color); + padding: 3px 10px; cursor: pointer; + border: none; + outline: none; } } } } } -.assets-container { +.assets-container-main { width: 100%; display: flex; flex-direction: row; flex-wrap: wrap; height: 100%; + max-height: 50vh; gap: 3px; - padding: 10px 0; + overflow: auto; + + .assets-result { + width: 100%; + .assets-wrapper { + margin: 0; + } + } + .assets-list-section { + width: 100%; + padding: 4px; + } .assets-wrapper { width: 100%; position: relative; - margin: 8px 10px; - h2 { + h2, + .searched-content { color: var(--text-color); font-family: $large; font-weight: $bold-weight; + padding: 8px; + @include flex-space-between; + .back-button { + cursor: pointer; + } } .categories-container { @@ -1167,8 +1193,8 @@ flex-direction: row; flex-wrap: wrap; height: 100%; - gap: 0px 4px; - padding: 10px 0; + gap: 4px; + padding: 2px; .category { width: 123px; @@ -1267,11 +1293,11 @@ flex-direction: row; flex-wrap: wrap; height: 100%; - gap: 0px 4px; - padding: 10px 0; + gap: 6px; + padding: 2px; .assets { - width: 123px; + width: 122px; height: 95px; border-radius: #{$border-radius-large}; background: var(--background-color); @@ -1295,7 +1321,11 @@ width: 100%; height: 100%; font-size: var(--font-size-regular); - background: linear-gradient(0deg,rgba(37, 24, 51, 0) 0%, rgba(78, 22, 128, 0.4) 100%); + background: linear-gradient( + 0deg, + rgba(37, 24, 51, 0) 0%, + rgba(78, 22, 128, 0.4) 100% + ); pointer-events: none; backdrop-filter: blur(8px); opacity: 0; @@ -1316,23 +1346,5 @@ } } } - - .back-button { - position: absolute; - top: 0; - right: 0; - @include flex-center; - cursor: pointer; - } - } -} - -.assets-result { - width: 100%; - height: 100%; - margin: 8px 10px; - - .assets-wrapper { - margin: 0; } } diff --git a/app/src/styles/pages/realTimeViz.scss b/app/src/styles/pages/realTimeViz.scss index 3aa1bd5..a9dba89 100644 --- a/app/src/styles/pages/realTimeViz.scss +++ b/app/src/styles/pages/realTimeViz.scss @@ -4,7 +4,6 @@ // Main Container .realTime-viz { background: #131313; - border-radius: 20px; box-shadow: $box-shadow-medium; width: calc(100% - (320px + 270px + 90px)); height: calc(100% - (250px)); @@ -24,19 +23,15 @@ } .floating { - - width: calc(var(--realTimeViz-container-width) * 0.2); height: calc(var(--realTimeViz-container-width) * 0.05); min-width: 250px; max-width: 300px; - // min-height: 83px !important; - // max-height: 100px !important; - background: var(--background-color); - border: 1.23px solid var(--border-color); + backdrop-filter: blur(10px); + border: 1px solid var(--border-color); box-shadow: 0px 4.91px 4.91px 0px #0000001c; border-radius: $border-radius-medium; padding: 18px; @@ -67,12 +62,12 @@ .zone-wrapper { display: flex; background: var(--background-color); + backdrop-filter: blur(10px); position: absolute; bottom: 0px; left: 50%; gap: 6px; border-radius: 8px; - max-width: 80%; overflow: auto; max-width: calc(100% - 500px); min-width: 150px; @@ -117,15 +112,13 @@ } .active { - background: var(--accent-color); + background: var(--background-color-accent); color: var(--background-color); - // color: #FCFDFD !important; } } .zone-wrapper.bottom { bottom: var(--bottomWidth); - // bottom: 200px; } .content-container { @@ -146,7 +139,6 @@ display: flex; background: rgba(224, 223, 255, 0.5); position: absolute; - // bottom: 10px; left: 50%; transform: translate(-50%, 0); gap: 6px; @@ -189,7 +181,6 @@ border-radius: 6px; overflow: auto; z-index: $z-index-tools; - overflow: auto; &::-webkit-scrollbar { display: none; @@ -204,6 +195,7 @@ flex-direction: column; gap: 6px; background: var(--background-color); + backdrop-filter: blur(10px); &::-webkit-scrollbar { display: none; @@ -211,12 +203,10 @@ .chart-container { width: 100%; - max-height: 100%; border: 1px dashed var(--background-color-gray); border-radius: 8px; box-shadow: var(--box-shadow-medium); - padding: 6px 0; background: var(--background-color); position: relative; padding: 0 10px; @@ -255,14 +245,11 @@ color: var(--text-color); &:hover { + background: var(--highlight-accent-color); + width: 100%; .label { color: var(--accent-color); } - } - - &:hover { - background: var(--highlight-accent-color); - width: 100%; svg { &:first-child { @@ -285,7 +272,6 @@ } } - .close-btn { position: absolute; top: 5px; @@ -369,7 +355,6 @@ .playingFlase { .zone-wrapper.bottom { bottom: var(--bottomWidth); - // bottom: 210px; } } @@ -398,7 +383,7 @@ } .active { - background: var(--accent-color); + background: var(--background-color-accent); } &:hover { @@ -413,8 +398,7 @@ height: 18px; display: flex; justify-content: center; - // align-items: center; - background: var(--accent-color); + background: var(--background-color-accent); border: none; color: var(--background-color); border-radius: 4px; @@ -425,20 +409,20 @@ } path { - stroke: var(--primary-color); + stroke: var(--text-color); stroke-width: 2; } } .active { - background: #ffe3e0; + background: #f657482f; .add-icon { rotate: 45deg; path { stroke: #f65648; - stroke-width: 2; + stroke-width: 1.3; } } } @@ -589,12 +573,6 @@ } .floating-wrapper { - .icon { - // width: 25px !important; - // height: 25px !important; - // background: transparent; - } - .kebab { width: 25px; height: 25px; @@ -640,9 +618,6 @@ .label { color: var(--accent-color); } - } - - &:hover { background: var(--highlight-accent-color); width: 100%; @@ -662,22 +637,19 @@ } .distance-line { - position: absolute; border-style: dashed; - border-color: var(--accent-color); - /* Green color for visibility */ + border-color: var(--background-color-accent); border-width: 1px; pointer-events: none; - /* Ensure lins don't interfere with dragging */ z-index: 10000; } /* Label styles for displaying distance values */ .distance-label { position: absolute; - background: var(--accent-color); - color: white; + background: var(--background-color-accent); + color: var(--text-button-color); font-size: 12px; padding: 2px 6px; border-radius: 3px; @@ -749,15 +721,12 @@ } .activeChart { - outline: 2px solid var(--accent-color); + outline: 1px solid var(--highlight-secondary-color); z-index: 2 !important; } .chart-container.notLinked { - outline: 1px solid red; - - } .connectionSuccess { @@ -801,4 +770,4 @@ } } } -} \ No newline at end of file +} From 5ea85f49f07bcde6d6d8d7a8efbfe2b9323daffa Mon Sep 17 00:00:00 2001 From: Vishnu Date: Wed, 30 Apr 2025 16:52:08 +0530 Subject: [PATCH 13/14] refactor: Update icon stroke and fill colors based on active state; modify EventProperties component structure; adjust styles in tools, sidebar, and realTimeViz for improved layout and responsiveness --- app/src/components/icons/SimulationIcons.tsx | 36 ++++++-- .../eventProperties/EventProperties.tsx | 8 +- app/src/styles/components/tools.scss | 2 +- app/src/styles/layout/sidebar.scss | 83 +++++++++---------- app/src/styles/pages/realTimeViz.scss | 7 +- 5 files changed, 75 insertions(+), 61 deletions(-) diff --git a/app/src/components/icons/SimulationIcons.tsx b/app/src/components/icons/SimulationIcons.tsx index b4aa881..ef23c8f 100644 --- a/app/src/components/icons/SimulationIcons.tsx +++ b/app/src/components/icons/SimulationIcons.tsx @@ -9,13 +9,17 @@ export function AnalysisIcon({ isActive }: { isActive: boolean }) { > @@ -34,11 +38,15 @@ export function MechanicsIcon({ isActive }: { isActive: boolean }) { > ); @@ -55,15 +63,21 @@ export function PropertiesIcon({ isActive }: { isActive: boolean }) { > ); @@ -82,13 +96,17 @@ export function SimulationIcon({ isActive }: { isActive: boolean }) { fillRule="evenodd" clipRule="evenodd" d="M6.44104 7.04762C6.57815 6.98413 6.73614 6.98413 6.87325 7.04762L12.0161 9.42958C12.198 9.51377 12.3143 9.69589 12.3143 9.89624V15.8512C12.3143 16.0347 12.2165 16.2043 12.0577 16.2962L6.9148 19.2736C6.75547 19.3659 6.55881 19.3659 6.39949 19.2736L1.25661 16.2962C1.09779 16.2043 1 16.0347 1 15.8512V9.89624C1 9.69589 1.11635 9.51377 1.29815 9.42958L6.44104 7.04762ZM2.02857 10.7297L6.14286 12.794V17.9366L2.02857 15.5546V10.7297ZM7.17143 17.9366L11.2857 15.5546V10.7297L7.17143 12.794V17.9366ZM6.65714 11.9013L10.6163 9.91477L6.65714 8.08106L2.69798 9.91477L6.65714 11.9013Z" - fill={"var(--icon-default-color-active)"} + fill={ + isActive ? "var(--icon-default-color-active)" : "var(--text-color)" + } /> ); diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx index 88ae240..a307c86 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx @@ -92,9 +92,9 @@ const EventProperties: React.FC = () => {

    Here are some products you can add it to:

    -
      +
      {products.map((product) => ( -
    • +
      -
    • +
      ))} -
    +
    )} diff --git a/app/src/styles/components/tools.scss b/app/src/styles/components/tools.scss index 54c21e7..0c1a9c3 100644 --- a/app/src/styles/components/tools.scss +++ b/app/src/styles/components/tools.scss @@ -30,7 +30,7 @@ .general-options, .activeDropicon { @include flex-center; - gap: 8px; + gap: 2px; interpolate-size: allow-keywords; width: 0; opacity: 0; diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index 70d3a5d..c7f1694 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -51,8 +51,6 @@ .active { background: var(--background-color-accent); - outline: 1px solid var(--border-color); - outline-offset: -1px; rect { stroke: var(--icon-default-color-active); } @@ -60,7 +58,12 @@ fill: var(--icon-default-color-active); } &:hover { - background: var(--background-color-secondary); + rect { + stroke: var(--icon-default-color); + } + circle { + fill: var(--icon-default-color); + } } } } @@ -365,14 +368,14 @@ width: 34px; border-radius: #{$border-radius-circle}; background: var(--background-color-secondary); - backdrop-filter: blur(8px); - box-shadow: #{$box-shadow-medium}; + backdrop-filter: blur(12px); outline: 1px solid var(--border-color); outline-offset: -1px; } .active { background: var(--background-color-accent); + outline: none; } } @@ -390,55 +393,43 @@ .no-event-selected { color: #666; - padding: 1.8rem 1rem; + padding: 16px; grid-column: 1 / -1; .products-list { padding-top: 1rem; + .product-item { + text-align: start; + margin-top: 8px; + padding: 2px 0; + text-decoration: none; + display: flex; + flex-wrap: wrap; + gap: 6px; + button { + width: fit-content; + position: relative; + @include flex-center; + gap: 4px; + background: var(--background-color); + padding: 8px 12px; + border-radius: #{$border-radius-extra-large}; + outline: 1px solid var(--border-color); + &:hover { + background: var(--background-color-accent); + color: var(--text-button-color); + outline: none; + path { + stroke: var(--text-button-color); + stroke-width: 1.3; + } + } + } + } .products-list-title { text-align: start; color: var(--accent-color); font-size: var(--font-size-regular); } - ul { - li { - text-align: start; - margin: 8px 0; - padding: 2px 0; - text-decoration: none; - &::marker { - content: ""; - } - button { - width: fit-content; - position: relative; - transition: all 0.2s ease; - @include flex-center; - gap: 4px; - &:before { - content: ""; - position: absolute; - left: 0; - bottom: -4px; - background: var(--accent-color); - height: 1px; - width: 0%; - transition: all 0.3s ease; - } - } - &:hover { - button { - path { - stroke: var(--accent-color); - stroke-width: 1.5px; - } - color: var(--accent-color); - &:before { - width: 100%; - } - } - } - } - } } } } diff --git a/app/src/styles/pages/realTimeViz.scss b/app/src/styles/pages/realTimeViz.scss index a9dba89..665e44b 100644 --- a/app/src/styles/pages/realTimeViz.scss +++ b/app/src/styles/pages/realTimeViz.scss @@ -113,7 +113,9 @@ .active { background: var(--background-color-accent); - color: var(--background-color); + color: var(--text-button-color); + border: none; + outline: none; } } @@ -406,6 +408,9 @@ .add-icon { @include flex-center; transition: rotate 0.2s; + path{ + stroke: var(--text-button-color); + } } path { From bd402275b2781f34d560d37748e907d6a2bac8c0 Mon Sep 17 00:00:00 2001 From: Vishnu Date: Wed, 30 Apr 2025 17:05:28 +0530 Subject: [PATCH 14/14] refactor: Adjust styles for dropdown options; modify padding, margin, and border-radius for improved layout and appearance --- app/src/styles/components/tools.scss | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/styles/components/tools.scss b/app/src/styles/components/tools.scss index 0c1a9c3..5984dab 100644 --- a/app/src/styles/components/tools.scss +++ b/app/src/styles/components/tools.scss @@ -79,19 +79,20 @@ position: absolute; bottom: 40px; left: 0; - box-shadow: #{$box-shadow-medium}; - padding: 8px; - border-radius: #{$border-radius-large}; + padding: 2px 4px; + border-radius: #{$border-radius-medium}; background: var(--background-color); + backdrop-filter: blur(8px); .option-list { - margin: 4px 0; display: flex; align-items: center; white-space: nowrap; border-radius: #{$border-radius-medium}; gap: 6px; - padding: 4px; + padding: 2px; + padding-right: 12px; + margin: 2px 0; &:hover { background: var(--highlight-accent-color);