From 61828622962497639a7f197567ff49e9eb76d0d7 Mon Sep 17 00:00:00 2001 From: Poovizhi Date: Thu, 28 Aug 2025 17:58:38 +0530 Subject: [PATCH] added temp vehicle schema that holds the path details and vehicle details --- .../events/points/creator/pointsCreator.tsx | 4 +- .../spatialUI/vehicle/vehicleUI.tsx | 1 + .../instances/animator/vehicleAnimator.tsx | 718 ++++++++++-------- .../instances/instance/vehicleInstance2.tsx | 253 ++++++ .../vehicle/instances/vehicleInstances.tsx | 53 +- .../pathCreator/function/usePathManager.ts | 2 +- .../vehicle/pathCreator/pathCreator.tsx | 15 +- .../vehicle/pathCreator/pointHandler.tsx | 369 ++++++--- app/src/store/builder/store.ts | 65 +- 9 files changed, 1017 insertions(+), 463 deletions(-) create mode 100644 app/src/modules/simulation/vehicle/instances/instance/vehicleInstance2.tsx diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx index 9fb27a9..f85417f 100644 --- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx +++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx @@ -180,11 +180,11 @@ function PointsCreator() { drag = false; }; - const onMouseUp = () => { + const onMouseUp = (e : MouseEvent) => { if (selectedEventSphere && !drag) { raycaster.setFromCamera(pointer, camera); const intersects = raycaster.intersectObjects(scene.children, true).filter((intersect) => intersect.object.name === "Event-Sphere"); - if (intersects.length === 0) { + if (intersects.length === 0 && e.button === 0) { clearSelectedEventSphere(); setTransformMode(null); } diff --git a/app/src/modules/simulation/spatialUI/vehicle/vehicleUI.tsx b/app/src/modules/simulation/spatialUI/vehicle/vehicleUI.tsx index e287b8e..43c9c1b 100644 --- a/app/src/modules/simulation/spatialUI/vehicle/vehicleUI.tsx +++ b/app/src/modules/simulation/spatialUI/vehicle/vehicleUI.tsx @@ -199,6 +199,7 @@ const VehicleUI = () => { steeringAngle: steeringRotation[1], }, }, + } ); diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index 208f879..9e9fcdd 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -1,365 +1,409 @@ - -import { useEffect, useRef, useState } from 'react' -import { useFrame, useThree, ThreeEvent } from '@react-three/fiber'; -import * as THREE from 'three'; -import { Line } from '@react-three/drei'; -import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; -import { useSceneContext } from '../../../../scene/sceneContext'; -import { useActiveTool, useSelectedPath } from '../../../../../store/builder/store'; - +import { useEffect, useRef, useState } from "react"; +import { useFrame, useThree, ThreeEvent } from "@react-three/fiber"; +import * as THREE from "three"; +import { Line } from "@react-three/drei"; +import { + useAnimationPlaySpeed, + usePauseButtonStore, + usePlayButtonStore, + useResetButtonStore, +} from "../../../../../store/usePlayButtonStore"; +import { useSceneContext } from "../../../../scene/sceneContext"; +import { + useActiveTool, + useSelectedPath, +} from "../../../../../store/builder/store"; interface VehicleAnimatorProps { - path: [number, number, number][]; - handleCallBack: () => void; - reset: () => void; - startUnloadingProcess: () => void; - currentPhase: string; - agvUuid: string; - agvDetail: VehicleStatus; + path: [number, number, number][]; + handleCallBack: () => void; + reset: () => void; + startUnloadingProcess: () => void; + currentPhase: string; + agvUuid: string; + agvDetail: VehicleStatus; } -function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset, startUnloadingProcess }: Readonly) { - const { vehicleStore } = useSceneContext(); - const { getVehicleById } = vehicleStore(); - const { isPaused } = usePauseButtonStore(); - const { isPlaying } = usePlayButtonStore(); - const { speed } = useAnimationPlaySpeed(); - const { isReset, setReset } = useResetButtonStore(); - const progressRef = useRef(0); - const movingForward = useRef(true); - const completedRef = useRef(false); - const [objectRotation, setObjectRotation] = useState<{ x: number; y: number; z: number } | undefined>(agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 }) - const [restRotation, setRestingRotation] = useState(true); - const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); - const { scene, controls } = useThree(); - const { selectedPath } = useSelectedPath(); - const [isAnyDragging, setIsAnyDragging] = useState(""); +function VehicleAnimator({ + path, + handleCallBack, + currentPhase, + agvUuid, + agvDetail, + reset, + startUnloadingProcess, +}: Readonly) { + const { vehicleStore } = useSceneContext(); + const { getVehicleById } = vehicleStore(); + const { isPaused } = usePauseButtonStore(); + const { isPlaying } = usePlayButtonStore(); + const { speed } = useAnimationPlaySpeed(); + const { isReset, setReset } = useResetButtonStore(); + const progressRef = useRef(0); + const movingForward = useRef(true); + const completedRef = useRef(false); + const [objectRotation, setObjectRotation] = useState< + { x: number; y: number; z: number } | undefined + >(agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 }); + const [restRotation, setRestingRotation] = useState(true); + const [currentPath, setCurrentPath] = useState<[number, number, number][]>( + [] + ); + const { scene, controls } = useThree(); + const { selectedPath } = useSelectedPath(); + const [isAnyDragging, setIsAnyDragging] = useState(""); + useEffect(() => { + if (currentPhase === "stationed-pickup" && path.length > 0) { + setCurrentPath(path); + setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation); + } else if (currentPhase === "pickup-drop" && path.length > 0) { + setObjectRotation(agvDetail.point.action?.unLoadPoint?.rotation); + setCurrentPath(path); + } else if (currentPhase === "drop-pickup" && path.length > 0) { + setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation); + setCurrentPath(path); + } + }, [currentPhase, path, objectRotation, selectedPath]); - useEffect(() => { - if (currentPhase === 'stationed-pickup' && path.length > 0 && selectedPath === "auto") { - setCurrentPath(path); - setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation) - } else if (currentPhase === 'pickup-drop' && path.length > 0) { - setObjectRotation(agvDetail.point.action?.unLoadPoint?.rotation) - setCurrentPath(path); - } else if (currentPhase === 'drop-pickup' && path.length > 0) { - setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation) - setCurrentPath(path); + useEffect(() => { + completedRef.current = false; + }, [currentPath]); + + useEffect(() => { + if (isReset || !isPlaying) { + reset(); + setCurrentPath([]); + completedRef.current = false; + movingForward.current = true; + progressRef.current = 0; + setReset(false); + setRestingRotation(true); + const object = scene.getObjectByProperty("uuid", agvUuid); + const vehicle = getVehicleById(agvDetail.modelUuid); + if (object && vehicle) { + object.position.set( + vehicle.position[0], + vehicle.position[1], + vehicle.position[2] + ); + object.rotation.set( + vehicle.rotation[0], + vehicle.rotation[1], + vehicle.rotation[2] + ); + } + } + }, [isReset, isPlaying]); + + const lastTimeRef = useRef(performance.now()); + + useFrame(() => { + if (!isPlaying) return; + const now = performance.now(); + const delta = (now - lastTimeRef.current) / 1000; + lastTimeRef.current = now; + + const object = scene.getObjectByProperty("uuid", agvUuid); + if (!object || currentPath.length < 2) return; + if (isPaused) return; + + let totalDistance = 0; + const distances = []; + let accumulatedDistance = 0; + let index = 0; + const rotationSpeed = 0.75; + + 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 && + progressRef.current > 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 targetQuaternion = new THREE.Quaternion().setFromRotationMatrix( + new THREE.Matrix4().lookAt(start, end, new THREE.Vector3(0, 1, 0)) + ); + const y180 = new THREE.Quaternion().setFromAxisAngle( + new THREE.Vector3(0, 1, 0), + Math.PI + ); + targetQuaternion.multiply(y180); + + const angle = object.quaternion.angleTo(targetQuaternion); + if (angle < 0.01) { + object.quaternion.copy(targetQuaternion); + } else { + const step = rotationSpeed * delta * speed * agvDetail.speed; + const angle = object.quaternion.angleTo(targetQuaternion); + + if (angle < step) { + object.quaternion.copy(targetQuaternion); + } else { + object.quaternion.rotateTowards(targetQuaternion, step); } - }, [currentPhase, path, objectRotation, selectedPath]); + } - useEffect(() => { - completedRef.current = false; - }, [currentPath]); + const isAligned = angle < 0.01; - useEffect(() => { - if (isReset || !isPlaying) { - reset(); - setCurrentPath([]); - completedRef.current = false; - movingForward.current = true; - progressRef.current = 0; - setReset(false); - setRestingRotation(true); - const object = scene.getObjectByProperty('uuid', agvUuid); - const vehicle = getVehicleById(agvDetail.modelUuid); - if (object && vehicle) { - object.position.set(vehicle.position[0], vehicle.position[1], vehicle.position[2]); - object.rotation.set(vehicle.rotation[0], vehicle.rotation[1], vehicle.rotation[2]); + if (isAligned) { + progressRef.current += delta * (speed * agvDetail.speed); + const t = (progressRef.current - accumulatedDistance) / segmentDistance; + const position = start.clone().lerp(end, t); + object.position.copy(position); + } + } + + if (progressRef.current >= totalDistance) { + if (restRotation && objectRotation) { + const targetEuler = new THREE.Euler( + 0, + objectRotation.y - agvDetail.point.action.steeringAngle, + 0 + ); + + const baseQuaternion = new THREE.Quaternion().setFromEuler(targetEuler); + const y180 = new THREE.Quaternion().setFromAxisAngle( + new THREE.Vector3(0, 1, 0), + Math.PI + ); + const targetQuaternion = baseQuaternion.multiply(y180); + + const angle = object.quaternion.angleTo(targetQuaternion); + if (angle < 0.01) { + object.quaternion.copy(targetQuaternion); + setRestingRotation(false); + } else { + const step = rotationSpeed * delta * speed * agvDetail.speed; + const angle = object.quaternion.angleTo(targetQuaternion); + + if (angle < step) { + object.quaternion.copy(targetQuaternion); + } else { + object.quaternion.rotateTowards(targetQuaternion, step); + } + } + return; + } + } + + if (progressRef.current >= totalDistance) { + setRestingRotation(true); + progressRef.current = 0; + movingForward.current = !movingForward.current; + setCurrentPath([]); + handleCallBack(); + if (currentPhase === "pickup-drop") { + requestAnimationFrame(startUnloadingProcess); + } + } + }); + + const updatePoint = (index: number, pos: THREE.Vector3) => { + const updated = [...currentPath]; + updated[index] = pos.toArray() as [number, number, number]; + setCurrentPath(updated); + }; + + return ( + <> + {selectedPath === "auto" && ( + + {currentPath.map((pos, i) => { + if (i < currentPath.length - 1) { + return ( + { + const updated = [...currentPath]; + updated[i0] = p0.toArray() as [number, number, number]; + updated[i1] = p1.toArray() as [number, number, number]; + setCurrentPath(updated); + }} + isAnyDragging={isAnyDragging} + setIsAnyDragging={setIsAnyDragging} + /> + ); } - } - }, [isReset, isPlaying]) - - const lastTimeRef = useRef(performance.now()); - - useFrame(() => { - if (!isPlaying) return - const now = performance.now(); - const delta = (now - lastTimeRef.current) / 1000; - lastTimeRef.current = now; - - const object = scene.getObjectByProperty('uuid', agvUuid); - if (!object || currentPath.length < 2) return; - if (isPaused) return; - - let totalDistance = 0; - const distances = []; - let accumulatedDistance = 0; - let index = 0; - const rotationSpeed = 0.75; - - 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 && progressRef.current > 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 targetQuaternion = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().lookAt(start, end, new THREE.Vector3(0, 1, 0))); - const y180 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI); - targetQuaternion.multiply(y180); - - const angle = object.quaternion.angleTo(targetQuaternion); - if (angle < 0.01) { - object.quaternion.copy(targetQuaternion); - } else { - const step = rotationSpeed * delta * speed * agvDetail.speed; - const angle = object.quaternion.angleTo(targetQuaternion); - - if (angle < step) { - object.quaternion.copy(targetQuaternion); - } else { - object.quaternion.rotateTowards(targetQuaternion, step); - } - } - - const isAligned = angle < 0.01; - - if (isAligned) { - progressRef.current += delta * (speed * agvDetail.speed); - const t = (progressRef.current - accumulatedDistance) / segmentDistance; - const position = start.clone().lerp(end, t); - object.position.copy(position); - } - } - - if (progressRef.current >= totalDistance) { - if (restRotation && objectRotation) { - const targetEuler = new THREE.Euler(0, objectRotation.y - agvDetail.point.action.steeringAngle, 0); - - const baseQuaternion = new THREE.Quaternion().setFromEuler(targetEuler); - const y180 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI); - const targetQuaternion = baseQuaternion.multiply(y180); - - const angle = object.quaternion.angleTo(targetQuaternion); - if (angle < 0.01) { - object.quaternion.copy(targetQuaternion); - setRestingRotation(false); - } else { - const step = rotationSpeed * delta * speed * agvDetail.speed; - const angle = object.quaternion.angleTo(targetQuaternion); - - if (angle < step) { - object.quaternion.copy(targetQuaternion); - } else { - object.quaternion.rotateTowards(targetQuaternion, step); - } - } - return; - } - } - - if (progressRef.current >= totalDistance) { - setRestingRotation(true); - progressRef.current = 0; - movingForward.current = !movingForward.current; - setCurrentPath([]); - handleCallBack(); - if (currentPhase === 'pickup-drop') { - requestAnimationFrame(startUnloadingProcess); - - } - } - - }); - - const updatePoint = (index: number, pos: THREE.Vector3) => { - const updated = [...currentPath]; - updated[index] = pos.toArray() as [number, number, number]; - setCurrentPath(updated); - }; - - return ( - <> - {selectedPath === "auto" && - - {currentPath.map((pos, i) => { - if (i < currentPath.length - 1) { - return ( - { - const updated = [...currentPath]; - updated[i0] = p0.toArray() as [number, number, number]; - updated[i1] = p1.toArray() as [number, number, number]; - setCurrentPath(updated); - }} - isAnyDragging={isAnyDragging} - setIsAnyDragging={setIsAnyDragging} - /> - ); - } - return null; - })} - {currentPath.length > 0 && ( - { if (controls) (controls as any).enabled = true; }}> - {currentPath.map((pos, i) => - ( - ) - )} - - )} - - } - - ); + return null; + })} + {currentPath.length > 0 && ( + { + if (controls) (controls as any).enabled = true; + }} + > + {currentPath.map((pos, i) => ( + + ))} + + )} + + )} + + ); } - - export default VehicleAnimator; - - - function DraggableSphere({ - index, - position, - onMove, - isAnyDragging, - setIsAnyDragging, + index, + position, + onMove, + isAnyDragging, + setIsAnyDragging, }: { - index: number; - position: THREE.Vector3; - onMove: (index: number, pos: THREE.Vector3) => void; - isAnyDragging: string; - setIsAnyDragging: (val: string) => void; + index: number; + position: THREE.Vector3; + onMove: (index: number, pos: THREE.Vector3) => void; + isAnyDragging: string; + setIsAnyDragging: (val: string) => void; }) { - const meshRef = useRef(null); - const { gl, controls, raycaster } = useThree(); - const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); - const { activeTool } = useActiveTool(); + const meshRef = useRef(null); + const { gl, controls, raycaster } = useThree(); + const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); + const { activeTool } = useActiveTool(); - const onPointerDown = (e: ThreeEvent) => { - e.stopPropagation() - if (activeTool !== 'pen') return; - setIsAnyDragging("point"); - gl.domElement.style.cursor = 'grabbing'; - if (controls) (controls as any).enabled = false; + const onPointerDown = (e: ThreeEvent) => { + e.stopPropagation(); + if (activeTool !== "pen") return; + setIsAnyDragging("point"); + gl.domElement.style.cursor = "grabbing"; + if (controls) (controls as any).enabled = false; + }; + + const onPointerMove = (e: ThreeEvent) => { + if (isAnyDragging !== "point" || activeTool !== "pen") return; + + const intersect = new THREE.Vector3(); + if (raycaster.ray.intersectPlane(plane, intersect)) { + meshRef.current!.position.copy(intersect); + onMove(index, intersect); + } + }; + + const onPointerUp = () => { + if (activeTool !== "pen") return; + setIsAnyDragging(""); + gl.domElement.style.cursor = "default"; + if (controls) (controls as any).enabled = true; + }; + useEffect(() => { + gl.domElement.addEventListener("pointerup", onPointerUp); + return () => { + gl.domElement.removeEventListener("pointerup", onPointerUp); }; + }, [activeTool]); - const onPointerMove = (e: ThreeEvent) => { - if (isAnyDragging !== "point" || activeTool !== 'pen') return; - - const intersect = new THREE.Vector3(); - if (raycaster.ray.intersectPlane(plane, intersect)) { - meshRef.current!.position.copy(intersect); - onMove(index, intersect); - } - }; - - const onPointerUp = () => { - if (activeTool !== 'pen') return; - setIsAnyDragging(""); - gl.domElement.style.cursor = 'default'; - if (controls) (controls as any).enabled = true; - }; - useEffect(() => { - gl.domElement.addEventListener("pointerup", onPointerUp); - return (() => { - gl.domElement.removeEventListener("pointerup", onPointerUp); - }) - }, [activeTool]) - - return ( - - - - - ); + return ( + + + + + ); } function DraggableLineSegment({ - index, - start, - end, - updatePoints, - isAnyDragging, - setIsAnyDragging, + index, + start, + end, + updatePoints, + isAnyDragging, + setIsAnyDragging, }: { - index: number; - start: THREE.Vector3; - end: THREE.Vector3; - updatePoints: (i0: number, p0: THREE.Vector3, i1: number, p1: THREE.Vector3) => void; - isAnyDragging: string; - setIsAnyDragging: (val: string) => void; + index: number; + start: THREE.Vector3; + end: THREE.Vector3; + updatePoints: ( + i0: number, + p0: THREE.Vector3, + i1: number, + p1: THREE.Vector3 + ) => void; + isAnyDragging: string; + setIsAnyDragging: (val: string) => void; }) { - const { gl, raycaster, controls } = useThree(); - const { activeTool } = useActiveTool(); - const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); - const dragStart = useRef(null); + const { gl, raycaster, controls } = useThree(); + const { activeTool } = useActiveTool(); + const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); + const dragStart = useRef(null); - const onPointerDown = () => { - if (activeTool !== 'pen' || isAnyDragging) return; - setIsAnyDragging("line"); - gl.domElement.style.cursor = 'grabbing'; - if (controls) (controls as any).enabled = false; + const onPointerDown = () => { + if (activeTool !== "pen" || isAnyDragging) return; + setIsAnyDragging("line"); + gl.domElement.style.cursor = "grabbing"; + if (controls) (controls as any).enabled = false; + }; + + const onPointerMove = (e: ThreeEvent) => { + if (isAnyDragging !== "line" || activeTool !== "pen") return; + + const intersect = new THREE.Vector3(); + if (raycaster.ray.intersectPlane(plane, intersect)) { + if (!dragStart.current) dragStart.current = intersect.clone(); + const offset = new THREE.Vector3().subVectors( + intersect, + dragStart.current + ); + const newStart = start.clone().add(offset); + const newEnd = end.clone().add(offset); + updatePoints(index, newStart, index + 1, newEnd); + } + }; + + const onPointerUp = () => { + if (activeTool !== "pen") return; + setIsAnyDragging(""); + dragStart.current = null; + gl.domElement.style.cursor = "default"; + if (controls) (controls as any).enabled = true; + }; + useEffect(() => { + gl.domElement.addEventListener("pointerup", onPointerUp); + return () => { + gl.domElement.removeEventListener("pointerup", onPointerUp); }; - - const onPointerMove = (e: ThreeEvent) => { - if (isAnyDragging !== "line" || activeTool !== 'pen') return; - - const intersect = new THREE.Vector3(); - if (raycaster.ray.intersectPlane(plane, intersect)) { - if (!dragStart.current) dragStart.current = intersect.clone(); - const offset = new THREE.Vector3().subVectors(intersect, dragStart.current); - const newStart = start.clone().add(offset); - const newEnd = end.clone().add(offset); - updatePoints(index, newStart, index + 1, newEnd); - } - }; - - const onPointerUp = () => { - if (activeTool !== 'pen') return; - setIsAnyDragging(""); - dragStart.current = null; - gl.domElement.style.cursor = 'default'; - if (controls) (controls as any).enabled = true; - }; - useEffect(() => { - gl.domElement.addEventListener("pointerup", onPointerUp); - return (() => { - gl.domElement.removeEventListener("pointerup", onPointerUp); - }) - }, [activeTool]) - return ( - - ); + }, [activeTool]); + return ( + + ); } diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance2.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance2.tsx new file mode 100644 index 0000000..5a1c85b --- /dev/null +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance2.tsx @@ -0,0 +1,253 @@ +import React, { useEffect, useMemo, useRef, useState } from "react"; +import { useCreatedPaths } from "../../../../../store/builder/store"; +import { useThree } from "@react-three/fiber"; +import { Vector3 } from "three"; +import { useSceneContext } from "../../../../scene/sceneContext"; +import { useProductContext } from "../../../products/productContext"; +import { useSelectedEventSphere } from "../../../../../store/simulation/useSimulationStore"; +function dist(a: PointData, b: PointData): number { + return Math.sqrt( + (a.position[0] - b.position[0]) ** 2 + + (a.position[1] - b.position[1]) ** 2 + + (a.position[2] - b.position[2]) ** 2 + ); +} +type SegmentPoint = { + position: Vector3; + originalPoint?: PointData; + pathId?: string; + startId?: string; + endId?: string; +}; + +/** --- A* Algorithm --- */ +type AStarResult = { + pointIds: string[]; + distance: number; +}; + +function aStarShortestPath( + startId: string, + goalId: string, + points: PointData[], + paths: PathData +): AStarResult | null { + const pointById = new Map(points.map((p) => [p.pointId, p])); + const start = pointById.get(startId); + const goal = pointById.get(goalId); + if (!start || !goal) return null; + + const openSet = new Set([startId]); + const cameFrom: Record = {}; + const gScore: Record = {}; + const fScore: Record = {}; + + for (const p of points) { + cameFrom[p.pointId] = null; + gScore[p.pointId] = Infinity; + fScore[p.pointId] = Infinity; + } + + gScore[startId] = 0; + fScore[startId] = dist(start, goal); + + const neighborsOf = (id: string): { id: string; cost: number }[] => { + const me = pointById.get(id)!; + const out: { id: string; cost: number }[] = []; + for (const edge of paths) { + const [a, b] = edge.pathPoints; + if (a.pointId === id) out.push({ id: b.pointId, cost: dist(me, b) }); + else if (b.pointId === id) out.push({ id: a.pointId, cost: dist(me, a) }); + } + return out; + }; + + while (openSet.size > 0) { + let current: string = [...openSet].reduce((a, b) => + fScore[a] < fScore[b] ? a : b + ); + + if (current === goalId) { + const ids: string[] = []; + let node: string | null = current; + while (node) { + ids.unshift(node); + node = cameFrom[node]; + } + return { pointIds: ids, distance: gScore[goalId] }; + } + + openSet.delete(current); + + for (const nb of neighborsOf(current)) { + const tentativeG = gScore[current] + nb.cost; + if (tentativeG < gScore[nb.id]) { + cameFrom[nb.id] = current; + gScore[nb.id] = tentativeG; + fScore[nb.id] = tentativeG + dist(pointById.get(nb.id)!, goal); + openSet.add(nb.id); + } + } + } + + return null; +} + +/** --- Convert node path to edges --- */ +function nodePathToEdges( + pointIds: string[], + points: PointData[], + paths: PathData +): PathData { + const byId = new Map(points.map((p) => [p.pointId, p])); + const edges: PathData = []; + + for (let i = 0; i < pointIds.length - 1; i++) { + const a = pointIds[i]; + const b = pointIds[i + 1]; + + const edge = paths.find( + (p) => + (p.pathPoints[0].pointId === a && p.pathPoints[1].pointId === b) || + (p.pathPoints[0].pointId === b && p.pathPoints[1].pointId === a) + ); + + if (edge) { + const [p1, p2] = edge.pathPoints; + edges.push({ + pathId: edge.pathId, + pathPoints: + p1.pointId === a + ? ([p1, p2] as [PointData, PointData]) + : ([p2, p1] as [PointData, PointData]), + }); + } else { + const pa = byId.get(a)!; + const pb = byId.get(b)!; + edges.push({ + pathId: `synthetic-${a}-${b}`, + pathPoints: [pa, pb], + }); + } + } + + return edges; +} +interface VehicleInstanceProps { + vehicleData: VehicleStructure; + vehiclesData: VehicleStructure[]; + setVehiclesData: React.Dispatch>; +} +export default function VehicleInstance2({ + vehicleData, + vehiclesData, + setVehiclesData, +}: VehicleInstanceProps) { + const { paths, setPaths } = useCreatedPaths(); + const { vehicleStore, productStore } = useSceneContext(); + const { vehicles, getVehicleById } = vehicleStore(); + const { selectedProductStore } = useProductContext(); + const { selectedProduct } = selectedProductStore(); + const { updateEvent, updateAction } = productStore(); + const { selectedEventSphere } = useSelectedEventSphere(); + + const { scene, gl, raycaster } = useThree(); + const [selected, setSelected] = useState([]); + const allPoints = useMemo(() => { + const points: PointData[] = []; + const seen = new Set(); + + paths?.forEach((path: PathDataInterface) => { + path.pathPoints.forEach((p) => { + if (!seen.has(p.pointId)) { + seen.add(p.pointId); + points.push(p); + } + }); + }); + return points; + }, [paths]); + const vehiclesDataRef = useRef(vehiclesData); + const selectedEventSphereRef = useRef(selectedEventSphere); + + useEffect(() => { + vehiclesDataRef.current = vehiclesData; + }, [vehiclesData]); + + useEffect(() => { + selectedEventSphereRef.current = selectedEventSphere; + }, [selectedEventSphere]); + + const handleContextMenu = (e: any) => { + const intersectObject = raycaster.intersectObjects(scene.children); + if (intersectObject.length > 0) { + const pathPoint = intersectObject[0].object; + if (pathPoint.name === "Path-Point") { + const point: any = pathPoint.userData; + + const pointIndex = allPoints.findIndex( + (p) => p.pointId === point.pointId + ); + if (pointIndex === -1) return; + + setSelected((prev: any) => { + if (prev.length === 0) { + return [pointIndex]; + } + + if (prev.length === 1) { + const prevPoint = allPoints[prev[0]]; + console.log("prevPoint: ", prevPoint); + const newPoint = allPoints[pointIndex]; + console.log("newPoint: ", newPoint); + + if (prevPoint.pointId === newPoint.pointId) return prev; + + const result = aStarShortestPath( + prevPoint.pointId, + newPoint.pointId, + allPoints, + paths + ); + + if (result) { + const edges = nodePathToEdges(result.pointIds, allPoints, paths); + + setTimeout(() => { + const modelUuid = selectedEventSphere?.userData?.modelUuid; + const index = vehiclesData.findIndex( + (v) => v.vehicleId === modelUuid + ); + + if (index !== -1) { + const updatedVehicles = [...vehiclesData]; + updatedVehicles[index] = { + ...updatedVehicles[index], + startPoint: prevPoint.position, + endPoint: newPoint.position, + route: edges, + }; + setVehiclesData(updatedVehicles); + } + }, 0); + } + + return [prev[0], pointIndex]; + } + + return [pointIndex]; + }); + } + } + }; + + useEffect(() => { + const canvasElement = gl.domElement; + canvasElement.addEventListener("contextmenu", handleContextMenu); + return () => { + canvasElement.removeEventListener("contextmenu", handleContextMenu); + }; + }, [raycaster]); + + return null; +} diff --git a/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx b/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx index 8f2b3f3..c9e8df6 100644 --- a/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx +++ b/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx @@ -1,24 +1,49 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import VehicleInstance from "./instance/vehicleInstance"; import VehicleContentUi from "../../ui3d/VehicleContentUi"; import { useSceneContext } from "../../../scene/sceneContext"; import { useViewSceneStore } from "../../../../store/builder/store"; +import PathCreator from "../pathCreator/pathCreator"; +import VehicleInstance2 from "./instance/vehicleInstance2"; function VehicleInstances() { - const { vehicleStore } = useSceneContext(); - const { vehicles } = vehicleStore(); - const { viewSceneLabels } = useViewSceneStore(); + const { vehicleStore } = useSceneContext(); + const { vehicles } = vehicleStore(); + const [vehiclesData, setVehiclesData] = useState([]); - return ( - <> - {vehicles.map((vehicle: VehicleStatus) => ( - - - {viewSceneLabels && } - - ))} - - ); + useEffect(() => { + const updatedVehicles = vehicles.map((val) => ({ + vehicleId: val.modelUuid, + position: val.position, + rotation: val.rotation, + startPoint: null, + endPoint: null, + selectedPointId: val.point.uuid, + })); + + console.log("updatedVehicles: ", updatedVehicles); + setVehiclesData(updatedVehicles); + }, [vehicles]); + + return ( + <> + {/* {vehicles.map((vehicle: VehicleStatus) => ( + + + {viewSceneLabels && } + + ))} */} + {vehiclesData.map((vehicle: VehicleStructure) => ( + + + + ))} + + ); } export default VehicleInstances; diff --git a/app/src/modules/simulation/vehicle/pathCreator/function/usePathManager.ts b/app/src/modules/simulation/vehicle/pathCreator/function/usePathManager.ts index 646e1e8..c35db5f 100644 --- a/app/src/modules/simulation/vehicle/pathCreator/function/usePathManager.ts +++ b/app/src/modules/simulation/vehicle/pathCreator/function/usePathManager.ts @@ -3,7 +3,7 @@ import { useCreatedPaths } from "../../../../../store/builder/store"; export const usePathManager = (pathId?: string, vehicleId?: string | null) => { const { paths, allPaths, setAllPaths } = useCreatedPaths(); - console.log("allPaths: ", allPaths); + useEffect(() => { if (!paths || paths.length === 0) return; diff --git a/app/src/modules/simulation/vehicle/pathCreator/pathCreator.tsx b/app/src/modules/simulation/vehicle/pathCreator/pathCreator.tsx index 7e7b64e..fc60b9c 100644 --- a/app/src/modules/simulation/vehicle/pathCreator/pathCreator.tsx +++ b/app/src/modules/simulation/vehicle/pathCreator/pathCreator.tsx @@ -35,11 +35,6 @@ interface PathDataInterface { type PathData = PathDataInterface[]; export default function PathCreator() { - // const [paths, setPaths] = useState([]); - // const [paths, setPaths] = useState(() => { - // const stored = localStorage.getItem("paths"); - // return stored ? JSON.parse(stored) : []; - // }); const { paths, setPaths } = useCreatedPaths(); const { activeTool } = useActiveTool(); const { toolMode } = useToolMode(); @@ -62,9 +57,9 @@ export default function PathCreator() { [] ); const plane = useMemo(() => new Plane(new Vector3(0, 1, 0), 0), []); - + const { scene, raycaster, gl } = useThree(); - + const POINT_SNAP_THRESHOLD = 0.5; const CAN_POINT_SNAP = true; @@ -80,8 +75,10 @@ export default function PathCreator() { ) ?? [] ); }, [paths, draftPoints]); + useEffect(() => { const stored = localStorage.getItem("paths"); + setPaths(stored ? JSON.parse(stored) : []); }, []); @@ -344,7 +341,7 @@ export default function PathCreator() { const allPoints = useMemo(() => { const points: PointData[] = []; const seen = new Set(); - console.log("paths: ", paths); + paths?.forEach((path: PathDataInterface) => { path.pathPoints.forEach((p) => { if (!seen.has(p.pointId)) { @@ -355,9 +352,9 @@ export default function PathCreator() { }); return points; }, [paths]); + useEffect(() => { - console.log("paths ", paths); localStorage.setItem("paths", JSON.stringify(paths)); }, [paths]); diff --git a/app/src/modules/simulation/vehicle/pathCreator/pointHandler.tsx b/app/src/modules/simulation/vehicle/pathCreator/pointHandler.tsx index 4ca9fba..da6e4fb 100644 --- a/app/src/modules/simulation/vehicle/pathCreator/pointHandler.tsx +++ b/app/src/modules/simulation/vehicle/pathCreator/pointHandler.tsx @@ -22,6 +22,8 @@ import { } from "../../../../store/usePlayButtonStore"; import { useSceneContext } from "../../../scene/sceneContext"; import { usePathManager } from "./function/usePathManager"; +import { useProductContext } from "../../products/productContext"; +import { useSelectedEventSphere } from "../../../../store/simulation/useSimulationStore"; type PointData = { pointId: string; position: [number, number, number]; @@ -202,6 +204,12 @@ export default function PointHandler({ const [multiPaths, setMultiPaths] = useState< { id: number; path: PathData }[] >([]); + const { vehicleStore, productStore } = useSceneContext(); + const { vehicles, getVehicleById } = vehicleStore(); + const { selectedProductStore } = useProductContext(); + const { selectedProduct } = selectedProductStore(); + const { updateEvent, updateAction } = productStore(); + const { selectedEventSphere } = useSelectedEventSphere(); const pathIdRef = useRef(1); // To ensure unique incremental IDs const { toolMode } = useToolMode(); const { activeTool } = useActiveTool(); @@ -230,19 +238,7 @@ export default function PointHandler({ const [vehicleData, setVehicleData] = useState([]); const { paths, setPaths } = useCreatedPaths(); const [managerData, setManagerData] = useState(); - // useEffect(() => { - // const findVehicle = assets - // .filter((val) => val.eventData?.type === "Vehicle") - // ?.map((val) => val.modelUuid); - // - // setVehicleUuids(findVehicle); - - // vehicleMovementState.current = {}; - // findVehicle.forEach((uuid) => { - // vehicleMovementState.current[uuid] = { index: 0, progress: 0 }; - // }); - // }, [assets]); useEffect(() => { const findVehicle = assets .filter((val) => val.eventData?.type === "Vehicle") @@ -417,87 +413,174 @@ export default function PointHandler({ removePathByPoint(point.pointId); return; } + }; + let selectedVehiclePaths: Array< + Array<{ + vehicleId: string; + pathId: string; + isActive?: boolean; + isCurved?: boolean; + pathPoints: [PointData, PointData]; + }> + > = []; - if (e.shiftKey) { - const pointIndex = points.findIndex((p) => p.pointId === point.pointId); - if (pointIndex === -1) { - return; + function assignPathToSelectedVehicle( + selectedVehicleId: string, + currentPath: PathData + ) { + const vehiclePathSegments = currentPath.map((path) => ({ + vehicleId: selectedVehicleId, + ...path, + })); + + return selectedVehiclePaths.push(vehiclePathSegments); + } + + const handleContextMenu = (e: any, point: PointData) => { + // if (e.shiftKey && e.button === 2) { + const pointIndex = points.findIndex((p) => p.pointId === point.pointId); + if (pointIndex === -1) { + return; + } + + setSelected((prev) => { + if (prev.length === 0) { + return [pointIndex]; } + // if (prev.length === 1) { + // setTimeout(() => { + // + // const prevPoint = points[prev[0]]; + // + // const newPoint = points[pointIndex]; + // + // const result = aStarShortestPath( + // prevPoint.pointId, + // newPoint.pointId, + // points, + // paths + // ); - setSelected((prev) => { - if (prev.length === 0) { - return [pointIndex]; - } - // if (prev.length === 1) { - // setTimeout(() => { - // - // const prevPoint = points[prev[0]]; - // - // const newPoint = points[pointIndex]; - // - // const result = aStarShortestPath( - // prevPoint.pointId, - // newPoint.pointId, - // points, - // paths - // ); + // if (result) { + // const edges = nodePathToEdges(result.pointIds, points, paths); + // + // setShortestPaths(edges); + // setShortestEdges(edges); + // } else { + // setShortestPaths([]); + // setShortestEdges([]); + // } + // if (prevPoint.pointId === newPoint.pointId) { + // return prev; + // } + // }, 0); - // if (result) { - // const edges = nodePathToEdges(result.pointIds, points, paths); - // - // setShortestPaths(edges); - // setShortestEdges(edges); - // } else { - // setShortestPaths([]); - // setShortestEdges([]); - // } - // if (prevPoint.pointId === newPoint.pointId) { - // return prev; - // } - // }, 0); + // return [prev[0], pointIndex]; + // } - // return [prev[0], pointIndex]; - // } - - // More than two points — reset - if (prev.length === 1) { - setTimeout(() => { - const prevPoint = points[prev[0]]; - const newPoint = points[pointIndex]; - - if (prevPoint.pointId === newPoint.pointId) return; - - const result = aStarShortestPath( - prevPoint.pointId, - newPoint.pointId, - points, - paths + // More than two points — reset + if (prev.length === 1) { + setTimeout(() => { + const prevPoint = points[prev[0]]; + const newPoint = points[pointIndex]; + console.log( + "selectedEventSphere?.userData.modelUuid: ", + selectedEventSphere?.userData.modelUuid + ); + if (selectedEventSphere?.userData.modelUuid) { + const updatedVehicle = getVehicleById( + selectedEventSphere.userData.modelUuid ); - if (result) { - const edges = nodePathToEdges(result.pointIds, points, paths); + const startPoint = new Vector3(...prevPoint.position); + const endPoint = new Vector3(...newPoint.position); + if (updatedVehicle && startPoint && endPoint) { + if (updatedVehicle.type === "vehicle") { + const event = updateAction( + selectedProduct.productUuid, + updatedVehicle.point?.action.actionUuid, + { + pickUpPoint: { + position: { + x: startPoint.x, + y: 0, + z: startPoint.z, + }, + rotation: { + x: + updatedVehicle.point.action.pickUpPoint?.rotation.x ?? + 0, + y: + updatedVehicle.point.action.pickUpPoint?.rotation.y ?? + 0, + z: + updatedVehicle.point.action.pickUpPoint?.rotation.z ?? + 0, + }, + }, + unLoadPoint: { + position: { + x: endPoint.x, + y: endPoint.y, + z: endPoint.z, + }, + rotation: { + x: + updatedVehicle.point.action.unLoadPoint?.rotation.x ?? + 0, + y: + updatedVehicle.point.action.unLoadPoint?.rotation.y ?? + 0, + z: + updatedVehicle.point.action.unLoadPoint?.rotation.z ?? + 0, + }, + }, + } + ); - // Create a new path object - const newPathObj = { - id: pathIdRef.current++, - path: edges, - }; - setShortestPaths(edges); - setShortestEdges(edges); - // Append it to the list of paths - setMultiPaths((prevPaths) => [...prevPaths, newPathObj]); + if (prevPoint.pointId === newPoint.pointId) return; + + const result = aStarShortestPath( + prevPoint.pointId, + newPoint.pointId, + points, + paths + ); + + if (result) { + const edges = nodePathToEdges(result.pointIds, points, paths); + + // Create a new path object/ + const newPathObj = { + id: pathIdRef.current++, + path: edges, + }; + const shortPath = assignPathToSelectedVehicle( + updatedVehicle?.modelUuid, + edges + ); + console.log("shortPath: ", shortPath); + + setShortestPaths(edges); + setShortestEdges(edges); + // Append it to the list of paths + setMultiPaths((prevPaths) => [...prevPaths, newPathObj]); + } + } } + } - // Reset selection to allow new pair selection - }, 0); + // Reset selection to allow new pair selection + }, 0); - return [prev[0], pointIndex]; - } + return [prev[0], pointIndex]; + } - setShortestPaths([]); - return [pointIndex]; - }); - } + setShortestPaths([]); + return [pointIndex]; + }); + // } }; const handleDragStart = (point: PointData) => { @@ -630,10 +713,8 @@ export default function PointHandler({ } return null; // not found } - - // + //works useFrame((_, delta) => { - // if (!isPlaying || pathSegments.length < 2 || vehicleData.length === 0) return; @@ -651,7 +732,6 @@ export default function PointHandler({ const pathStart = pathSegments[0].position; - // Step 1: Move vehicle to the start of the path if (!state.hasStarted) { const distanceToStart = object.position.distanceTo(pathStart); const step = speed * delta; @@ -659,11 +739,10 @@ export default function PointHandler({ if (distanceToStart <= step) { object.position.copy(pathStart); object.quaternion.identity(); - state.hasStarted = true; // start path animation next frame + state.hasStarted = true; return; } - // Move toward path start const direction = pathStart.clone().sub(object.position); const distance = direction.length(); @@ -671,21 +750,19 @@ export default function PointHandler({ direction.normalize(); object.position.add(direction.clone().multiplyScalar(step)); - // ROTATE toward direction of movement - const forward = new Vector3(0, 0, 1); // <-- adjust this based on your model + const forward = new Vector3(0, 0, 1); const targetQuat = new Quaternion().setFromUnitVectors( forward, direction ); - object.quaternion.slerp(targetQuat, 0.1); // smooth rotation + object.quaternion.slerp(targetQuat, 0.1); } else { - // Snap to start segment when close enough object.position.copy(pathStart); - object.quaternion.identity(); // reset orientation or leave as-is + object.quaternion.identity(); vehicleMovementState.current[uuid] = { index: 0, progress: 0 }; } - return; // still approaching start + return; } // Step 2: Follow the path @@ -707,14 +784,12 @@ export default function PointHandler({ state.index++; if (state.index >= pathSegments.length - 1) { - // Path complete state.index = 0; state.progress = 0; - state.hasStarted = false; // reset for next loop - object.position.copy(vehicleStartPos); // go back to start + state.hasStarted = false; + object.position.copy(vehicleStartPos); object.quaternion.identity(); - // Move to next vehicle setActiveVehicleIndex((prevIndex) => prevIndex + 1 >= vehicleData.length ? 0 : prevIndex + 1 ); @@ -737,6 +812,101 @@ export default function PointHandler({ object.quaternion.slerp(targetQuat, 0.1); }); + // useFrame((_, delta) => { + // if (!isPlaying || pathSegments.length < 2 || vehicleData.length === 0) + // return; + + // const vehicleStartPos = new Vector3(...agvDetail.position); + + // const object = scene.getObjectByProperty("uuid", agvDetail.modelUuid); + // if (!object) return; + + // const state = vehicleMovementState.current[agvDetail.modelUuid]; + // if (!state) return; + + // const moveSpeed = speed * delta; + + // const pathStart = pathSegments[0].position; + + // // ➤ Step 1: Move the object to the starting point of the path + // if (!state.hasStarted) { + // const distanceToStart = object.position.distanceTo(pathStart); + + // if (distanceToStart <= moveSpeed) { + // object.position.copy(pathStart); + // object.quaternion.identity(); + // state.hasStarted = true; + // state.index = 0; + // state.progress = 0; + // return; + // } + + // const direction = pathStart.clone().sub(object.position).normalize(); + // object.position.add(direction.clone().multiplyScalar(moveSpeed)); + + // const forward = new Vector3(0, 0, 1); + // const targetQuat = new Quaternion().setFromUnitVectors( + // forward, + // direction + // ); + // object.quaternion.slerp(targetQuat, 0.1); + + // return; + // } + + // // ➤ Step 2: Traverse path segments + // const startSeg = pathSegments[state.index]; + // const endSeg = pathSegments[state.index + 1]; + // if (!startSeg || !endSeg) return; + + // const currentPathId = getPathIdByPoints( + // startSeg.startId || startSeg.endId, + // endSeg.endId || endSeg.startId, + // shortestPaths + // ); + + // setManagerData({ pathId: currentPathId, vehicleId: agvDetail.modelUuid }); + + // const segmentDistance = startSeg.position.distanceTo(endSeg.position); + // state.progress += moveSpeed / segmentDistance; + + // // ➤ Step 3: If we've finished this segment, move to the next + // while (state.progress >= 1) { + // state.progress -= 1; + // state.index++; + + // if (state.index >= pathSegments.length - 1) { + // // Path completed + // state.index = 0; + // state.progress = 0; + // state.hasStarted = false; + + // object.position.copy(vehicleStartPos); + // object.quaternion.identity(); + + // setActiveVehicleIndex((prevIndex) => + // prevIndex + 1 >= vehicleData.length ? 0 : prevIndex + 1 + // ); + + // return; + // } + // } + + // // ➤ Step 4: Interpolate position and rotate + // const newPos = startSeg.position + // .clone() + // .lerp(endSeg.position, state.progress); + // object.position.copy(newPos); + + // const direction = endSeg.position + // .clone() + // .sub(startSeg.position) + // .normalize(); + // const forward = new Vector3(0, 0, 1); + // const targetQuat = new Quaternion().setFromUnitVectors(forward, direction); + // object.quaternion.slerp(targetQuat, 0.1); + // }); + // useFrame((_, delta) => { // if (!isPlaying || pathSegments.length < 2 || vehicleData.length === 0) // return; @@ -792,12 +962,12 @@ export default function PointHandler({ // object.quaternion.slerp(targetQuat, 0.1); // }); - useEffect(() => {}, [multiPaths]); + const manager = usePathManager(managerData?.pathId, managerData?.vehicleId); useEffect(() => { // if (managerData) { - // console.log("manager: ", manager); + // // } }, [managerData]); return ( @@ -817,6 +987,7 @@ export default function PointHandler({ onClick={(e) => { handlePointClick(e, point); }} + // onContextMenu={(e) => handleContextMenu(e, point)} onPointerOver={(e) => { if (!hoveredPoint && e.buttons === 0 && !e.ctrlKey) { setHoveredPoint(point); diff --git a/app/src/store/builder/store.ts b/app/src/store/builder/store.ts index bcbe317..973a65d 100644 --- a/app/src/store/builder/store.ts +++ b/app/src/store/builder/store.ts @@ -664,8 +664,71 @@ interface allPaths { type PathData = PathDataInterface[]; export const useCreatedPaths = create((set: any) => ({ - paths: [], + paths: [ + { + pathId: "276724c5-05a3-4b5e-a127-a60b3533ccce", + pathPoints: [ + { + pointId: "19c3f429-f214-4f87-8906-7eaaedd925da", + position: [2.33155763270131, 0, -20.538859668988927], + }, + { + pointId: "ea73c7c8-0e26-4aae-9ed8-2349ff2d6718", + position: [17.13371069714903, 0, -22.156135485080462], + }, + ], + }, + { + pathId: "2736b20b-a433-443c-a5c9-5ba4348ac682", + pathPoints: [ + { + pointId: "ea73c7c8-0e26-4aae-9ed8-2349ff2d6718", + position: [17.13371069714903, 0, -22.156135485080462], + }, + { + pointId: "2212bb52-c63c-4289-8b50-5ffd229d13e5", + position: [16.29236816120279, 0, -10.819973445497789], + }, + ], + }, + { + pathId: "3144a2df-7aad-483d-bbc7-de7f7b5b3bfc", + pathPoints: [ + { + pointId: "2212bb52-c63c-4289-8b50-5ffd229d13e5", + position: [16.29236816120279, 0, -10.819973445497789], + }, + { + pointId: "adfd05a7-4e16-403f-81d0-ce99f2e34f5f", + position: [4.677047323894161, 0, -8.279486846767094], + }, + ], + }, + { + pathId: "e0a1b5da-27c2-44a0-81db-759b5a5eb416", + pathPoints: [ + { + pointId: "adfd05a7-4e16-403f-81d0-ce99f2e34f5f", + position: [4.677047323894161, 0, -8.279486846767094], + }, + { + pointId: "19c3f429-f214-4f87-8906-7eaaedd925da", + position: [2.33155763270131, 0, -20.538859668988927], + }, + ], + }, + ], setPaths: (x: PathData) => set({ paths: x }), allPaths: [], setAllPaths: (x: allPaths) => set({ allPaths: x }), })); + +// route?: { +// pathId: string; +// pathPoints: { +// pointId: string; +// position: [number, number, number]; +// isCurved?: boolean; +// handleA?: [number, number, number] | null; +// handleB: [number, number, number] | null; + // }[]; \ No newline at end of file