diff --git a/app/src/modules/scene/controls/selection/selectionControls.tsx b/app/src/modules/scene/controls/selection/selectionControls.tsx index d26889d..ece6924 100644 --- a/app/src/modules/scene/controls/selection/selectionControls.tsx +++ b/app/src/modules/scene/controls/selection/selectionControls.tsx @@ -199,14 +199,12 @@ const SelectionControls: React.FC = () => { setDuplicatedObjects([]); setSelectedAssets([]); }; - const updateBackend = async (updatedPaths: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => { if (updatedPaths.length === 0) return; const email = localStorage.getItem("email"); const organization = email ? email.split("@")[1].split(".")[0] : ""; updatedPaths.forEach(async (updatedPath) => { - if (updatedPath.type === "Conveyor") { // await setEventApi( // organization, @@ -225,9 +223,7 @@ const SelectionControls: React.FC = () => { }; socket.emit("v2:model-asset:updateEventData", data); - } else if (updatedPath.type === "Vehicle") { - // await setEventApi( // organization, // updatedPath.modeluuid, @@ -241,9 +237,7 @@ const SelectionControls: React.FC = () => { }; socket.emit("v2:model-asset:updateEventData", data); - } else if (updatedPath.type === "StaticMachine") { - // await setEventApi( // organization, // updatedPath.modeluuid, @@ -257,9 +251,7 @@ const SelectionControls: React.FC = () => { }; socket.emit("v2:model-asset:updateEventData", data); - } else if (updatedPath.type === "ArmBot") { - // await setEventApi( // organization, // updatedPath.modeluuid, @@ -274,239 +266,118 @@ const SelectionControls: React.FC = () => { socket.emit("v2:model-asset:updateEventData", data); } - }); }; - // const removeConnection = (modelUUID: any) => { - // - // const removedPath = simulationStates?.flatMap((state) => { - // let shouldInclude = false; - - // if (state.type === "Conveyor") { - // state.points.forEach((point: any) => { - // const sourceMatch = - // point.connections?.source?.modelUUID === modelUUID; - // const targetMatch = point.connections?.targets?.some( - // (target: any) => target.modelUUID === modelUUID - // ); - - // if (sourceMatch || targetMatch) shouldInclude = true; - // }); - // } - - // if (state.type === "Vehicle") { - // const targetMatch = state.points.connections?.targets?.some( - // (target: any) => target.modelUUID === modelUUID - // ); - - // if (targetMatch) shouldInclude = true; - // } - - // if (state.type === "StaticMachine") { - // const targetMatch = state.points.connections?.targets?.some( - // (target: any) => target.modelUUID === modelUUID - // ); - - // if (targetMatch) shouldInclude = true; - // } - - // if (state.type === "ArmBot") { - // const sourceMatch = - // state.points.connections?.source?.modelUUID === modelUUID; - // const targetMatch = state.points.connections?.targets?.some( - // (target: any) => target.modelUUID === modelUUID - // ); - - // const processMatch = - // state.points.actions?.processes?.some( - // (process: any) => - // process.startPoint === modelUUID || process.endPoint === modelUUID - // ) ?? false; - - // if (sourceMatch || targetMatch || processMatch) shouldInclude = true; - // } - - // return shouldInclude ? [state] : []; - // }); - // updateBackend(removedPath); - // - // return removedPath; - // // updateBackend(updatedPaths); - - // // setSimulationStates(updatedStates); - // }; - // const removeConnection = (modelUUIDs: any[]) => { - // - // const removedPath = simulationStates?.flatMap((state) => { - // let shouldInclude = false; - - // if (state.type === "Conveyor") { - // state.points.forEach((point: any) => { - // const sourceMatch = modelUUIDs.includes( - // point.connections?.source?.modelUUID - // ); - // const targetMatch = point.connections?.targets?.some((target: any) => - // modelUUIDs.includes(target.modelUUID) - // ); - - // if (sourceMatch || targetMatch) shouldInclude = true; - // }); - // } - - // if (state.type === "Vehicle") { - // const targetMatch = state.points.connections?.targets?.some( - // (target: any) => modelUUIDs.includes(target.modelUUID) - // ); - - // if (targetMatch) shouldInclude = true; - // } - - // if (state.type === "StaticMachine") { - // const targetMatch = state.points.connections?.targets?.some( - // (target: any) => modelUUIDs.includes(target.modelUUID) - // ); - - // if (targetMatch) shouldInclude = true; - // } - - // if (state.type === "ArmBot") { - // const sourceMatch = modelUUIDs.includes( - // state.points.connections?.source?.modelUUID - // ); - // const targetMatch = state.points.connections?.targets?.some( - // (target: any) => modelUUIDs.includes(target.modelUUID) - // ); - - // const processMatch = - // state.points.actions?.processes?.some( - // (process: any) => - // modelUUIDs.includes(process.startPoint) || - // modelUUIDs.includes(process.endPoint) - // ) ?? false; - - // if (sourceMatch || targetMatch || processMatch) shouldInclude = true; - // } - - // return shouldInclude ? [state] : []; - // }); - // updateBackend(removedPath); - // - // return removedPath; - // }; - - const removeConnection = (modelUUIDs: any[]) => { - const removedPath = simulationStates?.flatMap((state: any) => { - let shouldInclude = false; - - // Conveyor type + const removeConnections = (deletedModelUUIDs: string[]) => { + const updatedStates = simulationStates.map((state) => { + // Handle Conveyor if (state.type === "Conveyor") { - state.points.forEach((point: any) => { - const sourceMatch = modelUUIDs.includes(point.connections?.source?.modelUUID); - const targetMatch = point.connections?.targets?.some((target: any) => modelUUIDs.includes(target.modelUUID)); - - if (sourceMatch) { - point.connections.source = {}; - shouldInclude = true; - } - - if (targetMatch) { - point.connections.targets = []; - shouldInclude = true; - } - }); + const updatedConveyor: SimulationTypes.ConveyorEventsSchema = { + ...state, + points: state.points.map((point) => { + return { + ...point, + connections: { + ...point.connections, + targets: point.connections.targets.filter( + (target) => !deletedModelUUIDs.includes(target.modelUUID) + ), + }, + }; + }), + }; + return updatedConveyor; } - // Vehicle & StaticMachine types - if (state.type === "Vehicle") { - const targets = state.points?.connections?.targets || []; - const targetMatch = targets.some((target: any) => modelUUIDs.includes(target.modelUUID)); - - if (targetMatch) { - state.points.connections.targets = []; - shouldInclude = true; - } - } - if (state.type === "StaticMachine") { - const targets = state.points?.connections?.targets || []; - const targetMatch = targets.some((target: any) => modelUUIDs.includes(target.modelUUID)); - - if (targetMatch) { - state.points.connections.targets = []; - shouldInclude = true; - } + // Handle Vehicle + else if (state.type === "Vehicle") { + const updatedVehicle: SimulationTypes.VehicleEventsSchema = { + ...state, + points: { + ...state.points, + connections: { + ...state.points.connections, + targets: state.points.connections.targets.filter( + (target) => !deletedModelUUIDs.includes(target.modelUUID) + ), + }, + }, + }; + return updatedVehicle; } - // ArmBot type - if (state.type === "ArmBot") { - const sourceMatch = modelUUIDs.includes(state.points.connections?.source?.modelUUID); - - const targetMatch = state.points.connections?.targets?.some( - (target: any) => modelUUIDs.includes(target.modelUUID) - ); - // state.points.actions.processes = state.points.actions.processes.filter( - // (process: any) => - // console.log( - // !modelUUIDs.includes(process.startPoint), - // !modelUUIDs.includes(process.endPoint), - // modelUUIDs, - // process.startPoint, - // process.endPoint - // ) - // ); - - // shouldInclude = true; - - // const processMatches = state.points.actions?.processes?.some( - // (process: any) => - // console.log( - // "process: ", - // process, - // modelUUIDs, - // process.startPoint, - // process.endPoint - // ) - // // modelUUIDs.includes(process.startPoint) || - // // modelUUIDs.includes(process.endPoint) - // ); - // const processMatch = state.points.actions?.processes?.some( - // (process: any) => - // modelUUIDs.includes(String(process.startPoint)) || - // modelUUIDs.includes(String(process.endPoint)) - // ); - - // console.log("processMatch: ", processMatch); - if (sourceMatch) { - state.points.connections.source = {}; - shouldInclude = true; - } - - if (targetMatch) { - state.points.connections.targets = - state.points.connections.targets.filter((target: any) => !modelUUIDs.includes(target.modelUUID)); - shouldInclude = true; - } - - // console.log("processMatch: ", processMatch); - // if (processMatch) { - // state.points.actions.processes = - // state.points.actions.processes.filter((process: any) => { - // const shouldRemove = - // modelUUIDs.includes(process.startPoint) || - // modelUUIDs.includes(process.endPoint); - - // console.log("shouldRemove: ", shouldRemove); - // return !shouldRemove; - // }); - // shouldInclude = true; - // } + // Handle StaticMachine + else if (state.type === "StaticMachine") { + const updatedStaticMachine: SimulationTypes.StaticMachineEventsSchema = + { + ...state, + points: { + ...state.points, + connections: { + ...state.points.connections, + targets: state.points.connections.targets.filter( + (target) => !deletedModelUUIDs.includes(target.modelUUID) + ), + }, + }, + }; + return updatedStaticMachine; } - return shouldInclude ? [state] : []; + // Handle ArmBot + else if (state.type === "ArmBot") { + const updatedArmBot: SimulationTypes.ArmBotEventsSchema = { + ...state, + points: { + ...state.points, + connections: { + ...state.points.connections, + + targets: state.points.connections.targets.filter( + (target: any) => !deletedModelUUIDs.includes(target.modelUUID) + ), + }, + actions: { + ...state.points.actions, + processes: (state.points.actions.processes = + state.points.actions.processes?.filter((process) => { + const matchedStates = simulationStates.filter((s) => deletedModelUUIDs.includes(s.modeluuid)); + + if (matchedStates.length > 0) { + if (matchedStates[0]?.type === "StaticMachine") { + const trigPoints = matchedStates[0]?.points; + + return !( + process.triggerId === trigPoints?.triggers?.uuid + ); + } else if (matchedStates[0]?.type === "Conveyor") { + const trigPoints = matchedStates[0]?.points; + + if (Array.isArray(trigPoints)) { + const nonEmptyTriggers = trigPoints.filter((point) => point && point.triggers && point.triggers.length > 0); + + const allTriggerUUIDs = nonEmptyTriggers.flatMap((point) => point.triggers).map((trigger) => trigger.uuid); + + return !allTriggerUUIDs.includes(process.triggerId); + } + } + } + return true; + })), + }, + }, + }; + return updatedArmBot; + } + + return state; }); - updateBackend(removedPath); - return removedPath; + const filteredStates = updatedStates.filter((state) => !deletedModelUUIDs.includes(state.modeluuid)); + + updateBackend(filteredStates); + setSimulationStates(filteredStates); }; const deleteSelection = () => { @@ -552,65 +423,17 @@ const SelectionControls: React.FC = () => { }); setSimulationStates((prevEvents: (| SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => { - const updatedEvents = (prevEvents || []).filter( - (event) => event.modeluuid !== selectedMesh.uuid - ); + const updatedEvents = (prevEvents || []).filter((event) => event.modeluuid !== selectedMesh.uuid); return updatedEvents; - } - ); + }); itemsGroupRef.current?.remove(selectedMesh); }); const allUUIDs = selectedAssets.map((val: any) => val.uuid); - removeConnection(allUUIDs); + removeConnections(allUUIDs); - // const removedPath = simulationStates?.flatMap((path: any) => { - // let shouldInclude = false; - - // if (Array.isArray(path.points)) { - // path.points.forEach((point: any) => { - // const sourceMatch = - // point.connections?.source?.modelUUID === selectedAssets[0].uuid; - // const targetMatch = point.connections?.targets?.some( - // (target: any) => target.modelUUID === selectedAssets[0].uuid - // ); - - // if (sourceMatch) { - // point.connections.source = {}; - // shouldInclude = true; - // } - - // if (targetMatch) { - // point.connections.targets = []; - // shouldInclude = true; - // } - // }); - // } else { - // const sourceMatch = - // path.connections?.source?.modelUUID === selectedAssets[0].uuid; - // const targetMatch = path.connections?.targets?.some( - // (target: any) => target.modelUUID === selectedAssets[0].uuid - // ); - - // if (sourceMatch) { - // path.connections.source = {}; - // shouldInclude = true; - // } - - // if (targetMatch) { - // path.connections.targets = []; - // shouldInclude = true; - // } - // } - - // return shouldInclude ? [path] : []; - // }); - // updateBackend(removedPath); - - 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/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx index 0008a73..4ca12a2 100644 --- a/app/src/modules/simulation/path/pathConnector.tsx +++ b/app/src/modules/simulation/path/pathConnector.tsx @@ -1,15 +1,15 @@ -import { useFrame, useThree } from '@react-three/fiber'; -import React, { useEffect, useRef, useState } from 'react'; -import * as THREE from 'three'; -import * as Types from '../../../types/world/worldTypes'; -import * as SimulationTypes from '../../../types/simulationTypes'; -import { QuadraticBezierLine } from '@react-three/drei'; -import { useDeleteTool, useIsConnecting, useRenderDistance, useSimulationStates, useSocketStore } from '../../../store/store'; -import useModuleStore from '../../../store/useModuleStore'; -import { usePlayButtonStore } from '../../../store/usePlayButtonStore'; -import { setEventApi } from '../../../services/factoryBuilder/assest/floorAsset/setEventsApt'; +import { useFrame, useThree } from "@react-three/fiber"; +import React, { useEffect, useRef, useState } from "react"; +import * as THREE from "three"; +import * as Types from "../../../types/world/worldTypes"; +import * as SimulationTypes from "../../../types/simulationTypes"; +import { QuadraticBezierLine } from "@react-three/drei"; +import { useDeleteTool, useIsConnecting, useRenderDistance, useSimulationStates, useSocketStore, } from "../../../store/store"; +import useModuleStore from "../../../store/useModuleStore"; +import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; +import { setEventApi } from "../../../services/factoryBuilder/assest/floorAsset/setEventsApt"; -function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject }) { +function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObject; }) { const { activeModule } = useModuleStore(); const { gl, raycaster, scene, pointer, camera } = useThree(); const { deleteTool } = useDeleteTool(); @@ -21,84 +21,77 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const groupRefs = useRef<{ [key: string]: any }>({}); const [firstSelected, setFirstSelected] = useState<{ modelUUID: string; sphereUUID: string; position: THREE.Vector3; isCorner: boolean; } | null>(null); - const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3, end: THREE.Vector3, mid: THREE.Vector3 } | null>(null); - const [helperlineColor, setHelperLineColor] = useState('red'); + const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3; end: THREE.Vector3; mid: THREE.Vector3; } | null>(null); + const [helperlineColor, setHelperLineColor] = useState("red"); const [hoveredLineKey, setHoveredLineKey] = useState(null); const updatePathConnections = (fromModelUUID: string, fromPointUUID: string, toModelUUID: string, toPointUUID: string) => { - const updatedPaths = simulationStates.map(path => { - if (path.type === 'Conveyor') { + const updatedPaths = simulationStates.map((path) => { + if (path.type === "Conveyor") { // Handle outgoing connections from Conveyor if (path.modeluuid === fromModelUUID) { return { ...path, - points: path.points.map(point => { + points: path.points.map((point) => { if (point.uuid === fromPointUUID) { const newTarget = { modelUUID: toModelUUID, - pointUUID: toPointUUID + pointUUID: toPointUUID, }; const existingTargets = point.connections.targets || []; - if (!existingTargets.some(target => - target.modelUUID === newTarget.modelUUID && - target.pointUUID === newTarget.pointUUID - )) { + if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) { return { ...point, connections: { ...point.connections, - targets: [...existingTargets, newTarget] - } + targets: [...existingTargets, newTarget], + }, }; } } return point; - }) + }), }; } // Handle incoming connections to Conveyor else if (path.modeluuid === toModelUUID) { return { ...path, - points: path.points.map(point => { + points: path.points.map((point) => { if (point.uuid === toPointUUID) { const reverseTarget = { modelUUID: fromModelUUID, - pointUUID: fromPointUUID + pointUUID: fromPointUUID, }; const existingTargets = point.connections.targets || []; - if (!existingTargets.some(target => - target.modelUUID === reverseTarget.modelUUID && - target.pointUUID === reverseTarget.pointUUID - )) { + if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) { return { ...point, connections: { ...point.connections, - targets: [...existingTargets, reverseTarget] - } + targets: [...existingTargets, reverseTarget], + }, }; } } return point; - }) + }), }; } - } - else if (path.type === 'Vehicle') { + } else if (path.type === "Vehicle") { // Handle outgoing connections from Vehicle if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) { const newTarget = { modelUUID: toModelUUID, - pointUUID: toPointUUID + pointUUID: toPointUUID, }; const existingTargets = path.points.connections.targets || []; // Check if target is a Conveyor - const toPath = simulationStates.find(p => p.modeluuid === toModelUUID); - if (toPath?.type !== 'Conveyor') { + const toPath = simulationStates.find((p) => p.modeluuid === toModelUUID); + if (toPath?.type !== "Conveyor") { console.log("Vehicle can only connect to Conveyors"); return path; } @@ -109,19 +102,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec return path; } - if (!existingTargets.some(target => - target.modelUUID === newTarget.modelUUID && - target.pointUUID === newTarget.pointUUID - )) { + if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) { return { ...path, points: { ...path.points, connections: { ...path.points.connections, - targets: [...existingTargets, newTarget] - } - } + targets: [...existingTargets, newTarget], + }, + }, }; } } @@ -129,13 +119,13 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) { const reverseTarget = { modelUUID: fromModelUUID, - pointUUID: fromPointUUID + pointUUID: fromPointUUID, }; const existingTargets = path.points.connections.targets || []; // Check if source is a Conveyor - const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID); - if (fromPath?.type !== 'Conveyor') { + const fromPath = simulationStates.find((p) => p.modeluuid === fromModelUUID); + if (fromPath?.type !== "Conveyor") { console.log("Vehicle can only connect to Conveyors"); return path; } @@ -146,35 +136,31 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec return path; } - if (!existingTargets.some(target => - target.modelUUID === reverseTarget.modelUUID && - target.pointUUID === reverseTarget.pointUUID - )) { + if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) { return { ...path, points: { ...path.points, connections: { ...path.points.connections, - targets: [...existingTargets, reverseTarget] - } - } + targets: [...existingTargets, reverseTarget], + }, + }, }; } } return path; - } - else if (path.type === 'StaticMachine') { + } else if (path.type === "StaticMachine") { // Handle outgoing connections from StaticMachine if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) { const newTarget = { modelUUID: toModelUUID, - pointUUID: toPointUUID + pointUUID: toPointUUID, }; // Ensure target is an ArmBot - const toPath = simulationStates.find(p => p.modeluuid === toModelUUID); - if (toPath?.type !== 'ArmBot') { + const toPath = simulationStates.find((p) => p.modeluuid === toModelUUID); + if (toPath?.type !== "ArmBot") { console.log("StaticMachine can only connect to ArmBot"); return path; } @@ -187,19 +173,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec return path; } - if (!existingTargets.some(target => - target.modelUUID === newTarget.modelUUID && - target.pointUUID === newTarget.pointUUID - )) { + if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) { return { ...path, points: { ...path.points, connections: { ...path.points.connections, - targets: [...existingTargets, newTarget] - } - } + targets: [...existingTargets, newTarget], + }, + }, }; } } @@ -208,11 +191,11 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) { const reverseTarget = { modelUUID: fromModelUUID, - pointUUID: fromPointUUID + pointUUID: fromPointUUID, }; - const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID); - if (fromPath?.type !== 'ArmBot') { + const fromPath = simulationStates.find((p) => p.modeluuid === fromModelUUID); + if (fromPath?.type !== "ArmBot") { console.log("StaticMachine can only be connected from ArmBot"); return path; } @@ -224,63 +207,56 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec return path; } - if (!existingTargets.some(target => - target.modelUUID === reverseTarget.modelUUID && - target.pointUUID === reverseTarget.pointUUID - )) { + if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) { return { ...path, points: { ...path.points, connections: { ...path.points.connections, - targets: [...existingTargets, reverseTarget] - } - } + targets: [...existingTargets, reverseTarget], + }, + }, }; } } return path; - } - else if (path.type === 'ArmBot') { + } else if (path.type === "ArmBot") { // Handle outgoing connections from ArmBot if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) { const newTarget = { modelUUID: toModelUUID, - pointUUID: toPointUUID + pointUUID: toPointUUID, }; - const toPath = simulationStates.find(p => p.modeluuid === toModelUUID); + const toPath = simulationStates.find((p) => p.modeluuid === toModelUUID); if (!toPath) return path; const existingTargets = path.points.connections.targets || []; // Check if connecting to a StaticMachine and already connected to one - const alreadyConnectedToStatic = existingTargets.some(target => { - const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID); - return targetPath?.type === 'StaticMachine'; + const alreadyConnectedToStatic = existingTargets.some((target) => { + const targetPath = simulationStates.find((p) => p.modeluuid === target.modelUUID); + return targetPath?.type === "StaticMachine"; }); - if (toPath.type === 'StaticMachine') { + if (toPath.type === "StaticMachine") { if (alreadyConnectedToStatic) { console.log("ArmBot can only connect to one StaticMachine"); return path; } } - if (!existingTargets.some(target => - target.modelUUID === newTarget.modelUUID && - target.pointUUID === newTarget.pointUUID - )) { + if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) { return { ...path, points: { ...path.points, connections: { ...path.points.connections, - targets: [...existingTargets, newTarget] - } - } + targets: [...existingTargets, newTarget], + }, + }, }; } } @@ -289,39 +265,38 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) { const reverseTarget = { modelUUID: fromModelUUID, - pointUUID: fromPointUUID + pointUUID: fromPointUUID, }; - const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID); + const fromPath = simulationStates.find((p) => p.modeluuid === fromModelUUID); if (!fromPath) return path; const existingTargets = path.points.connections.targets || []; - const alreadyConnectedFromStatic = existingTargets.some(target => { - const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID); - return targetPath?.type === 'StaticMachine'; + const alreadyConnectedFromStatic = existingTargets.some((target) => { + const targetPath = simulationStates.find((p) => p.modeluuid === target.modelUUID); + return targetPath?.type === "StaticMachine"; }); - if (fromPath.type === 'StaticMachine') { + if (fromPath.type === "StaticMachine") { if (alreadyConnectedFromStatic) { - console.log("ArmBot can only be connected from one StaticMachine"); + console.log( + "ArmBot can only be connected from one StaticMachine" + ); return path; } } - if (!existingTargets.some(target => - target.modelUUID === reverseTarget.modelUUID && - target.pointUUID === reverseTarget.pointUUID - )) { + if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) { return { ...path, points: { ...path.points, connections: { ...path.points.connections, - targets: [...existingTargets, reverseTarget] - } - } + targets: [...existingTargets, reverseTarget], + }, + }, }; } } @@ -333,21 +308,18 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec setSimulationStates(updatedPaths); - const updatedPathDetails = updatedPaths.filter(path => - path.modeluuid === fromModelUUID || path.modeluuid === toModelUUID - ); + const updatedPathDetails = updatedPaths.filter((path) => path.modeluuid === fromModelUUID || path.modeluuid === toModelUUID); updateBackend(updatedPathDetails); }; - const updateBackend = async (updatedPaths: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => { + const updateBackend = async (updatedPaths: (| SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => { if (updatedPaths.length === 0) return; const email = localStorage.getItem("email"); const organization = email ? email.split("@")[1].split(".")[0] : ""; updatedPaths.forEach(async (updatedPath) => { - if (updatedPath.type === 'Conveyor') { - + if (updatedPath.type === "Conveyor") { // await setEventApi( // organization, // updatedPath.modeluuid, @@ -357,13 +329,15 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const data = { organization: organization, modeluuid: updatedPath.modeluuid, - eventData: { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed } - } - - socket.emit('v2:model-asset:updateEventData', data); - - } else if (updatedPath.type === 'Vehicle') { + eventData: { + type: "Conveyor", + points: updatedPath.points, + speed: updatedPath.speed, + }, + }; + socket.emit("v2:model-asset:updateEventData", data); + } else if (updatedPath.type === "Vehicle") { // await setEventApi( // organization, // updatedPath.modeluuid, @@ -373,13 +347,11 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const data = { organization: organization, modeluuid: updatedPath.modeluuid, - eventData: { type: "Vehicle", points: updatedPath.points } - } - - socket.emit('v2:model-asset:updateEventData', data); - - } else if (updatedPath.type === 'StaticMachine') { + eventData: { type: "Vehicle", points: updatedPath.points }, + }; + socket.emit("v2:model-asset:updateEventData", data); + } else if (updatedPath.type === "StaticMachine") { // await setEventApi( // organization, // updatedPath.modeluuid, @@ -389,13 +361,11 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const data = { organization: organization, modeluuid: updatedPath.modeluuid, - eventData: { type: "StaticMachine", points: updatedPath.points } - } - - socket.emit('v2:model-asset:updateEventData', data); - - } else if (updatedPath.type === 'ArmBot') { + eventData: { type: "StaticMachine", points: updatedPath.points }, + }; + socket.emit("v2:model-asset:updateEventData", data); + } else if (updatedPath.type === "ArmBot") { // await setEventApi( // organization, // updatedPath.modeluuid, @@ -405,15 +375,13 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const data = { organization: organization, modeluuid: updatedPath.modeluuid, - eventData: { type: "ArmBot", points: updatedPath.points } - } - - socket.emit('v2:model-asset:updateEventData', data); + eventData: { type: "ArmBot", points: updatedPath.points }, + }; + socket.emit("v2:model-asset:updateEventData", data); } - }) - - } + }); + }; const handleAddConnection = (fromModelUUID: string, fromUUID: string, toModelUUID: string, toUUID: string) => { updatePathConnections(fromModelUUID, fromUUID, toModelUUID, toUUID); @@ -447,7 +415,10 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec if (drag || evt.button === 0) return; raycaster.setFromCamera(pointer, camera); - const intersects = raycaster.intersectObjects(pathsGroupRef.current.children, true); + const intersects = raycaster.intersectObjects( + pathsGroupRef.current.children, + true + ); if (intersects.length > 0) { const intersected = intersects[0].object; @@ -461,45 +432,46 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec let isStartOrEnd = false; if (intersected.userData.path.points && intersected.userData.path.points.length > 1) { - isStartOrEnd = intersected.userData.path.points.length > 0 && ( - sphereUUID === intersected.userData.path.points[0].uuid || - sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid - ); + isStartOrEnd = intersected.userData.path.points.length > 0 + && (sphereUUID === intersected.userData.path.points[0].uuid || sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid); } else if (intersected.userData.path.points) { isStartOrEnd = sphereUUID === intersected.userData.path.points.uuid; } if (modelUUID) { - const firstPath = simulationStates.find(p => p.modeluuid === firstSelected?.modelUUID); - const secondPath = simulationStates.find(p => p.modeluuid === modelUUID); + const firstPath = simulationStates.find((p) => p.modeluuid === firstSelected?.modelUUID); + const secondPath = simulationStates.find((p) => p.modeluuid === modelUUID); // Prevent vehicle-to-vehicle connections - if (firstPath && secondPath && firstPath.type === 'Vehicle' && secondPath.type === 'Vehicle') { + if (firstPath && secondPath && firstPath.type === "Vehicle" && secondPath.type === "Vehicle") { console.log("Cannot connect two vehicle paths together"); return; } // Prevent conveyor middle point to conveyor connections - if (firstPath && secondPath && - firstPath.type === 'Conveyor' && - secondPath.type === 'Conveyor' && - (!firstSelected?.isCorner || !isStartOrEnd)) { + if (firstPath && secondPath && firstPath.type === "Conveyor" && secondPath.type === "Conveyor" && (!firstSelected?.isCorner || !isStartOrEnd)) { console.log("Conveyor connections must be between start/end points"); return; } // Check if this specific connection already exists const isDuplicateConnection = firstSelected - ? simulationStates.some(path => { + ? simulationStates.some((path) => { if (path.modeluuid === firstSelected.modelUUID) { - if (path.type === 'Conveyor') { - const point = path.points.find(p => p.uuid === firstSelected.sphereUUID); - return point?.connections.targets.some(t => - t.modelUUID === modelUUID && t.pointUUID === sphereUUID + if (path.type === "Conveyor") { + const point = path.points.find( + (p) => p.uuid === firstSelected.sphereUUID ); - } else if (path.type === 'Vehicle') { - return path.points.connections.targets.some(t => - t.modelUUID === modelUUID && t.pointUUID === sphereUUID + return point?.connections.targets.some( + (t) => + t.modelUUID === modelUUID && + t.pointUUID === sphereUUID + ); + } else if (path.type === "Vehicle") { + return path.points.connections.targets.some( + (t) => + t.modelUUID === modelUUID && + t.pointUUID === sphereUUID ); } } @@ -513,8 +485,9 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } // For Vehicles, check if they're already connected to anything - if (intersected.userData.path.type === 'Vehicle') { - const vehicleConnections = intersected.userData.path.points.connections.targets.length; + if (intersected.userData.path.type === "Vehicle") { + const vehicleConnections = + intersected.userData.path.points.connections.targets.length; if (vehicleConnections >= 1) { console.log("Vehicle can only have one connection"); return; @@ -522,12 +495,13 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } // For non-Vehicle paths, check if already connected - if (intersected.userData.path.type !== 'Vehicle') { - const isAlreadyConnected = simulationStates.some(path => { - if (path.type === 'Conveyor') { - return path.points.some(point => - point.uuid === sphereUUID && - point.connections.targets.length > 0 + if (intersected.userData.path.type !== "Vehicle") { + const isAlreadyConnected = simulationStates.some((path) => { + if (path.type === "Conveyor") { + return path.points.some( + (point) => + point.uuid === sphereUUID && + point.connections.targets.length > 0 ); } return false; @@ -541,8 +515,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec if (firstSelected) { // Check if trying to connect Vehicle to non-Conveyor - if ((firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') || - (secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor')) { + if ((firstPath?.type === "Vehicle" && secondPath?.type !== "Conveyor") || (secondPath?.type === "Vehicle" && firstPath?.type !== "Conveyor")) { console.log("Vehicle can only connect to Conveyors"); return; } @@ -554,21 +527,20 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } // Check if StaticMachine is involved in the connection - if ((firstPath?.type === 'StaticMachine' && secondPath?.type !== 'ArmBot') || - (secondPath?.type === 'StaticMachine' && firstPath?.type !== 'ArmBot')) { + if ((firstPath?.type === "StaticMachine" && secondPath?.type !== "ArmBot") || (secondPath?.type === "StaticMachine" && firstPath?.type !== "ArmBot")) { console.log("StaticMachine can only connect to ArmBot"); return; } // Check if StaticMachine already has a connection - if (firstPath?.type === 'StaticMachine') { + if (firstPath?.type === "StaticMachine") { const staticConnections = firstPath.points.connections.targets.length; if (staticConnections >= 1) { console.log("StaticMachine can only have one connection"); return; } } - if (secondPath?.type === 'StaticMachine') { + if (secondPath?.type === "StaticMachine") { const staticConnections = secondPath.points.connections.targets.length; if (staticConnections >= 1) { console.log("StaticMachine can only have one connection"); @@ -577,17 +549,17 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } // Check if ArmBot is involved - if ((firstPath?.type === 'ArmBot' && secondPath?.type === 'StaticMachine') || - (secondPath?.type === 'ArmBot' && firstPath?.type === 'StaticMachine')) { - - const armBotPath = firstPath?.type === 'ArmBot' ? firstPath : secondPath; - const staticPath = firstPath?.type === 'StaticMachine' ? firstPath : secondPath; + if ((firstPath?.type === "ArmBot" && secondPath?.type === "StaticMachine") || (secondPath?.type === "ArmBot" && firstPath?.type === "StaticMachine")) { + const armBotPath = firstPath?.type === "ArmBot" ? firstPath : secondPath; + const staticPath = firstPath?.type === "StaticMachine" ? firstPath : secondPath; const armBotConnections = armBotPath.points.connections.targets || []; - const alreadyConnectedToStatic = armBotConnections.some(target => { - const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID); - return targetPath?.type === 'StaticMachine'; - }); + const alreadyConnectedToStatic = armBotConnections.some( + (target) => { + const targetPath = simulationStates.find((p) => p.modeluuid === target.modelUUID); + return targetPath?.type === "StaticMachine"; + } + ); if (alreadyConnectedToStatic) { console.log("ArmBot can only connect to one StaticMachine"); @@ -602,15 +574,15 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } // Prevent ArmBot ↔ ArmBot - if (firstPath?.type === 'ArmBot' && secondPath?.type === 'ArmBot') { + if (firstPath?.type === "ArmBot" && secondPath?.type === "ArmBot") { console.log("Cannot connect two ArmBots together"); return; } // If one is ArmBot, ensure the other is StaticMachine or Conveyor - if (firstPath?.type === 'ArmBot' || secondPath?.type === 'ArmBot') { - const otherType = firstPath?.type === 'ArmBot' ? secondPath?.type : firstPath?.type; - if (otherType !== 'StaticMachine' && otherType !== 'Conveyor') { + if (firstPath?.type === "ArmBot" || secondPath?.type === "ArmBot") { + const otherType = firstPath?.type === "ArmBot" ? secondPath?.type : firstPath?.type; + if (otherType !== "StaticMachine" && otherType !== "Conveyor") { console.log("ArmBot can only connect to Conveyors or one StaticMachine"); return; } @@ -639,7 +611,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } }; - if (activeModule === 'simulation' && !deleteTool) { + if (activeModule === "simulation" && !deleteTool) { canvasElement.addEventListener("mousedown", onMouseDown); canvasElement.addEventListener("mouseup", onMouseUp); canvasElement.addEventListener("mousemove", onMouseMove); @@ -662,7 +634,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec Object.values(groupRefs.current).forEach((group) => { if (group) { const distance = new THREE.Vector3(...group.position.toArray()).distanceTo(camera.position); - group.visible = ((distance <= renderDistance) && !isPlaying); + group.visible = distance <= renderDistance && !isPlaying; } }); }); @@ -670,16 +642,17 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec useFrame(() => { if (firstSelected) { raycaster.setFromCamera(pointer, camera); - const intersects = raycaster.intersectObjects(scene.children, true).filter((intersect) => - !intersect.object.name.includes("Roof") && - !intersect.object.name.includes("agv-collider") && - !intersect.object.name.includes("MeasurementReference") && - !intersect.object.userData.isPathObject && - !(intersect.object.type === "GridHelper") + const intersects = raycaster.intersectObjects(scene.children, true).filter( + (intersect) => + !intersect.object.name.includes("Roof") && + !intersect.object.name.includes("agv-collider") && + !intersect.object.name.includes("MeasurementReference") && + !intersect.object.userData.isPathObject && + !(intersect.object.type === "GridHelper") ); let point: THREE.Vector3 | null = null; - let snappedSphere: { sphereUUID: string, position: THREE.Vector3, modelUUID: string, isCorner: boolean } | null = null; + let snappedSphere: { sphereUUID: string; position: THREE.Vector3; modelUUID: string; isCorner: boolean; } | null = null; let isInvalidConnection = false; if (intersects.length > 0) { @@ -699,9 +672,9 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const pathData = sphere.userData.path; const modelUUID = pathData.modeluuid; - const firstPath = simulationStates.find(p => p.modeluuid === firstSelected.modelUUID); - const secondPath = simulationStates.find(p => p.modeluuid === modelUUID); - const isVehicleToVehicle = firstPath?.type === 'Vehicle' && secondPath?.type === 'Vehicle'; + const firstPath = simulationStates.find((p) => p.modeluuid === firstSelected.modelUUID); + const secondPath = simulationStates.find((p) => p.modeluuid === modelUUID); + const isVehicleToVehicle = firstPath?.type === "Vehicle" && secondPath?.type === "Vehicle"; // Inside the useFrame hook, where we check for snapped spheres: const isConnectable = ( @@ -816,7 +789,6 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } else { isInvalidConnection = true; } - } if (snappedSphere) { @@ -839,9 +811,9 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec }); if (sphereIntersects.length > 0) { - setHelperLineColor(isInvalidConnection ? 'red' : '#6cf542'); + setHelperLineColor(isInvalidConnection ? "red" : "#6cf542"); } else { - setHelperLineColor('yellow'); + setHelperLineColor("yellow"); } } else { setCurrentLine(null); @@ -854,118 +826,124 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec }); const removeConnection = (connection1: { model: string; point: string }, connection2: { model: string; point: string }) => { - const updatedStates = simulationStates.map(state => { + const updatedStates = simulationStates.map((state) => { + // Handle Conveyor (which has multiple points) - if (state.type === 'Conveyor') { + if (state.type === "Conveyor") { const updatedConveyor: SimulationTypes.ConveyorEventsSchema = { ...state, - points: state.points.map(point => { + points: state.points.map((point) => { // Check if this point is either connection1 or connection2 - if ((state.modeluuid === connection1.model && point.uuid === connection1.point) || - (state.modeluuid === connection2.model && point.uuid === connection2.point)) { - + if ((state.modeluuid === connection1.model && point.uuid === connection1.point) || (state.modeluuid === connection2.model && point.uuid === connection2.point)) { return { ...point, connections: { ...point.connections, - targets: point.connections.targets.filter(target => { + targets: point.connections.targets.filter((target) => { // Remove the target that matches the other connection return !( - (target.modelUUID === connection1.model && target.pointUUID === connection1.point) || - (target.modelUUID === connection2.model && target.pointUUID === connection2.point) + (target.modelUUID === connection1.model && + target.pointUUID === connection1.point) || + (target.modelUUID === connection2.model && + target.pointUUID === connection2.point) ); - }) - } + }), + }, }; } return point; - }) + }), }; return updatedConveyor; } - // Handle Vehicle - else if (state.type === 'Vehicle') { - if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) || - (state.modeluuid === connection2.model && state.points.uuid === connection2.point)) { + // Handle Vehicle + else if (state.type === "Vehicle") { + if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) || (state.modeluuid === connection2.model && state.points.uuid === connection2.point)) { const updatedVehicle: SimulationTypes.VehicleEventsSchema = { ...state, points: { ...state.points, connections: { ...state.points.connections, - targets: state.points.connections.targets.filter(target => { + targets: state.points.connections.targets.filter((target) => { return !( - (target.modelUUID === connection1.model && target.pointUUID === connection1.point) || - (target.modelUUID === connection2.model && target.pointUUID === connection2.point) + (target.modelUUID === connection1.model && + target.pointUUID === connection1.point) || + (target.modelUUID === connection2.model && + target.pointUUID === connection2.point) ); - }) + }), }, // Ensure all required Vehicle point properties are included speed: state.points.speed, - actions: state.points.actions - } + actions: state.points.actions, + }, }; return updatedVehicle; } } - // Handle StaticMachine - else if (state.type === 'StaticMachine') { - if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) || - (state.modeluuid === connection2.model && state.points.uuid === connection2.point)) { - const updatedStaticMachine: SimulationTypes.StaticMachineEventsSchema = { + // Handle StaticMachine + else if (state.type === "StaticMachine") { + if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) || (state.modeluuid === connection2.model && state.points.uuid === connection2.point)) { + const updatedStaticMachine: SimulationTypes.StaticMachineEventsSchema = + { ...state, points: { ...state.points, connections: { ...state.points.connections, - targets: state.points.connections.targets.filter(target => { + targets: state.points.connections.targets.filter((target) => { return !( - (target.modelUUID === connection1.model && target.pointUUID === connection1.point) || - (target.modelUUID === connection2.model && target.pointUUID === connection2.point) + (target.modelUUID === connection1.model && + target.pointUUID === connection1.point) || + (target.modelUUID === connection2.model && + target.pointUUID === connection2.point) ); - }) + }), }, // Ensure all required StaticMachine point properties are included actions: state.points.actions, - triggers: state.points.triggers - } + triggers: state.points.triggers, + }, }; return updatedStaticMachine; } } - // Handle ArmBot - else if (state.type === 'ArmBot') { - if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) || - (state.modeluuid === connection2.model && state.points.uuid === connection2.point)) { + // Handle ArmBot + else if (state.type === "ArmBot") { + if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) || (state.modeluuid === connection2.model && state.points.uuid === connection2.point)) { const updatedArmBot: SimulationTypes.ArmBotEventsSchema = { ...state, points: { ...state.points, connections: { ...state.points.connections, - targets: state.points.connections.targets.filter(target => { + targets: state.points.connections.targets.filter((target) => { return !( - (target.modelUUID === connection1.model && target.pointUUID === connection1.point) || - (target.modelUUID === connection2.model && target.pointUUID === connection2.point) + (target.modelUUID === connection1.model && + target.pointUUID === connection1.point) || + (target.modelUUID === connection2.model && + target.pointUUID === connection2.point) ); - }) + }), }, actions: { ...state.points.actions, - processes: state.points.actions.processes?.filter(process => { - return !( - process.startPoint === connection1.point || - process.endPoint === connection1.point || - process.startPoint === connection2.point || - process.endPoint === connection2.point - ); - }) || [] + processes: + state.points.actions.processes?.filter((process) => { + return !( + process.startPoint === connection1.point || + process.endPoint === connection1.point || + process.startPoint === connection2.point || + process.endPoint === connection2.point + ); + }) || [], }, - triggers: state.points.triggers - } + triggers: state.points.triggers, + }, }; return updatedArmBot; } @@ -973,26 +951,150 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec return state; }); - const updatedPaths = updatedStates.filter(state => - state.modeluuid === connection1.model || state.modeluuid === connection2.model + const updatedPaths = updatedStates.filter( + (state) => + state.modeluuid === connection1.model || + state.modeluuid === connection2.model ); + console.log("updatedPaths: ", updatedPaths); updateBackend(updatedPaths); setSimulationStates(updatedStates); }; - return ( - - {simulationStates.flatMap(path => { - if (path.type === 'Conveyor') { - return path.points.flatMap(point => - point.connections.targets.map((target, index) => { - const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID); - if (targetPath?.type !== 'Conveyor' && targetPath?.type !== 'ArmBot') return null; + const removeConnections = (deletedModelUUIDs: string[]) => { + const updatedStates = simulationStates.map((state) => { - const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid); - const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID); + // Handle Conveyor + if (state.type === "Conveyor") { + const updatedConveyor: SimulationTypes.ConveyorEventsSchema = { + ...state, + points: state.points.map((point) => { + return { + ...point, + connections: { + ...point.connections, + targets: point.connections.targets.filter( + (target) => !deletedModelUUIDs.includes(target.modelUUID) + ), + }, + }; + }), + }; + return updatedConveyor; + } + + // Handle Vehicle + else if (state.type === "Vehicle") { + const updatedVehicle: SimulationTypes.VehicleEventsSchema = { + ...state, + points: { + ...state.points, + connections: { + ...state.points.connections, + targets: state.points.connections.targets.filter( + (target) => !deletedModelUUIDs.includes(target.modelUUID) + ), + }, + }, + }; + return updatedVehicle; + } + + // Handle StaticMachine + else if (state.type === "StaticMachine") { + const updatedStaticMachine: SimulationTypes.StaticMachineEventsSchema = + { + ...state, + points: { + ...state.points, + connections: { + ...state.points.connections, + targets: state.points.connections.targets.filter( + (target) => !deletedModelUUIDs.includes(target.modelUUID) + ), + }, + }, + }; + return updatedStaticMachine; + } + + // Handle ArmBot + else if (state.type === "ArmBot") { + const updatedArmBot: SimulationTypes.ArmBotEventsSchema = { + ...state, + points: { + ...state.points, + connections: { + ...state.points.connections, + + targets: state.points.connections.targets.filter( + (target: any) => !deletedModelUUIDs.includes(target.modelUUID) + ), + }, + actions: { + ...state.points.actions, + processes: (state.points.actions.processes = + state.points.actions.processes?.filter((process) => { + const matchedStates = simulationStates.filter((s) => + deletedModelUUIDs.includes(s.modeluuid) + ); + + if (matchedStates.length > 0) { + if (matchedStates[0]?.type === "StaticMachine") { + const trigPoints = matchedStates[0]?.points; + + return !( + process.triggerId === trigPoints?.triggers?.uuid + ); + } else if (matchedStates[0]?.type === "Conveyor") { + const trigPoints = matchedStates[0]?.points; + + if (Array.isArray(trigPoints)) { + const nonEmptyTriggers = trigPoints.filter( + (point) => + point && point.triggers && point.triggers.length > 0 + ); + + const allTriggerUUIDs = nonEmptyTriggers + .flatMap((point) => point.triggers) + .map((trigger) => trigger.uuid); + + return !allTriggerUUIDs.includes(process.triggerId); + } + } + } + return true; + })), + }, + }, + }; + return updatedArmBot; + } + + return state; + }); + + const filteredStates = updatedStates.filter( + (state) => !deletedModelUUIDs.includes(state.modeluuid) + ); + + updateBackend(filteredStates); + setSimulationStates(filteredStates); + }; + + return ( + + {simulationStates.flatMap((path) => { + if (path.type === "Conveyor") { + return path.points.flatMap((point) => + point.connections.targets.map((target, index) => { + const targetPath = simulationStates.find((p) => p.modeluuid === target.modelUUID); + if (targetPath?.type !== "Conveyor" && targetPath?.type !== "ArmBot") return null; + + const fromSphere = pathsGroupRef.current?.getObjectByProperty("uuid", point.uuid); + const toSphere = pathsGroupRef.current?.getObjectByProperty("uuid", target.pointUUID); if (fromSphere && toSphere) { const fromWorldPosition = new THREE.Vector3(); @@ -1002,7 +1104,12 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const distance = fromWorldPosition.distanceTo(toWorldPosition); const heightFactor = Math.max(0.5, distance * 0.2); - const midPoint = new THREE.Vector3((fromWorldPosition.x + toWorldPosition.x) / 2, Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, (fromWorldPosition.z + toWorldPosition.z) / 2); + const midPoint = new THREE.Vector3( + (fromWorldPosition.x + toWorldPosition.x) / 2, + Math.max(fromWorldPosition.y, toWorldPosition.y) + + heightFactor, + (fromWorldPosition.z + toWorldPosition.z) / 2 + ); return ( setHoveredLineKey(`${point.uuid}-${target.pointUUID}-${index}`)} onPointerOut={() => setHoveredLineKey(null)} onClick={() => { if (deleteTool) { + const connection1 = { + model: path.modeluuid, + point: point.uuid, + }; + const connection2 = { + model: target.modelUUID, + point: target.pointUUID, + }; - const connection1 = { model: path.modeluuid, point: point.uuid } - const connection2 = { model: target.modelUUID, point: target.pointUUID } - - removeConnection(connection1, connection2) - + removeConnection(connection1, connection2); } }} - depthWrite={false} userData={target} /> ); @@ -1044,10 +1148,10 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec ); } - if (path.type === 'Vehicle') { + if (path.type === "Vehicle") { return path.points.connections.targets.map((target, index) => { - const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', path.points.uuid); - const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID); + const fromSphere = pathsGroupRef.current?.getObjectByProperty("uuid", path.points.uuid); + const toSphere = pathsGroupRef.current?.getObjectByProperty("uuid", target.pointUUID); if (fromSphere && toSphere) { const fromWorldPosition = new THREE.Vector3(); @@ -1057,7 +1161,11 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const distance = fromWorldPosition.distanceTo(toWorldPosition); const heightFactor = Math.max(0.5, distance * 0.2); - const midPoint = new THREE.Vector3((fromWorldPosition.x + toWorldPosition.x) / 2, Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, (fromWorldPosition.z + toWorldPosition.z) / 2); + const midPoint = new THREE.Vector3( + (fromWorldPosition.x + toWorldPosition.x) / 2, + Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, + (fromWorldPosition.z + toWorldPosition.z) / 2 + ); return ( setHoveredLineKey(`${path.points.uuid}-${target.pointUUID}-${index}`)} onPointerOut={() => setHoveredLineKey(null)} onClick={() => { if (deleteTool) { + const connection1 = { + model: path.modeluuid, + point: path.points.uuid, + }; + const connection2 = { + model: target.modelUUID, + point: target.pointUUID, + }; - const connection1 = { model: path.modeluuid, point: path.points.uuid } - const connection2 = { model: target.modelUUID, point: target.pointUUID } - - removeConnection(connection1, connection2) + removeConnection(connection1, connection2); } }} - depthWrite={false} userData={target} /> ); @@ -1095,13 +1203,13 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec }); } - if (path.type === 'StaticMachine') { + if (path.type === "StaticMachine") { return path.points.connections.targets.map((target, index) => { - const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID); - if (targetPath?.type !== 'ArmBot') return null; + const targetPath = simulationStates.find((p) => p.modeluuid === target.modelUUID); + if (targetPath?.type !== "ArmBot") return null; - const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', path.points.uuid); - const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID); + const fromSphere = pathsGroupRef.current?.getObjectByProperty("uuid", path.points.uuid); + const toSphere = pathsGroupRef.current?.getObjectByProperty("uuid", target.pointUUID); if (fromSphere && toSphere) { const fromWorldPosition = new THREE.Vector3(); @@ -1111,7 +1219,11 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const distance = fromWorldPosition.distanceTo(toWorldPosition); const heightFactor = Math.max(0.5, distance * 0.2); - const midPoint = new THREE.Vector3((fromWorldPosition.x + toWorldPosition.x) / 2, Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, (fromWorldPosition.z + toWorldPosition.z) / 2); + const midPoint = new THREE.Vector3( + (fromWorldPosition.x + toWorldPosition.x) / 2, + Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, + (fromWorldPosition.z + toWorldPosition.z) / 2 + ); return ( setHoveredLineKey(`${path.points.uuid}-${target.pointUUID}-${index}`)} onPointerOut={() => setHoveredLineKey(null)} onClick={() => { if (deleteTool) { + const connection1 = { + model: path.modeluuid, + point: path.points.uuid, + }; + const connection2 = { + model: target.modelUUID, + point: target.pointUUID, + }; - const connection1 = { model: path.modeluuid, point: path.points.uuid } - const connection2 = { model: target.modelUUID, point: target.pointUUID } - - removeConnection(connection1, connection2) - + removeConnection(connection1, connection2); } }} - depthWrite={false} userData={target} /> ); @@ -1163,12 +1274,10 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec dashed dashSize={1} dashScale={20} - depthWrite={false} /> )} ); - } -export default PathConnector; \ No newline at end of file +export default PathConnector;