From eb5683eadc18ca0786ba982928bbe5a862033bb2 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Thu, 3 Jul 2025 14:23:57 +0530 Subject: [PATCH] feat: Refactor human action handling to replace animatedTravel with worker actions and enhance animation management --- .../components/AnimationList.tsx | 104 ++++ .../mechanics/humanMechanics.tsx | 491 +++++++++++++++--- app/src/components/ui/inputs/RenameInput.tsx | 13 +- app/src/modules/builder/asset/assetsGroup.tsx | 29 +- .../builder/asset/functions/addAssetModel.ts | 28 +- ...edTravelHandler.ts => useWorkerHandler.ts} | 12 +- .../actions/human/useHumanActions.ts | 16 +- .../simulation/actions/useActionHandler.ts | 2 +- .../triggerConnections/triggerConnector.tsx | 6 +- app/src/store/simulation/useProductStore.ts | 4 +- app/src/types/simulationTypes.d.ts | 13 +- 11 files changed, 606 insertions(+), 112 deletions(-) create mode 100644 app/src/components/layout/sidebarRight/properties/eventProperties/components/AnimationList.tsx rename app/src/modules/simulation/actions/human/actionHandler/{useAnimatedTravelHandler.ts => useWorkerHandler.ts} (66%) diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/components/AnimationList.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/components/AnimationList.tsx new file mode 100644 index 0000000..f3283e3 --- /dev/null +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/components/AnimationList.tsx @@ -0,0 +1,104 @@ +import React, { useRef } from "react"; +import { AddIcon, RemoveIcon, ResizeHeightIcon } from "../../../../../icons/ExportCommonIcons"; +import { handleResize } from "../../../../../../functions/handleResizePannel"; +import { useSelectedAction } from "../../../../../../store/simulation/useSimulationStore"; +import RenameInput from "../../../../../ui/inputs/RenameInput"; + +interface AnimationListProps { + animationOptions: string[]; + animationSequences: { + animationUuid: string; + animationName: string; + animationType: "behaviour" | "animatedTravel"; + animation: string | null; + travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null }; + }[]; + onAddAnimation: () => void; + onRemoveAnimation: (animationUuid: string) => void; + handleAnimationSelect: (animationUuid: string) => void; + handleRenameAnimation: (animationUuid: string, newName: string) => void; + selectedAnimation: { + animationUuid: string; + animationName: string; + animationType: "behaviour" | "animatedTravel"; + animation: string | null; + travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null }; + } | undefined +} + +const AnimationList: React.FC = ({ + animationSequences, + onAddAnimation, + onRemoveAnimation, + handleAnimationSelect, + handleRenameAnimation, + selectedAnimation +}) => { + const animationContainerRef = useRef(null); + const { selectedAction } = useSelectedAction(); + + return ( +
+
+
+
Animation Sequences
+ +
+
+
+ {animationSequences.map((sequence) => ( +
+ + {animationSequences.length > 1 && ( + + )} +
+ ))} +
+ {animationSequences.length > 0 && ( + + )} +
+
+
+ ); +}; + +export default AnimationList; \ No newline at end of file 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 d07022a..24bb2e1 100644 --- a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/humanMechanics.tsx @@ -1,27 +1,38 @@ import { useEffect, useState } from "react"; +import { MathUtils } from "three"; import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown"; import RenameInput from "../../../../../ui/inputs/RenameInput"; import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; import Trigger from "../trigger/Trigger"; -import { useSelectedEventData, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore"; import PickAndPlaceAction from "../actions/PickAndPlaceAction"; +import ActionsList from "../components/ActionsList"; +import AnimationList from "../components/AnimationList"; +import { useSelectedEventData, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore"; import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi"; import { useProductContext } from "../../../../../../modules/simulation/products/productContext"; -import { useParams } from "react-router-dom"; import { useVersionContext } from "../../../../../../modules/builder/version/versionContext"; import { useSceneContext } from "../../../../../../modules/scene/sceneContext"; -import ActionsList from "../components/ActionsList"; +import { useParams } from "react-router-dom"; function HumanMechanics() { - const [activeOption, setActiveOption] = useState<"animatedTravel">("animatedTravel"); + const [activeOption, setActiveOption] = useState<"worker">("worker"); + const [animationOptions, setAnimationOptions] = useState([]); const [speed, setSpeed] = useState("0.5"); const [currentAction, setCurrentAction] = useState(); const [selectedPointData, setSelectedPointData] = useState(); const { selectedEventData } = useSelectedEventData(); - const { productStore } = useSceneContext(); - const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction } = productStore(); + const { productStore, assetStore } = useSceneContext(); + const { getAssetById } = assetStore(); + const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction } = productStore(); const { selectedProductStore } = useProductContext(); const { selectedProduct } = selectedProductStore(); + const [selectedAnimation, setSelectedAnimation] = useState<{ + animationUuid: string; + animationName: string; + animationType: "behaviour" | "animatedTravel"; + animation: string | null; + travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; } + }>(); const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction(); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); @@ -35,10 +46,15 @@ function HumanMechanics() { selectedEventData.selectedPoint ) as HumanPointSchema | undefined; - if (point?.action) { + if (point?.actions) { setSelectedPointData(point); - const action = point.action; - setSelectedAction(action.actionUuid, action.actionName); + 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) + } + } } } else { clearSelectedAction(); @@ -62,11 +78,16 @@ function HumanMechanics() { selectedEventData.selectedPoint ) as HumanPointSchema | undefined; - if (point?.action) { + if (point?.actions) { setSelectedPointData(point); - const action = point.action; - setCurrentAction(action); - setActiveOption(action.actionType as "animatedTravel"); + 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]); + } + } } } else { clearSelectedAction(); @@ -91,80 +112,387 @@ function HumanMechanics() { }; const handleSelectActionType = (actionType: string) => { - if (!currentAction) return; - setActiveOption(actionType as "animatedTravel"); + 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 event = updateAction( selectedProduct.productUuid, - currentAction.actionUuid, - { actionType: actionType as "animatedTravel" } + selectedAction.actionId, + updatedAction ); - if (event && selectedPointData) { - const updatedAction = { ...selectedPointData.action, actionType: actionType as "animatedTravel" }; - setSelectedPointData({ ...selectedPointData, action: updatedAction }); - } - if (event) { updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); } + + setCurrentAction(updatedAction); + setSelectedPointData(updatedPoint); }; - const handleRenameAction = (newName: string) => { - if (!currentAction) return; + 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, - currentAction.actionUuid, - { actionName: newName } + selectedAction.actionId, + updatedAction ); - if (event && selectedPointData) { - const updatedAction = { ...selectedPointData.action, actionName: newName }; - setSelectedPointData({ ...selectedPointData, action: updatedAction }); - } - if (event) { updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); } + + setCurrentAction(updatedAction); + setSelectedAnimation(updatedAnimation); + setSelectedPointData(updatedPoint); }; const handleSpeedChange = (value: string) => { if (!selectedEventData) return; + const numericValue = parseFloat(value); + if (isNaN(numericValue)) return; + + const updatedEvent = { + ...selectedEventData.data, + speed: numericValue + } as HumanEventSchema; + const event = updateEvent( selectedProduct.productUuid, selectedEventData.data.modelUuid, - { speed: parseFloat(value) } + updatedEvent ); if (event) { updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); } + + setSpeed(value); }; - const handleClearPoints = () => { - if (!currentAction) return; + const handleClearPoints = (animationUuid: string) => { + if (!currentAction || !selectedPointData || !selectedAction.actionId) return; + + const updatedAnimation = currentAction.animationSequences.find(anim => + anim.animationUuid === animationUuid + ); + + if (!updatedAnimation) return; + + updatedAnimation.travelPoints = { + startPoint: null, + endPoint: null + }; + + 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 event = updateAction( selectedProduct.productUuid, - currentAction.actionUuid, - { - travelPoints: { - startPoint: null, - endPoint: null, - }, - } + selectedAction.actionId, + updatedAction ); if (event) { updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); } + + setCurrentAction(updatedAction); + setSelectedPointData(updatedPoint); + if (selectedAnimation?.animationUuid === animationUuid) { + setSelectedAnimation(updatedAnimation); + } + }; + + const handleAddAction = () => { + if (!selectedEventData || !selectedPointData) return; + + const newAction: HumanAction = { + actionUuid: MathUtils.generateUUID(), + actionName: `Action ${selectedPointData.actions.length + 1}`, + actionType: "worker", + animationSequences: [ + { + animationUuid: MathUtils.generateUUID(), + animationName: 'Animation 1', + animationType: 'behaviour', + animation: null + } + ], + loadCapacity: 1, + triggers: [], + }; + + const event = addAction( + selectedProduct.productUuid, + selectedEventData.data.modelUuid, + selectedEventData.selectedPoint, + newAction + ); + + if (event) { + updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); + } + + const updatedPoint = { ...selectedPointData, actions: [...selectedPointData.actions, newAction] }; + setSelectedPointData(updatedPoint); + setSelectedAction(newAction.actionUuid, newAction.actionName); + }; + + const handleDeleteAction = (actionUuid: string) => { + 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( + selectedProduct.productUuid, + selectedAction.actionId, + updatedAction + ); + + if (event) { + updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event); + } + + setCurrentAction(updatedAction); + 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 + }; + + if (newType === 'animatedTravel') { + updatedAnim.travelPoints = { + startPoint: null, + endPoint: null + }; + } else { + delete updatedAnim.travelPoints; + } + + 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: "animatedTravel", - options: ["animatedTravel"], + defaultOption: "worker", + options: ["worker"], }; return ( @@ -186,21 +514,20 @@ function HumanMechanics() { +
+ - {currentAction && ( -
- - { }} - handleDeleteAction={() => { }} - /> + {selectedAction.actionId && currentAction && (
@@ -211,21 +538,63 @@ function HumanMechanics() { onSelect={handleSelectActionType} disabled={true} /> - {activeOption === 'animatedTravel' && ( - - )}
+ + {selectedAnimation && ( + <> +
+ +
+
+ + handleAnimationTypeChange( + selectedAnimation.animationUuid, + type as "behaviour" | "animatedTravel" + ) + } + /> + + + {selectedAnimation.animationType === "animatedTravel" && ( + handleClearPoints(selectedAnimation.animationUuid)} + /> + )} +
+ + )}
-
- )} + )} +
); } -export default HumanMechanics; +export default HumanMechanics; \ No newline at end of file diff --git a/app/src/components/ui/inputs/RenameInput.tsx b/app/src/components/ui/inputs/RenameInput.tsx index 593e1f1..637dec3 100644 --- a/app/src/components/ui/inputs/RenameInput.tsx +++ b/app/src/components/ui/inputs/RenameInput.tsx @@ -9,9 +9,10 @@ interface RenameInputProps { value: string; onRename?: (newText: string) => void; checkDuplicate?: (name: string) => boolean; + canEdit?: boolean; } -const RenameInput: React.FC = ({ value, onRename, checkDuplicate }) => { +const RenameInput: React.FC = ({ value, onRename, checkDuplicate, canEdit = true }) => { const [isEditing, setIsEditing] = useState(false); const [text, setText] = useState(value); const [isDuplicate, setIsDuplicate] = useState(false); @@ -28,13 +29,15 @@ const RenameInput: React.FC = ({ value, onRename, checkDuplica }, [text, checkDuplicate]); const handleDoubleClick = () => { - setIsEditing(true); - setTimeout(() => inputRef.current?.focus(), 0); + if (canEdit) { + setIsEditing(true); + setTimeout(() => inputRef.current?.focus(), 0); + } }; const handleBlur = () => { - - if(isDuplicate) return + + if (isDuplicate) return setIsEditing(false); if (onRename && !isDuplicate) { onRename(text); diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx index fbc2738..a761d39 100644 --- a/app/src/modules/builder/asset/assetsGroup.tsx +++ b/app/src/modules/builder/asset/assetsGroup.tsx @@ -256,18 +256,23 @@ 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], - action: { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Action 1", - actionType: "animatedTravel", - loadCapacity: 1, - travelPoints: { - startPoint: null, - endPoint: null, - }, - triggers: [] - } - + 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: [] + } + ] } } addEvent(humanEvent); diff --git a/app/src/modules/builder/asset/functions/addAssetModel.ts b/app/src/modules/builder/asset/functions/addAssetModel.ts index 471314f..8aa18f1 100644 --- a/app/src/modules/builder/asset/functions/addAssetModel.ts +++ b/app/src/modules/builder/asset/functions/addAssetModel.ts @@ -374,17 +374,23 @@ async function handleModelLoad( uuid: THREE.MathUtils.generateUUID(), position: [data.points[0].x, data.points[0].y, data.points[0].z], rotation: [0, 0, 0], - action: { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Action 1", - actionType: "animatedTravel", - loadCapacity: 1, - travelPoints: { - startPoint: null, - endPoint: null, - }, - triggers: [] - } + 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: [] + } + ] } } diff --git a/app/src/modules/simulation/actions/human/actionHandler/useAnimatedTravelHandler.ts b/app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts similarity index 66% rename from app/src/modules/simulation/actions/human/actionHandler/useAnimatedTravelHandler.ts rename to app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts index d347f03..9e775ff 100644 --- a/app/src/modules/simulation/actions/human/actionHandler/useAnimatedTravelHandler.ts +++ b/app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts @@ -2,7 +2,7 @@ import { useCallback } from "react"; import { useSceneContext } from "../../../../scene/sceneContext"; import { useProductContext } from "../../../products/productContext"; -export function useAnimatedTravelHandler() { +export function useWorkerHandler() { const { materialStore, humanStore, productStore } = useSceneContext(); const { getMaterialById } = materialStore(); const { } = humanStore(); @@ -10,12 +10,12 @@ export function useAnimatedTravelHandler() { const { selectedProductStore } = useProductContext(); const { selectedProduct } = selectedProductStore(); - const animatedTravelLogStatus = (materialUuid: string, status: string) => { + const workerLogStatus = (materialUuid: string, status: string) => { echo.info(`${materialUuid}, ${status}`); } - const handleAnimatedTravel = useCallback((action: HumanAction, materialId?: string) => { - if (!action || action.actionType !== 'animatedTravel' || !materialId) return; + const handleWorker = useCallback((action: HumanAction, materialId?: string) => { + if (!action || action.actionType !== 'worker' || !materialId) return; const material = getMaterialById(materialId); if (!material) return; @@ -24,11 +24,11 @@ export function useAnimatedTravelHandler() { if (!modelUuid) return; - animatedTravelLogStatus(material.materialName, `performing animatedTravel`); + workerLogStatus(material.materialName, `performing worker action`); }, [getMaterialById]); return { - handleAnimatedTravel, + handleWorker, }; } \ No newline at end of file diff --git a/app/src/modules/simulation/actions/human/useHumanActions.ts b/app/src/modules/simulation/actions/human/useHumanActions.ts index 96e40b0..8e30e45 100644 --- a/app/src/modules/simulation/actions/human/useHumanActions.ts +++ b/app/src/modules/simulation/actions/human/useHumanActions.ts @@ -1,24 +1,24 @@ import { useEffect, useCallback } from 'react'; -import { useAnimatedTravelHandler } from './actionHandler/useAnimatedTravelHandler'; +import { useWorkerHandler } from './actionHandler/useWorkerHandler'; export function useHumanActions() { - const { handleAnimatedTravel } = useAnimatedTravelHandler(); + const { handleWorker } = useWorkerHandler(); - const handleAnimatedTravelAction = useCallback((action: HumanAction) => { - handleAnimatedTravel(action); - }, [handleAnimatedTravel]); + const handleWorkerAction = useCallback((action: HumanAction) => { + handleWorker(action); + }, [handleWorker]); const handleHumanAction = useCallback((action: HumanAction, materialId: string) => { if (!action) return; switch (action.actionType) { - case 'animatedTravel': - handleAnimatedTravelAction(action); + case 'worker': + handleWorkerAction(action); break; default: console.warn(`Unknown Human action type: ${action.actionType}`); } - }, [handleAnimatedTravelAction]); + }, [handleWorkerAction]); const cleanup = useCallback(() => { }, []); diff --git a/app/src/modules/simulation/actions/useActionHandler.ts b/app/src/modules/simulation/actions/useActionHandler.ts index aef8d39..3bb95bf 100644 --- a/app/src/modules/simulation/actions/useActionHandler.ts +++ b/app/src/modules/simulation/actions/useActionHandler.ts @@ -39,7 +39,7 @@ export function useActionHandler() { case 'store': case 'retrieve': handleStorageAction(action as StorageAction, materialId as string); break; - case 'animatedTravel': + case 'worker': handleHumanAction(action as HumanAction, materialId as string); break; default: diff --git a/app/src/modules/simulation/events/triggerConnections/triggerConnector.tsx b/app/src/modules/simulation/events/triggerConnections/triggerConnector.tsx index ec7406c..918007a 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; - if (point.action?.triggers) { - point.action.triggers.forEach(trigger => { + point.actions?.forEach(action => { + 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/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts index 3b483ea..18d636b 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['action'] + action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0] ) => 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 2192101..b99feee 100644 --- a/app/src/types/simulationTypes.d.ts +++ b/app/src/types/simulationTypes.d.ts @@ -72,9 +72,15 @@ interface StorageAction { interface HumanAction { actionUuid: string; actionName: string; - actionType: "animatedTravel"; + actionType: "worker"; + animationSequences: { + animationUuid: string; + animationName: string; + animationType: "behaviour" | "animatedTravel"; + animation: string | null; + travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; } + }[] loadCapacity: number; - travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; } triggers: TriggerSchema[]; } @@ -120,7 +126,7 @@ interface HumanPointSchema { uuid: string; position: [number, number, number]; rotation: [number, number, number]; - action: HumanAction; + actions: HumanAction[]; } type PointsScheme = | ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema; @@ -229,6 +235,7 @@ interface HumanStatus extends HumanEventSchema { currentAction?: { actionUuid: string; actionName: string; + animationUuid: string; materialType?: string | null; materialId?: string | null; };