diff --git a/app/src/modules/simulation/conveyor/eventManager/useConveyorEventManager.ts b/app/src/modules/simulation/conveyor/eventManager/useConveyorEventManager.ts new file mode 100644 index 0000000..bdc014c --- /dev/null +++ b/app/src/modules/simulation/conveyor/eventManager/useConveyorEventManager.ts @@ -0,0 +1,65 @@ +import { useEffect, useRef } from 'react'; +import { useFrame } from '@react-three/fiber'; +import { useConveyorStore } from '../../../../store/simulation/useConveyorStore'; + +type ConveyorCallback = { + conveyorId: string; + callback: () => void; +}; + +export function useConveyorEventManager() { + const { getConveyorById } = useConveyorStore(); + const callbacksRef = useRef([]); + const isMonitoringRef = useRef(false); + + // Add a new conveyor to monitor + const addConveyorToMonitor = (conveyorId: string, callback: () => void) => { + // Avoid duplicates + if (!callbacksRef.current.some((entry) => entry.conveyorId === conveyorId)) { + callbacksRef.current.push({ conveyorId, callback }); + } + + // Start monitoring if not already running + if (!isMonitoringRef.current) { + isMonitoringRef.current = true; + } + }; + + // Remove a conveyor from monitoring + const removeConveyorFromMonitor = (conveyorId: string) => { + callbacksRef.current = callbacksRef.current.filter( + (entry) => entry.conveyorId !== conveyorId + ); + + // Stop monitoring if no more conveyors to track + if (callbacksRef.current.length === 0) { + isMonitoringRef.current = false; + } + }; + + // Check conveyor states every frame + useFrame(() => { + if (!isMonitoringRef.current || callbacksRef.current.length === 0) return; + + callbacksRef.current.forEach(({ conveyorId, callback }) => { + const conveyor = getConveyorById(conveyorId); + if (conveyor?.isPaused === false) { + callback(); + removeConveyorFromMonitor(conveyorId); // Remove after triggering + } + }); + }); + + // Cleanup on unmount + useEffect(() => { + return () => { + callbacksRef.current = []; + isMonitoringRef.current = false; + }; + }, []); + + return { + addConveyorToMonitor, + removeConveyorFromMonitor, + }; +} \ No newline at end of file diff --git a/app/src/modules/simulation/conveyor/instances/conveyorInstance/conveyorInstance.tsx b/app/src/modules/simulation/conveyor/instances/conveyorInstance/conveyorInstance.tsx index fa1b33b..8cd6db9 100644 --- a/app/src/modules/simulation/conveyor/instances/conveyorInstance/conveyorInstance.tsx +++ b/app/src/modules/simulation/conveyor/instances/conveyorInstance/conveyorInstance.tsx @@ -2,43 +2,37 @@ import React, { useEffect } from 'react' import { useMaterialStore } from '../../../../../store/simulation/useMaterialStore'; import { useConveyorStore } from '../../../../../store/simulation/useConveyorStore'; import { useResetButtonStore } from '../../../../../store/usePlayButtonStore'; -import { findConveyorInSequences } from '../../../simulator/functions/findConveyorInSequences'; -import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore'; -import { useProductStore } from '../../../../../store/simulation/useProductStore'; function ConveyorInstance({ conveyor }: { conveyor: ConveyorStatus }) { - const { getProductById } = useProductStore(); - const { selectedProduct } = useSelectedProduct(); const { materials, getMaterialsByCurrentModelUuid } = useMaterialStore(); const { isReset } = useResetButtonStore(); const { setConveyorPaused } = useConveyorStore(); useEffect(() => { - const product = getProductById(selectedProduct.productId); - if (!product) return; - - const sequenceInfo = findConveyorInSequences(product, conveyor.modelUuid); - if (!sequenceInfo) return; - - const { currentSubSequence } = sequenceInfo; const conveyorMaterials = getMaterialsByCurrentModelUuid(conveyor.modelUuid); + if (conveyorMaterials && conveyorMaterials?.length > 0) { - if (conveyorMaterials && conveyorMaterials.length > 0) { - const shouldPauseSubsequence = currentSubSequence.some(subConveyor => { - if (subConveyor.type !== 'transfer') return false; - const subMaterials = getMaterialsByCurrentModelUuid(subConveyor.modelUuid); - return subMaterials?.some(m => m.isPaused) ?? false; - }); + const hasPausedMaterials = conveyorMaterials.some(material => material.isPaused); - currentSubSequence.forEach(subConveyor => { - if (subConveyor.type === 'transfer') { - setConveyorPaused(subConveyor.modelUuid, shouldPauseSubsequence); - } - }); + if (hasPausedMaterials) { + setConveyorPaused(conveyor.modelUuid, true); + } else { + setConveyorPaused(conveyor.modelUuid, false); + } + }else{ + setConveyorPaused(conveyor.modelUuid, false); } - }, [materials, conveyor.modelUuid, getMaterialsByCurrentModelUuid, setConveyorPaused, isReset, selectedProduct.productId, getProductById]); - return null; -} + }, [materials, conveyor.modelUuid, getMaterialsByCurrentModelUuid, setConveyorPaused, isReset]); -export default React.memo(ConveyorInstance); \ No newline at end of file + useEffect(() => { + // console.log('conveyor: ', conveyor); + }, [conveyor]) + + return ( + <> + + ) +}; + +export default ConveyorInstance \ No newline at end of file diff --git a/app/src/modules/simulation/roboticArm/eventManager/useArmBotEventManager.ts b/app/src/modules/simulation/roboticArm/eventManager/useArmBotEventManager.ts new file mode 100644 index 0000000..97593b4 --- /dev/null +++ b/app/src/modules/simulation/roboticArm/eventManager/useArmBotEventManager.ts @@ -0,0 +1,65 @@ +import { useEffect, useRef } from 'react'; +import { useFrame } from '@react-three/fiber'; +import { useArmBotStore } from '../../../../store/simulation/useArmBotStore'; + +type ArmBotCallback = { + armBotId: string; + callback: () => void; +}; + +export function useArmBotEventManager() { + const { getArmBotById } = useArmBotStore(); + const callbacksRef = useRef([]); + const isMonitoringRef = useRef(false); + + // Add a new armbot to monitor + const addArmBotToMonitor = (armBotId: string, callback: () => void) => { + // Avoid duplicates + if (!callbacksRef.current.some((entry) => entry.armBotId === armBotId)) { + callbacksRef.current.push({ armBotId, callback }); + } + + // Start monitoring if not already running + if (!isMonitoringRef.current) { + isMonitoringRef.current = true; + } + }; + + // Remove an armbot from monitoring (e.g., when unmounted) + const removeArmBotFromMonitor = (armBotId: string) => { + callbacksRef.current = callbacksRef.current.filter( + (entry) => entry.armBotId !== armBotId + ); + + // Stop monitoring if no more armbots to track + if (callbacksRef.current.length === 0) { + isMonitoringRef.current = false; + } + }; + + // Check armbot states every frame + useFrame(() => { + if (!isMonitoringRef.current || callbacksRef.current.length === 0) return; + + callbacksRef.current.forEach(({ armBotId, callback }) => { + const armBot = getArmBotById(armBotId); + if (armBot?.isActive === false && armBot?.state === 'idle') { + callback(); + removeArmBotFromMonitor(armBotId); // Remove after triggering + } + }); + }); + + // Cleanup on unmount (optional, since useFrame auto-cleans) + useEffect(() => { + return () => { + callbacksRef.current = []; + isMonitoringRef.current = false; + }; + }, []); + + return { + addArmBotToMonitor, + removeArmBotFromMonitor, + }; +} \ 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 1c8c447..e07a4ab 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -27,15 +27,14 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { const pauseTimeRef = useRef(null); const isPausedRef = useRef(false); const isSpeedRef = useRef(null); - const isIdleRef = useRef(false); let startTime: number; - const { armBots, setArmBotActive, setArmBotState, removeCurrentAction, incrementActiveTime, incrementIdleTime } = useArmBotStore(); + const { setArmBotActive, setArmBotState, removeCurrentAction, incrementActiveTime, incrementIdleTime } = useArmBotStore(); const { decrementVehicleLoad, removeLastMaterial } = useVehicleStore(); const { removeLastMaterial: removeLastStorageMaterial, updateCurrentLoad } = useStorageUnitStore(); const { setIsVisible, setIsPaused, getMaterialById } = useMaterialStore(); const { selectedProduct } = useSelectedProduct(); - const { getActionByUuid, getEventByActionUuid, getEventByModelUuid, getProductById } = useProductStore(); + const { getActionByUuid, getEventByActionUuid, getEventByModelUuid } = useProductStore(); const { triggerPointActions } = useTriggerHandler(); const { isPlaying } = usePlayButtonStore(); const { isReset } = useResetButtonStore(); @@ -47,7 +46,6 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { const animationFrameIdRef = useRef(null); const previousTimeRef = useRef(null); - const checkActiveRoboticArms = useCheckActiveRoboticArmsInSubsequence(); const lastRemoved = useRef<{ type: string, materialId: string } | null>(null); @@ -95,15 +93,6 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { if (!model) return; if (model.type === 'transfer') { setIsVisible(armBot.currentAction.materialId || '', true); - - const product = getProductById(selectedProduct.productId); - if (product) { - const result = checkActiveRoboticArms(product, armBot.modelUuid); - // console.log('result: ', result); - // if (result?.hasActiveRoboticArm) { - // lastRemoved.current = null; - // } - } } else if (model.type === 'machine') { // } else if (model.type === 'vehicle') { @@ -116,6 +105,14 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { triggerPointActions(action, armBot.currentAction.materialId) removeCurrentAction(armBot.modelUuid) } + + if (lastRemoved.current) { + if (lastRemoved.current.type === 'transfer') { + setIsPaused(lastRemoved.current.materialId, true) + } else { + setIsPaused(lastRemoved.current.materialId, false) + } + } } } @@ -386,13 +383,6 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { setCurrentPhase("rest"); setPath([]) - if (lastRemoved.current) { - if (lastRemoved.current.type === 'transfer') { - setIsPaused(lastRemoved.current.materialId, true) - } else { - setIsPaused(lastRemoved.current.materialId, false) - } - } } } diff --git a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts index 7de5d29..daf9b4f 100644 --- a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts +++ b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts @@ -7,12 +7,18 @@ import { useArmBotStore } from '../../../../store/simulation/useArmBotStore'; import { useVehicleStore } from '../../../../store/simulation/useVehicleStore'; import { useMachineStore } from '../../../../store/simulation/useMachineStore'; import { useStorageUnitStore } from '../../../../store/simulation/useStorageUnitStore'; +import { useArmBotEventManager } from '../../roboticArm/eventManager/useArmBotEventManager'; +import { useConveyorStore } from '../../../../store/simulation/useConveyorStore'; +import { useConveyorEventManager } from '../../conveyor/eventManager/useConveyorEventManager'; export function useTriggerHandler() { const { handleAction } = useActionHandler(); const { selectedProduct } = useSelectedProduct(); const { getEventByTriggerUuid, getEventByModelUuid, getActionByUuid, getModelUuidByActionUuid } = useProductStore(); const { getArmBotById } = useArmBotStore(); + const { getConveyorById } = useConveyorStore(); + const { addArmBotToMonitor } = useArmBotEventManager(); + const { addConveyorToMonitor } = useConveyorEventManager(); const { getVehicleById } = useVehicleStore(); const { getMachineById } = useMachineStore(); const { getStorageUnitById } = useStorageUnitStore(); @@ -144,6 +150,10 @@ export function useTriggerHandler() { } else { // Event Manager Needed + setIsPaused(materialId, true); + addArmBotToMonitor(armBot.modelUuid, + () => handleAction(action, materialId) + ); } } @@ -320,12 +330,42 @@ export function useTriggerHandler() { if (armBot.isActive === false && armBot.state === 'idle') { // Handle current action from arm bot - handleAction(action, materialId); + const model = getEventByModelUuid(selectedProduct.productId, action.triggers[0].triggeredAsset?.triggeredModel.modelUuid || ''); + if (model?.type === 'transfer') { + const conveyor = getConveyorById(action.triggers[0].triggeredAsset?.triggeredModel.modelUuid || ''); + if (conveyor) { + addConveyorToMonitor(conveyor.modelUuid, + () => { + handleAction(action, materialId) + } + ) + // handleAction(action, materialId) + } + } else { + handleAction(action, materialId) + } } else { // Event Manager Needed - + addArmBotToMonitor(armBot.modelUuid, + () => { + const model = getEventByModelUuid(selectedProduct.productId, action.triggers[0].triggeredAsset?.triggeredModel.modelUuid || ''); + if (model?.type === 'transfer') { + const conveyor = getConveyorById(action.triggers[0].triggeredAsset?.triggeredModel.modelUuid || ''); + if (conveyor) { + addConveyorToMonitor(conveyor.modelUuid, + () => { + handleAction(action, materialId) + } + ) + // handleAction(action, materialId) + } + } else { + handleAction(action, materialId) + } + } + ); } } } @@ -342,8 +382,6 @@ export function useTriggerHandler() { const material = getMaterialById(materialId); if (material) { - // setIsPaused(material.materialId, false); - setPreviousLocation(material.materialId, { modelUuid: material.current.modelUuid, pointUuid: material.current.pointUuid, @@ -410,6 +448,15 @@ export function useTriggerHandler() { } } + } else if (model?.type === 'transfer') { + const conveyor = getConveyorById(action.triggers[0].triggeredAsset?.triggeredModel.modelUuid); + if (conveyor) { + setNextLocation(material.materialId, { + modelUuid: action.triggers[0].triggeredAsset?.triggeredModel.modelUuid, + pointUuid: action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid, + }) + handleAction(action, material.materialId); + } } else { setNextLocation(material.materialId, { modelUuid: action.triggers[0].triggeredAsset?.triggeredModel.modelUuid,