diff --git a/app/src/components/ui/simulation/simulationPlayer.tsx b/app/src/components/ui/simulation/simulationPlayer.tsx
index fd9f418..25a55e5 100644
--- a/app/src/components/ui/simulation/simulationPlayer.tsx
+++ b/app/src/components/ui/simulation/simulationPlayer.tsx
@@ -38,18 +38,10 @@ const SimulationPlayer: React.FC = () => {
const { isReset, setReset } = useResetButtonStore();
const { subModule } = useSubModuleStore();
- useEffect(() => {
- if (isReset) {
- setTimeout(() => {
- setReset(false);
- }, 0)
- }
- }, [isReset])
-
// Button functions
const handleReset = () => {
- setReset(true);
- // setSpeed(1);
+ setReset(!isReset);
+ setSpeed(1);
};
const handlePlayStop = () => {
setIsPaused(!isPaused);
@@ -279,10 +271,11 @@ const SimulationPlayer: React.FC = () => {
{index < intervals.length - 1 && (
= ((index + 1) / totalSegments) * 100
- ? "filled"
- : ""
- }`}
+ className={`line ${
+ progress >= ((index + 1) / totalSegments) * 100
+ ? "filled"
+ : ""
+ }`}
>
)}
diff --git a/app/src/modules/collaboration/functions/setCameraView.ts b/app/src/modules/collaboration/functions/setCameraView.ts
index 8bae59b..456f622 100644
--- a/app/src/modules/collaboration/functions/setCameraView.ts
+++ b/app/src/modules/collaboration/functions/setCameraView.ts
@@ -28,6 +28,4 @@ export default async function setCameraView({
controls?.setLookAt(...newPosition.toArray(), newPosition.x, 0, newPosition.z, true);
}
- // Optionally you can log
- console.log(`Camera view updated by ${username ?? 'unknown user'}`);
}
diff --git a/app/src/modules/simulation/actions/conveyor/actionHandler/spawnActionHandler.ts b/app/src/modules/simulation/actions/conveyor/actionHandler/useSpawnHandler.ts
similarity index 82%
rename from app/src/modules/simulation/actions/conveyor/actionHandler/spawnActionHandler.ts
rename to app/src/modules/simulation/actions/conveyor/actionHandler/useSpawnHandler.ts
index c28f1d0..776b539 100644
--- a/app/src/modules/simulation/actions/conveyor/actionHandler/spawnActionHandler.ts
+++ b/app/src/modules/simulation/actions/conveyor/actionHandler/useSpawnHandler.ts
@@ -7,7 +7,7 @@ import { useSelectedProduct } from "../../../../../store/simulation/useSimulatio
export function useSpawnHandler() {
const { addMaterial } = useMaterialStore();
- const { getModelUuidByActionUuid } = useProductStore();
+ const { getModelUuidByActionUuid, getPointUuidByActionUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const lastSpawnTime = useRef(null);
const startTime = useRef(null);
@@ -16,7 +16,7 @@ export function useSpawnHandler() {
material: string;
intervalMs: number;
totalCount: number;
- point: ConveyorPointSchema;
+ action: ConveyorAction;
} | null>(null);
const clearCurrentSpawn = useCallback(() => {
@@ -27,12 +27,13 @@ export function useSpawnHandler() {
}, []);
const spawnLogStatus = (materialUuid: string, status: string) => {
- // console.log(`${materialUuid}, ${status}`);
+ console.log(`${materialUuid}, ${status}`);
}
- const createNewMaterial = useCallback((materialType: string, point: ConveyorPointSchema) => {
- const modelUuid = getModelUuidByActionUuid(selectedProduct.productId, point.action.actionUuid);
- if (!modelUuid || !point.uuid) return;
+ const createNewMaterial = useCallback((materialType: string, action: ConveyorAction) => {
+ const modelUuid = getModelUuidByActionUuid(selectedProduct.productId, action.actionUuid);
+ const pointUuid = getPointUuidByActionUuid(selectedProduct.productId, action.actionUuid);
+ if (!modelUuid || !pointUuid) return;
const newMaterial: MaterialSchema = {
materialId: THREE.MathUtils.generateUUID(),
@@ -43,8 +44,8 @@ export function useSpawnHandler() {
isRendered: true,
current: {
modelUuid: modelUuid,
- pointUuid: point.uuid,
- actionUuid: point.action?.actionUuid || ''
+ pointUuid: pointUuid,
+ actionUuid: action?.actionUuid || ''
},
weight: 1,
cost: 1
@@ -58,14 +59,14 @@ export function useSpawnHandler() {
if (!spawnParams.current || !startTime.current) return;
const currentTime = performance.now();
- const { material, intervalMs, totalCount, point } = spawnParams.current;
+ const { material, intervalMs, totalCount, action } = spawnParams.current;
const isFirstSpawn = lastSpawnTime.current === null;
const elapsed = currentTime - startTime.current;
// First spawn
if (isFirstSpawn) {
if (elapsed >= intervalMs) {
- const createdMaterial = createNewMaterial(material, point);
+ const createdMaterial = createNewMaterial(material, action);
if (createdMaterial) {
spawnLogStatus(createdMaterial.materialId, `[${elapsed.toFixed(2)}ms] Spawned ${material} (1/${totalCount})`);
}
@@ -84,9 +85,9 @@ export function useSpawnHandler() {
const timeSinceLast = currentTime - lastSpawnTime.current;
if (timeSinceLast >= intervalMs) {
const count = spawnCountRef.current + 1;
- const createdMaterial = createNewMaterial(material, point);
+ const createdMaterial = createNewMaterial(material, action);
if (createdMaterial) {
- spawnLogStatus(createdMaterial.materialId, `[${elapsed.toFixed(2)}ms] Spawned ${material} (1/${totalCount})`);
+ spawnLogStatus(createdMaterial.materialId, `[${elapsed.toFixed(2)}ms] Spawned ${material} (${count}/${totalCount})`);
}
lastSpawnTime.current = currentTime;
spawnCountRef.current = count;
@@ -98,10 +99,10 @@ export function useSpawnHandler() {
}
});
- const handleSpawn = useCallback((point: ConveyorPointSchema) => {
- if (!point.action || point.action.actionType !== 'spawn') return;
+ const handleSpawn = useCallback((action: ConveyorAction) => {
+ if (!action || action.actionType !== 'spawn') return;
- const { material, spawnInterval = 0, spawnCount = 1 } = point.action;
+ const { material, spawnInterval = 0, spawnCount = 1 } = action;
const intervalMs = spawnInterval * 1000;
clearCurrentSpawn();
@@ -110,7 +111,7 @@ export function useSpawnHandler() {
material,
intervalMs,
totalCount: spawnCount,
- point: point
+ action: action
};
startTime.current = performance.now();
diff --git a/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts b/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts
index e10e115..a61e3c4 100644
--- a/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts
+++ b/app/src/modules/simulation/actions/conveyor/useConveyorActions.ts
@@ -1,40 +1,66 @@
-import { useEffect } from "react";
-import { useSpawnHandler } from "./actionHandler/spawnActionHandler";
+import { useEffect, useCallback, useRef } from "react";
+import { useSpawnHandler } from "./actionHandler/useSpawnHandler";
-// Conveyor Actions
-export function useConveyorActions(point: ConveyorPointSchema) {
- const { handleSpawn } = useSpawnHandler();
+export function useConveyorActions() {
+ const { handleSpawn, clearCurrentSpawn } = useSpawnHandler();
+
+ const handleDefaultAction = useCallback((action: ConveyorAction) => {
+ console.log(`Default conveyor action ${action.actionUuid}`);
+ }, []);
+
+ const handleSpawnAction = useCallback((action: ConveyorAction) => {
+ handleSpawn(action);
+ }, [handleSpawn]);
+
+ const handleSwapAction = useCallback((action: ConveyorAction) => {
+ console.log(`Swapping to material ${action.material}`);
+ }, []);
+
+ const handleDelayAction = useCallback((action: ConveyorAction) => {
+ const delayMs = (action.delay || 0) * 1000;
+ console.log(`Delaying for ${delayMs}ms`);
+ }, []);
+
+ const handleDespawnAction = useCallback((action: ConveyorAction) => {
+ console.log(`Despawning material`);
+ }, []);
+
+ const handleConveyorAction = useCallback((action: ConveyorAction) => {
+ if (!action) return;
+
+ switch (action.actionType) {
+ case 'default':
+ handleDefaultAction(action);
+ break;
+ case 'spawn':
+ handleSpawnAction(action);
+ break;
+ case 'swap':
+ handleSwapAction(action);
+ break;
+ case 'delay':
+ handleDelayAction(action);
+ break;
+ case 'despawn':
+ handleDespawnAction(action);
+ break;
+ default:
+ console.warn(`Unknown conveyor action type: ${action.actionType}`);
+ }
+ }, [handleDefaultAction, handleSpawnAction, handleSwapAction, handleDelayAction, handleDespawnAction]);
+
+ const cleanup = useCallback(() => {
+ clearCurrentSpawn();
+ }, [clearCurrentSpawn]);
useEffect(() => {
- if (!point.action) return;
-
- const { actionType, material, delay, spawnInterval, spawnCount } = point.action;
-
- const handleAction = () => {
- switch (actionType) {
- case 'default':
- console.log(`Default conveyor action at point ${point.uuid}`);
- break;
- case 'spawn':
- console.log(`Spawning material ${material} at point ${point.uuid}`);
- handleSpawn(point);
- break;
- case 'swap':
- console.log(`Swapping to material ${material} at point ${point.uuid}`);
- break;
- case 'delay':
- console.log(`Delaying for ${delay}ms at point ${point.uuid}`);
- break;
- case 'despawn':
- console.log(`Despawning material at point ${point.uuid}`);
- break;
- }
- };
-
- handleAction();
-
return () => {
- // Cleanup if needed
+ cleanup();
};
- }, [point]);
+ }, [cleanup]);
+
+ return {
+ handleConveyorAction,
+ cleanup
+ };
}
\ No newline at end of file
diff --git a/app/src/modules/simulation/actions/machine/useMachineActions.ts b/app/src/modules/simulation/actions/machine/useMachineActions.ts
index 0ac9865..38e8ce3 100644
--- a/app/src/modules/simulation/actions/machine/useMachineActions.ts
+++ b/app/src/modules/simulation/actions/machine/useMachineActions.ts
@@ -1,23 +1,35 @@
-import { useEffect } from 'react';
+import { useEffect, useCallback, useRef, useState } from 'react';
+
+export function useMachineActions() {
+
+ const handleProcessAction = useCallback((action: MachineAction) => {
+ if (!action || action.actionType !== 'process') return;
+ console.log(`Machine processing for ${action.processTime}ms`);
+ }, []);
+
+ const handleMachineAction = useCallback((action: MachineAction) => {
+ if (!action) return;
+
+ switch (action.actionType) {
+ case 'process':
+ handleProcessAction(action);
+ break;
+ default:
+ console.warn(`Unknown machine action type: ${action.actionType}`);
+ }
+ }, [handleProcessAction]);
+
+ const cleanup = useCallback(() => {
+ }, []);
-// Machine Actions
-export function useMachineActions(point: MachinePointSchema) {
useEffect(() => {
- if (!point.action) return;
-
- const { actionType, processTime, swapMaterial } = point.action;
-
- const handleAction = () => {
- if (actionType === 'process') {
- console.log(`Machine processing for ${processTime}ms at point ${point.uuid}`);
- if (swapMaterial) {
- console.log(`Swapping material to ${swapMaterial}`);
- }
- }
- };
-
return () => {
- // Cleanup if needed
+ cleanup();
};
- }, [point]);
+ }, [cleanup]);
+
+ return {
+ handleMachineAction,
+ cleanup,
+ };
}
\ No newline at end of file
diff --git a/app/src/modules/simulation/actions/roboticArm/useRoboticArmActions.ts b/app/src/modules/simulation/actions/roboticArm/useRoboticArmActions.ts
index 50a6196..37990db 100644
--- a/app/src/modules/simulation/actions/roboticArm/useRoboticArmActions.ts
+++ b/app/src/modules/simulation/actions/roboticArm/useRoboticArmActions.ts
@@ -1,26 +1,32 @@
-import { useEffect } from 'react';
+import { useEffect, useCallback } from 'react';
+
+export function useRoboticArmActions() {
+
+ const handlePickAndPlace = useCallback((action: RoboticArmAction) => {
+ console.log(`Robotic arm pick and place`);
+ }, []);
+
+ const handleRoboticArmAction = useCallback((action: RoboticArmAction) => {
+ switch (action.actionType) {
+ case 'pickAndPlace':
+ handlePickAndPlace(action);
+ break;
+ default:
+ console.warn(`Unknown robotic arm action type: ${action.actionType}`);
+ }
+ }, [handlePickAndPlace]);
+
+ const cleanup = useCallback(() => {
+ }, []);
-// Robotic Arm Actions
-export function useRoboticArmActions(point: RoboticArmPointSchema) {
useEffect(() => {
- point.actions.forEach(action => {
- const { actionType, process } = action;
-
- const handleAction = () => {
- if (actionType === 'pickAndPlace') {
- console.log(`Robotic arm pick and place at point ${point.uuid}`);
- if (process.startPoint) {
- console.log(`Start point: ${process.startPoint}`);
- }
- if (process.endPoint) {
- console.log(`End point: ${process.endPoint}`);
- }
- }
- };
- });
-
return () => {
- // Cleanup if needed
+ cleanup();
};
- }, [point]);
+ }, [cleanup]);
+
+ return {
+ handleRoboticArmAction,
+ cleanup
+ };
}
\ No newline at end of file
diff --git a/app/src/modules/simulation/actions/storageUnit/useStorageUnitActions.ts b/app/src/modules/simulation/actions/storageUnit/useStorageUnitActions.ts
index 6ffa8ad..bc1ab94 100644
--- a/app/src/modules/simulation/actions/storageUnit/useStorageUnitActions.ts
+++ b/app/src/modules/simulation/actions/storageUnit/useStorageUnitActions.ts
@@ -1,22 +1,33 @@
-import { useEffect } from 'react';
+import { useEffect, useCallback, useRef, useState } from 'react';
+
+export function useStorageActions() {
+ const handleStoreAction = useCallback((action: StorageAction) => {
+ if (!action || action.actionType !== 'store') return;
+ }, []);
+
+ const handleStorageAction = useCallback((action: StorageAction) => {
+ if (!action) return;
+
+ switch (action.actionType) {
+ case 'store':
+ handleStoreAction(action);
+ break;
+ default:
+ console.warn(`Unknown storage action type: ${action.actionType}`);
+ }
+ }, [handleStoreAction]);
+
+ const cleanup = useCallback(() => {
+ }, []);
-// Storage Actions
-export function useStorageActions(point: StoragePointSchema) {
useEffect(() => {
- if (!point.action) return;
-
- const { actionType, materials, storageCapacity } = point.action;
-
- const handleAction = () => {
- if (actionType === 'store') {
- console.log(`Storage action at point ${point.uuid}`);
- console.log(`Materials: ${materials.map(m => m.materialName).join(', ')}`);
- console.log(`Capacity: ${storageCapacity}`);
- }
- };
-
return () => {
- // Cleanup if needed
+ cleanup();
};
- }, [point]);
+ }, [cleanup]);
+
+ return {
+ handleStorageAction,
+ cleanup
+ };
}
\ No newline at end of file
diff --git a/app/src/modules/simulation/actions/useActionHandler.ts b/app/src/modules/simulation/actions/useActionHandler.ts
index f49381f..dbffd69 100644
--- a/app/src/modules/simulation/actions/useActionHandler.ts
+++ b/app/src/modules/simulation/actions/useActionHandler.ts
@@ -3,23 +3,76 @@ import { useMachineActions } from "./machine/useMachineActions";
import { useRoboticArmActions } from "./roboticArm/useRoboticArmActions";
import { useStorageActions } from "./storageUnit/useStorageUnitActions";
import { useVehicleActions } from "./vehicle/useVehicleActions";
+import { useCallback, useEffect } from "react";
-// Master hook that selects the appropriate action handler
-export function useActionHandler(point: PointsScheme) {
- // if ('actions' in point) {
- // // Robotic Arm
- // useRoboticArmActions(point);
- // } else if (point.action.actionType === 'travel') {
- // // Vehicle
- // useVehicleActions(point as VehiclePointSchema);
- // } else if (point.action.actionType === 'process') {
- // // Machine
- // useMachineActions(point as MachinePointSchema);
- // } else if (point.action.actionType === 'store') {
- // // Storage
- // useStorageActions(point as StoragePointSchema);
- // } else {
- // // Conveyor
- // useConveyorActions(point as ConveyorPointSchema);
- // }
+export function useActionHandler() {
+ // Initialize all action handlers
+ const { handleConveyorAction, cleanup: cleanupConveyor } = useConveyorActions();
+ const { handleVehicleAction, cleanup: cleanupVehicle } = useVehicleActions();
+ const { handleRoboticArmAction, cleanup: cleanupRoboticArm } = useRoboticArmActions();
+ const { handleMachineAction, cleanup: cleanupMachine } = useMachineActions();
+ const { handleStorageAction, cleanup: cleanupStorage } = useStorageActions();
+
+ // Main handler function
+ const handleAction = useCallback((action: Action) => {
+ if (!action) return;
+
+ try {
+ switch (action.actionType) {
+ case 'default': case 'spawn': case 'swap': case 'delay': case 'despawn':
+ handleConveyorAction(action as ConveyorAction);
+ break;
+ case 'travel':
+ handleVehicleAction(action as VehicleAction);
+ break;
+ case 'pickAndPlace':
+ handleRoboticArmAction(action as RoboticArmAction);
+ break;
+ case 'process':
+ handleMachineAction(action as MachineAction);
+ break;
+ case 'store':
+ handleStorageAction(action as StorageAction);
+ break;
+ default:
+ console.warn(`Unknown action type: ${(action as Action).actionType}`);
+ }
+ } catch (error) {
+ console.error('Error handling action:', error);
+ // Consider adding error recovery or notification here
+ }
+ }, [
+ handleConveyorAction,
+ handleVehicleAction,
+ handleRoboticArmAction,
+ handleMachineAction,
+ handleStorageAction
+ ]);
+
+ // Cleanup all actions
+ const cleanup = useCallback(() => {
+ cleanupConveyor();
+ cleanupVehicle();
+ cleanupRoboticArm();
+ cleanupMachine();
+ cleanupStorage();
+ }, [
+ cleanupConveyor,
+ cleanupVehicle,
+ cleanupRoboticArm,
+ cleanupMachine,
+ cleanupStorage
+ ]);
+
+ // Auto cleanup on unmount
+ useEffect(() => {
+ return () => {
+ cleanup();
+ };
+ }, [cleanup]);
+
+ return {
+ handleAction,
+ cleanup
+ };
}
\ No newline at end of file
diff --git a/app/src/modules/simulation/actions/vehicle/useVehicleActions.ts b/app/src/modules/simulation/actions/vehicle/useVehicleActions.ts
index 7a6ce4d..313fb5d 100644
--- a/app/src/modules/simulation/actions/vehicle/useVehicleActions.ts
+++ b/app/src/modules/simulation/actions/vehicle/useVehicleActions.ts
@@ -1,26 +1,37 @@
-import { useEffect } from 'react';
+import { useEffect, useCallback } from 'react';
+
+export function useVehicleActions() {
+
+ const handleTravelAction = useCallback((action: VehicleAction) => {
+ if (!action || action.actionType !== 'travel') return;
+
+ console.log(`Vehicle travel action ${action.actionUuid}`);
+
+ }, []);
+
+ const handleVehicleAction = useCallback((action: VehicleAction) => {
+ if (!action) return;
+
+ switch (action.actionType) {
+ case 'travel':
+ handleTravelAction(action);
+ break;
+ default:
+ console.warn(`Unknown vehicle action type: ${action.actionType}`);
+ }
+ }, [handleTravelAction]);
+
+ const cleanup = useCallback(() => {
+ }, []);
-// Vehicle Actions
-export function useVehicleActions(point: VehiclePointSchema) {
useEffect(() => {
- if (!point.action) return;
-
- const { actionType, unLoadDuration, loadCapacity, steeringAngle } = point.action;
-
- const handleAction = () => {
- if (actionType === 'travel') {
- console.log(`Vehicle travel action at point ${point.uuid}`);
- if (point.action.pickUpPoint) {
- console.log(`Pick up at: ${JSON.stringify(point.action.pickUpPoint)}`);
- }
- if (point.action.unLoadPoint) {
- console.log(`Unload at: ${JSON.stringify(point.action.unLoadPoint)}`);
- }
- }
- };
-
return () => {
- // Cleanup if needed
+ cleanup();
};
- }, [point]);
+ }, [cleanup]);
+
+ return {
+ handleVehicleAction,
+ cleanup
+ };
}
\ No newline at end of file
diff --git a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx
index ceccd40..fd649c6 100644
--- a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx
@@ -3,240 +3,260 @@ import { useFrame } from '@react-three/fiber';
import * as THREE from 'three';
import { Line } from '@react-three/drei';
import {
- useAnimationPlaySpeed,
- usePauseButtonStore,
- usePlayButtonStore,
- useResetButtonStore
+ useAnimationPlaySpeed,
+ usePauseButtonStore,
+ usePlayButtonStore,
+ useResetButtonStore
} from '../../../../../store/usePlayButtonStore';
function RoboticArmAnimator({
- HandleCallback,
- restPosition,
- ikSolver,
- targetBone,
- armBot,
- logStatus,
- path
+ HandleCallback,
+ restPosition,
+ ikSolver,
+ targetBone,
+ armBot,
+ logStatus,
+ path
}: any) {
- const progressRef = useRef(0);
- const curveRef = useRef(null);
- const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
- const [circlePoints, setCirclePoints] = useState<[number, number, number][]>([]);
- const [customCurvePoints, setCustomCurvePoints] = useState(null);
- let curveHeight = 1.75
- const totalDistanceRef = useRef(0);
- const startTimeRef = useRef(null);
- const segmentDistancesRef = useRef([]);
- // Zustand stores
- const { isPlaying } = usePlayButtonStore();
- const { isPaused } = usePauseButtonStore();
- const { isReset, setReset } = useResetButtonStore();
- const { speed } = useAnimationPlaySpeed();
+ const progressRef = useRef(0);
+ const curveRef = useRef(null);
+ const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
+ const [circlePoints, setCirclePoints] = useState<[number, number, number][]>([]);
+ const [customCurvePoints, setCustomCurvePoints] = useState(null);
+ let curveHeight = 1.75
+ const totalDistanceRef = useRef(0);
+ const startTimeRef = useRef(null);
+ const segmentDistancesRef = useRef([]);
+ // Zustand stores
+ const { isPlaying } = usePlayButtonStore();
+ const { isPaused } = usePauseButtonStore();
+ const { isReset, setReset } = useResetButtonStore();
+ const { speed } = useAnimationPlaySpeed();
- // Update path state whenever `path` prop changes
- useEffect(() => {
- setCurrentPath(path);
- }, [path]);
+ // Update path state whenever `path` prop changes
+ useEffect(() => {
+ setCurrentPath(path);
+ }, [path]);
- // Handle circle points based on armBot position
- useEffect(() => {
- const points = generateRingPoints(1.6, 64)
- setCirclePoints(points);
- }, [armBot.position]);
+ // Handle circle points based on armBot position
+ useEffect(() => {
+ const points = generateRingPoints(1.6, 64)
+ setCirclePoints(points);
+ }, [armBot.position]);
- useEffect(() => {
- if (isReset || !isPlaying) {
- progressRef.current = 0;
- curveRef.current = null;
- setCurrentPath([]);
- setCustomCurvePoints(null);
- totalDistanceRef.current = 0;
- startTimeRef.current = null;
- segmentDistancesRef.current = [];
- setReset(false);
+ //Handle Reset Animation
+ useEffect(() => {
+ if (isReset ) {
+ progressRef.current = 0;
+ curveRef.current = null;
+ setCurrentPath([]);
+ setCustomCurvePoints(null);
+ totalDistanceRef.current = 0;
+ startTimeRef.current = null;
+ segmentDistancesRef.current = [];
+ if (!ikSolver) return
+ const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
+ if (!bone) return;
+ bone.position.copy(restPosition)
+ ikSolver.update();
+ }
+ }, [isReset, isPlaying])
+
+ //Generate Circle Points
+ function generateRingPoints(radius: any, segments: any) {
+ const points: [number, number, number][] = [];
+ for (let i = 0; i < segments; i++) {
+ // Calculate angle for current segment
+ const angle = (i / segments) * Math.PI * 2;
+ // Calculate x and z coordinates (y remains the same for a flat ring)
+ const x = Math.cos(angle) * radius;
+ const z = Math.sin(angle) * radius;
+ points.push([x, 1.5, z]);
+ }
+ return points;
}
- }, [isReset, isPlaying])
+ // Function for find nearest Circlepoints Index
+ const findNearestIndex = (nearestPoint: [number, number, number], points: [number, number, number][], epsilon = 1e-6) => {
+ for (let i = 0; i < points.length; i++) {
+ const [x, y, z] = points[i];
+ if (
+ Math.abs(x - nearestPoint[0]) < epsilon &&
+ Math.abs(y - nearestPoint[1]) < epsilon &&
+ Math.abs(z - nearestPoint[2]) < epsilon
+ ) {
+ return i; // Found the matching index
+ }
+ }
+ return -1; // Not found
+ };
-
- function generateRingPoints(radius: any, segments: any) {
- const points: [number, number, number][] = [];
- for (let i = 0; i < segments; i++) {
- // Calculate angle for current segment
- const angle = (i / segments) * Math.PI * 2;
- // Calculate x and z coordinates (y remains the same for a flat ring)
- const x = Math.cos(angle) * radius;
- const z = Math.sin(angle) * radius;
- points.push([x, 1.5, z]);
- }
- return points;
- }
-
- const findNearestIndex = (nearestPoint: [number, number, number], points: [number, number, number][], epsilon = 1e-6) => {
- for (let i = 0; i < points.length; i++) {
- const [x, y, z] = points[i];
- if (
- Math.abs(x - nearestPoint[0]) < epsilon &&
- Math.abs(y - nearestPoint[1]) < epsilon &&
- Math.abs(z - nearestPoint[2]) < epsilon
- ) {
- return i; // Found the matching index
- }
- }
- return -1; // Not found
- };
-
- // Handle nearest points and final path (including arc points)
- useEffect(() => {
- if (circlePoints.length > 0 && currentPath.length > 0) {
-
- const start = currentPath[0];
- const end = currentPath[currentPath.length - 1];
-
- const raisedStart = [start[0], start[1] + 0.5, start[2]] as [number, number, number];
- const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [number, number, number];
-
- const findNearest = (target: [number, number, number]) => {
+ //function to find nearest Circlepoints
+ const findNearest = (target: [number, number, number]) => {
return circlePoints.reduce((nearest, point) => {
- const distance = Math.hypot(target[0] - point[0], target[1] - point[1], target[2] - point[2]);
- const nearestDistance = Math.hypot(target[0] - nearest[0], target[1] - nearest[1], target[2] - nearest[2]);
- return distance < nearestDistance ? point : nearest;
+ const distance = Math.hypot(target[0] - point[0], target[1] - point[1], target[2] - point[2]);
+ const nearestDistance = Math.hypot(target[0] - nearest[0], target[1] - nearest[1], target[2] - nearest[2]);
+ return distance < nearestDistance ? point : nearest;
}, circlePoints[0]);
- };
+ };
+
+ // Handle nearest points and final path (including arc points)
+ useEffect(() => {
+ if (circlePoints.length > 0 && currentPath.length > 0) {
- const nearestToStart = findNearest(raisedStart);
- const nearestToEnd = findNearest(raisedEnd);
+ const start = currentPath[0];
+ const end = currentPath[currentPath.length - 1];
- const indexOfNearestStart = findNearestIndex(nearestToStart, circlePoints);
- const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints);
+ const raisedStart = [start[0], start[1] + 0.5, start[2]] as [number, number, number];
+ const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [number, number, number];
- const clockwiseDistance = (indexOfNearestEnd - indexOfNearestStart + 64) % 64;
- const counterClockwiseDistance = (indexOfNearestStart - indexOfNearestEnd + 64) % 64;
- const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance;
+ // const findNearest = (target: [number, number, number]) => {
+ // return circlePoints.reduce((nearest, point) => {
+ // const distance = Math.hypot(target[0] - point[0], target[1] - point[1], target[2] - point[2]);
+ // const nearestDistance = Math.hypot(target[0] - nearest[0], target[1] - nearest[1], target[2] - nearest[2]);
+ // return distance < nearestDistance ? point : nearest;
+ // }, circlePoints[0]);
+ // };
- let arcPoints: [number, number, number][] = [];
+ const nearestToStart = findNearest(raisedStart);
+ const nearestToEnd = findNearest(raisedEnd);
+
+ const indexOfNearestStart = findNearestIndex(nearestToStart, circlePoints);
+ const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints);
+
+ const clockwiseDistance = (indexOfNearestEnd - indexOfNearestStart + 64) % 64;
+ const counterClockwiseDistance = (indexOfNearestStart - indexOfNearestEnd + 64) % 64;
+ const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance;
+
+ let arcPoints: [number, number, number][] = [];
+
+ if (clockwiseIsShorter) {
+ if (indexOfNearestStart <= indexOfNearestEnd) {
+ arcPoints = circlePoints.slice(indexOfNearestStart, indexOfNearestEnd + 1);
+ } else {
+ arcPoints = [
+ ...circlePoints.slice(indexOfNearestStart, 64),
+ ...circlePoints.slice(0, indexOfNearestEnd + 1)
+ ];
+ }
+ } else {
+ if (indexOfNearestStart >= indexOfNearestEnd) {
+ for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) {
+ arcPoints.push(circlePoints[i]);
+ }
+ } else {
+ for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) {
+ arcPoints.push(circlePoints[i]);
+ }
+ }
+ }
+
+ const pathVectors = [
+ new THREE.Vector3(start[0], start[1], start[2]),
+ new THREE.Vector3(start[0], curveHeight, start[2]),
+ new THREE.Vector3(nearestToStart[0], curveHeight, nearestToStart[2]),
+ ...arcPoints.map(point => new THREE.Vector3(point[0], curveHeight, point[2])),
+ new THREE.Vector3(nearestToEnd[0], curveHeight, nearestToEnd[2]),
+ new THREE.Vector3(end[0], curveHeight, end[2]),
+ new THREE.Vector3(end[0], end[1], end[2])
+ ];
+
+
+ const pathSegments: [THREE.Vector3, THREE.Vector3][] = [];
+
+ for (let i = 0; i < pathVectors.length - 1; i++) {
+ pathSegments.push([pathVectors[i], pathVectors[i + 1]]);
+ }
+
+ const segmentDistances = pathSegments.map(([p1, p2]) => p1.distanceTo(p2));
+ segmentDistancesRef.current = segmentDistances;
+ const totalDistance = segmentDistances.reduce((sum, d) => sum + d, 0);
+ totalDistanceRef.current = totalDistance;
+
+ const movementSpeed = speed * armBot.speed;
+ const totalMoveTime = totalDistance / movementSpeed;
+
+ const segmentTimes = segmentDistances.map(distance => (distance / totalDistance) * totalMoveTime);
+
+ setCustomCurvePoints(pathVectors);
- if (clockwiseIsShorter) {
- if (indexOfNearestStart <= indexOfNearestEnd) {
- arcPoints = circlePoints.slice(indexOfNearestStart, indexOfNearestEnd + 1);
- } else {
- arcPoints = [
- ...circlePoints.slice(indexOfNearestStart, 64),
- ...circlePoints.slice(0, indexOfNearestEnd + 1)
- ];
}
- } else {
- if (indexOfNearestStart >= indexOfNearestEnd) {
- for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) {
- arcPoints.push(circlePoints[i]);
- }
- } else {
- for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) {
- arcPoints.push(circlePoints[i]);
- }
+ }, [circlePoints, currentPath]);
+
+ // Frame update for animation
+ useFrame((state, delta) => {
+ if (!ikSolver) return;
+
+ const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
+ if (!bone) return;
+
+ if (isPlaying) {
+ if (isReset) {
+ bone.position.copy(restPosition);
+ setCustomCurvePoints([]);
+ ikSolver.update();
+ }
+ if (!isPaused && customCurvePoints && customCurvePoints.length > 0) {
+ const distances = segmentDistancesRef.current;
+ const totalDistance = totalDistanceRef.current;
+
+ progressRef.current += delta * (speed * armBot.speed);
+ const coveredDistance = progressRef.current;
+
+ let index = 0;
+ let accumulatedDistance = 0;
+
+ while (index < distances.length && coveredDistance > accumulatedDistance + distances[index]) {
+ accumulatedDistance += distances[index];
+ index++;
+ }
+
+ if (index < distances.length) {
+ const startPoint = customCurvePoints[index];
+ const endPoint = customCurvePoints[index + 1];
+ const segmentDistance = distances[index];
+ const t = (coveredDistance - accumulatedDistance) / segmentDistance;
+ if (startPoint && endPoint) {
+ const position = startPoint.clone().lerp(endPoint, t);
+ bone.position.copy(position);
+ }
+ }
+
+ if (progressRef.current >= totalDistance) {
+ HandleCallback();
+ setCurrentPath([]);
+ setCustomCurvePoints([]);
+ curveRef.current = null;
+ progressRef.current = 0;
+ startTimeRef.current = null;
+ }
+
+ ikSolver.update();
+ }
+ } else if (!isPlaying && currentPath.length === 0) {
+ bone.position.copy(restPosition);
}
- }
-
- const pathVectors = [
- new THREE.Vector3(start[0], start[1], start[2]),
- new THREE.Vector3(start[0], curveHeight, start[2]),
- new THREE.Vector3(nearestToStart[0], curveHeight, nearestToStart[2]),
- ...arcPoints.map(point => new THREE.Vector3(point[0], curveHeight, point[2])),
- new THREE.Vector3(nearestToEnd[0], curveHeight, nearestToEnd[2]),
- new THREE.Vector3(end[0], curveHeight, end[2]),
- new THREE.Vector3(end[0], end[1], end[2])
- ];
-
-
- const pathSegments: [THREE.Vector3, THREE.Vector3][] = [];
-
- for (let i = 0; i < pathVectors.length - 1; i++) {
- pathSegments.push([pathVectors[i], pathVectors[i + 1]]);
- }
-
- const segmentDistances = pathSegments.map(([p1, p2]) => p1.distanceTo(p2));
- segmentDistancesRef.current = segmentDistances;
- const totalDistance = segmentDistances.reduce((sum, d) => sum + d, 0);
- totalDistanceRef.current = totalDistance;
-
- const movementSpeed = speed * armBot.speed;
- const totalMoveTime = totalDistance / movementSpeed;
-
- const segmentTimes = segmentDistances.map(distance => (distance / totalDistance) * totalMoveTime);
-
- setCustomCurvePoints(pathVectors);
-
- }
- }, [circlePoints, currentPath]);
-
- // Frame update for animation
- useFrame((state, delta) => {
- if (!ikSolver) return;
-
- const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
- if (!bone) return;
-
- if (isPlaying) {
- if (!isPaused && customCurvePoints && customCurvePoints.length > 0) {
- const distances = segmentDistancesRef.current; // distances between each pair of points
- const totalDistance = totalDistanceRef.current;
-
- progressRef.current += delta * (speed * armBot.speed);
- const coveredDistance = progressRef.current;
-
- let index = 0;
- let accumulatedDistance = 0;
-
- // Find which segment we are currently in
- while (index < distances.length && coveredDistance > accumulatedDistance + distances[index]) {
- accumulatedDistance += distances[index];
- index++;
- }
- if (index < distances.length) {
- const startPoint = customCurvePoints[index];
- const endPoint = customCurvePoints[index + 1];
- const segmentDistance = distances[index];
- const t = (coveredDistance - accumulatedDistance) / segmentDistance;
- if (startPoint && endPoint) {
- const position = startPoint.clone().lerp(endPoint, t);
- bone.position.copy(position);
- }
- }
- if (progressRef.current >= totalDistance) {
- HandleCallback();
- setCurrentPath([]);
- setCustomCurvePoints([]);
- curveRef.current = null;
- progressRef.current = 0;
- startTimeRef.current = null;
- }
-
ikSolver.update();
- }
- } else if ((!isPlaying && currentPath.length === 0) || isReset) {
- bone.position.copy(restPosition);
- ikSolver.update();
- }
+ });
- });
- return (
- <>
- {customCurvePoints && customCurvePoints?.length >= 2 && currentPath && isPlaying && (
-
- [p.x, p.y, p.z] as [number, number, number])}
- color="green"
- lineWidth={5}
- dashed={false}
- />
-
- )}
-
-
-
-
- >
- );
+ return (
+ <>
+ {customCurvePoints && customCurvePoints?.length >= 2 && currentPath && isPlaying && (
+
+ [p.x, p.y, p.z] as [number, number, number])}
+ color="green"
+ lineWidth={5}
+ dashed={false}
+ />
+
+ )}
+
+
+
+
+ >
+ );
}
export default RoboticArmAnimator;
\ No newline at end of file
diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx
index 60d4c33..c67d6f6 100644
--- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx
@@ -97,24 +97,24 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
useEffect(() => {
if (isReset || !isPlaying) {
logStatus(armBot.modelUuid, "Simulation Play Reset Successfully")
- removeCurrentAction(armBot.modelUuid)
setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "idle")
setCurrentPhase("init");
+ setPath([])
+ removeCurrentAction(armBot.modelUuid)
isPausedRef.current = false
pauseTimeRef.current = null
startTime = 0
- const targetBones = ikSolver?.mesh.skeleton.bones.find(
- (b: any) => b.name === targetBone
+ const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone
);
- if (targetBones) {
+ if (targetBones && isPlaying) {
let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition)
if (curve) {
setPath(curve.points.map(point => [point.x, point.y, point.z]));
+ logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.")
}
}
- setReset(false);
- logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.")
+ // setReset(false);
}
}, [isReset, isPlaying])
@@ -127,7 +127,6 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
(b: any) => b.name === targetBone
);
if (isPlaying) {
-
//Moving armBot from initial point to rest position.
if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "init") {
@@ -204,16 +203,16 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
// logStatus(armBot.modelUuid, "Moving armBot from end point to rest position.")
}
} else {
- logStatus(armBot.modelUuid, "Simulation Play Exited")
- setArmBotActive(armBot.modelUuid, false)
- setArmBotState(armBot.modelUuid, "idle")
- setCurrentPhase("init");
- setPath([])
- isPausedRef.current = false
- pauseTimeRef.current = null
- isPausedRef.current = false
- startTime = 0
- removeCurrentAction(armBot.modelUuid)
+ // logStatus(armBot.modelUuid, "Simulation Play Exited")
+ // setArmBotActive(armBot.modelUuid, false)
+ // setArmBotState(armBot.modelUuid, "idle")
+ // setCurrentPhase("init");
+ // setPath([])
+ // isPausedRef.current = false
+ // pauseTimeRef.current = null
+ // isPausedRef.current = false
+ // startTime = 0
+ // removeCurrentAction(armBot.modelUuid)
}
}, [currentPhase, armBot, isPlaying, ikSolver])
@@ -260,6 +259,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
}
const logStatus = (id: string, status: string) => {
+
//
}
diff --git a/app/src/modules/simulation/simulator/simulator.tsx b/app/src/modules/simulation/simulator/simulator.tsx
index b62e75a..320760f 100644
--- a/app/src/modules/simulation/simulator/simulator.tsx
+++ b/app/src/modules/simulation/simulator/simulator.tsx
@@ -1,114 +1,21 @@
+import { useEffect } from 'react';
import { useProductStore } from '../../../store/simulation/useProductStore';
import { useActionHandler } from '../actions/useActionHandler';
function Simulator() {
const { products } = useProductStore();
+ const { handleAction } = useActionHandler();
- const executionOrder = determineExecutionOrder(products);
-
- executionOrder.forEach(point => {
- // useActionHandler(point);
- });
-
- function determineExecutionSequences(products: productsSchema): PointsScheme[][] {
- // Create maps for all points
- const pointMap = new Map();
- const allPoints: PointsScheme[] = [];
-
- // First pass: collect all points
- products.forEach(product => {
- product.eventDatas.forEach(event => {
- if (event.type === 'transfer') {
- event.points.forEach(point => {
- pointMap.set(point.uuid, point);
- allPoints.push(point);
- });
- } else if (event.type === 'vehicle' ||
- event.type === 'machine' ||
- event.type === 'storageUnit' ||
- event.type === 'roboticArm') {
- pointMap.set(event.point.uuid, event.point);
- allPoints.push(event.point);
- }
- });
- });
-
- // Build complete dependency graph
- const dependencyGraph = new Map();
- const reverseDependencyGraph = new Map();
- const triggeredPoints = new Set();
-
- allPoints.forEach(point => {
- const triggers = extractTriggersFromPoint(point);
- const dependencies: string[] = [];
-
- triggers.forEach(trigger => {
- const targetUuid = trigger.triggeredAsset?.triggeredPoint?.pointUuid;
- if (targetUuid && pointMap.has(targetUuid)) {
- dependencies.push(targetUuid);
- triggeredPoints.add(targetUuid);
-
- if (!reverseDependencyGraph.has(targetUuid)) {
- reverseDependencyGraph.set(targetUuid, []);
- }
- reverseDependencyGraph.get(targetUuid)!.push(point.uuid);
- }
- });
-
- dependencyGraph.set(point.uuid, dependencies);
- });
-
- // Identify independent root points (points that trigger others but aren't triggered themselves)
- const rootPoints = allPoints.filter(point => {
- const hasOutgoingTriggers = extractTriggersFromPoint(point).some(
- t => t.triggeredAsset?.triggeredPoint?.pointUuid
- );
- return hasOutgoingTriggers && !triggeredPoints.has(point.uuid);
- });
-
- // For each root point, build its complete trigger chain
- const executionSequences: PointsScheme[][] = [];
-
- function buildSequence(startUuid: string): PointsScheme[] {
- const sequence: PointsScheme[] = [];
- const visited = new Set();
-
- function traverse(uuid: string) {
- if (visited.has(uuid)) return;
- visited.add(uuid);
-
- const point = pointMap.get(uuid);
- if (point) {
- sequence.push(point);
- }
-
- // Follow forward dependencies
- const nextPoints = dependencyGraph.get(uuid) || [];
- nextPoints.forEach(nextUuid => traverse(nextUuid));
- }
-
- traverse(startUuid);
- return sequence;
- }
-
- // Build sequences for all root points
- rootPoints.forEach(root => {
- executionSequences.push(buildSequence(root.uuid));
- });
-
- // Handle any triggered points not reachable from roots (isolated chains)
- const processedPoints = new Set(
- executionSequences.flat().map(p => p.uuid)
- );
-
- allPoints.forEach(point => {
- if (triggeredPoints.has(point.uuid) && !processedPoints.has(point.uuid)) {
- executionSequences.push(buildSequence(point.uuid));
+ useEffect(() => {
+ const executionOrder = determineExecutionOrder(products);
+ executionOrder.forEach(point => {
+ if ('actions' in point) {
+ handleAction(point.actions[0]);
+ } else {
+ handleAction(point.action);
}
});
-
- return executionSequences;
- }
+ }, [products, handleAction]);
function determineExecutionOrder(products: productsSchema): PointsScheme[] {
// Create maps for all events and points
@@ -223,6 +130,106 @@ function Simulator() {
return triggeredPoints;
}
+ function determineExecutionSequences(products: productsSchema): PointsScheme[][] {
+ // Create maps for all points
+ const pointMap = new Map();
+ const allPoints: PointsScheme[] = [];
+
+ // First pass: collect all points
+ products.forEach(product => {
+ product.eventDatas.forEach(event => {
+ if (event.type === 'transfer') {
+ event.points.forEach(point => {
+ pointMap.set(point.uuid, point);
+ allPoints.push(point);
+ });
+ } else if (event.type === 'vehicle' ||
+ event.type === 'machine' ||
+ event.type === 'storageUnit' ||
+ event.type === 'roboticArm') {
+ pointMap.set(event.point.uuid, event.point);
+ allPoints.push(event.point);
+ }
+ });
+ });
+
+ // Build complete dependency graph
+ const dependencyGraph = new Map();
+ const reverseDependencyGraph = new Map();
+ const triggeredPoints = new Set();
+
+ allPoints.forEach(point => {
+ const triggers = extractTriggersFromPoint(point);
+ const dependencies: string[] = [];
+
+ triggers.forEach(trigger => {
+ const targetUuid = trigger.triggeredAsset?.triggeredPoint?.pointUuid;
+ if (targetUuid && pointMap.has(targetUuid)) {
+ dependencies.push(targetUuid);
+ triggeredPoints.add(targetUuid);
+
+ if (!reverseDependencyGraph.has(targetUuid)) {
+ reverseDependencyGraph.set(targetUuid, []);
+ }
+ reverseDependencyGraph.get(targetUuid)!.push(point.uuid);
+ }
+ });
+
+ dependencyGraph.set(point.uuid, dependencies);
+ });
+
+ // Identify independent root points (points that trigger others but aren't triggered themselves)
+ const rootPoints = allPoints.filter(point => {
+ const hasOutgoingTriggers = extractTriggersFromPoint(point).some(
+ t => t.triggeredAsset?.triggeredPoint?.pointUuid
+ );
+ return hasOutgoingTriggers && !triggeredPoints.has(point.uuid);
+ });
+
+ // For each root point, build its complete trigger chain
+ const executionSequences: PointsScheme[][] = [];
+
+ function buildSequence(startUuid: string): PointsScheme[] {
+ const sequence: PointsScheme[] = [];
+ const visited = new Set();
+
+ function traverse(uuid: string) {
+ if (visited.has(uuid)) return;
+ visited.add(uuid);
+
+ const point = pointMap.get(uuid);
+ if (point) {
+ sequence.push(point);
+ }
+
+ // Follow forward dependencies
+ const nextPoints = dependencyGraph.get(uuid) || [];
+ nextPoints.forEach(nextUuid => traverse(nextUuid));
+ }
+
+ traverse(startUuid);
+ return sequence;
+ }
+
+ // Build sequences for all root points
+ rootPoints.forEach(root => {
+ executionSequences.push(buildSequence(root.uuid));
+ });
+
+ // Handle any triggered points not reachable from roots (isolated chains)
+ const processedPoints = new Set(
+ executionSequences.flat().map(p => p.uuid)
+ );
+
+ allPoints.forEach(point => {
+ if (triggeredPoints.has(point.uuid) && !processedPoints.has(point.uuid)) {
+ executionSequences.push(buildSequence(point.uuid));
+ }
+ });
+
+ return executionSequences;
+ }
+
function extractTriggersFromPoint(point: PointsScheme): TriggerSchema[] {
if ('actions' in point) {
return point.actions.flatMap(action => action.triggers);
diff --git a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts
new file mode 100644
index 0000000..6e1f095
--- /dev/null
+++ b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts
@@ -0,0 +1,13 @@
+import { useCallback } from 'react';
+import { useActionHandler } from '../../actions/useActionHandler';
+
+export function useTriggerHandler() {
+
+ const triggerPointActions = useCallback((point: PointsScheme) => {
+ if (!point) return;
+ }, []);
+
+ return {
+ triggerPointActions
+ };
+}
\ No newline at end of file
diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts
index c24ec63..3ed534e 100644
--- a/app/src/store/simulation/useProductStore.ts
+++ b/app/src/store/simulation/useProductStore.ts
@@ -64,6 +64,7 @@ type ProductsStore = {
getPointByUuid: (productId: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
getActionByUuid: (productId: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
getModelUuidByActionUuid: (productId: string, actionUuid: string) => (string) | undefined;
+ getPointUuidByActionUuid: (productId: string, actionUuid: string) => (string) | undefined;
getTriggerByUuid: (productId: string, triggerUuid: string) => TriggerSchema | undefined;
getIsEventInProduct: (productId: string, modelUuid: string) => boolean;
};
@@ -598,6 +599,30 @@ export const useProductStore = create()(
return undefined;
},
+ getPointUuidByActionUuid: (productId, actionUuid) => {
+ const product = get().products.find(p => p.productId === productId);
+ if (!product) return undefined;
+
+ for (const event of product.eventDatas) {
+ if ('points' in event) {
+ for (const point of (event as ConveyorEventSchema).points) {
+ if (point.action?.actionUuid === actionUuid) {
+ return point.uuid;
+ }
+ }
+ } else if ('point' in event) {
+ const point = (event as any).point;
+ if ('action' in point && point.action?.actionUuid === actionUuid) {
+ return point.uuid;
+ } else if ('actions' in point) {
+ const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
+ if (action) return point.uuid;
+ }
+ }
+ }
+ return undefined;
+ },
+
getTriggerByUuid: (productId, triggerUuid) => {
const product = get().products.find(p => p.productId === productId);
if (!product) return undefined;
diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts
index a33056e..3cd7267 100644
--- a/app/src/types/simulationTypes.d.ts
+++ b/app/src/types/simulationTypes.d.ts
@@ -203,4 +203,56 @@ interface MaterialSchema {
};
}
-type MaterialsSchema = MaterialSchema[];
\ No newline at end of file
+type MaterialsSchema = MaterialSchema[];
+
+
+interface ConveyorAction {
+ actionUuid: string;
+ actionName: string;
+ actionType: "default" | "spawn" | "swap" | "delay" | "despawn";
+ material: string;
+ delay: number;
+ spawnInterval: number;
+ spawnCount: number;
+ triggers: TriggerSchema[];
+}
+
+interface VehicleAction {
+ actionUuid: string;
+ actionName: string;
+ actionType: "travel";
+ unLoadDuration: number;
+ loadCapacity: number;
+ steeringAngle: number;
+ pickUpPoint: { position: { x: number; y: number, z: number }, rotation: { x: number; y: number, z: number } } | null;
+ unLoadPoint: { position: { x: number; y: number, z: number }, rotation: { x: number; y: number, z: number } } | null;
+ triggers: TriggerSchema[];
+}
+
+interface RoboticArmAction {
+ actionUuid: string;
+ actionName: string;
+ actionType: "pickAndPlace";
+ process: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; };
+ triggers: TriggerSchema[];
+}
+
+interface MachineAction {
+ actionUuid: string;
+ actionName: string;
+ actionType: "process";
+ processTime: number;
+ swapMaterial: string;
+ triggers: TriggerSchema[];
+}
+
+interface StorageAction {
+ actionUuid: string;
+ actionName: string;
+ actionType: "store";
+ materials: { materialName: string; materialId: string; }[];
+ storageCapacity: number;
+ triggers: TriggerSchema[];
+}
+
+type Action = ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction;