From 82a7cd0001b0efd91e7dcc91b73a1f58f0a1f720 Mon Sep 17 00:00:00 2001
From: Poovizhi99 <poovizhi@hexrfactory.com>
Date: Tue, 15 Apr 2025 09:11:01 +0530
Subject: [PATCH 01/20] updated paths

---
 .../modules/simulation/path/pathConnector.tsx | 2562 ++++++++++-------
 1 file changed, 1445 insertions(+), 1117 deletions(-)

diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx
index c561cbb..f6ee51f 100644
--- a/app/src/modules/simulation/path/pathConnector.tsx
+++ b/app/src/modules/simulation/path/pathConnector.tsx
@@ -1,1170 +1,1498 @@
-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 { 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 { 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<THREE.Group> }) {
-    const { activeModule } = useModuleStore();
-    const { gl, raycaster, scene, pointer, camera } = useThree();
-    const { deleteTool } = useDeleteTool();
-    const { renderDistance } = useRenderDistance();
-    const { setIsConnecting } = useIsConnecting();
-    const { simulationStates, setSimulationStates } = useSimulationStates();
-    const { isPlaying } = usePlayButtonStore();
-    const { socket } = useSocketStore();
-    const groupRefs = useRef<{ [key: string]: any }>({});
+function PathConnector({
+  pathsGroupRef,
+}: {
+  pathsGroupRef: React.MutableRefObject<THREE.Group>;
+}) {
+  const { activeModule } = useModuleStore();
+  const { gl, raycaster, scene, pointer, camera } = useThree();
+  const { deleteTool } = useDeleteTool();
+  const { renderDistance } = useRenderDistance();
+  const { setIsConnecting } = useIsConnecting();
+  const { simulationStates, setSimulationStates } = useSimulationStates();
+  const { isPlaying } = usePlayButtonStore();
+  const { socket } = useSocketStore();
+  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<string>('red');
-    const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
+  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<string>("red");
+  const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
 
-    const updatePathConnections = (fromModelUUID: string, fromPointUUID: string, toModelUUID: string, toPointUUID: string) => {
-        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 => {
-                            if (point.uuid === fromPointUUID) {
-                                const newTarget = {
-                                    modelUUID: toModelUUID,
-                                    pointUUID: toPointUUID
-                                };
-                                const existingTargets = point.connections.targets || [];
+  const updatePathConnections = (
+    fromModelUUID: string,
+    fromPointUUID: string,
+    toModelUUID: string,
+    toPointUUID: string
+  ) => {
+    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) => {
+              if (point.uuid === fromPointUUID) {
+                const newTarget = {
+                  modelUUID: toModelUUID,
+                  pointUUID: toPointUUID,
+                };
+                const existingTargets = point.connections.targets || [];
 
-                                if (!existingTargets.some(target =>
-                                    target.modelUUID === newTarget.modelUUID &&
-                                    target.pointUUID === newTarget.pointUUID
-                                )) {
-                                    return {
-                                        ...point,
-                                        connections: {
-                                            ...point.connections,
-                                            targets: [...existingTargets, newTarget]
-                                        }
-                                    };
-                                }
-                            }
-                            return point;
-                        })
-                    };
+                if (
+                  !existingTargets.some(
+                    (target) =>
+                      target.modelUUID === newTarget.modelUUID &&
+                      target.pointUUID === newTarget.pointUUID
+                  )
+                ) {
+                  return {
+                    ...point,
+                    connections: {
+                      ...point.connections,
+                      targets: [...existingTargets, newTarget],
+                    },
+                  };
                 }
-                // Handle incoming connections to Conveyor
-                else if (path.modeluuid === toModelUUID) {
-                    return {
-                        ...path,
-                        points: path.points.map(point => {
-                            if (point.uuid === toPointUUID) {
-                                const reverseTarget = {
-                                    modelUUID: fromModelUUID,
-                                    pointUUID: fromPointUUID
-                                };
-                                const existingTargets = point.connections.targets || [];
+              }
+              return point;
+            }),
+          };
+        }
+        // Handle incoming connections to Conveyor
+        else if (path.modeluuid === toModelUUID) {
+          return {
+            ...path,
+            points: path.points.map((point) => {
+              if (point.uuid === toPointUUID) {
+                const reverseTarget = {
+                  modelUUID: fromModelUUID,
+                  pointUUID: fromPointUUID,
+                };
+                const existingTargets = point.connections.targets || [];
 
-                                if (!existingTargets.some(target =>
-                                    target.modelUUID === reverseTarget.modelUUID &&
-                                    target.pointUUID === reverseTarget.pointUUID
-                                )) {
-                                    return {
-                                        ...point,
-                                        connections: {
-                                            ...point.connections,
-                                            targets: [...existingTargets, reverseTarget]
-                                        }
-                                    };
-                                }
-                            }
-                            return point;
-                        })
-                    };
+                if (
+                  !existingTargets.some(
+                    (target) =>
+                      target.modelUUID === reverseTarget.modelUUID &&
+                      target.pointUUID === reverseTarget.pointUUID
+                  )
+                ) {
+                  return {
+                    ...point,
+                    connections: {
+                      ...point.connections,
+                      targets: [...existingTargets, reverseTarget],
+                    },
+                  };
                 }
-            }
-            else if (path.type === 'Vehicle') {
-                // Handle outgoing connections from Vehicle
-                if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
-                    const newTarget = {
-                        modelUUID: toModelUUID,
-                        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') {
-                        console.log("Vehicle can only connect to Conveyors");
-                        return path;
-                    }
-
-                    // Check if already has a connection
-                    if (existingTargets.length >= 1) {
-                        console.log("Vehicle can have only one connection");
-                        return path;
-                    }
-
-                    if (!existingTargets.some(target =>
-                        target.modelUUID === newTarget.modelUUID &&
-                        target.pointUUID === newTarget.pointUUID
-                    )) {
-                        return {
-                            ...path,
-                            points: {
-                                ...path.points,
-                                connections: {
-                                    ...path.points.connections,
-                                    targets: [...existingTargets, newTarget]
-                                }
-                            }
-                        };
-                    }
-                }
-                // Handle incoming connections to Vehicle
-                else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
-                    const reverseTarget = {
-                        modelUUID: fromModelUUID,
-                        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') {
-                        console.log("Vehicle can only connect to Conveyors");
-                        return path;
-                    }
-
-                    // Check if already has a connection
-                    if (existingTargets.length >= 1) {
-                        console.log("Vehicle can have only one connection");
-                        return path;
-                    }
-
-                    if (!existingTargets.some(target =>
-                        target.modelUUID === reverseTarget.modelUUID &&
-                        target.pointUUID === reverseTarget.pointUUID
-                    )) {
-                        return {
-                            ...path,
-                            points: {
-                                ...path.points,
-                                connections: {
-                                    ...path.points.connections,
-                                    targets: [...existingTargets, reverseTarget]
-                                }
-                            }
-                        };
-                    }
-                }
-                return path;
-            }
-            else if (path.type === 'StaticMachine') {
-                // Handle outgoing connections from StaticMachine
-                if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
-                    const newTarget = {
-                        modelUUID: toModelUUID,
-                        pointUUID: toPointUUID
-                    };
-
-                    // Ensure target is an ArmBot
-                    const toPath = simulationStates.find(p => p.modeluuid === toModelUUID);
-                    if (toPath?.type !== 'ArmBot') {
-                        console.log("StaticMachine can only connect to ArmBot");
-                        return path;
-                    }
-
-                    const existingTargets = path.points.connections.targets || [];
-
-                    // Allow only one connection
-                    if (existingTargets.length >= 1) {
-                        console.log("StaticMachine can only have one connection");
-                        return path;
-                    }
-
-                    if (!existingTargets.some(target =>
-                        target.modelUUID === newTarget.modelUUID &&
-                        target.pointUUID === newTarget.pointUUID
-                    )) {
-                        return {
-                            ...path,
-                            points: {
-                                ...path.points,
-                                connections: {
-                                    ...path.points.connections,
-                                    targets: [...existingTargets, newTarget]
-                                }
-                            }
-                        };
-                    }
-                }
-
-                // Handle incoming connections to StaticMachine
-                else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
-                    const reverseTarget = {
-                        modelUUID: fromModelUUID,
-                        pointUUID: fromPointUUID
-                    };
-
-                    const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID);
-                    if (fromPath?.type !== 'ArmBot') {
-                        console.log("StaticMachine can only be connected from ArmBot");
-                        return path;
-                    }
-
-                    const existingTargets = path.points.connections.targets || [];
-
-                    if (existingTargets.length >= 1) {
-                        console.log("StaticMachine can only have one connection");
-                        return path;
-                    }
-
-                    if (!existingTargets.some(target =>
-                        target.modelUUID === reverseTarget.modelUUID &&
-                        target.pointUUID === reverseTarget.pointUUID
-                    )) {
-                        return {
-                            ...path,
-                            points: {
-                                ...path.points,
-                                connections: {
-                                    ...path.points.connections,
-                                    targets: [...existingTargets, reverseTarget]
-                                }
-                            }
-                        };
-                    }
-                }
-                return path;
-            }
-            else if (path.type === 'ArmBot') {
-                // Handle outgoing connections from ArmBot
-                if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
-                    const newTarget = {
-                        modelUUID: toModelUUID,
-                        pointUUID: toPointUUID
-                    };
-
-                    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';
-                    });
-
-                    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
-                    )) {
-                        return {
-                            ...path,
-                            points: {
-                                ...path.points,
-                                connections: {
-                                    ...path.points.connections,
-                                    targets: [...existingTargets, newTarget]
-                                }
-                            }
-                        };
-                    }
-                }
-
-                // Handle incoming connections to ArmBot
-                else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
-                    const reverseTarget = {
-                        modelUUID: fromModelUUID,
-                        pointUUID: fromPointUUID
-                    };
-
-                    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';
-                    });
-
-                    if (fromPath.type === 'StaticMachine') {
-                        if (alreadyConnectedFromStatic) {
-                            console.log("ArmBot can only be connected from one StaticMachine");
-                            return path;
-                        }
-                    }
-
-                    if (!existingTargets.some(target =>
-                        target.modelUUID === reverseTarget.modelUUID &&
-                        target.pointUUID === reverseTarget.pointUUID
-                    )) {
-                        return {
-                            ...path,
-                            points: {
-                                ...path.points,
-                                connections: {
-                                    ...path.points.connections,
-                                    targets: [...existingTargets, reverseTarget]
-                                }
-                            }
-                        };
-                    }
-                }
-                return path;
-            }
+              }
+              return point;
+            }),
+          };
+        }
+      } else if (path.type === "Vehicle") {
+        // Handle outgoing connections from Vehicle
+        if (
+          path.modeluuid === fromModelUUID &&
+          path.points.uuid === fromPointUUID
+        ) {
+          const newTarget = {
+            modelUUID: toModelUUID,
+            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") {
+            console.log("Vehicle can only connect to Conveyors");
             return path;
-        });
+          }
 
-        setSimulationStates(updatedPaths);
+          // Check if already has a connection
+          if (existingTargets.length >= 1) {
+            console.log("Vehicle can have only one connection");
+            return path;
+          }
 
-        const updatedPathDetails = updatedPaths.filter(path =>
-            path.modeluuid === fromModelUUID || path.modeluuid === toModelUUID
-        );
+          if (
+            !existingTargets.some(
+              (target) =>
+                target.modelUUID === newTarget.modelUUID &&
+                target.pointUUID === newTarget.pointUUID
+            )
+          ) {
+            return {
+              ...path,
+              points: {
+                ...path.points,
+                connections: {
+                  ...path.points.connections,
+                  targets: [...existingTargets, newTarget],
+                },
+              },
+            };
+          }
+        }
+        // Handle incoming connections to Vehicle
+        else if (
+          path.modeluuid === toModelUUID &&
+          path.points.uuid === toPointUUID
+        ) {
+          const reverseTarget = {
+            modelUUID: fromModelUUID,
+            pointUUID: fromPointUUID,
+          };
+          const existingTargets = path.points.connections.targets || [];
 
-        updateBackend(updatedPathDetails);
+          // Check if source is a Conveyor
+          const fromPath = simulationStates.find(
+            (p) => p.modeluuid === fromModelUUID
+          );
+          if (fromPath?.type !== "Conveyor") {
+            console.log("Vehicle can only connect to Conveyors");
+            return path;
+          }
+
+          // Check if already has a connection
+          if (existingTargets.length >= 1) {
+            console.log("Vehicle can have only one connection");
+            return path;
+          }
+
+          if (
+            !existingTargets.some(
+              (target) =>
+                target.modelUUID === reverseTarget.modelUUID &&
+                target.pointUUID === reverseTarget.pointUUID
+            )
+          ) {
+            return {
+              ...path,
+              points: {
+                ...path.points,
+                connections: {
+                  ...path.points.connections,
+                  targets: [...existingTargets, reverseTarget],
+                },
+              },
+            };
+          }
+        }
+        return path;
+      } else if (path.type === "StaticMachine") {
+        // Handle outgoing connections from StaticMachine
+        if (
+          path.modeluuid === fromModelUUID &&
+          path.points.uuid === fromPointUUID
+        ) {
+          const newTarget = {
+            modelUUID: toModelUUID,
+            pointUUID: toPointUUID,
+          };
+
+          // Ensure target is an ArmBot
+          const toPath = simulationStates.find(
+            (p) => p.modeluuid === toModelUUID
+          );
+          if (toPath?.type !== "ArmBot") {
+            console.log("StaticMachine can only connect to ArmBot");
+            return path;
+          }
+
+          const existingTargets = path.points.connections.targets || [];
+
+          // Allow only one connection
+          if (existingTargets.length >= 1) {
+            console.log("StaticMachine can only have one connection");
+            return path;
+          }
+
+          if (
+            !existingTargets.some(
+              (target) =>
+                target.modelUUID === newTarget.modelUUID &&
+                target.pointUUID === newTarget.pointUUID
+            )
+          ) {
+            return {
+              ...path,
+              points: {
+                ...path.points,
+                connections: {
+                  ...path.points.connections,
+                  targets: [...existingTargets, newTarget],
+                },
+              },
+            };
+          }
+        }
+
+        // Handle incoming connections to StaticMachine
+        else if (
+          path.modeluuid === toModelUUID &&
+          path.points.uuid === toPointUUID
+        ) {
+          const reverseTarget = {
+            modelUUID: fromModelUUID,
+            pointUUID: fromPointUUID,
+          };
+
+          const fromPath = simulationStates.find(
+            (p) => p.modeluuid === fromModelUUID
+          );
+          if (fromPath?.type !== "ArmBot") {
+            console.log("StaticMachine can only be connected from ArmBot");
+            return path;
+          }
+
+          const existingTargets = path.points.connections.targets || [];
+
+          if (existingTargets.length >= 1) {
+            console.log("StaticMachine can only have one connection");
+            return path;
+          }
+
+          if (
+            !existingTargets.some(
+              (target) =>
+                target.modelUUID === reverseTarget.modelUUID &&
+                target.pointUUID === reverseTarget.pointUUID
+            )
+          ) {
+            return {
+              ...path,
+              points: {
+                ...path.points,
+                connections: {
+                  ...path.points.connections,
+                  targets: [...existingTargets, reverseTarget],
+                },
+              },
+            };
+          }
+        }
+        return path;
+      } else if (path.type === "ArmBot") {
+        // Handle outgoing connections from ArmBot
+        if (
+          path.modeluuid === fromModelUUID &&
+          path.points.uuid === fromPointUUID
+        ) {
+          const newTarget = {
+            modelUUID: toModelUUID,
+            pointUUID: toPointUUID,
+          };
+
+          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";
+          });
+
+          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
+            )
+          ) {
+            return {
+              ...path,
+              points: {
+                ...path.points,
+                connections: {
+                  ...path.points.connections,
+                  targets: [...existingTargets, newTarget],
+                },
+              },
+            };
+          }
+        }
+
+        // Handle incoming connections to ArmBot
+        else if (
+          path.modeluuid === toModelUUID &&
+          path.points.uuid === toPointUUID
+        ) {
+          const reverseTarget = {
+            modelUUID: fromModelUUID,
+            pointUUID: fromPointUUID,
+          };
+
+          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";
+          });
+
+          if (fromPath.type === "StaticMachine") {
+            if (alreadyConnectedFromStatic) {
+              console.log(
+                "ArmBot can only be connected from one StaticMachine"
+              );
+              return path;
+            }
+          }
+
+          if (
+            !existingTargets.some(
+              (target) =>
+                target.modelUUID === reverseTarget.modelUUID &&
+                target.pointUUID === reverseTarget.pointUUID
+            )
+          ) {
+            return {
+              ...path,
+              points: {
+                ...path.points,
+                connections: {
+                  ...path.points.connections,
+                  targets: [...existingTargets, reverseTarget],
+                },
+              },
+            };
+          }
+        }
+        return path;
+      }
+
+      return path;
+    });
+
+    setSimulationStates(updatedPaths);
+
+    const updatedPathDetails = updatedPaths.filter(
+      (path) =>
+        path.modeluuid === fromModelUUID || path.modeluuid === toModelUUID
+    );
+
+    updateBackend(updatedPathDetails);
+  };
+
+  const updateBackend = async (
+    updatedPaths: (
+      | Types.ConveyorEventsSchema
+      | Types.VehicleEventsSchema
+      | Types.StaticMachineEventsSchema
+      | Types.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,
+        //   updatedPath.modeluuid,
+        //   { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
+        // );
+
+        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") {
+        // await setEventApi(
+        //     organization,
+        //     updatedPath.modeluuid,
+        //     { type: "Vehicle", points: updatedPath.points }
+        // );
+
+        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") {
+        // await setEventApi(
+        //     organization,
+        //     updatedPath.modeluuid,
+        //     { type: "StaticMachine", points: updatedPath.points }
+        // );
+
+        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") {
+        // await setEventApi(
+        //     organization,
+        //     updatedPath.modeluuid,
+        //     { type: "ArmBot", points: updatedPath.points }
+        // );
+
+        const data = {
+          organization: organization,
+          modeluuid: updatedPath.modeluuid,
+          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);
+    setFirstSelected(null);
+    setCurrentLine(null);
+    setIsConnecting(false);
+  };
+
+  useEffect(() => {
+    const canvasElement = gl.domElement;
+    let drag = false;
+    let MouseDown = false;
+
+    const onMouseDown = () => {
+      MouseDown = true;
+      drag = false;
     };
 
-    const updateBackend = async (updatedPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => {
-        if (updatedPaths.length === 0) return;
-        const email = localStorage.getItem("email");
-        const organization = email ? email.split("@")[1].split(".")[0] : "";
+    const onMouseUp = () => {
+      MouseDown = false;
+    };
 
-        updatedPaths.forEach(async (updatedPath) => {
-            if (updatedPath.type === 'Conveyor') {
+    const onMouseMove = () => {
+      if (MouseDown) {
+        drag = true;
+      }
+    };
 
-                // await setEventApi(
-                //   organization,
-                //   updatedPath.modeluuid,
-                //   { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
-                // );
+    const onContextMenu = (evt: MouseEvent) => {
+      evt.preventDefault();
+      if (drag || evt.button === 0) return;
 
-                const data = {
-                    organization: organization,
-                    modeluuid: updatedPath.modeluuid,
-                    eventData: { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
-                }
+      raycaster.setFromCamera(pointer, camera);
+      const intersects = raycaster.intersectObjects(
+        pathsGroupRef.current.children,
+        true
+      );
 
-                socket.emit('v2:model-asset:updateEventData', data);
+      if (intersects.length > 0) {
+        const intersected = intersects[0].object;
 
-            } else if (updatedPath.type === 'Vehicle') {
+        if (intersected.name.includes("events-sphere")) {
+          const modelUUID = intersected.userData.path.modeluuid;
+          const sphereUUID = intersected.uuid;
+          const worldPosition = new THREE.Vector3();
+          intersected.getWorldPosition(worldPosition);
 
-                // await setEventApi(
-                //     organization,
-                //     updatedPath.modeluuid,
-                //     { type: "Vehicle", points: updatedPath.points }
-                // );
+          let isStartOrEnd = false;
 
-                const data = {
-                    organization: organization,
-                    modeluuid: updatedPath.modeluuid,
-                    eventData: { type: "Vehicle", points: updatedPath.points }
-                }
+          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);
+          } else if (intersected.userData.path.points) {
+            isStartOrEnd = sphereUUID === intersected.userData.path.points.uuid;
+          }
 
-                socket.emit('v2:model-asset:updateEventData', data);
-
-            } else if (updatedPath.type === 'StaticMachine') {
-
-                // await setEventApi(
-                //     organization,
-                //     updatedPath.modeluuid,
-                //     { type: "StaticMachine", points: updatedPath.points }
-                // );
-
-                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') {
-
-                // await setEventApi(
-                //     organization,
-                //     updatedPath.modeluuid,
-                //     { type: "ArmBot", points: updatedPath.points }
-                // );
-
-                const data = {
-                    organization: organization,
-                    modeluuid: updatedPath.modeluuid,
-                    eventData: { type: "ArmBot", points: updatedPath.points }
-                }
-
-                socket.emit('v2:model-asset:updateEventData', data);
+          if (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"
+            ) {
+              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)
+            ) {
+              console.log(
+                "Conveyor connections must be between start/end points"
+              );
+              return;
+            }
 
-    const handleAddConnection = (fromModelUUID: string, fromUUID: string, toModelUUID: string, toUUID: string) => {
-        updatePathConnections(fromModelUUID, fromUUID, toModelUUID, toUUID);
+            // Check if this specific connection already exists
+            const isDuplicateConnection = firstSelected
+              ? 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
+                      );
+                    } else if (path.type === "Vehicle") {
+                      return path.points.connections.targets.some(
+                        (t) =>
+                          t.modelUUID === modelUUID &&
+                          t.pointUUID === sphereUUID
+                      );
+                    }
+                  }
+                  return false;
+                })
+              : false;
+
+            if (isDuplicateConnection) {
+              console.log("These points are already connected. Ignoring.");
+              return;
+            }
+
+            // 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 (vehicleConnections >= 1) {
+                console.log("Vehicle can only have one connection");
+                return;
+              }
+            }
+
+            // 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
+                  );
+                }
+                return false;
+              });
+
+              if (isAlreadyConnected) {
+                console.log("Conveyor point is already connected. Ignoring.");
+                return;
+              }
+            }
+
+            if (firstSelected) {
+              // Check if trying to connect Vehicle to non-Conveyor
+              if (
+                (firstPath?.type === "Vehicle" &&
+                  secondPath?.type !== "Conveyor") ||
+                (secondPath?.type === "Vehicle" &&
+                  firstPath?.type !== "Conveyor")
+              ) {
+                console.log("Vehicle can only connect to Conveyors");
+                return;
+              }
+
+              // Prevent same-path connections
+              if (firstSelected.modelUUID === modelUUID) {
+                console.log("Cannot connect spheres on the same path.");
+                return;
+              }
+
+              // Check if StaticMachine is involved in the connection
+              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") {
+                const staticConnections =
+                  firstPath.points.connections.targets.length;
+                if (staticConnections >= 1) {
+                  console.log("StaticMachine can only have one connection");
+                  return;
+                }
+              }
+              if (secondPath?.type === "StaticMachine") {
+                const staticConnections =
+                  secondPath.points.connections.targets.length;
+                if (staticConnections >= 1) {
+                  console.log("StaticMachine can only have one connection");
+                  return;
+                }
+              }
+
+              // 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;
+
+                const armBotConnections =
+                  armBotPath.points.connections.targets || [];
+                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");
+                  return;
+                }
+
+                const staticConnections =
+                  staticPath.points.connections.targets.length;
+                if (staticConnections >= 1) {
+                  console.log("StaticMachine can only have one connection");
+                  return;
+                }
+              }
+
+              // Prevent ArmBot ↔ 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") {
+                  console.log(
+                    "ArmBot can only connect to Conveyors or one StaticMachine"
+                  );
+                  return;
+                }
+              }
+
+              // At least one must be start/end point
+              if (!firstSelected.isCorner && !isStartOrEnd) {
+                console.log(
+                  "At least one of the selected spheres must be a start or end point."
+                );
+                return;
+              }
+
+              // All checks passed - make the connection
+              handleAddConnection(
+                firstSelected.modelUUID,
+                firstSelected.sphereUUID,
+                modelUUID,
+                sphereUUID
+              );
+            } else {
+              // First selection - just store it
+              setFirstSelected({
+                modelUUID,
+                sphereUUID,
+                position: worldPosition,
+                isCorner: isStartOrEnd,
+              });
+              setIsConnecting(true);
+            }
+          }
+        }
+      } else {
+        // Clicked outside - cancel connection
         setFirstSelected(null);
         setCurrentLine(null);
         setIsConnecting(false);
+      }
     };
 
-    useEffect(() => {
-        const canvasElement = gl.domElement;
-        let drag = false;
-        let MouseDown = false;
+    if (activeModule === "simulation" && !deleteTool) {
+      canvasElement.addEventListener("mousedown", onMouseDown);
+      canvasElement.addEventListener("mouseup", onMouseUp);
+      canvasElement.addEventListener("mousemove", onMouseMove);
+      canvasElement.addEventListener("contextmenu", onContextMenu);
+    } else {
+      setFirstSelected(null);
+      setCurrentLine(null);
+      setIsConnecting(false);
+    }
 
-        const onMouseDown = () => {
-            MouseDown = true;
-            drag = false;
-        };
+    return () => {
+      canvasElement.removeEventListener("mousedown", onMouseDown);
+      canvasElement.removeEventListener("mouseup", onMouseUp);
+      canvasElement.removeEventListener("mousemove", onMouseMove);
+      canvasElement.removeEventListener("contextmenu", onContextMenu);
+    };
+  }, [camera, scene, raycaster, firstSelected, simulationStates, deleteTool]);
 
-        const onMouseUp = () => {
-            MouseDown = false;
-        };
-
-        const onMouseMove = () => {
-            if (MouseDown) {
-                drag = true;
-            }
-        };
-
-        const onContextMenu = (evt: MouseEvent) => {
-            evt.preventDefault();
-            if (drag || evt.button === 0) return;
-
-            raycaster.setFromCamera(pointer, camera);
-            const intersects = raycaster.intersectObjects(pathsGroupRef.current.children, true);
-
-            if (intersects.length > 0) {
-                const intersected = intersects[0].object;
-
-                if (intersected.name.includes("events-sphere")) {
-                    const modelUUID = intersected.userData.path.modeluuid;
-                    const sphereUUID = intersected.uuid;
-                    const worldPosition = new THREE.Vector3();
-                    intersected.getWorldPosition(worldPosition);
-
-                    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
-                        );
-                    } 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);
-
-                        // Prevent vehicle-to-vehicle connections
-                        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)) {
-                            console.log("Conveyor connections must be between start/end points");
-                            return;
-                        }
-
-                        // Check if this specific connection already exists
-                        const isDuplicateConnection = firstSelected
-                            ? 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
-                                        );
-                                    } else if (path.type === 'Vehicle') {
-                                        return path.points.connections.targets.some(t =>
-                                            t.modelUUID === modelUUID && t.pointUUID === sphereUUID
-                                        );
-                                    }
-                                }
-                                return false;
-                            })
-                            : false;
-
-                        if (isDuplicateConnection) {
-                            console.log("These points are already connected. Ignoring.");
-                            return;
-                        }
-
-                        // 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 (vehicleConnections >= 1) {
-                                console.log("Vehicle can only have one connection");
-                                return;
-                            }
-                        }
-
-                        // 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
-                                    );
-                                }
-                                return false;
-                            });
-
-                            if (isAlreadyConnected) {
-                                console.log("Conveyor point is already connected. Ignoring.");
-                                return;
-                            }
-                        }
-
-                        if (firstSelected) {
-                            // Check if trying to connect Vehicle to non-Conveyor
-                            if ((firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
-                                (secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor')) {
-                                console.log("Vehicle can only connect to Conveyors");
-                                return;
-                            }
-
-                            // Prevent same-path connections
-                            if (firstSelected.modelUUID === modelUUID) {
-                                console.log("Cannot connect spheres on the same path.");
-                                return;
-                            }
-
-                            // Check if StaticMachine is involved in the connection
-                            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') {
-                                const staticConnections = firstPath.points.connections.targets.length;
-                                if (staticConnections >= 1) {
-                                    console.log("StaticMachine can only have one connection");
-                                    return;
-                                }
-                            }
-                            if (secondPath?.type === 'StaticMachine') {
-                                const staticConnections = secondPath.points.connections.targets.length;
-                                if (staticConnections >= 1) {
-                                    console.log("StaticMachine can only have one connection");
-                                    return;
-                                }
-                            }
-
-                            // 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;
-
-                                const armBotConnections = armBotPath.points.connections.targets || [];
-                                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");
-                                    return;
-                                }
-
-                                const staticConnections = staticPath.points.connections.targets.length;
-                                if (staticConnections >= 1) {
-                                    console.log("StaticMachine can only have one connection");
-                                    return;
-                                }
-                            }
-
-                            // Prevent ArmBot ↔ 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') {
-                                    console.log("ArmBot can only connect to Conveyors or one StaticMachine");
-                                    return;
-                                }
-                            }
-
-                            // At least one must be start/end point
-                            if (!firstSelected.isCorner && !isStartOrEnd) {
-                                console.log("At least one of the selected spheres must be a start or end point.");
-                                return;
-                            }
-
-                            // All checks passed - make the connection
-                            handleAddConnection(firstSelected.modelUUID, firstSelected.sphereUUID, modelUUID, sphereUUID);
-                        } else {
-                            // First selection - just store it
-                            setFirstSelected({ modelUUID, sphereUUID, position: worldPosition, isCorner: isStartOrEnd });
-                            setIsConnecting(true);
-                        }
-                    }
-                }
-            } else {
-                // Clicked outside - cancel connection
-                setFirstSelected(null);
-                setCurrentLine(null);
-                setIsConnecting(false);
-            }
-        };
-
-        if (activeModule === 'simulation' && !deleteTool) {
-            canvasElement.addEventListener("mousedown", onMouseDown);
-            canvasElement.addEventListener("mouseup", onMouseUp);
-            canvasElement.addEventListener("mousemove", onMouseMove);
-            canvasElement.addEventListener("contextmenu", onContextMenu);
-        } else {
-            setFirstSelected(null);
-            setCurrentLine(null);
-            setIsConnecting(false);
-        }
-
-        return () => {
-            canvasElement.removeEventListener("mousedown", onMouseDown);
-            canvasElement.removeEventListener("mouseup", onMouseUp);
-            canvasElement.removeEventListener("mousemove", onMouseMove);
-            canvasElement.removeEventListener("contextmenu", onContextMenu);
-        };
-    }, [camera, scene, raycaster, firstSelected, simulationStates, deleteTool]);
-
-    useFrame(() => {
-        Object.values(groupRefs.current).forEach((group) => {
-            if (group) {
-                const distance = new THREE.Vector3(...group.position.toArray()).distanceTo(camera.position);
-                group.visible = ((distance <= renderDistance) && !isPlaying);
-            }
-        });
+  useFrame(() => {
+    Object.values(groupRefs.current).forEach((group) => {
+      if (group) {
+        const distance = new THREE.Vector3(
+          ...group.position.toArray()
+        ).distanceTo(camera.position);
+        group.visible = distance <= renderDistance && !isPlaying;
+      }
     });
+  });
 
-    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")
-            );
-
-            let point: THREE.Vector3 | null = null;
-            let snappedSphere: { sphereUUID: string, position: THREE.Vector3, modelUUID: string, isCorner: boolean } | null = null;
-            let isInvalidConnection = false;
-
-            if (intersects.length > 0) {
-                point = intersects[0].point;
-                if (point.y < 0.05) {
-                    point = new THREE.Vector3(point.x, 0.05, point.z);
-                }
-            }
-
-            const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) => obj.object.name.includes("events-sphere"));
-
-            if (sphereIntersects.length > 0) {
-                const sphere = sphereIntersects[0].object;
-                const sphereUUID = sphere.uuid;
-                const spherePosition = new THREE.Vector3();
-                sphere.getWorldPosition(spherePosition);
-                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';
-
-                // Inside the useFrame hook, where we check for snapped spheres:
-                const isConnectable = (
-                    pathData.type === 'Vehicle' ||
-                    pathData.type === 'ArmBot' ||
-                    (pathData.points.length > 0 && (
-                        sphereUUID === pathData.points[0].uuid ||
-                        sphereUUID === pathData.points[pathData.points.length - 1].uuid ||
-                        (pathData.type === 'Conveyor' && firstPath?.type === 'ArmBot')  // Allow ArmBot to connect to middle points
-                    ))
-                ) &&
-                    !isVehicleToVehicle &&
-                    !(
-                        firstPath?.type === 'Conveyor' &&
-                        pathData.type === 'Conveyor' &&
-                        !firstSelected.isCorner
-                    );
-
-                // Check for duplicate connection (regardless of path type)
-                const isDuplicateConnection = 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
-                            );
-                        } else if (path.type === 'Vehicle') {
-                            return path.points.connections.targets.some(t =>
-                                t.modelUUID === modelUUID && t.pointUUID === sphereUUID
-                            );
-                        }
-                    }
-                    return false;
-                });
-
-                // For non-Vehicle paths, check if already connected
-                const isNonVehicleAlreadyConnected = pathData.type !== 'Vehicle' &&
-                    simulationStates.some(path => {
-                        if (path.type === 'Conveyor') {
-                            return path.points.some(point =>
-                                point.uuid === sphereUUID &&
-                                point.connections.targets.length > 0
-                            );
-                        }
-                        return false;
-                    });
-
-                // Check vehicle connection rules
-                const isVehicleAtMaxConnections = pathData.type === 'Vehicle' &&
-                    pathData.points.connections.targets.length >= 1;
-                const isVehicleConnectingToNonConveyor =
-                    (firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
-                    (secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor');
-
-                // Check if StaticMachine is connecting to non-ArmBot
-                const isStaticMachineToNonArmBot =
-                    (firstPath?.type === 'StaticMachine' && secondPath?.type !== 'ArmBot') ||
-                    (secondPath?.type === 'StaticMachine' && firstPath?.type !== 'ArmBot');
-
-                // Check if StaticMachine already has a connection
-                const isStaticMachineAtMaxConnections =
-                    (firstPath?.type === 'StaticMachine' && firstPath.points.connections.targets.length >= 1) ||
-                    (secondPath?.type === 'StaticMachine' && secondPath.points.connections.targets.length >= 1);
-
-                // Check if ArmBot is connecting to StaticMachine
-                const isArmBotToStaticMachine =
-                    (firstPath?.type === 'ArmBot' && secondPath?.type === 'StaticMachine') ||
-                    (secondPath?.type === 'ArmBot' && firstPath?.type === 'StaticMachine');
-
-                // Prevent multiple StaticMachine connections to ArmBot
-                let isArmBotAlreadyConnectedToStatic = false;
-                if (isArmBotToStaticMachine) {
-                    const armBotPath = firstPath?.type === 'ArmBot' ? firstPath : secondPath;
-                    isArmBotAlreadyConnectedToStatic = armBotPath.points.connections.targets.some(target => {
-                        const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
-                        return targetPath?.type === 'StaticMachine';
-                    });
-                }
-
-                // Prevent ArmBot to ArmBot
-                const isArmBotToArmBot = firstPath?.type === 'ArmBot' && secondPath?.type === 'ArmBot';
-
-                // If ArmBot is involved, other must be Conveyor or StaticMachine
-                const isArmBotToInvalidType = (firstPath?.type === 'ArmBot' || secondPath?.type === 'ArmBot') &&
-                    !(firstPath?.type === 'Conveyor' || firstPath?.type === 'StaticMachine' ||
-                        secondPath?.type === 'Conveyor' || secondPath?.type === 'StaticMachine');
-
-                if (
-                    !isDuplicateConnection &&
-                    !isVehicleToVehicle &&
-                    !isNonVehicleAlreadyConnected &&
-                    !isVehicleAtMaxConnections &&
-                    !isVehicleConnectingToNonConveyor &&
-                    !isStaticMachineToNonArmBot &&
-                    !isStaticMachineAtMaxConnections &&
-                    !isArmBotToArmBot &&
-                    !isArmBotToInvalidType &&
-                    !isArmBotAlreadyConnectedToStatic &&
-                    firstSelected.sphereUUID !== sphereUUID &&
-                    firstSelected.modelUUID !== modelUUID &&
-                    (firstSelected.isCorner || isConnectable) &&
-                    !(firstPath?.type === 'Conveyor' &&
-                        pathData.type === 'Conveyor' &&
-                        !(firstSelected.isCorner && isConnectable))
-                ) {
-                    snappedSphere = {
-                        sphereUUID,
-                        position: spherePosition,
-                        modelUUID,
-                        isCorner: isConnectable
-                    };
-                } else {
-                    isInvalidConnection = true;
-                }
-
-            }
-
-            if (snappedSphere) {
-                point = snappedSphere.position;
-            }
-
-            if (point) {
-                const distance = firstSelected.position.distanceTo(point);
-                const heightFactor = Math.max(0.5, distance * 0.2);
-                const midPoint = new THREE.Vector3(
-                    (firstSelected.position.x + point.x) / 2,
-                    Math.max(firstSelected.position.y, point.y) + heightFactor,
-                    (firstSelected.position.z + point.z) / 2
-                );
-
-                setCurrentLine({
-                    start: firstSelected.position,
-                    end: point,
-                    mid: midPoint,
-                });
-
-                if (sphereIntersects.length > 0) {
-                    setHelperLineColor(isInvalidConnection ? 'red' : '#6cf542');
-                } else {
-                    setHelperLineColor('yellow');
-                }
-            } else {
-                setCurrentLine(null);
-                setIsConnecting(false);
-            }
-        } else {
-            setCurrentLine(null);
-            setIsConnecting(false);
-        }
-    });
-
-    const removeConnections = (connection1: { model: string; point: string }, connection2: { model: string; point: string }) => {
-        const updatedStates = simulationStates.map(state => {
-            // Handle Conveyor (which has multiple points)
-            if (state.type === 'Conveyor') {
-                const updatedConveyor: Types.ConveyorEventsSchema = {
-                    ...state,
-                    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)) {
-
-                            return {
-                                ...point,
-                                connections: {
-                                    ...point.connections,
-                                    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)
-                                        );
-                                    })
-                                }
-                            };
-                        }
-                        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)) {
-
-                    const updatedVehicle: Types.VehicleEventsSchema = {
-                        ...state,
-                        points: {
-                            ...state.points,
-                            connections: {
-                                ...state.points.connections,
-                                targets: state.points.connections.targets.filter(target => {
-                                    return !(
-                                        (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
-                        }
-                    };
-                    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: Types.StaticMachineEventsSchema = {
-                        ...state,
-                        points: {
-                            ...state.points,
-                            connections: {
-                                ...state.points.connections,
-                                targets: state.points.connections.targets.filter(target => {
-                                    return !(
-                                        (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
-                        }
-                    };
-                    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)) {
-
-                    const updatedArmBot: Types.ArmBotEventsSchema = {
-                        ...state,
-                        points: {
-                            ...state.points,
-                            connections: {
-                                ...state.points.connections,
-                                targets: state.points.connections.targets.filter(target => {
-                                    return !(
-                                        (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
-                                    );
-                                }) || []
-                            },
-                            triggers: state.points.triggers
-                        }
-                    };
-                    return updatedArmBot;
-                }
-            }
-            return state;
-        });
-
-        const updatedPaths = updatedStates.filter(state =>
-            state.modeluuid === connection1.model || state.modeluuid === connection2.model
+  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")
         );
 
-        updateBackend(updatedPaths);
+      let point: THREE.Vector3 | null = null;
+      let snappedSphere: {
+        sphereUUID: string;
+        position: THREE.Vector3;
+        modelUUID: string;
+        isCorner: boolean;
+      } | null = null;
+      let isInvalidConnection = false;
 
-        setSimulationStates(updatedStates);
-    };
+      if (intersects.length > 0) {
+        point = intersects[0].point;
+        if (point.y < 0.05) {
+          point = new THREE.Vector3(point.x, 0.05, point.z);
+        }
+      }
 
+      const sphereIntersects = raycaster
+        .intersectObjects(pathsGroupRef.current.children, true)
+        .filter((obj) => obj.object.name.includes("events-sphere"));
 
-    return (
-        <group name='simulationConnectionGroup' visible={!isPlaying}>
-            {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;
+      if (sphereIntersects.length > 0) {
+        const sphere = sphereIntersects[0].object;
+        const sphereUUID = sphere.uuid;
+        const spherePosition = new THREE.Vector3();
+        sphere.getWorldPosition(spherePosition);
+        const pathData = sphere.userData.path;
+        const modelUUID = pathData.modeluuid;
 
-                            const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid);
-                            const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
+        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";
 
-                            if (fromSphere && toSphere) {
-                                const fromWorldPosition = new THREE.Vector3();
-                                const toWorldPosition = new THREE.Vector3();
-                                fromSphere.getWorldPosition(fromWorldPosition);
-                                toSphere.getWorldPosition(toWorldPosition);
+        // Inside the useFrame hook, where we check for snapped spheres:
+        const isConnectable =
+          (pathData.type === "Vehicle" ||
+            pathData.type === "ArmBot" ||
+            (pathData.points.length > 0 &&
+              (sphereUUID === pathData.points[0].uuid ||
+                sphereUUID ===
+                  pathData.points[pathData.points.length - 1].uuid ||
+                (pathData.type === "Conveyor" &&
+                  firstPath?.type === "ArmBot")))) && // Allow ArmBot to connect to middle points
+          !isVehicleToVehicle &&
+          !(
+            firstPath?.type === "Conveyor" &&
+            pathData.type === "Conveyor" &&
+            !firstSelected.isCorner
+          );
 
-                                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);
+        // Check for duplicate connection (regardless of path type)
+        const isDuplicateConnection = 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
+              );
+            } else if (path.type === "Vehicle") {
+              return path.points.connections.targets.some(
+                (t) => t.modelUUID === modelUUID && t.pointUUID === sphereUUID
+              );
+            }
+          }
+          return false;
+        });
 
-                                return (
-                                    <QuadraticBezierLine
-                                        key={`${point.uuid}-${target.pointUUID}-${index}`}
-                                        ref={(el) => (groupRefs.current[`${point.uuid}-${target.pointUUID}-${index}`] = el!)}
-                                        start={fromWorldPosition.toArray()}
-                                        end={toWorldPosition.toArray()}
-                                        mid={midPoint.toArray()}
-                                        color={
-                                            deleteTool && hoveredLineKey === `${point.uuid}-${target.pointUUID}-${index}`
-                                                ? 'red'
-                                                : targetPath?.type === 'ArmBot'
-                                                    ? '#42a5f5'
-                                                    : 'white'
-                                        }
-                                        lineWidth={4}
-                                        dashed={(deleteTool && hoveredLineKey === `${point.uuid}-${target.pointUUID}-${index}`) ? false : true}
-                                        dashSize={0.75}
-                                        dashScale={20}
-                                        onPointerOver={() => setHoveredLineKey(`${point.uuid}-${target.pointUUID}-${index}`)}
-                                        onPointerOut={() => setHoveredLineKey(null)}
-                                        onClick={() => {
-                                            if (deleteTool) {
+        // For non-Vehicle paths, check if already connected
+        const isNonVehicleAlreadyConnected =
+          pathData.type !== "Vehicle" &&
+          simulationStates.some((path) => {
+            if (path.type === "Conveyor") {
+              return path.points.some(
+                (point) =>
+                  point.uuid === sphereUUID &&
+                  point.connections.targets.length > 0
+              );
+            }
+            return false;
+          });
 
-                                                const connection1 = { model: path.modeluuid, point: point.uuid }
-                                                const connection2 = { model: target.modelUUID, point: target.pointUUID }
+        // Check vehicle connection rules
+        const isVehicleAtMaxConnections =
+          pathData.type === "Vehicle" &&
+          pathData.points.connections.targets.length >= 1;
+        const isVehicleConnectingToNonConveyor =
+          (firstPath?.type === "Vehicle" && secondPath?.type !== "Conveyor") ||
+          (secondPath?.type === "Vehicle" && firstPath?.type !== "Conveyor");
 
-                                                removeConnections(connection1, connection2)
+        // Check if StaticMachine is connecting to non-ArmBot
+        const isStaticMachineToNonArmBot =
+          (firstPath?.type === "StaticMachine" &&
+            secondPath?.type !== "ArmBot") ||
+          (secondPath?.type === "StaticMachine" &&
+            firstPath?.type !== "ArmBot");
 
-                                            }
-                                        }}
-                                        userData={target}
-                                    />
-                                );
-                            }
-                            return null;
-                        })
+        // Check if StaticMachine already has a connection
+        const isStaticMachineAtMaxConnections =
+          (firstPath?.type === "StaticMachine" &&
+            firstPath.points.connections.targets.length >= 1) ||
+          (secondPath?.type === "StaticMachine" &&
+            secondPath.points.connections.targets.length >= 1);
+
+        // Check if ArmBot is connecting to StaticMachine
+        const isArmBotToStaticMachine =
+          (firstPath?.type === "ArmBot" &&
+            secondPath?.type === "StaticMachine") ||
+          (secondPath?.type === "ArmBot" &&
+            firstPath?.type === "StaticMachine");
+
+        // Prevent multiple StaticMachine connections to ArmBot
+        let isArmBotAlreadyConnectedToStatic = false;
+        if (isArmBotToStaticMachine) {
+          const armBotPath =
+            firstPath?.type === "ArmBot" ? firstPath : secondPath;
+          isArmBotAlreadyConnectedToStatic =
+            armBotPath.points.connections.targets.some((target) => {
+              const targetPath = simulationStates.find(
+                (p) => p.modeluuid === target.modelUUID
+              );
+              return targetPath?.type === "StaticMachine";
+            });
+        }
+
+        // Prevent ArmBot to ArmBot
+        const isArmBotToArmBot =
+          firstPath?.type === "ArmBot" && secondPath?.type === "ArmBot";
+
+        // If ArmBot is involved, other must be Conveyor or StaticMachine
+        const isArmBotToInvalidType =
+          (firstPath?.type === "ArmBot" || secondPath?.type === "ArmBot") &&
+          !(
+            firstPath?.type === "Conveyor" ||
+            firstPath?.type === "StaticMachine" ||
+            secondPath?.type === "Conveyor" ||
+            secondPath?.type === "StaticMachine"
+          );
+
+        if (
+          !isDuplicateConnection &&
+          !isVehicleToVehicle &&
+          !isNonVehicleAlreadyConnected &&
+          !isVehicleAtMaxConnections &&
+          !isVehicleConnectingToNonConveyor &&
+          !isStaticMachineToNonArmBot &&
+          !isStaticMachineAtMaxConnections &&
+          !isArmBotToArmBot &&
+          !isArmBotToInvalidType &&
+          !isArmBotAlreadyConnectedToStatic &&
+          firstSelected.sphereUUID !== sphereUUID &&
+          firstSelected.modelUUID !== modelUUID &&
+          (firstSelected.isCorner || isConnectable) &&
+          !(
+            firstPath?.type === "Conveyor" &&
+            pathData.type === "Conveyor" &&
+            !(firstSelected.isCorner && isConnectable)
+          )
+        ) {
+          snappedSphere = {
+            sphereUUID,
+            position: spherePosition,
+            modelUUID,
+            isCorner: isConnectable,
+          };
+        } else {
+          isInvalidConnection = true;
+        }
+      }
+
+      if (snappedSphere) {
+        point = snappedSphere.position;
+      }
+
+      if (point) {
+        const distance = firstSelected.position.distanceTo(point);
+        const heightFactor = Math.max(0.5, distance * 0.2);
+        const midPoint = new THREE.Vector3(
+          (firstSelected.position.x + point.x) / 2,
+          Math.max(firstSelected.position.y, point.y) + heightFactor,
+          (firstSelected.position.z + point.z) / 2
+        );
+
+        setCurrentLine({
+          start: firstSelected.position,
+          end: point,
+          mid: midPoint,
+        });
+
+        if (sphereIntersects.length > 0) {
+          setHelperLineColor(isInvalidConnection ? "red" : "#6cf542");
+        } else {
+          setHelperLineColor("yellow");
+        }
+      } else {
+        setCurrentLine(null);
+        setIsConnecting(false);
+      }
+    } else {
+      setCurrentLine(null);
+      setIsConnecting(false);
+    }
+  });
+
+  const removeConnections = (
+    connection1: { model: string; point: string },
+    connection2: { model: string; point: string }
+  ) => {
+    const updatedStates = simulationStates.map((state) => {
+      // Handle Conveyor (which has multiple points)
+      if (state.type === "Conveyor") {
+        const updatedConveyor: Types.ConveyorEventsSchema = {
+          ...state,
+          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)
+            ) {
+              return {
+                ...point,
+                connections: {
+                  ...point.connections,
+                  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)
                     );
-                }
+                  }),
+                },
+              };
+            }
+            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)
+        ) {
+          const updatedVehicle: Types.VehicleEventsSchema = {
+            ...state,
+            points: {
+              ...state.points,
+              connections: {
+                ...state.points.connections,
+                targets: state.points.connections.targets.filter((target) => {
+                  return !(
+                    (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,
+            },
+          };
+          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: Types.StaticMachineEventsSchema = {
+            ...state,
+            points: {
+              ...state.points,
+              connections: {
+                ...state.points.connections,
+                targets: state.points.connections.targets.filter((target) => {
+                  return !(
+                    (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,
+            },
+          };
+          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)
+        ) {
+          const updatedArmBot: Types.ArmBotEventsSchema = {
+            ...state,
+            points: {
+              ...state.points,
+              connections: {
+                ...state.points.connections,
+                targets: state.points.connections.targets.filter((target) => {
+                  return !(
+                    (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
+                    );
+                  }) || [],
+              },
+              triggers: state.points.triggers,
+            },
+          };
+          return updatedArmBot;
+        }
+      }
+      return state;
+    });
 
-                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);
-
-                        if (fromSphere && toSphere) {
-                            const fromWorldPosition = new THREE.Vector3();
-                            const toWorldPosition = new THREE.Vector3();
-                            fromSphere.getWorldPosition(fromWorldPosition);
-                            toSphere.getWorldPosition(toWorldPosition);
-
-                            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);
-
-                            return (
-                                <QuadraticBezierLine
-                                    key={`${path.points.uuid}-${target.pointUUID}-${index}`}
-                                    ref={(el) => (groupRefs.current[`${path.points.uuid}-${target.pointUUID}-${index}`] = el!)}
-                                    start={fromWorldPosition.toArray()}
-                                    end={toWorldPosition.toArray()}
-                                    mid={midPoint.toArray()}
-                                    color={
-                                        deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`
-                                            ? 'red'
-                                            : 'orange'
-                                    }
-                                    lineWidth={4}
-                                    dashed={(deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`) ? false : true}
-                                    dashSize={0.75}
-                                    dashScale={20}
-                                    onPointerOver={() => 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 }
-
-                                            removeConnections(connection1, connection2)
-                                        }
-                                    }}
-                                    userData={target}
-                                />
-                            );
-                        }
-                        return null;
-                    });
-                }
-
-                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 fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', path.points.uuid);
-                        const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
-
-                        if (fromSphere && toSphere) {
-                            const fromWorldPosition = new THREE.Vector3();
-                            const toWorldPosition = new THREE.Vector3();
-                            fromSphere.getWorldPosition(fromWorldPosition);
-                            toSphere.getWorldPosition(toWorldPosition);
-
-                            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);
-
-                            return (
-                                <QuadraticBezierLine
-                                    key={`${path.points.uuid}-${target.pointUUID}-${index}`}
-                                    ref={(el) => (groupRefs.current[`${path.points.uuid}-${target.pointUUID}-${index}`] = el!)}
-                                    start={fromWorldPosition.toArray()}
-                                    end={toWorldPosition.toArray()}
-                                    mid={midPoint.toArray()}
-                                    color={
-                                        deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`
-                                            ? 'red'
-                                            : '#42a5f5'
-                                    }
-                                    lineWidth={4}
-                                    dashed={(deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`) ? false : true}
-                                    dashSize={0.75}
-                                    dashScale={20}
-                                    onPointerOver={() => 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 }
-
-                                            removeConnections(connection1, connection2)
-
-                                        }
-                                    }}
-                                    userData={target}
-                                />
-                            );
-                        }
-                        return null;
-                    });
-                }
-
-                return [];
-            })}
-
-            {currentLine && (
-                <QuadraticBezierLine
-                    start={currentLine.start.toArray()}
-                    end={currentLine.end.toArray()}
-                    mid={currentLine.mid.toArray()}
-                    color={helperlineColor}
-                    lineWidth={4}
-                    dashed
-                    dashSize={1}
-                    dashScale={20}
-                />
-            )}
-        </group>
+    const updatedPaths = updatedStates.filter(
+      (state) =>
+        state.modeluuid === connection1.model ||
+        state.modeluuid === connection2.model
     );
 
+    console.log("updatedPaths: ", updatedPaths);
+    updateBackend(updatedPaths);
+
+    setSimulationStates(updatedStates);
+  };
+
+  return (
+    <group name="simulationConnectionGroup" visible={!isPlaying}>
+      {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();
+                const toWorldPosition = new THREE.Vector3();
+                fromSphere.getWorldPosition(fromWorldPosition);
+                toSphere.getWorldPosition(toWorldPosition);
+
+                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
+                );
+
+                return (
+                  <QuadraticBezierLine
+                    key={`${point.uuid}-${target.pointUUID}-${index}`}
+                    ref={(el) =>
+                      (groupRefs.current[
+                        `${point.uuid}-${target.pointUUID}-${index}`
+                      ] = el!)
+                    }
+                    start={fromWorldPosition.toArray()}
+                    end={toWorldPosition.toArray()}
+                    mid={midPoint.toArray()}
+                    color={
+                      deleteTool &&
+                      hoveredLineKey ===
+                        `${point.uuid}-${target.pointUUID}-${index}`
+                        ? "red"
+                        : targetPath?.type === "ArmBot"
+                        ? "#42a5f5"
+                        : "white"
+                    }
+                    lineWidth={4}
+                    dashed={
+                      deleteTool &&
+                      hoveredLineKey ===
+                        `${point.uuid}-${target.pointUUID}-${index}`
+                        ? false
+                        : true
+                    }
+                    dashSize={0.75}
+                    dashScale={20}
+                    onPointerOver={() =>
+                      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,
+                        };
+
+                        removeConnections(connection1, connection2);
+                      }
+                    }}
+                    userData={target}
+                  />
+                );
+              }
+              return null;
+            })
+          );
+        }
+
+        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
+            );
+
+            if (fromSphere && toSphere) {
+              const fromWorldPosition = new THREE.Vector3();
+              const toWorldPosition = new THREE.Vector3();
+              fromSphere.getWorldPosition(fromWorldPosition);
+              toSphere.getWorldPosition(toWorldPosition);
+
+              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
+              );
+
+              return (
+                <QuadraticBezierLine
+                  key={`${path.points.uuid}-${target.pointUUID}-${index}`}
+                  ref={(el) =>
+                    (groupRefs.current[
+                      `${path.points.uuid}-${target.pointUUID}-${index}`
+                    ] = el!)
+                  }
+                  start={fromWorldPosition.toArray()}
+                  end={toWorldPosition.toArray()}
+                  mid={midPoint.toArray()}
+                  color={
+                    deleteTool &&
+                    hoveredLineKey ===
+                      `${path.points.uuid}-${target.pointUUID}-${index}`
+                      ? "red"
+                      : "orange"
+                  }
+                  lineWidth={4}
+                  dashed={
+                    deleteTool &&
+                    hoveredLineKey ===
+                      `${path.points.uuid}-${target.pointUUID}-${index}`
+                      ? false
+                      : true
+                  }
+                  dashSize={0.75}
+                  dashScale={20}
+                  onPointerOver={() =>
+                    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,
+                      };
+
+                      removeConnections(connection1, connection2);
+                    }
+                  }}
+                  userData={target}
+                />
+              );
+            }
+            return null;
+          });
+        }
+
+        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 fromSphere = pathsGroupRef.current?.getObjectByProperty(
+              "uuid",
+              path.points.uuid
+            );
+            const toSphere = pathsGroupRef.current?.getObjectByProperty(
+              "uuid",
+              target.pointUUID
+            );
+
+            if (fromSphere && toSphere) {
+              const fromWorldPosition = new THREE.Vector3();
+              const toWorldPosition = new THREE.Vector3();
+              fromSphere.getWorldPosition(fromWorldPosition);
+              toSphere.getWorldPosition(toWorldPosition);
+
+              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
+              );
+
+              return (
+                <QuadraticBezierLine
+                  key={`${path.points.uuid}-${target.pointUUID}-${index}`}
+                  ref={(el) =>
+                    (groupRefs.current[
+                      `${path.points.uuid}-${target.pointUUID}-${index}`
+                    ] = el!)
+                  }
+                  start={fromWorldPosition.toArray()}
+                  end={toWorldPosition.toArray()}
+                  mid={midPoint.toArray()}
+                  color={
+                    deleteTool &&
+                    hoveredLineKey ===
+                      `${path.points.uuid}-${target.pointUUID}-${index}`
+                      ? "red"
+                      : "#42a5f5"
+                  }
+                  lineWidth={4}
+                  dashed={
+                    deleteTool &&
+                    hoveredLineKey ===
+                      `${path.points.uuid}-${target.pointUUID}-${index}`
+                      ? false
+                      : true
+                  }
+                  dashSize={0.75}
+                  dashScale={20}
+                  onPointerOver={() =>
+                    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,
+                      };
+
+                      removeConnections(connection1, connection2);
+                    }
+                  }}
+                  userData={target}
+                />
+              );
+            }
+            return null;
+          });
+        }
+
+        return [];
+      })}
+
+      {currentLine && (
+        <QuadraticBezierLine
+          start={currentLine.start.toArray()}
+          end={currentLine.end.toArray()}
+          mid={currentLine.mid.toArray()}
+          color={helperlineColor}
+          lineWidth={4}
+          dashed
+          dashSize={1}
+          dashScale={20}
+        />
+      )}
+    </group>
+  );
 }
 
-export default PathConnector;
\ No newline at end of file
+export default PathConnector;

From 344650730725600b882ee4fa33885dfe3fcfa0fa Mon Sep 17 00:00:00 2001
From: Poovizhi99 <poovizhi@hexrfactory.com>
Date: Tue, 15 Apr 2025 10:05:53 +0530
Subject: [PATCH 02/20] removed targets based on condition for armbot

---
 .../controls/selection/selectionControls.tsx  | 1300 +++++++++--------
 1 file changed, 712 insertions(+), 588 deletions(-)

diff --git a/app/src/modules/scene/controls/selection/selectionControls.tsx b/app/src/modules/scene/controls/selection/selectionControls.tsx
index d1eed1e..80a7518 100644
--- a/app/src/modules/scene/controls/selection/selectionControls.tsx
+++ b/app/src/modules/scene/controls/selection/selectionControls.tsx
@@ -3,7 +3,13 @@ import { useEffect, useMemo, useRef, useState } from "react";
 import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox";
 import { SelectionHelper } from "./selectionHelper";
 import { useFrame, useThree } from "@react-three/fiber";
-import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView, } from "../../../../store/store";
+import {
+  useFloorItems,
+  useSelectedAssets,
+  useSimulationStates,
+  useSocketStore,
+  useToggleView,
+} from "../../../../store/store";
 import BoundingBox from "./boundingBoxHelper";
 import { toast } from "react-toastify";
 // import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
@@ -17,622 +23,740 @@ import RotateControls from "./rotateControls";
 import useModuleStore from "../../../../store/useModuleStore";
 
 const SelectionControls: React.FC = () => {
-    const { camera, controls, gl, scene, pointer } = useThree();
-    const itemsGroupRef = useRef<THREE.Group | undefined>(undefined);
-    const selectionGroup = useRef() as Types.RefGroup;
-    const { toggleView } = useToggleView();
-    const { simulationStates, setSimulationStates } = useSimulationStates();
-    const { selectedAssets, setSelectedAssets } = useSelectedAssets();
-    const [movedObjects, setMovedObjects] = useState<THREE.Object3D[]>([]);
-    const [rotatedObjects, setRotatedObjects] = useState<THREE.Object3D[]>([]);
-    const [copiedObjects, setCopiedObjects] = useState<THREE.Object3D[]>([]);
-    const [pastedObjects, setpastedObjects] = useState<THREE.Object3D[]>([]);
-    const [duplicatedObjects, setDuplicatedObjects] = useState<THREE.Object3D[]>([]);
-    const boundingBoxRef = useRef<THREE.Mesh>();
-    const { floorItems, setFloorItems } = useFloorItems();
-    const { activeModule } = useModuleStore();
-    const { socket } = useSocketStore();
-    const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]);
+  const { camera, controls, gl, scene, pointer } = useThree();
+  const itemsGroupRef = useRef<THREE.Group | undefined>(undefined);
+  const selectionGroup = useRef() as Types.RefGroup;
+  const { toggleView } = useToggleView();
+  const { simulationStates, setSimulationStates } = useSimulationStates();
+  const { selectedAssets, setSelectedAssets } = useSelectedAssets();
+  const [movedObjects, setMovedObjects] = useState<THREE.Object3D[]>([]);
+  const [rotatedObjects, setRotatedObjects] = useState<THREE.Object3D[]>([]);
+  const [copiedObjects, setCopiedObjects] = useState<THREE.Object3D[]>([]);
+  const [pastedObjects, setpastedObjects] = useState<THREE.Object3D[]>([]);
+  const [duplicatedObjects, setDuplicatedObjects] = useState<THREE.Object3D[]>(
+    []
+  );
+  const boundingBoxRef = useRef<THREE.Mesh>();
+  const { floorItems, setFloorItems } = useFloorItems();
+  const { activeModule } = useModuleStore();
+  const { socket } = useSocketStore();
+  const selectionBox = useMemo(
+    () => new SelectionBox(camera, scene),
+    [camera, scene]
+  );
 
-    useEffect(() => {
-        if (!camera || !scene || toggleView) return;
+  useEffect(() => {
+    if (!camera || !scene || toggleView) return;
 
-        const canvasElement = gl.domElement;
-        canvasElement.tabIndex = 0;
+    const canvasElement = gl.domElement;
+    canvasElement.tabIndex = 0;
 
-        const itemsGroup: any = scene.getObjectByName("itemsGroup");
-        itemsGroupRef.current = itemsGroup;
+    const itemsGroup: any = scene.getObjectByName("itemsGroup");
+    itemsGroupRef.current = itemsGroup;
 
-        let isSelecting = false;
-        let isRightClick = false;
-        let rightClickMoved = false;
-        let isCtrlSelecting = false;
+    let isSelecting = false;
+    let isRightClick = false;
+    let rightClickMoved = false;
+    let isCtrlSelecting = false;
 
-        const helper = new SelectionHelper(gl);
+    const helper = new SelectionHelper(gl);
 
-        if (!itemsGroup) {
-            toast.warn("itemsGroup not found in the scene.");
-            return;
+    if (!itemsGroup) {
+      toast.warn("itemsGroup not found in the scene.");
+      return;
+    }
+
+    const onPointerDown = (event: PointerEvent) => {
+      if (event.button === 2) {
+        isRightClick = true;
+        rightClickMoved = false;
+      } else if (event.button === 0) {
+        isSelecting = false;
+        isCtrlSelecting = event.ctrlKey;
+        if (event.ctrlKey && duplicatedObjects.length === 0) {
+          if (controls) (controls as any).enabled = false;
+          selectionBox.startPoint.set(pointer.x, pointer.y, 0);
         }
+      }
+    };
 
-        const onPointerDown = (event: PointerEvent) => {
-            if (event.button === 2) {
-                isRightClick = true;
-                rightClickMoved = false;
-            } else if (event.button === 0) {
-                isSelecting = false;
-                isCtrlSelecting = event.ctrlKey;
-                if (event.ctrlKey && duplicatedObjects.length === 0) {
-                    if (controls) (controls as any).enabled = false;
-                    selectionBox.startPoint.set(pointer.x, pointer.y, 0);
-                }
-            }
-        };
+    const onPointerMove = (event: PointerEvent) => {
+      if (isRightClick) {
+        rightClickMoved = true;
+      }
+      isSelecting = true;
+      if (
+        helper.isDown &&
+        event.ctrlKey &&
+        duplicatedObjects.length === 0 &&
+        isCtrlSelecting
+      ) {
+        selectionBox.endPoint.set(pointer.x, pointer.y, 0);
+      }
+    };
 
-        const onPointerMove = (event: PointerEvent) => {
-            if (isRightClick) {
-                rightClickMoved = true;
-            }
-            isSelecting = true;
-            if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) {
-                selectionBox.endPoint.set(pointer.x, pointer.y, 0);
-            }
-        };
-
-        const onPointerUp = (event: PointerEvent) => {
-            if (event.button === 2) {
-                isRightClick = false;
-                if (!rightClickMoved) {
-                    clearSelection();
-                }
-                return;
-            }
-
-            if (isSelecting && isCtrlSelecting) {
-                isCtrlSelecting = false;
-                isSelecting = false;
-                if (event.ctrlKey && duplicatedObjects.length === 0) {
-                    selectAssets();
-                }
-            } else if (!isSelecting && selectedAssets.length > 0 && ((pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) || event.button !== 0)) {
-                clearSelection();
-                helper.enabled = true;
-                isCtrlSelecting = false;
-            }
-        };
-
-        const onKeyDown = (event: KeyboardEvent) => {
-            if (movedObjects.length > 0 || rotatedObjects.length > 0) return;
-            if (event.key.toLowerCase() === "escape") {
-                event.preventDefault();
-                clearSelection();
-            }
-            if (event.key.toLowerCase() === "delete") {
-                event.preventDefault();
-                deleteSelection();
-            }
-        };
-
-        const onContextMenu = (event: MouseEvent) => {
-            event.preventDefault();
-            if (!rightClickMoved) {
-                clearSelection();
-            }
-        };
-
-        if (!toggleView && activeModule === "builder") {
-            helper.enabled = true;
-            if (duplicatedObjects.length === 0 && pastedObjects.length === 0) {
-                canvasElement.addEventListener("pointerdown", onPointerDown);
-                canvasElement.addEventListener("pointermove", onPointerMove);
-                canvasElement.addEventListener("pointerup", onPointerUp);
-            } else {
-                helper.enabled = false;
-                helper.dispose();
-            }
-            canvasElement.addEventListener("contextmenu", onContextMenu);
-            canvasElement.addEventListener("keydown", onKeyDown);
-        } else {
-            helper.enabled = false;
-            helper.dispose();
+    const onPointerUp = (event: PointerEvent) => {
+      if (event.button === 2) {
+        isRightClick = false;
+        if (!rightClickMoved) {
+          clearSelection();
         }
+        return;
+      }
 
-        return () => {
-            canvasElement.removeEventListener("pointerdown", onPointerDown);
-            canvasElement.removeEventListener("pointermove", onPointerMove);
-            canvasElement.removeEventListener("contextmenu", onContextMenu);
-            canvasElement.removeEventListener("pointerup", onPointerUp);
-            canvasElement.removeEventListener("keydown", onKeyDown);
-            helper.enabled = false;
-            helper.dispose();
-        };
-    }, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, floorItems, rotatedObjects, activeModule,]);
-
-    useEffect(() => {
-        if (activeModule !== "builder") {
-            clearSelection();
+      if (isSelecting && isCtrlSelecting) {
+        isCtrlSelecting = false;
+        isSelecting = false;
+        if (event.ctrlKey && duplicatedObjects.length === 0) {
+          selectAssets();
         }
-    }, [activeModule]);
+      } else if (
+        !isSelecting &&
+        selectedAssets.length > 0 &&
+        ((pastedObjects.length === 0 &&
+          duplicatedObjects.length === 0 &&
+          movedObjects.length === 0 &&
+          rotatedObjects.length === 0) ||
+          event.button !== 0)
+      ) {
+        clearSelection();
+        helper.enabled = true;
+        isCtrlSelecting = false;
+      }
+    };
 
-    useFrame(() => {
-        if (pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
-            selectionGroup.current.position.set(0, 0, 0);
+    const onKeyDown = (event: KeyboardEvent) => {
+      if (movedObjects.length > 0 || rotatedObjects.length > 0) return;
+      if (event.key.toLowerCase() === "escape") {
+        event.preventDefault();
+        clearSelection();
+      }
+      if (event.key.toLowerCase() === "delete") {
+        event.preventDefault();
+        deleteSelection();
+      }
+    };
+
+    const onContextMenu = (event: MouseEvent) => {
+      event.preventDefault();
+      if (!rightClickMoved) {
+        clearSelection();
+      }
+    };
+
+    if (!toggleView && activeModule === "builder") {
+      helper.enabled = true;
+      if (duplicatedObjects.length === 0 && pastedObjects.length === 0) {
+        canvasElement.addEventListener("pointerdown", onPointerDown);
+        canvasElement.addEventListener("pointermove", onPointerMove);
+        canvasElement.addEventListener("pointerup", onPointerUp);
+      } else {
+        helper.enabled = false;
+        helper.dispose();
+      }
+      canvasElement.addEventListener("contextmenu", onContextMenu);
+      canvasElement.addEventListener("keydown", onKeyDown);
+    } else {
+      helper.enabled = false;
+      helper.dispose();
+    }
+
+    return () => {
+      canvasElement.removeEventListener("pointerdown", onPointerDown);
+      canvasElement.removeEventListener("pointermove", onPointerMove);
+      canvasElement.removeEventListener("contextmenu", onContextMenu);
+      canvasElement.removeEventListener("pointerup", onPointerUp);
+      canvasElement.removeEventListener("keydown", onKeyDown);
+      helper.enabled = false;
+      helper.dispose();
+    };
+  }, [
+    camera,
+    controls,
+    scene,
+    toggleView,
+    selectedAssets,
+    copiedObjects,
+    pastedObjects,
+    duplicatedObjects,
+    movedObjects,
+    socket,
+    floorItems,
+    rotatedObjects,
+    activeModule,
+  ]);
+
+  useEffect(() => {
+    if (activeModule !== "builder") {
+      clearSelection();
+    }
+  }, [activeModule]);
+
+  useFrame(() => {
+    if (
+      pastedObjects.length === 0 &&
+      duplicatedObjects.length === 0 &&
+      movedObjects.length === 0 &&
+      rotatedObjects.length === 0
+    ) {
+      selectionGroup.current.position.set(0, 0, 0);
+    }
+  });
+
+  const selectAssets = () => {
+    selectionBox.endPoint.set(pointer.x, pointer.y, 0);
+    if (controls) (controls as any).enabled = true;
+
+    let selectedObjects = selectionBox.select();
+    let Objects = new Set<THREE.Object3D>();
+
+    selectedObjects.map((object) => {
+      let currentObject: THREE.Object3D | null = object;
+      while (currentObject) {
+        if (currentObject.userData.modelId) {
+          Objects.add(currentObject);
+          break;
         }
+        currentObject = currentObject.parent || null;
+      }
     });
 
-    const selectAssets = () => {
-        selectionBox.endPoint.set(pointer.x, pointer.y, 0);
-        if (controls) (controls as any).enabled = true;
+    if (Objects.size === 0) {
+      clearSelection();
+      return;
+    }
 
-        let selectedObjects = selectionBox.select();
-        let Objects = new Set<THREE.Object3D>();
+    const updatedSelections = new Set(selectedAssets);
+    Objects.forEach((obj) => {
+      updatedSelections.has(obj)
+        ? updatedSelections.delete(obj)
+        : updatedSelections.add(obj);
+    });
 
-        selectedObjects.map((object) => {
-            let currentObject: THREE.Object3D | null = object;
-            while (currentObject) {
-                if (currentObject.userData.modelId) {
-                    Objects.add(currentObject);
-                    break;
-                }
-                currentObject = currentObject.parent || null;
-            }
+    const selected = Array.from(updatedSelections);
+
+    setSelectedAssets(selected);
+  };
+
+  const clearSelection = () => {
+    selectionGroup.current.children = [];
+    selectionGroup.current.position.set(0, 0, 0);
+    selectionGroup.current.rotation.set(0, 0, 0);
+    setpastedObjects([]);
+    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,
+        //   updatedPath.modeluuid,
+        //   { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
+        // );
+
+        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") {
+        // await setEventApi(
+        //     organization,
+        //     updatedPath.modeluuid,
+        //     { type: "Vehicle", points: updatedPath.points }
+        // );
+
+        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") {
+        // await setEventApi(
+        //     organization,
+        //     updatedPath.modeluuid,
+        //     { type: "StaticMachine", points: updatedPath.points }
+        // );
+
+        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") {
+        // await setEventApi(
+        //     organization,
+        //     updatedPath.modeluuid,
+        //     { type: "ArmBot", points: updatedPath.points }
+        // );
+
+        const data = {
+          organization: organization,
+          modeluuid: updatedPath.modeluuid,
+          eventData: { type: "ArmBot", points: updatedPath.points },
+        };
+
+        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
+      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;
+          }
         });
+      }
+      // Vehicle & StaticMachine types
+      if (state.type === "Vehicle") {
+        const targets = state.points?.connections?.targets || [];
+        const targetMatch = targets.some((target: any) =>
+          modelUUIDs.includes(target.modelUUID)
+        );
 
-        if (Objects.size === 0) {
-            clearSelection();
-            return;
+        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;
+        }
+      }
+
+      // ArmBot type
+      if (state.type === "ArmBot") {
+        const sourceMatch = modelUUIDs.includes(
+          state.points.connections?.source?.modelUUID
+        );
+        console.log("model", modelUUIDs);
+        console.log("state.points.connections: ", state.points);
+
+        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;
         }
 
-        const updatedSelections = new Set(selectedAssets);
-        Objects.forEach((obj) => { updatedSelections.has(obj) ? updatedSelections.delete(obj) : updatedSelections.add(obj); });
-
-        const selected = Array.from(updatedSelections);
-
-        setSelectedAssets(selected);
-    };
-
-    const clearSelection = () => {
-        selectionGroup.current.children = [];
-        selectionGroup.current.position.set(0, 0, 0);
-        selectionGroup.current.rotation.set(0, 0, 0);
-        setpastedObjects([]);
-        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,
-                //   updatedPath.modeluuid,
-                //   { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
-                // );
-
-                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") {
-
-                // await setEventApi(
-                //     organization,
-                //     updatedPath.modeluuid,
-                //     { type: "Vehicle", points: updatedPath.points }
-                // );
-
-                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") {
-
-                // await setEventApi(
-                //     organization,
-                //     updatedPath.modeluuid,
-                //     { type: "StaticMachine", points: updatedPath.points }
-                // );
-
-                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") {
-
-                // await setEventApi(
-                //     organization,
-                //     updatedPath.modeluuid,
-                //     { type: "ArmBot", points: updatedPath.points }
-                // );
-
-                const data = {
-                    organization: organization,
-                    modeluuid: updatedPath.modeluuid,
-                    eventData: { type: "ArmBot", points: updatedPath.points },
-                };
-
-                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
-            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;
-                    }
-                });
-            }
-
-            // 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;
-                }
-            }
-
-            // 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;
-                // }
-            }
-
-            return shouldInclude ? [state] : [];
-        });
-
-        updateBackend(removedPath);
-        return removedPath;
-    };
-
-    const deleteSelection = () => {
-        if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
-            const email = localStorage.getItem("email");
-            const organization = email!.split("@")[1].split(".")[0];
-
-            const storedItems = JSON.parse(localStorage.getItem("FloorItems") || "[]");
-            const selectedUUIDs = selectedAssets.map((mesh: THREE.Object3D) => mesh.uuid);
-
-            const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid));
-            localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems));
-
-            selectedAssets.forEach((selectedMesh: THREE.Object3D) => {
-                //REST
-
-                // const response = await deleteFloorItem(organization, selectedMesh.uuid, selectedMesh.userData.name);
-
-                //SOCKET
-
-                const data = {
-                    organization: organization,
-                    modeluuid: selectedMesh.uuid,
-                    modelname: selectedMesh.userData.name,
-                    socketId: socket.id,
-                };
-
-                socket.emit("v2:model-asset:delete", data);
-
-                selectedMesh.traverse((child: THREE.Object3D) => {
-                    if (child instanceof THREE.Mesh) {
-                        if (child.geometry) child.geometry.dispose();
-                        if (Array.isArray(child.material)) {
-                            child.material.forEach((material) => {
-                                if (material.map) material.map.dispose();
-                                material.dispose();
-                            });
-                        } else if (child.material) {
-                            if (child.material.map) child.material.map.dispose();
-                            child.material.dispose();
-                        }
-                    }
-                });
-
-                setSimulationStates((prevEvents: (| SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
-                    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);
-
-            //   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)
+        if (targetMatch) {
+          state.points.connections.targets =
+            state.points.connections.targets.filter(
+              (target: any) => !modelUUIDs.includes(target.modelUUID)
             );
-            setFloorItems(updatedItems);
+          shouldInclude = true;
         }
-        toast.success("Selected models removed!");
-        clearSelection();
-    };
 
-    return (
-        <>
-            <group name="SelectionGroup">
-                <group ref={selectionGroup} name="selectionAssetGroup">
-                    <BoundingBox boundingBoxRef={boundingBoxRef} />
-                </group>
-            </group>
+        // 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;
+        // }
+      }
 
-            <MoveControls movedObjects={movedObjects} setMovedObjects={setMovedObjects} itemsGroupRef={itemsGroupRef} copiedObjects={copiedObjects} setCopiedObjects={setCopiedObjects} pastedObjects={pastedObjects} setpastedObjects={setpastedObjects} duplicatedObjects={duplicatedObjects} setDuplicatedObjects={setDuplicatedObjects} rotatedObjects={rotatedObjects} setRotatedObjects={setRotatedObjects} selectionGroup={selectionGroup} boundingBoxRef={boundingBoxRef} />
+      return shouldInclude ? [state] : [];
+    });
 
-            <RotateControls rotatedObjects={rotatedObjects} setRotatedObjects={setRotatedObjects} movedObjects={movedObjects} setMovedObjects={setMovedObjects} itemsGroupRef={itemsGroupRef} copiedObjects={copiedObjects} setCopiedObjects={setCopiedObjects} pastedObjects={pastedObjects} setpastedObjects={setpastedObjects} duplicatedObjects={duplicatedObjects} setDuplicatedObjects={setDuplicatedObjects} selectionGroup={selectionGroup} boundingBoxRef={boundingBoxRef} />
+    updateBackend(removedPath);
+    return removedPath;
+  };
 
-            <DuplicationControls itemsGroupRef={itemsGroupRef} duplicatedObjects={duplicatedObjects} setDuplicatedObjects={setDuplicatedObjects} setpastedObjects={setpastedObjects} selectionGroup={selectionGroup} movedObjects={movedObjects} setMovedObjects={setMovedObjects} rotatedObjects={rotatedObjects} setRotatedObjects={setRotatedObjects} boundingBoxRef={boundingBoxRef} />
+  const deleteSelection = () => {
+    if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
+      const email = localStorage.getItem("email");
+      const organization = email!.split("@")[1].split(".")[0];
 
-            <CopyPasteControls itemsGroupRef={itemsGroupRef} copiedObjects={copiedObjects} setCopiedObjects={setCopiedObjects} pastedObjects={pastedObjects} setpastedObjects={setpastedObjects} selectionGroup={selectionGroup} setDuplicatedObjects={setDuplicatedObjects} movedObjects={movedObjects} setMovedObjects={setMovedObjects} rotatedObjects={rotatedObjects} setRotatedObjects={setRotatedObjects} boundingBoxRef={boundingBoxRef} />
-        </>
-    );
+      const storedItems = JSON.parse(
+        localStorage.getItem("FloorItems") || "[]"
+      );
+      const selectedUUIDs = selectedAssets.map(
+        (mesh: THREE.Object3D) => mesh.uuid
+      );
+
+      const updatedStoredItems = storedItems.filter(
+        (item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid)
+      );
+      localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems));
+
+      selectedAssets.forEach((selectedMesh: THREE.Object3D) => {
+        //REST
+
+        // const response = await deleteFloorItem(organization, selectedMesh.uuid, selectedMesh.userData.name);
+
+        //SOCKET
+
+        const data = {
+          organization: organization,
+          modeluuid: selectedMesh.uuid,
+          modelname: selectedMesh.userData.name,
+          socketId: socket.id,
+        };
+
+        socket.emit("v2:model-asset:delete", data);
+
+        selectedMesh.traverse((child: THREE.Object3D) => {
+          if (child instanceof THREE.Mesh) {
+            if (child.geometry) child.geometry.dispose();
+            if (Array.isArray(child.material)) {
+              child.material.forEach((material) => {
+                if (material.map) material.map.dispose();
+                material.dispose();
+              });
+            } else if (child.material) {
+              if (child.material.map) child.material.map.dispose();
+              child.material.dispose();
+            }
+          }
+        });
+
+        setSimulationStates(
+          (
+            prevEvents: (
+              | SimulationTypes.ConveyorEventsSchema
+              | SimulationTypes.VehicleEventsSchema
+              | SimulationTypes.StaticMachineEventsSchema
+              | SimulationTypes.ArmBotEventsSchema
+            )[]
+          ) => {
+            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);
+
+      //   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)
+      );
+      setFloorItems(updatedItems);
+    }
+    toast.success("Selected models removed!");
+    clearSelection();
+  };
+
+  return (
+    <>
+      <group name="SelectionGroup">
+        <group ref={selectionGroup} name="selectionAssetGroup">
+          <BoundingBox boundingBoxRef={boundingBoxRef} />
+        </group>
+      </group>
+
+      <MoveControls
+        movedObjects={movedObjects}
+        setMovedObjects={setMovedObjects}
+        itemsGroupRef={itemsGroupRef}
+        copiedObjects={copiedObjects}
+        setCopiedObjects={setCopiedObjects}
+        pastedObjects={pastedObjects}
+        setpastedObjects={setpastedObjects}
+        duplicatedObjects={duplicatedObjects}
+        setDuplicatedObjects={setDuplicatedObjects}
+        rotatedObjects={rotatedObjects}
+        setRotatedObjects={setRotatedObjects}
+        selectionGroup={selectionGroup}
+        boundingBoxRef={boundingBoxRef}
+      />
+
+      <RotateControls
+        rotatedObjects={rotatedObjects}
+        setRotatedObjects={setRotatedObjects}
+        movedObjects={movedObjects}
+        setMovedObjects={setMovedObjects}
+        itemsGroupRef={itemsGroupRef}
+        copiedObjects={copiedObjects}
+        setCopiedObjects={setCopiedObjects}
+        pastedObjects={pastedObjects}
+        setpastedObjects={setpastedObjects}
+        duplicatedObjects={duplicatedObjects}
+        setDuplicatedObjects={setDuplicatedObjects}
+        selectionGroup={selectionGroup}
+        boundingBoxRef={boundingBoxRef}
+      />
+
+      <DuplicationControls
+        itemsGroupRef={itemsGroupRef}
+        duplicatedObjects={duplicatedObjects}
+        setDuplicatedObjects={setDuplicatedObjects}
+        setpastedObjects={setpastedObjects}
+        selectionGroup={selectionGroup}
+        movedObjects={movedObjects}
+        setMovedObjects={setMovedObjects}
+        rotatedObjects={rotatedObjects}
+        setRotatedObjects={setRotatedObjects}
+        boundingBoxRef={boundingBoxRef}
+      />
+
+      <CopyPasteControls
+        itemsGroupRef={itemsGroupRef}
+        copiedObjects={copiedObjects}
+        setCopiedObjects={setCopiedObjects}
+        pastedObjects={pastedObjects}
+        setpastedObjects={setpastedObjects}
+        selectionGroup={selectionGroup}
+        setDuplicatedObjects={setDuplicatedObjects}
+        movedObjects={movedObjects}
+        setMovedObjects={setMovedObjects}
+        rotatedObjects={rotatedObjects}
+        setRotatedObjects={setRotatedObjects}
+        boundingBoxRef={boundingBoxRef}
+      />
+    </>
+  );
 };
 
 export default SelectionControls;

From c2a29fc8930da44087e4a2532a8537b6f90c72e1 Mon Sep 17 00:00:00 2001
From: Poovizhi99 <poovizhi@hexrfactory.com>
Date: Tue, 15 Apr 2025 15:37:11 +0530
Subject: [PATCH 03/20] integrated path while deleting the asset

---
 .../controls/selection/selectionControls.tsx  | 391 +++++-------------
 1 file changed, 113 insertions(+), 278 deletions(-)

diff --git a/app/src/modules/scene/controls/selection/selectionControls.tsx b/app/src/modules/scene/controls/selection/selectionControls.tsx
index 80a7518..8d7c4cc 100644
--- a/app/src/modules/scene/controls/selection/selectionControls.tsx
+++ b/app/src/modules/scene/controls/selection/selectionControls.tsx
@@ -323,247 +323,124 @@ const SelectionControls: React.FC = () => {
     });
   };
 
-  //   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;
-          }
-        });
-      }
-      // 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;
-        }
+        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;
       }
 
-      // ArmBot type
-      if (state.type === "ArmBot") {
-        const sourceMatch = modelUUIDs.includes(
-          state.points.connections?.source?.modelUUID
-        );
-        console.log("model", modelUUIDs);
-        console.log("state.points.connections: ", state.points);
-
-        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 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;
       }
 
-      return shouldInclude ? [state] : [];
+      // 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;
     });
 
-    updateBackend(removedPath);
-    return removedPath;
+    const filteredStates = updatedStates.filter(
+      (state) => !deletedModelUUIDs.includes(state.modeluuid)
+    );
+
+    updateBackend(filteredStates);
+    setSimulationStates(filteredStates);
   };
 
   const deleteSelection = () => {
@@ -633,51 +510,9 @@ const SelectionControls: React.FC = () => {
         itemsGroupRef.current?.remove(selectedMesh);
       });
 
+      console.log("selectedAssets: ", selectedAssets);
       const allUUIDs = selectedAssets.map((val: any) => val.uuid);
-      removeConnection(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);
+      removeConnections(allUUIDs);
 
       const updatedItems = floorItems.filter(
         (item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid)

From f62d231a79e6709fedd6ee94034ac13c53091866 Mon Sep 17 00:00:00 2001
From: Poovizhi99 <poovizhi@hexrfactory.com>
Date: Tue, 15 Apr 2025 15:39:05 +0530
Subject: [PATCH 04/20] integrated the removeConnections in path connector

---
 .../modules/simulation/path/pathConnector.tsx | 158 +++++++++++++++---
 1 file changed, 139 insertions(+), 19 deletions(-)

diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx
index 1e93bd5..fe3bb1b 100644
--- a/app/src/modules/simulation/path/pathConnector.tsx
+++ b/app/src/modules/simulation/path/pathConnector.tsx
@@ -1133,26 +1133,27 @@ function PathConnector({
           (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) => {
-                  return !(
-                    (target.modelUUID === connection1.model &&
-                      target.pointUUID === connection1.point) ||
-                    (target.modelUUID === connection2.model &&
-                      target.pointUUID === connection2.point)
-                  );
-                }),
+          const updatedStaticMachine: SimulationTypes.StaticMachineEventsSchema =
+            {
+              ...state,
+              points: {
+                ...state.points,
+                connections: {
+                  ...state.points.connections,
+                  targets: state.points.connections.targets.filter((target) => {
+                    return !(
+                      (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,
               },
-              // Ensure all required StaticMachine point properties are included
-              actions: state.points.actions,
-              triggers: state.points.triggers,
-            },
-          };
+            };
           return updatedStaticMachine;
         }
       }
@@ -1211,6 +1212,125 @@ function PathConnector({
 
     setSimulationStates(updatedStates);
   };
+  const removeConnection = (deletedModelUUIDs: string[]) => {
+    const updatedStates = simulationStates.map((state) => {
+      // 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 (
     <group name="simulationConnectionGroup" visible={!isPlaying}>

From db9c9fb8b5f7b36a806d4c1f17a358dcf7baaea2 Mon Sep 17 00:00:00 2001
From: Gomathi9520 <gomathi@hexrfactory.com>
Date: Tue, 15 Apr 2025 18:28:37 +0530
Subject: [PATCH 05/20] duplicate zone rename bug resolved

---
 .../properties/ZoneProperties.tsx             | 12 +++--
 app/src/components/ui/inputs/RenameInput.tsx  | 50 +++++++++++++------
 app/src/components/ui/list/List.tsx           | 42 +++++++++++++---
 .../modules/builder/agv/navMeshCreator.tsx    |  2 +-
 app/src/modules/visualization/DisplayZone.tsx |  4 +-
 .../floating/DroppedFloatingWidgets.tsx       | 26 +++++-----
 app/src/styles/components/input.scss          | 15 +++---
 7 files changed, 101 insertions(+), 50 deletions(-)

diff --git a/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx b/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx
index c36b656..ab1430c 100644
--- a/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx
+++ b/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx
@@ -62,19 +62,25 @@ const ZoneProperties: React.FC = () => {
             : zone
         )
       );
-    }else{
+    } else {
       // console.log(response?.message);
     }
   }
   function handleVectorChange(key: "zoneViewPortTarget" | "zoneViewPortPosition", newValue: [number, number, number]) {
     setSelectedZone((prev) => ({ ...prev, [key]: newValue }));
   }
-
+  const checkZoneNameDuplicate = (name: string) => {
+    return zones.some(
+      (zone: any) =>
+        zone.zoneName.trim().toLowerCase() === name.trim().toLowerCase() &&
+        zone.zoneId !== selectedZone.zoneId
+    );
+  };
 
   return (
     <div className="zone-properties-container">
       <div className="header">
-        <RenameInput value={selectedZone.zoneName} onRename={handleZoneNameChange} />
+        <RenameInput value={selectedZone.zoneName} onRename={handleZoneNameChange} checkDuplicate={checkZoneNameDuplicate} />
         <div className="button" onClick={handleEditView}>
           {Edit ? "Cancel" : "Edit"}
         </div>
diff --git a/app/src/components/ui/inputs/RenameInput.tsx b/app/src/components/ui/inputs/RenameInput.tsx
index d197dd4..593e1f1 100644
--- a/app/src/components/ui/inputs/RenameInput.tsx
+++ b/app/src/components/ui/inputs/RenameInput.tsx
@@ -1,26 +1,42 @@
 import React, { useState, useRef, useEffect } from "react";
 
+// interface RenameInputProps {
+//   value: string;
+//   onRename?: (newText: string) => void;
+// }
+
 interface RenameInputProps {
   value: string;
   onRename?: (newText: string) => void;
+  checkDuplicate?: (name: string) => boolean;
 }
 
-const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
+const RenameInput: React.FC<RenameInputProps> = ({ value, onRename, checkDuplicate }) => {
   const [isEditing, setIsEditing] = useState(false);
   const [text, setText] = useState(value);
+  const [isDuplicate, setIsDuplicate] = useState(false);
   const inputRef = useRef<HTMLInputElement | null>(null);
+
   useEffect(() => {
-    setText(value); // Ensure state updates when parent value changes
+    setText(value);
   }, [value]);
 
+  useEffect(() => {
+    if (checkDuplicate) {
+      setIsDuplicate(checkDuplicate(text));
+    }
+  }, [text, checkDuplicate]);
+
   const handleDoubleClick = () => {
     setIsEditing(true);
-    setTimeout(() => inputRef.current?.focus(), 0); // Focus the input after rendering
+    setTimeout(() => inputRef.current?.focus(), 0);
   };
 
   const handleBlur = () => {
+  
+    if(isDuplicate) return
     setIsEditing(false);
-    if (onRename) {
+    if (onRename && !isDuplicate) {
       onRename(text);
     }
   };
@@ -30,7 +46,7 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
   };
 
   const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
-    if (e.key === "Enter") {
+    if (e.key === "Enter" && !isDuplicate) {
       setIsEditing(false);
       if (onRename) {
         onRename(text);
@@ -41,15 +57,18 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
   return (
     <>
       {isEditing ? (
-        <input
-          ref={inputRef}
-          type="text"
-          value={text}
-          onChange={handleChange}
-          onBlur={handleBlur}
-          onKeyDown={handleKeyDown}
-          className="rename-input"
-        />
+        <>
+          <input
+            ref={inputRef}
+            type="text"
+            value={text}
+            onChange={handleChange}
+            onBlur={handleBlur}
+            onKeyDown={handleKeyDown}
+            className={`rename-input ${isDuplicate ? "input-error" : ""}`}
+          />
+          {/* {isDuplicate && <div className="error-msg">Name already exists!</div>} */}
+        </>
       ) : (
         <span onDoubleClick={handleDoubleClick} className="input-value">
           {text}
@@ -58,5 +77,4 @@ const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
     </>
   );
 };
-
-export default RenameInput;
+export default RenameInput
diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx
index 06bc129..49e86f4 100644
--- a/app/src/components/ui/list/List.tsx
+++ b/app/src/components/ui/list/List.tsx
@@ -13,7 +13,7 @@ import {
   RmoveIcon,
 } from "../../icons/ExportCommonIcons";
 import { useThree } from "@react-three/fiber";
-import { useFloorItems, useZoneAssetId } from "../../../store/store";
+import { useFloorItems, useZoneAssetId, useZones } from "../../../store/store";
 import { zoneCameraUpdate } from "../../../services/realTimeVisulization/zoneData/zoneCameraUpdation";
 import { setFloorItemApi } from "../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
 
@@ -40,7 +40,7 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
   const { activeModule, setActiveModule } = useModuleStore();
   const { selectedZone, setSelectedZone } = useSelectedZoneStore();
   const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
-
+  const { zones, setZones } = useZones();
   const { setSubModule } = useSubModuleStore();
   const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>(
     {}
@@ -100,19 +100,33 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
   function handleAssetClick(asset: Asset) {
     setZoneAssetId(asset)
   }
+
   async function handleZoneNameChange(newName: string) {
-    //zone apiiiiii
     const email = localStorage.getItem("email") || "";
     const organization = email?.split("@")[1]?.split(".")[0];
-    let zonesdata = {
+
+    const isDuplicate = zones.some(
+      (zone: any) =>
+        zone.zoneName.trim().toLowerCase() === newName.trim().toLowerCase() &&
+        zone.zoneId !== selectedZone.zoneId
+    );
+
+    if (isDuplicate) {
+      alert("Zone name already exists. Please choose a different name.");
+      return; // DO NOT update state
+    }
+
+    const zonesdata = {
       zoneId: selectedZone.zoneId,
-      zoneName: newName
+      zoneName: newName,
     };
-    let response = await zoneCameraUpdate(zonesdata, organization);
+
+    const response = await zoneCameraUpdate(zonesdata, organization);
     if (response.message === "updated successfully") {
       setSelectedZone((prev) => ({ ...prev, zoneName: newName }));
     }
   }
+
   async function handleZoneAssetName(newName: string) {
     const email = localStorage.getItem("email") || "";
     const organization = email?.split("@")[1]?.split(".")[0];
@@ -128,10 +142,17 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
         )
       );
     }
-   
+
     console.log('newName: ', newName);
 
   }
+  const checkZoneNameDuplicate = (name: string) => {
+    return zones.some(
+      (zone: any) =>
+        zone.zoneName.trim().toLowerCase() === name.trim().toLowerCase() &&
+        zone.zoneId !== selectedZone.zoneId
+    );
+  };
 
   return (
     <>
@@ -146,7 +167,12 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
                       className="value"
                       onClick={() => handleSelectZone(item.id)}
                     >
-                      <RenameInput value={item.name} onRename={handleZoneNameChange} />
+                      <RenameInput
+                        value={item.name}
+                        onRename={handleZoneNameChange}
+                        checkDuplicate={checkZoneNameDuplicate}
+                      />
+
                     </div>
                   </div>
                   <div className="options-container">
diff --git a/app/src/modules/builder/agv/navMeshCreator.tsx b/app/src/modules/builder/agv/navMeshCreator.tsx
index cdbca45..c0f8808 100644
--- a/app/src/modules/builder/agv/navMeshCreator.tsx
+++ b/app/src/modules/builder/agv/navMeshCreator.tsx
@@ -19,7 +19,7 @@ function NavMeshCreator({ lines }: NavMeshCreatorProps) {
             <NavMeshDetails lines={lines} setNavMesh={setNavMesh} groupRef={groupRef} />
 
             <group ref={groupRef} visible={false} name="Meshes">
-                <mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} name="Plane" receiveShadow>
+                <mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} receiveShadow>
                     <planeGeometry args={[300, 300]} />
                     <meshBasicMaterial color={CONSTANTS.planeConfig.color} />
                 </mesh>
diff --git a/app/src/modules/visualization/DisplayZone.tsx b/app/src/modules/visualization/DisplayZone.tsx
index dfe68f6..e2f3b2f 100644
--- a/app/src/modules/visualization/DisplayZone.tsx
+++ b/app/src/modules/visualization/DisplayZone.tsx
@@ -104,8 +104,8 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
       setShowLeftArrow(isOverflowing && canScrollLeft);
       setShowRightArrow(isOverflowing && canScrollRight);
 
-      console.log('canScrollRight: ', canScrollRight);
-      console.log('isOverflowing: ', isOverflowing);
+      // console.log('canScrollRight: ', canScrollRight);
+      // console.log('isOverflowing: ', isOverflowing);
 
     }
   }, []);
diff --git a/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx b/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx
index 62c1de7..6d12ad8 100644
--- a/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx
+++ b/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx
@@ -520,37 +520,37 @@ const DroppedObjects: React.FC = () => {
       onPointerUp={handlePointerUp}
       className="floating-wrapper"
     >
-      {zone.objects.map((obj, index) => {
+      {zone?.objects?.map((obj, index) => {
         const topPosition =
-          typeof obj.position.top === "number"
-            ? `calc(${obj.position.top}px + ${
-                isPlaying && selectedZone.activeSides.includes("top")
+          typeof obj?.position?.top === "number"
+            ? `calc(${obj?.position?.top}px + ${
+                isPlaying && selectedZone?.activeSides?.includes("top")
                   ? `${heightMultiplier - 55}px`
                   : "0px"
               })`
             : "auto";
 
         const leftPosition =
-          typeof obj.position.left === "number"
-            ? `calc(${obj.position.left}px + ${
-                isPlaying && selectedZone.activeSides.includes("left")
+          typeof obj?.position?.left === "number"
+            ? `calc(${obj?.position?.left}px + ${
+                isPlaying && selectedZone?.activeSides?.includes("left")
                   ? `${widthMultiplier - 150}px`
                   : "0px"
               })`
             : "auto";
 
         const rightPosition =
-          typeof obj.position.right === "number"
-            ? `calc(${obj.position.right}px + ${
-                isPlaying && selectedZone.activeSides.includes("right")
+          typeof obj?.position?.right === "number"
+            ? `calc(${obj?.position?.right}px + ${
+                isPlaying && selectedZone?.activeSides?.includes("right")
                   ? `${widthMultiplier - 150}px`
                   : "0px"
               })`
             : "auto";
         const bottomPosition =
-          typeof obj.position.bottom === "number"
-            ? `calc(${obj.position.bottom}px + ${
-                isPlaying && selectedZone.activeSides.includes("bottom")
+          typeof obj?.position?.bottom === "number"
+            ? `calc(${obj?.position?.bottom}px + ${
+                isPlaying && selectedZone?.activeSides?.includes("bottom")
                   ? `${heightMultiplier - 55}px`
                   : "0px"
               })`
diff --git a/app/src/styles/components/input.scss b/app/src/styles/components/input.scss
index 0c89cc5..883f6c2 100644
--- a/app/src/styles/components/input.scss
+++ b/app/src/styles/components/input.scss
@@ -56,6 +56,12 @@ input {
   padding: 0 8px;
 }
 
+.input-error {
+  border: 1px solid #f65648 !important;
+  outline: none !important;
+  color: #f65648;
+}
+
 .toggle-header-container {
   @include flex-center;
   padding: 6px 12px;
@@ -344,7 +350,6 @@ input {
       padding: 10px;
     }
 
-
     .loading {
       position: absolute;
       bottom: 0;
@@ -364,9 +369,7 @@ input {
       left: -50%;
       height: 100%;
       width: 50%;
-      background: linear-gradient(to right,
-          var(--accent-color),
-          transparent);
+      background: linear-gradient(to right, var(--accent-color), transparent);
       animation: loadingAnimation 1.2s linear infinite;
       border-radius: 4px;
     }
@@ -381,8 +384,6 @@ input {
       }
     }
 
-
-
     .dropdown-item {
       display: block;
       padding: 5px 10px;
@@ -710,4 +711,4 @@ input {
   .multi-email-invite-input.active {
     border: 1px solid var(--accent-color);
   }
-}
\ No newline at end of file
+}

From c7147773c56633176dace562eea88f36e2dbd722 Mon Sep 17 00:00:00 2001
From: SreeNath14 <153710861+SreeNath14@users.noreply.github.com>
Date: Tue, 15 Apr 2025 18:34:38 +0530
Subject: [PATCH 06/20] "updated arm logic"

---
 .../mechanics/ArmBotMechanics.tsx             |    1 +
 app/src/modules/builder/agv/pathNavigator.tsx |  116 +-
 .../simulation/process/processAnimator.tsx    |   52 +-
 .../simulation/process/processCreator.tsx     |  508 +------
 app/src/modules/simulation/process/types.ts   |   16 +-
 .../process/useProcessAnimations.tsx          | 1196 +++++++++--------
 app/src/modules/simulation/simulation.tsx     |    2 +
 7 files changed, 822 insertions(+), 1069 deletions(-)

diff --git a/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx
index e157d07..8b05525 100644
--- a/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx
+++ b/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx
@@ -150,6 +150,7 @@ const ArmBotMechanics: React.FC = () => {
             modeluuid: updatedPath.modeluuid,
             eventData: { type: "ArmBot", points: updatedPath.points }
         }
+        console.log('data: ', data);
 
         socket.emit('v2:model-asset:updateEventData', data);
     }
diff --git a/app/src/modules/builder/agv/pathNavigator.tsx b/app/src/modules/builder/agv/pathNavigator.tsx
index 9a6fae7..a81925f 100644
--- a/app/src/modules/builder/agv/pathNavigator.tsx
+++ b/app/src/modules/builder/agv/pathNavigator.tsx
@@ -3,7 +3,10 @@ import * as THREE from "three";
 import { useFrame, useThree } from "@react-three/fiber";
 import { NavMeshQuery } from "@recast-navigation/core";
 import { Line } from "@react-three/drei";
-import { useAnimationPlaySpeed, usePlayButtonStore } from "../../../store/usePlayButtonStore";
+import {
+  useAnimationPlaySpeed,
+  usePlayButtonStore,
+} from "../../../store/usePlayButtonStore";
 import { usePlayAgv } from "../../../store/store";
 
 interface PathNavigatorProps {
@@ -11,7 +14,7 @@ interface PathNavigatorProps {
   pathPoints: any;
   id: string;
   speed: number;
-  globalSpeed: number,
+  globalSpeed: number;
   bufferTime: number;
   hitCount: number;
   processes: any[];
@@ -40,11 +43,21 @@ export default function PathNavigator({
 }: PathNavigatorProps) {
   const [currentPhase, setCurrentPhase] = useState<Phase>("initial");
   const [path, setPath] = useState<[number, number, number][]>([]);
-  const [toPickupPath, setToPickupPath] = useState<[number, number, number][]>([]);
-  const [pickupDropPath, setPickupDropPath] = useState<[number, number, number][]>([]);
-  const [dropPickupPath, setDropPickupPath] = useState<[number, number, number][]>([]);
-  const [initialPosition, setInitialPosition] = useState<THREE.Vector3 | null>(null);
-  const [initialRotation, setInitialRotation] = useState<THREE.Euler | null>(null);
+  const [toPickupPath, setToPickupPath] = useState<[number, number, number][]>(
+    []
+  );
+  const [pickupDropPath, setPickupDropPath] = useState<
+    [number, number, number][]
+  >([]);
+  const [dropPickupPath, setDropPickupPath] = useState<
+    [number, number, number][]
+  >([]);
+  const [initialPosition, setInitialPosition] = useState<THREE.Vector3 | null>(
+    null
+  );
+  const [initialRotation, setInitialRotation] = useState<THREE.Euler | null>(
+    null
+  );
   const [boxVisible, setBoxVisible] = useState(false);
 
   const distancesRef = useRef<number[]>([]);
@@ -61,11 +74,14 @@ export default function PathNavigator({
 
   const boxRef = useRef<THREE.Mesh | null>(null);
 
-  const baseMaterials = useMemo(() => ({
-    Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
-    Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
-    Default: new THREE.MeshStandardMaterial({ color: 0xcccccc })
-  }), []);
+  const baseMaterials = useMemo(
+    () => ({
+      Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
+      Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
+      Default: new THREE.MeshStandardMaterial({ color: 0xcccccc }),
+    }),
+    []
+  );
 
   useEffect(() => {
     const object = scene.getObjectByProperty("uuid", id);
@@ -135,7 +151,11 @@ export default function PathNavigator({
     const pickupToDropPath = computePath(pickup, drop);
     const dropToPickupPath = computePath(drop, pickup);
 
-    if (toPickupPath.length && pickupToDropPath.length && dropToPickupPath.length) {
+    if (
+      toPickupPath.length &&
+      pickupToDropPath.length &&
+      dropToPickupPath.length
+    ) {
       setPickupDropPath(pickupToDropPath);
       setDropPickupPath(dropToPickupPath);
       setToPickupPath(toPickupPath);
@@ -163,7 +183,10 @@ export default function PathNavigator({
   }, [path]);
 
   function logAgvStatus(id: string, status: string) {
-    // console.log(`AGV ${id}: ${status}`);
+    // console.log(
+    //   `AGV ${id}: ${status}`
+    
+    // );
   }
 
   function findProcessByTargetModelUUID(processes: any, targetModelUUID: any) {
@@ -223,7 +246,9 @@ export default function PathNavigator({
   }, [processes, MaterialRef, boxVisible, scene, id, baseMaterials]);
 
   useFrame((_, delta) => {
-    const currentAgv = (agvRef.current || []).find((agv: AGVData) => agv.vehicleId === id);
+    const currentAgv = (agvRef.current || []).find(
+      (agv: AGVData) => agv.vehicleId === id
+    );
 
     if (!scene || !id || !isPlaying) return;
 
@@ -243,6 +268,7 @@ export default function PathNavigator({
     const isAgvReady = () => {
       if (!agvRef.current || agvRef.current.length === 0) return false;
       if (!currentAgv) return false;
+
       return currentAgv.isActive && hitCount >= currentAgv.maxHitCount;
     };
 
@@ -266,12 +292,19 @@ export default function PathNavigator({
     }
 
     if (isPlaying && currentPhase === "initial" && !hasReachedPickup.current) {
-      const reached = moveAlongPath(object, path, distancesRef.current, speed, delta, progressRef);
+      const reached = moveAlongPath(
+        object,
+        path,
+        distancesRef.current,
+        speed,
+        delta,
+        progressRef
+      );
 
       if (reached) {
         hasReachedPickup.current = true;
         if (currentAgv) {
-          currentAgv.status = 'picking';
+          currentAgv.status = "picking";
         }
         logAgvStatus(id, "Reached pickup point, Waiting for material");
       }
@@ -287,20 +320,28 @@ export default function PathNavigator({
         progressRef.current = 0;
         logAgvStatus(id, "Started from pickup point, heading to drop point");
         if (currentAgv) {
-          currentAgv.status = 'toDrop';
+          currentAgv.status = "toDrop";
         }
-      }, 0)
+      }, 0);
       return;
     }
 
     if (isPlaying && currentPhase === "toDrop") {
-      const reached = moveAlongPath(object, path, distancesRef.current, speed, delta, progressRef);
+      const reached = moveAlongPath(
+        object,
+        path,
+        distancesRef.current,
+        speed,
+        delta,
+        progressRef
+      );
 
       if (reached && !isWaiting.current) {
         isWaiting.current = true;
         logAgvStatus(id, "Reached drop point");
         if (currentAgv) {
-          currentAgv.status = 'droping';
+          currentAgv.status = "droping";
+          currentAgv.hitCount = currentAgv.hitCount--;
         }
         timeoutRef.current = setTimeout(() => {
           setPath([...dropPickupPath]);
@@ -309,16 +350,26 @@ export default function PathNavigator({
           isWaiting.current = false;
           setBoxVisible(false);
           if (currentAgv) {
-            currentAgv.status = 'toPickup';
+            currentAgv.status = "toPickup";
           }
-          logAgvStatus(id, "Started from droping point, heading to pickup point");
+          logAgvStatus(
+            id,
+            "Started from droping point, heading to pickup point"
+          );
         }, bufferTime * 1000);
       }
       return;
     }
 
     if (isPlaying && currentPhase === "toPickup") {
-      const reached = moveAlongPath(object, path, distancesRef.current, speed, delta, progressRef);
+      const reached = moveAlongPath(
+        object,
+        path,
+        distancesRef.current,
+        speed,
+        delta,
+        progressRef
+      );
 
       if (reached) {
         if (currentAgv) {
@@ -326,14 +377,21 @@ export default function PathNavigator({
         }
         setCurrentPhase("initial");
         if (currentAgv) {
-          currentAgv.status = 'picking';
+          currentAgv.status = "picking";
         }
         logAgvStatus(id, "Reached pickup point again, cycle complete");
       }
       return;
     }
 
-    moveAlongPath(object, path, distancesRef.current, speed, delta, progressRef);
+    moveAlongPath(
+      object,
+      path,
+      distancesRef.current,
+      speed,
+      delta,
+      progressRef
+    );
   });
 
   function moveAlongPath(
@@ -379,7 +437,11 @@ export default function PathNavigator({
       const targetRotationY = Math.atan2(targetDirection.x, targetDirection.z);
 
       const rotationSpeed = Math.min(5 * delta, 1);
-      object.rotation.y = THREE.MathUtils.lerp(object.rotation.y, targetRotationY, rotationSpeed);
+      object.rotation.y = THREE.MathUtils.lerp(
+        object.rotation.y,
+        targetRotationY,
+        rotationSpeed
+      );
     }
 
     return false;
diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx
index c1063c3..65bc4c5 100644
--- a/app/src/modules/simulation/process/processAnimator.tsx
+++ b/app/src/modules/simulation/process/processAnimator.tsx
@@ -8,8 +8,7 @@ import crate from "../../../assets/gltf-glb/crate_box.glb";
 import { useProcessAnimation } from "./useProcessAnimations";
 import ProcessObject from "./processObject";
 import { ProcessData } from "./types";
-import { useSimulationStates } from "../../../store/store";
-import { retrieveGLTF } from "../../../utils/indexDB/idbUtils";
+
 
 interface ProcessContainerProps {
   processes: ProcessData[];
@@ -44,19 +43,23 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
     checkAndCountTriggers,
   } = useProcessAnimation(processes, setProcesses, agvRef);
 
-  const baseMaterials = useMemo(() => ({
-    Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
-    Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
-    Default: new THREE.MeshStandardMaterial(),
-  }), []);
+  const baseMaterials = useMemo(
+    () => ({
+      Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
+      Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
+      Default: new THREE.MeshStandardMaterial(),
+    }),
+    []
+  );
 
   useEffect(() => {
     // Update material references for all spawned objects
     Object.entries(animationStates).forEach(([processId, processState]) => {
       Object.keys(processState.spawnedObjects).forEach((objectId) => {
-        const entry = { processId, objectId, };
+        const entry = { processId, objectId };
 
-        const materialType = processState.spawnedObjects[objectId]?.currentMaterialType;
+        const materialType =
+          processState.spawnedObjects[objectId]?.currentMaterialType;
 
         if (!materialType) {
           return;
@@ -65,13 +68,17 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
         const matRefArray = MaterialRef.current;
 
         // Find existing material group
-        const existing = matRefArray.find((entryGroup: { material: string; objects: any[] }) =>
-          entryGroup.material === materialType
+        const existing = matRefArray.find(
+          (entryGroup: { material: string; objects: any[] }) =>
+            entryGroup.material === materialType
         );
 
         if (existing) {
           // Check if this processId + objectId already exists
-          const alreadyExists = existing.objects.some((o: any) => o.processId === entry.processId && o.objectId === entry.objectId);
+          const alreadyExists = existing.objects.some(
+            (o: any) =>
+              o.processId === entry.processId && o.objectId === entry.objectId
+          );
 
           if (!alreadyExists) {
             existing.objects.push(entry);
@@ -91,7 +98,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
   useFrame(() => {
     // Spawn logic frame
-    const currentTime = clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
+    const currentTime =
+      clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
 
     setAnimationStates((prev) => {
       const newStates = { ...prev };
@@ -119,7 +127,10 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             : parseFloat(spawnAction.spawnInterval as string) || 0;
 
         // Check if this is a zero interval spawn and we already spawned an object
-        if (spawnInterval === 0 && processState.hasSpawnedZeroIntervalObject === true) {
+        if (
+          spawnInterval === 0 &&
+          processState.hasSpawnedZeroIntervalObject === true
+        ) {
           return; // Don't spawn more objects for zero interval
         }
 
@@ -324,10 +335,13 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             if (isLastPoint) {
               const isAgvPicking = agvRef.current.some(
-                (agv: any) => agv.processId === process.id && agv.status === "picking"
+                (agv: any) =>
+                  agv.processId === process.id && agv.status === "picking"
               );
 
-              const shouldHide = !currentPointData?.actions || !hasNonInheritActions(currentPointData.actions);
+              const shouldHide =
+                !currentPointData?.actions ||
+                !hasNonInheritActions(currentPointData.actions);
 
               if (shouldHide) {
                 if (isAgvPicking) {
@@ -358,7 +372,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             if (tempStackedObjectsRef.current[objectId]) {
               const isAgvPicking = agvRef.current.some(
-                (agv: any) => agv.processId === process.id && agv.status === "picking"
+                (agv: any) =>
+                  agv.processId === process.id && agv.status === "picking"
               );
 
               if (isAgvPicking) {
@@ -377,7 +392,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             if (!isLastPoint) {
               const nextPoint = path[nextPointIdx];
-              const distance = path[stateRef.currentIndex].distanceTo(nextPoint);
+              const distance =
+                path[stateRef.currentIndex].distanceTo(nextPoint);
               const effectiveSpeed = stateRef.speed * speedRef.current;
               const movement = effectiveSpeed * delta;
 
diff --git a/app/src/modules/simulation/process/processCreator.tsx b/app/src/modules/simulation/process/processCreator.tsx
index f7f9974..c46791f 100644
--- a/app/src/modules/simulation/process/processCreator.tsx
+++ b/app/src/modules/simulation/process/processCreator.tsx
@@ -1,450 +1,3 @@
-// import React, {
-//   useEffect,
-//   useMemo,
-//   useState,
-//   useCallback,
-//   useRef,
-// } from "react";
-// import { useSimulationStates } from "../../../store/store";
-// import * as THREE from "three";
-// import { useThree } from "@react-three/fiber";
-// import {
-//   ConveyorEventsSchema,
-//   VehicleEventsSchema,
-// } from "../../../types/world/worldTypes";
-
-// // Type definitions
-// export interface PointAction {
-//   uuid: string;
-//   name: string;
-//   type: string;
-//   material: string;
-//   delay: number | string;
-//   spawnInterval: string | number;
-//   isUsed: boolean;
-// }
-
-// export interface PointTrigger {
-//   uuid: string;
-//   bufferTime: number;
-//   name: string;
-//   type: string;
-//   isUsed: boolean;
-// }
-
-// export interface PathPoint {
-//   uuid: string;
-//   position: [number, number, number];
-//   actions: PointAction[];
-//   triggers: PointTrigger[];
-//   connections: {
-//     targets: Array<{ modelUUID: string }>;
-//   };
-// }
-
-// export interface SimulationPath {
-//   type: string;
-//   modeluuid: string;
-//   points: PathPoint[];
-//   pathPosition: [number, number, number];
-//   speed?: number;
-// }
-
-// export interface Process {
-//   id: string;
-//   paths: SimulationPath[];
-//   animationPath: THREE.Vector3[];
-//   pointActions: PointAction[][];
-//   pointTriggers: PointTrigger[][];
-//   speed: number;
-//   isActive: boolean;
-// }
-
-// interface ProcessCreatorProps {
-//   onProcessesCreated: (processes: Process[]) => void;
-// }
-
-// // Convert event schemas to SimulationPath
-// function convertToSimulationPath(
-//   path: ConveyorEventsSchema | VehicleEventsSchema
-// ): SimulationPath {
-//   const { modeluuid } = path;
-
-//   // Normalized action handler
-//   const normalizeAction = (action: any): PointAction => {
-//     return { ...action }; // Return exact copy with no modifications
-//   };
-
-//   // Normalized trigger handler
-//   const normalizeTrigger = (trigger: any): PointTrigger => {
-//     return { ...trigger }; // Return exact copy with no modifications
-//   };
-
-//   if (path.type === "Conveyor") {
-//     return {
-//       type: path.type,
-//       modeluuid,
-//       points: path.points.map((point) => ({
-//         uuid: point.uuid,
-//         position: point.position,
-//         actions: Array.isArray(point.actions)
-//           ? point.actions.map(normalizeAction)
-//           : point.actions
-//           ? [normalizeAction(point.actions)]
-//           : [],
-//         triggers: Array.isArray(point.triggers)
-//           ? point.triggers.map(normalizeTrigger)
-//           : point.triggers
-//           ? [normalizeTrigger(point.triggers)]
-//           : [],
-//         connections: {
-//           targets: point.connections.targets.map((target) => ({
-//             modelUUID: target.modelUUID,
-//           })),
-//         },
-//       })),
-//       pathPosition: path.position,
-//       speed:
-//         typeof path.speed === "string"
-//           ? parseFloat(path.speed) || 1
-//           : path.speed || 1,
-//     };
-//   } else {
-//     // For vehicle paths, handle the case where triggers might not exist
-//     return {
-//       type: path.type,
-//       modeluuid,
-//       points: [
-//         {
-//           uuid: path.points.uuid,
-//           position: path.points.position,
-//           actions: Array.isArray(path.points.actions)
-//             ? path.points.actions.map(normalizeAction)
-//             : path.points.actions
-//             ? [normalizeAction(path.points.actions)]
-//             : [],
-//           // For vehicle paths, since triggers might not exist in the schema,
-//           // we always define default to an empty array
-//           triggers: [],
-//           connections: {
-//             targets: path.points.connections.targets.map((target) => ({
-//               modelUUID: target.modelUUID,
-//             })),
-//           },
-//         },
-//       ],
-//       pathPosition: path.position,
-//       speed: path.points.speed || 1,
-//     };
-//   }
-// }
-
-// // Helper function to create an empty process
-// const createEmptyProcess = (): Process => ({
-//   id: `process-${Math.random().toString(36).substring(2, 11)}`,
-//   paths: [],
-//   animationPath: [],
-//   pointActions: [],
-//   pointTriggers: [], // Added point triggers array
-//   speed: 1,
-//   isActive: false,
-// });
-
-// // Enhanced connection checking function
-// function shouldReverseNextPath(
-//   currentPath: SimulationPath,
-//   nextPath: SimulationPath
-// ): boolean {
-//   if (nextPath.points.length !== 3) return false;
-
-//   const currentLastPoint = currentPath.points[currentPath.points.length - 1];
-//   const nextFirstPoint = nextPath.points[0];
-//   const nextLastPoint = nextPath.points[nextPath.points.length - 1];
-
-//   // Check if current last connects to next last (requires reversal)
-//   const connectsToLast = currentLastPoint.connections.targets.some(
-//     (target) =>
-//       target.modelUUID === nextPath.modeluuid &&
-//       nextLastPoint.connections.targets.some(
-//         (t) => t.modelUUID === currentPath.modeluuid
-//       )
-//   );
-
-//   // Check if current last connects to next first (no reversal needed)
-//   const connectsToFirst = currentLastPoint.connections.targets.some(
-//     (target) =>
-//       target.modelUUID === nextPath.modeluuid &&
-//       nextFirstPoint.connections.targets.some(
-//         (t) => t.modelUUID === currentPath.modeluuid
-//       )
-//   );
-
-//   // Only reverse if connected to last point and not to first point
-//   return connectsToLast && !connectsToFirst;
-// }
-
-// // Check if a point has a spawn action
-// function hasSpawnAction(point: PathPoint): boolean {
-//   return point.actions.some((action) => action.type.toLowerCase() === "spawn");
-// }
-
-// // Ensure spawn point is always at the beginning of the path
-// function ensureSpawnPointIsFirst(path: SimulationPath): SimulationPath {
-//   if (path.points.length !== 3) return path;
-
-//   // If the third point has spawn action and first doesn't, reverse the array
-//   if (hasSpawnAction(path.points[2]) && !hasSpawnAction(path.points[0])) {
-//     return {
-//       ...path,
-//       points: [...path.points].reverse(),
-//     };
-//   }
-
-//   return path;
-// }
-
-// // Updated path adjustment function
-// function adjustPathPointsOrder(paths: SimulationPath[]): SimulationPath[] {
-//   if (paths.length < 1) return paths;
-
-//   const adjustedPaths = [...paths];
-
-//   // First ensure all paths have spawn points at the beginning
-//   for (let i = 0; i < adjustedPaths.length; i++) {
-//     adjustedPaths[i] = ensureSpawnPointIsFirst(adjustedPaths[i]);
-//   }
-
-//   // Then handle connections between paths
-//   for (let i = 0; i < adjustedPaths.length - 1; i++) {
-//     const currentPath = adjustedPaths[i];
-//     const nextPath = adjustedPaths[i + 1];
-
-//     if (shouldReverseNextPath(currentPath, nextPath)) {
-//       const reversedPoints = [
-//         nextPath.points[2],
-//         nextPath.points[1],
-//         nextPath.points[0],
-//       ];
-
-//       adjustedPaths[i + 1] = {
-//         ...nextPath,
-//         points: reversedPoints,
-//       };
-//     }
-//   }
-
-//   return adjustedPaths;
-// }
-
-// // Main hook for process creation
-// export function useProcessCreation() {
-//   const { scene } = useThree();
-//   const [processes, setProcesses] = useState<Process[]>([]);
-
-//   const hasSpawnAction = useCallback((path: SimulationPath): boolean => {
-//     if (path.type !== "Conveyor") return false;
-//     return path.points.some((point) =>
-//       point.actions.some((action) => action.type.toLowerCase() === "spawn")
-//     );
-//   }, []);
-
-//   const createProcess = useCallback(
-//     (paths: SimulationPath[]): Process => {
-//       if (!paths || paths.length === 0) {
-//         return createEmptyProcess();
-//       }
-
-//       const animationPath: THREE.Vector3[] = [];
-//       const pointActions: PointAction[][] = [];
-//       const pointTriggers: PointTrigger[][] = []; // Added point triggers collection
-//       const processSpeed = paths[0]?.speed || 1;
-
-//       for (const path of paths) {
-//         for (const point of path.points) {
-//           if (path.type === "Conveyor") {
-//             const obj = scene.getObjectByProperty("uuid", point.uuid);
-//             if (!obj) {
-//               console.warn(`Object with UUID ${point.uuid} not found in scene`);
-//               continue;
-//             }
-
-//             const position = obj.getWorldPosition(new THREE.Vector3());
-//             animationPath.push(position.clone());
-//             pointActions.push(point.actions);
-//             pointTriggers.push(point.triggers); // Collect triggers for each point
-//           }
-//         }
-//       }
-
-//       return {
-//         id: `process-${Math.random().toString(36).substring(2, 11)}`,
-//         paths,
-//         animationPath,
-//         pointActions,
-//         pointTriggers,
-//         speed: processSpeed,
-//         isActive: false,
-//       };
-//     },
-//     [scene]
-//   );
-
-//   const getAllConnectedPaths = useCallback(
-//     (
-//       initialPath: SimulationPath,
-//       allPaths: SimulationPath[],
-//       visited: Set<string> = new Set()
-//     ): SimulationPath[] => {
-//       const connectedPaths: SimulationPath[] = [];
-//       const queue: SimulationPath[] = [initialPath];
-//       visited.add(initialPath.modeluuid);
-
-//       const pathMap = new Map<string, SimulationPath>();
-//       allPaths.forEach((path) => pathMap.set(path.modeluuid, path));
-
-//       while (queue.length > 0) {
-//         const currentPath = queue.shift()!;
-//         connectedPaths.push(currentPath);
-
-//         // Process outgoing connections
-//         for (const point of currentPath.points) {
-//           for (const target of point.connections.targets) {
-//             if (!visited.has(target.modelUUID)) {
-//               const targetPath = pathMap.get(target.modelUUID);
-//               if (targetPath) {
-//                 visited.add(target.modelUUID);
-//                 queue.push(targetPath);
-//               }
-//             }
-//           }
-//         }
-
-//         // Process incoming connections
-//         for (const [uuid, path] of pathMap) {
-//           if (!visited.has(uuid)) {
-//             const hasConnectionToCurrent = path.points.some((point) =>
-//               point.connections.targets.some(
-//                 (t) => t.modelUUID === currentPath.modeluuid
-//               )
-//             );
-//             if (hasConnectionToCurrent) {
-//               visited.add(uuid);
-//               queue.push(path);
-//             }
-//           }
-//         }
-//       }
-
-//       return connectedPaths;
-//     },
-//     []
-//   );
-
-//   const createProcessesFromPaths = useCallback(
-//     (paths: SimulationPath[]): Process[] => {
-//       if (!paths || paths.length === 0) return [];
-
-//       const visited = new Set<string>();
-//       const processes: Process[] = [];
-//       const pathMap = new Map<string, SimulationPath>();
-//       paths.forEach((path) => pathMap.set(path.modeluuid, path));
-
-//       for (const path of paths) {
-//         if (!visited.has(path.modeluuid) && hasSpawnAction(path)) {
-//           const connectedPaths = getAllConnectedPaths(path, paths, visited);
-//           const adjustedPaths = adjustPathPointsOrder(connectedPaths);
-//           const process = createProcess(adjustedPaths);
-//           processes.push(process);
-//         }
-//       }
-
-//       return processes;
-//     },
-//     [createProcess, getAllConnectedPaths, hasSpawnAction]
-//   );
-
-//   return {
-//     processes,
-//     createProcessesFromPaths,
-//     setProcesses,
-//   };
-// }
-
-// const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
-//   ({ onProcessesCreated }) => {
-//     const { simulationStates } = useSimulationStates();
-//     const { createProcessesFromPaths } = useProcessCreation();
-//     const prevPathsRef = useRef<SimulationPath[]>([]);
-//     const prevProcessesRef = useRef<Process[]>([]);
-
-//     const convertedPaths = useMemo((): SimulationPath[] => {
-//       if (!simulationStates) return [];
-//       return simulationStates.map((path) =>
-//         convertToSimulationPath(
-//           path as ConveyorEventsSchema | VehicleEventsSchema
-//         )
-//       );
-//     }, [simulationStates]);
-
-//     // Enhanced dependency tracking that includes action and trigger types
-//     const pathsDependency = useMemo(() => {
-//       if (!convertedPaths) return null;
-//       return convertedPaths.map((path) => ({
-//         id: path.modeluuid,
-//         // Track all action types for each point
-//         actionSignature: path.points
-//           .map((point, index) =>
-//             point.actions.map((action) => `${index}-${action.type}`).join("|")
-//           )
-//           .join(","),
-//         // Track all trigger types for each point
-//         triggerSignature: path.points
-//           .map((point, index) =>
-//             point.triggers
-//               .map((trigger) => `${index}-${trigger.type}`)
-//               .join("|")
-//           )
-//           .join(","),
-//         connections: path.points
-//           .flatMap((p: PathPoint) =>
-//             p.connections.targets.map((t: { modelUUID: string }) => t.modelUUID)
-//           )
-//           .join(","),
-//         isActive: false,
-//       }));
-//     }, [convertedPaths]);
-
-//     // Force process recreation when paths change
-//     useEffect(() => {
-//       if (!convertedPaths || convertedPaths.length === 0) {
-//         if (prevProcessesRef.current.length > 0) {
-//           onProcessesCreated([]);
-//           prevProcessesRef.current = [];
-//         }
-//         return;
-//       }
-
-//       // Always regenerate processes if the pathsDependency has changed
-//       // This ensures action and trigger type changes will be detected
-//       const newProcesses = createProcessesFromPaths(convertedPaths);
-//       prevPathsRef.current = convertedPaths;
-
-//       // Always update processes when action or trigger types change
-//       onProcessesCreated(newProcesses);
-//       prevProcessesRef.current = newProcesses;
-//     }, [
-//       pathsDependency, // This now includes action and trigger types
-//       onProcessesCreated,
-//       convertedPaths,
-//       createProcessesFromPaths,
-//     ]);
-
-//     return null;
-//   }
-// );
-
-// export default ProcessCreator;
-
 import React, {
   useEffect,
   useMemo,
@@ -456,6 +9,7 @@ import { useSimulationStates } from "../../../store/store";
 import * as THREE from "three";
 import { useThree } from "@react-three/fiber";
 import {
+  ArmBotEventsSchema,
   ConveyorEventsSchema,
   VehicleEventsSchema,
 } from "../../../types/simulation";
@@ -480,13 +34,14 @@ export interface PointTrigger {
   isUsed: boolean;
 }
 
+// Update the connections type in your interfaces
 export interface PathPoint {
   uuid: string;
   position: [number, number, number];
   actions: PointAction[];
   triggers: PointTrigger[];
   connections: {
-    targets: Array<{ modelUUID: string }>;
+    targets: Array<{ modelUUID: string; pointUUID?: string }>;
   };
 }
 
@@ -498,6 +53,14 @@ export interface SimulationPath {
   speed?: number;
   isActive: boolean;
 }
+export interface ArmBot {
+  type: string;
+  modeluuid: string;
+  points: PathPoint[];
+  pathPosition: [number, number, number];
+  speed?: number;
+  isActive: boolean;
+}
 
 export interface Process {
   id: string;
@@ -515,7 +78,7 @@ interface ProcessCreatorProps {
 
 // Convert event schemas to SimulationPath
 function convertToSimulationPath(
-  path: ConveyorEventsSchema | VehicleEventsSchema
+  path: ConveyorEventsSchema | VehicleEventsSchema | ArmBotEventsSchema
 ): SimulationPath {
   const { modeluuid } = path;
 
@@ -539,13 +102,13 @@ function convertToSimulationPath(
         actions: Array.isArray(point.actions)
           ? point.actions.map(normalizeAction)
           : point.actions
-            ? [normalizeAction(point.actions)]
-            : [],
+          ? [normalizeAction(point.actions)]
+          : [],
         triggers: Array.isArray(point.triggers)
           ? point.triggers.map(normalizeTrigger)
           : point.triggers
-            ? [normalizeTrigger(point.triggers)]
-            : [],
+          ? [normalizeTrigger(point.triggers)]
+          : [],
         connections: {
           targets: point.connections.targets.map((target) => ({
             modelUUID: target.modelUUID,
@@ -559,6 +122,36 @@ function convertToSimulationPath(
           : path.speed || 1,
       isActive: false, // Added missing property
     };
+  } else if (path.type === "ArmBot") {
+    return {
+      type: path.type,
+      modeluuid,
+      points: [
+        {
+          uuid: path.points.uuid,
+          position: path.points.position,
+          actions: Array.isArray(path.points.actions)
+            ? path.points.actions.map(normalizeAction)
+            : path.points.actions
+            ? [normalizeAction(path.points.actions)]
+            : [],
+          triggers: Array.isArray(path.points.triggers)
+            ? path.points.triggers.map(normalizeTrigger)
+            : path.points.triggers
+            ? [normalizeTrigger(path.points.triggers)]
+            : [],
+          connections: {
+            targets: path.points.connections.targets.map((target) => ({
+              modelUUID: target.modelUUID,
+              pointUUID: target.pointUUID, // Include if available
+            })),
+          },
+        },
+      ],
+      pathPosition: path.position,
+      speed: path.points.actions?.speed || 1,
+      isActive: false,
+    };
   } else {
     // For vehicle paths, handle the case where triggers might not exist
     return {
@@ -571,8 +164,8 @@ function convertToSimulationPath(
           actions: Array.isArray(path.points.actions)
             ? path.points.actions.map(normalizeAction)
             : path.points.actions
-              ? [normalizeAction(path.points.actions)]
-              : [],
+            ? [normalizeAction(path.points.actions)]
+            : [],
           triggers: [],
           connections: {
             targets: path.points.connections.targets.map((target) => ({
@@ -831,7 +424,10 @@ const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
       if (!simulationStates) return [];
       return simulationStates.map((path) =>
         convertToSimulationPath(
-          path as ConveyorEventsSchema | VehicleEventsSchema
+          path as
+            | ConveyorEventsSchema
+            | VehicleEventsSchema
+            | ArmBotEventsSchema
         )
       );
     }, [simulationStates]);
diff --git a/app/src/modules/simulation/process/types.ts b/app/src/modules/simulation/process/types.ts
index 6f935fc..246e780 100644
--- a/app/src/modules/simulation/process/types.ts
+++ b/app/src/modules/simulation/process/types.ts
@@ -21,15 +21,15 @@ export interface PointAction {
 }
 
 export interface ProcessPoint {
-  uuid: string; 
+  uuid: string;
   position: number[];
-  rotation: number[]; 
-  actions: PointAction[]; 
+  rotation: number[];
+  actions: PointAction[];
   connections: {
-    source: { modelUUID: string; pointUUID: string }; 
-    targets: { modelUUID: string; pointUUID: string }[]; 
+    source: { modelUUID: string; pointUUID: string };
+    targets: { modelUUID: string; pointUUID: string }[];
   };
-  triggers?: Trigger[]; 
+  triggers?: Trigger[];
 }
 export interface ProcessPath {
   modeluuid: string;
@@ -38,8 +38,8 @@ export interface ProcessPath {
   pathPosition: number[];
   pathRotation: number[];
   speed: number;
-  type: "Conveyor" | "Vehicle";
-  isActive: boolean
+  type: "Conveyor" | "Vehicle" | "ArmBot";
+  isActive: boolean;
 }
 
 export interface ProcessData {
diff --git a/app/src/modules/simulation/process/useProcessAnimations.tsx b/app/src/modules/simulation/process/useProcessAnimations.tsx
index 032d013..232f17c 100644
--- a/app/src/modules/simulation/process/useProcessAnimations.tsx
+++ b/app/src/modules/simulation/process/useProcessAnimations.tsx
@@ -1,609 +1,685 @@
 import { useCallback, useEffect, useRef, useState } from "react";
 import * as THREE from "three";
 import {
-    ProcessData,
-    ProcessAnimationState,
-    SpawnedObject,
-    AnimationState,
-    ProcessPoint,
-    PointAction,
-    Trigger,
+  ProcessData,
+  ProcessAnimationState,
+  SpawnedObject,
+  AnimationState,
+  ProcessPoint,
+  PointAction,
+  Trigger,
 } from "./types";
 import {
-    useAnimationPlaySpeed,
-    usePauseButtonStore,
-    usePlayButtonStore,
-    useResetButtonStore,
+  useAnimationPlaySpeed,
+  usePauseButtonStore,
+  usePlayButtonStore,
+  useResetButtonStore,
 } from "../../../store/usePlayButtonStore";
 import { usePlayAgv } from "../../../store/store";
 
+interface ArmBotProcess {
+  triggerId: string;
+  startPoint: string;
+  endPoint: string;
+}
+
 // Enhanced ProcessAnimationState with trigger tracking
 interface EnhancedProcessAnimationState extends ProcessAnimationState {
-    triggerCounts: Record<string, number>;
-    triggerLogs: Array<{
-        timestamp: number;
-        pointId: string;
-        objectId: string;
-        triggerId: string;
-    }>;
+  triggerCounts: Record<string, number>;
+  triggerLogs: Array<{
+    timestamp: number;
+    pointId: string;
+    objectId: string;
+    triggerId: string;
+  }>;
 }
 
 interface ProcessContainerProps {
-    processes: ProcessData[];
-    setProcesses: React.Dispatch<React.SetStateAction<any[]>>;
-    agvRef: any;
+  processes: ProcessData[];
+  setProcesses: React.Dispatch<React.SetStateAction<any[]>>;
+  agvRef: any;
 }
 
 interface PlayAgvState {
-    playAgv: Record<string, any>;
-    setPlayAgv: (data: any) => void;
+  playAgv: Record<string, any>;
+  setPlayAgv: (data: any) => void;
 }
 
 export const useProcessAnimation = (
-    processes: ProcessData[],
-    setProcesses: React.Dispatch<React.SetStateAction<any[]>>,
-    agvRef: any
+  processes: ProcessData[],
+  setProcesses: React.Dispatch<React.SetStateAction<any[]>>,
+  agvRef: any
 ) => {
-    // State and refs initialization
-    const { isPlaying, setIsPlaying } = usePlayButtonStore();
-    const { isPaused, setIsPaused } = usePauseButtonStore();
-    const { isReset, setReset } = useResetButtonStore();
-    const debugRef = useRef<boolean>(false);
-    const clockRef = useRef<THREE.Clock>(new THREE.Clock());
-    const pauseTimeRef = useRef<number>(0);
-    const elapsedBeforePauseRef = useRef<number>(0);
-    const animationStatesRef = useRef<Record<string, EnhancedProcessAnimationState>>({});
-    const { speed } = useAnimationPlaySpeed();
-    const prevIsPlaying = useRef<boolean | null>(null);
-    const [internalResetFlag, setInternalResetFlag] = useState(false);
-    const [animationStates, setAnimationStates] = useState<Record<string, EnhancedProcessAnimationState>>({});
-    const speedRef = useRef<number>(speed);
-    const { PlayAgv, setPlayAgv } = usePlayAgv();
+  // State and refs initialization
+  const { isPlaying, setIsPlaying } = usePlayButtonStore();
+  const { isPaused, setIsPaused } = usePauseButtonStore();
+  const { isReset, setReset } = useResetButtonStore();
+  const debugRef = useRef<boolean>(false);
+  const clockRef = useRef<THREE.Clock>(new THREE.Clock());
+  const pauseTimeRef = useRef<number>(0);
+  const elapsedBeforePauseRef = useRef<number>(0);
+  const animationStatesRef = useRef<
+    Record<string, EnhancedProcessAnimationState>
+  >({});
+  const { speed } = useAnimationPlaySpeed();
+  const prevIsPlaying = useRef<boolean | null>(null);
+  const [internalResetFlag, setInternalResetFlag] = useState(false);
+  const [animationStates, setAnimationStates] = useState<
+    Record<string, EnhancedProcessAnimationState>
+  >({});
+  const speedRef = useRef<number>(speed);
+  const armBotRef = useRef<any[]>([]);
+ 
 
-    // Effect hooks
-    useEffect(() => {
-        speedRef.current = speed;
-    }, [speed]);
+  // Effect hooks
+  useEffect(() => {
+    speedRef.current = speed;
+  }, [speed]);
 
-    useEffect(() => {
-        if (prevIsPlaying.current !== null || !isPlaying) {
-            setAnimationStates({});
-        }
-        prevIsPlaying.current = isPlaying;
-    }, [isPlaying]);
+  useEffect(() => {
+    if (prevIsPlaying.current !== null || !isPlaying) {
+      setAnimationStates({});
+    }
+    prevIsPlaying.current = isPlaying;
+  }, [isPlaying]);
 
-    useEffect(() => {
-        animationStatesRef.current = animationStates;
-    }, [animationStates]);
+  useEffect(() => {
+    animationStatesRef.current = animationStates;
+  }, [animationStates]);
 
-    // Reset handler
-    useEffect(() => {
-        if (isReset) {
-            setInternalResetFlag(true);
-            setIsPlaying(false);
-            setIsPaused(false);
-            setAnimationStates({});
-            animationStatesRef.current = {};
-            clockRef.current = new THREE.Clock();
-            elapsedBeforePauseRef.current = 0;
-            pauseTimeRef.current = 0;
-            setReset(false);
-            setTimeout(() => {
-                setInternalResetFlag(false);
-                setIsPlaying(true);
-            }, 0);
-        }
-    }, [isReset, setReset, setIsPlaying, setIsPaused]);
+  // Reset handler
+  useEffect(() => {
+    if (isReset) {
+      setInternalResetFlag(true);
+      setIsPlaying(false);
+      setIsPaused(false);
+      setAnimationStates({});
+      animationStatesRef.current = {};
+      clockRef.current = new THREE.Clock();
+      elapsedBeforePauseRef.current = 0;
+      pauseTimeRef.current = 0;
+      setReset(false);
+      setTimeout(() => {
+        setInternalResetFlag(false);
+        setIsPlaying(true);
+      }, 0);
+    }
+  }, [isReset, setReset, setIsPlaying, setIsPaused]);
 
-    // Pause handler
-    useEffect(() => {
-        if (isPaused) {
-            pauseTimeRef.current = clockRef.current.getElapsedTime();
-        } else if (pauseTimeRef.current > 0) {
-            const pausedDuration = clockRef.current.getElapsedTime() - pauseTimeRef.current;
-            elapsedBeforePauseRef.current += pausedDuration;
-        }
-    }, [isPaused]);
+  // Pause handler
+  useEffect(() => {
+    if (isPaused) {
+      pauseTimeRef.current = clockRef.current.getElapsedTime();
+    } else if (pauseTimeRef.current > 0) {
+      const pausedDuration =
+        clockRef.current.getElapsedTime() - pauseTimeRef.current;
+      elapsedBeforePauseRef.current += pausedDuration;
+    }
+  }, [isPaused]);
 
-    // Initialize animation states with trigger tracking
-    useEffect(() => {
-        if (isPlaying && !internalResetFlag) {
-            const newStates: Record<string, EnhancedProcessAnimationState> = {};
+  // Initialize animation states with trigger tracking
+  useEffect(() => {
+    if (isPlaying && !internalResetFlag) {
+      const newStates: Record<string, EnhancedProcessAnimationState> = {};
 
-            processes.forEach((process) => {
-                const triggerCounts: Record<string, number> = {};
+      processes.forEach((process) => {
+        const triggerCounts: Record<string, number> = {};
 
-                // Initialize trigger counts for all On-Hit triggers
-                process.paths?.forEach((path) => {
-                    path.points?.forEach((point) => {
-                        point.triggers?.forEach((trigger: Trigger) => {
-                            if (trigger.type === "On-Hit" && trigger.isUsed) {
-                                triggerCounts[`${point.uuid}-${trigger.uuid}`] = 0;
-                            }
-                        });
-                    });
-                });
-
-                newStates[process.id] = {
-                    spawnedObjects: {},
-                    nextSpawnTime: 0,
-                    objectIdCounter: 0,
-                    isProcessDelaying: false,
-                    processDelayStartTime: 0,
-                    processDelayDuration: 0,
-                    triggerCounts,
-                    triggerLogs: [],
-                };
+        // Initialize trigger counts for all On-Hit triggers
+        process.paths?.forEach((path) => {
+          path.points?.forEach((point) => {
+            point.triggers?.forEach((trigger: Trigger) => {
+              if (trigger.type === "On-Hit" && trigger.isUsed) {
+                triggerCounts[`${point.uuid}-${trigger.uuid}`] = 0;
+              }
             });
+          });
+        });
 
-            setAnimationStates(newStates);
-            animationStatesRef.current = newStates;
-            clockRef.current.start();
-        }
-    }, [isPlaying, processes, internalResetFlag]);
+        newStates[process.id] = {
+          spawnedObjects: {},
+          nextSpawnTime: 0,
+          objectIdCounter: 0,
+          isProcessDelaying: false,
+          processDelayStartTime: 0,
+          processDelayDuration: 0,
+          triggerCounts,
+          triggerLogs: [],
+        };
+      });
 
-    useEffect(() => {
-        if (isPlaying && !internalResetFlag) {
-            const newStates: Record<string, EnhancedProcessAnimationState> = {};
+      setAnimationStates(newStates);
+      animationStatesRef.current = newStates;
+      clockRef.current.start();
+    }
+  }, [isPlaying, processes, internalResetFlag]);
 
-            // Initialize AGVs for each process first
-            processes.forEach((process) => {
-                // Find all vehicle paths for this process
-                const vehiclePaths = process.paths?.filter(
-                    (path) => path.type === "Vehicle"
-                ) || [];
+  useEffect(() => {
+    if (isPlaying && !internalResetFlag) {
+      const newStates: Record<string, EnhancedProcessAnimationState> = {};
 
-                // Initialize AGVs for each vehicle path
-                vehiclePaths.forEach((vehiclePath) => {
-                    if (vehiclePath.points?.length > 0) {
-                        const vehiclePoint = vehiclePath.points[0];
-                        const action = vehiclePoint.actions?.[0];
-                        const maxHitCount = action?.hitCount;
+      // Initialize AGVs for each process first
+      processes.forEach((process) => {
+        // Find all vehicle paths for this process
+        const vehiclePaths =
+          process.paths?.filter((path) => path.type === "Vehicle") || [];
 
-                        const vehicleId = vehiclePath.modeluuid;
-                        const processId = process.id;
+        // Initialize AGVs for each vehicle path
+        vehiclePaths.forEach((vehiclePath) => {
+          if (vehiclePath.points?.length > 0) {
+            const vehiclePoint = vehiclePath.points[0];
+            const action = vehiclePoint.actions?.[0];
+            const maxHitCount = action?.hitCount;
 
-                        // Check if this AGV already exists
-                        const existingAgv = agvRef.current.find(
-                            (v: any) => v.vehicleId === vehicleId && v.processId === processId
-                        );
+            const vehicleId = vehiclePath.modeluuid;
+            const processId = process.id;
 
-                        if (!existingAgv) {
-                            // Initialize the AGV in a stationed state
-                            agvRef.current.push({
-                                processId,
-                                vehicleId,
-                                maxHitCount: maxHitCount || 0,
-                                isActive: false,
-                                hitCount: 0,
-                                status: 'stationed',
-                                lastUpdated: 0
-                            });
-                        }
-                    }
-                });
-
-                // Then initialize trigger counts as before
-                const triggerCounts: Record<string, number> = {};
-                process.paths?.forEach((path) => {
-                    path.points?.forEach((point) => {
-                        point.triggers?.forEach((trigger: Trigger) => {
-                            if (trigger.type === "On-Hit" && trigger.isUsed) {
-                                triggerCounts[`${point.uuid}-${trigger.uuid}`] = 0;
-                            }
-                        });
-                    });
-                });
-
-                newStates[process.id] = {
-                    spawnedObjects: {},
-                    nextSpawnTime: 0,
-                    objectIdCounter: 0,
-                    isProcessDelaying: false,
-                    processDelayStartTime: 0,
-                    processDelayDuration: 0,
-                    triggerCounts,
-                    triggerLogs: [],
-                };
-            });
-
-            setAnimationStates(newStates);
-            animationStatesRef.current = newStates;
-            clockRef.current.start();
-        }
-    }, [isPlaying, processes, internalResetFlag]);
-
-    // Helper functions
-    const findSpawnPoint = (process: ProcessData): ProcessPoint | null => {
-        for (const path of process.paths || []) {
-            for (const point of path.points || []) {
-                const spawnAction = point.actions?.find(
-                    (a) => a.isUsed && a.type === "Spawn"
-                );
-                if (spawnAction) {
-                    return point;
-                }
-            }
-        }
-        return null;
-    };
-
-    const findAnimationPathPoint = (
-        process: ProcessData,
-        spawnPoint: ProcessPoint
-    ): THREE.Vector3 => {
-        if (process.animationPath && process.animationPath.length > 0) {
-            let pointIndex = 0;
-            for (const path of process.paths || []) {
-                for (let i = 0; i < (path.points?.length || 0); i++) {
-                    const point = path.points?.[i];
-                    if (point && point.uuid === spawnPoint.uuid) {
-                        if (process.animationPath[pointIndex]) {
-                            const p = process.animationPath[pointIndex];
-                            return new THREE.Vector3(p.x, p.y, p.z);
-                        }
-                    }
-                    pointIndex++;
-                }
-            }
-        }
-        return new THREE.Vector3(
-            spawnPoint.position[0],
-            spawnPoint.position[1],
-            spawnPoint.position[2]
-        );
-    };
-
-    // Optimized object creation
-    const createSpawnedObject = useCallback(
-        (
-            process: ProcessData,
-            currentTime: number,
-            materialType: string,
-            spawnPoint: ProcessPoint,
-            baseMaterials: Record<string, THREE.Material>
-        ): SpawnedObject => {
-            const processMaterials = {
-                ...baseMaterials,
-                ...(process.customMaterials || {}),
-            };
-
-            const spawnPosition = findAnimationPathPoint(process, spawnPoint);
-            const material =
-                processMaterials[materialType as keyof typeof processMaterials] ||
-                baseMaterials.Default;
-
-            return {
-                ref: { current: null },
-                state: {
-                    currentIndex: 0,
-                    progress: 0,
-                    isAnimating: true,
-                    speed: process.speed || 1,
-                    isDelaying: false,
-                    delayStartTime: 0,
-                    currentDelayDuration: 0,
-                    delayComplete: false,
-                    currentPathIndex: 0,
-                },
-                visible: true,
-                material: material,
-                currentMaterialType: materialType,
-                spawnTime: currentTime,
-                position: spawnPosition,
-            };
-        },
-        []
-    );
-
-    // Material handling
-    const handleMaterialSwap = useCallback(
-        (
-            processId: string,
-            objectId: string,
-            materialType: string,
-            processes: ProcessData[],
-            baseMaterials: Record<string, THREE.Material>
-        ) => {
-            setAnimationStates((prev) => {
-                const processState = prev[processId];
-                if (!processState || !processState.spawnedObjects[objectId])
-                    return prev;
-
-                const process = processes.find((p) => p.id === processId);
-                if (!process) return prev;
-
-                const processMaterials = {
-                    ...baseMaterials,
-                    ...(process.customMaterials || {}),
-                };
-
-                const newMaterial =
-                    processMaterials[materialType as keyof typeof processMaterials];
-                if (!newMaterial) return prev;
-
-                return {
-                    ...prev,
-                    [processId]: {
-                        ...processState,
-                        spawnedObjects: {
-                            ...processState.spawnedObjects,
-                            [objectId]: {
-                                ...processState.spawnedObjects[objectId],
-                                material: newMaterial,
-                                currentMaterialType: materialType,
-                            },
-                        },
-                    },
-                };
-            });
-        },
-        []
-    );
-
-    // Point action handler with trigger counting
-    const handlePointActions = useCallback(
-        (
-            processId: string,
-            objectId: string,
-            actions: PointAction[] = [],
-            currentTime: number,
-            processes: ProcessData[],
-            baseMaterials: Record<string, THREE.Material>
-        ): boolean => {
-            let shouldStopAnimation = false;
-
-            actions.forEach((action) => {
-                if (!action.isUsed) return;
-
-                switch (action.type) {
-                    case "Delay":
-                        setAnimationStates((prev) => {
-                            const processState = prev[processId];
-                            if (!processState || processState.isProcessDelaying) return prev;
-
-                            const delayDuration =
-                                typeof action.delay === "number"
-                                    ? action.delay
-                                    : parseFloat(action.delay as string) || 0;
-
-                            if (delayDuration > 0) {
-                                return {
-                                    ...prev,
-                                    [processId]: {
-                                        ...processState,
-                                        isProcessDelaying: true,
-                                        processDelayStartTime: currentTime,
-                                        processDelayDuration: delayDuration,
-                                        spawnedObjects: {
-                                            ...processState.spawnedObjects,
-                                            [objectId]: {
-                                                ...processState.spawnedObjects[objectId],
-                                                state: {
-                                                    ...processState.spawnedObjects[objectId].state,
-                                                    isAnimating: false,
-                                                    isDelaying: true,
-                                                    delayStartTime: currentTime,
-                                                    currentDelayDuration: delayDuration,
-                                                    delayComplete: false,
-                                                },
-                                            },
-                                        },
-                                    },
-                                };
-                            }
-                            return prev;
-                        });
-                        shouldStopAnimation = true;
-                        break;
-
-                    case "Despawn":
-                        setAnimationStates((prev) => {
-                            const processState = prev[processId];
-                            if (!processState) return prev;
-
-                            const newSpawnedObjects = { ...processState.spawnedObjects };
-                            delete newSpawnedObjects[objectId];
-
-                            return {
-                                ...prev,
-                                [processId]: {
-                                    ...processState,
-                                    spawnedObjects: newSpawnedObjects,
-                                },
-                            };
-                        });
-                        shouldStopAnimation = true;
-                        break;
-
-                    case "Swap":
-                        if (action.material) {
-                            handleMaterialSwap(
-                                processId,
-                                objectId,
-                                action.material,
-                                processes,
-                                baseMaterials
-                            );
-                        }
-                        break;
-
-                    default:
-                        break;
-                }
-            });
-
-            return shouldStopAnimation;
-        },
-        [handleMaterialSwap]
-    );
-
-    // Trigger counting system
-    const checkAndCountTriggers = useCallback(
-        (
-            processId: string,
-            objectId: string,
-            currentPointIndex: number,
-            processes: ProcessData[],
-            currentTime: number
-        ) => {
-            setAnimationStates((prev) => {
-                const processState = prev[processId];
-                if (!processState) return prev;
-
-                const process = processes.find((p) => p.id === processId);
-                if (!process) return prev;
-
-                const point = getPointDataForAnimationIndex(process, currentPointIndex);
-                if (!point?.triggers) return prev;
-
-                const onHitTriggers = point.triggers.filter(
-                    (t: Trigger) => t.type === "On-Hit" && t.isUsed
-                );
-                if (onHitTriggers.length === 0) return prev;
-
-                let newTriggerCounts = { ...processState.triggerCounts };
-                const newTriggerLogs = [...processState.triggerLogs];
-                let shouldLog = false;
-
-                // Find all vehicle paths for this process
-                const vehiclePaths = process.paths.filter(
-                    (path) => path.type === "Vehicle"
-                );
-
-                // Check if any vehicle is active for this process
-                const activeVehicles = vehiclePaths.filter(path => {
-                    const vehicleId = path.modeluuid;
-                    const vehicleEntry = agvRef.current.find(
-                        (v: any) => v.vehicleId === vehicleId && v.processId === processId
-                    );
-                    return vehicleEntry?.isActive;
-                });
-
-                // Only count triggers if no vehicles are active for this process
-                if (activeVehicles.length === 0) {
-                    onHitTriggers.forEach((trigger: Trigger) => {
-                        const triggerKey = `${point.uuid}-${trigger.uuid}`;
-                        newTriggerCounts[triggerKey] = (newTriggerCounts[triggerKey] || 0) + 1;
-                        shouldLog = true;
-                        newTriggerLogs.push({
-                            timestamp: currentTime,
-                            pointId: point.uuid,
-                            objectId,
-                            triggerId: trigger.uuid,
-                        });
-                    });
-                }
-
-                let processTotalHits = Object.values(newTriggerCounts).reduce((a, b) => a + b, 0);
-
-                if (shouldLog) {
-                    vehiclePaths.forEach((vehiclePath) => {
-                        if (vehiclePath.points?.length > 0) {
-                            const vehiclePoint = vehiclePath.points[0];
-                            const action = vehiclePoint.actions?.[0];
-                            const maxHitCount = action?.hitCount;
-
-                            if (maxHitCount !== undefined) {
-                                const vehicleId = vehiclePath.modeluuid;
-                                let vehicleEntry = agvRef.current.find((v: any) => v.vehicleId === vehicleId && v.processId === processId);
-
-                                if (!vehicleEntry) {
-                                    vehicleEntry = {
-                                        processId,
-                                        vehicleId,
-                                        maxHitCount: maxHitCount,
-                                        isActive: false,
-                                        hitCount: 0,
-                                        status: 'stationed'
-                                    };
-                                    agvRef.current.push(vehicleEntry);
-                                }
-
-                                // if (!vehicleEntry.isActive && vehicleEntry.status === 'picking') {
-                                if (!vehicleEntry.isActive) {
-                                    vehicleEntry.hitCount = processTotalHits;
-                                    vehicleEntry.lastUpdated = currentTime;
-
-                                    if (vehicleEntry.hitCount >= vehicleEntry.maxHitCount) {
-                                        vehicleEntry.isActive = true;
-                                        newTriggerCounts = {};
-                                        processTotalHits = 0;
-                                    }
-                                }
-                            }
-                        }
-                    });
-                }
-
-                return {
-                    ...prev,
-                    [processId]: {
-                        ...processState,
-                        triggerCounts: newTriggerCounts,
-                        triggerLogs: newTriggerLogs,
-                        totalHits: processTotalHits,
-                    },
-                };
-            });
-        },
-        []
-    );
-
-    // Utility functions
-    const hasNonInheritActions = useCallback(
-        (actions: PointAction[] = []): boolean => {
-            return actions.some(
-                (action) => action.isUsed && action.type !== "Inherit"
+            // Check if this AGV already exists
+            const existingAgv = agvRef.current.find(
+              (v: any) => v.vehicleId === vehicleId && v.processId === processId
             );
-        },
-        []
+
+            if (!existingAgv) {
+              // Initialize the AGV in a stationed state
+              agvRef.current.push({
+                processId,
+                vehicleId,
+                maxHitCount: maxHitCount || 0,
+                isActive: false,
+                hitCount: 0,
+                status: "stationed",
+                lastUpdated: 0,
+              });
+            }
+          }
+        });
+
+        // Then initialize trigger counts as before
+        const triggerCounts: Record<string, number> = {};
+        process.paths?.forEach((path) => {
+          path.points?.forEach((point) => {
+            point.triggers?.forEach((trigger: Trigger) => {
+              if (trigger.type === "On-Hit" && trigger.isUsed) {
+                triggerCounts[`${point.uuid}-${trigger.uuid}`] = 0;
+              }
+            });
+          });
+        });
+
+        newStates[process.id] = {
+          spawnedObjects: {},
+          nextSpawnTime: 0,
+          objectIdCounter: 0,
+          isProcessDelaying: false,
+          processDelayStartTime: 0,
+          processDelayDuration: 0,
+          triggerCounts,
+          triggerLogs: [],
+        };
+      });
+
+      setAnimationStates(newStates);
+      animationStatesRef.current = newStates;
+      clockRef.current.start();
+    }
+  }, [isPlaying, processes, internalResetFlag]);
+
+  // Helper functions
+  const findSpawnPoint = (process: ProcessData): ProcessPoint | null => {
+    for (const path of process.paths || []) {
+      for (const point of path.points || []) {
+        const spawnAction = point.actions?.find(
+          (a) => a.isUsed && a.type === "Spawn"
+        );
+        if (spawnAction) {
+          return point;
+        }
+      }
+    }
+    return null;
+  };
+
+  const findAnimationPathPoint = (
+    process: ProcessData,
+    spawnPoint: ProcessPoint
+  ): THREE.Vector3 => {
+    if (process.animationPath && process.animationPath.length > 0) {
+      let pointIndex = 0;
+      for (const path of process.paths || []) {
+        for (let i = 0; i < (path.points?.length || 0); i++) {
+          const point = path.points?.[i];
+          if (point && point.uuid === spawnPoint.uuid) {
+            if (process.animationPath[pointIndex]) {
+              const p = process.animationPath[pointIndex];
+              return new THREE.Vector3(p.x, p.y, p.z);
+            }
+          }
+          pointIndex++;
+        }
+      }
+    }
+    return new THREE.Vector3(
+      spawnPoint.position[0],
+      spawnPoint.position[1],
+      spawnPoint.position[2]
     );
+  };
 
-    const getPointDataForAnimationIndex = useCallback(
-        (process: ProcessData, index: number): ProcessPoint | null => {
-            if (!process.paths) return null;
+  // Optimized object creation
+  const createSpawnedObject = useCallback(
+    (
+      process: ProcessData,
+      currentTime: number,
+      materialType: string,
+      spawnPoint: ProcessPoint,
+      baseMaterials: Record<string, THREE.Material>
+    ): SpawnedObject => {
+      const processMaterials = {
+        ...baseMaterials,
+        ...(process.customMaterials || {}),
+      };
 
-            let cumulativePoints = 0;
-            for (const path of process.paths) {
-                const pointCount = path.points?.length || 0;
+      const spawnPosition = findAnimationPathPoint(process, spawnPoint);
+      const material =
+        processMaterials[materialType as keyof typeof processMaterials] ||
+        baseMaterials.Default;
 
-                if (index < cumulativePoints + pointCount) {
-                    const pointIndex = index - cumulativePoints;
-                    return path.points?.[pointIndex] || null;
+      return {
+        ref: { current: null },
+        state: {
+          currentIndex: 0,
+          progress: 0,
+          isAnimating: true,
+          speed: process.speed || 1,
+          isDelaying: false,
+          delayStartTime: 0,
+          currentDelayDuration: 0,
+          delayComplete: false,
+          currentPathIndex: 0,
+        },
+        visible: true,
+        material: material,
+        currentMaterialType: materialType,
+        spawnTime: currentTime,
+        position: spawnPosition,
+      };
+    },
+    []
+  );
+
+  // Material handling
+  const handleMaterialSwap = useCallback(
+    (
+      processId: string,
+      objectId: string,
+      materialType: string,
+      processes: ProcessData[],
+      baseMaterials: Record<string, THREE.Material>
+    ) => {
+      setAnimationStates((prev) => {
+        const processState = prev[processId];
+        if (!processState || !processState.spawnedObjects[objectId])
+          return prev;
+
+        const process = processes.find((p) => p.id === processId);
+        if (!process) return prev;
+
+        const processMaterials = {
+          ...baseMaterials,
+          ...(process.customMaterials || {}),
+        };
+
+        const newMaterial =
+          processMaterials[materialType as keyof typeof processMaterials];
+        if (!newMaterial) return prev;
+
+        return {
+          ...prev,
+          [processId]: {
+            ...processState,
+            spawnedObjects: {
+              ...processState.spawnedObjects,
+              [objectId]: {
+                ...processState.spawnedObjects[objectId],
+                material: newMaterial,
+                currentMaterialType: materialType,
+              },
+            },
+          },
+        };
+      });
+    },
+    []
+  );
+
+  // Point action handler with trigger counting
+  const handlePointActions = useCallback(
+    (
+      processId: string,
+      objectId: string,
+      actions: PointAction[] = [],
+      currentTime: number,
+      processes: ProcessData[],
+      baseMaterials: Record<string, THREE.Material>
+    ): boolean => {
+      let shouldStopAnimation = false;
+
+      actions.forEach((action) => {
+        if (!action.isUsed) return;
+
+        switch (action.type) {
+          case "Delay":
+            setAnimationStates((prev) => {
+              const processState = prev[processId];
+              if (!processState || processState.isProcessDelaying) return prev;
+
+              const delayDuration =
+                typeof action.delay === "number"
+                  ? action.delay
+                  : parseFloat(action.delay as string) || 0;
+
+              if (delayDuration > 0) {
+                return {
+                  ...prev,
+                  [processId]: {
+                    ...processState,
+                    isProcessDelaying: true,
+                    processDelayStartTime: currentTime,
+                    processDelayDuration: delayDuration,
+                    spawnedObjects: {
+                      ...processState.spawnedObjects,
+                      [objectId]: {
+                        ...processState.spawnedObjects[objectId],
+                        state: {
+                          ...processState.spawnedObjects[objectId].state,
+                          isAnimating: false,
+                          isDelaying: true,
+                          delayStartTime: currentTime,
+                          currentDelayDuration: delayDuration,
+                          delayComplete: false,
+                        },
+                      },
+                    },
+                  },
+                };
+              }
+              return prev;
+            });
+            shouldStopAnimation = true;
+            break;
+
+          case "Despawn":
+            setAnimationStates((prev) => {
+              const processState = prev[processId];
+              if (!processState) return prev;
+
+              const newSpawnedObjects = { ...processState.spawnedObjects };
+              delete newSpawnedObjects[objectId];
+
+              return {
+                ...prev,
+                [processId]: {
+                  ...processState,
+                  spawnedObjects: newSpawnedObjects,
+                },
+              };
+            });
+            shouldStopAnimation = true;
+            break;
+
+          case "Swap":
+            if (action.material) {
+              handleMaterialSwap(
+                processId,
+                objectId,
+                action.material,
+                processes,
+                baseMaterials
+              );
+            }
+            break;
+
+          default:
+            break;
+        }
+      });
+
+      return shouldStopAnimation;
+    },
+    [handleMaterialSwap]
+  );
+
+  // Trigger counting system
+  const checkAndCountTriggers = useCallback(
+    (
+      processId: string,
+      objectId: string,
+      currentPointIndex: number,
+      processes: ProcessData[],
+      currentTime: number
+    ) => {
+      setAnimationStates((prev) => {
+        const processState = prev[processId];
+        if (!processState) return prev;
+
+        const process = processes.find((p) => p.id === processId);
+        if (!process) return prev;
+
+        const point = getPointDataForAnimationIndex(process, currentPointIndex);
+        if (!point?.triggers) return prev;
+
+        const onHitTriggers = point.triggers.filter(
+          (t: Trigger) => t.type === "On-Hit" && t.isUsed
+        );
+
+        if (onHitTriggers.length === 0) return prev;
+
+        let newTriggerCounts = { ...processState.triggerCounts };
+        const newTriggerLogs = [...processState.triggerLogs];
+        let shouldLog = false;
+
+        // Find all vehicle paths for this process
+        const vehiclePaths = process.paths.filter(
+          (path) => path.type === "Vehicle"
+        );
+
+        // Find all ArmBot paths for this process
+        const armBotPaths = process.paths.filter(
+          (path) => path.type === "ArmBot"
+        );
+
+        // Check if any vehicle is active for this process
+        const activeVehicles = vehiclePaths.filter((path) => {
+          const vehicleId = path.modeluuid;
+          const vehicleEntry = agvRef.current.find(
+            (v: any) => v.vehicleId === vehicleId && v.processId === processId
+          );
+          return vehicleEntry?.isActive;
+        });
+
+        // Check if any ArmBot is active for this process
+        const activeArmBots = armBotPaths.filter((path) => {
+          const armBotId = path.modeluuid;
+          const armBotEntry = armBotRef.current.find(
+            (a: any) => a.armBotId === armBotId && a.processId === processId
+          );
+          return armBotEntry?.isActive;
+        });
+
+        // Only count triggers if no vehicles and no ArmBots are active for this process
+        if (activeVehicles.length === 0 && activeArmBots.length === 0) {
+          onHitTriggers.forEach((trigger: Trigger) => {
+            const triggerKey = `${point.uuid}-${trigger.uuid}`;
+            newTriggerCounts[triggerKey] =
+              (newTriggerCounts[triggerKey] || 0) + 1;
+            shouldLog = true;
+            newTriggerLogs.push({
+              timestamp: currentTime,
+              pointId: point.uuid,
+              objectId,
+              triggerId: trigger.uuid,
+            });
+          });
+        }
+
+        let processTotalHits = Object.values(newTriggerCounts).reduce(
+          (a, b) => a + b,
+          0
+        );
+
+        // Handle logic for vehicles and ArmBots when a trigger is hit
+        if (shouldLog) {
+          // Handle vehicle logic (existing code)
+          vehiclePaths.forEach((vehiclePath) => {
+            if (vehiclePath.points?.length > 0) {
+              const vehiclePoint = vehiclePath.points[0];
+              const action = vehiclePoint.actions?.[0];
+              const maxHitCount = action?.hitCount;
+
+              if (maxHitCount !== undefined) {
+                const vehicleId = vehiclePath.modeluuid;
+                let vehicleEntry = agvRef.current.find(
+                  (v: any) =>
+                    v.vehicleId === vehicleId && v.processId === processId
+                );
+
+                if (!vehicleEntry) {
+                  vehicleEntry = {
+                    processId,
+                    vehicleId,
+                    maxHitCount: maxHitCount,
+                    isActive: false,
+                    hitCount: 0,
+                    status: "stationed",
+                  };
+                  agvRef.current.push(vehicleEntry);
                 }
 
-                cumulativePoints += pointCount;
+                if (!vehicleEntry.isActive) {
+                  vehicleEntry.hitCount++;
+                  vehicleEntry.lastUpdated = currentTime;
+
+                  if (vehicleEntry.hitCount >= vehicleEntry.maxHitCount) {
+                    vehicleEntry.isActive = true;
+                    newTriggerCounts = {};
+                    processTotalHits = 0;
+                  }
+                }
+              }
             }
+          });
 
-            return null;
-        },
-        []
-    );
+          // Handle ArmBot logic (new code)
+          armBotPaths.forEach((armBotPath) => {
+            if (armBotPath.points?.length > 0) {
+              const armBotPoint = armBotPath.points[0];
+              const action = armBotPoint.actions?.[0];
+              const maxHitCount = action?.hitCount;
 
-    const getTriggerCounts = useCallback((processId: string) => {
-        return animationStatesRef.current[processId]?.triggerCounts || {};
-    }, []);
+              if (maxHitCount !== undefined) {
+                const armBotId = armBotPath.modeluuid;
+                let armBotEntry = armBotRef.current.find(
+                  (a: any) =>
+                    a.armBotId === armBotId && a.processId === processId
+                );
 
-    const getTriggerLogs = useCallback((processId: string) => {
-        return animationStatesRef.current[processId]?.triggerLogs || [];
-    }, []);
+                if (!armBotEntry) {
+                  armBotEntry = {
+                    processId,
+                    armBotId,
+                    maxHitCount: maxHitCount,
+                    isActive: false,
+                    hitCount: 0,
+                    status: "stationed",
+                  };
+                  armBotRef.current.push(armBotEntry);
+                  console.log('armBotEntry: ', armBotEntry);
+                }
 
-    return {
-        animationStates,
-        setAnimationStates,
-        clockRef,
-        elapsedBeforePauseRef,
-        speedRef,
-        debugRef,
-        findSpawnPoint,
-        createSpawnedObject,
-        handlePointActions,
-        hasNonInheritActions,
-        getPointDataForAnimationIndex,
-        checkAndCountTriggers,
-        getTriggerCounts,
-        getTriggerLogs,
-        processes,
-    };
+                if (!armBotEntry.isActive) {
+                  armBotEntry.hitCount++;
+                  armBotEntry.lastUpdated = currentTime;
+
+                  if (armBotEntry.hitCount >= armBotEntry.maxHitCount) {
+                    armBotEntry.isActive = true;
+                    // Reset trigger counts when ArmBot activates, similar to vehicle
+                    newTriggerCounts = {};
+                    processTotalHits = 0;
+                  }
+                }
+              }
+            }
+          });
+        }
+
+        return {
+          ...prev,
+          [processId]: {
+            ...processState,
+            triggerCounts: newTriggerCounts,
+            triggerLogs: newTriggerLogs,
+            totalHits: processTotalHits,
+          },
+        };
+      });
+    },
+    []
+  );
+
+  // Utility functions
+  const hasNonInheritActions = useCallback(
+    (actions: PointAction[] = []): boolean => {
+      return actions.some(
+        (action) => action.isUsed && action.type !== "Inherit"
+      );
+    },
+    []
+  );
+
+  const getPointDataForAnimationIndex = useCallback(
+    (process: ProcessData, index: number): ProcessPoint | null => {
+      if (!process.paths) return null;
+
+      let cumulativePoints = 0;
+      for (const path of process.paths) {
+        const pointCount = path.points?.length || 0;
+
+        if (index < cumulativePoints + pointCount) {
+          const pointIndex = index - cumulativePoints;
+          return path.points?.[pointIndex] || null;
+        }
+
+        cumulativePoints += pointCount;
+      }
+
+      return null;
+    },
+    []
+  );
+
+  const getTriggerCounts = useCallback((processId: string) => {
+    return animationStatesRef.current[processId]?.triggerCounts || {};
+  }, []);
+
+  const getTriggerLogs = useCallback((processId: string) => {
+    return animationStatesRef.current[processId]?.triggerLogs || [];
+  }, []);
+
+  return {
+    animationStates,
+    setAnimationStates,
+    clockRef,
+    elapsedBeforePauseRef,
+    speedRef,
+    debugRef,
+    findSpawnPoint,
+    createSpawnedObject,
+    handlePointActions,
+    hasNonInheritActions,
+    getPointDataForAnimationIndex,
+    checkAndCountTriggers,
+    getTriggerCounts,
+    getTriggerLogs,
+    processes,
+  };
 };
diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx
index b1f961e..fb789ec 100644
--- a/app/src/modules/simulation/simulation.tsx
+++ b/app/src/modules/simulation/simulation.tsx
@@ -11,8 +11,10 @@ function Simulation() {
   const { activeModule } = useModuleStore();
   const pathsGroupRef = useRef() as React.MutableRefObject<THREE.Group>;
   const [processes, setProcesses] = useState<any[]>([]);
+
   const agvRef = useRef([]);
   const MaterialRef = useRef([]);
+  const { simulationStates } = useSimulationStates();
 
   return (
     <>

From a26e0dacd08d743bcfd55a9e2169e45bb0eed921 Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B <jerald@hexrfactory.com>
Date: Wed, 16 Apr 2025 10:03:01 +0530
Subject: [PATCH 07/20] Implement code changes to enhance functionality and
 improve performance

---
 .../controls/selection/selectionControls.tsx  |  978 +++---
 .../modules/simulation/path/pathConnector.tsx | 2784 ++++++++---------
 2 files changed, 1646 insertions(+), 2116 deletions(-)

diff --git a/app/src/modules/scene/controls/selection/selectionControls.tsx b/app/src/modules/scene/controls/selection/selectionControls.tsx
index aa2bca4..ece6924 100644
--- a/app/src/modules/scene/controls/selection/selectionControls.tsx
+++ b/app/src/modules/scene/controls/selection/selectionControls.tsx
@@ -3,13 +3,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
 import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox";
 import { SelectionHelper } from "./selectionHelper";
 import { useFrame, useThree } from "@react-three/fiber";
-import {
-  useFloorItems,
-  useSelectedAssets,
-  useSimulationStates,
-  useSocketStore,
-  useToggleView,
-} from "../../../../store/store";
+import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView, } from "../../../../store/store";
 import BoundingBox from "./boundingBoxHelper";
 import { toast } from "react-toastify";
 // import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
@@ -23,574 +17,446 @@ import RotateControls from "./rotateControls";
 import useModuleStore from "../../../../store/useModuleStore";
 
 const SelectionControls: React.FC = () => {
-  const { camera, controls, gl, scene, pointer } = useThree();
-  const itemsGroupRef = useRef<THREE.Group | undefined>(undefined);
-  const selectionGroup = useRef() as Types.RefGroup;
-  const { toggleView } = useToggleView();
-  const { simulationStates, setSimulationStates } = useSimulationStates();
-  const { selectedAssets, setSelectedAssets } = useSelectedAssets();
-  const [movedObjects, setMovedObjects] = useState<THREE.Object3D[]>([]);
-  const [rotatedObjects, setRotatedObjects] = useState<THREE.Object3D[]>([]);
-  const [copiedObjects, setCopiedObjects] = useState<THREE.Object3D[]>([]);
-  const [pastedObjects, setpastedObjects] = useState<THREE.Object3D[]>([]);
-  const [duplicatedObjects, setDuplicatedObjects] = useState<THREE.Object3D[]>(
-    []
-  );
-  const boundingBoxRef = useRef<THREE.Mesh>();
-  const { floorItems, setFloorItems } = useFloorItems();
-  const { activeModule } = useModuleStore();
-  const { socket } = useSocketStore();
-  const selectionBox = useMemo(
-    () => new SelectionBox(camera, scene),
-    [camera, scene]
-  );
+    const { camera, controls, gl, scene, pointer } = useThree();
+    const itemsGroupRef = useRef<THREE.Group | undefined>(undefined);
+    const selectionGroup = useRef() as Types.RefGroup;
+    const { toggleView } = useToggleView();
+    const { simulationStates, setSimulationStates } = useSimulationStates();
+    const { selectedAssets, setSelectedAssets } = useSelectedAssets();
+    const [movedObjects, setMovedObjects] = useState<THREE.Object3D[]>([]);
+    const [rotatedObjects, setRotatedObjects] = useState<THREE.Object3D[]>([]);
+    const [copiedObjects, setCopiedObjects] = useState<THREE.Object3D[]>([]);
+    const [pastedObjects, setpastedObjects] = useState<THREE.Object3D[]>([]);
+    const [duplicatedObjects, setDuplicatedObjects] = useState<THREE.Object3D[]>([]);
+    const boundingBoxRef = useRef<THREE.Mesh>();
+    const { floorItems, setFloorItems } = useFloorItems();
+    const { activeModule } = useModuleStore();
+    const { socket } = useSocketStore();
+    const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]);
 
-  useEffect(() => {
-    if (!camera || !scene || toggleView) return;
+    useEffect(() => {
+        if (!camera || !scene || toggleView) return;
 
-    const canvasElement = gl.domElement;
-    canvasElement.tabIndex = 0;
+        const canvasElement = gl.domElement;
+        canvasElement.tabIndex = 0;
 
-    const itemsGroup: any = scene.getObjectByName("itemsGroup");
-    itemsGroupRef.current = itemsGroup;
+        const itemsGroup: any = scene.getObjectByName("itemsGroup");
+        itemsGroupRef.current = itemsGroup;
 
-    let isSelecting = false;
-    let isRightClick = false;
-    let rightClickMoved = false;
-    let isCtrlSelecting = false;
+        let isSelecting = false;
+        let isRightClick = false;
+        let rightClickMoved = false;
+        let isCtrlSelecting = false;
 
-    const helper = new SelectionHelper(gl);
+        const helper = new SelectionHelper(gl);
 
-    if (!itemsGroup) {
-      toast.warn("itemsGroup not found in the scene.");
-      return;
-    }
-
-    const onPointerDown = (event: PointerEvent) => {
-      if (event.button === 2) {
-        isRightClick = true;
-        rightClickMoved = false;
-      } else if (event.button === 0) {
-        isSelecting = false;
-        isCtrlSelecting = event.ctrlKey;
-        if (event.ctrlKey && duplicatedObjects.length === 0) {
-          if (controls) (controls as any).enabled = false;
-          selectionBox.startPoint.set(pointer.x, pointer.y, 0);
+        if (!itemsGroup) {
+            toast.warn("itemsGroup not found in the scene.");
+            return;
         }
-      }
-    };
 
-    const onPointerMove = (event: PointerEvent) => {
-      if (isRightClick) {
-        rightClickMoved = true;
-      }
-      isSelecting = true;
-      if (
-        helper.isDown &&
-        event.ctrlKey &&
-        duplicatedObjects.length === 0 &&
-        isCtrlSelecting
-      ) {
-        selectionBox.endPoint.set(pointer.x, pointer.y, 0);
-      }
-    };
-
-    const onPointerUp = (event: PointerEvent) => {
-      if (event.button === 2) {
-        isRightClick = false;
-        if (!rightClickMoved) {
-          clearSelection();
-        }
-        return;
-      }
-
-      if (isSelecting && isCtrlSelecting) {
-        isCtrlSelecting = false;
-        isSelecting = false;
-        if (event.ctrlKey && duplicatedObjects.length === 0) {
-          selectAssets();
-        }
-      } else if (
-        !isSelecting &&
-        selectedAssets.length > 0 &&
-        ((pastedObjects.length === 0 &&
-          duplicatedObjects.length === 0 &&
-          movedObjects.length === 0 &&
-          rotatedObjects.length === 0) ||
-          event.button !== 0)
-      ) {
-        clearSelection();
-        helper.enabled = true;
-        isCtrlSelecting = false;
-      }
-    };
-
-    const onKeyDown = (event: KeyboardEvent) => {
-      if (movedObjects.length > 0 || rotatedObjects.length > 0) return;
-      if (event.key.toLowerCase() === "escape") {
-        event.preventDefault();
-        clearSelection();
-      }
-      if (event.key.toLowerCase() === "delete") {
-        event.preventDefault();
-        deleteSelection();
-      }
-    };
-
-    const onContextMenu = (event: MouseEvent) => {
-      event.preventDefault();
-      if (!rightClickMoved) {
-        clearSelection();
-      }
-    };
-
-    if (!toggleView && activeModule === "builder") {
-      helper.enabled = true;
-      if (duplicatedObjects.length === 0 && pastedObjects.length === 0) {
-        canvasElement.addEventListener("pointerdown", onPointerDown);
-        canvasElement.addEventListener("pointermove", onPointerMove);
-        canvasElement.addEventListener("pointerup", onPointerUp);
-      } else {
-        helper.enabled = false;
-        helper.dispose();
-      }
-      canvasElement.addEventListener("contextmenu", onContextMenu);
-      canvasElement.addEventListener("keydown", onKeyDown);
-    } else {
-      helper.enabled = false;
-      helper.dispose();
-    }
-
-    return () => {
-      canvasElement.removeEventListener("pointerdown", onPointerDown);
-      canvasElement.removeEventListener("pointermove", onPointerMove);
-      canvasElement.removeEventListener("contextmenu", onContextMenu);
-      canvasElement.removeEventListener("pointerup", onPointerUp);
-      canvasElement.removeEventListener("keydown", onKeyDown);
-      helper.enabled = false;
-      helper.dispose();
-    };
-  }, [
-    camera,
-    controls,
-    scene,
-    toggleView,
-    selectedAssets,
-    copiedObjects,
-    pastedObjects,
-    duplicatedObjects,
-    movedObjects,
-    socket,
-    floorItems,
-    rotatedObjects,
-    activeModule,
-  ]);
-
-  useEffect(() => {
-    if (activeModule !== "builder") {
-      clearSelection();
-    }
-  }, [activeModule]);
-
-  useFrame(() => {
-    if (
-      pastedObjects.length === 0 &&
-      duplicatedObjects.length === 0 &&
-      movedObjects.length === 0 &&
-      rotatedObjects.length === 0
-    ) {
-      selectionGroup.current.position.set(0, 0, 0);
-    }
-  });
-
-  const selectAssets = () => {
-    selectionBox.endPoint.set(pointer.x, pointer.y, 0);
-    if (controls) (controls as any).enabled = true;
-
-    let selectedObjects = selectionBox.select();
-    let Objects = new Set<THREE.Object3D>();
-
-    selectedObjects.map((object) => {
-      let currentObject: THREE.Object3D | null = object;
-      while (currentObject) {
-        if (currentObject.userData.modelId) {
-          Objects.add(currentObject);
-          break;
-        }
-        currentObject = currentObject.parent || null;
-      }
-    });
-
-    if (Objects.size === 0) {
-      clearSelection();
-      return;
-    }
-
-    const updatedSelections = new Set(selectedAssets);
-    Objects.forEach((obj) => {
-      updatedSelections.has(obj)
-        ? updatedSelections.delete(obj)
-        : updatedSelections.add(obj);
-    });
-
-    const selected = Array.from(updatedSelections);
-
-    setSelectedAssets(selected);
-  };
-
-  const clearSelection = () => {
-    selectionGroup.current.children = [];
-    selectionGroup.current.position.set(0, 0, 0);
-    selectionGroup.current.rotation.set(0, 0, 0);
-    setpastedObjects([]);
-    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,
-        //   updatedPath.modeluuid,
-        //   { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
-        // );
-
-        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") {
-        // await setEventApi(
-        //     organization,
-        //     updatedPath.modeluuid,
-        //     { type: "Vehicle", points: updatedPath.points }
-        // );
-
-        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") {
-        // await setEventApi(
-        //     organization,
-        //     updatedPath.modeluuid,
-        //     { type: "StaticMachine", points: updatedPath.points }
-        // );
-
-        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") {
-        // await setEventApi(
-        //     organization,
-        //     updatedPath.modeluuid,
-        //     { type: "ArmBot", points: updatedPath.points }
-        // );
-
-        const data = {
-          organization: organization,
-          modeluuid: updatedPath.modeluuid,
-          eventData: { type: "ArmBot", points: updatedPath.points },
-        };
-
-        socket.emit("v2:model-asset:updateEventData", data);
-      }
-    });
-  };
-
-  const removeConnections = (deletedModelUUIDs: string[]) => {
-    const updatedStates = simulationStates.map((state) => {
-      // 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);
-  };
-
-  const deleteSelection = () => {
-    if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
-      const email = localStorage.getItem("email");
-      const organization = email!.split("@")[1].split(".")[0];
-
-      const storedItems = JSON.parse(
-        localStorage.getItem("FloorItems") || "[]"
-      );
-      const selectedUUIDs = selectedAssets.map(
-        (mesh: THREE.Object3D) => mesh.uuid
-      );
-
-      const updatedStoredItems = storedItems.filter(
-        (item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid)
-      );
-      localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems));
-
-      selectedAssets.forEach((selectedMesh: THREE.Object3D) => {
-        //REST
-
-        // const response = await deleteFloorItem(organization, selectedMesh.uuid, selectedMesh.userData.name);
-
-        //SOCKET
-
-        const data = {
-          organization: organization,
-          modeluuid: selectedMesh.uuid,
-          modelname: selectedMesh.userData.name,
-          socketId: socket.id,
-        };
-
-        socket.emit("v2:model-asset:delete", data);
-
-        selectedMesh.traverse((child: THREE.Object3D) => {
-          if (child instanceof THREE.Mesh) {
-            if (child.geometry) child.geometry.dispose();
-            if (Array.isArray(child.material)) {
-              child.material.forEach((material) => {
-                if (material.map) material.map.dispose();
-                material.dispose();
-              });
-            } else if (child.material) {
-              if (child.material.map) child.material.map.dispose();
-              child.material.dispose();
+        const onPointerDown = (event: PointerEvent) => {
+            if (event.button === 2) {
+                isRightClick = true;
+                rightClickMoved = false;
+            } else if (event.button === 0) {
+                isSelecting = false;
+                isCtrlSelecting = event.ctrlKey;
+                if (event.ctrlKey && duplicatedObjects.length === 0) {
+                    if (controls) (controls as any).enabled = false;
+                    selectionBox.startPoint.set(pointer.x, pointer.y, 0);
+                }
+            }
+        };
+
+        const onPointerMove = (event: PointerEvent) => {
+            if (isRightClick) {
+                rightClickMoved = true;
+            }
+            isSelecting = true;
+            if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) {
+                selectionBox.endPoint.set(pointer.x, pointer.y, 0);
+            }
+        };
+
+        const onPointerUp = (event: PointerEvent) => {
+            if (event.button === 2) {
+                isRightClick = false;
+                if (!rightClickMoved) {
+                    clearSelection();
+                }
+                return;
+            }
+
+            if (isSelecting && isCtrlSelecting) {
+                isCtrlSelecting = false;
+                isSelecting = false;
+                if (event.ctrlKey && duplicatedObjects.length === 0) {
+                    selectAssets();
+                }
+            } else if (!isSelecting && selectedAssets.length > 0 && ((pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) || event.button !== 0)) {
+                clearSelection();
+                helper.enabled = true;
+                isCtrlSelecting = false;
+            }
+        };
+
+        const onKeyDown = (event: KeyboardEvent) => {
+            if (movedObjects.length > 0 || rotatedObjects.length > 0) return;
+            if (event.key.toLowerCase() === "escape") {
+                event.preventDefault();
+                clearSelection();
+            }
+            if (event.key.toLowerCase() === "delete") {
+                event.preventDefault();
+                deleteSelection();
+            }
+        };
+
+        const onContextMenu = (event: MouseEvent) => {
+            event.preventDefault();
+            if (!rightClickMoved) {
+                clearSelection();
+            }
+        };
+
+        if (!toggleView && activeModule === "builder") {
+            helper.enabled = true;
+            if (duplicatedObjects.length === 0 && pastedObjects.length === 0) {
+                canvasElement.addEventListener("pointerdown", onPointerDown);
+                canvasElement.addEventListener("pointermove", onPointerMove);
+                canvasElement.addEventListener("pointerup", onPointerUp);
+            } else {
+                helper.enabled = false;
+                helper.dispose();
+            }
+            canvasElement.addEventListener("contextmenu", onContextMenu);
+            canvasElement.addEventListener("keydown", onKeyDown);
+        } else {
+            helper.enabled = false;
+            helper.dispose();
+        }
+
+        return () => {
+            canvasElement.removeEventListener("pointerdown", onPointerDown);
+            canvasElement.removeEventListener("pointermove", onPointerMove);
+            canvasElement.removeEventListener("contextmenu", onContextMenu);
+            canvasElement.removeEventListener("pointerup", onPointerUp);
+            canvasElement.removeEventListener("keydown", onKeyDown);
+            helper.enabled = false;
+            helper.dispose();
+        };
+    }, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, floorItems, rotatedObjects, activeModule,]);
+
+    useEffect(() => {
+        if (activeModule !== "builder") {
+            clearSelection();
+        }
+    }, [activeModule]);
+
+    useFrame(() => {
+        if (pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
+            selectionGroup.current.position.set(0, 0, 0);
+        }
+    });
+
+    const selectAssets = () => {
+        selectionBox.endPoint.set(pointer.x, pointer.y, 0);
+        if (controls) (controls as any).enabled = true;
+
+        let selectedObjects = selectionBox.select();
+        let Objects = new Set<THREE.Object3D>();
+
+        selectedObjects.map((object) => {
+            let currentObject: THREE.Object3D | null = object;
+            while (currentObject) {
+                if (currentObject.userData.modelId) {
+                    Objects.add(currentObject);
+                    break;
+                }
+                currentObject = currentObject.parent || null;
             }
-          }
         });
 
-        setSimulationStates(
-          (
-            prevEvents: (
-              | SimulationTypes.ConveyorEventsSchema
-              | SimulationTypes.VehicleEventsSchema
-              | SimulationTypes.StaticMachineEventsSchema
-              | SimulationTypes.ArmBotEventsSchema
-            )[]
-          ) => {
-            const updatedEvents = (prevEvents || []).filter(
-              (event) => event.modeluuid !== selectedMesh.uuid
-            );
-            return updatedEvents;
-          }
-        );
+        if (Objects.size === 0) {
+            clearSelection();
+            return;
+        }
 
-        itemsGroupRef.current?.remove(selectedMesh);
-      });
+        const updatedSelections = new Set(selectedAssets);
+        Objects.forEach((obj) => { updatedSelections.has(obj) ? updatedSelections.delete(obj) : updatedSelections.add(obj); });
 
-      const allUUIDs = selectedAssets.map((val: any) => val.uuid);
-      removeConnections(allUUIDs);
+        const selected = Array.from(updatedSelections);
 
-      const updatedItems = floorItems.filter(
-        (item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid)
-      );
-      setFloorItems(updatedItems);
-    }
-    toast.success("Selected models removed!");
-    clearSelection();
-  };
+        setSelectedAssets(selected);
+    };
 
-  return (
-    <>
-      <group name="SelectionGroup">
-        <group ref={selectionGroup} name="selectionAssetGroup">
-          <BoundingBox boundingBoxRef={boundingBoxRef} />
-        </group>
-      </group>
+    const clearSelection = () => {
+        selectionGroup.current.children = [];
+        selectionGroup.current.position.set(0, 0, 0);
+        selectionGroup.current.rotation.set(0, 0, 0);
+        setpastedObjects([]);
+        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] : "";
 
-      <MoveControls
-        movedObjects={movedObjects}
-        setMovedObjects={setMovedObjects}
-        itemsGroupRef={itemsGroupRef}
-        copiedObjects={copiedObjects}
-        setCopiedObjects={setCopiedObjects}
-        pastedObjects={pastedObjects}
-        setpastedObjects={setpastedObjects}
-        duplicatedObjects={duplicatedObjects}
-        setDuplicatedObjects={setDuplicatedObjects}
-        rotatedObjects={rotatedObjects}
-        setRotatedObjects={setRotatedObjects}
-        selectionGroup={selectionGroup}
-        boundingBoxRef={boundingBoxRef}
-      />
+        updatedPaths.forEach(async (updatedPath) => {
+            if (updatedPath.type === "Conveyor") {
+                // await setEventApi(
+                //   organization,
+                //   updatedPath.modeluuid,
+                //   { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
+                // );
 
-      <RotateControls
-        rotatedObjects={rotatedObjects}
-        setRotatedObjects={setRotatedObjects}
-        movedObjects={movedObjects}
-        setMovedObjects={setMovedObjects}
-        itemsGroupRef={itemsGroupRef}
-        copiedObjects={copiedObjects}
-        setCopiedObjects={setCopiedObjects}
-        pastedObjects={pastedObjects}
-        setpastedObjects={setpastedObjects}
-        duplicatedObjects={duplicatedObjects}
-        setDuplicatedObjects={setDuplicatedObjects}
-        selectionGroup={selectionGroup}
-        boundingBoxRef={boundingBoxRef}
-      />
+                const data = {
+                    organization: organization,
+                    modeluuid: updatedPath.modeluuid,
+                    eventData: {
+                        type: "Conveyor",
+                        points: updatedPath.points,
+                        speed: updatedPath.speed,
+                    },
+                };
 
-      <DuplicationControls
-        itemsGroupRef={itemsGroupRef}
-        duplicatedObjects={duplicatedObjects}
-        setDuplicatedObjects={setDuplicatedObjects}
-        setpastedObjects={setpastedObjects}
-        selectionGroup={selectionGroup}
-        movedObjects={movedObjects}
-        setMovedObjects={setMovedObjects}
-        rotatedObjects={rotatedObjects}
-        setRotatedObjects={setRotatedObjects}
-        boundingBoxRef={boundingBoxRef}
-      />
+                socket.emit("v2:model-asset:updateEventData", data);
+            } else if (updatedPath.type === "Vehicle") {
+                // await setEventApi(
+                //     organization,
+                //     updatedPath.modeluuid,
+                //     { type: "Vehicle", points: updatedPath.points }
+                // );
 
-      <CopyPasteControls
-        itemsGroupRef={itemsGroupRef}
-        copiedObjects={copiedObjects}
-        setCopiedObjects={setCopiedObjects}
-        pastedObjects={pastedObjects}
-        setpastedObjects={setpastedObjects}
-        selectionGroup={selectionGroup}
-        setDuplicatedObjects={setDuplicatedObjects}
-        movedObjects={movedObjects}
-        setMovedObjects={setMovedObjects}
-        rotatedObjects={rotatedObjects}
-        setRotatedObjects={setRotatedObjects}
-        boundingBoxRef={boundingBoxRef}
-      />
-    </>
-  );
+                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") {
+                // await setEventApi(
+                //     organization,
+                //     updatedPath.modeluuid,
+                //     { type: "StaticMachine", points: updatedPath.points }
+                // );
+
+                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") {
+                // await setEventApi(
+                //     organization,
+                //     updatedPath.modeluuid,
+                //     { type: "ArmBot", points: updatedPath.points }
+                // );
+
+                const data = {
+                    organization: organization,
+                    modeluuid: updatedPath.modeluuid,
+                    eventData: { type: "ArmBot", points: updatedPath.points },
+                };
+
+                socket.emit("v2:model-asset:updateEventData", data);
+            }
+        });
+    };
+
+    const removeConnections = (deletedModelUUIDs: string[]) => {
+        const updatedStates = simulationStates.map((state) => {
+            // 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);
+    };
+
+    const deleteSelection = () => {
+        if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
+            const email = localStorage.getItem("email");
+            const organization = email!.split("@")[1].split(".")[0];
+
+            const storedItems = JSON.parse(localStorage.getItem("FloorItems") || "[]");
+            const selectedUUIDs = selectedAssets.map((mesh: THREE.Object3D) => mesh.uuid);
+
+            const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid));
+            localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems));
+
+            selectedAssets.forEach((selectedMesh: THREE.Object3D) => {
+                //REST
+
+                // const response = await deleteFloorItem(organization, selectedMesh.uuid, selectedMesh.userData.name);
+
+                //SOCKET
+
+                const data = {
+                    organization: organization,
+                    modeluuid: selectedMesh.uuid,
+                    modelname: selectedMesh.userData.name,
+                    socketId: socket.id,
+                };
+
+                socket.emit("v2:model-asset:delete", data);
+
+                selectedMesh.traverse((child: THREE.Object3D) => {
+                    if (child instanceof THREE.Mesh) {
+                        if (child.geometry) child.geometry.dispose();
+                        if (Array.isArray(child.material)) {
+                            child.material.forEach((material) => {
+                                if (material.map) material.map.dispose();
+                                material.dispose();
+                            });
+                        } else if (child.material) {
+                            if (child.material.map) child.material.map.dispose();
+                            child.material.dispose();
+                        }
+                    }
+                });
+
+                setSimulationStates((prevEvents: (| SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
+                    const updatedEvents = (prevEvents || []).filter((event) => event.modeluuid !== selectedMesh.uuid);
+                    return updatedEvents;
+                });
+
+                itemsGroupRef.current?.remove(selectedMesh);
+            });
+
+            const allUUIDs = selectedAssets.map((val: any) => val.uuid);
+            removeConnections(allUUIDs);
+
+            const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid));
+            setFloorItems(updatedItems);
+        }
+        toast.success("Selected models removed!");
+        clearSelection();
+    };
+
+    return (
+        <>
+            <group name="SelectionGroup">
+                <group ref={selectionGroup} name="selectionAssetGroup">
+                    <BoundingBox boundingBoxRef={boundingBoxRef} />
+                </group>
+            </group>
+
+            <MoveControls movedObjects={movedObjects} setMovedObjects={setMovedObjects} itemsGroupRef={itemsGroupRef} copiedObjects={copiedObjects} setCopiedObjects={setCopiedObjects} pastedObjects={pastedObjects} setpastedObjects={setpastedObjects} duplicatedObjects={duplicatedObjects} setDuplicatedObjects={setDuplicatedObjects} rotatedObjects={rotatedObjects} setRotatedObjects={setRotatedObjects} selectionGroup={selectionGroup} boundingBoxRef={boundingBoxRef} />
+
+            <RotateControls rotatedObjects={rotatedObjects} setRotatedObjects={setRotatedObjects} movedObjects={movedObjects} setMovedObjects={setMovedObjects} itemsGroupRef={itemsGroupRef} copiedObjects={copiedObjects} setCopiedObjects={setCopiedObjects} pastedObjects={pastedObjects} setpastedObjects={setpastedObjects} duplicatedObjects={duplicatedObjects} setDuplicatedObjects={setDuplicatedObjects} selectionGroup={selectionGroup} boundingBoxRef={boundingBoxRef} />
+
+            <DuplicationControls itemsGroupRef={itemsGroupRef} duplicatedObjects={duplicatedObjects} setDuplicatedObjects={setDuplicatedObjects} setpastedObjects={setpastedObjects} selectionGroup={selectionGroup} movedObjects={movedObjects} setMovedObjects={setMovedObjects} rotatedObjects={rotatedObjects} setRotatedObjects={setRotatedObjects} boundingBoxRef={boundingBoxRef} />
+
+            <CopyPasteControls itemsGroupRef={itemsGroupRef} copiedObjects={copiedObjects} setCopiedObjects={setCopiedObjects} pastedObjects={pastedObjects} setpastedObjects={setpastedObjects} selectionGroup={selectionGroup} setDuplicatedObjects={setDuplicatedObjects} movedObjects={movedObjects} setMovedObjects={setMovedObjects} rotatedObjects={rotatedObjects} setRotatedObjects={setRotatedObjects} boundingBoxRef={boundingBoxRef} />
+        </>
+    );
 };
 
 export default SelectionControls;
diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx
index 9a49f39..4ca12a2 100644
--- a/app/src/modules/simulation/path/pathConnector.tsx
+++ b/app/src/modules/simulation/path/pathConnector.tsx
@@ -4,1616 +4,1280 @@ 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 { 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<THREE.Group>;
-}) {
-  const { activeModule } = useModuleStore();
-  const { gl, raycaster, scene, pointer, camera } = useThree();
-  const { deleteTool } = useDeleteTool();
-  const { renderDistance } = useRenderDistance();
-  const { setIsConnecting } = useIsConnecting();
-  const { simulationStates, setSimulationStates } = useSimulationStates();
-  const { isPlaying } = usePlayButtonStore();
-  const { socket } = useSocketStore();
-  const groupRefs = useRef<{ [key: string]: any }>({});
+function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObject<THREE.Group>; }) {
+    const { activeModule } = useModuleStore();
+    const { gl, raycaster, scene, pointer, camera } = useThree();
+    const { deleteTool } = useDeleteTool();
+    const { renderDistance } = useRenderDistance();
+    const { setIsConnecting } = useIsConnecting();
+    const { simulationStates, setSimulationStates } = useSimulationStates();
+    const { isPlaying } = usePlayButtonStore();
+    const { socket } = useSocketStore();
+    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<string>("red");
-  const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
+    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<string>("red");
+    const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
 
-  const updatePathConnections = (
-    fromModelUUID: string,
-    fromPointUUID: string,
-    toModelUUID: string,
-    toPointUUID: string
-  ) => {
-    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) => {
-              if (point.uuid === fromPointUUID) {
-                const newTarget = {
-                  modelUUID: toModelUUID,
-                  pointUUID: toPointUUID,
-                };
-                const existingTargets = point.connections.targets || [];
+    const updatePathConnections = (fromModelUUID: string, fromPointUUID: string, toModelUUID: string, toPointUUID: string) => {
+        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) => {
+                            if (point.uuid === fromPointUUID) {
+                                const newTarget = {
+                                    modelUUID: toModelUUID,
+                                    pointUUID: toPointUUID,
+                                };
+                                const existingTargets = point.connections.targets || [];
 
-                if (
-                  !existingTargets.some(
-                    (target) =>
-                      target.modelUUID === newTarget.modelUUID &&
-                      target.pointUUID === newTarget.pointUUID
-                  )
-                ) {
-                  return {
-                    ...point,
-                    connections: {
-                      ...point.connections,
-                      targets: [...existingTargets, newTarget],
-                    },
-                  };
+                                if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) {
+                                    return {
+                                        ...point,
+                                        connections: {
+                                            ...point.connections,
+                                            targets: [...existingTargets, newTarget],
+                                        },
+                                    };
+                                }
+                            }
+                            return point;
+                        }),
+                    };
                 }
-              }
-              return point;
-            }),
-          };
-        }
-        // Handle incoming connections to Conveyor
-        else if (path.modeluuid === toModelUUID) {
-          return {
-            ...path,
-            points: path.points.map((point) => {
-              if (point.uuid === toPointUUID) {
-                const reverseTarget = {
-                  modelUUID: fromModelUUID,
-                  pointUUID: fromPointUUID,
-                };
-                const existingTargets = point.connections.targets || [];
+                // Handle incoming connections to Conveyor
+                else if (path.modeluuid === toModelUUID) {
+                    return {
+                        ...path,
+                        points: path.points.map((point) => {
+                            if (point.uuid === toPointUUID) {
+                                const reverseTarget = {
+                                    modelUUID: fromModelUUID,
+                                    pointUUID: fromPointUUID,
+                                };
+                                const existingTargets = point.connections.targets || [];
 
-                if (
-                  !existingTargets.some(
-                    (target) =>
-                      target.modelUUID === reverseTarget.modelUUID &&
-                      target.pointUUID === reverseTarget.pointUUID
-                  )
-                ) {
-                  return {
-                    ...point,
-                    connections: {
-                      ...point.connections,
-                      targets: [...existingTargets, reverseTarget],
-                    },
-                  };
+                                if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) {
+                                    return {
+                                        ...point,
+                                        connections: {
+                                            ...point.connections,
+                                            targets: [...existingTargets, reverseTarget],
+                                        },
+                                    };
+                                }
+                            }
+                            return point;
+                        }),
+                    };
                 }
-              }
-              return point;
-            }),
-          };
-        }
-      } else if (path.type === "Vehicle") {
-        // Handle outgoing connections from Vehicle
-        if (
-          path.modeluuid === fromModelUUID &&
-          path.points.uuid === fromPointUUID
-        ) {
-          const newTarget = {
-            modelUUID: toModelUUID,
-            pointUUID: toPointUUID,
-          };
-          const existingTargets = path.points.connections.targets || [];
+            } else if (path.type === "Vehicle") {
+                // Handle outgoing connections from Vehicle
+                if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
+                    const newTarget = {
+                        modelUUID: toModelUUID,
+                        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") {
-            console.log("Vehicle can only connect to Conveyors");
-            return path;
-          }
-
-          // Check if already has a connection
-          if (existingTargets.length >= 1) {
-            console.log("Vehicle can have only one connection");
-            return path;
-          }
-
-          if (
-            !existingTargets.some(
-              (target) =>
-                target.modelUUID === newTarget.modelUUID &&
-                target.pointUUID === newTarget.pointUUID
-            )
-          ) {
-            return {
-              ...path,
-              points: {
-                ...path.points,
-                connections: {
-                  ...path.points.connections,
-                  targets: [...existingTargets, newTarget],
-                },
-              },
-            };
-          }
-        }
-        // Handle incoming connections to Vehicle
-        else if (
-          path.modeluuid === toModelUUID &&
-          path.points.uuid === toPointUUID
-        ) {
-          const reverseTarget = {
-            modelUUID: fromModelUUID,
-            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") {
-            console.log("Vehicle can only connect to Conveyors");
-            return path;
-          }
-
-          // Check if already has a connection
-          if (existingTargets.length >= 1) {
-            console.log("Vehicle can have only one connection");
-            return path;
-          }
-
-          if (
-            !existingTargets.some(
-              (target) =>
-                target.modelUUID === reverseTarget.modelUUID &&
-                target.pointUUID === reverseTarget.pointUUID
-            )
-          ) {
-            return {
-              ...path,
-              points: {
-                ...path.points,
-                connections: {
-                  ...path.points.connections,
-                  targets: [...existingTargets, reverseTarget],
-                },
-              },
-            };
-          }
-        }
-        return path;
-      } else if (path.type === "StaticMachine") {
-        // Handle outgoing connections from StaticMachine
-        if (
-          path.modeluuid === fromModelUUID &&
-          path.points.uuid === fromPointUUID
-        ) {
-          const newTarget = {
-            modelUUID: toModelUUID,
-            pointUUID: toPointUUID,
-          };
-
-          // Ensure target is an ArmBot
-          const toPath = simulationStates.find(
-            (p) => p.modeluuid === toModelUUID
-          );
-          if (toPath?.type !== "ArmBot") {
-            console.log("StaticMachine can only connect to ArmBot");
-            return path;
-          }
-
-          const existingTargets = path.points.connections.targets || [];
-
-          // Allow only one connection
-          if (existingTargets.length >= 1) {
-            console.log("StaticMachine can only have one connection");
-            return path;
-          }
-
-          if (
-            !existingTargets.some(
-              (target) =>
-                target.modelUUID === newTarget.modelUUID &&
-                target.pointUUID === newTarget.pointUUID
-            )
-          ) {
-            return {
-              ...path,
-              points: {
-                ...path.points,
-                connections: {
-                  ...path.points.connections,
-                  targets: [...existingTargets, newTarget],
-                },
-              },
-            };
-          }
-        }
-
-        // Handle incoming connections to StaticMachine
-        else if (
-          path.modeluuid === toModelUUID &&
-          path.points.uuid === toPointUUID
-        ) {
-          const reverseTarget = {
-            modelUUID: fromModelUUID,
-            pointUUID: fromPointUUID,
-          };
-
-          const fromPath = simulationStates.find(
-            (p) => p.modeluuid === fromModelUUID
-          );
-          if (fromPath?.type !== "ArmBot") {
-            console.log("StaticMachine can only be connected from ArmBot");
-            return path;
-          }
-
-          const existingTargets = path.points.connections.targets || [];
-
-          if (existingTargets.length >= 1) {
-            console.log("StaticMachine can only have one connection");
-            return path;
-          }
-
-          if (
-            !existingTargets.some(
-              (target) =>
-                target.modelUUID === reverseTarget.modelUUID &&
-                target.pointUUID === reverseTarget.pointUUID
-            )
-          ) {
-            return {
-              ...path,
-              points: {
-                ...path.points,
-                connections: {
-                  ...path.points.connections,
-                  targets: [...existingTargets, reverseTarget],
-                },
-              },
-            };
-          }
-        }
-        return path;
-      } else if (path.type === "ArmBot") {
-        // Handle outgoing connections from ArmBot
-        if (
-          path.modeluuid === fromModelUUID &&
-          path.points.uuid === fromPointUUID
-        ) {
-          const newTarget = {
-            modelUUID: toModelUUID,
-            pointUUID: toPointUUID,
-          };
-
-          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";
-          });
-
-          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
-            )
-          ) {
-            return {
-              ...path,
-              points: {
-                ...path.points,
-                connections: {
-                  ...path.points.connections,
-                  targets: [...existingTargets, newTarget],
-                },
-              },
-            };
-          }
-        }
-
-        // Handle incoming connections to ArmBot
-        else if (
-          path.modeluuid === toModelUUID &&
-          path.points.uuid === toPointUUID
-        ) {
-          const reverseTarget = {
-            modelUUID: fromModelUUID,
-            pointUUID: fromPointUUID,
-          };
-
-          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";
-          });
-
-          if (fromPath.type === "StaticMachine") {
-            if (alreadyConnectedFromStatic) {
-              console.log(
-                "ArmBot can only be connected from one StaticMachine"
-              );
-              return path;
-            }
-          }
-
-          if (
-            !existingTargets.some(
-              (target) =>
-                target.modelUUID === reverseTarget.modelUUID &&
-                target.pointUUID === reverseTarget.pointUUID
-            )
-          ) {
-            return {
-              ...path,
-              points: {
-                ...path.points,
-                connections: {
-                  ...path.points.connections,
-                  targets: [...existingTargets, reverseTarget],
-                },
-              },
-            };
-          }
-        }
-        return path;
-      }
-
-      return path;
-    });
-
-    setSimulationStates(updatedPaths);
-
-    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
-    )[]
-  ) => {
-    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,
-        //   updatedPath.modeluuid,
-        //   { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
-        // );
-
-        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") {
-        // await setEventApi(
-        //     organization,
-        //     updatedPath.modeluuid,
-        //     { type: "Vehicle", points: updatedPath.points }
-        // );
-
-        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") {
-        // await setEventApi(
-        //     organization,
-        //     updatedPath.modeluuid,
-        //     { type: "StaticMachine", points: updatedPath.points }
-        // );
-
-        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") {
-        // await setEventApi(
-        //     organization,
-        //     updatedPath.modeluuid,
-        //     { type: "ArmBot", points: updatedPath.points }
-        // );
-
-        const data = {
-          organization: organization,
-          modeluuid: updatedPath.modeluuid,
-          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);
-    setFirstSelected(null);
-    setCurrentLine(null);
-    setIsConnecting(false);
-  };
-
-  useEffect(() => {
-    const canvasElement = gl.domElement;
-    let drag = false;
-    let MouseDown = false;
-
-    const onMouseDown = () => {
-      MouseDown = true;
-      drag = false;
-    };
-
-    const onMouseUp = () => {
-      MouseDown = false;
-    };
-
-    const onMouseMove = () => {
-      if (MouseDown) {
-        drag = true;
-      }
-    };
-
-    const onContextMenu = (evt: MouseEvent) => {
-      evt.preventDefault();
-      if (drag || evt.button === 0) return;
-
-      raycaster.setFromCamera(pointer, camera);
-      const intersects = raycaster.intersectObjects(
-        pathsGroupRef.current.children,
-        true
-      );
-
-      if (intersects.length > 0) {
-        const intersected = intersects[0].object;
-
-        if (intersected.name.includes("events-sphere")) {
-          const modelUUID = intersected.userData.path.modeluuid;
-          const sphereUUID = intersected.uuid;
-          const worldPosition = new THREE.Vector3();
-          intersected.getWorldPosition(worldPosition);
-
-          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);
-          } 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
-            );
-
-            // Prevent vehicle-to-vehicle connections
-            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)
-            ) {
-              console.log(
-                "Conveyor connections must be between start/end points"
-              );
-              return;
-            }
-
-            // Check if this specific connection already exists
-            const isDuplicateConnection = firstSelected
-              ? 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
-                      );
-                    } else if (path.type === "Vehicle") {
-                      return path.points.connections.targets.some(
-                        (t) =>
-                          t.modelUUID === modelUUID &&
-                          t.pointUUID === sphereUUID
-                      );
+                    // Check if target is a Conveyor
+                    const toPath = simulationStates.find((p) => p.modeluuid === toModelUUID);
+                    if (toPath?.type !== "Conveyor") {
+                        console.log("Vehicle can only connect to Conveyors");
+                        return path;
                     }
-                  }
-                  return false;
-                })
-              : false;
 
-            if (isDuplicateConnection) {
-              console.log("These points are already connected. Ignoring.");
-              return;
+                    // Check if already has a connection
+                    if (existingTargets.length >= 1) {
+                        console.log("Vehicle can have only one connection");
+                        return path;
+                    }
+
+                    if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) {
+                        return {
+                            ...path,
+                            points: {
+                                ...path.points,
+                                connections: {
+                                    ...path.points.connections,
+                                    targets: [...existingTargets, newTarget],
+                                },
+                            },
+                        };
+                    }
+                }
+                // Handle incoming connections to Vehicle
+                else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
+                    const reverseTarget = {
+                        modelUUID: fromModelUUID,
+                        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") {
+                        console.log("Vehicle can only connect to Conveyors");
+                        return path;
+                    }
+
+                    // Check if already has a connection
+                    if (existingTargets.length >= 1) {
+                        console.log("Vehicle can have only one connection");
+                        return path;
+                    }
+
+                    if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) {
+                        return {
+                            ...path,
+                            points: {
+                                ...path.points,
+                                connections: {
+                                    ...path.points.connections,
+                                    targets: [...existingTargets, reverseTarget],
+                                },
+                            },
+                        };
+                    }
+                }
+                return path;
+            } else if (path.type === "StaticMachine") {
+                // Handle outgoing connections from StaticMachine
+                if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
+                    const newTarget = {
+                        modelUUID: toModelUUID,
+                        pointUUID: toPointUUID,
+                    };
+
+                    // Ensure target is an ArmBot
+                    const toPath = simulationStates.find((p) => p.modeluuid === toModelUUID);
+                    if (toPath?.type !== "ArmBot") {
+                        console.log("StaticMachine can only connect to ArmBot");
+                        return path;
+                    }
+
+                    const existingTargets = path.points.connections.targets || [];
+
+                    // Allow only one connection
+                    if (existingTargets.length >= 1) {
+                        console.log("StaticMachine can only have one connection");
+                        return path;
+                    }
+
+                    if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) {
+                        return {
+                            ...path,
+                            points: {
+                                ...path.points,
+                                connections: {
+                                    ...path.points.connections,
+                                    targets: [...existingTargets, newTarget],
+                                },
+                            },
+                        };
+                    }
+                }
+
+                // Handle incoming connections to StaticMachine
+                else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
+                    const reverseTarget = {
+                        modelUUID: fromModelUUID,
+                        pointUUID: fromPointUUID,
+                    };
+
+                    const fromPath = simulationStates.find((p) => p.modeluuid === fromModelUUID);
+                    if (fromPath?.type !== "ArmBot") {
+                        console.log("StaticMachine can only be connected from ArmBot");
+                        return path;
+                    }
+
+                    const existingTargets = path.points.connections.targets || [];
+
+                    if (existingTargets.length >= 1) {
+                        console.log("StaticMachine can only have one connection");
+                        return path;
+                    }
+
+                    if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) {
+                        return {
+                            ...path,
+                            points: {
+                                ...path.points,
+                                connections: {
+                                    ...path.points.connections,
+                                    targets: [...existingTargets, reverseTarget],
+                                },
+                            },
+                        };
+                    }
+                }
+                return path;
+            } else if (path.type === "ArmBot") {
+                // Handle outgoing connections from ArmBot
+                if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
+                    const newTarget = {
+                        modelUUID: toModelUUID,
+                        pointUUID: toPointUUID,
+                    };
+
+                    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";
+                    });
+
+                    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)) {
+                        return {
+                            ...path,
+                            points: {
+                                ...path.points,
+                                connections: {
+                                    ...path.points.connections,
+                                    targets: [...existingTargets, newTarget],
+                                },
+                            },
+                        };
+                    }
+                }
+
+                // Handle incoming connections to ArmBot
+                else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
+                    const reverseTarget = {
+                        modelUUID: fromModelUUID,
+                        pointUUID: fromPointUUID,
+                    };
+
+                    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";
+                    });
+
+                    if (fromPath.type === "StaticMachine") {
+                        if (alreadyConnectedFromStatic) {
+                            console.log(
+                                "ArmBot can only be connected from one StaticMachine"
+                            );
+                            return path;
+                        }
+                    }
+
+                    if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) {
+                        return {
+                            ...path,
+                            points: {
+                                ...path.points,
+                                connections: {
+                                    ...path.points.connections,
+                                    targets: [...existingTargets, reverseTarget],
+                                },
+                            },
+                        };
+                    }
+                }
+                return path;
             }
 
-            // 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 (vehicleConnections >= 1) {
-                console.log("Vehicle can only have one connection");
-                return;
-              }
+            return path;
+        });
+
+        setSimulationStates(updatedPaths);
+
+        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)[]) => {
+        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,
+                //   updatedPath.modeluuid,
+                //   { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
+                // );
+
+                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") {
+                // await setEventApi(
+                //     organization,
+                //     updatedPath.modeluuid,
+                //     { type: "Vehicle", points: updatedPath.points }
+                // );
+
+                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") {
+                // await setEventApi(
+                //     organization,
+                //     updatedPath.modeluuid,
+                //     { type: "StaticMachine", points: updatedPath.points }
+                // );
+
+                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") {
+                // await setEventApi(
+                //     organization,
+                //     updatedPath.modeluuid,
+                //     { type: "ArmBot", points: updatedPath.points }
+                // );
+
+                const data = {
+                    organization: organization,
+                    modeluuid: updatedPath.modeluuid,
+                    eventData: { type: "ArmBot", points: updatedPath.points },
+                };
+
+                socket.emit("v2:model-asset:updateEventData", data);
             }
+        });
+    };
 
-            // 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
-                  );
-                }
-                return false;
-              });
-
-              if (isAlreadyConnected) {
-                console.log("Conveyor point is already connected. Ignoring.");
-                return;
-              }
-            }
-
-            if (firstSelected) {
-              // Check if trying to connect Vehicle to non-Conveyor
-              if (
-                (firstPath?.type === "Vehicle" &&
-                  secondPath?.type !== "Conveyor") ||
-                (secondPath?.type === "Vehicle" &&
-                  firstPath?.type !== "Conveyor")
-              ) {
-                console.log("Vehicle can only connect to Conveyors");
-                return;
-              }
-
-              // Prevent same-path connections
-              if (firstSelected.modelUUID === modelUUID) {
-                console.log("Cannot connect spheres on the same path.");
-                return;
-              }
-
-              // Check if StaticMachine is involved in the connection
-              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") {
-                const staticConnections =
-                  firstPath.points.connections.targets.length;
-                if (staticConnections >= 1) {
-                  console.log("StaticMachine can only have one connection");
-                  return;
-                }
-              }
-              if (secondPath?.type === "StaticMachine") {
-                const staticConnections =
-                  secondPath.points.connections.targets.length;
-                if (staticConnections >= 1) {
-                  console.log("StaticMachine can only have one connection");
-                  return;
-                }
-              }
-
-              // 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;
-
-                const armBotConnections =
-                  armBotPath.points.connections.targets || [];
-                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");
-                  return;
-                }
-
-                const staticConnections =
-                  staticPath.points.connections.targets.length;
-                if (staticConnections >= 1) {
-                  console.log("StaticMachine can only have one connection");
-                  return;
-                }
-              }
-
-              // Prevent ArmBot ↔ 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") {
-                  console.log(
-                    "ArmBot can only connect to Conveyors or one StaticMachine"
-                  );
-                  return;
-                }
-              }
-
-              // At least one must be start/end point
-              if (!firstSelected.isCorner && !isStartOrEnd) {
-                console.log(
-                  "At least one of the selected spheres must be a start or end point."
-                );
-                return;
-              }
-
-              // All checks passed - make the connection
-              handleAddConnection(
-                firstSelected.modelUUID,
-                firstSelected.sphereUUID,
-                modelUUID,
-                sphereUUID
-              );
-            } else {
-              // First selection - just store it
-              setFirstSelected({
-                modelUUID,
-                sphereUUID,
-                position: worldPosition,
-                isCorner: isStartOrEnd,
-              });
-              setIsConnecting(true);
-            }
-          }
-        }
-      } else {
-        // Clicked outside - cancel connection
+    const handleAddConnection = (fromModelUUID: string, fromUUID: string, toModelUUID: string, toUUID: string) => {
+        updatePathConnections(fromModelUUID, fromUUID, toModelUUID, toUUID);
         setFirstSelected(null);
         setCurrentLine(null);
         setIsConnecting(false);
-      }
     };
 
-    if (activeModule === "simulation" && !deleteTool) {
-      canvasElement.addEventListener("mousedown", onMouseDown);
-      canvasElement.addEventListener("mouseup", onMouseUp);
-      canvasElement.addEventListener("mousemove", onMouseMove);
-      canvasElement.addEventListener("contextmenu", onContextMenu);
-    } else {
-      setFirstSelected(null);
-      setCurrentLine(null);
-      setIsConnecting(false);
-    }
+    useEffect(() => {
+        const canvasElement = gl.domElement;
+        let drag = false;
+        let MouseDown = false;
 
-    return () => {
-      canvasElement.removeEventListener("mousedown", onMouseDown);
-      canvasElement.removeEventListener("mouseup", onMouseUp);
-      canvasElement.removeEventListener("mousemove", onMouseMove);
-      canvasElement.removeEventListener("contextmenu", onContextMenu);
-    };
-  }, [camera, scene, raycaster, firstSelected, simulationStates, deleteTool]);
-
-  useFrame(() => {
-    Object.values(groupRefs.current).forEach((group) => {
-      if (group) {
-        const distance = new THREE.Vector3(
-          ...group.position.toArray()
-        ).distanceTo(camera.position);
-        group.visible = distance <= renderDistance && !isPlaying;
-      }
-    });
-  });
-
-  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")
-        );
-
-      let point: THREE.Vector3 | null = null;
-      let snappedSphere: {
-        sphereUUID: string;
-        position: THREE.Vector3;
-        modelUUID: string;
-        isCorner: boolean;
-      } | null = null;
-      let isInvalidConnection = false;
-
-      if (intersects.length > 0) {
-        point = intersects[0].point;
-        if (point.y < 0.05) {
-          point = new THREE.Vector3(point.x, 0.05, point.z);
-        }
-      }
-
-      const sphereIntersects = raycaster
-        .intersectObjects(pathsGroupRef.current.children, true)
-        .filter((obj) => obj.object.name.includes("events-sphere"));
-
-      if (sphereIntersects.length > 0) {
-        const sphere = sphereIntersects[0].object;
-        const sphereUUID = sphere.uuid;
-        const spherePosition = new THREE.Vector3();
-        sphere.getWorldPosition(spherePosition);
-        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";
-
-        // Inside the useFrame hook, where we check for snapped spheres:
-        const isConnectable =
-          (pathData.type === "Vehicle" ||
-            pathData.type === "ArmBot" ||
-            (pathData.points.length > 0 &&
-              (sphereUUID === pathData.points[0].uuid ||
-                sphereUUID ===
-                  pathData.points[pathData.points.length - 1].uuid ||
-                (pathData.type === "Conveyor" &&
-                  firstPath?.type === "ArmBot")))) && // Allow ArmBot to connect to middle points
-          !isVehicleToVehicle &&
-          !(
-            firstPath?.type === "Conveyor" &&
-            pathData.type === "Conveyor" &&
-            !firstSelected.isCorner
-          );
-
-        // Check for duplicate connection (regardless of path type)
-        const isDuplicateConnection = 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
-              );
-            } else if (path.type === "Vehicle") {
-              return path.points.connections.targets.some(
-                (t) => t.modelUUID === modelUUID && t.pointUUID === sphereUUID
-              );
-            }
-          }
-          return false;
-        });
-
-        // For non-Vehicle paths, check if already connected
-        const isNonVehicleAlreadyConnected =
-          pathData.type !== "Vehicle" &&
-          simulationStates.some((path) => {
-            if (path.type === "Conveyor") {
-              return path.points.some(
-                (point) =>
-                  point.uuid === sphereUUID &&
-                  point.connections.targets.length > 0
-              );
-            }
-            return false;
-          });
-
-        // Check vehicle connection rules
-        const isVehicleAtMaxConnections =
-          pathData.type === "Vehicle" &&
-          pathData.points.connections.targets.length >= 1;
-        const isVehicleConnectingToNonConveyor =
-          (firstPath?.type === "Vehicle" && secondPath?.type !== "Conveyor") ||
-          (secondPath?.type === "Vehicle" && firstPath?.type !== "Conveyor");
-
-        // Check if StaticMachine is connecting to non-ArmBot
-        const isStaticMachineToNonArmBot =
-          (firstPath?.type === "StaticMachine" &&
-            secondPath?.type !== "ArmBot") ||
-          (secondPath?.type === "StaticMachine" &&
-            firstPath?.type !== "ArmBot");
-
-        // Check if StaticMachine already has a connection
-        const isStaticMachineAtMaxConnections =
-          (firstPath?.type === "StaticMachine" &&
-            firstPath.points.connections.targets.length >= 1) ||
-          (secondPath?.type === "StaticMachine" &&
-            secondPath.points.connections.targets.length >= 1);
-
-        // Check if ArmBot is connecting to StaticMachine
-        const isArmBotToStaticMachine =
-          (firstPath?.type === "ArmBot" &&
-            secondPath?.type === "StaticMachine") ||
-          (secondPath?.type === "ArmBot" &&
-            firstPath?.type === "StaticMachine");
-
-        // Prevent multiple StaticMachine connections to ArmBot
-        let isArmBotAlreadyConnectedToStatic = false;
-        if (isArmBotToStaticMachine) {
-          const armBotPath =
-            firstPath?.type === "ArmBot" ? firstPath : secondPath;
-          isArmBotAlreadyConnectedToStatic =
-            armBotPath.points.connections.targets.some((target) => {
-              const targetPath = simulationStates.find(
-                (p) => p.modeluuid === target.modelUUID
-              );
-              return targetPath?.type === "StaticMachine";
-            });
-        }
-
-        // Prevent ArmBot to ArmBot
-        const isArmBotToArmBot =
-          firstPath?.type === "ArmBot" && secondPath?.type === "ArmBot";
-
-        // If ArmBot is involved, other must be Conveyor or StaticMachine
-        const isArmBotToInvalidType =
-          (firstPath?.type === "ArmBot" || secondPath?.type === "ArmBot") &&
-          !(
-            firstPath?.type === "Conveyor" ||
-            firstPath?.type === "StaticMachine" ||
-            secondPath?.type === "Conveyor" ||
-            secondPath?.type === "StaticMachine"
-          );
-
-        if (
-          !isDuplicateConnection &&
-          !isVehicleToVehicle &&
-          !isNonVehicleAlreadyConnected &&
-          !isVehicleAtMaxConnections &&
-          !isVehicleConnectingToNonConveyor &&
-          !isStaticMachineToNonArmBot &&
-          !isStaticMachineAtMaxConnections &&
-          !isArmBotToArmBot &&
-          !isArmBotToInvalidType &&
-          !isArmBotAlreadyConnectedToStatic &&
-          firstSelected.sphereUUID !== sphereUUID &&
-          firstSelected.modelUUID !== modelUUID &&
-          (firstSelected.isCorner || isConnectable) &&
-          !(
-            firstPath?.type === "Conveyor" &&
-            pathData.type === "Conveyor" &&
-            !(firstSelected.isCorner && isConnectable)
-          )
-        ) {
-          snappedSphere = {
-            sphereUUID,
-            position: spherePosition,
-            modelUUID,
-            isCorner: isConnectable,
-          };
-        } else {
-          isInvalidConnection = true;
-        }
-      }
-
-      if (snappedSphere) {
-        point = snappedSphere.position;
-      }
-
-      if (point) {
-        const distance = firstSelected.position.distanceTo(point);
-        const heightFactor = Math.max(0.5, distance * 0.2);
-        const midPoint = new THREE.Vector3(
-          (firstSelected.position.x + point.x) / 2,
-          Math.max(firstSelected.position.y, point.y) + heightFactor,
-          (firstSelected.position.z + point.z) / 2
-        );
-
-        setCurrentLine({
-          start: firstSelected.position,
-          end: point,
-          mid: midPoint,
-        });
-
-        if (sphereIntersects.length > 0) {
-          setHelperLineColor(isInvalidConnection ? "red" : "#6cf542");
-        } else {
-          setHelperLineColor("yellow");
-        }
-      } else {
-        setCurrentLine(null);
-        setIsConnecting(false);
-      }
-    } else {
-      setCurrentLine(null);
-      setIsConnecting(false);
-    }
-  });
-
-  const removeConnections = (
-    connection1: { model: string; point: string },
-    connection2: { model: string; point: string }
-  ) => {
-    const updatedStates = simulationStates.map((state) => {
-      // Handle Conveyor (which has multiple points)
-      if (state.type === "Conveyor") {
-        const updatedConveyor: SimulationTypes.ConveyorEventsSchema = {
-          ...state,
-          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)
-            ) {
-              return {
-                ...point,
-                connections: {
-                  ...point.connections,
-                  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)
-                    );
-                  }),
-                },
-              };
-            }
-            return point;
-          }),
+        const onMouseDown = () => {
+            MouseDown = true;
+            drag = false;
         };
-        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)
-        ) {
-          const updatedVehicle: SimulationTypes.VehicleEventsSchema = {
-            ...state,
-            points: {
-              ...state.points,
-              connections: {
-                ...state.points.connections,
-                targets: state.points.connections.targets.filter((target) => {
-                  return !(
-                    (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,
-            },
-          };
-          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 =
-            {
-              ...state,
-              points: {
-                ...state.points,
-                connections: {
-                  ...state.points.connections,
-                  targets: state.points.connections.targets.filter((target) => {
-                    return !(
-                      (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,
-              },
-            };
-          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)
-        ) {
-          const updatedArmBot: SimulationTypes.ArmBotEventsSchema = {
-            ...state,
-            points: {
-              ...state.points,
-              connections: {
-                ...state.points.connections,
-                targets: state.points.connections.targets.filter((target) => {
-                  return !(
-                    (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
-                    );
-                  }) || [],
-              },
-              triggers: state.points.triggers,
-            },
-          };
-          return updatedArmBot;
-        }
-      }
-      return state;
-    });
 
-    const updatedPaths = updatedStates.filter(
-      (state) =>
-        state.modeluuid === connection1.model ||
-        state.modeluuid === connection2.model
-    );
-
-    console.log("updatedPaths: ", updatedPaths);
-    updateBackend(updatedPaths);
-
-    setSimulationStates(updatedStates);
-  };
-  const removeConnection = (deletedModelUUIDs: string[]) => {
-    const updatedStates = simulationStates.map((state) => {
-      // 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)
-                ),
-              },
-            };
-          }),
+        const onMouseUp = () => {
+            MouseDown = false;
         };
-        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)
-              ),
-            },
-          },
+        const onMouseMove = () => {
+            if (MouseDown) {
+                drag = true;
+            }
         };
-        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;
-      }
+        const onContextMenu = (evt: MouseEvent) => {
+            evt.preventDefault();
+            if (drag || evt.button === 0) return;
 
-      // Handle ArmBot
-      else if (state.type === "ArmBot") {
-        const updatedArmBot: SimulationTypes.ArmBotEventsSchema = {
-          ...state,
-          points: {
-            ...state.points,
-            connections: {
-              ...state.points.connections,
+            raycaster.setFromCamera(pointer, camera);
+            const intersects = raycaster.intersectObjects(
+                pathsGroupRef.current.children,
+                true
+            );
 
-              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 (intersects.length > 0) {
+                const intersected = intersects[0].object;
 
-                  if (matchedStates.length > 0) {
-                    if (matchedStates[0]?.type === "StaticMachine") {
-                      const trigPoints = matchedStates[0]?.points;
+                if (intersected.name.includes("events-sphere")) {
+                    const modelUUID = intersected.userData.path.modeluuid;
+                    const sphereUUID = intersected.uuid;
+                    const worldPosition = new THREE.Vector3();
+                    intersected.getWorldPosition(worldPosition);
 
-                      return !(
-                        process.triggerId === trigPoints?.triggers?.uuid
-                      );
-                    } else if (matchedStates[0]?.type === "Conveyor") {
-                      const trigPoints = matchedStates[0]?.points;
+                    let isStartOrEnd = false;
 
-                      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);
-                      }
+                    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);
+                    } else if (intersected.userData.path.points) {
+                        isStartOrEnd = sphereUUID === intersected.userData.path.points.uuid;
                     }
-                  }
-                  return true;
-                })),
-            },
-          },
-        };
-        return updatedArmBot;
-      }
 
-      return state;
+                    if (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") {
+                            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)) {
+                            console.log("Conveyor connections must be between start/end points");
+                            return;
+                        }
+
+                        // Check if this specific connection already exists
+                        const isDuplicateConnection = firstSelected
+                            ? 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
+                                        );
+                                    } else if (path.type === "Vehicle") {
+                                        return path.points.connections.targets.some(
+                                            (t) =>
+                                                t.modelUUID === modelUUID &&
+                                                t.pointUUID === sphereUUID
+                                        );
+                                    }
+                                }
+                                return false;
+                            })
+                            : false;
+
+                        if (isDuplicateConnection) {
+                            console.log("These points are already connected. Ignoring.");
+                            return;
+                        }
+
+                        // 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 (vehicleConnections >= 1) {
+                                console.log("Vehicle can only have one connection");
+                                return;
+                            }
+                        }
+
+                        // 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
+                                    );
+                                }
+                                return false;
+                            });
+
+                            if (isAlreadyConnected) {
+                                console.log("Conveyor point is already connected. Ignoring.");
+                                return;
+                            }
+                        }
+
+                        if (firstSelected) {
+                            // Check if trying to connect Vehicle to non-Conveyor
+                            if ((firstPath?.type === "Vehicle" && secondPath?.type !== "Conveyor") || (secondPath?.type === "Vehicle" && firstPath?.type !== "Conveyor")) {
+                                console.log("Vehicle can only connect to Conveyors");
+                                return;
+                            }
+
+                            // Prevent same-path connections
+                            if (firstSelected.modelUUID === modelUUID) {
+                                console.log("Cannot connect spheres on the same path.");
+                                return;
+                            }
+
+                            // Check if StaticMachine is involved in the connection
+                            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") {
+                                const staticConnections = firstPath.points.connections.targets.length;
+                                if (staticConnections >= 1) {
+                                    console.log("StaticMachine can only have one connection");
+                                    return;
+                                }
+                            }
+                            if (secondPath?.type === "StaticMachine") {
+                                const staticConnections = secondPath.points.connections.targets.length;
+                                if (staticConnections >= 1) {
+                                    console.log("StaticMachine can only have one connection");
+                                    return;
+                                }
+                            }
+
+                            // 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;
+
+                                const armBotConnections = armBotPath.points.connections.targets || [];
+                                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");
+                                    return;
+                                }
+
+                                const staticConnections = staticPath.points.connections.targets.length;
+                                if (staticConnections >= 1) {
+                                    console.log("StaticMachine can only have one connection");
+                                    return;
+                                }
+                            }
+
+                            // Prevent ArmBot ↔ 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") {
+                                    console.log("ArmBot can only connect to Conveyors or one StaticMachine");
+                                    return;
+                                }
+                            }
+
+                            // At least one must be start/end point
+                            if (!firstSelected.isCorner && !isStartOrEnd) {
+                                console.log("At least one of the selected spheres must be a start or end point.");
+                                return;
+                            }
+
+                            // All checks passed - make the connection
+                            handleAddConnection(firstSelected.modelUUID, firstSelected.sphereUUID, modelUUID, sphereUUID);
+                        } else {
+                            // First selection - just store it
+                            setFirstSelected({ modelUUID, sphereUUID, position: worldPosition, isCorner: isStartOrEnd });
+                            setIsConnecting(true);
+                        }
+                    }
+                }
+            } else {
+                // Clicked outside - cancel connection
+                setFirstSelected(null);
+                setCurrentLine(null);
+                setIsConnecting(false);
+            }
+        };
+
+        if (activeModule === "simulation" && !deleteTool) {
+            canvasElement.addEventListener("mousedown", onMouseDown);
+            canvasElement.addEventListener("mouseup", onMouseUp);
+            canvasElement.addEventListener("mousemove", onMouseMove);
+            canvasElement.addEventListener("contextmenu", onContextMenu);
+        } else {
+            setFirstSelected(null);
+            setCurrentLine(null);
+            setIsConnecting(false);
+        }
+
+        return () => {
+            canvasElement.removeEventListener("mousedown", onMouseDown);
+            canvasElement.removeEventListener("mouseup", onMouseUp);
+            canvasElement.removeEventListener("mousemove", onMouseMove);
+            canvasElement.removeEventListener("contextmenu", onContextMenu);
+        };
+    }, [camera, scene, raycaster, firstSelected, simulationStates, deleteTool]);
+
+    useFrame(() => {
+        Object.values(groupRefs.current).forEach((group) => {
+            if (group) {
+                const distance = new THREE.Vector3(...group.position.toArray()).distanceTo(camera.position);
+                group.visible = distance <= renderDistance && !isPlaying;
+            }
+        });
     });
 
-    const filteredStates = updatedStates.filter(
-      (state) => !deletedModelUUIDs.includes(state.modeluuid)
-    );
+    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")
+            );
 
-    updateBackend(filteredStates);
-    setSimulationStates(filteredStates);
-  };
+            let point: THREE.Vector3 | null = null;
+            let snappedSphere: { sphereUUID: string; position: THREE.Vector3; modelUUID: string; isCorner: boolean; } | null = null;
+            let isInvalidConnection = false;
 
-  return (
-    <group name="simulationConnectionGroup" visible={!isPlaying}>
-      {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;
+            if (intersects.length > 0) {
+                point = intersects[0].point;
+                if (point.y < 0.05) {
+                    point = new THREE.Vector3(point.x, 0.05, point.z);
+                }
+            }
 
-              const fromSphere = pathsGroupRef.current?.getObjectByProperty(
-                "uuid",
-                point.uuid
-              );
-              const toSphere = pathsGroupRef.current?.getObjectByProperty(
-                "uuid",
-                target.pointUUID
-              );
+            const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) => obj.object.name.includes("events-sphere"));
 
-              if (fromSphere && toSphere) {
-                const fromWorldPosition = new THREE.Vector3();
-                const toWorldPosition = new THREE.Vector3();
-                fromSphere.getWorldPosition(fromWorldPosition);
-                toSphere.getWorldPosition(toWorldPosition);
+            if (sphereIntersects.length > 0) {
+                const sphere = sphereIntersects[0].object;
+                const sphereUUID = sphere.uuid;
+                const spherePosition = new THREE.Vector3();
+                sphere.getWorldPosition(spherePosition);
+                const pathData = sphere.userData.path;
+                const modelUUID = pathData.modeluuid;
 
-                const distance = fromWorldPosition.distanceTo(toWorldPosition);
+                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 = (
+                    pathData.type === 'Vehicle' ||
+                    pathData.type === 'ArmBot' ||
+                    (pathData.points.length > 0 && (
+                        sphereUUID === pathData.points[0].uuid ||
+                        sphereUUID === pathData.points[pathData.points.length - 1].uuid ||
+                        (pathData.type === 'Conveyor' && firstPath?.type === 'ArmBot')  // Allow ArmBot to connect to middle points
+                    ))
+                ) &&
+                    !isVehicleToVehicle &&
+                    !(
+                        firstPath?.type === 'Conveyor' &&
+                        pathData.type === 'Conveyor' &&
+                        !firstSelected.isCorner
+                    );
+
+                // Check for duplicate connection (regardless of path type)
+                const isDuplicateConnection = 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
+                            );
+                        } else if (path.type === 'Vehicle') {
+                            return path.points.connections.targets.some(t =>
+                                t.modelUUID === modelUUID && t.pointUUID === sphereUUID
+                            );
+                        }
+                    }
+                    return false;
+                });
+
+                // For non-Vehicle paths, check if already connected
+                const isNonVehicleAlreadyConnected = pathData.type !== 'Vehicle' &&
+                    simulationStates.some(path => {
+                        if (path.type === 'Conveyor') {
+                            return path.points.some(point =>
+                                point.uuid === sphereUUID &&
+                                point.connections.targets.length > 0
+                            );
+                        }
+                        return false;
+                    });
+
+                // Check vehicle connection rules
+                const isVehicleAtMaxConnections = pathData.type === 'Vehicle' &&
+                    pathData.points.connections.targets.length >= 1;
+                const isVehicleConnectingToNonConveyor =
+                    (firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
+                    (secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor');
+
+                // Check if StaticMachine is connecting to non-ArmBot
+                const isStaticMachineToNonArmBot =
+                    (firstPath?.type === 'StaticMachine' && secondPath?.type !== 'ArmBot') ||
+                    (secondPath?.type === 'StaticMachine' && firstPath?.type !== 'ArmBot');
+
+                // Check if StaticMachine already has a connection
+                const isStaticMachineAtMaxConnections =
+                    (firstPath?.type === 'StaticMachine' && firstPath.points.connections.targets.length >= 1) ||
+                    (secondPath?.type === 'StaticMachine' && secondPath.points.connections.targets.length >= 1);
+
+                // Check if ArmBot is connecting to StaticMachine
+                const isArmBotToStaticMachine =
+                    (firstPath?.type === 'ArmBot' && secondPath?.type === 'StaticMachine') ||
+                    (secondPath?.type === 'ArmBot' && firstPath?.type === 'StaticMachine');
+
+                // Prevent multiple StaticMachine connections to ArmBot
+                let isArmBotAlreadyConnectedToStatic = false;
+                if (isArmBotToStaticMachine) {
+                    const armBotPath = firstPath?.type === 'ArmBot' ? firstPath : secondPath;
+                    isArmBotAlreadyConnectedToStatic = armBotPath.points.connections.targets.some(target => {
+                        const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
+                        return targetPath?.type === 'StaticMachine';
+                    });
+                }
+
+                // Prevent ArmBot to ArmBot
+                const isArmBotToArmBot = firstPath?.type === 'ArmBot' && secondPath?.type === 'ArmBot';
+
+                // If ArmBot is involved, other must be Conveyor or StaticMachine
+                const isArmBotToInvalidType = (firstPath?.type === 'ArmBot' || secondPath?.type === 'ArmBot') &&
+                    !(firstPath?.type === 'Conveyor' || firstPath?.type === 'StaticMachine' ||
+                        secondPath?.type === 'Conveyor' || secondPath?.type === 'StaticMachine');
+
+                if (
+                    !isDuplicateConnection &&
+                    !isVehicleToVehicle &&
+                    !isNonVehicleAlreadyConnected &&
+                    !isVehicleAtMaxConnections &&
+                    !isVehicleConnectingToNonConveyor &&
+                    !isStaticMachineToNonArmBot &&
+                    !isStaticMachineAtMaxConnections &&
+                    !isArmBotToArmBot &&
+                    !isArmBotToInvalidType &&
+                    !isArmBotAlreadyConnectedToStatic &&
+                    firstSelected.sphereUUID !== sphereUUID &&
+                    firstSelected.modelUUID !== modelUUID &&
+                    (firstSelected.isCorner || isConnectable) &&
+                    !(firstPath?.type === 'Conveyor' &&
+                        pathData.type === 'Conveyor' &&
+                        !(firstSelected.isCorner && isConnectable))
+                ) {
+                    snappedSphere = {
+                        sphereUUID,
+                        position: spherePosition,
+                        modelUUID,
+                        isCorner: isConnectable
+                    };
+                } else {
+                    isInvalidConnection = true;
+                }
+            }
+
+            if (snappedSphere) {
+                point = snappedSphere.position;
+            }
+
+            if (point) {
+                const distance = firstSelected.position.distanceTo(point);
                 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
+                    (firstSelected.position.x + point.x) / 2,
+                    Math.max(firstSelected.position.y, point.y) + heightFactor,
+                    (firstSelected.position.z + point.z) / 2
                 );
 
-                return (
-                  <QuadraticBezierLine
-                    key={`${point.uuid}-${target.pointUUID}-${index}`}
-                    ref={(el) =>
-                      (groupRefs.current[
-                        `${point.uuid}-${target.pointUUID}-${index}`
-                      ] = el!)
-                    }
-                    start={fromWorldPosition.toArray()}
-                    end={toWorldPosition.toArray()}
-                    mid={midPoint.toArray()}
-                    color={
-                      deleteTool &&
-                      hoveredLineKey ===
-                        `${point.uuid}-${target.pointUUID}-${index}`
-                        ? "red"
-                        : targetPath?.type === "ArmBot"
-                        ? "#42a5f5"
-                        : "white"
-                    }
+                setCurrentLine({
+                    start: firstSelected.position,
+                    end: point,
+                    mid: midPoint,
+                });
+
+                if (sphereIntersects.length > 0) {
+                    setHelperLineColor(isInvalidConnection ? "red" : "#6cf542");
+                } else {
+                    setHelperLineColor("yellow");
+                }
+            } else {
+                setCurrentLine(null);
+                setIsConnecting(false);
+            }
+        } else {
+            setCurrentLine(null);
+            setIsConnecting(false);
+        }
+    });
+
+    const removeConnection = (connection1: { model: string; point: string }, connection2: { model: string; point: string }) => {
+        const updatedStates = simulationStates.map((state) => {
+
+            // Handle Conveyor (which has multiple points)
+            if (state.type === "Conveyor") {
+                const updatedConveyor: SimulationTypes.ConveyorEventsSchema = {
+                    ...state,
+                    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)) {
+                            return {
+                                ...point,
+                                connections: {
+                                    ...point.connections,
+                                    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)
+                                        );
+                                    }),
+                                },
+                            };
+                        }
+                        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)) {
+                    const updatedVehicle: SimulationTypes.VehicleEventsSchema = {
+                        ...state,
+                        points: {
+                            ...state.points,
+                            connections: {
+                                ...state.points.connections,
+                                targets: state.points.connections.targets.filter((target) => {
+                                    return !(
+                                        (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,
+                        },
+                    };
+                    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 =
+                    {
+                        ...state,
+                        points: {
+                            ...state.points,
+                            connections: {
+                                ...state.points.connections,
+                                targets: state.points.connections.targets.filter((target) => {
+                                    return !(
+                                        (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,
+                        },
+                    };
+                    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)) {
+                    const updatedArmBot: SimulationTypes.ArmBotEventsSchema = {
+                        ...state,
+                        points: {
+                            ...state.points,
+                            connections: {
+                                ...state.points.connections,
+                                targets: state.points.connections.targets.filter((target) => {
+                                    return !(
+                                        (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
+                                        );
+                                    }) || [],
+                            },
+                            triggers: state.points.triggers,
+                        },
+                    };
+                    return updatedArmBot;
+                }
+            }
+            return state;
+        });
+
+        const updatedPaths = updatedStates.filter(
+            (state) =>
+                state.modeluuid === connection1.model ||
+                state.modeluuid === connection2.model
+        );
+
+        console.log("updatedPaths: ", updatedPaths);
+        updateBackend(updatedPaths);
+
+        setSimulationStates(updatedStates);
+    };
+
+    const removeConnections = (deletedModelUUIDs: string[]) => {
+        const updatedStates = simulationStates.map((state) => {
+
+            // 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 (
+        <group name="simulationConnectionGroup" visible={!isPlaying}>
+            {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();
+                                const toWorldPosition = new THREE.Vector3();
+                                fromSphere.getWorldPosition(fromWorldPosition);
+                                toSphere.getWorldPosition(toWorldPosition);
+
+                                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
+                                );
+
+                                return (
+                                    <QuadraticBezierLine
+                                        key={`${point.uuid}-${target.pointUUID}-${index}`}
+                                        ref={(el) => (groupRefs.current[`${point.uuid}-${target.pointUUID}-${index}`] = el!)}
+                                        start={fromWorldPosition.toArray()}
+                                        end={toWorldPosition.toArray()}
+                                        mid={midPoint.toArray()}
+                                        color={deleteTool && hoveredLineKey === `${point.uuid}-${target.pointUUID}-${index}` ? "red" : targetPath?.type === "ArmBot" ? "#42a5f5" : "white"}
+                                        lineWidth={4}
+                                        dashed={deleteTool && hoveredLineKey === `${point.uuid}-${target.pointUUID}-${index}` ? false : true}
+                                        dashSize={0.75}
+                                        dashScale={20}
+                                        onPointerOver={() => 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,
+                                                };
+
+                                                removeConnection(connection1, connection2);
+                                            }
+                                        }}
+                                        userData={target}
+                                    />
+                                );
+                            }
+                            return null;
+                        })
+                    );
+                }
+
+                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);
+
+                        if (fromSphere && toSphere) {
+                            const fromWorldPosition = new THREE.Vector3();
+                            const toWorldPosition = new THREE.Vector3();
+                            fromSphere.getWorldPosition(fromWorldPosition);
+                            toSphere.getWorldPosition(toWorldPosition);
+
+                            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
+                            );
+
+                            return (
+                                <QuadraticBezierLine
+                                    key={`${path.points.uuid}-${target.pointUUID}-${index}`}
+                                    ref={(el) => (groupRefs.current[`${path.points.uuid}-${target.pointUUID}-${index}`] = el!)}
+                                    start={fromWorldPosition.toArray()}
+                                    end={toWorldPosition.toArray()}
+                                    mid={midPoint.toArray()}
+                                    color={deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}` ? "red" : "orange"}
+                                    lineWidth={4}
+                                    dashed={deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}` ? false : true}
+                                    dashSize={0.75}
+                                    dashScale={20}
+                                    onPointerOver={() => 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,
+                                            };
+
+                                            removeConnection(connection1, connection2);
+                                        }
+                                    }}
+                                    userData={target}
+                                />
+                            );
+                        }
+                        return null;
+                    });
+                }
+
+                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 fromSphere = pathsGroupRef.current?.getObjectByProperty("uuid", path.points.uuid);
+                        const toSphere = pathsGroupRef.current?.getObjectByProperty("uuid", target.pointUUID);
+
+                        if (fromSphere && toSphere) {
+                            const fromWorldPosition = new THREE.Vector3();
+                            const toWorldPosition = new THREE.Vector3();
+                            fromSphere.getWorldPosition(fromWorldPosition);
+                            toSphere.getWorldPosition(toWorldPosition);
+
+                            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
+                            );
+
+                            return (
+                                <QuadraticBezierLine
+                                    key={`${path.points.uuid}-${target.pointUUID}-${index}`}
+                                    ref={(el) => (groupRefs.current[`${path.points.uuid}-${target.pointUUID}-${index}`] = el!)}
+                                    start={fromWorldPosition.toArray()}
+                                    end={toWorldPosition.toArray()}
+                                    mid={midPoint.toArray()}
+                                    color={deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}` ? "red" : "#42a5f5"}
+                                    lineWidth={4}
+                                    dashed={deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}` ? false : true}
+                                    dashSize={0.75}
+                                    dashScale={20}
+                                    onPointerOver={() => 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,
+                                            };
+
+                                            removeConnection(connection1, connection2);
+                                        }
+                                    }}
+                                    userData={target}
+                                />
+                            );
+                        }
+                        return null;
+                    });
+                }
+
+                return [];
+            })}
+
+            {currentLine && (
+                <QuadraticBezierLine
+                    start={currentLine.start.toArray()}
+                    end={currentLine.end.toArray()}
+                    mid={currentLine.mid.toArray()}
+                    color={helperlineColor}
                     lineWidth={4}
-                    dashed={
-                      deleteTool &&
-                      hoveredLineKey ===
-                        `${point.uuid}-${target.pointUUID}-${index}`
-                        ? false
-                        : true
-                    }
-                    dashSize={0.75}
+                    dashed
+                    dashSize={1}
                     dashScale={20}
-                    onPointerOver={() =>
-                      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,
-                        };
-
-                        removeConnections(connection1, connection2);
-                      }
-                    }}
-                    userData={target}
-                  />
-                );
-              }
-              return null;
-            })
-          );
-        }
-
-        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
-            );
-
-            if (fromSphere && toSphere) {
-              const fromWorldPosition = new THREE.Vector3();
-              const toWorldPosition = new THREE.Vector3();
-              fromSphere.getWorldPosition(fromWorldPosition);
-              toSphere.getWorldPosition(toWorldPosition);
-
-              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
-              );
-
-              return (
-                <QuadraticBezierLine
-                  key={`${path.points.uuid}-${target.pointUUID}-${index}`}
-                  ref={(el) =>
-                    (groupRefs.current[
-                      `${path.points.uuid}-${target.pointUUID}-${index}`
-                    ] = el!)
-                  }
-                  start={fromWorldPosition.toArray()}
-                  end={toWorldPosition.toArray()}
-                  mid={midPoint.toArray()}
-                  color={
-                    deleteTool &&
-                    hoveredLineKey ===
-                      `${path.points.uuid}-${target.pointUUID}-${index}`
-                      ? "red"
-                      : "orange"
-                  }
-                  lineWidth={4}
-                  dashed={
-                    deleteTool &&
-                    hoveredLineKey ===
-                      `${path.points.uuid}-${target.pointUUID}-${index}`
-                      ? false
-                      : true
-                  }
-                  dashSize={0.75}
-                  dashScale={20}
-                  onPointerOver={() =>
-                    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,
-                      };
-
-                      removeConnections(connection1, connection2);
-                    }
-                  }}
-                  userData={target}
                 />
-              );
-            }
-            return null;
-          });
-        }
-
-        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 fromSphere = pathsGroupRef.current?.getObjectByProperty(
-              "uuid",
-              path.points.uuid
-            );
-            const toSphere = pathsGroupRef.current?.getObjectByProperty(
-              "uuid",
-              target.pointUUID
-            );
-
-            if (fromSphere && toSphere) {
-              const fromWorldPosition = new THREE.Vector3();
-              const toWorldPosition = new THREE.Vector3();
-              fromSphere.getWorldPosition(fromWorldPosition);
-              toSphere.getWorldPosition(toWorldPosition);
-
-              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
-              );
-
-              return (
-                <QuadraticBezierLine
-                  key={`${path.points.uuid}-${target.pointUUID}-${index}`}
-                  ref={(el) =>
-                    (groupRefs.current[
-                      `${path.points.uuid}-${target.pointUUID}-${index}`
-                    ] = el!)
-                  }
-                  start={fromWorldPosition.toArray()}
-                  end={toWorldPosition.toArray()}
-                  mid={midPoint.toArray()}
-                  color={
-                    deleteTool &&
-                    hoveredLineKey ===
-                      `${path.points.uuid}-${target.pointUUID}-${index}`
-                      ? "red"
-                      : "#42a5f5"
-                  }
-                  lineWidth={4}
-                  dashed={
-                    deleteTool &&
-                    hoveredLineKey ===
-                      `${path.points.uuid}-${target.pointUUID}-${index}`
-                      ? false
-                      : true
-                  }
-                  dashSize={0.75}
-                  dashScale={20}
-                  onPointerOver={() =>
-                    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,
-                      };
-
-                      removeConnections(connection1, connection2);
-                    }
-                  }}
-                  userData={target}
-                />
-              );
-            }
-            return null;
-          });
-        }
-
-        return [];
-      })}
-
-      {currentLine && (
-        <QuadraticBezierLine
-          start={currentLine.start.toArray()}
-          end={currentLine.end.toArray()}
-          mid={currentLine.mid.toArray()}
-          color={helperlineColor}
-          lineWidth={4}
-          dashed
-          dashSize={1}
-          dashScale={20}
-        />
-      )}
-    </group>
-  );
+            )}
+        </group>
+    );
 }
 
 export default PathConnector;

From 83f92d4b015507c7b88d67ee77fb1d29f783b925 Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B <jerald@hexrfactory.com>
Date: Wed, 16 Apr 2025 10:16:54 +0530
Subject: [PATCH 08/20] feat: Enhance connection removal logic to handle
 deleted models and their points

---
 .../controls/selection/selectionControls.tsx  | 61 ++++++++++------
 .../modules/simulation/path/pathConnector.tsx | 73 ++++++++++---------
 2 files changed, 79 insertions(+), 55 deletions(-)

diff --git a/app/src/modules/scene/controls/selection/selectionControls.tsx b/app/src/modules/scene/controls/selection/selectionControls.tsx
index ece6924..8998bc9 100644
--- a/app/src/modules/scene/controls/selection/selectionControls.tsx
+++ b/app/src/modules/scene/controls/selection/selectionControls.tsx
@@ -270,6 +270,20 @@ const SelectionControls: React.FC = () => {
     };
 
     const removeConnections = (deletedModelUUIDs: string[]) => {
+
+        const deletedPointUUIDs = new Set<string>();
+        simulationStates.forEach(state => {
+            if (deletedModelUUIDs.includes(state.modeluuid)) {
+                if (state.type === "Conveyor" && state.points) {
+                    state.points.forEach(point => {
+                        deletedPointUUIDs.add(point.uuid);
+                    });
+                } else if (state.points && 'uuid' in state.points) {
+                    deletedPointUUIDs.add(state.points.uuid);
+                }
+            }
+        });
+
         const updatedStates = simulationStates.map((state) => {
             // Handle Conveyor
             if (state.type === "Conveyor") {
@@ -333,38 +347,41 @@ const SelectionControls: React.FC = () => {
                         ...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));
+                            processes: state.points.actions.processes?.filter((process) => {
+                                // Check if trigger is from deleted model
+                                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);
+                                if (matchedStates.length > 0) {
+                                    if (matchedStates[0]?.type === "StaticMachine") {
+                                        const trigPoints = matchedStates[0]?.points;
+                                        if (process.triggerId === trigPoints?.triggers?.uuid) {
+                                            return false;
+                                        }
+                                    } 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);
+                                            if (allTriggerUUIDs.includes(process.triggerId)) {
+                                                return false;
                                             }
                                         }
                                     }
-                                    return true;
-                                })),
+                                }
+
+                                // Check if startPoint or endPoint is from deleted model
+                                if (deletedPointUUIDs.has(process.startPoint) || deletedPointUUIDs.has(process.endPoint)) {
+                                    return false;
+                                }
+
+                                return true;
+                            }),
                         },
                     },
                 };
diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx
index 4ca12a2..3e35925 100644
--- a/app/src/modules/simulation/path/pathConnector.tsx
+++ b/app/src/modules/simulation/path/pathConnector.tsx
@@ -964,8 +964,21 @@ function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObje
     };
 
     const removeConnections = (deletedModelUUIDs: string[]) => {
-        const updatedStates = simulationStates.map((state) => {
 
+        const deletedPointUUIDs = new Set<string>();
+        simulationStates.forEach(state => {
+            if (deletedModelUUIDs.includes(state.modeluuid)) {
+                if (state.type === "Conveyor" && state.points) {
+                    state.points.forEach(point => {
+                        deletedPointUUIDs.add(point.uuid);
+                    });
+                } else if (state.points && 'uuid' in state.points) {
+                    deletedPointUUIDs.add(state.points.uuid);
+                }
+            }
+        });
+
+        const updatedStates = simulationStates.map((state) => {
             // Handle Conveyor
             if (state.type === "Conveyor") {
                 const updatedConveyor: SimulationTypes.ConveyorEventsSchema = {
@@ -1028,45 +1041,41 @@ function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObje
                         ...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)
-                                    );
+                            processes: state.points.actions.processes?.filter((process) => {
+                                // Check if trigger is from deleted model
+                                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);
+                                if (matchedStates.length > 0) {
+                                    if (matchedStates[0]?.type === "StaticMachine") {
+                                        const trigPoints = matchedStates[0]?.points;
+                                        if (process.triggerId === trigPoints?.triggers?.uuid) {
+                                            return false;
+                                        }
+                                    } 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);
+                                            if (allTriggerUUIDs.includes(process.triggerId)) {
+                                                return false;
                                             }
                                         }
                                     }
-                                    return true;
-                                })),
+                                }
+
+                                // Check if startPoint or endPoint is from deleted model
+                                if (deletedPointUUIDs.has(process.startPoint) || deletedPointUUIDs.has(process.endPoint)) {
+                                    return false;
+                                }
+
+                                return true;
+                            }),
                         },
                     },
                 };
@@ -1076,9 +1085,7 @@ function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObje
             return state;
         });
 
-        const filteredStates = updatedStates.filter(
-            (state) => !deletedModelUUIDs.includes(state.modeluuid)
-        );
+        const filteredStates = updatedStates.filter((state) => !deletedModelUUIDs.includes(state.modeluuid));
 
         updateBackend(filteredStates);
         setSimulationStates(filteredStates);

From 5c24d7ca71f82d474851c3b89e1c328e19f1f8ea Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B <jerald@hexrfactory.com>
Date: Wed, 16 Apr 2025 10:47:12 +0530
Subject: [PATCH 09/20] feat: Improve trigger processing and static machine
 status updates in IKAnimationController

---
 .../armbot/IKAnimationController.tsx          | 57 +++++++++----------
 1 file changed, 28 insertions(+), 29 deletions(-)

diff --git a/app/src/modules/simulation/armbot/IKAnimationController.tsx b/app/src/modules/simulation/armbot/IKAnimationController.tsx
index 1044540..9f19797 100644
--- a/app/src/modules/simulation/armbot/IKAnimationController.tsx
+++ b/app/src/modules/simulation/armbot/IKAnimationController.tsx
@@ -114,10 +114,38 @@ const IKAnimationController = ({
 
         if (prev.needsInitialMovement !== needsInitialMovement && !needsInitialMovement) {
             logStatus(`[Arm ${uuid}] Reached rest position, ready for animation`);
+
         }
 
         if (prev.selectedTrigger !== selectedTrigger) {
             logStatus(`[Arm ${uuid}] Processing new trigger: ${selectedTrigger}`);
+
+
+            const currentProcess = process.find(p => p.triggerId === prev.selectedTrigger);
+            if (currentProcess) {
+                const triggerId = currentProcess.triggerId;
+
+                const endPoint = armBot.actions.processes.find((process) => process.triggerId === triggerId)?.endPoint;
+
+                // Search simulationStates for a StaticMachine that has a point matching this endPointId
+                const matchedStaticMachine = simulationStates.find(
+                    (state) =>
+                        state.type === "StaticMachine" &&
+                        state.points?.uuid === endPoint// check for static machine with matching point uuid
+                ) as any;
+
+                if (matchedStaticMachine) {
+                    setStaticMachines((machines) => {
+                        return machines.map((machine) => {
+                            if (machine.uuid === matchedStaticMachine.modeluuid) {
+                                return { ...machine, status: "running" };
+                            } else {
+                                return machine;
+                            }
+                        });
+                    });
+                }
+            }
         }
 
         // Update previous state
@@ -249,35 +277,6 @@ const IKAnimationController = ({
         } else if (progress >= startToEndRange[0] && progress < startToEndRange[1]) {
             currentSpeed = speed;
             currentStatus = "moving"; // Moving between points
-            if (1 - progress < 0.05) {
-                // Find the process that matches the current trigger
-                const currentProcess = process.find(p => p.triggerId === selectedTrigger);
-                if (currentProcess) {
-                    const triggerId = currentProcess.triggerId;
-
-                    const endPoint = armBot.actions.processes.find((process) => process.triggerId === triggerId)?.endPoint;
-
-                    // Search simulationStates for a StaticMachine that has a point matching this endPointId
-                    const matchedStaticMachine = simulationStates.find(
-                        (state) =>
-                            state.type === "StaticMachine" &&
-                            state.points?.uuid === endPoint// check for static machine with matching point uuid
-                    ) as any;
-
-                    if (matchedStaticMachine) {
-                        setStaticMachines((machines) => {
-                            return machines.map((machine) => {
-                                if (machine.uuid === matchedStaticMachine.modeluuid) {
-                                    return { ...machine, status: "running" };
-                                } else {
-                                    return machine;
-                                }
-                            });
-                        });
-                    }
-                }
-
-            }
         } else if (progress >= endToRestRange[0] && progress < 1) {
             currentSpeed = restSpeed;
             currentStatus = "moving"; // Returning to rest

From e0082cb55a4ea64a7562f97ee16c10f763776445 Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B <jerald@hexrfactory.com>
Date: Wed, 16 Apr 2025 11:39:03 +0530
Subject: [PATCH 10/20] feat: Enhance ArmBotState with connections and isActive
 properties

- Updated ArmBotState interface across multiple files to include connections (source and targets) and isActive properties.
- Implemented logic in ProcessAnimator to check if processes are connected to active ArmBots, preventing future spawns if connected.
- Adjusted animation state handling to account for active ArmBots, stopping animations and resetting states as necessary.
- Refactored related functions for better clarity and maintainability.
---
 app/src/modules/simulation/armbot/ArmBot.tsx  |    8 +-
 .../simulation/armbot/ArmBotInstances.tsx     |   15 +-
 .../armbot/IKAnimationController.tsx          |   79 +-
 .../modules/simulation/armbot/IkInstances.tsx |   17 +-
 .../simulation/process/processAnimator.tsx    |   84 +-
 .../simulation/process/processContainer.tsx   |    5 +
 .../process/useProcessAnimations.tsx          | 1174 +++++++++--------
 app/src/modules/simulation/simulation.tsx     |    5 +
 .../staticMachine/staticMachine.tsx           |    6 +-
 9 files changed, 755 insertions(+), 638 deletions(-)

diff --git a/app/src/modules/simulation/armbot/ArmBot.tsx b/app/src/modules/simulation/armbot/ArmBot.tsx
index a6d8d23..1c7bb83 100644
--- a/app/src/modules/simulation/armbot/ArmBot.tsx
+++ b/app/src/modules/simulation/armbot/ArmBot.tsx
@@ -12,7 +12,12 @@ interface ArmBotState {
     status: string;
     material: string;
     triggerId: string;
+    connections: {
+        source: { modelUUID: string; pointUUID: string };
+        targets: { modelUUID: string; pointUUID: string }[];
+    };
     actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+    isActive?: boolean;
 }
 
 interface StaticMachineState {
@@ -45,7 +50,8 @@ const ArmBot = ({ armBots, setArmBots, setStaticMachines }: ArmBotProps) => {
                 status: "idle",
                 material: "default",
                 triggerId: '',
-                actions: bot.points.actions
+                actions: bot.points.actions,
+                connections: bot.points.connections
             }));
         setArmBots(initialStates);
     }, [simulationStates]);
diff --git a/app/src/modules/simulation/armbot/ArmBotInstances.tsx b/app/src/modules/simulation/armbot/ArmBotInstances.tsx
index 10a49f6..8d20a87 100644
--- a/app/src/modules/simulation/armbot/ArmBotInstances.tsx
+++ b/app/src/modules/simulation/armbot/ArmBotInstances.tsx
@@ -18,16 +18,12 @@ interface ArmBotState {
     status: string;
     material: string;
     triggerId: string;
-    actions: {
-        uuid: string;
-        name: string;
-        speed: number;
-        processes: {
-            triggerId: string;
-            startPoint: string;
-            endPoint: string;
-        }[];
+    connections: {
+        source: { modelUUID: string; pointUUID: string };
+        targets: { modelUUID: string; pointUUID: string }[];
     };
+    actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+    isActive?: boolean;
 }
 
 interface StaticMachineState {
@@ -87,6 +83,7 @@ export const ArmbotInstances: React.FC<ArmbotInstancesProps> = ({ index, armBot,
             rotation={armBot.rotation}
             processes={processes}
             armBot={armBot}
+            setArmBots={setArmBots}
             setStaticMachines={setStaticMachines}
             updateArmBotStatus={updateArmBotStatus}
         />
diff --git a/app/src/modules/simulation/armbot/IKAnimationController.tsx b/app/src/modules/simulation/armbot/IKAnimationController.tsx
index 9f19797..d0aaec1 100644
--- a/app/src/modules/simulation/armbot/IKAnimationController.tsx
+++ b/app/src/modules/simulation/armbot/IKAnimationController.tsx
@@ -20,16 +20,12 @@ interface ArmBotState {
     status: string;
     material: string;
     triggerId: string;
-    actions: {
-        uuid: string;
-        name: string;
-        speed: number;
-        processes: {
-            triggerId: string;
-            startPoint: string;
-            endPoint: string;
-        }[];
+    connections: {
+        source: { modelUUID: string; pointUUID: string };
+        targets: { modelUUID: string; pointUUID: string }[];
     };
+    actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+    isActive?: boolean;
 }
 
 type IKAnimationControllerProps = {
@@ -46,6 +42,7 @@ type IKAnimationControllerProps = {
     logStatus: (status: string) => void;
     groupRef: React.RefObject<THREE.Group>;
     armBot: ArmBotState;
+    setArmBots: React.Dispatch<React.SetStateAction<ArmBotState[]>>;
     setStaticMachines: React.Dispatch<React.SetStateAction<StaticMachineState[]>>;
     updateArmBotStatus: (status: string) => void;
 }
@@ -59,6 +56,7 @@ const IKAnimationController = ({
     logStatus,
     groupRef,
     armBot,
+    setArmBots,
     setStaticMachines,
     updateArmBotStatus
 }: IKAnimationControllerProps) => {
@@ -120,30 +118,61 @@ const IKAnimationController = ({
         if (prev.selectedTrigger !== selectedTrigger) {
             logStatus(`[Arm ${uuid}] Processing new trigger: ${selectedTrigger}`);
 
-
             const currentProcess = process.find(p => p.triggerId === prev.selectedTrigger);
             if (currentProcess) {
                 const triggerId = currentProcess.triggerId;
 
                 const endPoint = armBot.actions.processes.find((process) => process.triggerId === triggerId)?.endPoint;
 
-                // Search simulationStates for a StaticMachine that has a point matching this endPointId
-                const matchedStaticMachine = simulationStates.find(
-                    (state) =>
-                        state.type === "StaticMachine" &&
-                        state.points?.uuid === endPoint// check for static machine with matching point uuid
-                ) as any;
+                // Search simulationStates for a StaticMachine or Conveyor that has a point matching this endPointId
+                const matchedMachine = simulationStates.find((state) => {
+                    if (state.type === "Conveyor") {
+                        // For Conveyor, points is an array
+                        return (state).points.some(
+                            (point) => point.uuid === endPoint
+                        );
+                    } else if (state.type === "StaticMachine") {
+                        // For StaticMachine, points is an object
+                        return state.points.uuid === endPoint;
+                    }
+                    return false;
+                });
 
-                if (matchedStaticMachine) {
-                    setStaticMachines((machines) => {
-                        return machines.map((machine) => {
-                            if (machine.uuid === matchedStaticMachine.modeluuid) {
-                                return { ...machine, status: "running" };
-                            } else {
-                                return machine;
-                            }
+                if (matchedMachine) {
+                    // Log if the end point is a conveyor
+                    if (matchedMachine.type === "Conveyor") {
+                        logStatus(`[Arm ${uuid}] Reached end point which is a conveyor (${matchedMachine.modelName})`);
+                    } else {
+                        logStatus(`[Arm ${uuid}] Reached end point which is a static machine (${matchedMachine.modelName})`);
+                    }
+
+                    if (matchedMachine.type === "StaticMachine") {
+                        setStaticMachines((machines) => {
+                            return machines.map((machine) => {
+                                if (machine.uuid === matchedMachine.modeluuid) {
+                                    return { ...machine, status: "running" };
+                                } else {
+                                    return machine;
+                                }
+                            });
                         });
-                    });
+                    }
+
+                    if (matchedMachine.type === "Conveyor") {
+                        setArmBots((prev) =>
+                            prev.map((arm) => {
+                                if (arm.uuid === uuid) {
+                                    return {
+                                        ...arm,
+                                        isActive: false
+                                    };
+                                }
+                                else {
+                                    return arm;
+                                }
+                            })
+                        );
+                    }
                 }
             }
         }
diff --git a/app/src/modules/simulation/armbot/IkInstances.tsx b/app/src/modules/simulation/armbot/IkInstances.tsx
index 50b8ffb..5a0d23b 100644
--- a/app/src/modules/simulation/armbot/IkInstances.tsx
+++ b/app/src/modules/simulation/armbot/IkInstances.tsx
@@ -23,16 +23,12 @@ interface ArmBotState {
     status: string;
     material: string;
     triggerId: string;
-    actions: {
-        uuid: string;
-        name: string;
-        speed: number;
-        processes: {
-            triggerId: string;
-            startPoint: string;
-            endPoint: string;
-        }[];
+    connections: {
+        source: { modelUUID: string; pointUUID: string };
+        targets: { modelUUID: string; pointUUID: string }[];
     };
+    actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+    isActive?: boolean;
 }
 
 const IkInstances = ({
@@ -43,6 +39,7 @@ const IkInstances = ({
     position,
     rotation,
     armBot,
+    setArmBots,
     setStaticMachines,
     updateArmBotStatus
 }: {
@@ -53,6 +50,7 @@ const IkInstances = ({
     position: [number, number, number];
     rotation: [number, number, number];
     armBot: ArmBotState;
+    setArmBots: React.Dispatch<React.SetStateAction<ArmBotState[]>>;
     setStaticMachines: React.Dispatch<React.SetStateAction<StaticMachineState[]>>;
     updateArmBotStatus: (status: string) => void;
 }) => {
@@ -141,6 +139,7 @@ const IkInstances = ({
                 logStatus={logStatus}
                 groupRef={groupRef}
                 armBot={armBot}
+                setArmBots={setArmBots}
                 setStaticMachines={setStaticMachines}
                 updateArmBotStatus={updateArmBotStatus}
             />
diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx
index 460de49..f01e799 100644
--- a/app/src/modules/simulation/process/processAnimator.tsx
+++ b/app/src/modules/simulation/process/processAnimator.tsx
@@ -1,4 +1,4 @@
-import React, { useRef, useEffect, useMemo } from "react";
+import React, { useRef, useEffect, useMemo, useCallback } from "react";
 import { useLoader, useFrame } from "@react-three/fiber";
 import { GLTFLoader } from "three-stdlib";
 import * as THREE from "three";
@@ -18,9 +18,13 @@ interface ArmBotState {
   status: string;
   material: string;
   triggerId: string;
+  connections: {
+    source: { modelUUID: string; pointUUID: string };
+    targets: { modelUUID: string; pointUUID: string }[];
+  };
   actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+  isActive?: boolean;
 }
-
 interface ProcessContainerProps {
   processes: ProcessData[];
   setProcesses: React.Dispatch<React.SetStateAction<any[]>>;
@@ -103,9 +107,33 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
   // In processAnimator.tsx - only the relevant spawn logic part that needs fixes
 
+
+  // Add this function to ProcessAnimator component
+  const isConnectedToActiveArmBot = useCallback(
+    (processId: any) => {
+      // Check if any active armbot is connected to this process
+      return armBots.some((armbot) => {
+        if (!armbot.isActive) return false;
+
+        // Check if this armbot is connected to the process
+        return armbot.connections?.targets?.some((connection: any) => {
+          // Find the process that owns this modelUUID
+          const connectedProcess = processes.find((p) =>
+            p.paths?.some((path) => path.modeluuid === connection.modelUUID)
+          );
+          return connectedProcess?.id === processId;
+        });
+      });
+    },
+    [armBots, processes]
+  );
+
+  // In processAnimator.tsx - only the relevant spawn logic part that needs fixes
+
   useFrame(() => {
     // Spawn logic frame
-    const currentTime = clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
+    const currentTime =
+      clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
 
     setAnimationStates((prev) => {
       const newStates = { ...prev };
@@ -119,6 +147,14 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           return;
         }
 
+        if (isConnectedToActiveArmBot(process.id)) {
+          newStates[process.id] = {
+            ...processState,
+            nextSpawnTime: Infinity, // Prevent future spawns
+          };
+          return;
+        }
+
         const spawnPoint = findSpawnPoint(process);
         if (!spawnPoint || !spawnPoint.actions) return;
 
@@ -133,7 +169,10 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             : parseFloat(spawnAction.spawnInterval as string) || 0;
 
         // Check if this is a zero interval spawn and we already spawned an object
-        if (spawnInterval === 0 && processState.hasSpawnedZeroIntervalObject === true) {
+        if (
+          spawnInterval === 0 &&
+          processState.hasSpawnedZeroIntervalObject === true
+        ) {
           return; // Don't spawn more objects for zero interval
         }
 
@@ -183,6 +222,29 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
         const processState = newStates[process.id];
         if (!processState) return;
 
+        if (isConnectedToActiveArmBot(process.id)) {
+          newStates[process.id] = {
+            ...processState,
+            spawnedObjects: Object.entries(processState.spawnedObjects).reduce(
+              (acc, [id, obj]) => ({
+                ...acc,
+                [id]: {
+                  ...obj,
+                  state: {
+                    ...obj.state,
+                    isAnimating: false, // Stop animation
+                    isDelaying: false, // Clear delays
+                    delayComplete: false, // Reset delays
+                    progress: 0, // Reset progress
+                  },
+                },
+              }),
+              {}
+            ),
+          };
+          return;
+        }
+
         if (processState.isProcessDelaying) {
           const effectiveDelayTime =
             processState.processDelayDuration / speedRef.current;
@@ -338,10 +400,13 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             if (isLastPoint) {
               const isAgvPicking = agvRef.current.some(
-                (agv: any) => agv.processId === process.id && agv.status === "picking"
+                (agv: any) =>
+                  agv.processId === process.id && agv.status === "picking"
               );
 
-              const shouldHide = !currentPointData?.actions || !hasNonInheritActions(currentPointData.actions);
+              const shouldHide =
+                !currentPointData?.actions ||
+                !hasNonInheritActions(currentPointData.actions);
 
               if (shouldHide) {
                 if (isAgvPicking) {
@@ -372,7 +437,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             if (tempStackedObjectsRef.current[objectId]) {
               const isAgvPicking = agvRef.current.some(
-                (agv: any) => agv.processId === process.id && agv.status === "picking"
+                (agv: any) =>
+                  agv.processId === process.id && agv.status === "picking"
               );
 
               if (isAgvPicking) {
@@ -391,7 +457,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             if (!isLastPoint) {
               const nextPoint = path[nextPointIdx];
-              const distance = path[stateRef.currentIndex].distanceTo(nextPoint);
+              const distance =
+                path[stateRef.currentIndex].distanceTo(nextPoint);
               const effectiveSpeed = stateRef.speed * speedRef.current;
               const movement = effectiveSpeed * delta;
 
@@ -442,7 +509,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
       return newStates;
     });
   });
-
   if (!processedProcesses || processedProcesses.length === 0) {
     return null;
   }
diff --git a/app/src/modules/simulation/process/processContainer.tsx b/app/src/modules/simulation/process/processContainer.tsx
index 4cc7edf..0bcdb13 100644
--- a/app/src/modules/simulation/process/processContainer.tsx
+++ b/app/src/modules/simulation/process/processContainer.tsx
@@ -9,7 +9,12 @@ interface ArmBotState {
   status: string;
   material: string;
   triggerId: string;
+  connections: {
+      source: { modelUUID: string; pointUUID: string };
+      targets: { modelUUID: string; pointUUID: string }[];
+  };
   actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+  isActive?: boolean;
 }
 
 interface ProcessContainerProps {
diff --git a/app/src/modules/simulation/process/useProcessAnimations.tsx b/app/src/modules/simulation/process/useProcessAnimations.tsx
index 8c0f20d..5fc96dc 100644
--- a/app/src/modules/simulation/process/useProcessAnimations.tsx
+++ b/app/src/modules/simulation/process/useProcessAnimations.tsx
@@ -1,645 +1,651 @@
 import { useCallback, useEffect, useRef, useState } from "react";
 import * as THREE from "three";
 import {
-    ProcessData,
-    ProcessAnimationState,
-    SpawnedObject,
-    AnimationState,
-    ProcessPoint,
-    PointAction,
-    Trigger,
+  ProcessData,
+  ProcessAnimationState,
+  SpawnedObject,
+  AnimationState,
+  ProcessPoint,
+  PointAction,
+  Trigger,
 } from "./types";
 import {
-    useAnimationPlaySpeed,
-    usePauseButtonStore,
-    usePlayButtonStore,
-    useResetButtonStore,
+  useAnimationPlaySpeed,
+  usePauseButtonStore,
+  usePlayButtonStore,
+  useResetButtonStore,
 } from "../../../store/usePlayButtonStore";
 import { usePlayAgv } from "../../../store/store";
 
 // Enhanced ProcessAnimationState with trigger tracking
 interface EnhancedProcessAnimationState extends ProcessAnimationState {
-    triggerCounts: Record<string, number>;
-    triggerLogs: Array<{
-        timestamp: number;
-        pointId: string;
-        objectId: string;
-        triggerId: string;
-    }>;
+  triggerCounts: Record<string, number>;
+  triggerLogs: Array<{
+    timestamp: number;
+    pointId: string;
+    objectId: string;
+    triggerId: string;
+  }>;
 }
 
 interface ProcessContainerProps {
-    processes: ProcessData[];
-    setProcesses: React.Dispatch<React.SetStateAction<any[]>>;
-    agvRef: any;
+  processes: ProcessData[];
+  setProcesses: React.Dispatch<React.SetStateAction<any[]>>;
+  agvRef: any;
 }
 
 interface PlayAgvState {
-    playAgv: Record<string, any>;
-    setPlayAgv: (data: any) => void;
+  playAgv: Record<string, any>;
+  setPlayAgv: (data: any) => void;
 }
 
 interface ArmBotState {
-    uuid: string;
-    position: [number, number, number];
-    rotation: [number, number, number];
-    status: string;
-    material: string;
-    triggerId: string;
-    actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+  uuid: string;
+  position: [number, number, number];
+  rotation: [number, number, number];
+  status: string;
+  material: string;
+  triggerId: string;
+  connections: {
+    source: { modelUUID: string; pointUUID: string };
+    targets: { modelUUID: string; pointUUID: string }[];
+  };
+  actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+  isActive?: boolean;
 }
 
 export const useProcessAnimation = (
-    processes: ProcessData[],
-    setProcesses: React.Dispatch<React.SetStateAction<any[]>>,
-    agvRef: any,
-    armBots: ArmBotState[],
-    setArmBots: React.Dispatch<React.SetStateAction<ArmBotState[]>>
+  processes: ProcessData[],
+  setProcesses: React.Dispatch<React.SetStateAction<any[]>>,
+  agvRef: any,
+  armBots: ArmBotState[],
+  setArmBots: React.Dispatch<React.SetStateAction<ArmBotState[]>>
 ) => {
-    // State and refs initialization
-    const { isPlaying, setIsPlaying } = usePlayButtonStore();
-    const { isPaused, setIsPaused } = usePauseButtonStore();
-    const { isReset, setReset } = useResetButtonStore();
-    const debugRef = useRef<boolean>(false);
-    const clockRef = useRef<THREE.Clock>(new THREE.Clock());
-    const pauseTimeRef = useRef<number>(0);
-    const elapsedBeforePauseRef = useRef<number>(0);
-    const animationStatesRef = useRef<Record<string, EnhancedProcessAnimationState>>({});
-    const { speed } = useAnimationPlaySpeed();
-    const prevIsPlaying = useRef<boolean | null>(null);
-    const [internalResetFlag, setInternalResetFlag] = useState(false);
-    const [animationStates, setAnimationStates] = useState<Record<string, EnhancedProcessAnimationState>>({});
-    const speedRef = useRef<number>(speed);
-    const { PlayAgv, setPlayAgv } = usePlayAgv();
+  // State and refs initialization
+  const { isPlaying, setIsPlaying } = usePlayButtonStore();
+  const { isPaused, setIsPaused } = usePauseButtonStore();
+  const { isReset, setReset } = useResetButtonStore();
+  const debugRef = useRef<boolean>(false);
+  const clockRef = useRef<THREE.Clock>(new THREE.Clock());
+  const pauseTimeRef = useRef<number>(0);
+  const elapsedBeforePauseRef = useRef<number>(0);
+  const animationStatesRef = useRef<Record<string, EnhancedProcessAnimationState>>({});
+  const { speed } = useAnimationPlaySpeed();
+  const prevIsPlaying = useRef<boolean | null>(null);
+  const [internalResetFlag, setInternalResetFlag] = useState(false);
+  const [animationStates, setAnimationStates] = useState<Record<string, EnhancedProcessAnimationState>>({});
+  const speedRef = useRef<number>(speed);
+  const { PlayAgv, setPlayAgv } = usePlayAgv();
 
-    // Effect hooks
-    useEffect(() => {
-        speedRef.current = speed;
-    }, [speed]);
+  // Effect hooks
+  useEffect(() => {
+    speedRef.current = speed;
+  }, [speed]);
 
-    useEffect(() => {
-        if (prevIsPlaying.current !== null || !isPlaying) {
-            setAnimationStates({});
-        }
-        prevIsPlaying.current = isPlaying;
-    }, [isPlaying]);
+  useEffect(() => {
+    if (prevIsPlaying.current !== null || !isPlaying) {
+      setAnimationStates({});
+    }
+    prevIsPlaying.current = isPlaying;
+  }, [isPlaying]);
 
-    useEffect(() => {
-        animationStatesRef.current = animationStates;
-    }, [animationStates]);
+  useEffect(() => {
+    animationStatesRef.current = animationStates;
+  }, [animationStates]);
 
-    // Reset handler
-    useEffect(() => {
-        if (isReset) {
-            setInternalResetFlag(true);
-            setIsPlaying(false);
-            setIsPaused(false);
-            setAnimationStates({});
-            animationStatesRef.current = {};
-            clockRef.current = new THREE.Clock();
-            elapsedBeforePauseRef.current = 0;
-            pauseTimeRef.current = 0;
-            setReset(false);
-            setTimeout(() => {
-                setInternalResetFlag(false);
-                setIsPlaying(true);
-            }, 0);
-        }
-    }, [isReset, setReset, setIsPlaying, setIsPaused]);
+  // Reset handler
+  useEffect(() => {
+    if (isReset) {
+      setInternalResetFlag(true);
+      setIsPlaying(false);
+      setIsPaused(false);
+      setAnimationStates({});
+      animationStatesRef.current = {};
+      clockRef.current = new THREE.Clock();
+      elapsedBeforePauseRef.current = 0;
+      pauseTimeRef.current = 0;
+      setReset(false);
+      setTimeout(() => {
+        setInternalResetFlag(false);
+        setIsPlaying(true);
+      }, 0);
+    }
+  }, [isReset, setReset, setIsPlaying, setIsPaused]);
 
-    // Pause handler
-    useEffect(() => {
-        if (isPaused) {
-            pauseTimeRef.current = clockRef.current.getElapsedTime();
-        } else if (pauseTimeRef.current > 0) {
-            const pausedDuration = clockRef.current.getElapsedTime() - pauseTimeRef.current;
-            elapsedBeforePauseRef.current += pausedDuration;
-        }
-    }, [isPaused]);
+  // Pause handler
+  useEffect(() => {
+    if (isPaused) {
+      pauseTimeRef.current = clockRef.current.getElapsedTime();
+    } else if (pauseTimeRef.current > 0) {
+      const pausedDuration = clockRef.current.getElapsedTime() - pauseTimeRef.current;
+      elapsedBeforePauseRef.current += pausedDuration;
+    }
+  }, [isPaused]);
 
-    // Initialize animation states with trigger tracking
-    useEffect(() => {
-        if (isPlaying && !internalResetFlag) {
-            const newStates: Record<string, EnhancedProcessAnimationState> = {};
+  // Initialize animation states with trigger tracking
+  useEffect(() => {
+    if (isPlaying && !internalResetFlag) {
+      const newStates: Record<string, EnhancedProcessAnimationState> = {};
 
-            processes.forEach((process) => {
-                const triggerCounts: Record<string, number> = {};
+      processes.forEach((process) => {
+        const triggerCounts: Record<string, number> = {};
 
-                // Initialize trigger counts for all On-Hit triggers
-                process.paths?.forEach((path) => {
-                    path.points?.forEach((point) => {
-                        point.triggers?.forEach((trigger: Trigger) => {
-                            if (trigger.type === "On-Hit" && trigger.isUsed) {
-                                triggerCounts[`${point.uuid}-${trigger.uuid}`] = 0;
-                            }
-                        });
-                    });
-                });
-
-                newStates[process.id] = {
-                    spawnedObjects: {},
-                    nextSpawnTime: 0,
-                    objectIdCounter: 0,
-                    isProcessDelaying: false,
-                    processDelayStartTime: 0,
-                    processDelayDuration: 0,
-                    triggerCounts,
-                    triggerLogs: [],
-                };
+        // Initialize trigger counts for all On-Hit triggers
+        process.paths?.forEach((path) => {
+          path.points?.forEach((point) => {
+            point.triggers?.forEach((trigger: Trigger) => {
+              if (trigger.type === "On-Hit" && trigger.isUsed) {
+                triggerCounts[`${point.uuid}-${trigger.uuid}`] = 0;
+              }
             });
+          });
+        });
 
-            setAnimationStates(newStates);
-            animationStatesRef.current = newStates;
-            clockRef.current.start();
-        }
-    }, [isPlaying, processes, internalResetFlag]);
+        newStates[process.id] = {
+          spawnedObjects: {},
+          nextSpawnTime: 0,
+          objectIdCounter: 0,
+          isProcessDelaying: false,
+          processDelayStartTime: 0,
+          processDelayDuration: 0,
+          triggerCounts,
+          triggerLogs: [],
+        };
+      });
 
-    useEffect(() => {
-        if (isPlaying && !internalResetFlag) {
-            const newStates: Record<string, EnhancedProcessAnimationState> = {};
+      setAnimationStates(newStates);
+      animationStatesRef.current = newStates;
+      clockRef.current.start();
+    }
+  }, [isPlaying, processes, internalResetFlag]);
 
-            // Initialize AGVs for each process first
-            processes.forEach((process) => {
-                // Find all vehicle paths for this process
-                const vehiclePaths = process.paths?.filter(
-                    (path) => path.type === "Vehicle"
-                ) || [];
+  useEffect(() => {
+    if (isPlaying && !internalResetFlag) {
+      const newStates: Record<string, EnhancedProcessAnimationState> = {};
 
-                // Initialize AGVs for each vehicle path
-                vehiclePaths.forEach((vehiclePath) => {
-                    if (vehiclePath.points?.length > 0) {
-                        const vehiclePoint = vehiclePath.points[0];
-                        const action = vehiclePoint.actions?.[0];
-                        const maxHitCount = action?.hitCount;
+      // Initialize AGVs for each process first
+      processes.forEach((process) => {
+        // Find all vehicle paths for this process
+        const vehiclePaths = process.paths?.filter(
+          (path) => path.type === "Vehicle"
+        ) || [];
 
-                        const vehicleId = vehiclePath.modeluuid;
-                        const processId = process.id;
+        // Initialize AGVs for each vehicle path
+        vehiclePaths.forEach((vehiclePath) => {
+          if (vehiclePath.points?.length > 0) {
+            const vehiclePoint = vehiclePath.points[0];
+            const action = vehiclePoint.actions?.[0];
+            const maxHitCount = action?.hitCount;
 
-                        // Check if this AGV already exists
-                        const existingAgv = agvRef.current.find(
-                            (v: any) => v.vehicleId === vehicleId && v.processId === processId
-                        );
+            const vehicleId = vehiclePath.modeluuid;
+            const processId = process.id;
 
-                        if (!existingAgv) {
-                            // Initialize the AGV in a stationed state
-                            agvRef.current.push({
-                                processId,
-                                vehicleId,
-                                maxHitCount: maxHitCount || 0,
-                                isActive: false,
-                                hitCount: 0,
-                                status: 'stationed',
-                                lastUpdated: 0
-                            });
-                        }
-                    }
-                });
+            // Check if this AGV already exists
+            const existingAgv = agvRef.current.find(
+              (v: any) => v.vehicleId === vehicleId && v.processId === processId
+            );
 
-                // Then initialize trigger counts as before
-                const triggerCounts: Record<string, number> = {};
-                process.paths?.forEach((path) => {
-                    path.points?.forEach((point) => {
-                        point.triggers?.forEach((trigger: Trigger) => {
-                            if (trigger.type === "On-Hit" && trigger.isUsed) {
-                                triggerCounts[`${point.uuid}-${trigger.uuid}`] = 0;
-                            }
-                        });
-                    });
-                });
+            if (!existingAgv) {
+              // Initialize the AGV in a stationed state
+              agvRef.current.push({
+                processId,
+                vehicleId,
+                maxHitCount: maxHitCount || 0,
+                isActive: false,
+                hitCount: 0,
+                status: 'stationed',
+                lastUpdated: 0
+              });
+            }
+          }
+        });
 
-                newStates[process.id] = {
-                    spawnedObjects: {},
-                    nextSpawnTime: 0,
-                    objectIdCounter: 0,
-                    isProcessDelaying: false,
-                    processDelayStartTime: 0,
-                    processDelayDuration: 0,
-                    triggerCounts,
-                    triggerLogs: [],
-                };
+        // Then initialize trigger counts as before
+        const triggerCounts: Record<string, number> = {};
+        process.paths?.forEach((path) => {
+          path.points?.forEach((point) => {
+            point.triggers?.forEach((trigger: Trigger) => {
+              if (trigger.type === "On-Hit" && trigger.isUsed) {
+                triggerCounts[`${point.uuid}-${trigger.uuid}`] = 0;
+              }
             });
+          });
+        });
 
-            setAnimationStates(newStates);
-            animationStatesRef.current = newStates;
-            clockRef.current.start();
-        }
-    }, [isPlaying, processes, internalResetFlag]);
+        newStates[process.id] = {
+          spawnedObjects: {},
+          nextSpawnTime: 0,
+          objectIdCounter: 0,
+          isProcessDelaying: false,
+          processDelayStartTime: 0,
+          processDelayDuration: 0,
+          triggerCounts,
+          triggerLogs: [],
+        };
+      });
 
-    // Helper functions
-    const findSpawnPoint = (process: ProcessData): ProcessPoint | null => {
-        for (const path of process.paths || []) {
-            for (const point of path.points || []) {
-                const spawnAction = point.actions?.find(
-                    (a) => a.isUsed && a.type === "Spawn"
-                );
-                if (spawnAction) {
-                    return point;
-                }
-            }
-        }
-        return null;
-    };
+      setAnimationStates(newStates);
+      animationStatesRef.current = newStates;
+      clockRef.current.start();
+    }
+  }, [isPlaying, processes, internalResetFlag]);
 
-    const findAnimationPathPoint = (
-        process: ProcessData,
-        spawnPoint: ProcessPoint
-    ): THREE.Vector3 => {
-        if (process.animationPath && process.animationPath.length > 0) {
-            let pointIndex = 0;
-            for (const path of process.paths || []) {
-                for (let i = 0; i < (path.points?.length || 0); i++) {
-                    const point = path.points?.[i];
-                    if (point && point.uuid === spawnPoint.uuid) {
-                        if (process.animationPath[pointIndex]) {
-                            const p = process.animationPath[pointIndex];
-                            return new THREE.Vector3(p.x, p.y, p.z);
-                        }
-                    }
-                    pointIndex++;
-                }
-            }
-        }
-        return new THREE.Vector3(
-            spawnPoint.position[0],
-            spawnPoint.position[1],
-            spawnPoint.position[2]
+  // Helper functions
+  const findSpawnPoint = (process: ProcessData): ProcessPoint | null => {
+    for (const path of process.paths || []) {
+      for (const point of path.points || []) {
+        const spawnAction = point.actions?.find(
+          (a) => a.isUsed && a.type === "Spawn"
         );
-    };
-
-    // Optimized object creation
-    const createSpawnedObject = useCallback(
-        (
-            process: ProcessData,
-            currentTime: number,
-            materialType: string,
-            spawnPoint: ProcessPoint,
-            baseMaterials: Record<string, THREE.Material>
-        ): SpawnedObject => {
-            const processMaterials = {
-                ...baseMaterials,
-                ...(process.customMaterials || {}),
-            };
-
-            const spawnPosition = findAnimationPathPoint(process, spawnPoint);
-            const material =
-                processMaterials[materialType as keyof typeof processMaterials] ||
-                baseMaterials.Default;
-
-            return {
-                ref: { current: null },
-                state: {
-                    currentIndex: 0,
-                    progress: 0,
-                    isAnimating: true,
-                    speed: process.speed || 1,
-                    isDelaying: false,
-                    delayStartTime: 0,
-                    currentDelayDuration: 0,
-                    delayComplete: false,
-                    currentPathIndex: 0,
-                },
-                visible: true,
-                material: material,
-                currentMaterialType: materialType,
-                spawnTime: currentTime,
-                position: spawnPosition,
-            };
-        },
-        []
-    );
-
-    // Material handling
-    const handleMaterialSwap = useCallback(
-        (
-            processId: string,
-            objectId: string,
-            materialType: string,
-            processes: ProcessData[],
-            baseMaterials: Record<string, THREE.Material>
-        ) => {
-            setAnimationStates((prev) => {
-                const processState = prev[processId];
-                if (!processState || !processState.spawnedObjects[objectId])
-                    return prev;
-
-                const process = processes.find((p) => p.id === processId);
-                if (!process) return prev;
-
-                const processMaterials = {
-                    ...baseMaterials,
-                    ...(process.customMaterials || {}),
-                };
-
-                const newMaterial =
-                    processMaterials[materialType as keyof typeof processMaterials];
-                if (!newMaterial) return prev;
-
-                return {
-                    ...prev,
-                    [processId]: {
-                        ...processState,
-                        spawnedObjects: {
-                            ...processState.spawnedObjects,
-                            [objectId]: {
-                                ...processState.spawnedObjects[objectId],
-                                material: newMaterial,
-                                currentMaterialType: materialType,
-                            },
-                        },
-                    },
-                };
-            });
-        },
-        []
-    );
-
-    // Point action handler with trigger counting
-    const handlePointActions = useCallback(
-        (
-            processId: string,
-            objectId: string,
-            actions: PointAction[] = [],
-            currentTime: number,
-            processes: ProcessData[],
-            baseMaterials: Record<string, THREE.Material>
-        ): boolean => {
-            let shouldStopAnimation = false;
-
-            actions.forEach((action) => {
-                if (!action.isUsed) return;
-
-                switch (action.type) {
-                    case "Delay":
-                        setAnimationStates((prev) => {
-                            const processState = prev[processId];
-                            if (!processState || processState.isProcessDelaying) return prev;
-
-                            const delayDuration =
-                                typeof action.delay === "number"
-                                    ? action.delay
-                                    : parseFloat(action.delay as string) || 0;
-
-                            if (delayDuration > 0) {
-                                return {
-                                    ...prev,
-                                    [processId]: {
-                                        ...processState,
-                                        isProcessDelaying: true,
-                                        processDelayStartTime: currentTime,
-                                        processDelayDuration: delayDuration,
-                                        spawnedObjects: {
-                                            ...processState.spawnedObjects,
-                                            [objectId]: {
-                                                ...processState.spawnedObjects[objectId],
-                                                state: {
-                                                    ...processState.spawnedObjects[objectId].state,
-                                                    isAnimating: false,
-                                                    isDelaying: true,
-                                                    delayStartTime: currentTime,
-                                                    currentDelayDuration: delayDuration,
-                                                    delayComplete: false,
-                                                },
-                                            },
-                                        },
-                                    },
-                                };
-                            }
-                            return prev;
-                        });
-                        shouldStopAnimation = true;
-                        break;
-
-                    case "Despawn":
-                        setAnimationStates((prev) => {
-                            const processState = prev[processId];
-                            if (!processState) return prev;
-
-                            const newSpawnedObjects = { ...processState.spawnedObjects };
-                            delete newSpawnedObjects[objectId];
-
-                            return {
-                                ...prev,
-                                [processId]: {
-                                    ...processState,
-                                    spawnedObjects: newSpawnedObjects,
-                                },
-                            };
-                        });
-                        shouldStopAnimation = true;
-                        break;
-
-                    case "Swap":
-                        if (action.material) {
-                            handleMaterialSwap(
-                                processId,
-                                objectId,
-                                action.material,
-                                processes,
-                                baseMaterials
-                            );
-                        }
-                        break;
-
-                    default:
-                        break;
-                }
-            });
-
-            return shouldStopAnimation;
-        },
-        [handleMaterialSwap]
-    );
-
-    const deferredArmBotUpdates = useRef<{ uuid: string; triggerId: string }[]>([]);
-
-    // Trigger counting system
-    const checkAndCountTriggers = useCallback(
-        (
-            processId: string,
-            objectId: string,
-            currentPointIndex: number,
-            processes: ProcessData[],
-            currentTime: number
-        ) => {
-            setAnimationStates((prev) => {
-                const processState = prev[processId];
-                if (!processState) return prev;
-
-                const process = processes.find((p) => p.id === processId);
-                if (!process) return prev;
-
-                const point = getPointDataForAnimationIndex(process, currentPointIndex);
-                if (!point?.triggers) return prev;
-
-                const onHitTriggers = point.triggers.filter((t: Trigger) => t.type === "On-Hit" && t.isUsed);
-
-                if (onHitTriggers.length === 0) return prev;
-
-                let newTriggerCounts = { ...processState.triggerCounts };
-                const newTriggerLogs = [...processState.triggerLogs];
-                let shouldLog = false;
-
-                const vehiclePaths = process.paths.filter((path) => path.type === "Vehicle");
-                const armBotPaths = process.paths.filter((path) => path.type === "ArmBot");
-
-                const activeVehicles = vehiclePaths.filter((path) => {
-                    const vehicleId = path.modeluuid;
-                    const vehicleEntry = agvRef.current.find((v: any) => v.vehicleId === vehicleId && v.processId === processId);
-                    return vehicleEntry?.isActive;
-                });
-
-                // Check if any ArmBot is active for this process
-                // const activeArmBots = armBotPaths.filter((path) => {
-                //     const armBotId = path.modeluuid;
-                //     const armBotEntry = armBots.find((a: any) => a.uuid === armBotId);
-                //     return armBotEntry;
-                // });
-
-                // Only count triggers if no vehicles and no ArmBots are active for this process
-
-                if (activeVehicles.length === 0) {
-                    onHitTriggers.forEach((trigger: Trigger) => {
-                        const connections = point.connections?.targets || [];
-
-                        connections.forEach((connection) => {
-                            const connectedModelUUID = connection.modelUUID;
-
-                            const matchingArmPath = armBotPaths.find((path) => path.modeluuid === connectedModelUUID);
-
-                            if (matchingArmPath) {
-                                deferredArmBotUpdates.current.push({
-                                    uuid: connectedModelUUID,
-                                    triggerId: trigger.uuid,
-                                });
-                            }
-                        });
-                    });
-                }
-
-                let processTotalHits = Object.values(newTriggerCounts).reduce((a, b) => a + b, 0);
-
-                // Handle logic for vehicles and ArmBots when a trigger is hit
-                if (shouldLog) {
-                    vehiclePaths.forEach((vehiclePath) => {
-                        if (vehiclePath.points?.length > 0) {
-                            const vehiclePoint = vehiclePath.points[0];
-                            const action = vehiclePoint.actions?.[0];
-                            const maxHitCount = action?.hitCount;
-
-                            if (maxHitCount !== undefined) {
-                                const vehicleId = vehiclePath.modeluuid;
-                                let vehicleEntry = agvRef.current.find(
-                                    (v: any) =>
-                                        v.vehicleId === vehicleId && v.processId === processId
-                                );
-
-                                if (!vehicleEntry) {
-                                    vehicleEntry = {
-                                        processId,
-                                        vehicleId,
-                                        maxHitCount: maxHitCount,
-                                        isActive: false,
-                                        hitCount: 0,
-                                        status: "stationed",
-                                    };
-                                    agvRef.current.push(vehicleEntry);
-                                }
-
-                                if (!vehicleEntry.isActive) {
-                                    vehicleEntry.hitCount++;
-                                    vehicleEntry.lastUpdated = currentTime;
-
-                                    if (vehicleEntry.hitCount >= vehicleEntry.maxHitCount) {
-                                        vehicleEntry.isActive = true;
-                                        newTriggerCounts = {};
-                                        processTotalHits = 0;
-                                    }
-                                }
-                            }
-                        }
-                    });
-                }
-
-                return {
-                    ...prev,
-                    [processId]: {
-                        ...processState,
-                        triggerCounts: newTriggerCounts,
-                        triggerLogs: newTriggerLogs,
-                        totalHits: processTotalHits,
-                    },
-                };
-            });
-        }, []);
-
-    useEffect(() => {
-        if (deferredArmBotUpdates.current.length > 0) {
-            const updates = [...deferredArmBotUpdates.current];
-            deferredArmBotUpdates.current = [];
-
-            setArmBots((prev) =>
-                prev.map((bot) => {
-                    const update = updates.find((u) => u.uuid === bot.uuid);
-                    return update ? { ...bot, triggerId: update.triggerId } : bot;
-                })
-            );
+        if (spawnAction) {
+          return point;
         }
-    }, [animationStates]); 
+      }
+    }
+    return null;
+  };
 
-    // Utility functions
-    const hasNonInheritActions = useCallback(
-        (actions: PointAction[] = []): boolean => {
-            return actions.some(
-                (action) => action.isUsed && action.type !== "Inherit"
-            );
-        },
-        []
+  const findAnimationPathPoint = (
+    process: ProcessData,
+    spawnPoint: ProcessPoint
+  ): THREE.Vector3 => {
+    if (process.animationPath && process.animationPath.length > 0) {
+      let pointIndex = 0;
+      for (const path of process.paths || []) {
+        for (let i = 0; i < (path.points?.length || 0); i++) {
+          const point = path.points?.[i];
+          if (point && point.uuid === spawnPoint.uuid) {
+            if (process.animationPath[pointIndex]) {
+              const p = process.animationPath[pointIndex];
+              return new THREE.Vector3(p.x, p.y, p.z);
+            }
+          }
+          pointIndex++;
+        }
+      }
+    }
+    return new THREE.Vector3(
+      spawnPoint.position[0],
+      spawnPoint.position[1],
+      spawnPoint.position[2]
     );
+  };
 
-    const getPointDataForAnimationIndex = useCallback(
-        (process: ProcessData, index: number): ProcessPoint | null => {
-            if (!process.paths) return null;
+  // Optimized object creation
+  const createSpawnedObject = useCallback(
+    (
+      process: ProcessData,
+      currentTime: number,
+      materialType: string,
+      spawnPoint: ProcessPoint,
+      baseMaterials: Record<string, THREE.Material>
+    ): SpawnedObject => {
+      const processMaterials = {
+        ...baseMaterials,
+        ...(process.customMaterials || {}),
+      };
 
-            let cumulativePoints = 0;
-            for (const path of process.paths) {
-                const pointCount = path.points?.length || 0;
+      const spawnPosition = findAnimationPathPoint(process, spawnPoint);
+      const material =
+        processMaterials[materialType as keyof typeof processMaterials] ||
+        baseMaterials.Default;
 
-                if (index < cumulativePoints + pointCount) {
-                    const pointIndex = index - cumulativePoints;
-                    return path.points?.[pointIndex] || null;
+      return {
+        ref: { current: null },
+        state: {
+          currentIndex: 0,
+          progress: 0,
+          isAnimating: true,
+          speed: process.speed || 1,
+          isDelaying: false,
+          delayStartTime: 0,
+          currentDelayDuration: 0,
+          delayComplete: false,
+          currentPathIndex: 0,
+        },
+        visible: true,
+        material: material,
+        currentMaterialType: materialType,
+        spawnTime: currentTime,
+        position: spawnPosition,
+      };
+    },
+    []
+  );
+
+  // Material handling
+  const handleMaterialSwap = useCallback(
+    (
+      processId: string,
+      objectId: string,
+      materialType: string,
+      processes: ProcessData[],
+      baseMaterials: Record<string, THREE.Material>
+    ) => {
+      setAnimationStates((prev) => {
+        const processState = prev[processId];
+        if (!processState || !processState.spawnedObjects[objectId])
+          return prev;
+
+        const process = processes.find((p) => p.id === processId);
+        if (!process) return prev;
+
+        const processMaterials = {
+          ...baseMaterials,
+          ...(process.customMaterials || {}),
+        };
+
+        const newMaterial =
+          processMaterials[materialType as keyof typeof processMaterials];
+        if (!newMaterial) return prev;
+
+        return {
+          ...prev,
+          [processId]: {
+            ...processState,
+            spawnedObjects: {
+              ...processState.spawnedObjects,
+              [objectId]: {
+                ...processState.spawnedObjects[objectId],
+                material: newMaterial,
+                currentMaterialType: materialType,
+              },
+            },
+          },
+        };
+      });
+    },
+    []
+  );
+
+  // Point action handler with trigger counting
+  const handlePointActions = useCallback(
+    (
+      processId: string,
+      objectId: string,
+      actions: PointAction[] = [],
+      currentTime: number,
+      processes: ProcessData[],
+      baseMaterials: Record<string, THREE.Material>
+    ): boolean => {
+      let shouldStopAnimation = false;
+
+      actions.forEach((action) => {
+        if (!action.isUsed) return;
+
+        switch (action.type) {
+          case "Delay":
+            setAnimationStates((prev) => {
+              const processState = prev[processId];
+              if (!processState || processState.isProcessDelaying) return prev;
+
+              const delayDuration =
+                typeof action.delay === "number"
+                  ? action.delay
+                  : parseFloat(action.delay as string) || 0;
+
+              if (delayDuration > 0) {
+                return {
+                  ...prev,
+                  [processId]: {
+                    ...processState,
+                    isProcessDelaying: true,
+                    processDelayStartTime: currentTime,
+                    processDelayDuration: delayDuration,
+                    spawnedObjects: {
+                      ...processState.spawnedObjects,
+                      [objectId]: {
+                        ...processState.spawnedObjects[objectId],
+                        state: {
+                          ...processState.spawnedObjects[objectId].state,
+                          isAnimating: false,
+                          isDelaying: true,
+                          delayStartTime: currentTime,
+                          currentDelayDuration: delayDuration,
+                          delayComplete: false,
+                        },
+                      },
+                    },
+                  },
+                };
+              }
+              return prev;
+            });
+            shouldStopAnimation = true;
+            break;
+
+          case "Despawn":
+            setAnimationStates((prev) => {
+              const processState = prev[processId];
+              if (!processState) return prev;
+
+              const newSpawnedObjects = { ...processState.spawnedObjects };
+              delete newSpawnedObjects[objectId];
+
+              return {
+                ...prev,
+                [processId]: {
+                  ...processState,
+                  spawnedObjects: newSpawnedObjects,
+                },
+              };
+            });
+            shouldStopAnimation = true;
+            break;
+
+          case "Swap":
+            if (action.material) {
+              handleMaterialSwap(
+                processId,
+                objectId,
+                action.material,
+                processes,
+                baseMaterials
+              );
+            }
+            break;
+
+          default:
+            break;
+        }
+      });
+
+      return shouldStopAnimation;
+    },
+    [handleMaterialSwap]
+  );
+
+  const deferredArmBotUpdates = useRef<{ uuid: string; triggerId: string }[]>([]);
+
+  // Trigger counting system
+  const checkAndCountTriggers = useCallback(
+    (
+      processId: string,
+      objectId: string,
+      currentPointIndex: number,
+      processes: ProcessData[],
+      currentTime: number
+    ) => {
+      setAnimationStates((prev) => {
+        const processState = prev[processId];
+        if (!processState) return prev;
+
+        const process = processes.find((p) => p.id === processId);
+        if (!process) return prev;
+
+        const point = getPointDataForAnimationIndex(process, currentPointIndex);
+        if (!point?.triggers) return prev;
+
+        const onHitTriggers = point.triggers.filter((t: Trigger) => t.type === "On-Hit" && t.isUsed);
+
+        if (onHitTriggers.length === 0) return prev;
+
+        let newTriggerCounts = { ...processState.triggerCounts };
+        const newTriggerLogs = [...processState.triggerLogs];
+        let shouldLog = false;
+
+        const vehiclePaths = process.paths.filter((path) => path.type === "Vehicle");
+        const armBotPaths = process.paths.filter((path) => path.type === "ArmBot");
+
+        const activeVehicles = vehiclePaths.filter((path) => {
+          const vehicleId = path.modeluuid;
+          const vehicleEntry = agvRef.current.find((v: any) => v.vehicleId === vehicleId && v.processId === processId);
+          return vehicleEntry?.isActive;
+        });
+
+        // Check if any ArmBot is active for this process
+        // const activeArmBots = armBotPaths.filter((path) => {
+        //     const armBotId = path.modeluuid;
+        //     const armBotEntry = armBots.find((a: any) => a.uuid === armBotId);
+        //     return armBotEntry;
+        // });
+
+        // Only count triggers if no vehicles and no ArmBots are active for this process
+
+        if (activeVehicles.length === 0) {
+          onHitTriggers.forEach((trigger: Trigger) => {
+            const connections = point.connections?.targets || [];
+
+            connections.forEach((connection) => {
+              const connectedModelUUID = connection.modelUUID;
+
+              const matchingArmPath = armBotPaths.find((path) => path.modeluuid === connectedModelUUID);
+
+              if (matchingArmPath) {
+                deferredArmBotUpdates.current.push({
+                  uuid: connectedModelUUID,
+                  triggerId: trigger.uuid,
+                });
+              }
+            });
+          });
+        }
+
+        let processTotalHits = Object.values(newTriggerCounts).reduce((a, b) => a + b, 0);
+
+        // Handle logic for vehicles and ArmBots when a trigger is hit
+        if (shouldLog) {
+          vehiclePaths.forEach((vehiclePath) => {
+            if (vehiclePath.points?.length > 0) {
+              const vehiclePoint = vehiclePath.points[0];
+              const action = vehiclePoint.actions?.[0];
+              const maxHitCount = action?.hitCount;
+
+              if (maxHitCount !== undefined) {
+                const vehicleId = vehiclePath.modeluuid;
+                let vehicleEntry = agvRef.current.find(
+                  (v: any) =>
+                    v.vehicleId === vehicleId && v.processId === processId
+                );
+
+                if (!vehicleEntry) {
+                  vehicleEntry = {
+                    processId,
+                    vehicleId,
+                    maxHitCount: maxHitCount,
+                    isActive: false,
+                    hitCount: 0,
+                    status: "stationed",
+                  };
+                  agvRef.current.push(vehicleEntry);
                 }
 
-                cumulativePoints += pointCount;
+                if (!vehicleEntry.isActive) {
+                  vehicleEntry.hitCount++;
+                  vehicleEntry.lastUpdated = currentTime;
+
+                  if (vehicleEntry.hitCount >= vehicleEntry.maxHitCount) {
+                    vehicleEntry.isActive = true;
+                    newTriggerCounts = {};
+                    processTotalHits = 0;
+                  }
+                }
+              }
             }
+          });
+        }
 
-            return null;
-        },
-        []
-    );
-
-    const getTriggerCounts = useCallback((processId: string) => {
-        return animationStatesRef.current[processId]?.triggerCounts || {};
+        return {
+          ...prev,
+          [processId]: {
+            ...processState,
+            triggerCounts: newTriggerCounts,
+            triggerLogs: newTriggerLogs,
+            totalHits: processTotalHits,
+          },
+        };
+      });
     }, []);
 
-    const getTriggerLogs = useCallback((processId: string) => {
-        return animationStatesRef.current[processId]?.triggerLogs || [];
+  useEffect(() => {
+    if (deferredArmBotUpdates.current.length > 0) {
+      const updates = [...deferredArmBotUpdates.current];
+      deferredArmBotUpdates.current = [];
+
+      setArmBots((prev) =>
+        prev.map((bot) => {
+          const update = updates.find((u) => u.uuid === bot.uuid);
+
+          return update
+            ? { ...bot, triggerId: update.triggerId, isActive: true }
+            : bot;
+        })
+      );
+    }
+  }, [animationStates]);
+
+  // Utility functions
+  const hasNonInheritActions = useCallback(
+    (actions: PointAction[] = []): boolean => {
+      return actions.some(
+        (action) => action.isUsed && action.type !== "Inherit"
+      );
     }, []);
 
-    return {
-        animationStates,
-        setAnimationStates,
-        clockRef,
-        elapsedBeforePauseRef,
-        speedRef,
-        debugRef,
-        findSpawnPoint,
-        createSpawnedObject,
-        handlePointActions,
-        hasNonInheritActions,
-        getPointDataForAnimationIndex,
-        checkAndCountTriggers,
-        getTriggerCounts,
-        getTriggerLogs,
-        processes,
-    };
+  const getPointDataForAnimationIndex = useCallback(
+    (process: ProcessData, index: number): ProcessPoint | null => {
+      if (!process.paths) return null;
+
+      let cumulativePoints = 0;
+      for (const path of process.paths) {
+        const pointCount = path.points?.length || 0;
+
+        if (index < cumulativePoints + pointCount) {
+          const pointIndex = index - cumulativePoints;
+          return path.points?.[pointIndex] || null;
+        }
+
+        cumulativePoints += pointCount;
+      }
+
+      return null;
+    },
+    []
+  );
+
+  const getTriggerCounts = useCallback((processId: string) => {
+    return animationStatesRef.current[processId]?.triggerCounts || {};
+  }, []);
+
+  const getTriggerLogs = useCallback((processId: string) => {
+    return animationStatesRef.current[processId]?.triggerLogs || [];
+  }, []);
+
+  return {
+    animationStates,
+    setAnimationStates,
+    clockRef,
+    elapsedBeforePauseRef,
+    speedRef,
+    debugRef,
+    findSpawnPoint,
+    createSpawnedObject,
+    handlePointActions,
+    hasNonInheritActions,
+    getPointDataForAnimationIndex,
+    checkAndCountTriggers,
+    getTriggerCounts,
+    getTriggerLogs,
+    processes,
+  };
 };
diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx
index 2f66ab8..84d3651 100644
--- a/app/src/modules/simulation/simulation.tsx
+++ b/app/src/modules/simulation/simulation.tsx
@@ -15,7 +15,12 @@ interface ArmBotState {
     status: string;
     material: string;
     triggerId: string;
+    connections: {
+        source: { modelUUID: string; pointUUID: string };
+        targets: { modelUUID: string; pointUUID: string }[];
+    };
     actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+    isActive?: boolean;
 }
 
 interface StaticMachineState {
diff --git a/app/src/modules/simulation/staticMachine/staticMachine.tsx b/app/src/modules/simulation/staticMachine/staticMachine.tsx
index ba9b4f0..26760eb 100644
--- a/app/src/modules/simulation/staticMachine/staticMachine.tsx
+++ b/app/src/modules/simulation/staticMachine/staticMachine.tsx
@@ -10,9 +10,13 @@ interface ArmBotState {
     status: string;
     material: string;
     triggerId: string;
+    connections: {
+        source: { modelUUID: string; pointUUID: string };
+        targets: { modelUUID: string; pointUUID: string }[];
+    };
     actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+    isActive?: boolean;
 }
-
 interface StaticMachineState {
     uuid: string;
     status: string;

From 43d21a522c6da72e05727f9f34c6c41991a36dfc Mon Sep 17 00:00:00 2001
From: SreeNath14 <153710861+SreeNath14@users.noreply.github.com>
Date: Wed, 16 Apr 2025 12:09:18 +0530
Subject: [PATCH 11/20] bug fix

---
 .../simulation/process/processAnimator.tsx    | 173 ++++++++++++------
 1 file changed, 118 insertions(+), 55 deletions(-)

diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx
index 19e55b8..f6cda0b 100644
--- a/app/src/modules/simulation/process/processAnimator.tsx
+++ b/app/src/modules/simulation/process/processAnimator.tsx
@@ -9,7 +9,6 @@ import { useProcessAnimation } from "./useProcessAnimations";
 import ProcessObject from "./processObject";
 import { ProcessData } from "./types";
 
-
 interface ArmBotState {
   uuid: string;
   position: [number, number, number];
@@ -21,7 +20,12 @@ interface ArmBotState {
     source: { modelUUID: string; pointUUID: string };
     targets: { modelUUID: string; pointUUID: string }[];
   };
-  actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
+  actions: {
+    uuid: string;
+    name: string;
+    speed: number;
+    processes: { triggerId: string; startPoint: string; endPoint: string }[];
+  };
   isActive?: boolean;
 }
 interface ProcessContainerProps {
@@ -39,7 +43,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
   agvRef,
   MaterialRef,
   armBots,
-  setArmBots
+  setArmBots,
 }) => {
   const gltf = useLoader(GLTFLoader, crate) as GLTF;
   const groupRef = useRef<THREE.Group>(null);
@@ -114,7 +118,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
   // In processAnimator.tsx - only the relevant spawn logic part that needs fixes
 
-
   // Add this function to ProcessAnimator component
   const isConnectedToActiveArmBot = useCallback(
     (processId: any) => {
@@ -123,7 +126,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
         if (!armbot.isActive) return false;
 
         // Check if this armbot is connected to the process
-        return armbot.connections?.targets?.some((connection: any) => {
+        return armbot.connections?.targets?.some((connection) => {
           // Find the process that owns this modelUUID
           const connectedProcess = processes.find((p) =>
             p.paths?.some((path) => path.modeluuid === connection.modelUUID)
@@ -135,8 +138,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
     [armBots, processes]
   );
 
-  // In processAnimator.tsx - only the relevant spawn logic part that needs fixes
-
+  // First useFrame for spawn logic
   useFrame(() => {
     // Spawn logic frame
     const currentTime =
@@ -149,12 +151,15 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
         const processState = newStates[process.id];
         if (!processState) return;
 
+        // Check connection status
+        const isConnected = isConnectedToActiveArmBot(process.id);
+
         if (processState.isProcessDelaying) {
           // Existing delay handling logic...
           return;
         }
 
-        if (isConnectedToActiveArmBot(process.id)) {
+        if (isConnected) {
           newStates[process.id] = {
             ...processState,
             nextSpawnTime: Infinity, // Prevent future spawns
@@ -163,17 +168,24 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
         }
 
         const spawnPoint = findSpawnPoint(process);
-        if (!spawnPoint || !spawnPoint.actions) return;
+        if (!spawnPoint || !spawnPoint.actions) {
+          console.log(
+            `Process ${process.id} has no valid spawn point or actions`
+          );
+          return;
+        }
 
         const spawnAction = spawnPoint.actions.find(
           (a) => a.isUsed && a.type === "Spawn"
         );
-        if (!spawnAction) return;
+        if (!spawnAction) {
+          return;
+        }
 
         const spawnInterval =
           typeof spawnAction.spawnInterval === "number"
             ? spawnAction.spawnInterval
-            : parseFloat(spawnAction.spawnInterval as string) || 0;
+            : parseFloat(spawnAction.spawnInterval || "0") || 0;
 
         // Check if this is a zero interval spawn and we already spawned an object
         if (
@@ -195,6 +207,15 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             baseMaterials
           );
 
+          // Initialize state properly to ensure animation
+          newObject.state = {
+            ...newObject.state,
+            isAnimating: true,
+            isDelaying: false,
+            delayComplete: false,
+            progress: 0.005, // Start with tiny progress to ensure animation begins
+          };
+
           // Update state with the new object and flag for zero interval
           newStates[process.id] = {
             ...processState,
@@ -217,6 +238,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
     });
   });
 
+  // Second useFrame for animation logic
   useFrame((_, delta) => {
     // Animation logic frame
     const currentTime =
@@ -227,9 +249,19 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
       processedProcesses.forEach((process) => {
         const processState = newStates[process.id];
-        if (!processState) return;
+        if (!processState) {
+          return;
+        }
 
-        if (isConnectedToActiveArmBot(process.id)) {
+        // Check connection status with debugging
+        const isConnected = isConnectedToActiveArmBot(process.id);
+        console.log(
+          `Process ${process.id} animation - connected:`,
+          isConnected
+        );
+
+        if (isConnected) {
+          // Stop all animations when connected to active arm bot
           newStates[process.id] = {
             ...processState,
             spawnedObjects: Object.entries(processState.spawnedObjects).reduce(
@@ -252,6 +284,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           return;
         }
 
+        // Process delay handling
         if (processState.isProcessDelaying) {
           const effectiveDelayTime =
             processState.processDelayDuration / speedRef.current;
@@ -260,6 +293,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             currentTime - processState.processDelayStartTime >=
             effectiveDelayTime
           ) {
+            console.log(
+              `Process ${process.id} delay completed, resuming animation`
+            );
             newStates[process.id] = {
               ...processState,
               isProcessDelaying: false,
@@ -283,26 +319,42 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                 {}
               ),
             };
-            return newStates;
+            return;
           } else {
-            return newStates;
+            return;
           }
         }
 
+        // Ensure we have a valid path to follow
         const path =
           process.animationPath?.map((p) => new THREE.Vector3(p.x, p.y, p.z)) ||
           [];
-        if (path.length < 2) return;
+
+        if (path.length < 2) {
+          console.log(
+            `Process ${process.id} has insufficient path points: ${path.length}`
+          );
+          return;
+        }
 
         const updatedObjects = { ...processState.spawnedObjects };
+        let animationOccurring = false; // Track if any animation is happening
 
         Object.entries(processState.spawnedObjects).forEach(
           ([objectId, obj]) => {
-            if (!obj.visible) return;
+            if (!obj.visible) {
+              return;
+            }
 
             const currentRef = gltf?.scene ? obj.ref.current : obj.ref.current;
-            if (!currentRef) return;
+            if (!currentRef) {
+              console.log(
+                `No reference for object ${objectId}, skipping animation`
+              );
+              return;
+            }
 
+            // Initialize position for new objects
             if (
               obj.position &&
               obj.state.currentIndex === 0 &&
@@ -313,11 +365,22 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             const stateRef = obj.state;
 
+            // Ensure animation state is properly set for objects
+            if (!stateRef.isAnimating && !stateRef.isDelaying && !isConnected) {
+              stateRef.isAnimating = true;
+              stateRef.progress =
+                stateRef.progress > 0 ? stateRef.progress : 0.005;
+            }
+
+            // Handle delay logic
             if (stateRef.isDelaying) {
               const effectiveDelayTime =
                 stateRef.currentDelayDuration / speedRef.current;
 
               if (currentTime - stateRef.delayStartTime >= effectiveDelayTime) {
+                console.log(
+                  `Delay complete for object ${objectId}, resuming animation`
+                );
                 stateRef.isDelaying = false;
                 stateRef.delayComplete = true;
                 stateRef.isAnimating = true;
@@ -343,8 +406,17 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
               }
             }
 
-            if (!stateRef.isAnimating) return;
+            // Skip non-animating objects
+            if (!stateRef.isAnimating) {
+              console.log(
+                `Object ${objectId} not animating, skipping animation updates`
+              );
+              return;
+            }
 
+            animationOccurring = true; // Mark that animation is happening
+
+            // Handle point actions
             const currentPointData = getPointDataForAnimationIndex(
               process,
               stateRef.currentIndex
@@ -369,42 +441,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             const nextPointIdx = stateRef.currentIndex + 1;
             const isLastPoint = nextPointIdx >= path.length;
 
-            // if (isLastPoint) {
-            //   if (currentPointData?.actions) {
-            //     const shouldStop = !hasNonInheritActions(
-            //       currentPointData.actions
-            //     );
-            //     if (shouldStop) {
-            //       return;
-            //     }
-            //   }
-            // }
-
-            // if (isLastPoint) {
-            //   if (currentPointData?.actions) {
-            //     const hasNonInherit = hasNonInheritActions(
-            //       currentPointData.actions
-            //     );
-            //     if (!hasNonInherit) {
-            //       // Remove the object if all actions are inherit
-            //       updatedObjects[objectId] = {
-            //         ...obj,
-            //         visible: false,
-            //         state: { ...stateRef, isAnimating: false },
-            //       };
-            //       return;
-            //     }
-            //   } else {
-            //     // No actions at last point - remove the object
-            //     updatedObjects[objectId] = {
-            //       ...obj,
-            //       visible: false,
-            //       state: { ...stateRef, isAnimating: false },
-            //     };
-            //     return;
-            //   }
-            // }
-
+            // Handle objects at the last point
             if (isLastPoint) {
               const isAgvPicking = agvRef.current.some(
                 (agv: any) =>
@@ -417,6 +454,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
               if (shouldHide) {
                 if (isAgvPicking) {
+                  console.log(
+                    `AGV picking at last point for object ${objectId}, hiding object`
+                  );
                   updatedObjects[objectId] = {
                     ...obj,
                     visible: false,
@@ -442,6 +482,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
               }
             }
 
+            // Handle stacked objects when AGV picks
             if (tempStackedObjectsRef.current[objectId]) {
               const isAgvPicking = agvRef.current.some(
                 (agv: any) =>
@@ -459,9 +500,12 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                     isAnimating: false,
                   },
                 };
+
+                return;
               }
             }
 
+            // Handle normal animation progress for objects not at last point
             if (!isLastPoint) {
               const nextPoint = path[nextPointIdx];
               const distance =
@@ -469,13 +513,21 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
               const effectiveSpeed = stateRef.speed * speedRef.current;
               const movement = effectiveSpeed * delta;
 
+              // Ensure progress is always moving forward
               if (stateRef.delayComplete && stateRef.progress < 0.01) {
                 stateRef.progress = 0.05;
                 stateRef.delayComplete = false;
+                console.log(
+                  `Boosting progress for object ${objectId} after delay`
+                );
               } else {
                 stateRef.progress += movement / distance;
+                console.log(
+                  `Object ${objectId} progress: ${stateRef.progress.toFixed(3)}`
+                );
               }
 
+              // Handle point transition
               if (stateRef.progress >= 1) {
                 stateRef.currentIndex = nextPointIdx;
                 stateRef.progress = 0;
@@ -494,7 +546,10 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                   process,
                   stateRef.currentIndex
                 );
+
+                // No action needed with newPointData here - will be handled in next frame
               } else {
+                // Update position with lerp
                 currentRef.position.lerpVectors(
                   path[stateRef.currentIndex],
                   nextPoint,
@@ -507,6 +562,13 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           }
         );
 
+        // Log if no animation is occurring when it should
+        if (!animationOccurring && !isConnected) {
+          console.log(
+            `Warning: No animation occurring for process ${process.id} despite not being connected`
+          );
+        }
+
         newStates[process.id] = {
           ...processState,
           spawnedObjects: updatedObjects,
@@ -516,6 +578,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
       return newStates;
     });
   });
+
   if (!processedProcesses || processedProcesses.length === 0) {
     return null;
   }

From a59aa1d61c7e7d1c277058b01e9d73755a367bbd Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B <jerald@hexrfactory.com>
Date: Wed, 16 Apr 2025 13:22:47 +0530
Subject: [PATCH 12/20] feat: Add MaterialInstances component for rendering
 animated materials based on active curves refactor: Clean up console logs in
 ProcessAnimator for better readability fix: Update group visibility logic in
 Agv and PathNavigator components

---
 app/src/modules/builder/agv/agv.tsx           |  3 +-
 app/src/modules/builder/agv/pathNavigator.tsx |  4 +-
 .../armbot/IKAnimationController.tsx          | 19 ++++++++-
 .../simulation/armbot/MaterialInstances.tsx   | 42 +++++++++++++++++++
 .../simulation/process/processAnimator.tsx    | 37 ++--------------
 .../process/useProcessAnimations.tsx          | 10 ++++-
 6 files changed, 76 insertions(+), 39 deletions(-)
 create mode 100644 app/src/modules/simulation/armbot/MaterialInstances.tsx

diff --git a/app/src/modules/builder/agv/agv.tsx b/app/src/modules/builder/agv/agv.tsx
index c2e7783..0a2d14e 100644
--- a/app/src/modules/builder/agv/agv.tsx
+++ b/app/src/modules/builder/agv/agv.tsx
@@ -79,8 +79,9 @@ const Agv: React.FC<ProcessContainerProps> = ({
 	return (
 		<>
 			{pathPoints.map((pair, i) => (
-				<group key={i} visible={!isPlaying}>
+				<group key={i}>
 					<PathNavigator
+						key={i}
 						navMesh={navMesh}
 						pathPoints={pair.points}
 						id={pair.modelUuid}
diff --git a/app/src/modules/builder/agv/pathNavigator.tsx b/app/src/modules/builder/agv/pathNavigator.tsx
index a81925f..a82b53c 100644
--- a/app/src/modules/builder/agv/pathNavigator.tsx
+++ b/app/src/modules/builder/agv/pathNavigator.tsx
@@ -185,7 +185,7 @@ export default function PathNavigator({
   function logAgvStatus(id: string, status: string) {
     // console.log(
     //   `AGV ${id}: ${status}`
-    
+
     // );
   }
 
@@ -456,7 +456,7 @@ export default function PathNavigator({
   }, []);
 
   return (
-    <group name="path-navigator-lines" visible={!isPlaying}>
+    <group name="path-navigator-lines">
       {toPickupPath.length > 0 && (
         <Line
           points={toPickupPath}
diff --git a/app/src/modules/simulation/armbot/IKAnimationController.tsx b/app/src/modules/simulation/armbot/IKAnimationController.tsx
index d0aaec1..dbb7386 100644
--- a/app/src/modules/simulation/armbot/IKAnimationController.tsx
+++ b/app/src/modules/simulation/armbot/IKAnimationController.tsx
@@ -3,6 +3,7 @@ import { useFrame } from "@react-three/fiber";
 import * as THREE from "three";
 import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
 import { useSimulationStates } from "../../../store/store";
+import MaterialInstances from "./MaterialInstances";
 
 
 interface StaticMachineState {
@@ -257,6 +258,10 @@ const IKAnimationController = ({
             });
     }, [process, groupRef, isPlaying]);
 
+    useEffect(() => {
+        console.log('processedCurves: ', processedCurves);
+    }, [processedCurves])
+
     const activeCurve = useMemo(() => {
         if (isPlaying && processedCurves)
             return processedCurves.find((c) => c?.trigger === selectedTrigger);
@@ -337,7 +342,19 @@ const IKAnimationController = ({
         ikSolver.update();
     });
 
-    return null;
+    return (
+        <>
+            {armBot.status === 'moving' && activeCurve &&
+                <MaterialInstances
+                    groupRef={groupRef}
+                    activeCurve={activeCurve}
+                    progress={progress}
+                    ikSolver={ikSolver}
+                    targetBoneName={targetBoneName}
+                />
+            }
+        </>
+    );
 };
 
 export default IKAnimationController;
\ No newline at end of file
diff --git a/app/src/modules/simulation/armbot/MaterialInstances.tsx b/app/src/modules/simulation/armbot/MaterialInstances.tsx
new file mode 100644
index 0000000..778ae30
--- /dev/null
+++ b/app/src/modules/simulation/armbot/MaterialInstances.tsx
@@ -0,0 +1,42 @@
+import React from 'react';
+import * as THREE from 'three';
+import { Box } from '@react-three/drei';
+
+type MaterialInstancesProps = {
+    groupRef: React.RefObject<THREE.Group>;
+    activeCurve: any;
+    progress: number;
+    ikSolver: any;
+    targetBoneName: string;
+};
+
+function MaterialInstances({
+    groupRef,
+    activeCurve,
+    progress,
+    ikSolver,
+    targetBoneName
+}: MaterialInstancesProps) {
+    const { endToRestRange, startToEndRange } = activeCurve;
+
+    // Show the box from when we reach the start point until we leave the end point
+    const shouldShow = (progress >= startToEndRange[0] && progress < startToEndRange[1] && progress >= endToRestRange[0]);
+
+    if (!shouldShow || !ikSolver) return null;
+
+    const targetBone = ikSolver.mesh.skeleton.bones.find(
+        (b: any) => b.name === targetBoneName
+    );
+    if (!targetBone) return null;
+
+    const worldPos = new THREE.Vector3();
+    targetBone.getWorldPosition(worldPos);
+
+    return (
+        <Box args={[0.5, 0.5, 0.5]} position={worldPos}>
+            <meshStandardMaterial color="orange" />
+        </Box>
+    );
+}
+
+export default MaterialInstances;
\ No newline at end of file
diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx
index f6cda0b..a32b34b 100644
--- a/app/src/modules/simulation/process/processAnimator.tsx
+++ b/app/src/modules/simulation/process/processAnimator.tsx
@@ -169,9 +169,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         const spawnPoint = findSpawnPoint(process);
         if (!spawnPoint || !spawnPoint.actions) {
-          console.log(
-            `Process ${process.id} has no valid spawn point or actions`
-          );
           return;
         }
 
@@ -255,10 +252,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // Check connection status with debugging
         const isConnected = isConnectedToActiveArmBot(process.id);
-        console.log(
-          `Process ${process.id} animation - connected:`,
-          isConnected
-        );
 
         if (isConnected) {
           // Stop all animations when connected to active arm bot
@@ -293,9 +286,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             currentTime - processState.processDelayStartTime >=
             effectiveDelayTime
           ) {
-            console.log(
-              `Process ${process.id} delay completed, resuming animation`
-            );
             newStates[process.id] = {
               ...processState,
               isProcessDelaying: false,
@@ -331,9 +321,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           [];
 
         if (path.length < 2) {
-          console.log(
-            `Process ${process.id} has insufficient path points: ${path.length}`
-          );
           return;
         }
 
@@ -348,9 +335,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             const currentRef = gltf?.scene ? obj.ref.current : obj.ref.current;
             if (!currentRef) {
-              console.log(
-                `No reference for object ${objectId}, skipping animation`
-              );
               return;
             }
 
@@ -378,9 +362,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                 stateRef.currentDelayDuration / speedRef.current;
 
               if (currentTime - stateRef.delayStartTime >= effectiveDelayTime) {
-                console.log(
-                  `Delay complete for object ${objectId}, resuming animation`
-                );
                 stateRef.isDelaying = false;
                 stateRef.delayComplete = true;
                 stateRef.isAnimating = true;
@@ -408,9 +389,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             // Skip non-animating objects
             if (!stateRef.isAnimating) {
-              console.log(
-                `Object ${objectId} not animating, skipping animation updates`
-              );
               return;
             }
 
@@ -454,9 +432,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
               if (shouldHide) {
                 if (isAgvPicking) {
-                  console.log(
-                    `AGV picking at last point for object ${objectId}, hiding object`
-                  );
                   updatedObjects[objectId] = {
                     ...obj,
                     visible: false,
@@ -517,14 +492,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
               if (stateRef.delayComplete && stateRef.progress < 0.01) {
                 stateRef.progress = 0.05;
                 stateRef.delayComplete = false;
-                console.log(
-                  `Boosting progress for object ${objectId} after delay`
-                );
               } else {
                 stateRef.progress += movement / distance;
-                console.log(
-                  `Object ${objectId} progress: ${stateRef.progress.toFixed(3)}`
-                );
               }
 
               // Handle point transition
@@ -564,9 +533,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // Log if no animation is occurring when it should
         if (!animationOccurring && !isConnected) {
-          console.log(
-            `Warning: No animation occurring for process ${process.id} despite not being connected`
-          );
+          // console.log(
+          //   `Warning: No animation occurring for process ${process.id} despite not being connected`
+          // );
         }
 
         newStates[process.id] = {
diff --git a/app/src/modules/simulation/process/useProcessAnimations.tsx b/app/src/modules/simulation/process/useProcessAnimations.tsx
index 9f08cf3..a46fe3c 100644
--- a/app/src/modules/simulation/process/useProcessAnimations.tsx
+++ b/app/src/modules/simulation/process/useProcessAnimations.tsx
@@ -510,6 +510,14 @@ export const useProcessAnimation = (
 
         if (activeVehicles.length === 0) {
           onHitTriggers.forEach((trigger: Trigger) => {
+            const triggerKey = `${point.uuid}-${trigger.uuid}`;
+
+            newTriggerCounts[triggerKey] = (newTriggerCounts[triggerKey] || 0) + 1;
+
+            shouldLog = true;
+
+            newTriggerLogs.push({ timestamp: currentTime, pointId: point.uuid, objectId, triggerId: trigger.uuid, });
+
             const connections = point.connections?.targets || [];
 
             connections.forEach((connection) => {
@@ -529,7 +537,7 @@ export const useProcessAnimation = (
 
         let processTotalHits = Object.values(newTriggerCounts).reduce((a, b) => a + b, 0);
 
-        // Handle logic for vehicles and ArmBots when a trigger is hit
+        // Handle logic for vehicles when a trigger is hit
         if (shouldLog) {
           vehiclePaths.forEach((vehiclePath) => {
             if (vehiclePath.points?.length > 0) {

From 8b7b7f589a0e06f6477cc11f28aba96605622c8f Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B <jerald@hexrfactory.com>
Date: Wed, 16 Apr 2025 15:04:52 +0530
Subject: [PATCH 13/20] feat: Integrate reset functionality in ArmBot and
 StaticMachine components

---
 app/src/modules/simulation/armbot/ArmBot.tsx  |   4 +-
 .../armbot/IKAnimationController.tsx          | 358 ++++++++----------
 .../modules/simulation/armbot/IkInstances.tsx |   2 +-
 .../staticMachine/staticMachine.tsx           |   4 +-
 4 files changed, 166 insertions(+), 202 deletions(-)

diff --git a/app/src/modules/simulation/armbot/ArmBot.tsx b/app/src/modules/simulation/armbot/ArmBot.tsx
index 1c7bb83..5d55791 100644
--- a/app/src/modules/simulation/armbot/ArmBot.tsx
+++ b/app/src/modules/simulation/armbot/ArmBot.tsx
@@ -4,6 +4,7 @@ import useModuleStore from "../../../store/useModuleStore";
 import { useSimulationStates } from "../../../store/store";
 import * as SimulationTypes from '../../../types/simulationTypes';
 import { ArmbotInstances } from "./ArmBotInstances";
+import { useResetButtonStore } from "../../../store/usePlayButtonStore";
 
 interface ArmBotState {
     uuid: string;
@@ -38,6 +39,7 @@ const ArmBot = ({ armBots, setArmBots, setStaticMachines }: ArmBotProps) => {
     const { activeModule } = useModuleStore();
     const { scene } = useThree();
     const { simulationStates } = useSimulationStates();
+    const { isReset } = useResetButtonStore();
 
     useEffect(() => {
         const filtered = simulationStates.filter((s): s is SimulationTypes.ArmBotEventsSchema => s.type === "ArmBot");
@@ -54,7 +56,7 @@ const ArmBot = ({ armBots, setArmBots, setStaticMachines }: ArmBotProps) => {
                 connections: bot.points.connections
             }));
         setArmBots(initialStates);
-    }, [simulationStates]);
+    }, [simulationStates, isReset]);
 
     useEffect(() => {
         armBots.forEach((bot) => {
diff --git a/app/src/modules/simulation/armbot/IKAnimationController.tsx b/app/src/modules/simulation/armbot/IKAnimationController.tsx
index dbb7386..efe88d4 100644
--- a/app/src/modules/simulation/armbot/IKAnimationController.tsx
+++ b/app/src/modules/simulation/armbot/IKAnimationController.tsx
@@ -31,7 +31,7 @@ interface ArmBotState {
 
 type IKAnimationControllerProps = {
     ikSolver: any;
-    process: {
+    processes: {
         triggerId: string;
         startPoint: THREE.Vector3;
         endPoint: THREE.Vector3;
@@ -50,7 +50,7 @@ type IKAnimationControllerProps = {
 
 const IKAnimationController = ({
     ikSolver,
-    process,
+    processes,
     selectedTrigger,
     targetBoneName,
     uuid,
@@ -67,20 +67,10 @@ const IKAnimationController = ({
     const [isInitializing, setIsInitializing] = useState(true);
     const restSpeed = 0.1;
     const restPosition = new THREE.Vector3(0, 2, 1.6);
-    const { isPlaying } = usePlayButtonStore();
+    const { isPlaying } = usePlayButtonStore();;
+    const statusRef = useRef("idle");
     const { simulationStates } = useSimulationStates();
 
-    // Track previous states for comparison
-    const prevStateRef = useRef({
-        isInitializing: true,
-        needsInitialMovement: true,
-        selectedTrigger: "",
-        progress: 0
-    });
-
-    // Track previous status for comparison
-    const prevStatusRef = useRef("");
-
     const initialCurveRef = useRef<THREE.CatmullRomCurve3 | null>(null);
     const initialStartPositionRef = useRef<THREE.Vector3 | null>(null);
 
@@ -101,91 +91,6 @@ const IKAnimationController = ({
         }
     }, [ikSolver]);
 
-    // Log state changes
-    useEffect(() => {
-        const prev = prevStateRef.current;
-
-        if (prev.isInitializing !== isInitializing) {
-            if (!isInitializing) {
-                logStatus(`[Arm ${uuid}] Completed initialization, now at rest position`);
-            }
-        }
-
-        if (prev.needsInitialMovement !== needsInitialMovement && !needsInitialMovement) {
-            logStatus(`[Arm ${uuid}] Reached rest position, ready for animation`);
-
-        }
-
-        if (prev.selectedTrigger !== selectedTrigger) {
-            logStatus(`[Arm ${uuid}] Processing new trigger: ${selectedTrigger}`);
-
-            const currentProcess = process.find(p => p.triggerId === prev.selectedTrigger);
-            if (currentProcess) {
-                const triggerId = currentProcess.triggerId;
-
-                const endPoint = armBot.actions.processes.find((process) => process.triggerId === triggerId)?.endPoint;
-
-                // Search simulationStates for a StaticMachine or Conveyor that has a point matching this endPointId
-                const matchedMachine = simulationStates.find((state) => {
-                    if (state.type === "Conveyor") {
-                        // For Conveyor, points is an array
-                        return (state).points.some(
-                            (point) => point.uuid === endPoint
-                        );
-                    } else if (state.type === "StaticMachine") {
-                        // For StaticMachine, points is an object
-                        return state.points.uuid === endPoint;
-                    }
-                    return false;
-                });
-
-                if (matchedMachine) {
-                    // Log if the end point is a conveyor
-                    if (matchedMachine.type === "Conveyor") {
-                        logStatus(`[Arm ${uuid}] Reached end point which is a conveyor (${matchedMachine.modelName})`);
-                    } else {
-                        logStatus(`[Arm ${uuid}] Reached end point which is a static machine (${matchedMachine.modelName})`);
-                    }
-
-                    if (matchedMachine.type === "StaticMachine") {
-                        setStaticMachines((machines) => {
-                            return machines.map((machine) => {
-                                if (machine.uuid === matchedMachine.modeluuid) {
-                                    return { ...machine, status: "running" };
-                                } else {
-                                    return machine;
-                                }
-                            });
-                        });
-                    }
-
-                    if (matchedMachine.type === "Conveyor") {
-                        setArmBots((prev) =>
-                            prev.map((arm) => {
-                                if (arm.uuid === uuid) {
-                                    return {
-                                        ...arm,
-                                        isActive: false
-                                    };
-                                }
-                                else {
-                                    return arm;
-                                }
-                            })
-                        );
-                    }
-                }
-            }
-        }
-
-        // Update previous state
-        prevStateRef.current = {
-            isInitializing,
-            needsInitialMovement,
-            selectedTrigger,
-            progress
-        };
-    }, [isInitializing, needsInitialMovement, selectedTrigger, progress]);
 
     const calculateInitialCurve = (startPosition: THREE.Vector3) => {
         const direction = new THREE.Vector3().subVectors(restPosition, startPosition);
@@ -211,61 +116,56 @@ const IKAnimationController = ({
         ]);
     };
 
-    const processedCurves = useMemo(() => {
-        if (isPlaying)
-            return process.map((p) => {
-                const tempLift = 0.5;
-                const localStart = groupRef.current?.worldToLocal(p.startPoint.clone().add(new THREE.Vector3(0, tempLift, 0)));
-                const localEnd = groupRef.current?.worldToLocal(p.endPoint.clone().add(new THREE.Vector3(0, tempLift, 0)));
+    const processCurves = useMemo(() => {
+        if (!isPlaying) return [];
 
-                if (localStart && localEnd) {
+        return processes.map(process => {
+            const localStart = groupRef.current?.worldToLocal(process.startPoint.clone());
+            const localEnd = groupRef.current?.worldToLocal(process.endPoint.clone());
 
-                    const mid = new THREE.Vector3(
-                        (localStart.x + localEnd.x) / 1,
-                        Math.max(localStart.y, localEnd.y) + 0.8,
-                        (localStart.z + localEnd.z) / 0.9
-                    );
+            if (!localStart || !localEnd) return null;
 
-                    const points = [
-                        restPosition.clone(),
-                        localStart.clone(),
-                        mid.clone(),
-                        localEnd.clone(),
-                        restPosition.clone(),
-                    ];
-                    const curve = new THREE.CatmullRomCurve3(points);
-                    const restToStartDist = points[0].distanceTo(points[1]);
-                    const startToEndDist = points[1].distanceTo(points[3]);
-                    const endToRestDist = points[3].distanceTo(points[4]);
+            const midPoint = new THREE.Vector3(
+                (localStart.x + localEnd.x) / 2,
+                Math.max(localStart.y, localEnd.y) + 1,
+                (localStart.z + localEnd.z) / 2
+            );
+            const restToStartCurve = new THREE.CatmullRomCurve3([
+                restPosition,
+                new THREE.Vector3().lerpVectors(restPosition, localStart, 0.5),
+                localStart
+            ]);
 
-                    const totalDist = restToStartDist + startToEndDist + endToRestDist;
-                    const restToStartRange = [0, restToStartDist / totalDist];
-                    const startToEndRange = [
-                        restToStartRange[1],
-                        restToStartRange[1] + startToEndDist / totalDist,
-                    ];
-                    const endToRestRange = [startToEndRange[1], 1];
+            const processCurve = new THREE.CatmullRomCurve3([
+                localStart,
+                midPoint,
+                localEnd
+            ]);
 
-                    return {
-                        trigger: p.triggerId,
-                        curve,
-                        speed: p.speed,
-                        restToStartRange,
-                        startToEndRange,
-                        endToRestRange,
-                    };
-                }
-            });
-    }, [process, groupRef, isPlaying]);
+            const endToRestCurve = new THREE.CatmullRomCurve3([
+                localEnd,
+                new THREE.Vector3().lerpVectors(localEnd, restPosition, 0.5),
+                restPosition
+            ]);
 
-    useEffect(() => {
-        console.log('processedCurves: ', processedCurves);
-    }, [processedCurves])
+            return {
+                triggerId: process.triggerId,
+                restToStartCurve,
+                processCurve,
+                endToRestCurve,
+                speed: process.speed,
+                totalDistance:
+                    restPosition.distanceTo(localStart) +
+                    localStart.distanceTo(localEnd) +
+                    localEnd.distanceTo(restPosition)
+            };
+        }).filter(Boolean);
+    }, [processes, isPlaying]);
 
-    const activeCurve = useMemo(() => {
-        if (isPlaying && processedCurves)
-            return processedCurves.find((c) => c?.trigger === selectedTrigger);
-    }, [processedCurves, selectedTrigger, isPlaying]);
+    const activeProcess = useMemo(() => {
+        if (!selectedTrigger) return null;
+        return processCurves.find(p => p?.triggerId === selectedTrigger);
+    }, [processCurves, selectedTrigger]);
 
     // Initial movement to rest position
     useFrame((_, delta) => {
@@ -293,68 +193,128 @@ const IKAnimationController = ({
 
     // Main animation loop
     useFrame((_, delta) => {
-        if (!ikSolver || !activeCurve || isInitializing || !isPlaying) return;
+        if (isInitializing || !isPlaying || !selectedTrigger || !activeProcess || !ikSolver) return;
 
-        const { curve, speed, restToStartRange, startToEndRange, endToRestRange } = activeCurve;
-        const targetBone = ikSolver.mesh.skeleton.bones.find(
-            (b: any) => b.name === targetBoneName
-        );
-        if (!targetBone) return;
+        const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBoneName);
+        if (!bone) return;
 
-        let currentSpeed = restSpeed;
-        let currentStatus = "idle"; // Default status
+        const {
+            restToStartCurve,
+            processCurve,
+            endToRestCurve,
+            speed,
+            totalDistance
+        } = activeProcess;
 
-        // Determine current phase and status
-        if (progress < restToStartRange[1]) {
-            currentSpeed = restSpeed;
-            currentStatus = "moving"; // Moving to start point
-        } else if (progress >= startToEndRange[0] && progress < startToEndRange[1]) {
-            currentSpeed = speed;
-            currentStatus = "moving"; // Moving between points
-        } else if (progress >= endToRestRange[0] && progress < 1) {
-            currentSpeed = restSpeed;
-            currentStatus = "moving"; // Returning to rest
-        } else if (progress >= 1) {
-            currentStatus = "idle"; // Completed cycle
-        }
+        // Calculate current segment and progress
+        const restToStartDist = restPosition.distanceTo(restToStartCurve.points[2]);
+        const processDist = processCurve.getLength();
+        const endToRestDist = endToRestCurve.getLength();
 
-        // Update status when it changes
-        if (prevStatusRef.current !== currentStatus) {
-            updateArmBotStatus(currentStatus);
-            prevStatusRef.current = currentStatus;
-        }
+        const restToStartEnd = restToStartDist / totalDistance;
+        const processEnd = (restToStartDist + processDist) / totalDistance;
 
-        // Only update progress if we're not already at the end
-        if (progress < 1) {
-            setProgress((prev) => {
-                const next = prev + delta * currentSpeed;
-                return Math.min(next, 1); // Cap at 1
-            });
-        }
+        setProgress(prev => {
+            let currentStatus = statusRef.current;
+            let currentPosition: THREE.Vector3;
+            const newProgress = Math.min(prev + delta * ((currentStatus === 'returning to rest') ? restSpeed : speed), 1);
 
-        // Update bone position based on progress
-        if (progress < 1) {
-            targetBone.position.copy(curve.getPoint(progress));
-        } else {
-            targetBone.position.copy(curve.getPoint(1));
-        }
+            if (newProgress < restToStartEnd) {
+                // Moving from rest to start position
+                currentStatus = "moving to start";
+                const segmentProgress = newProgress / restToStartEnd;
+                currentPosition = restToStartCurve.getPoint(segmentProgress);
+            } else if (newProgress < processEnd) {
+                // Processing - moving from start to end
+                currentStatus = "processing";
+                const segmentProgress = (newProgress - restToStartEnd) / (processEnd - restToStartEnd);
+                currentPosition = processCurve.getPoint(segmentProgress);
+            } else {
+                // Returning to rest position
+                currentStatus = "returning to rest";
+                const segmentProgress = (newProgress - processEnd) / (1 - processEnd);
+                currentPosition = endToRestCurve.getPoint(segmentProgress);
+            }
 
-        ikSolver.update();
+            // Update status if changed
+            if (currentStatus !== statusRef.current) {
+                statusRef.current = currentStatus;
+                // updateArmBotStatus(currentStatus);
+                logStatus(`[Arm ${uuid}] Status: ${currentStatus}`);
+            }
+
+            // Only trigger when the entire animation is complete (newProgress === 1)
+            if (newProgress === 1 && currentStatus === "returning to rest") {
+                updateConveyorOrStaticMachineStatus(selectedTrigger);
+            }
+
+            bone.position.copy(currentPosition);
+            ikSolver.update();
+            return newProgress;
+        });
     });
 
-    return (
-        <>
-            {armBot.status === 'moving' && activeCurve &&
-                <MaterialInstances
-                    groupRef={groupRef}
-                    activeCurve={activeCurve}
-                    progress={progress}
-                    ikSolver={ikSolver}
-                    targetBoneName={targetBoneName}
-                />
+    const updateConveyorOrStaticMachineStatus = (selectedTrigger: string) => {
+        const currentProcess = processes.find(p => p.triggerId === selectedTrigger);
+        if (currentProcess) {
+            const triggerId = currentProcess.triggerId;
+
+            const endPoint = armBot.actions.processes.find((process) => process.triggerId === triggerId)?.endPoint;
+
+            const matchedMachine = simulationStates.find((state) => {
+                if (state.type === "Conveyor") {
+                    return (state).points.some(
+                        (point) => point.uuid === endPoint
+                    );
+                } else if (state.type === "StaticMachine") {
+                    return state.points.uuid === endPoint;
+                }
+                return false;
+            });
+
+            if (matchedMachine) {
+                if (matchedMachine.type === "Conveyor") {
+                    logStatus(`[Arm ${uuid}] Reached end point which is a conveyor (${matchedMachine.modelName})`);
+                } else {
+                    logStatus(`[Arm ${uuid}] Reached end point which is a static machine (${matchedMachine.modelName})`);
+                }
+
+                setTimeout(() => {
+                    if (matchedMachine.type === "StaticMachine") {
+                        setStaticMachines((machines) => {
+                            return machines.map((machine) => {
+                                if (machine.uuid === matchedMachine.modeluuid) {
+                                    return { ...machine, status: "running" };
+                                } else {
+                                    return machine;
+                                }
+                            });
+                        });
+                        updateArmBotStatus('idle');
+                    }
+
+                    if (matchedMachine.type === "Conveyor") {
+                        setArmBots((prev) =>
+                            prev.map((arm) => {
+                                if (arm.uuid === uuid) {
+                                    return {
+                                        ...arm,
+                                        isActive: false,
+                                        status: "idle",
+                                    };
+                                }
+                                else {
+                                    return arm;
+                                }
+                            })
+                        );
+                    }
+                }, 0);
             }
-        </>
-    );
+        }
+    }
+
+    return null;
 };
 
 export default IKAnimationController;
\ No newline at end of file
diff --git a/app/src/modules/simulation/armbot/IkInstances.tsx b/app/src/modules/simulation/armbot/IkInstances.tsx
index 5a0d23b..6e7dc13 100644
--- a/app/src/modules/simulation/armbot/IkInstances.tsx
+++ b/app/src/modules/simulation/armbot/IkInstances.tsx
@@ -132,7 +132,7 @@ const IkInstances = ({
             </group>
             <IKAnimationController
                 ikSolver={ikSolver}
-                process={processes}
+                processes={processes}
                 selectedTrigger={selectedTrigger}
                 targetBoneName={targetBoneName}
                 uuid={uuid}
diff --git a/app/src/modules/simulation/staticMachine/staticMachine.tsx b/app/src/modules/simulation/staticMachine/staticMachine.tsx
index 26760eb..3f61993 100644
--- a/app/src/modules/simulation/staticMachine/staticMachine.tsx
+++ b/app/src/modules/simulation/staticMachine/staticMachine.tsx
@@ -2,6 +2,7 @@ import React, { useEffect } from 'react'
 import * as SimulationTypes from '../../../types/simulationTypes';
 import { useSimulationStates } from '../../../store/store';
 import StaticMachineInstances from './staticMachineInstances';
+import { useResetButtonStore } from '../../../store/usePlayButtonStore';
 
 interface ArmBotState {
     uuid: string;
@@ -34,6 +35,7 @@ type StaticMachineProps = {
 function StaticMachine({ setArmBots, staticMachines, setStaticMachines }: StaticMachineProps) {
 
     const { simulationStates } = useSimulationStates();
+    const { isReset } = useResetButtonStore();
 
     useEffect(() => {
         const filtered = simulationStates.filter((s): s is SimulationTypes.StaticMachineEventsSchema => s.type === "StaticMachine");
@@ -47,7 +49,7 @@ function StaticMachine({ setArmBots, staticMachines, setStaticMachines }: Static
                 connectedArmBot: machine.points.connections.targets[0].modelUUID
             }));
         setStaticMachines(initialStates);
-    }, [simulationStates]);
+    }, [simulationStates, isReset]);
 
     const updateArmBotTriggerAndMachineStatus = (armBotUuid: string, triggerId: string, machineId: string) => {
         setArmBots((prevArmBots) => {

From 0eedbdd58e27557a2b681f3ca3056bad9af1fa04 Mon Sep 17 00:00:00 2001
From: SreeNath14 <153710861+SreeNath14@users.noreply.github.com>
Date: Wed, 16 Apr 2025 15:07:11 +0530
Subject: [PATCH 14/20] "multiple spawn bug fixed"

---
 .../simulation/process/processAnimator.tsx    | 59 ++++++++++++++-----
 1 file changed, 45 insertions(+), 14 deletions(-)

diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx
index a32b34b..981846b 100644
--- a/app/src/modules/simulation/process/processAnimator.tsx
+++ b/app/src/modules/simulation/process/processAnimator.tsx
@@ -1,4 +1,10 @@
-import React, { useRef, useEffect, useMemo, useCallback } from "react";
+import React, {
+  useRef,
+  useEffect,
+  useMemo,
+  useCallback,
+  useState,
+} from "react";
 import { useLoader, useFrame } from "@react-three/fiber";
 import { GLTFLoader } from "three-stdlib";
 import * as THREE from "three";
@@ -48,6 +54,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
   const gltf = useLoader(GLTFLoader, crate) as GLTF;
   const groupRef = useRef<THREE.Group>(null);
   const tempStackedObjectsRef = useRef<Record<string, boolean>>({});
+  const [previouslyConnected, setPreviouslyConnected] = useState<any>({});
+  const currentSpawnedObjectRef = useRef<any>(null);
 
   const {
     animationStates,
@@ -116,8 +124,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
     });
   }, [animationStates, MaterialRef, agvRef]);
 
-  // In processAnimator.tsx - only the relevant spawn logic part that needs fixes
-
   // Add this function to ProcessAnimator component
   const isConnectedToActiveArmBot = useCallback(
     (processId: any) => {
@@ -153,6 +159,26 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // Check connection status
         const isConnected = isConnectedToActiveArmBot(process.id);
+        const wasConnected = previouslyConnected[process.id] || false;
+
+        // Track connection state changes
+        if (wasConnected !== isConnected) {
+          setTimeout(() => {
+            setPreviouslyConnected((prev: any) => ({
+              ...prev,
+              [process.id]: isConnected,
+            }));
+          }, 0);
+        }
+
+        // If just disconnected, reset the spawn timer to allow new spawns
+        if (wasConnected && !isConnected) {
+          newStates[process.id] = {
+            ...processState,
+            nextSpawnTime: currentTime + 0.1,
+            hasSpawnedZeroIntervalObject: false,
+          };
+        }
 
         if (processState.isProcessDelaying) {
           // Existing delay handling logic...
@@ -192,7 +218,10 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           return; // Don't spawn more objects for zero interval
         }
 
-        const effectiveSpawnInterval = spawnInterval / speedRef.current;
+        const effectiveSpawnInterval = Math.max(
+          0.1,
+          spawnInterval / speedRef.current
+        );
 
         if (currentTime >= processState.nextSpawnTime) {
           const objectId = `obj-${process.id}-${processState.objectIdCounter}`;
@@ -213,6 +242,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             progress: 0.005, // Start with tiny progress to ensure animation begins
           };
 
+          // Calculate next spawn time
+          const nextSpawnAt = currentTime + effectiveSpawnInterval;
+
           // Update state with the new object and flag for zero interval
           newStates[process.id] = {
             ...processState,
@@ -221,7 +253,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
               [objectId]: newObject,
             },
             objectIdCounter: processState.objectIdCounter + 1,
-            nextSpawnTime: currentTime + effectiveSpawnInterval,
+            nextSpawnTime: nextSpawnAt,
             // Mark that we've spawned an object for zero interval case
             hasSpawnedZeroIntervalObject:
               spawnInterval === 0
@@ -237,6 +269,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
   // Second useFrame for animation logic
   useFrame((_, delta) => {
+    let currentProcessObject: any = null;
+
     // Animation logic frame
     const currentTime =
       clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
@@ -250,7 +284,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           return;
         }
 
-        // Check connection status with debugging
+        // Check connection status
         const isConnected = isConnectedToActiveArmBot(process.id);
 
         if (isConnected) {
@@ -263,6 +297,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                 [id]: {
                   ...obj,
                   state: {
+                    visible: true,
                     ...obj.state,
                     isAnimating: false, // Stop animation
                     isDelaying: false, // Clear delays
@@ -511,12 +546,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                   currentTime
                 );
 
-                const newPointData = getPointDataForAnimationIndex(
-                  process,
-                  stateRef.currentIndex
-                );
-
                 // No action needed with newPointData here - will be handled in next frame
+                getPointDataForAnimationIndex(process, stateRef.currentIndex);
               } else {
                 // Update position with lerp
                 currentRef.position.lerpVectors(
@@ -533,9 +564,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // Log if no animation is occurring when it should
         if (!animationOccurring && !isConnected) {
-          // console.log(
-          //   `Warning: No animation occurring for process ${process.id} despite not being connected`
-          // );
+          console.log(
+            `Warning: No animation occurring for process ${process.id} despite not being connected`
+          );
         }
 
         newStates[process.id] = {

From 496c8b0305fa7345aae514fd06d1d5f4d23ec5f7 Mon Sep 17 00:00:00 2001
From: SreeNath14 <153710861+SreeNath14@users.noreply.github.com>
Date: Wed, 16 Apr 2025 16:08:47 +0530
Subject: [PATCH 15/20] new comit

---
 .../simulation/process/processAnimator.tsx    | 25 ++++++++++++-------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx
index 981846b..408cd37 100644
--- a/app/src/modules/simulation/process/processAnimator.tsx
+++ b/app/src/modules/simulation/process/processAnimator.tsx
@@ -55,7 +55,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
   const groupRef = useRef<THREE.Group>(null);
   const tempStackedObjectsRef = useRef<Record<string, boolean>>({});
   const [previouslyConnected, setPreviouslyConnected] = useState<any>({});
-  const currentSpawnedObjectRef = useRef<any>(null);
 
   const {
     animationStates,
@@ -124,6 +123,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
     });
   }, [animationStates, MaterialRef, agvRef]);
 
+  // In processAnimator.tsx - only the relevant spawn logic part that needs fixes
+
   // Add this function to ProcessAnimator component
   const isConnectedToActiveArmBot = useCallback(
     (processId: any) => {
@@ -163,6 +164,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // Track connection state changes
         if (wasConnected !== isConnected) {
+    
+          // Update connection tracking (in a separate useEffect to avoid issues with setState in render)
           setTimeout(() => {
             setPreviouslyConnected((prev: any) => ({
               ...prev,
@@ -173,10 +176,11 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // If just disconnected, reset the spawn timer to allow new spawns
         if (wasConnected && !isConnected) {
+   
           newStates[process.id] = {
             ...processState,
-            nextSpawnTime: currentTime + 0.1,
-            hasSpawnedZeroIntervalObject: false,
+            nextSpawnTime: currentTime + 0.1, // Start spawning soon after disconnect
+            hasSpawnedZeroIntervalObject: false, // Reset for zero interval spawns
           };
         }
 
@@ -195,6 +199,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         const spawnPoint = findSpawnPoint(process);
         if (!spawnPoint || !spawnPoint.actions) {
+   
           return;
         }
 
@@ -210,6 +215,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             ? spawnAction.spawnInterval
             : parseFloat(spawnAction.spawnInterval || "0") || 0;
 
+ 
+
         // Check if this is a zero interval spawn and we already spawned an object
         if (
           spawnInterval === 0 &&
@@ -224,6 +231,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
         );
 
         if (currentTime >= processState.nextSpawnTime) {
+   
           const objectId = `obj-${process.id}-${processState.objectIdCounter}`;
           const newObject = createSpawnedObject(
             process,
@@ -269,8 +277,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
   // Second useFrame for animation logic
   useFrame((_, delta) => {
-    let currentProcessObject: any = null;
-
     // Animation logic frame
     const currentTime =
       clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
@@ -297,7 +303,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                 [id]: {
                   ...obj,
                   state: {
-                    visible: true,
                     ...obj.state,
                     isAnimating: false, // Stop animation
                     isDelaying: false, // Clear delays
@@ -321,6 +326,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             currentTime - processState.processDelayStartTime >=
             effectiveDelayTime
           ) {
+     
             newStates[process.id] = {
               ...processState,
               isProcessDelaying: false,
@@ -356,6 +362,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           [];
 
         if (path.length < 2) {
+  
           return;
         }
 
@@ -370,6 +377,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             const currentRef = gltf?.scene ? obj.ref.current : obj.ref.current;
             if (!currentRef) {
+      
               return;
             }
 
@@ -397,6 +405,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                 stateRef.currentDelayDuration / speedRef.current;
 
               if (currentTime - stateRef.delayStartTime >= effectiveDelayTime) {
+         
                 stateRef.isDelaying = false;
                 stateRef.delayComplete = true;
                 stateRef.isAnimating = true;
@@ -564,9 +573,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // Log if no animation is occurring when it should
         if (!animationOccurring && !isConnected) {
-          console.log(
-            `Warning: No animation occurring for process ${process.id} despite not being connected`
-          );
+      
         }
 
         newStates[process.id] = {

From 9b9164c6005faf28f62cb8bacf89ff296f951304 Mon Sep 17 00:00:00 2001
From: SreeNath14 <153710861+SreeNath14@users.noreply.github.com>
Date: Wed, 16 Apr 2025 16:25:02 +0530
Subject: [PATCH 16/20] minor changes in conveyor box spawn

---
 .../simulation/process/processAnimator.tsx    | 93 +++++++++----------
 1 file changed, 43 insertions(+), 50 deletions(-)

diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx
index 408cd37..f6cda0b 100644
--- a/app/src/modules/simulation/process/processAnimator.tsx
+++ b/app/src/modules/simulation/process/processAnimator.tsx
@@ -1,10 +1,4 @@
-import React, {
-  useRef,
-  useEffect,
-  useMemo,
-  useCallback,
-  useState,
-} from "react";
+import React, { useRef, useEffect, useMemo, useCallback } from "react";
 import { useLoader, useFrame } from "@react-three/fiber";
 import { GLTFLoader } from "three-stdlib";
 import * as THREE from "three";
@@ -54,7 +48,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
   const gltf = useLoader(GLTFLoader, crate) as GLTF;
   const groupRef = useRef<THREE.Group>(null);
   const tempStackedObjectsRef = useRef<Record<string, boolean>>({});
-  const [previouslyConnected, setPreviouslyConnected] = useState<any>({});
 
   const {
     animationStates,
@@ -160,29 +153,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // Check connection status
         const isConnected = isConnectedToActiveArmBot(process.id);
-        const wasConnected = previouslyConnected[process.id] || false;
-
-        // Track connection state changes
-        if (wasConnected !== isConnected) {
-    
-          // Update connection tracking (in a separate useEffect to avoid issues with setState in render)
-          setTimeout(() => {
-            setPreviouslyConnected((prev: any) => ({
-              ...prev,
-              [process.id]: isConnected,
-            }));
-          }, 0);
-        }
-
-        // If just disconnected, reset the spawn timer to allow new spawns
-        if (wasConnected && !isConnected) {
-   
-          newStates[process.id] = {
-            ...processState,
-            nextSpawnTime: currentTime + 0.1, // Start spawning soon after disconnect
-            hasSpawnedZeroIntervalObject: false, // Reset for zero interval spawns
-          };
-        }
 
         if (processState.isProcessDelaying) {
           // Existing delay handling logic...
@@ -199,7 +169,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         const spawnPoint = findSpawnPoint(process);
         if (!spawnPoint || !spawnPoint.actions) {
-   
+          console.log(
+            `Process ${process.id} has no valid spawn point or actions`
+          );
           return;
         }
 
@@ -215,8 +187,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             ? spawnAction.spawnInterval
             : parseFloat(spawnAction.spawnInterval || "0") || 0;
 
- 
-
         // Check if this is a zero interval spawn and we already spawned an object
         if (
           spawnInterval === 0 &&
@@ -225,13 +195,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           return; // Don't spawn more objects for zero interval
         }
 
-        const effectiveSpawnInterval = Math.max(
-          0.1,
-          spawnInterval / speedRef.current
-        );
+        const effectiveSpawnInterval = spawnInterval / speedRef.current;
 
         if (currentTime >= processState.nextSpawnTime) {
-   
           const objectId = `obj-${process.id}-${processState.objectIdCounter}`;
           const newObject = createSpawnedObject(
             process,
@@ -250,9 +216,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             progress: 0.005, // Start with tiny progress to ensure animation begins
           };
 
-          // Calculate next spawn time
-          const nextSpawnAt = currentTime + effectiveSpawnInterval;
-
           // Update state with the new object and flag for zero interval
           newStates[process.id] = {
             ...processState,
@@ -261,7 +224,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
               [objectId]: newObject,
             },
             objectIdCounter: processState.objectIdCounter + 1,
-            nextSpawnTime: nextSpawnAt,
+            nextSpawnTime: currentTime + effectiveSpawnInterval,
             // Mark that we've spawned an object for zero interval case
             hasSpawnedZeroIntervalObject:
               spawnInterval === 0
@@ -290,8 +253,12 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           return;
         }
 
-        // Check connection status
+        // Check connection status with debugging
         const isConnected = isConnectedToActiveArmBot(process.id);
+        console.log(
+          `Process ${process.id} animation - connected:`,
+          isConnected
+        );
 
         if (isConnected) {
           // Stop all animations when connected to active arm bot
@@ -326,7 +293,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             currentTime - processState.processDelayStartTime >=
             effectiveDelayTime
           ) {
-     
+            console.log(
+              `Process ${process.id} delay completed, resuming animation`
+            );
             newStates[process.id] = {
               ...processState,
               isProcessDelaying: false,
@@ -362,7 +331,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           [];
 
         if (path.length < 2) {
-  
+          console.log(
+            `Process ${process.id} has insufficient path points: ${path.length}`
+          );
           return;
         }
 
@@ -377,7 +348,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             const currentRef = gltf?.scene ? obj.ref.current : obj.ref.current;
             if (!currentRef) {
-      
+              console.log(
+                `No reference for object ${objectId}, skipping animation`
+              );
               return;
             }
 
@@ -405,7 +378,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                 stateRef.currentDelayDuration / speedRef.current;
 
               if (currentTime - stateRef.delayStartTime >= effectiveDelayTime) {
-         
+                console.log(
+                  `Delay complete for object ${objectId}, resuming animation`
+                );
                 stateRef.isDelaying = false;
                 stateRef.delayComplete = true;
                 stateRef.isAnimating = true;
@@ -433,6 +408,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             // Skip non-animating objects
             if (!stateRef.isAnimating) {
+              console.log(
+                `Object ${objectId} not animating, skipping animation updates`
+              );
               return;
             }
 
@@ -476,6 +454,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
               if (shouldHide) {
                 if (isAgvPicking) {
+                  console.log(
+                    `AGV picking at last point for object ${objectId}, hiding object`
+                  );
                   updatedObjects[objectId] = {
                     ...obj,
                     visible: false,
@@ -536,8 +517,14 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
               if (stateRef.delayComplete && stateRef.progress < 0.01) {
                 stateRef.progress = 0.05;
                 stateRef.delayComplete = false;
+                console.log(
+                  `Boosting progress for object ${objectId} after delay`
+                );
               } else {
                 stateRef.progress += movement / distance;
+                console.log(
+                  `Object ${objectId} progress: ${stateRef.progress.toFixed(3)}`
+                );
               }
 
               // Handle point transition
@@ -555,8 +542,12 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                   currentTime
                 );
 
+                const newPointData = getPointDataForAnimationIndex(
+                  process,
+                  stateRef.currentIndex
+                );
+
                 // No action needed with newPointData here - will be handled in next frame
-                getPointDataForAnimationIndex(process, stateRef.currentIndex);
               } else {
                 // Update position with lerp
                 currentRef.position.lerpVectors(
@@ -573,7 +564,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // Log if no animation is occurring when it should
         if (!animationOccurring && !isConnected) {
-      
+          console.log(
+            `Warning: No animation occurring for process ${process.id} despite not being connected`
+          );
         }
 
         newStates[process.id] = {

From ee319c28e440ccc8c10df9596e57eb9874d203f9 Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B <jerald@hexrfactory.com>
Date: Wed, 16 Apr 2025 16:33:48 +0530
Subject: [PATCH 17/20] refactor: Remove unnecessary console logs and improve
 connection limit checks in simulation components

---
 .../mechanics/ArmBotMechanics.tsx             |   1 -
 .../simulation/armbot/ArmBotInstances.tsx     |   1 -
 .../armbot/IKAnimationController.tsx          |  63 ++++++-
 .../simulation/armbot/MaterialInstances.tsx   |  21 +--
 .../modules/simulation/path/pathConnector.tsx | 166 ++++++++++++++++--
 .../simulation/process/processAnimator.tsx    |   6 +-
 6 files changed, 219 insertions(+), 39 deletions(-)

diff --git a/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx
index d3e5301..70e297b 100644
--- a/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx
+++ b/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx
@@ -150,7 +150,6 @@ const ArmBotMechanics: React.FC = () => {
             modeluuid: updatedPath.modeluuid,
             eventData: { type: "ArmBot", points: updatedPath.points }
         }
-        console.log('data: ', data);
 
         socket.emit('v2:model-asset:updateEventData', data);
     }
diff --git a/app/src/modules/simulation/armbot/ArmBotInstances.tsx b/app/src/modules/simulation/armbot/ArmBotInstances.tsx
index 8d20a87..a0657db 100644
--- a/app/src/modules/simulation/armbot/ArmBotInstances.tsx
+++ b/app/src/modules/simulation/armbot/ArmBotInstances.tsx
@@ -46,7 +46,6 @@ export const ArmbotInstances: React.FC<ArmbotInstancesProps> = ({ index, armBot,
     const [processes, setProcesses] = useState<Process[]>([]);
 
     useEffect(() => {
-
         if (armBot.actions.processes.length > 0) {
             const mappedProcesses = armBot.actions.processes.map((process) => {
                 return {
diff --git a/app/src/modules/simulation/armbot/IKAnimationController.tsx b/app/src/modules/simulation/armbot/IKAnimationController.tsx
index efe88d4..6b77bac 100644
--- a/app/src/modules/simulation/armbot/IKAnimationController.tsx
+++ b/app/src/modules/simulation/armbot/IKAnimationController.tsx
@@ -1,7 +1,7 @@
 import { useEffect, useMemo, useState, useRef } from "react";
 import { useFrame } from "@react-three/fiber";
 import * as THREE from "three";
-import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
+import { usePlayButtonStore, useResetButtonStore } from "../../../store/usePlayButtonStore";
 import { useSimulationStates } from "../../../store/store";
 import MaterialInstances from "./MaterialInstances";
 
@@ -70,6 +70,7 @@ const IKAnimationController = ({
     const { isPlaying } = usePlayButtonStore();;
     const statusRef = useRef("idle");
     const { simulationStates } = useSimulationStates();
+    const { isReset } = useResetButtonStore();
 
     const initialCurveRef = useRef<THREE.CatmullRomCurve3 | null>(null);
     const initialStartPositionRef = useRef<THREE.Vector3 | null>(null);
@@ -78,6 +79,13 @@ const IKAnimationController = ({
         setProgress(0);
     }, [selectedTrigger]);
 
+    useEffect(() => {
+        setProgress(0);
+        setNeedsInitialMovement(true);
+        setInitialProgress(0);
+        setIsInitializing(true);
+    }, [isReset]);
+
     useEffect(() => {
         if (ikSolver) {
             const targetBone = ikSolver.mesh.skeleton.bones.find(
@@ -229,6 +237,9 @@ const IKAnimationController = ({
                 currentStatus = "processing";
                 const segmentProgress = (newProgress - restToStartEnd) / (processEnd - restToStartEnd);
                 currentPosition = processCurve.getPoint(segmentProgress);
+                if (statusRef.current !== "processing") {
+                    updateConveyorOrStaticMachineStatusOnStart(selectedTrigger);
+                }
             } else {
                 // Returning to rest position
                 currentStatus = "returning to rest";
@@ -245,7 +256,7 @@ const IKAnimationController = ({
 
             // Only trigger when the entire animation is complete (newProgress === 1)
             if (newProgress === 1 && currentStatus === "returning to rest") {
-                updateConveyorOrStaticMachineStatus(selectedTrigger);
+                updateConveyorOrStaticMachineStatusOnEnd(selectedTrigger);
             }
 
             bone.position.copy(currentPosition);
@@ -254,7 +265,45 @@ const IKAnimationController = ({
         });
     });
 
-    const updateConveyorOrStaticMachineStatus = (selectedTrigger: string) => {
+    const updateConveyorOrStaticMachineStatusOnStart = (selectedTrigger: string) => {
+        const currentProcess = processes.find(p => p.triggerId === selectedTrigger);
+        if (currentProcess) {
+            const triggerId = currentProcess.triggerId;
+
+            const startPoint = armBot.actions.processes.find((process) => process.triggerId === triggerId)?.startPoint;
+
+            const matchedMachine = simulationStates.find((state) => {
+                if (state.type === "Conveyor") {
+                    return (state).points.some(
+                        (point) => point.uuid === startPoint
+                    );
+                } else if (state.type === "StaticMachine") {
+                    return state.points.uuid === startPoint;
+                }
+                return false;
+            });
+
+            if (matchedMachine) {
+                if (matchedMachine.type === "Conveyor") {
+                    logStatus(`[Arm ${uuid}] start point which is a conveyor (${matchedMachine.modelName})`);
+                } else {
+                    logStatus(`[Arm ${uuid}] started form start point which is a static machine (${matchedMachine.modelName})`);
+                }
+
+                setTimeout(() => {
+                    if (matchedMachine.type === "StaticMachine") {
+                        updateArmBotStatus('dropping');
+                    }
+
+                    if (matchedMachine.type === "Conveyor") {
+                        updateArmBotStatus('picking');
+                    }
+                }, 0);
+            }
+        }
+    }
+
+    const updateConveyorOrStaticMachineStatusOnEnd = (selectedTrigger: string) => {
         const currentProcess = processes.find(p => p.triggerId === selectedTrigger);
         if (currentProcess) {
             const triggerId = currentProcess.triggerId;
@@ -314,7 +363,13 @@ const IKAnimationController = ({
         }
     }
 
-    return null;
+    return (
+        <MaterialInstances
+            statusRef={statusRef}
+            ikSolver={ikSolver}
+            targetBoneName={targetBoneName}
+        />
+    );
 };
 
 export default IKAnimationController;
\ No newline at end of file
diff --git a/app/src/modules/simulation/armbot/MaterialInstances.tsx b/app/src/modules/simulation/armbot/MaterialInstances.tsx
index 778ae30..c83cd51 100644
--- a/app/src/modules/simulation/armbot/MaterialInstances.tsx
+++ b/app/src/modules/simulation/armbot/MaterialInstances.tsx
@@ -3,37 +3,26 @@ import * as THREE from 'three';
 import { Box } from '@react-three/drei';
 
 type MaterialInstancesProps = {
-    groupRef: React.RefObject<THREE.Group>;
-    activeCurve: any;
-    progress: number;
+    statusRef: React.RefObject<string>;
     ikSolver: any;
     targetBoneName: string;
 };
 
 function MaterialInstances({
-    groupRef,
-    activeCurve,
-    progress,
+    statusRef,
     ikSolver,
     targetBoneName
 }: MaterialInstancesProps) {
-    const { endToRestRange, startToEndRange } = activeCurve;
+    if (!ikSolver) return null;
 
-    // Show the box from when we reach the start point until we leave the end point
-    const shouldShow = (progress >= startToEndRange[0] && progress < startToEndRange[1] && progress >= endToRestRange[0]);
-
-    if (!shouldShow || !ikSolver) return null;
-
-    const targetBone = ikSolver.mesh.skeleton.bones.find(
-        (b: any) => b.name === targetBoneName
-    );
+    const targetBone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBoneName);
     if (!targetBone) return null;
 
     const worldPos = new THREE.Vector3();
     targetBone.getWorldPosition(worldPos);
 
     return (
-        <Box args={[0.5, 0.5, 0.5]} position={worldPos}>
+        <Box args={[0.5, 0.5, 0.5]} position={worldPos} visible={statusRef.current === 'processing'}>
             <meshStandardMaterial color="orange" />
         </Box>
     );
diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx
index 3e35925..3db399e 100644
--- a/app/src/modules/simulation/path/pathConnector.tsx
+++ b/app/src/modules/simulation/path/pathConnector.tsx
@@ -40,6 +40,37 @@ function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObje
                                 };
                                 const existingTargets = point.connections.targets || [];
 
+                                // Check connection limits
+                                const toPath = simulationStates.find(p => p.modeluuid === toModelUUID);
+                                if (toPath) {
+                                    // Check if we already have this type of connection
+                                    const hasConveyor = existingTargets.some(t => {
+                                        const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
+                                        return targetPath?.type === "Conveyor";
+                                    });
+                                    const hasArmBot = existingTargets.some(t => {
+                                        const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
+                                        return targetPath?.type === "ArmBot";
+                                    });
+                                    const hasVehicle = existingTargets.some(t => {
+                                        const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
+                                        return targetPath?.type === "Vehicle";
+                                    });
+
+                                    if (toPath.type === "Conveyor" && hasConveyor) {
+                                        console.log("Conveyor can only connect to one other conveyor");
+                                        return point;
+                                    }
+                                    if (toPath.type === "ArmBot" && hasArmBot) {
+                                        console.log("Conveyor can only connect to one ArmBot");
+                                        return point;
+                                    }
+                                    if (toPath.type === "Vehicle" && hasVehicle) {
+                                        console.log("Conveyor can only connect to one Vehicle");
+                                        return point;
+                                    }
+                                }
+
                                 if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) {
                                     return {
                                         ...point,
@@ -66,6 +97,36 @@ function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObje
                                 };
                                 const existingTargets = point.connections.targets || [];
 
+                                // Check connection limits
+                                const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID);
+                                if (fromPath) {
+                                    const hasConveyor = existingTargets.some(t => {
+                                        const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
+                                        return targetPath?.type === "Conveyor";
+                                    });
+                                    const hasArmBot = existingTargets.some(t => {
+                                        const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
+                                        return targetPath?.type === "ArmBot";
+                                    });
+                                    const hasVehicle = existingTargets.some(t => {
+                                        const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
+                                        return targetPath?.type === "Vehicle";
+                                    });
+
+                                    if (fromPath.type === "Conveyor" && hasConveyor) {
+                                        console.log("Conveyor can only connect to one other conveyor");
+                                        return point;
+                                    }
+                                    if (fromPath.type === "ArmBot" && hasArmBot) {
+                                        console.log("Conveyor can only connect to one ArmBot");
+                                        return point;
+                                    }
+                                    if (fromPath.type === "Vehicle" && hasVehicle) {
+                                        console.log("Conveyor can only connect to one Vehicle");
+                                        return point;
+                                    }
+                                }
+
                                 if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) {
                                     return {
                                         ...point,
@@ -494,21 +555,59 @@ function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObje
                             }
                         }
 
-                        // 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
-                                    );
+                        // For Conveyors, check connection limits in BOTH DIRECTIONS
+                        if (firstSelected && (firstPath?.type === "Conveyor" || secondPath?.type === "Conveyor")) {
+                            const checkConveyorLimits = (path: any, pointUUID: string) => {
+                                if (path?.type === "Conveyor") {
+                                    const point = path.points.find((p: { uuid: string }) => p.uuid === pointUUID);
+                                    if (point) {
+                                        return {
+                                            hasConveyor: point.connections.targets.some((t: { modelUUID: string }) => {
+                                                const targetPath = simulationStates.find((p: { modeluuid: string }) => p.modeluuid === t.modelUUID);
+                                                return targetPath?.type === "Conveyor";
+                                            }),
+                                            hasArmBot: point.connections.targets.some((t: { modelUUID: string }) => {
+                                                const targetPath = simulationStates.find((p: { modeluuid: string }) => p.modeluuid === t.modelUUID);
+                                                return targetPath?.type === "ArmBot";
+                                            }),
+                                            hasVehicle: point.connections.targets.some((t: { modelUUID: string }) => {
+                                                const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
+                                                return targetPath?.type === "Vehicle";
+                                            })
+                                        };
+                                    }
                                 }
-                                return false;
-                            });
+                                return { hasConveyor: false, hasArmBot: false, hasVehicle: false };
+                            };
 
-                            if (isAlreadyConnected) {
-                                console.log("Conveyor point is already connected. Ignoring.");
+                            const firstConveyorLimits = checkConveyorLimits(firstPath, firstSelected?.sphereUUID);
+                            const secondConveyorLimits = checkConveyorLimits(secondPath, sphereUUID);
+
+                            // Check if trying to connect two conveyors
+                            if (firstPath?.type === "Conveyor" && secondPath?.type === "Conveyor") {
+                                if (firstConveyorLimits.hasConveyor || secondConveyorLimits.hasConveyor) {
+                                    console.log("Conveyor can only connect to one other conveyor");
+                                    return;
+                                }
+                            }
+
+                            // Check if trying to connect to an ArmBot when already connected to one
+                            if (secondPath?.type === "ArmBot" && firstConveyorLimits.hasArmBot) {
+                                console.log("Conveyor can only connect to one ArmBot");
+                                return;
+                            }
+                            if (firstPath?.type === "ArmBot" && secondConveyorLimits.hasArmBot) {
+                                console.log("Conveyor can only connect to one ArmBot");
+                                return;
+                            }
+
+                            // Check if trying to connect to a Vehicle when already connected to one
+                            if (secondPath?.type === "Vehicle" && firstConveyorLimits.hasVehicle) {
+                                console.log("Conveyor can only connect to one Vehicle");
+                                return;
+                            }
+                            if (firstPath?.type === "Vehicle" && secondConveyorLimits.hasVehicle) {
+                                console.log("Conveyor can only connect to one Vehicle");
                                 return;
                             }
                         }
@@ -762,6 +861,45 @@ function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObje
                     !(firstPath?.type === 'Conveyor' || firstPath?.type === 'StaticMachine' ||
                         secondPath?.type === 'Conveyor' || secondPath?.type === 'StaticMachine');
 
+                // NEW: Check conveyor connection limits
+                let isConveyorAtMaxConnections = false;
+                if (firstPath?.type === 'Conveyor' || secondPath?.type === 'Conveyor') {
+                    const conveyorPath = firstPath?.type === 'Conveyor' ? firstPath : secondPath;
+                    const otherPath = firstPath?.type === 'Conveyor' ? secondPath : firstPath;
+
+                    if (conveyorPath) {
+                        const conveyorPoint = Array.isArray(conveyorPath.points)
+                            ? conveyorPath.points.find((p: { uuid: string }) => p.uuid ===
+                                (firstPath?.type === 'Conveyor' ? firstSelected.sphereUUID : sphereUUID))
+                            : undefined;
+
+                        if (conveyorPoint) {
+                            const hasConveyor = conveyorPoint.connections.targets.some((t: { modelUUID: string }) => {
+                                const targetPath = simulationStates.find((p: { modeluuid: string }) => p.modeluuid === t.modelUUID);
+                                return targetPath?.type === 'Conveyor';
+                            });
+                            const hasArmBot = conveyorPoint.connections.targets.some((t: { modelUUID: string }) => {
+                                const targetPath = simulationStates.find((p: { modeluuid: string }) => p.modeluuid === t.modelUUID);
+                                return targetPath?.type === 'ArmBot';
+                            });
+                            const hasVehicle = conveyorPoint.connections.targets.some((t: { modelUUID: string }) => {
+                                const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
+                                return targetPath?.type === 'Vehicle';
+                            });
+
+                            if (otherPath?.type === 'Conveyor' && hasConveyor) {
+                                isConveyorAtMaxConnections = true;
+                            }
+                            if (otherPath?.type === 'ArmBot' && hasArmBot) {
+                                isConveyorAtMaxConnections = true;
+                            }
+                            if (otherPath?.type === 'Vehicle' && hasVehicle) {
+                                isConveyorAtMaxConnections = true;
+                            }
+                        }
+                    }
+                }
+
                 if (
                     !isDuplicateConnection &&
                     !isVehicleToVehicle &&
@@ -773,6 +911,7 @@ function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObje
                     !isArmBotToArmBot &&
                     !isArmBotToInvalidType &&
                     !isArmBotAlreadyConnectedToStatic &&
+                    !isConveyorAtMaxConnections && // NEW: Check conveyor limits
                     firstSelected.sphereUUID !== sphereUUID &&
                     firstSelected.modelUUID !== modelUUID &&
                     (firstSelected.isCorner || isConnectable) &&
@@ -957,7 +1096,6 @@ function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObje
                 state.modeluuid === connection2.model
         );
 
-        console.log("updatedPaths: ", updatedPaths);
         updateBackend(updatedPaths);
 
         setSimulationStates(updatedStates);
diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx
index 981846b..ddf21be 100644
--- a/app/src/modules/simulation/process/processAnimator.tsx
+++ b/app/src/modules/simulation/process/processAnimator.tsx
@@ -564,9 +564,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // Log if no animation is occurring when it should
         if (!animationOccurring && !isConnected) {
-          console.log(
-            `Warning: No animation occurring for process ${process.id} despite not being connected`
-          );
+          // console.log(
+          //   `Warning: No animation occurring for process ${process.id} despite not being connected`
+          // );
         }
 
         newStates[process.id] = {

From 16cf1b96ccd3a5b0c64cc788586ad730749ff69c Mon Sep 17 00:00:00 2001
From: gabriel <gabriel@hexrfactory.com>
Date: Wed, 16 Apr 2025 18:04:29 +0530
Subject: [PATCH 18/20] bug fix for data selection tab

---
 .../IotInputCards/BarChartInput.tsx           |   5 +-
 .../FleetEfficiencyInputComponent.tsx         |   7 +-
 .../IotInputCards/FlotingWidgetInput.tsx      |   3 +-
 .../IotInputCards/LineGrapInput.tsx           |   3 +-
 .../IotInputCards/PieChartInput.tsx           |   3 +-
 .../IotInputCards/Progress1Input.tsx          |   3 +-
 .../IotInputCards/Progress2Input.tsx          |   3 +-
 .../WarehouseThroughputInputComponent.tsx     |   3 +-
 .../IotInputCards/Widget2InputCard3D.tsx      |   1 +
 .../IotInputCards/Widget3InputCard3D.tsx      |   1 +
 .../IotInputCards/Widget4InputCard3D.tsx      |   1 +
 .../ui/inputs/MultiLevelDropDown.tsx          | 218 ++++--------------
 .../floating/DroppedFloatingWidgets.tsx       |   2 +-
 13 files changed, 74 insertions(+), 179 deletions(-)

diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/BarChartInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/BarChartInput.tsx
index 8e2d4f1..9fb7b78 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/BarChartInput.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/BarChartInput.tsx
@@ -62,7 +62,7 @@ const BarChartInput = (props: Props) => {
 
     fetchSavedInputes();
 
-  }, [selectedChartId.id]);
+  }, [selectedChartId]);
 
   // Sync Zustand state when component mounts
   useEffect(() => {
@@ -138,7 +138,7 @@ const BarChartInput = (props: Props) => {
       <div className="inputs-wrapper">
         <div className="datas">
           <div className="datas__label">Title</div>
-          <RenameInput value={selectedChartId?.title || "untited"} onRename={handleNameChange}/>
+          <RenameInput value={widgetName || selectedChartId?.title} onRename={handleNameChange}/>
         </div>
         {[...Array(3)].map((_, index) => {
           const inputKey = `input${index + 1}`;
@@ -152,6 +152,7 @@ const BarChartInput = (props: Props) => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx
index af6f735..78b82c8 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FleetEfficiencyInputComponent.tsx
@@ -23,6 +23,10 @@ const FleetEfficiencyInputComponent = (props: Props) => {
   const organization = email?.split("@")[1]?.split(".")[0]
   const [isLoading, setLoading] = useState<boolean>(true);
 
+  const isSelected = () => {
+
+  }
+
   useEffect(() => {
     const fetchZoneData = async () => {
       try {
@@ -139,7 +143,7 @@ const FleetEfficiencyInputComponent = (props: Props) => {
       <div className="inputs-wrapper">
         <div className="datas">
           <div className="datas__label">Title</div>
-          <RenameInput value={selectedChartId?.header || "untited"} onRename={handleNameChange}/>
+          <RenameInput value={widgetName || selectedChartId?.header} onRename={handleNameChange}/>
         </div>
         {[...Array(1)].map((_, index) => {
           const inputKey = `input${index + 1}`;
@@ -153,6 +157,7 @@ const FleetEfficiencyInputComponent = (props: Props) => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx
index 53ddbcc..271b4fc 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/FlotingWidgetInput.tsx
@@ -139,7 +139,7 @@ const FlotingWidgetInput = (props: Props) => {
       <div className="inputs-wrapper">
         <div className="datas">
           <div className="datas__label">Title</div>
-          <RenameInput value={selectedChartId?.header || "untited"} onRename={handleNameChange}/>
+          <RenameInput value={widgetName || selectedChartId?.header} onRename={handleNameChange}/>
         </div>
         {[...Array(6)].map((_, index) => {
           const inputKey = `input${index + 1}`;
@@ -153,6 +153,7 @@ const FlotingWidgetInput = (props: Props) => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx
index 3cf647e..50330d1 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx
@@ -257,7 +257,7 @@ const LineGrapInput = (props: Props) => {
       <div className="inputs-wrapper">
         <div className="datas">
           <div className="datas__label">Title</div>
-          <RenameInput value={selectedChartId?.title || "untited"} onRename={handleNameChange}/>
+          <RenameInput value={widgetName || selectedChartId?.title} onRename={handleNameChange}/>
         </div>
         {[...Array(4)].map((_, index) => {
           const inputKey = `input${index + 1}`;
@@ -271,6 +271,7 @@ const LineGrapInput = (props: Props) => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx
index 1d16358..e7486f2 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx
@@ -138,7 +138,7 @@ const PieChartInput = (props: Props) => {
       <div className="inputs-wrapper">
         <div className="datas">
           <div className="datas__label">Title</div>
-          <RenameInput value={selectedChartId?.title || "untited"} onRename={handleNameChange}/>
+          <RenameInput value={widgetName || selectedChartId?.title} onRename={handleNameChange}/>
         </div>
         {[...Array(2)].map((_, index) => {
           const inputKey = `input${index + 1}`;
@@ -152,6 +152,7 @@ const PieChartInput = (props: Props) => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress1Input.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress1Input.tsx
index 5d9dd58..797f63a 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress1Input.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress1Input.tsx
@@ -132,7 +132,7 @@ const Progress1Input = (props: Props) => {
       <div className="inputs-wrapper">
         <div className="datas">
           <div className="datas__label">Title</div>
-          <RenameInput value={selectedChartId?.title || "untited"} onRename={handleNameChange}/>
+          <RenameInput value={widgetName || selectedChartId?.title} onRename={handleNameChange}/>
         </div>
         {[...Array(1)].map((_, index) => {
           const inputKey = `input${index + 1}`;
@@ -146,6 +146,7 @@ const Progress1Input = (props: Props) => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress2Input.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress2Input.tsx
index bc6059c..a7d2934 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress2Input.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Progress2Input.tsx
@@ -132,7 +132,7 @@ const Progress2Input = (props: Props) => {
       <div className="inputs-wrapper">
         <div className="datas">
           <div className="datas__label">Title</div>
-          <RenameInput value={selectedChartId?.title || "untited"} onRename={handleNameChange}/>
+          <RenameInput value={widgetName || selectedChartId?.title} onRename={handleNameChange}/>
         </div>
         {[...Array(2)].map((_, index) => {
           const inputKey = `input${index + 1}`;
@@ -146,6 +146,7 @@ const Progress2Input = (props: Props) => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx
index 8d5e717..764be54 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/WarehouseThroughputInputComponent.tsx
@@ -139,7 +139,7 @@ const WarehouseThroughputInputComponent = (props: Props) => {
       <div className="inputs-wrapper">
         <div className="datas">
           <div className="datas__label">Title</div>
-          <RenameInput value={selectedChartId?.header || "untited"} onRename={handleNameChange}/>
+          <RenameInput value={widgetName || selectedChartId?.header} onRename={handleNameChange}/>
         </div>
         {[...Array(1)].map((_, index) => {
           const inputKey = `input${index + 1}`;
@@ -153,6 +153,7 @@ const WarehouseThroughputInputComponent = (props: Props) => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx
index a1b4360..345de09 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx
@@ -151,6 +151,7 @@ const Widget2InputCard3D = (props: Props) => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx
index 43f8e55..c41447a 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx
@@ -144,6 +144,7 @@ const Widget3InputCard3D = () => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx
index 4aa9855..20369bd 100644
--- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx
@@ -151,6 +151,7 @@ const Widget4InputCard3D = (props: Props) => {
                   onUnselect={() => handleSelect(inputKey, null)}
                   selectedValue={selections[inputKey]} // Load from Zustand
                   isLoading={isLoading}
+                  allSelections={selections}
                 />
                 <div className="icon">
                   <AddIcon />
diff --git a/app/src/components/ui/inputs/MultiLevelDropDown.tsx b/app/src/components/ui/inputs/MultiLevelDropDown.tsx
index 1293e4a..fa30a55 100644
--- a/app/src/components/ui/inputs/MultiLevelDropDown.tsx
+++ b/app/src/components/ui/inputs/MultiLevelDropDown.tsx
@@ -1,145 +1,3 @@
-// import React, { useState, useRef, useEffect } from "react";
-
-// // Dropdown Item Component
-// const DropdownItem = ({
-//   label,
-//   href,
-//   onClick,
-// }: {
-//   label: string;
-//   href?: string;
-//   onClick?: () => void;
-// }) => (
-//   <a
-//     href={href || "#"}
-//     className="dropdown-item"
-//     onClick={(e) => {
-//       e.preventDefault();
-//       onClick?.();
-//     }}
-//   >
-//     {label}
-//   </a>
-// );
-
-// // Nested Dropdown Component
-// const NestedDropdown = ({
-//   label,
-//   children,
-//   onSelect,
-// }: {
-//   label: string;
-//   children: React.ReactNode;
-//   onSelect: (selectedLabel: string) => void;
-// }) => {
-//   const [open, setOpen] = useState(false);
-
-//   return (
-//     <div className="nested-dropdown">
-//       {/* Dropdown Trigger */}
-//       <div
-//         className={`dropdown-trigger ${open ? "open" : ""}`}
-//         onClick={() => setOpen(!open)} // Toggle submenu on click
-//       >
-//         {label} <span className="icon">{open ? "▼" : "▶"}</span>
-//       </div>
-
-//       {/* Submenu */}
-//       {open && (
-//         <div className="submenu">
-//           {React.Children.map(children, (child) => {
-//             if (React.isValidElement(child)) {
-//               // Clone the element and pass the `onSelect` prop only if it's expected
-//               return React.cloneElement(child as React.ReactElement<any>, { onSelect });
-//             }
-//             return child; // Return non-element children as-is
-//           })}
-//         </div>
-//       )}
-//     </div>
-//   );
-// };
-
-// // Recursive Function to Render Nested Data
-// const renderNestedData = (
-//   data: Record<string, any>,
-//   onSelect: (selectedLabel: string) => void
-// ) => {
-//   return Object.entries(data).map(([key, value]) => {
-//     if (typeof value === "object" && !Array.isArray(value)) {
-//       // If the value is an object, render it as a nested dropdown
-//       return (
-//         <NestedDropdown key={key} label={key} onSelect={onSelect}>
-//           {renderNestedData(value, onSelect)}
-//         </NestedDropdown>
-//       );
-//     } else if (Array.isArray(value)) {
-//       // If the value is an array, render each item as a dropdown item
-//       return value.map((item, index) => (
-//         <DropdownItem key={index} label={item} onClick={() => onSelect(item)} />
-//       ));
-//     } else {
-//       // If the value is a simple string, render it as a dropdown item
-//       return (
-//         <DropdownItem key={key} label={value} onClick={() => onSelect(value)} />
-//       );
-//     }
-//   });
-// };
-
-// // Main Multi-Level Dropdown Component
-// const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
-//   const [open, setOpen] = useState(false);
-//   const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger");
-//   const dropdownRef = useRef<HTMLDivElement>(null);
-
-//   // Handle outer click to close the dropdown
-//   useEffect(() => {
-//     const handleClickOutside = (event: MouseEvent) => {
-//       if (
-//         dropdownRef.current &&
-//         !dropdownRef.current.contains(event.target as Node)
-//       ) {
-//         setOpen(false);
-//       }
-//     };
-
-//     document.addEventListener("mousedown", handleClickOutside);
-//     return () => {
-//       document.removeEventListener("mousedown", handleClickOutside);
-//     };
-//   }, []);
-
-//   // Handle selection of an item
-//   const handleSelect = (selectedLabel: string) => {
-//     setSelectedLabel(selectedLabel); // Update the dropdown trigger text
-//     setOpen(false); // Close the dropdown
-//   };
-
-//   return (
-//     <div className="multi-level-dropdown" ref={dropdownRef}>
-//       {/* Dropdown Trigger Button */}
-//       <button
-//         className={`dropdown-button ${open ? "open" : ""}`}
-//         onClick={() => setOpen(!open)} // Toggle main menu on click
-//       >
-//         {selectedLabel} <span className="icon">▾</span>
-//       </button>
-
-//       {/* Dropdown Menu */}
-//       {open && (
-//         <div className="dropdown-menu">
-//           <div className="dropdown-content">
-//             {renderNestedData(data, handleSelect)}
-//           </div>
-//         </div>
-//       )}
-//     </div>
-//   );
-// };
-
-// export default MultiLevelDropdown;
-
 import React, { useState, useRef, useEffect } from "react";
 import { ArrowIcon } from "../../icons/ExportCommonIcons";
 
@@ -147,11 +5,19 @@ import { ArrowIcon } from "../../icons/ExportCommonIcons";
 const DropdownItem = ({
   label,
   onClick,
+  disabled = false,
 }: {
   label: string;
   onClick: () => void;
+  disabled?: boolean;
 }) => (
-  <div className="dropdown-item" onClick={onClick}>
+  <div
+    className={`dropdown-item ${disabled ? "disabled" : ""}`}
+    onClick={() => {
+      if (!disabled) onClick();
+    }}
+    style={{ cursor: disabled ? "not-allowed": "default", opacity: disabled ? 0.5 : 1 }}
+  >
     {label}
   </div>
 );
@@ -161,10 +27,12 @@ const NestedDropdown = ({
   label,
   fields,
   onSelect,
+  disabledFields = [],
 }: {
   label: string;
   fields: string[];
   onSelect: (selectedData: { name: string; fields: string }) => void;
+  disabledFields?: string[];
 }) => {
   const [open, setOpen] = useState(false);
 
@@ -184,13 +52,17 @@ const NestedDropdown = ({
       </div>
       {open && (
         <div className="submenu">
-          {fields.map((field) => (
-            <DropdownItem
-              key={field}
-              label={field}
-              onClick={() => onSelect({ name: label, fields: field })}
-            />
-          ))}
+          {fields.map((field) => {
+            const isDisabled = disabledFields.includes(`${label}-${field}`);
+            return (
+              <DropdownItem
+                key={field}
+                label={field}
+                onClick={() => onSelect({ name: label, fields: field })}
+                disabled={isDisabled}
+              />
+            );
+          })}
         </div>
       )}
     </div>
@@ -203,6 +75,7 @@ interface MultiLevelDropdownProps {
   onSelect: (selectedData: { name: string; fields: string }) => void;
   onUnselect: () => void;
   selectedValue?: { name: string; fields: string };
+  allSelections?: Record<string, { name: string; fields: string }>;
   isLoading?: boolean;
 }
 
@@ -212,6 +85,7 @@ const MultiLevelDropdown = ({
   onSelect,
   onUnselect,
   selectedValue,
+  allSelections = {},
   isLoading = false,
 }: MultiLevelDropdownProps) => {
   const [open, setOpen] = useState(false);
@@ -249,6 +123,14 @@ const MultiLevelDropdown = ({
     ? `${selectedValue.name} - ${selectedValue.fields}`
     : "Dropdown trigger";
 
+  // Build list of disabled selections
+  const disabledFieldsList = Object.values(allSelections)
+    .filter(
+      (sel) =>
+        !(sel.name === selectedValue?.name && sel.fields === selectedValue?.fields)
+    )
+    .map((sel) => `${sel.name}-${sel.fields}`);
+
   return (
     <div className="multi-level-dropdown" ref={dropdownRef}>
       <button
@@ -260,25 +142,23 @@ const MultiLevelDropdown = ({
       </button>
       {open && (
         <div className="dropdown-menu">
-          <div className="dropdown-content ">
-            
-            {/* loading list */}
-            
-
-            {/* Unselect Option */}
-            <DropdownItem label="Unselect" onClick={handleItemUnselect} />
-            {/* Nested Dropdown Items */}
-            {
-              isLoading ?  <div className="loading" /> :   
-              Object.entries(data).map(([key, value]) => (
-                <NestedDropdown
-                  key={key}
-                  label={key}
-                  fields={Object.keys(value)}
-                  onSelect={handleItemSelect}
-                />
-              ))
-            }
+          <div className="dropdown-content">
+            {isLoading ? (
+              <div className="loading" />
+            ) : (
+              <>
+                <DropdownItem label="Unselect" onClick={handleItemUnselect} />
+                {Object.entries(data).map(([key, value]) => (
+                  <NestedDropdown
+                    key={key}
+                    label={key}
+                    fields={Object.keys(value)}
+                    onSelect={handleItemSelect}
+                    disabledFields={disabledFieldsList}
+                  />
+                ))}
+              </>
+            )}
           </div>
         </div>
       )}
diff --git a/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx b/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx
index 62c1de7..243d2ef 100644
--- a/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx
+++ b/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx
@@ -558,7 +558,7 @@ const DroppedObjects: React.FC = () => {
 
         return (
           <div
-            key={`${zoneName}-${index}`}
+            key={obj.id}
             className={`${obj.className} ${
               selectedChartId?.id === obj.id && "activeChart"
             } `}

From 64885f246e9cd130f31409da26372aa35352f941 Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B <jerald@hexrfactory.com>
Date: Wed, 16 Apr 2025 18:05:23 +0530
Subject: [PATCH 19/20] refactor: Improve error handling and variable naming in
 Assets and IKAnimationController components

---
 .../components/layout/sidebarLeft/Assets.tsx  |  5 +++--
 .../armbot/IKAnimationController.tsx          | 20 +++++++++++--------
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/app/src/components/layout/sidebarLeft/Assets.tsx b/app/src/components/layout/sidebarLeft/Assets.tsx
index 1cdd9bd..5477790 100644
--- a/app/src/components/layout/sidebarLeft/Assets.tsx
+++ b/app/src/components/layout/sidebarLeft/Assets.tsx
@@ -73,7 +73,7 @@ const Assets: React.FC = () => {
       try {
         const filt = await fetchAssets();
         setFiltereredAssets(filt);
-      } catch {}
+      } catch { }
     };
     filteredAssets();
   }, [categoryAssets]);
@@ -135,7 +135,7 @@ const Assets: React.FC = () => {
         const res = await getCategoryAsset(asset);
         setCategoryAssets(res);
         setFiltereredAssets(res);
-      } catch (error) {}
+      } catch (error) { }
     }
   };
   return (
@@ -234,6 +234,7 @@ const Assets: React.FC = () => {
                     src={categoryInfo?.categoryImage || ""}
                     alt={category}
                     className="category-image"
+                    draggable={false}
                   />
                   <div className="category-name">{category}</div>
                 </div>
diff --git a/app/src/modules/simulation/armbot/IKAnimationController.tsx b/app/src/modules/simulation/armbot/IKAnimationController.tsx
index 6b77bac..a58e2d8 100644
--- a/app/src/modules/simulation/armbot/IKAnimationController.tsx
+++ b/app/src/modules/simulation/armbot/IKAnimationController.tsx
@@ -4,6 +4,8 @@ import * as THREE from "three";
 import { usePlayButtonStore, useResetButtonStore } from "../../../store/usePlayButtonStore";
 import { useSimulationStates } from "../../../store/store";
 import MaterialInstances from "./MaterialInstances";
+import { Line } from "react-chartjs-2";
+import { QuadraticBezierLine } from "@react-three/drei";
 
 
 interface StaticMachineState {
@@ -124,7 +126,7 @@ const IKAnimationController = ({
         ]);
     };
 
-    const processCurves = useMemo(() => {
+    const processedCurves = useMemo(() => {
         if (!isPlaying) return [];
 
         return processes.map(process => {
@@ -172,8 +174,8 @@ const IKAnimationController = ({
 
     const activeProcess = useMemo(() => {
         if (!selectedTrigger) return null;
-        return processCurves.find(p => p?.triggerId === selectedTrigger);
-    }, [processCurves, selectedTrigger]);
+        return processedCurves.find(p => p?.triggerId === selectedTrigger);
+    }, [processedCurves, selectedTrigger]);
 
     // Initial movement to rest position
     useFrame((_, delta) => {
@@ -364,11 +366,13 @@ const IKAnimationController = ({
     }
 
     return (
-        <MaterialInstances
-            statusRef={statusRef}
-            ikSolver={ikSolver}
-            targetBoneName={targetBoneName}
-        />
+        <>
+            <MaterialInstances
+                statusRef={statusRef}
+                ikSolver={ikSolver}
+                targetBoneName={targetBoneName}
+            />
+        </>
     );
 };
 

From 8e491a0002f6e8b3135c06681e64c324cd81f364 Mon Sep 17 00:00:00 2001
From: Jerald-Golden-B <jerald@hexrfactory.com>
Date: Wed, 16 Apr 2025 18:30:43 +0530
Subject: [PATCH 20/20] feat: Add isActive property to ArmBot state and update
 IKAnimationController logic refactor: Remove commented console logs in
 ProcessAnimator and useProcessAnimations

---
 app/src/modules/simulation/armbot/ArmBot.tsx  |  3 +-
 .../armbot/IKAnimationController.tsx          |  2 +-
 .../simulation/process/processAnimator.tsx    | 62 +++++++++----------
 .../process/useProcessAnimations.tsx          |  4 +-
 4 files changed, 36 insertions(+), 35 deletions(-)

diff --git a/app/src/modules/simulation/armbot/ArmBot.tsx b/app/src/modules/simulation/armbot/ArmBot.tsx
index 5d55791..066779a 100644
--- a/app/src/modules/simulation/armbot/ArmBot.tsx
+++ b/app/src/modules/simulation/armbot/ArmBot.tsx
@@ -53,7 +53,8 @@ const ArmBot = ({ armBots, setArmBots, setStaticMachines }: ArmBotProps) => {
                 material: "default",
                 triggerId: '',
                 actions: bot.points.actions,
-                connections: bot.points.connections
+                connections: bot.points.connections,
+                isActive: false
             }));
         setArmBots(initialStates);
     }, [simulationStates, isReset]);
diff --git a/app/src/modules/simulation/armbot/IKAnimationController.tsx b/app/src/modules/simulation/armbot/IKAnimationController.tsx
index a58e2d8..e2df7f5 100644
--- a/app/src/modules/simulation/armbot/IKAnimationController.tsx
+++ b/app/src/modules/simulation/armbot/IKAnimationController.tsx
@@ -347,7 +347,7 @@ const IKAnimationController = ({
                     if (matchedMachine.type === "Conveyor") {
                         setArmBots((prev) =>
                             prev.map((arm) => {
-                                if (arm.uuid === uuid) {
+                                if (arm.uuid === uuid && arm.isActive === true) {
                                     return {
                                         ...arm,
                                         isActive: false,
diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx
index 04ddf90..2cd574f 100644
--- a/app/src/modules/simulation/process/processAnimator.tsx
+++ b/app/src/modules/simulation/process/processAnimator.tsx
@@ -169,9 +169,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         const spawnPoint = findSpawnPoint(process);
         if (!spawnPoint || !spawnPoint.actions) {
-          console.log(
-            `Process ${process.id} has no valid spawn point or actions`
-          );
+          // console.log(
+          //   `Process ${process.id} has no valid spawn point or actions`
+          // );
           return;
         }
 
@@ -255,10 +255,10 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
         // Check connection status with debugging
         const isConnected = isConnectedToActiveArmBot(process.id);
-        console.log(
-          `Process ${process.id} animation - connected:`,
-          isConnected
-        );
+        // console.log(
+        //   `Process ${process.id} animation - connected:`,
+        //   isConnected
+        // );
 
         if (isConnected) {
           // Stop all animations when connected to active arm bot
@@ -293,9 +293,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
             currentTime - processState.processDelayStartTime >=
             effectiveDelayTime
           ) {
-            console.log(
-              `Process ${process.id} delay completed, resuming animation`
-            );
+            // console.log(
+            //   `Process ${process.id} delay completed, resuming animation`
+            // );
             newStates[process.id] = {
               ...processState,
               isProcessDelaying: false,
@@ -331,9 +331,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
           [];
 
         if (path.length < 2) {
-          console.log(
-            `Process ${process.id} has insufficient path points: ${path.length}`
-          );
+          // console.log(
+          //   `Process ${process.id} has insufficient path points: ${path.length}`
+          // );
           return;
         }
 
@@ -348,9 +348,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             const currentRef = gltf?.scene ? obj.ref.current : obj.ref.current;
             if (!currentRef) {
-              console.log(
-                `No reference for object ${objectId}, skipping animation`
-              );
+              // console.log(
+              //   `No reference for object ${objectId}, skipping animation`
+              // );
               return;
             }
 
@@ -378,9 +378,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
                 stateRef.currentDelayDuration / speedRef.current;
 
               if (currentTime - stateRef.delayStartTime >= effectiveDelayTime) {
-                console.log(
-                  `Delay complete for object ${objectId}, resuming animation`
-                );
+                // console.log(
+                //   `Delay complete for object ${objectId}, resuming animation`
+                // );
                 stateRef.isDelaying = false;
                 stateRef.delayComplete = true;
                 stateRef.isAnimating = true;
@@ -408,9 +408,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
             // Skip non-animating objects
             if (!stateRef.isAnimating) {
-              console.log(
-                `Object ${objectId} not animating, skipping animation updates`
-              );
+              // console.log(
+              //   `Object ${objectId} not animating, skipping animation updates`
+              // );
               return;
             }
 
@@ -454,9 +454,9 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
 
               if (shouldHide) {
                 if (isAgvPicking) {
-                  console.log(
-                    `AGV picking at last point for object ${objectId}, hiding object`
-                  );
+                  // console.log(
+                  //   `AGV picking at last point for object ${objectId}, hiding object`
+                  // );
                   updatedObjects[objectId] = {
                     ...obj,
                     visible: false,
@@ -517,14 +517,14 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
               if (stateRef.delayComplete && stateRef.progress < 0.01) {
                 stateRef.progress = 0.05;
                 stateRef.delayComplete = false;
-                console.log(
-                  `Boosting progress for object ${objectId} after delay`
-                );
+                // console.log(
+                //   `Boosting progress for object ${objectId} after delay`
+                // );
               } else {
                 stateRef.progress += movement / distance;
-                console.log(
-                  `Object ${objectId} progress: ${stateRef.progress.toFixed(3)}`
-                );
+                // console.log(
+                //   `Object ${objectId} progress: ${stateRef.progress.toFixed(3)}`
+                // );
               }
 
               // Handle point transition
diff --git a/app/src/modules/simulation/process/useProcessAnimations.tsx b/app/src/modules/simulation/process/useProcessAnimations.tsx
index a46fe3c..579ee3f 100644
--- a/app/src/modules/simulation/process/useProcessAnimations.tsx
+++ b/app/src/modules/simulation/process/useProcessAnimations.tsx
@@ -514,8 +514,6 @@ export const useProcessAnimation = (
 
             newTriggerCounts[triggerKey] = (newTriggerCounts[triggerKey] || 0) + 1;
 
-            shouldLog = true;
-
             newTriggerLogs.push({ timestamp: currentTime, pointId: point.uuid, objectId, triggerId: trigger.uuid, });
 
             const connections = point.connections?.targets || [];
@@ -530,6 +528,8 @@ export const useProcessAnimation = (
                   uuid: connectedModelUUID,
                   triggerId: trigger.uuid,
                 });
+              } else {
+                shouldLog = true;
               }
             });
           });