diff --git a/app/src/components/ui/Tools.tsx b/app/src/components/ui/Tools.tsx index 71ebfe3..02a6d82 100644 --- a/app/src/components/ui/Tools.tsx +++ b/app/src/components/ui/Tools.tsx @@ -32,7 +32,10 @@ import { useTransformMode, } from "../../store/store"; import useToggleStore from "../../store/useUIToggleStore"; -import { use3DWidget, useFloatingWidget } from "../../store/useDroppedObjectsStore"; +import { + use3DWidget, + useFloatingWidget, +} from "../../store/useDroppedObjectsStore"; const Tools: React.FC = () => { const { templates } = useTemplateStore(); @@ -47,8 +50,8 @@ const Tools: React.FC = () => { const { isPlaying, setIsPlaying } = usePlayButtonStore(); const { addTemplate } = useTemplateStore(); const { selectedZone } = useSelectedZoneStore(); - const { floatingWidget } = useFloatingWidget() - const { widgets3D } = use3DWidget() + const { floatingWidget } = useFloatingWidget(); + const { widgets3D } = use3DWidget(); // wall options const { toggleView, setToggleView } = useToggleView(); @@ -71,7 +74,7 @@ const Tools: React.FC = () => { : true ); }, []); - useEffect(() => { }, [activeModule]); + useEffect(() => {}, [activeModule]); useEffect(() => { setActiveTool(activeSubTool); setActiveSubTool(activeSubTool); @@ -213,8 +216,9 @@ const Tools: React.FC = () => {
{activeSubTool == "cursor" && (
{ setActiveTool("cursor"); }} @@ -224,8 +228,9 @@ const Tools: React.FC = () => { )} {activeSubTool == "free-hand" && (
{ setActiveTool("free-hand"); }} @@ -235,8 +240,9 @@ const Tools: React.FC = () => { )} {activeSubTool == "delete" && (
{ setActiveTool("delete"); }} @@ -308,8 +314,9 @@ const Tools: React.FC = () => {
{ setActiveTool("draw-wall"); }} @@ -318,8 +325,9 @@ const Tools: React.FC = () => {
{ setActiveTool("draw-zone"); }} @@ -328,8 +336,9 @@ const Tools: React.FC = () => {
{ setActiveTool("draw-aisle"); }} @@ -338,8 +347,9 @@ const Tools: React.FC = () => {
{ setActiveTool("draw-floor"); }} @@ -355,8 +365,9 @@ const Tools: React.FC = () => {
{ setActiveTool("measure"); }} @@ -372,8 +383,9 @@ const Tools: React.FC = () => {
{ setActiveTool("pen"); }} @@ -390,16 +402,14 @@ const Tools: React.FC = () => {
{ - handleSaveTemplate({ addTemplate, floatingWidget, widgets3D, selectedZone, templates, - }) - } - } + }); + }} >
@@ -409,8 +419,9 @@ const Tools: React.FC = () => {
{ setActiveTool("comment"); }} @@ -419,10 +430,12 @@ const Tools: React.FC = () => {
{toggleThreeD && (
{ setIsPlaying(!isPlaying); + setActiveTool("play"); }} > @@ -433,14 +446,19 @@ const Tools: React.FC = () => { <>
-
+
2d
-
+
3d
diff --git a/app/src/modules/builder/agv/agv.tsx b/app/src/modules/builder/agv/agv.tsx index 37c4f4e..ace2e3e 100644 --- a/app/src/modules/builder/agv/agv.tsx +++ b/app/src/modules/builder/agv/agv.tsx @@ -5,22 +5,83 @@ import * as THREE from "three"; import * as Types from "../../../types/world/worldTypes"; import PathNavigator from "./pathNavigator"; import NavMeshDetails from "./navMeshDetails"; +import { + useSelectedActionSphere, + useSimulationPaths, +} from "../../../store/store"; -const Agv = ({ lines, plane }: { lines: Types.RefLines; plane: Types.RefMesh; }) => { - const pathPoints = useMemo(() => [ - [ - { x: 8.477161935339709, y: 0, z: 17.41343083550102 }, - { x: 9.175416491482693, y: 0, z: -12.361001232663693 }, - ], - // [ - // { x: 13.508213355232144, y: 0, z: -15.456970649652018 }, - // { x: -30.464866520869617, y: 0, z: 9.779806557688929 }, - // ], - [ - { x: 16.792040856420844, y: 0, z: 15.86281907549489 }, - { x: -42.77173264503395, y: 0, z: -15.821322764400804 }, - ], - ], []); +const Agv = ({ + lines, + plane, +}: { + lines: Types.RefLines; + plane: Types.RefMesh; +}) => { + const [pathPoints, setPathPoints] = useState< + { + uuid: string; + points: { x: number; y: number; z: number }[]; + }[] + >([]); + const { simulationPaths } = useSimulationPaths(); + const { selectedActionSphere } = useSelectedActionSphere(); + useEffect(() => { + if (!Array.isArray(simulationPaths)) { + } else { + let agvModels = simulationPaths.filter( + (val: any) => val.modelName === "agv" + ); + + let findMesh = agvModels.filter( + (val: any) => + val.modeluuid === selectedActionSphere?.path?.modeluuid && + val.type === "Vehicle" + ); + + const result = + findMesh.length > 0 && + findMesh[0].type === "Vehicle" && + typeof findMesh[0].point?.actions.start === "object" && + typeof findMesh[0].point?.actions.end === "object" && + "x" in findMesh[0].point.actions.start && + "y" in findMesh[0].point.actions.start && + "x" in findMesh[0].point.actions.end && + "y" in findMesh[0].point.actions.end + ? [ + { + uuid: findMesh[0].modeluuid, // Ensure it's a number + + points: [ + { + x: findMesh[0].position[0], + y: findMesh[0].position[1], + z: findMesh[0].position[2], + }, + { + x: findMesh[0].point.actions.start.x, + y: 0, + z: findMesh[0].point.actions.start.y, + }, + { + x: findMesh[0].point.actions.end.x, + y: 0, + z: findMesh[0].point.actions.end.y, + }, + ], + }, + ] + : []; + if (result.length > 0) { + setPathPoints((prev) => { + const existingUUIDs = new Set(prev.map((item) => item.uuid)); + const newItems = result.filter( + (item) => !existingUUIDs.has(item.uuid) + ); + return [...prev, ...newItems]; + }); + } + } + }, [simulationPaths, selectedActionSphere]); let groupRef = useRef() as Types.RefGroup; const [navMesh, setNavMesh] = useState(); @@ -35,7 +96,12 @@ const Agv = ({ lines, plane }: { lines: Types.RefLines; plane: Types.RefMesh; }) plane={plane} /> {pathPoints.map((pair, i) => ( - + ))} diff --git a/app/src/modules/builder/agv/navMeshDetails.tsx b/app/src/modules/builder/agv/navMeshDetails.tsx index 571be5a..ecb539b 100644 --- a/app/src/modules/builder/agv/navMeshDetails.tsx +++ b/app/src/modules/builder/agv/navMeshDetails.tsx @@ -35,10 +35,14 @@ export default function NavMeshDetails({ const [positions, indices] = getPositionsAndIndices(meshes); const cs = 0.25; - const ch = 0.5; + const ch = 0.69; const walkableRadius = 0.5; - const { success, navMesh } = generateSoloNavMesh(positions, indices, { cs, ch, walkableRadius: Math.round(walkableRadius / ch), }); + const { success, navMesh } = generateSoloNavMesh(positions, indices, { + cs, + ch, + walkableRadius: Math.round(walkableRadius / ch), + }); if (!success || !navMesh) { return; @@ -49,7 +53,7 @@ export default function NavMeshDetails({ const debugDrawer = new DebugDrawer(); debugDrawer.drawNavMesh(navMesh); // scene.add(debugDrawer); - } catch (error) { } + } catch (error) {} }; initializeNavigation(); diff --git a/app/src/modules/builder/agv/pathNavigator.tsx b/app/src/modules/builder/agv/pathNavigator.tsx index 25d3af0..9da0d59 100644 --- a/app/src/modules/builder/agv/pathNavigator.tsx +++ b/app/src/modules/builder/agv/pathNavigator.tsx @@ -1,98 +1,149 @@ import React, { useEffect, useState, useRef } from "react"; import * as THREE from "three"; -import { useFrame } from "@react-three/fiber"; +import { useFrame, useThree } from "@react-three/fiber"; import { NavMeshQuery } from "@recast-navigation/core"; import { Line } from "@react-three/drei"; +import { useTh } from "leva/dist/declarations/src/styles"; +import { useActiveTool } from "../../../store/store"; // Define interface for props interface PathNavigatorProps { navMesh: any; selectedPoints: any; + id: string; } export default function PathNavigator({ navMesh, selectedPoints, + id, }: PathNavigatorProps) { const [path, setPath] = useState<[number, number, number][]>([]); const progressRef = useRef(0); + const distancesRef = useRef([]); + const totalDistanceRef = useRef(0); + const currentSegmentIndex = useRef(0); + const { scene } = useThree(); + const { activeTool } = useActiveTool(); + const [startPoint, setStartPoint] = useState(new THREE.Vector3()); const meshRef = useRef(null); - useEffect(() => { - if (selectedPoints.length === 2 && navMesh) { - const [start, end] = selectedPoints; - if (!start || !end) return; + if (!scene || !id || path.length < 2) return; - const navMeshQuery = new NavMeshQuery(navMesh); - - const { path: computedPath } = navMeshQuery.computePath(start, end); - - if (computedPath.length > 0) { - setPath(computedPath.map(({ x, y, z }) => [x, y + 0.1, z])); - progressRef.current = 0; - } + let totalDistance = 0; + const distances: number[] = []; + for (let i = 0; i < path.length - 1; i++) { + const start = new THREE.Vector3(...path[i]); + const end = new THREE.Vector3(...path[i + 1]); + const segmentDistance = start.distanceTo(end); + distances.push(segmentDistance); + totalDistance += segmentDistance; } - }, [selectedPoints, navMesh]); + + distancesRef.current = distances; + totalDistanceRef.current = totalDistance; + progressRef.current = 0; // Reset progress when the path changes + }, [path]); + useEffect(() => { + if (!navMesh || selectedPoints.length === 0) return; + + // Flatten the selectedPoints array into a single list of points + const allPoints = selectedPoints.flat(); + + // Compute paths between consecutive points + const computedPath: [number, number, number][] = []; + for (let i = 0; i < allPoints.length - 1; i++) { + const start = allPoints[i]; + setStartPoint( + new THREE.Vector3(allPoints[0].x, allPoints[0].y, allPoints[0].z) + ); + + const end = allPoints[i + 1]; + + try { + const navMeshQuery = new NavMeshQuery(navMesh); + const { path: segmentPath } = navMeshQuery.computePath(start, end); + + if (segmentPath && segmentPath.length > 0) { + computedPath.push( + ...segmentPath.map(({ x, y, z }): [number, number, number] => [ + x, + y + 0.1, + z, + ]) + ); + } + } catch (error) {} + } + + // Set the full computed path + + if (computedPath.length > 0) { + setPath(computedPath); + currentSegmentIndex.current = 0; // Reset to the first segment + } + }, [selectedPoints, navMesh, path]); useFrame((_, delta) => { - if (path.length > 1 && meshRef.current) { - const speed = 3; - progressRef.current += delta * speed; + if (!scene || !id || path.length < 2) return; - let totalDistance = 0; - const distances: number[] = []; - for (let i = 0; i < path.length - 1; i++) { - const start = new THREE.Vector3(...path[i]); - const end = new THREE.Vector3(...path[i + 1]); - const segmentDistance = start.distanceTo(end); - distances.push(segmentDistance); - totalDistance += segmentDistance; - } + // Find the object in the scene + const findObject = scene.getObjectByProperty("uuid", id); + if (activeTool === "play") { + if (!findObject) return; + + const speed = 5; + progressRef.current += delta * speed; let coveredDistance = progressRef.current; let accumulatedDistance = 0; let index = 0; + // Determine the current segment of the path while ( - index < distances.length && - coveredDistance > accumulatedDistance + distances[index] + index < distancesRef.current.length && + coveredDistance > accumulatedDistance + distancesRef.current[index] ) { - accumulatedDistance += distances[index]; + accumulatedDistance += distancesRef.current[index]; index++; } - if (index < distances.length) { - const start = new THREE.Vector3(...path[index]); - const end = new THREE.Vector3(...path[index + 1]); - const segmentDistance = distances[index]; - - const t = (coveredDistance - accumulatedDistance) / segmentDistance; - const position = start.clone().lerp(end, t); // Use clone() to avoid mutating the original vector - meshRef.current.position.copy(position); - - const direction = new THREE.Vector3() - .subVectors(end, start) - .normalize(); - const targetQuaternion = new THREE.Quaternion().setFromUnitVectors( - new THREE.Vector3(0, 0, 1), - direction - ); - meshRef.current.quaternion.slerp(targetQuaternion, 0.1); - } else { - progressRef.current = totalDistance; + // If the object has reached the end of the path, stop moving + if (index >= distancesRef.current.length) { + progressRef.current = totalDistanceRef.current; + return; } + + // Interpolate position within the current segment + const start = new THREE.Vector3(...path[index]); + const end = new THREE.Vector3(...path[index + 1]); + const segmentDistance = distancesRef.current[index]; + + const t = (coveredDistance - accumulatedDistance) / segmentDistance; + const position = start.clone().lerp(end, t); + findObject.position.copy(position); + + // Rotate the object to face the direction of movement + const direction = new THREE.Vector3().subVectors(end, start).normalize(); + const targetQuaternion = new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, 0, 1), // Assuming forward direction is (0, 0, 1) + direction + ); + findObject.quaternion.slerp(targetQuaternion, 0.1); // Smoothly interpolate rotation + } else if (activeTool === "cursor") { + findObject?.position.copy(startPoint); } }); return ( <> - {/* {path.length > 0 && } */} - {path.length > 0 && ( + {path.length > 0 && } + {/* {path.length > 0 && ( 0 ? path[0] : [0, 0.1, 0]}> - )} + )} */} ); } diff --git a/app/src/modules/scene/world/world.tsx b/app/src/modules/scene/world/world.tsx index 76cf539..7fe2979 100644 --- a/app/src/modules/scene/world/world.tsx +++ b/app/src/modules/scene/world/world.tsx @@ -52,6 +52,7 @@ import Layer2DVisibility from "../../builder/geomentries/layers/layer2DVisibilit import DrieHtmlTemp from "../mqttTemp/drieHtmlTemp"; import ZoneGroup from "../../builder/groups/zoneGroup"; import Agv from "../../builder/agv/agv"; +import useModuleStore from "../../../store/useModuleStore"; export default function World() { const state = useThree(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements. @@ -120,6 +121,7 @@ export default function World() { const { updateScene, setUpdateScene } = useUpdateScene(); const { walls, setWalls } = useWalls(); const { refTextupdate, setRefTextUpdate } = useRefTextUpdate(); + const { activeModule } = useModuleStore(); // const loader = new GLTFLoader(); // const dracoLoader = new DRACOLoader(); @@ -359,8 +361,7 @@ export default function World() { /> {/* */} - - + {activeModule === "simulation" && } ); } diff --git a/app/src/modules/simulation/path/pathCreation.tsx b/app/src/modules/simulation/path/pathCreation.tsx index 84c3b78..7af4afd 100644 --- a/app/src/modules/simulation/path/pathCreation.tsx +++ b/app/src/modules/simulation/path/pathCreation.tsx @@ -1,299 +1,362 @@ -import * as THREE from 'three'; -import * as Types from '../../../types/world/worldTypes'; -import { useRef, useState, useEffect, useMemo } from 'react'; -import { Sphere, TransformControls } from '@react-three/drei'; -import { useEditingPoint, useEyeDropMode, useIsConnecting, usePreviewPosition, useRenderDistance, useSelectedActionSphere, useSelectedPath, useSimulationPaths } from '../../../store/store'; -import { useFrame, useThree } from '@react-three/fiber'; -import { useSubModuleStore } from '../../../store/useModuleStore'; +import * as THREE from "three"; +import * as Types from "../../../types/world/worldTypes"; +import { useRef, useState, useEffect, useMemo } from "react"; +import { Sphere, TransformControls } from "@react-three/drei"; +import { + useEditingPoint, + useEyeDropMode, + useIsConnecting, + usePreviewPosition, + useRenderDistance, + useSelectedActionSphere, + useSelectedPath, + useSimulationPaths, +} from "../../../store/store"; +import { useFrame, useThree } from "@react-three/fiber"; +import { useSubModuleStore } from "../../../store/useModuleStore"; -function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject }) { - const { renderDistance } = useRenderDistance(); - const { setSubModule } = useSubModuleStore(); - const { setSelectedActionSphere, selectedActionSphere } = useSelectedActionSphere(); - const { eyeDropMode, setEyeDropMode } = useEyeDropMode(); - const { editingPoint, setEditingPoint } = useEditingPoint(); - const { previewPosition, setPreviewPosition } = usePreviewPosition(); - const { raycaster, camera, pointer, gl } = useThree(); - const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); - const { setSelectedPath } = useSelectedPath(); - const { simulationPaths, setSimulationPaths } = useSimulationPaths(); - const { isConnecting } = useIsConnecting(); - - const groupRefs = useRef<{ [key: string]: THREE.Group }>({}); - const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); - const isMovingRef = useRef(false); - const transformRef = useRef(null); - const [transformMode, setTransformMode] = useState<'translate' | 'rotate' | null>(null); +function PathCreation({ + pathsGroupRef, +}: { + pathsGroupRef: React.MutableRefObject; +}) { + const { renderDistance } = useRenderDistance(); + const { setSubModule } = useSubModuleStore(); + const { setSelectedActionSphere, selectedActionSphere } = + useSelectedActionSphere(); + const { eyeDropMode, setEyeDropMode } = useEyeDropMode(); + const { editingPoint, setEditingPoint } = useEditingPoint(); + const { previewPosition, setPreviewPosition } = usePreviewPosition(); + const { raycaster, camera, pointer, gl } = useThree(); + const plane = useMemo( + () => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), + [] + ); + const { setSelectedPath } = useSelectedPath(); + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); + const { isConnecting } = useIsConnecting(); - useEffect(() => { - setTransformMode(null); - const handleKeyDown = (e: KeyboardEvent) => { - if (!selectedActionSphere) return; - if (e.key === 'g') { - setTransformMode(prev => prev === 'translate' ? null : 'translate'); - } - if (e.key === 'r') { - setTransformMode(prev => prev === 'rotate' ? null : 'rotate'); - } - }; + const groupRefs = useRef<{ [key: string]: THREE.Group }>({}); + const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); + const isMovingRef = useRef(false); + const transformRef = useRef(null); + const [transformMode, setTransformMode] = useState< + "translate" | "rotate" | null + >(null); - window.addEventListener('keydown', handleKeyDown); - return () => window.removeEventListener('keydown', handleKeyDown); - }, [selectedActionSphere]); - - useFrame(() => { - Object.values(groupRefs.current).forEach(group => { - if (group) { - const distance = new THREE.Vector3(...group.position.toArray()).distanceTo(camera.position); - group.visible = distance <= renderDistance; - } - }); - }); - - const updateSimulationPaths = () => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => { - if (path.type === "Conveyor") { - return { - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - position: [ - selectedActionSphere.point.position.x, - selectedActionSphere.point.position.y, - selectedActionSphere.point.position.z, - ], - rotation: [ - selectedActionSphere.point.rotation.x, - selectedActionSphere.point.rotation.y, - selectedActionSphere.point.rotation.z, - ] - } - : point - ), - }; - } - return path; - }) as Types.ConveyorEventsSchema[]; - - setSimulationPaths(updatedPaths); + useEffect(() => { + setTransformMode(null); + const handleKeyDown = (e: KeyboardEvent) => { + if (!selectedActionSphere) return; + if (e.key === "g") { + setTransformMode((prev) => (prev === "translate" ? null : "translate")); + } + if (e.key === "r") { + setTransformMode((prev) => (prev === "rotate" ? null : "rotate")); + } }; - useFrame(() => { - if (eyeDropMode) { - raycaster.setFromCamera(pointer, camera); - const intersectionPoint = new THREE.Vector3(); - const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [selectedActionSphere]); - if (point) { - setPreviewPosition({ x: point.x, y: point.z }); - } - } else { - setPreviewPosition(null); + useFrame(() => { + Object.values(groupRefs.current).forEach((group) => { + if (group) { + const distance = new THREE.Vector3( + ...group.position.toArray() + ).distanceTo(camera.position); + group.visible = distance <= renderDistance; + } + }); + }); + + const updateSimulationPaths = () => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => { + if (path.type === "Conveyor") { + return { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + position: [ + selectedActionSphere.point.position.x, + selectedActionSphere.point.position.y, + selectedActionSphere.point.position.z, + ], + rotation: [ + selectedActionSphere.point.rotation.x, + selectedActionSphere.point.rotation.y, + selectedActionSphere.point.rotation.z, + ], + } + : point + ), + }; + } + return path; + }) as Types.ConveyorEventsSchema[]; + + setSimulationPaths(updatedPaths); + }; + + useFrame(() => { + if (eyeDropMode) { + raycaster.setFromCamera(pointer, camera); + const intersectionPoint = new THREE.Vector3(); + const point = raycaster.ray.intersectPlane(plane, intersectionPoint); + + if (point) { + setPreviewPosition({ x: point.x, y: point.z }); + } + } else { + setPreviewPosition(null); + } + }); + + useEffect(() => { + if (!camera) return; + const canvasElement = gl.domElement; + canvasElement.tabIndex = 0; + + const onPointerDown = () => { + isMovingRef.current = false; + }; + + const onPointerMove = () => { + isMovingRef.current = true; + }; + + const onPointerUp = (event: PointerEvent) => { + if ( + !isMovingRef.current && + eyeDropMode && + event.button === 0 && + previewPosition + ) { + event.preventDefault(); + if (editingPoint) { + handlePointUpdate(editingPoint, previewPosition.x, previewPosition.y); + setEditingPoint(null); + setEyeDropMode(false); } + } + }; + + if (eyeDropMode) { + canvasElement.addEventListener("pointerdown", onPointerDown); + canvasElement.addEventListener("pointermove", onPointerMove); + canvasElement.addEventListener("pointerup", onPointerUp); + } + + return () => { + canvasElement.removeEventListener("pointerdown", onPointerDown); + canvasElement.removeEventListener("pointermove", onPointerMove); + canvasElement.removeEventListener("pointerup", onPointerUp); + }; + }, [eyeDropMode, editingPoint, previewPosition]); + + const handlePointUpdate = ( + pointType: "start" | "end", + x: number, + z: number + ) => { + if (!selectedActionSphere?.point?.uuid) return; + + const updatedPaths = simulationPaths.map((path) => { + if ( + path.type === "Vehicle" && + path.point.uuid === selectedActionSphere.point.uuid + ) { + return { + ...path, + point: { + ...path.point, + actions: { + ...path.point.actions, + [pointType]: { + ...path.point.actions[pointType], + x: x, + y: z, + }, + }, + }, + }; + } + return path; }); - useEffect(() => { - if (!camera) return; - const canvasElement = gl.domElement; - canvasElement.tabIndex = 0; + setSimulationPaths(updatedPaths); + }; + return ( + + {simulationPaths.map((path) => { + if (path.type === "Conveyor") { + const points = path.points.map( + (point) => new THREE.Vector3(...point.position) + ); - const onPointerDown = () => { - isMovingRef.current = false; - }; - - const onPointerMove = () => { - isMovingRef.current = true; - }; - - const onPointerUp = (event: PointerEvent) => { - if (!isMovingRef.current && eyeDropMode && event.button === 0 && previewPosition) { - event.preventDefault(); - if (editingPoint) { - handlePointUpdate(editingPoint, previewPosition.x, previewPosition.y); - setEditingPoint(null); - setEyeDropMode(false); - } - } - }; - - if (eyeDropMode) { - canvasElement.addEventListener("pointerdown", onPointerDown); - canvasElement.addEventListener("pointermove", onPointerMove); - canvasElement.addEventListener("pointerup", onPointerUp); - } - - return () => { - canvasElement.removeEventListener("pointerdown", onPointerDown); - canvasElement.removeEventListener("pointermove", onPointerMove); - canvasElement.removeEventListener("pointerup", onPointerUp); - }; - }, [eyeDropMode, editingPoint, previewPosition]); - - const handlePointUpdate = (pointType: 'start' | 'end', x: number, z: number) => { - if (!selectedActionSphere?.point?.uuid) return; - - const updatedPaths = simulationPaths.map((path) => { - if (path.type === "Vehicle" && path.point.uuid === selectedActionSphere.point.uuid) { - return { - ...path, - point: { - ...path.point, - actions: { - ...path.point.actions, - [pointType]: { - ...path.point.actions[pointType], - x: x, - y: z - } - } + return ( + (groupRefs.current[path.modeluuid] = el!)} + position={path.position} + rotation={path.rotation} + onClick={(e) => { + if (isConnecting || eyeDropMode) return; + e.stopPropagation(); + setSelectedPath({ + path, + group: groupRefs.current[path.modeluuid], + }); + setSelectedActionSphere(null); + setTransformMode(null); + setSubModule("mechanics"); + }} + onPointerMissed={() => { + if (eyeDropMode) return; + setSelectedPath(null); + setSubModule("properties"); + }} + > + {path.points.map((point, index) => ( + (sphereRefs.current[point.uuid] = el!)} + onClick={(e) => { + if (isConnecting || eyeDropMode) return; + e.stopPropagation(); + setSelectedActionSphere({ + path, + point: sphereRefs.current[point.uuid], + }); + setSubModule("mechanics"); + setSelectedPath(null); + }} + userData={{ point, path }} + onPointerMissed={() => { + if (eyeDropMode) return; + setSubModule("properties"); + setSelectedActionSphere(null); + }} + > + + + ))} - setSimulationPaths(updatedPaths); - }; + {points.slice(0, -1).map((point, index) => { + const nextPoint = points[index + 1]; + const segmentCurve = new THREE.CatmullRomCurve3([ + point, + nextPoint, + ]); + const tubeGeometry = new THREE.TubeGeometry( + segmentCurve, + 20, + 0.1, + 16, + false + ); - return ( - - {simulationPaths.map((path) => { - if (path.type === 'Conveyor') { - const points = path.points.map(point => new THREE.Vector3(...point.position)); + return ( + + + + ); + })} + + ); + } else if (path.type === "Vehicle") { + return ( + (groupRefs.current[path.modeluuid] = el!)} + position={path.position} + onClick={(e) => { + if (isConnecting || eyeDropMode) return; + e.stopPropagation(); + setSelectedPath({ + path, + group: groupRefs.current[path.modeluuid], + }); + setSelectedActionSphere(null); + setTransformMode(null); + setSubModule("mechanics"); + }} + onPointerMissed={() => { + if (eyeDropMode) return; + setSelectedPath(null); + setSubModule("properties"); + }} + > + (sphereRefs.current[path.point.uuid] = el!)} + onClick={(e) => { + if (isConnecting || eyeDropMode) return; + e.stopPropagation(); + setSelectedActionSphere({ + path, + point: sphereRefs.current[path.point.uuid], + }); + setSubModule("mechanics"); + setSelectedPath(null); + }} + userData={{ point: path.point, path }} + onPointerMissed={() => { + if (eyeDropMode) return; + setSubModule("properties"); + setSelectedActionSphere(null); + }} + > + + + + ); + } + return null; + })} - return ( - (groupRefs.current[path.modeluuid] = el!)} - position={path.position} - rotation={path.rotation} - onClick={(e) => { - if (isConnecting || eyeDropMode) return; - e.stopPropagation(); - setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); - setSelectedActionSphere(null); - setTransformMode(null); - setSubModule('mechanics'); - }} - onPointerMissed={() => { - if (eyeDropMode) return; - setSelectedPath(null); - setSubModule('properties'); - }} - > - {path.points.map((point, index) => ( - (sphereRefs.current[point.uuid] = el!)} - onClick={(e) => { - if (isConnecting || eyeDropMode) return; - e.stopPropagation(); - setSelectedActionSphere({ - path, - point: sphereRefs.current[point.uuid] - }); - setSubModule('mechanics'); - setSelectedPath(null); - }} - userData={{ point, path }} - onPointerMissed={() => { - if (eyeDropMode) return; - setSubModule('properties'); - setSelectedActionSphere(null); - }} - > - - - ))} - - {points.slice(0, -1).map((point, index) => { - const nextPoint = points[index + 1]; - const segmentCurve = new THREE.CatmullRomCurve3([point, nextPoint]); - const tubeGeometry = new THREE.TubeGeometry(segmentCurve, 20, 0.1, 16, false); - - return ( - - - - ); - })} - - ); - } else if (path.type === 'Vehicle') { - return ( - (groupRefs.current[path.modeluuid] = el!)} - position={path.position} - onClick={(e) => { - if (isConnecting || eyeDropMode) return; - e.stopPropagation(); - setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); - setSelectedActionSphere(null); - setTransformMode(null); - setSubModule('mechanics'); - }} - onPointerMissed={() => { - if (eyeDropMode) return; - setSelectedPath(null); - setSubModule('properties'); - }} - > - (sphereRefs.current[path.point.uuid] = el!)} - onClick={(e) => { - if (isConnecting || eyeDropMode) return; - e.stopPropagation(); - setSelectedActionSphere({ - path, - point: sphereRefs.current[path.point.uuid] - }); - setSubModule('mechanics'); - setSelectedPath(null); - }} - userData={{ point: path.point, path }} - onPointerMissed={() => { - if (eyeDropMode) return; - setSubModule('properties'); - setSelectedActionSphere(null); - }} - > - - - - ); - } - return null; - })} - - {selectedActionSphere && transformMode && ( - - )} - - ); + {selectedActionSphere && transformMode && ( + + )} + + ); } export default PathCreation; diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx index 0212d50..fd8b520 100644 --- a/app/src/modules/simulation/simulation.tsx +++ b/app/src/modules/simulation/simulation.tsx @@ -1,47 +1,52 @@ -import { useState, useEffect, useRef, useMemo } from 'react'; -import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from '../../store/store'; -import * as THREE from 'three'; -import Behaviour from './behaviour/behaviour'; -import PathCreation from './path/pathCreation'; -import PathConnector from './path/pathConnector'; -import useModuleStore from '../../store/useModuleStore'; -import ProcessContainer from './process/processContainer'; +import { useState, useEffect, useRef, useMemo } from "react"; +import { + useSelectedActionSphere, + useSelectedPath, + useSimulationPaths, +} from "../../store/store"; +import * as THREE from "three"; +import Behaviour from "./behaviour/behaviour"; +import PathCreation from "./path/pathCreation"; +import PathConnector from "./path/pathConnector"; +import useModuleStore from "../../store/useModuleStore"; +import ProcessContainer from "./process/processContainer"; +import Agv from "../builder/agv/agv"; function Simulation() { - const { activeModule } = useModuleStore(); - const pathsGroupRef = useRef() as React.MutableRefObject; - const { simulationPaths, setSimulationPaths } = useSimulationPaths(); - const [processes, setProcesses] = useState([]); + const { activeModule } = useModuleStore(); + const pathsGroupRef = useRef() as React.MutableRefObject; + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); + const [processes, setProcesses] = useState([]); - useEffect(() => { - // console.log('simulationPaths: ', simulationPaths); - }, [simulationPaths]); + useEffect(() => { + // console.log('simulationPaths: ', simulationPaths); + }, [simulationPaths]); - // useEffect(() => { - // if (selectedActionSphere) { - // console.log('selectedActionSphere: ', selectedActionSphere); - // } - // }, [selectedActionSphere]); + // useEffect(() => { + // if (selectedActionSphere) { + // console.log('selectedActionSphere: ', selectedActionSphere); + // } + // }, [selectedActionSphere]); - // useEffect(() => { - // if (selectedPath) { - // console.log('selectedPath: ', selectedPath); - // } - // }, [selectedPath]); + // useEffect(() => { + // if (selectedPath) { + // console.log('selectedPath: ', selectedPath); + // } + // }, [selectedPath]); - - return ( + return ( + <> + + {activeModule === "simulation" && ( <> - - {activeModule === 'simulation' && ( - <> - - - - - )} + + + + {/* */} - ); + )} + + ); } -export default Simulation; \ No newline at end of file +export default Simulation;