diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx index 17e8363..e823697 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx @@ -40,15 +40,10 @@ function HumanMechanics() { selectedEventData.selectedPoint ) as HumanPointSchema | undefined; - if (point?.actions) { + if (point?.action) { setSelectedPointData(point); - if (point.actions.length > 0) { - setSelectedAction(point.actions[0].actionUuid, point.actions[0].actionName); - const asset = getAssetById(selectedEventData.data.modelUuid); - if (asset && asset.animations) { - setAnimationOptions(asset.animations) - } - } + setCurrentAction(point.action); + setSelectedAction(point.action.actionUuid, point.action.actionName); } } else { clearSelectedAction(); @@ -57,31 +52,17 @@ function HumanMechanics() { useEffect(() => { if (selectedEventData && selectedProduct.productUuid) { - const event = getEventByModelUuid( - selectedProduct.productUuid, - selectedEventData.data.modelUuid - ) as HumanEventSchema | undefined; - - if (event?.speed !== undefined) { - setSpeed(event.speed.toString()); - } - const point = getPointByUuid( selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint ) as HumanPointSchema | undefined; - if (point?.actions) { + if (point?.action) { setSelectedPointData(point); - const action = point.actions.find((a) => a.actionUuid === selectedAction.actionId); - if (action) { - setCurrentAction(action); - setActiveOption(action.actionType as "worker"); - if (action.animationSequences.length > 0) { - setSelectedAnimation(action.animationSequences[0]); - } - } + setCurrentAction(point.action); + setActiveOption(point.action.actionType); + setSelectedAction(point.action.actionUuid, point.action.actionName); } } else { clearSelectedAction(); @@ -108,17 +89,8 @@ function HumanMechanics() { const handleSelectActionType = (actionType: string) => { if (!selectedAction.actionId || !currentAction || !selectedPointData) return; - const updatedAction = { - ...currentAction, - actionType: actionType as "worker" - }; - - const updatedPoint = { - ...selectedPointData, - actions: selectedPointData.actions.map(action => - action.actionUuid === selectedAction.actionId ? updatedAction : action - ) - }; + const updatedAction = { ...currentAction, actionType: actionType as "worker" }; + const updatedPoint = { ...selectedPointData, action: updatedAction }; const event = updateAction( selectedProduct.productUuid, @@ -134,43 +106,6 @@ function HumanMechanics() { setSelectedPointData(updatedPoint); }; - const handleChooseAnimation = (animationOption: string) => { - if (!selectedAction.actionId || !currentAction || !selectedAnimation || !selectedPointData) return; - - const updatedAnimation = { - ...selectedAnimation, - animation: animationOption - }; - - const updatedAction = { - ...currentAction, - animationSequences: currentAction.animationSequences.map(anim => - anim.animationUuid === selectedAnimation.animationUuid ? updatedAnimation : anim - ) - }; - - const updatedPoint = { - ...selectedPointData, - actions: selectedPointData.actions.map(action => - action.actionUuid === selectedAction.actionId ? updatedAction : action - ) - }; - - const event = updateAction( - selectedProduct.productUuid, - selectedAction.actionId, - updatedAction - ); - - if (event) { - updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); - } - - setCurrentAction(updatedAction); - setSelectedAnimation(updatedAnimation); - setSelectedPointData(updatedPoint); - }; - const handleSpeedChange = (value: string) => { if (!selectedEventData) return; @@ -195,31 +130,14 @@ function HumanMechanics() { setSpeed(value); }; - const handleClearPoints = (animationUuid: string) => { + const handleClearPoints = () => { if (!currentAction || !selectedPointData || !selectedAction.actionId) return; - const updatedAnimation = currentAction.animationSequences.find(anim => - anim.animationUuid === animationUuid - ); + const updatedAction = { ...currentAction }; + delete updatedAction.pickUpPoint; + delete updatedAction.dropPoint; - if (!updatedAnimation) return; - - delete updatedAnimation.startPoint; - delete updatedAnimation.endPoint; - - const updatedAction = { - ...currentAction, - animationSequences: currentAction.animationSequences.map(anim => - anim.animationUuid === animationUuid ? updatedAnimation : anim - ) - }; - - const updatedPoint = { - ...selectedPointData, - actions: selectedPointData.actions.map(action => - action.actionUuid === selectedAction.actionId ? updatedAction : action - ) - }; + const updatedPoint = { ...selectedPointData, action: updatedAction }; const event = updateAction( selectedProduct.productUuid, @@ -233,9 +151,6 @@ function HumanMechanics() { setCurrentAction(updatedAction); setSelectedPointData(updatedPoint); - if (selectedAnimation?.animationUuid === animationUuid) { - setSelectedAnimation(updatedAnimation); - } }; const handleAddAction = () => { @@ -243,16 +158,8 @@ function HumanMechanics() { const newAction: HumanAction = { actionUuid: MathUtils.generateUUID(), - actionName: `Action ${selectedPointData.actions.length + 1}`, + actionName: `Action`, actionType: "worker", - animationSequences: [ - { - animationUuid: MathUtils.generateUUID(), - animationName: 'Animation 1', - animationType: 'behaviour', - animation: null - } - ], loadCapacity: 1, triggers: [], }; @@ -268,217 +175,27 @@ function HumanMechanics() { updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); } - const updatedPoint = { ...selectedPointData, actions: [...selectedPointData.actions, newAction] }; + const updatedPoint = { ...selectedPointData, action: newAction }; setSelectedPointData(updatedPoint); setSelectedAction(newAction.actionUuid, newAction.actionName); }; - const handleDeleteAction = (actionUuid: string) => { + const handleDeleteAction = () => { if (!selectedPointData) return; - const event = removeAction(selectedProduct.productUuid, actionUuid); - - if (event) { - updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); - } - - const index = selectedPointData.actions.findIndex((a) => a.actionUuid === actionUuid); - const newActions = selectedPointData.actions.filter((a) => a.actionUuid !== actionUuid); - const updatedPoint = { ...selectedPointData, actions: newActions }; - setSelectedPointData(updatedPoint); - - if (selectedAction.actionId === actionUuid) { - const nextAction = newActions[index] || newActions[index - 1]; - if (nextAction) { - setSelectedAction(nextAction.actionUuid, nextAction.actionName); - } else { - clearSelectedAction(); - } - } - }; - - const handleAddAnimation = () => { - if (!currentAction || !selectedPointData || !selectedAction.actionId) return; - - const newAnimation = { - animationUuid: MathUtils.generateUUID(), - animationName: `Animation ${currentAction.animationSequences.length + 1}`, - animationType: 'behaviour' as "behaviour", - animation: null - }; - - const updatedAction = { - ...currentAction, - animationSequences: [...currentAction.animationSequences, newAnimation] - }; - - const updatedPoint = { - ...selectedPointData, - actions: selectedPointData.actions.map(action => - action.actionUuid === selectedAction.actionId ? updatedAction : action - ) - }; - - const event = updateAction( + const event = removeAction( selectedProduct.productUuid, - selectedAction.actionId, - updatedAction + selectedPointData.action.actionUuid ); if (event) { updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); } - setCurrentAction(updatedAction); + const updatedPoint = { ...selectedPointData, action: undefined as any }; setSelectedPointData(updatedPoint); - setSelectedAnimation(newAnimation); - }; - - const handleRemoveAnimation = (animationUuid: string) => { - if (!currentAction || !selectedPointData || !selectedAction.actionId) return; - - const updatedAction = { - ...currentAction, - animationSequences: currentAction.animationSequences.filter( - anim => anim.animationUuid !== animationUuid - ) - }; - - const updatedPoint = { - ...selectedPointData, - actions: selectedPointData.actions.map(action => - action.actionUuid === selectedAction.actionId ? updatedAction : action - ) - }; - - const event = updateAction( - selectedProduct.productUuid, - selectedAction.actionId, - updatedAction - ); - - if (event) { - updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); - } - - setCurrentAction(updatedAction); - setSelectedPointData(updatedPoint); - - if (selectedAnimation?.animationUuid === animationUuid) { - setSelectedAnimation(updatedAction.animationSequences[0] || undefined); - } - }; - - const handleAnimationTypeChange = (animationUuid: string, newType: "behaviour" | "animatedTravel") => { - if (!currentAction || !selectedPointData || !selectedAction.actionId) return; - - const updatedAnimationSequences = currentAction.animationSequences.map(anim => { - if (anim.animationUuid === animationUuid) { - const updatedAnim = { - ...anim, - animationType: newType - }; - - delete updatedAnim.startPoint; - delete updatedAnim.endPoint; - - return updatedAnim; - } - return anim; - }); - - const updatedAction = { - ...currentAction, - animationSequences: updatedAnimationSequences - }; - - const updatedPoint = { - ...selectedPointData, - actions: selectedPointData.actions.map(action => - action.actionUuid === selectedAction.actionId ? updatedAction : action - ) - }; - - const event = updateAction( - selectedProduct.productUuid, - selectedAction.actionId, - updatedAction - ); - - if (event) { - updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); - } - - setCurrentAction(updatedAction); - setSelectedPointData(updatedPoint); - - if (selectedAnimation?.animationUuid === animationUuid) { - const updatedAnimation = updatedAnimationSequences.find(anim => - anim.animationUuid === animationUuid - ); - if (updatedAnimation) { - setSelectedAnimation(updatedAnimation); - } - } - }; - - const handleAnimationSelect = (animationUuid: string) => { - if (!currentAction || !selectedAction.actionId) return; - - const animation = currentAction.animationSequences.find( - anim => anim.animationUuid === animationUuid - ); - - if (animation) { - setSelectedAnimation(animation); - } - }; - - const handleRenameAnimation = (animationUuid: string, newName: string) => { - if (!currentAction || !selectedPointData || !selectedAction.actionId) return; - - const updatedAnimation = currentAction.animationSequences.find(anim => - anim.animationUuid === animationUuid - ); - - if (!updatedAnimation) return; - - const renamedAnimation = { ...updatedAnimation, animationName: newName }; - - const updatedAction = { - ...currentAction, - animationSequences: currentAction.animationSequences.map(anim => - anim.animationUuid === animationUuid ? renamedAnimation : anim - ) - }; - - const updatedPoint = { - ...selectedPointData, - actions: selectedPointData.actions.map(action => - action.actionUuid === selectedAction.actionId ? updatedAction : action - ) - }; - - const event = updateAction( - selectedProduct.productUuid, - selectedAction.actionId, - updatedAction - ); - - if (event) { - updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); - } - - setCurrentAction(updatedAction); - setSelectedPointData(updatedPoint); - if (selectedAnimation?.animationUuid === animationUuid) { - setSelectedAnimation(renamedAnimation); - } - }; - - const availableActions = { - defaultOption: "worker", - options: ["worker"], + clearSelectedAction(); + setCurrentAction(undefined); }; return ( @@ -503,7 +220,7 @@ function HumanMechanics() {
@@ -511,69 +228,20 @@ function HumanMechanics() { {selectedAction.actionId && currentAction && (
- +
- - {selectedAnimation && ( - <> -
- -
-
- - handleAnimationTypeChange( - selectedAnimation.animationUuid, - type as "behaviour" | "animatedTravel" - ) - } - /> - - - {selectedAnimation.animationType === "animatedTravel" && ( - handleClearPoints(selectedAnimation.animationUuid)} - /> - )} -
- - )} +
- +
)} diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx index a761d39..547445e 100644 --- a/app/src/modules/builder/asset/assetsGroup.tsx +++ b/app/src/modules/builder/asset/assetsGroup.tsx @@ -256,23 +256,14 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) { uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(), position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0], rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0], - actions: [ - { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Action 1", - actionType: "worker", - animationSequences: [ - { - animationUuid: THREE.MathUtils.generateUUID(), - animationName: 'Animation 1', - animationType: 'behaviour', - animation: null - } - ], - loadCapacity: 1, - triggers: [] - } - ] + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "worker", + loadCapacity: 1, + triggers: [] + } + } } addEvent(humanEvent); diff --git a/app/src/modules/builder/asset/functions/addAssetModel.ts b/app/src/modules/builder/asset/functions/addAssetModel.ts index 43c4b8a..8a09bb7 100644 --- a/app/src/modules/builder/asset/functions/addAssetModel.ts +++ b/app/src/modules/builder/asset/functions/addAssetModel.ts @@ -373,23 +373,13 @@ async function handleModelLoad( uuid: THREE.MathUtils.generateUUID(), position: [data.points[0].x, data.points[0].y, data.points[0].z], rotation: [0, 0, 0], - actions: [ - { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Action 1", - actionType: "worker", - animationSequences: [ - { - animationUuid: THREE.MathUtils.generateUUID(), - animationName: 'Animation 1', - animationType: 'behaviour', - animation: null - } - ], - loadCapacity: 1, - triggers: [] - } - ] + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "worker", + loadCapacity: 1, + triggers: [] + } } } diff --git a/app/src/modules/simulation/events/points/functions/handleAddEventToProduct.ts b/app/src/modules/simulation/events/points/functions/handleAddEventToProduct.ts index 9439c3c..0ba13a7 100644 --- a/app/src/modules/simulation/events/points/functions/handleAddEventToProduct.ts +++ b/app/src/modules/simulation/events/points/functions/handleAddEventToProduct.ts @@ -30,7 +30,7 @@ export const handleAddEventToProduct = ({ projectId: projectId || '', eventDatas: event }).then((data) => { - console.log(data); + // console.log(data); }) if (clearSelectedAsset) { diff --git a/app/src/modules/simulation/events/triggerConnections/triggerConnector.tsx b/app/src/modules/simulation/events/triggerConnections/triggerConnector.tsx index 918007a..ec7406c 100644 --- a/app/src/modules/simulation/events/triggerConnections/triggerConnector.tsx +++ b/app/src/modules/simulation/events/triggerConnections/triggerConnector.tsx @@ -155,8 +155,8 @@ function TriggerConnector() { // Handle Human point else if (event.type === "human" && 'point' in event) { const point = event.point; - point.actions?.forEach(action => { - action.triggers?.forEach(trigger => { + if (point.action?.triggers) { + point.action.triggers.forEach(trigger => { if (trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint) { newConnections.push({ id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`, @@ -166,7 +166,7 @@ function TriggerConnector() { }); } }); - }); + } } }); diff --git a/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts b/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts index 1ab16f7..94ce8b3 100644 --- a/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts +++ b/app/src/modules/simulation/human/eventManager/useHumanEventManager.ts @@ -5,7 +5,6 @@ import { useSceneContext } from '../../../scene/sceneContext'; type HumanCallback = { humanId: string; - actionId: string; callback: () => void; }; @@ -25,10 +24,10 @@ export function useHumanEventManager() { }, [isReset]) // Add a new human to monitor - const addHumanToMonitor = (humanId: string, actionId: string, callback: () => void) => { + const addHumanToMonitor = (humanId: string, callback: () => void) => { // Avoid duplicates if (!callbacksRef.current.some((entry) => entry.humanId === humanId)) { - callbacksRef.current.push({ humanId, actionId, callback }); + callbacksRef.current.push({ humanId, callback }); } // Start monitoring if not already running @@ -53,11 +52,9 @@ export function useHumanEventManager() { useFrame(() => { if (!isMonitoringRef.current || callbacksRef.current.length === 0 || !isPlaying || isPaused) return; - callbacksRef.current.forEach(({ humanId, actionId, callback }) => { + callbacksRef.current.forEach(({ humanId, callback }) => { const human = getHumanById(humanId); - if (!human) return; - const action = human.point.actions.find((action) => action.actionUuid === actionId); - if (action && human.isActive === false && human.state === 'idle' && human.isPicking && human.currentLoad < action.loadCapacity) { + if (human && human.isActive === false && human.state === 'idle' && human.isPicking && human.currentLoad < human.point.action.loadCapacity) { callback(); removeHumanFromMonitor(humanId); // Remove after triggering } diff --git a/app/src/modules/simulation/human/human.tsx b/app/src/modules/simulation/human/human.tsx index 49c9435..767269c 100644 --- a/app/src/modules/simulation/human/human.tsx +++ b/app/src/modules/simulation/human/human.tsx @@ -16,12 +16,7 @@ function Human() { useEffect(() => { if (selectedEventSphere) { const selectedHuman = getHumanById(selectedEventSphere.userData.modelUuid); - if (selectedHuman && - selectedHuman.point.actions.some((action) => - action.animationSequences.some((animation) => - animation.animationUuid === selectedAnimation?.animationUuid && animation.animationType === 'animatedTravel' - ) - )) { + if (selectedHuman) { setIsHumanSelected(true); } else { setIsHumanSelected(false); diff --git a/app/src/modules/simulation/human/instances/animator/humanAnimator.tsx b/app/src/modules/simulation/human/instances/animator/humanAnimator.tsx new file mode 100644 index 0000000..82934eb --- /dev/null +++ b/app/src/modules/simulation/human/instances/animator/humanAnimator.tsx @@ -0,0 +1,170 @@ +import { useEffect, useRef, useState } from 'react' +import { useFrame, useThree } from '@react-three/fiber'; +import * as THREE from 'three'; +import { Line } from '@react-three/drei'; +import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; +import { useSceneContext } from '../../../../scene/sceneContext'; + +interface HumanAnimatorProps { + path: [number, number, number][]; + handleCallBack: () => void; + reset: () => void; + startUnloadingProcess: () => void; + currentPhase: string; + human: HumanStatus; +} + +function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, startUnloadingProcess }: Readonly) { + const { humanStore } = useSceneContext(); + const { getHumanById } = humanStore(); + const { isPaused } = usePauseButtonStore(); + const { isPlaying } = usePlayButtonStore(); + const { speed } = useAnimationPlaySpeed(); + const { isReset, setReset } = useResetButtonStore(); + const progressRef = useRef(0); + const movingForward = useRef(true); + const completedRef = useRef(false); + const [objectRotation, setObjectRotation] = useState<[number, number, number] | null>(human.point?.action?.pickUpPoint?.rotation || [0, 0, 0]) + const [restRotation, setRestingRotation] = useState(true); + const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); + const { scene } = useThree(); + + useEffect(() => { + if (currentPhase === 'init-pickup' && path.length > 0) { + setCurrentPath(path); + setObjectRotation(human.point.action.pickUpPoint?.rotation ?? null) + } else if (currentPhase === 'pickup-drop' && path.length > 0) { + setObjectRotation(human.point.action?.dropPoint?.rotation ?? null) + setCurrentPath(path); + } else if (currentPhase === 'drop-pickup' && path.length > 0) { + setObjectRotation(human.point.action?.pickUpPoint?.rotation ?? null) + setCurrentPath(path); + } + }, [currentPhase, path, objectRotation]); + + useEffect(() => { + completedRef.current = false; + }, [currentPath]); + + useEffect(() => { + if (isReset || !isPlaying) { + reset(); + setCurrentPath([]); + completedRef.current = false; + movingForward.current = true; + progressRef.current = 0; + setReset(false); + setRestingRotation(true); + const object = scene.getObjectByProperty('uuid', human.modelUuid); + const humanData = getHumanById(human.modelUuid); + if (object && humanData) { + object.position.set(humanData.position[0], humanData.position[1], humanData.position[2]); + object.rotation.set(humanData.rotation[0], humanData.rotation[1], humanData.rotation[2]); + } + } + }, [isReset, isPlaying]) + + const lastTimeRef = useRef(performance.now()); + + useFrame(() => { + const now = performance.now(); + const delta = (now - lastTimeRef.current) / 1000; + lastTimeRef.current = now; + + const object = scene.getObjectByProperty('uuid', human.modelUuid); + if (!object || currentPath.length < 2) return; + if (isPaused) return; + + let totalDistance = 0; + const distances = []; + let accumulatedDistance = 0; + let index = 0; + const rotationSpeed = 1; + + for (let i = 0; i < currentPath.length - 1; i++) { + const start = new THREE.Vector3(...currentPath[i]); + const end = new THREE.Vector3(...currentPath[i + 1]); + const segmentDistance = start.distanceTo(end); + distances.push(segmentDistance); + totalDistance += segmentDistance; + } + + while (index < distances.length && progressRef.current > accumulatedDistance + distances[index]) { + accumulatedDistance += distances[index]; + index++; + } + + if (index < distances.length) { + const start = new THREE.Vector3(...currentPath[index]); + const end = new THREE.Vector3(...currentPath[index + 1]); + const segmentDistance = distances[index]; + + const currentDirection = new THREE.Vector3().subVectors(end, start).normalize(); + const targetAngle = Math.atan2(currentDirection.x, currentDirection.z); + const currentAngle = object.rotation.y; + + let angleDifference = targetAngle - currentAngle; + if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI; + if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI; + + const maxRotationStep = (rotationSpeed * speed * human.speed) * delta; + object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); + const isAligned = Math.abs(angleDifference) < 0.01; + + if (isAligned) { + progressRef.current += delta * (speed * human.speed); + const t = (progressRef.current - accumulatedDistance) / segmentDistance; + const position = start.clone().lerp(end, t); + object.position.copy(position); + } + } + + if (progressRef.current >= totalDistance) { + if (restRotation && objectRotation) { + const targetEuler = new THREE.Euler( + objectRotation[0], + objectRotation[1] + Math.PI, + objectRotation[2] + ); + const targetQuaternion = new THREE.Quaternion().setFromEuler(targetEuler); + object.quaternion.slerp(targetQuaternion, delta * (rotationSpeed * speed * human.speed)); + if (object.quaternion.angleTo(targetQuaternion) < 0.01) { + object.quaternion.copy(targetQuaternion); + object.rotation.copy(targetEuler); + setRestingRotation(false); + } + return; + } + } + + if (progressRef.current >= totalDistance) { + setRestingRotation(true); + progressRef.current = 0; + movingForward.current = !movingForward.current; + setCurrentPath([]); + handleCallBack(); + if (currentPhase === 'pickup-drop') { + requestAnimationFrame(startUnloadingProcess); + } + } + }); + + return ( + <> + {currentPath.length > 0 && ( + // helper + + + {currentPath.map((point, index) => ( + + + + + ))} + + )} + + ) +} + +export default HumanAnimator \ No newline at end of file diff --git a/app/src/modules/simulation/human/instances/instance/animator/humanAnimator.tsx b/app/src/modules/simulation/human/instances/instance/animator/humanAnimator.tsx deleted file mode 100644 index 01f569e..0000000 --- a/app/src/modules/simulation/human/instances/instance/animator/humanAnimator.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react' - -function HumanAnimator() { - return ( - <> - - ) -} - -export default HumanAnimator \ No newline at end of file diff --git a/app/src/modules/simulation/human/instances/instance/humanInstance.tsx b/app/src/modules/simulation/human/instances/instance/humanInstance.tsx index 6e1ebc0..d3fe30a 100644 --- a/app/src/modules/simulation/human/instances/instance/humanInstance.tsx +++ b/app/src/modules/simulation/human/instances/instance/humanInstance.tsx @@ -7,7 +7,7 @@ import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHa import { useSceneContext } from '../../../../scene/sceneContext'; import { useProductContext } from '../../../products/productContext'; -import HumanAnimator from './animator/humanAnimator'; +import HumanAnimator from '../animator/humanAnimator'; function HumanInstance({ human }: { human: HumanStatus }) { const { navMesh } = useNavMesh(); @@ -66,12 +66,10 @@ function HumanInstance({ human }: { human: HumanStatus }) { console.error("Failed to compute path"); return []; } - }, - [navMesh] - ); + }, [navMesh]); function humanStatus(modelId: string, status: string) { - // console.log(`${modelId} , ${status}`); + console.log(`${modelId} , ${status}`); } function reset() { @@ -96,6 +94,25 @@ function HumanInstance({ human }: { human: HumanStatus }) { useEffect(() => { if (isPlaying) { + if (!human.point.action.pickUpPoint || !human.point.action.dropPoint) return; + + if (!human.isActive && human.state === 'idle' && currentPhase === 'init') { + const toPickupPath = computePath( + new THREE.Vector3(human?.position[0], human?.position[1], human?.position[2]), + new THREE.Vector3( + human?.point?.action?.pickUpPoint?.position?.[0] ?? 0, + human?.point?.action?.pickUpPoint?.position?.[1] ?? 0, + human?.point?.action?.pickUpPoint?.position?.[2] ?? 0 + ) + ); + setPath(toPickupPath); + setCurrentPhase('init-pickup'); + setHumanState(human.modelUuid, 'running'); + setHumanPicking(human.modelUuid, false); + setHumanActive(human.modelUuid, true); + humanStatus(human.modelUuid, 'Started from init, heading to pickup'); + return; + } } else { @@ -104,10 +121,28 @@ function HumanInstance({ human }: { human: HumanStatus }) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [human, currentPhase, path, isPlaying]); + function handleCallBack() { + if (currentPhase === 'init-pickup') { + setCurrentPhase('picking'); + } else if (currentPhase === 'pickup-drop') { + } else if (currentPhase === 'drop-pickup') { + } + } + + function startUnloadingProcess() { + } + return ( <> - + ) diff --git a/app/src/modules/simulation/human/instances/instance/humanUi.tsx b/app/src/modules/simulation/human/instances/instance/humanUi.tsx index cfb0fc9..f3688c5 100644 --- a/app/src/modules/simulation/human/instances/instance/humanUi.tsx +++ b/app/src/modules/simulation/human/instances/instance/humanUi.tsx @@ -60,35 +60,29 @@ function HumanUi() { useEffect(() => { if (!selectedEventSphere) return; + const selectedHuman = getHumanById(selectedEventSphere.userData.modelUuid); + if (!selectedHuman || !selectedHuman.point?.action) return; - if (selectedHuman) { - setSelectedHumanData({ - position: selectedHuman.position, - rotation: selectedHuman.rotation, - }); + setSelectedHumanData({ + position: selectedHuman.position, + rotation: selectedHuman.rotation, + }); - if (selectedHuman.point?.actions && selectedAction.actionId) { - const action = selectedHuman.point.actions.find(a => a.actionUuid === selectedAction.actionId); + const action = selectedHuman.point.action; - if (action?.animationSequences[0]) { - const sequence = action.animationSequences[0]; + if (action.pickUpPoint?.position && outerGroup.current) { + const worldPos = new Vector3(...action.pickUpPoint.position); + const localPosition = outerGroup.current.worldToLocal(worldPos.clone()); + setStartPosition([localPosition.x, 0.5, localPosition.z]); + setStartRotation(action.pickUpPoint.rotation || [0, 0, 0]); + } - if (sequence.startPoint?.position && outerGroup.current) { - const worldPos = new Vector3(...sequence.startPoint.position); - const localPosition = outerGroup.current.worldToLocal(worldPos.clone()); - setStartPosition([localPosition.x, 0.5, localPosition.z]); - setStartRotation(sequence.startPoint.rotation || [0, 0, 0]); - } - - if (sequence.endPoint?.position && outerGroup.current) { - const worldPos = new Vector3(...sequence.endPoint.position); - const localPosition = outerGroup.current.worldToLocal(worldPos.clone()); - setEndPosition([localPosition.x, 0.5, localPosition.z]); - setEndRotation(sequence.endPoint.rotation || [0, 0, 0]); - } - } - } + if (action.dropPoint?.position && outerGroup.current) { + const worldPos = new Vector3(...action.dropPoint.position); + const localPosition = outerGroup.current.worldToLocal(worldPos.clone()); + setEndPosition([localPosition.x, 0.5, localPosition.z]); + setEndRotation(action.dropPoint.rotation || [0, 0, 0]); } }, [selectedEventSphere, outerGroup.current, selectedAction, humans]); @@ -126,29 +120,17 @@ function HumanUi() { const worldPosEnd = new Vector3(...endPosition); const globalEndPosition = outerGroup.current.localToWorld(worldPosEnd.clone()); - const updatedActions = selectedHuman.point.actions.map(action => { - if (action.actionUuid === selectedAction.actionId) { - const updatedSequences = action.animationSequences.map(sequence => { - return { - ...sequence, - startPoint: { - position: [globalStartPosition.x, globalStartPosition.y, globalStartPosition.z] as [number, number, number], - rotation: startRotation - }, - endPoint: { - position: [globalEndPosition.x, globalEndPosition.y, globalEndPosition.z] as [number, number, number], - rotation: endRotation - } - }; - }); - - return { - ...action, - animationSequences: updatedSequences - }; + const updatedAction = { + ...selectedHuman.point.action, + pickUpPoint: { + position: [globalStartPosition.x, globalStartPosition.y, globalStartPosition.z] as [number, number, number], + rotation: startRotation + }, + dropPoint: { + position: [globalEndPosition.x, globalEndPosition.y, globalEndPosition.z] as [number, number, number], + rotation: endRotation } - return action; - }); + }; const event = updateEvent( selectedProduct.productUuid, @@ -157,7 +139,7 @@ function HumanUi() { ...selectedHuman, point: { ...selectedHuman.point, - actions: updatedActions + action: updatedAction } } ); @@ -195,8 +177,7 @@ function HumanUi() { const currentPointerX = state.pointer.x; const deltaX = currentPointerX - prevMousePos.current.x; prevMousePos.current.x = currentPointerX; - const marker = - isRotating === "start" ? startMarker.current : endMarker.current; + const marker =isRotating === "start" ? startMarker.current : endMarker.current; if (marker) { const rotationSpeed = 10; marker.rotation.y += deltaX * rotationSpeed; diff --git a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts index 9af9d78..cd1a67c 100644 --- a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts +++ b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts @@ -301,7 +301,7 @@ export function useTriggerHandler() { } else { // Handle current action using Event Manager - addHumanToMonitor(human.modelUuid, triggeredAction.actionUuid, () => { + addHumanToMonitor(human.modelUuid, () => { handleAction(action, materialId); }) } diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index 9d45fd8..a5255e0 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -32,7 +32,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai useEffect(() => { if (currentPhase === 'stationed-pickup' && path.length > 0) { - // console.log('path: ', path); setCurrentPath(path); setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation) } else if (currentPhase === 'pickup-drop' && path.length > 0) { @@ -66,84 +65,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai } }, [isReset, isPlaying]) - // useFrame((_, delta) => { - // const object = scene.getObjectByProperty('uuid', agvUuid); - // if (!object || currentPath.length < 2) return; - // if (isPaused) return; - - // let totalDistance = 0; - // const distances = []; - // let accumulatedDistance = 0; - // let index = 0; - // const rotationSpeed = 1; - - // for (let i = 0; i < currentPath.length - 1; i++) { - // const start = new THREE.Vector3(...currentPath[i]); - // const end = new THREE.Vector3(...currentPath[i + 1]); - // const segmentDistance = start.distanceTo(end); - // distances.push(segmentDistance); - // totalDistance += segmentDistance; - // } - - // while (index < distances.length && progressRef.current > accumulatedDistance + distances[index]) { - // accumulatedDistance += distances[index]; - // index++; - // } - - // if (index < distances.length) { - // const start = new THREE.Vector3(...currentPath[index]); - // const end = new THREE.Vector3(...currentPath[index + 1]); - // const segmentDistance = distances[index]; - - // const currentDirection = new THREE.Vector3().subVectors(end, start).normalize(); - // const targetAngle = Math.atan2(currentDirection.x, currentDirection.z); - - // const currentAngle = object.rotation.y; - - // let angleDifference = targetAngle - currentAngle; - // if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI; - // if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI; - - // const maxRotationStep = (rotationSpeed * speed * agvDetail.speed) * delta; - // object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); - // const isAligned = Math.abs(angleDifference) < 0.01; - - // if (isAligned) { - // progressRef.current += delta * (speed * agvDetail.speed); - // const t = (progressRef.current - accumulatedDistance) / segmentDistance; - // const position = start.clone().lerp(end, t); - // object.position.copy(position); - // } - // } - - // if (progressRef.current >= totalDistance) { - // if (restRotation && objectRotation) { - // const targetEuler = new THREE.Euler( - // objectRotation.x, - // objectRotation.y - (agvDetail.point.action.steeringAngle), - // objectRotation.z - // ); - // const targetQuaternion = new THREE.Quaternion().setFromEuler(targetEuler); - // object.quaternion.slerp(targetQuaternion, delta * (rotationSpeed * speed * agvDetail.speed)); - // if (object.quaternion.angleTo(targetQuaternion) < 0.01) { - // object.quaternion.copy(targetQuaternion); - // object.rotation.copy(targetEuler); - // setRestingRotation(false); - // } - // return; - // } - // } - // if (progressRef.current >= totalDistance) { - // setRestingRotation(true); - // progressRef.current = 0; - // movingForward.current = !movingForward.current; - // setCurrentPath([]); - // handleCallBack(); - // if (currentPhase === 'pickup-drop') { - // requestAnimationFrame(startUnloadingProcess); - // } - // } - // }); const lastTimeRef = useRef(performance.now()); useFrame(() => { diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index 782d4a0..09b498c 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -104,6 +104,10 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) new THREE.Vector3(agvDetail?.position[0], agvDetail?.position[1], agvDetail?.position[2]), agvDetail?.point?.action?.pickUpPoint?.position ); + // const toPickupPath = computePath( + // new THREE.Vector3(agvDetail?.position[0], agvDetail?.position[1], agvDetail?.position[2]), + // new THREE.Vector3(agvDetail?.position[0], agvDetail?.position[1], agvDetail?.position[2]) + // ); setPath(toPickupPath); setCurrentPhase('stationed-pickup'); setVehicleState(agvDetail.modelUuid, 'running'); @@ -193,7 +197,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) }; }, [agvDetail, isPlaying]); - function handleCallBack() { if (currentPhase === 'stationed-pickup') { setCurrentPhase('picking'); diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts index 18d636b..3b483ea 100644 --- a/app/src/store/simulation/useProductStore.ts +++ b/app/src/store/simulation/useProductStore.ts @@ -32,13 +32,13 @@ type ProductsStore = { productUuid: string, modelUuid: string, pointUuid: string, - action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0] + action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['action'] ) => EventsSchema | undefined; removeAction: (productUuid: string, actionUuid: string) => EventsSchema | undefined; updateAction: ( productUuid: string, actionUuid: string, - updates: Partial + updates: Partial ) => EventsSchema | undefined; // Trigger-level actionss diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts index 02d66c8..678f117 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -73,14 +73,8 @@ interface HumanAction { actionUuid: string; actionName: string; actionType: "worker"; - animationSequences: { - animationUuid: string; - animationName: string; - animationType: "behaviour" | "animatedTravel"; - animation: string | null; - startPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } - endPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } - }[] + pickUpPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } + dropPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; } loadCapacity: number; triggers: TriggerSchema[]; } @@ -127,7 +121,7 @@ interface HumanPointSchema { uuid: string; position: [number, number, number]; rotation: [number, number, number]; - actions: HumanAction[]; + action: HumanAction; } type PointsScheme = | ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema;