import { useCallback, useEffect, useRef, useState } from 'react'; import * as THREE from 'three'; import { NavMeshQuery } from '@recast-navigation/core'; import { useNavMesh } from '../../../../../store/builder/store'; import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler'; import { useSceneContext } from '../../../../scene/sceneContext'; import { useProductContext } from '../../../products/productContext'; import HumanAnimator from './animator/humanAnimator'; function HumanInstance({ human }: { human: HumanStatus }) { const { navMesh } = useNavMesh(); const { isPlaying } = usePlayButtonStore(); const { materialStore, armBotStore, conveyorStore, vehicleStore, humanStore, storageUnitStore, productStore } = useSceneContext(); const { removeMaterial, setEndTime } = materialStore(); const { getStorageUnitById } = storageUnitStore(); const { getArmBotById } = armBotStore(); const { getConveyorById } = conveyorStore(); const { getVehicleById } = vehicleStore(); const { triggerPointActions } = useTriggerHandler(); const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = productStore(); const { selectedProductStore } = useProductContext(); const { selectedProduct } = selectedProductStore(); const { humans, setHumanActive, setHumanState, setHumanPicking, clearCurrentMaterials, setHumanLoad, decrementHumanLoad, removeLastMaterial, getLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = humanStore(); const [currentPhase, setCurrentPhase] = useState('init'); const [path, setPath] = useState<[number, number, number][]>([]); const pauseTimeRef = useRef(null); const idleTimeRef = useRef(0); const activeTimeRef = useRef(0); const isPausedRef = useRef(false); const isSpeedRef = useRef(0); let startTime: number; let fixedInterval: number; const { speed } = useAnimationPlaySpeed(); const { isPaused } = usePauseButtonStore(); const previousTimeRef = useRef(null); const animationFrameIdRef = useRef(null); useEffect(() => { isPausedRef.current = isPaused; }, [isPaused]); useEffect(() => { isSpeedRef.current = speed; }, [speed]); const computePath = useCallback( (start: any, end: any) => { try { const navMeshQuery = new NavMeshQuery(navMesh); const { path: segmentPath } = navMeshQuery.computePath(start, end); if ( segmentPath.length > 0 && Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(end.x) && Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(end.z) ) { return segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || []; } else { console.log("There is no path here...Choose valid path") const { path: segmentPaths } = navMeshQuery.computePath(start, start); return segmentPaths.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || []; } } catch { console.error("Failed to compute path"); return []; } }, [navMesh] ); function humanStatus(modelId: string, status: string) { // console.log(`${modelId} , ${status}`); } function reset() { setCurrentPhase('init'); setHumanActive(human.modelUuid, false); setHumanPicking(human.modelUuid, false); setHumanState(human.modelUuid, 'idle'); setHumanLoad(human.modelUuid, 0); setPath([]); startTime = 0; isPausedRef.current = false; pauseTimeRef.current = 0; resetTime(human.modelUuid) activeTimeRef.current = 0 idleTimeRef.current = 0 previousTimeRef.current = null if (animationFrameIdRef.current !== null) { cancelAnimationFrame(animationFrameIdRef.current) animationFrameIdRef.current = null } } useEffect(() => { if (isPlaying) { } else { reset() } // eslint-disable-next-line react-hooks/exhaustive-deps }, [human, currentPhase, path, isPlaying]); return ( <> ) } export default HumanInstance