feat: Implement human event handling in copy and duplication controls

- Added support for handling "Human" type events in the copy and duplication controls.
- Created a new HumanEventSchema to manage human-related events, including position, rotation, and action details.
- Updated the HumanAnimator to improve rotation handling using quaternions for smoother transitions.
- Enhanced the HumanInstance to ensure proper synchronization of human positions and rotations.
- Integrated human event handling in the trigger handler for various interactions, including vehicle and machine actions.
- Introduced material drop functionality from vehicles to humans, allowing for dynamic interactions in the simulation.
This commit is contained in:
2025-07-04 17:15:10 +05:30
parent ff02f01430
commit 508c88dce2
9 changed files with 821 additions and 86 deletions

View File

@@ -30,7 +30,7 @@ function HumanMechanics() {
const { projectId } = useParams();
useEffect(() => {
if (selectedEventData) {
if (selectedEventData && selectedEventData.data.type === "human") {
const point = getPointByUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,

View File

@@ -16,6 +16,7 @@ import { getUserData } from '../../../../../functions/getUserData';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useVersionContext } from '../../../version/versionContext';
import { SkeletonUtils } from 'three-stdlib';
import { useAnimationPlaySpeed } from '../../../../../store/usePlayButtonStore';
function Model({ asset }: { readonly asset: Asset }) {
const { camera, controls, gl } = useThree();
@@ -23,6 +24,7 @@ function Model({ asset }: { readonly asset: Asset }) {
const { toggleView } = useToggleView();
const { subModule } = useSubModuleStore();
const { activeModule } = useModuleStore();
const { speed } = useAnimationPlaySpeed();
const { assetStore, eventStore, productStore } = useSceneContext();
const { removeAsset, setAnimations, resetAnimation, setAnimationComplete, setCurrentAnimation: setAnmationAnimation } = assetStore();
const { setTop } = useTopData();
@@ -289,7 +291,7 @@ function Model({ asset }: { readonly asset: Asset }) {
useFrame((_, delta) => {
if (mixerRef.current) {
mixerRef.current.update(delta);
mixerRef.current.update(delta * speed);
}
});

View File

@@ -332,6 +332,34 @@ const CopyPasteControls = ({
position: storageEvent.point.position,
rotation: storageEvent.point.rotation
};
} else if (obj.userData.eventData.type === "Human") {
const humanEvent: HumanEventSchema = {
modelUuid: newFloorItem.modelUuid,
modelName: newFloorItem.modelName,
position: newFloorItem.position,
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
state: "idle",
type: "human",
speed: 1,
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Action 1",
actionType: "worker",
loadCapacity: 1,
triggers: []
}
}
}
addEvent(humanEvent);
eventData.point = {
uuid: humanEvent.point.uuid,
position: humanEvent.point.position,
rotation: humanEvent.point.rotation
};
}
newFloorItem.eventData = eventData;

View File

@@ -306,6 +306,34 @@ const DuplicationControls = ({
position: storageEvent.point.position,
rotation: storageEvent.point.rotation
};
} else if (obj.userData.eventData.type === "Human") {
const humanEvent: HumanEventSchema = {
modelUuid: newFloorItem.modelUuid,
modelName: newFloorItem.modelName,
position: newFloorItem.position,
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
state: "idle",
type: "human",
speed: 1,
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Action 1",
actionType: "worker",
loadCapacity: 1,
triggers: []
}
}
}
addEvent(humanEvent);
eventData.point = {
uuid: humanEvent.point.uuid,
position: humanEvent.point.position,
rotation: humanEvent.point.rotation
};
}
newFloorItem.eventData = eventData;

View File

@@ -100,17 +100,18 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
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;
const targetQuaternion = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().lookAt(start, end, new THREE.Vector3(0, 1, 0)));
const y180 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
targetQuaternion.multiply(y180);
let angleDifference = targetAngle - currentAngle;
if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI;
if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI;
const angle = object.quaternion.angleTo(targetQuaternion);
if (angle < 0.01) {
object.quaternion.copy(targetQuaternion);
} else {
object.quaternion.slerp(targetQuaternion, delta * rotationSpeed * speed * human.speed * 5);
}
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;
const isAligned = angle < 0.01;
if (isAligned) {
progressRef.current += delta * (speed * human.speed);
@@ -133,23 +134,26 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
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) {
const targetEuler = new THREE.Euler(0, objectRotation[1], 0);
const baseQuaternion = new THREE.Quaternion().setFromEuler(targetEuler);
const y180 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
const targetQuaternion = baseQuaternion.multiply(y180);
const angle = object.quaternion.angleTo(targetQuaternion);
if (angle < 0.01) {
object.quaternion.copy(targetQuaternion);
object.rotation.copy(targetEuler);
setRestingRotation(false);
} else {
object.quaternion.slerp(targetQuaternion, delta * rotationSpeed * speed * human.speed * 4);
}
if (human.currentMaterials.length > 0) {
setCurrentAnimation(human.modelUuid, 'idle_with_box', true, true, true);
} else {
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
}
return;
}
}
@@ -170,7 +174,7 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
<>
{currentPath.length > 0 && (
// helper
<group >
<group visible={false}>
<Line points={currentPath} color="blue" lineWidth={3} />
{currentPath.map((point, index) => (
<mesh key={index} position={point}>

View File

@@ -1,5 +1,6 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { useThree } from '@react-three/fiber';
import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh } from '../../../../../store/builder/store';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
@@ -13,6 +14,7 @@ import MaterialAnimator from '../animator/materialAnimator';
function HumanInstance({ human }: { human: HumanStatus }) {
const { navMesh } = useNavMesh();
const { isPlaying } = usePlayButtonStore();
const { scene } = useThree();
const { assetStore, materialStore, armBotStore, conveyorStore, machineStore, vehicleStore, humanStore, storageUnitStore, productStore } = useSceneContext();
const { removeMaterial, setEndTime } = materialStore();
const { getStorageUnitById } = storageUnitStore();
@@ -92,6 +94,11 @@ function HumanInstance({ human }: { human: HumanStatus }) {
cancelAnimationFrame(animationFrameIdRef.current)
animationFrameIdRef.current = null
}
const object = scene.getObjectByProperty('uuid', human.modelUuid);
if (object && human) {
object.position.set(human.position[0], human.position[1], human.position[2]);
object.rotation.set(human.rotation[0], human.rotation[1], human.rotation[2]);
}
}
useEffect(() => {
@@ -292,6 +299,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
}
function handleMaterialDropToStorageUnit(model: StorageEventSchema) {
const humanAsset = getAssetById(human.modelUuid);
if (model && humanAsset?.animationState?.current !== 'drop') {
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
}
@@ -322,6 +330,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
action: HumanAction
) {
const storageUnit = getStorageUnitById(storageUnitId);
const humanAsset = getAssetById(human.modelUuid);
if (!storageUnit || humanCurrentLoad <= 0 || storageUnit.currentLoad >= storageMaxCapacity) {
return;
@@ -340,7 +349,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
const waitForNextDrop = () => {
if (humanAsset?.animationState?.isCompleted) {
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
loopMaterialDropToStorage(
humanId,
humanCurrentLoad,
@@ -357,6 +366,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
}
function handleMaterialDropToConveyor(model: ConveyorEventSchema) {
const humanAsset = getAssetById(human.modelUuid);
if (humanAsset?.animationState?.current !== 'drop') {
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
}
@@ -386,6 +396,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
action: HumanAction
) {
const conveyor = getConveyorById(conveyorId);
const humanAsset = getAssetById(human.modelUuid);
if (!conveyor || humanCurrentLoad <= 0) {
return;
@@ -420,12 +431,13 @@ function HumanInstance({ human }: { human: HumanStatus }) {
}
function handleMaterialDropToArmBot(model: RoboticArmEventSchema) {
const humanAsset = getAssetById(human.modelUuid);
if (humanAsset?.animationState?.current !== 'drop') {
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
}
const checkAnimation = () => {
if (humanAsset?.animationState?.isCompleted) {
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
const armBot = getArmBotById(model.modelUuid);
if (armBot && armBot.state === 'idle' && !armBot.isActive) {
loopMaterialDropToArmBot(
@@ -449,6 +461,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
action: HumanAction
) {
const armBot = getArmBotById(armBotId);
const humanAsset = getAssetById(human.modelUuid);
if (!armBot || armBot.state !== 'idle' || armBot.isActive || humanCurrentLoad <= 0) {
return;
@@ -488,12 +501,13 @@ function HumanInstance({ human }: { human: HumanStatus }) {
}
function handleMaterialDropToVehicle(model: VehicleEventSchema) {
const humanAsset = getAssetById(human.modelUuid);
if (humanAsset?.animationState?.current !== 'drop') {
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
}
const checkAnimation = () => {
if (humanAsset?.animationState?.isCompleted) {
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
const vehicle = getVehicleById(model.modelUuid);
if (vehicle && vehicle.state === 'idle' && !vehicle.isActive) {
loopMaterialDropToVehicle(
@@ -517,6 +531,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
action: HumanAction
) {
const vehicle = getVehicleById(vehicleId);
const humanAsset = getAssetById(human.modelUuid);
if (!vehicle || vehicle.state !== 'idle' || vehicle.isActive || humanCurrentLoad <= 0) {
return;
@@ -535,10 +550,10 @@ function HumanInstance({ human }: { human: HumanStatus }) {
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
const waitForNextTransfer = () => {
const currentArmBot = getVehicleById(vehicleId);
if (currentArmBot && currentArmBot.state === 'idle' && !currentArmBot.isActive) {
const currentVehicle = getVehicleById(vehicleId);
if (currentVehicle && currentVehicle.state === 'idle' && !currentVehicle.isActive) {
if (humanAsset?.animationState?.isCompleted) {
loopMaterialDropToArmBot(
loopMaterialDropToVehicle(
humanId,
humanCurrentLoad,
vehicleId,
@@ -556,12 +571,13 @@ function HumanInstance({ human }: { human: HumanStatus }) {
}
function handleMaterialDropToMachine(model: MachineEventSchema) {
const humanAsset = getAssetById(human.modelUuid);
if (humanAsset?.animationState?.current !== 'drop') {
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
}
const checkAnimation = () => {
if (humanAsset?.animationState?.isCompleted) {
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
const machine = getMachineById(model.modelUuid);
if (machine && machine.state === 'idle' && !machine.isActive) {
loopMaterialDropToMachine(
@@ -585,6 +601,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
action: HumanAction
) {
const machine = getMachineById(machineId);
const humanAsset = getAssetById(human.modelUuid);
if (!machine || machine.state !== 'idle' || machine.isActive || humanCurrentLoad <= 0) {
return;
@@ -603,10 +620,10 @@ function HumanInstance({ human }: { human: HumanStatus }) {
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
const waitForNextTransfer = () => {
const currentArmBot = getMachineById(machineId);
if (currentArmBot && currentArmBot.state === 'idle' && !currentArmBot.isActive) {
const currentMachine = getMachineById(machineId);
if (currentMachine && currentMachine.state === 'idle' && !currentMachine.isActive) {
if (humanAsset?.animationState?.isCompleted) {
loopMaterialDropToArmBot(
loopMaterialDropToMachine(
humanId,
humanCurrentLoad,
machineId,
@@ -624,6 +641,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
}
function handleMaterialDropByDefault(droppedMaterial: number) {
const humanAsset = getAssetById(human.modelUuid);
if (humanAsset?.animationState?.current !== 'drop') {
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
}

View File

@@ -219,7 +219,6 @@ function HumanUi() {
{selectedHumanData && (
<group
position={selectedHumanData.position}
rotation={selectedHumanData.rotation}
ref={outerGroup}
>
<primitive

View File

@@ -152,6 +152,9 @@ export function useTriggerHandler() {
const model = getEventByModelUuid(selectedProduct.productUuid, action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
if (model?.type === 'vehicle') {
const armBot = getArmBotById(trigger.triggeredAsset?.triggeredModel.modelUuid);
if (armBot) {
if (armBot.isActive === false && armBot.state === 'idle') {
const vehicle = getVehicleById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
if (vehicle) {
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
@@ -171,6 +174,31 @@ export function useTriggerHandler() {
)
}
}
} else {
setIsPaused(materialId, true);
addArmBotToMonitor(armBot.modelUuid, () => {
const vehicle = getVehicleById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (vehicle) {
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
// Handle current action from vehicle
setIsPaused(materialId, true);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addVehicleToMonitor(vehicle.modelUuid,
() => {
handleAction(action, materialId);
}
)
}
}
})
}
}
} else if (model?.type === 'machine') {
const armBot = getArmBotById(trigger.triggeredAsset?.triggeredModel.modelUuid);
if (armBot) {
@@ -194,8 +222,7 @@ export function useTriggerHandler() {
}
} else {
setIsPaused(materialId, true);
addArmBotToMonitor(armBot.modelUuid,
() => {
addArmBotToMonitor(armBot.modelUuid, () => {
const machine = getMachineById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (machine) {
if (machine.isActive === false && machine.state === 'idle' && !machine.currentAction) {
@@ -289,25 +316,208 @@ export function useTriggerHandler() {
if (action) {
if (human) {
if (action && action.triggers.length > 0 &&
action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid &&
action.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid &&
action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid) {
const model = getEventByModelUuid(selectedProduct.productUuid, action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
if (human.isActive === false && human.state === 'idle' && human.isPicking && human.currentLoad < human.point.action.loadCapacity) {
setIsVisible(materialId, false);
if (model?.type === 'vehicle') {
const human = getHumanById(trigger.triggeredAsset?.triggeredModel.modelUuid);
if (human) {
if (human.isActive === false && human.state === 'idle') {
const vehicle = getVehicleById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
if (vehicle) {
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
// Handle current action from vehicle
setIsVisible(materialId, false);
setIsPaused(materialId, true);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
addHumanToMonitor(human.modelUuid, () => {
setIsPaused(materialId, true);
addVehicleToMonitor(vehicle.modelUuid,
() => {
setIsVisible(materialId, false);
handleAction(action, materialId);
}
)
}
}
} else {
setIsPaused(materialId, true);
addHumanToMonitor(human.modelUuid, () => {
const vehicle = getVehicleById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (vehicle) {
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
// Handle current action from vehicle
setIsVisible(materialId, false);
setIsPaused(materialId, true);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addVehicleToMonitor(vehicle.modelUuid,
() => {
setIsVisible(materialId, false);
handleAction(action, materialId);
}
)
}
}
})
}
}
} else if (model?.type === 'transfer') {
const human = getHumanById(trigger.triggeredAsset?.triggeredModel.modelUuid);
if (human) {
if (human.isActive === false && human.state === 'idle') {
const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
if (conveyor) {
if (!conveyor.isPaused) {
// Handle current action from vehicle
setIsVisible(materialId, false);
setIsPaused(materialId, true);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addConveyorToMonitor(conveyor.modelUuid,
() => {
setIsVisible(materialId, false);
handleAction(action, materialId);
}
)
}
}
} else {
setIsPaused(materialId, true);
addHumanToMonitor(human.modelUuid, () => {
const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (conveyor) {
if (!conveyor.isPaused) {
// Handle current action from vehicle
setIsVisible(materialId, false);
setIsPaused(materialId, true);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addConveyorToMonitor(conveyor.modelUuid,
() => {
setIsVisible(materialId, false);
handleAction(action, materialId);
}
)
}
}
})
}
}
} else if (model?.type === 'machine') {
const human = getHumanById(trigger.triggeredAsset?.triggeredModel.modelUuid);
if (human) {
if (human.isActive === false && human.state === 'idle') {
const machine = getMachineById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
if (machine) {
if (machine.isActive === false && machine.state === 'idle' && !machine.currentAction) {
setIsPaused(materialId, true);
setIsVisible(materialId, false);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addMachineToMonitor(machine.modelUuid,
() => {
setIsVisible(materialId, false);
handleAction(action, materialId);
}
)
}
}
} else {
setIsPaused(materialId, true);
addHumanToMonitor(human.modelUuid, () => {
const machine = getMachineById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (machine) {
if (machine.isActive === false && machine.state === 'idle' && !machine.currentAction) {
setIsPaused(materialId, true);
setIsVisible(materialId, false);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addMachineToMonitor(machine.modelUuid,
() => {
setIsVisible(materialId, false);
handleAction(action, materialId);
}
)
}
}
}
);
}
}
} else {
if (human.isActive === false && human.state === 'idle') {
// Handle current action from arm bot
setIsPaused(materialId, true);
setIsVisible(materialId, false);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addHumanToMonitor(human.modelUuid,
() => {
setIsVisible(materialId, false);
handleAction(action, materialId)
}
);
}
}
} else {
if (human.isActive === false && human.state === 'idle') {
// Handle current action from arm bot
setIsPaused(materialId, true);
setIsVisible(materialId, false);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addHumanToMonitor(human.modelUuid,
() => {
setIsVisible(materialId, false);
handleAction(action, materialId)
}
);
}
}
}
}
}
}
@@ -378,18 +588,25 @@ export function useTriggerHandler() {
setNextLocation(material.materialId, null);
setIsVisible(materialId, false);
if (action && armBot) {
if (armBot.isActive === false && armBot.state === 'idle') {
// Handle current action from arm bot
setIsVisible(materialId, false);
handleAction(action, materialId);
} else {
// Event Manager Needed
addArmBotToMonitor(armBot.modelUuid,
() => {
setIsVisible(materialId, false);
handleAction(action, materialId);
}
)
}
}
@@ -438,6 +655,49 @@ export function useTriggerHandler() {
} else if (toEvent?.type === 'human') {
// Vehicle to Human
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
const material = getMaterialById(materialId);
if (material) {
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
const human = getHumanById(trigger.triggeredAsset?.triggeredModel.modelUuid);
setPreviousLocation(material.materialId, {
modelUuid: material.current.modelUuid,
pointUuid: material.current.pointUuid,
actionUuid: material.current.actionUuid,
})
setCurrentLocation(material.materialId, {
modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid,
pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid,
});
setNextLocation(material.materialId, null);
if (action && human) {
if (human.isActive === false && human.state === 'idle') {
// Handle current action from arm bot
setIsVisible(materialId, false);
handleAction(action, materialId);
} else {
addHumanToMonitor(human.modelUuid,
() => {
setIsVisible(materialId, false);
handleAction(action, materialId);
}
)
}
}
}
}
}
} else if (fromEvent?.type === 'machine') {
if (toEvent?.type === 'transfer') {
@@ -546,7 +806,133 @@ export function useTriggerHandler() {
} else if (toEvent?.type === 'human') {
// Machine to Human
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
const material = getMaterialById(materialId);
setIsPaused(materialId, true);
if (material) {
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
const human = getHumanById(trigger.triggeredAsset?.triggeredModel.modelUuid);
setPreviousLocation(material.materialId, {
modelUuid: material.current.modelUuid,
pointUuid: material.current.pointUuid,
actionUuid: material.current.actionUuid,
})
setCurrentLocation(material.materialId, {
modelUuid: material.current.modelUuid,
pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid,
});
setNextLocation(material.materialId, null);
setIsVisible(materialId, false);
if (action && human) {
if (human.isActive === false && human.state === 'idle') {
// Handle current action from arm bot
const model = getEventByModelUuid(selectedProduct.productUuid, action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (model?.type === 'transfer') {
const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (conveyor) {
const previousModel = getEventByModelUuid(selectedProduct.productUuid, material.previous?.modelUuid || '');
if (previousModel) {
if (previousModel.type === 'transfer' && previousModel.modelUuid === model.modelUuid) {
handleAction(action, materialId)
} else {
addConveyorToMonitor(conveyor.modelUuid,
() => {
handleAction(action, materialId)
}
)
}
} else {
handleAction(action, materialId)
}
// handleAction(action, materialId)
}
} else if (model?.type === 'vehicle') {
const vehicle = getVehicleById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (vehicle) {
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
// Handle current action from vehicle
setIsPaused(materialId, true);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addVehicleToMonitor(vehicle.modelUuid,
() => {
handleAction(action, materialId);
}
)
}
}
} else {
handleAction(action, materialId)
}
} else {
// Handle current action using Event Manager
addHumanToMonitor(human.modelUuid, () => {
const model = getEventByModelUuid(selectedProduct.productUuid, action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (model?.type === 'transfer') {
const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (conveyor) {
const previousModel = getEventByModelUuid(selectedProduct.productUuid, material.previous?.modelUuid || '');
if (previousModel) {
if (previousModel.type === 'transfer' && previousModel.modelUuid === model.modelUuid) {
handleAction(action, materialId)
} else {
addConveyorToMonitor(conveyor.modelUuid,
() => {
handleAction(action, materialId)
}
)
}
} else {
handleAction(action, materialId)
}
}
} else if (model?.type === 'vehicle') {
const vehicle = getVehicleById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (vehicle) {
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
// Handle current action from vehicle
setIsPaused(materialId, true);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addVehicleToMonitor(vehicle.modelUuid,
() => {
handleAction(action, materialId);
}
)
}
}
} else {
handleAction(action, materialId)
}
}
);
}
}
}
}
}
} else if (fromEvent?.type === 'roboticArm') {
if (toEvent?.type === 'transfer') {
@@ -821,7 +1207,7 @@ export function useTriggerHandler() {
}
}
} else if (toEvent?.type === 'human') {
// Robotic Arm to Vehicle
// Robotic Arm to Human
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
const material = getMaterialById(materialId);
if (material) {
@@ -895,7 +1281,6 @@ export function useTriggerHandler() {
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
const material = getMaterialById(materialId);
if (material) {
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
setPreviousLocation(material.materialId, {
modelUuid: material.current.modelUuid,
@@ -909,18 +1294,120 @@ export function useTriggerHandler() {
actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid,
});
setIsVisible(materialId, true);
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
if (action &&
if (action && action.triggers.length > 0 &&
action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid &&
action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid
) {
action.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid &&
action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid) {
const model = getEventByModelUuid(selectedProduct.productUuid, action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
if (model?.type === 'roboticArm') {
handleAction(action, material.materialId);
} else if (model?.type === 'vehicle') {
const nextAction = getActionByUuid(selectedProduct.productUuid, action.triggers[0]?.triggeredAsset?.triggeredAction.actionUuid);
if (action) {
handleAction(action, material.materialId);
const vehicle = getVehicleById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
setPreviousLocation(material.materialId, {
modelUuid: material.current.modelUuid,
pointUuid: material.current.pointUuid,
actionUuid: material.current.actionUuid,
})
setCurrentLocation(material.materialId, {
modelUuid: trigger.triggeredAsset?.triggeredModel.modelUuid,
pointUuid: trigger.triggeredAsset?.triggeredPoint?.pointUuid,
actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid,
});
setNextLocation(material.materialId, null);
if (nextAction) {
if (vehicle) {
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
setPreviousLocation(material.materialId, {
modelUuid: material.current.modelUuid,
pointUuid: material.current.pointUuid,
actionUuid: material.current.actionUuid,
})
setCurrentLocation(material.materialId, {
modelUuid: action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '',
pointUuid: action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid || '',
actionUuid: action.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid || '',
});
setNextLocation(material.materialId, null);
setIsVisible(materialId, false);
setIsPaused(materialId, false);
// Handle current action from vehicle
handleAction(nextAction, materialId);
} else {
// Handle current action using Event Manager
setIsPaused(materialId, true);
addVehicleToMonitor(vehicle.modelUuid,
() => {
setPreviousLocation(material.materialId, {
modelUuid: material.current.modelUuid,
pointUuid: material.current.pointUuid,
actionUuid: material.current.actionUuid,
})
setCurrentLocation(material.materialId, {
modelUuid: action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '',
pointUuid: action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid || '',
actionUuid: action.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid || '',
});
setNextLocation(material.materialId, null);
setIsPaused(materialId, false);
setIsVisible(materialId, false);
handleAction(nextAction, materialId);
}
)
}
}
}
}
} 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,
});
})
setIsPaused(material.materialId, false);
setIsVisible(material.materialId, true);
handleAction(action, material.materialId);
}
} else {
setNextLocation(material.materialId, {
modelUuid: action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid,
pointUuid: action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid,
})
handleAction(action, materialId);
handleAction(action, material.materialId);
}
} else if (action) {
setNextLocation(material.materialId, null)
handleAction(action, material.materialId);
}
}
@@ -929,9 +1416,96 @@ export function useTriggerHandler() {
} else if (toEvent?.type === 'vehicle') {
// Human to Vehicle
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
const material = getMaterialById(materialId);
if (material) {
setIsPaused(material.materialId, false);
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
const vehicle = getVehicleById(trigger.triggeredAsset?.triggeredModel.modelUuid);
setNextLocation(material.materialId, null);
if (action) {
if (vehicle) {
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
setIsVisible(materialId, false);
setPreviousLocation(material.materialId, {
modelUuid: material.current.modelUuid,
pointUuid: material.current.pointUuid,
actionUuid: material.current.actionUuid,
})
setCurrentLocation(material.materialId, {
modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid,
pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid,
});
// Handle current action from vehicle
handleAction(action, materialId);
} else {
// Event Manager Needed
}
}
}
}
}
} else if (toEvent?.type === 'machine') {
// Human to Machine
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
const material = getMaterialById(materialId);
if (material) {
// setIsPaused(material.materialId, false);
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
const machine = getMachineById(trigger.triggeredAsset?.triggeredModel.modelUuid);
setNextLocation(material.materialId, null);
if (action) {
if (machine) {
if (machine.isActive === false && machine.state === 'idle') {
setIsVisible(materialId, false);
setPreviousLocation(material.materialId, {
modelUuid: material.current.modelUuid,
pointUuid: material.current.pointUuid,
actionUuid: material.current.actionUuid,
})
setCurrentLocation(material.materialId, {
modelUuid: material.current.modelUuid,
pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid,
});
// Handle current action from machine
handleAction(action, materialId);
} else {
// Event Manager Needed
}
}
}
}
}
} else if (toEvent?.type === 'roboticArm') {
// Human to Robotic Arm
@@ -1013,6 +1587,9 @@ export function useTriggerHandler() {
}
}
}
} else if (toEvent?.type === 'human') {
// Human to Human
}
}
}

View File

@@ -13,9 +13,10 @@ import VehicleAnimator from '../animator/vehicleAnimator';
function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) {
const { navMesh } = useNavMesh();
const { isPlaying } = usePlayButtonStore();
const { materialStore, armBotStore, conveyorStore, vehicleStore, storageUnitStore, productStore } = useSceneContext();
const { materialStore, armBotStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, productStore } = useSceneContext();
const { removeMaterial, setEndTime } = materialStore();
const { getStorageUnitById } = storageUnitStore();
const { getHumanById } = humanStore();
const { getArmBotById } = armBotStore();
const { getConveyorById } = conveyorStore();
const { triggerPointActions } = useTriggerHandler();
@@ -246,6 +247,11 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
if (action) {
handleMaterialDropToStorageUnit(model);
}
} else if (model.type === 'human') {
const action = getActionByUuid(selectedProduct.productUuid, agvDetail.point.action.actionUuid);
if (action) {
handleMaterialDropToHuman(model);
}
}
} else {
const droppedMaterial = agvDetail.currentLoad;
@@ -259,6 +265,79 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}
}
function handleMaterialDropToHuman(model: HumanEventSchema) {
if (model) {
if (model.point.action.actionType === 'worker') {
loopMaterialDropToHuman(
agvDetail.modelUuid,
agvDetail.currentLoad,
agvDetail.point.action.unLoadDuration,
model.modelUuid,
model.point.action.loadCapacity,
agvDetail.point.action
);
}
}
}
function loopMaterialDropToHuman(
vehicleId: string,
vehicleCurrentLoad: number,
unLoadDuration: number,
humanId: string,
storageMaxCapacity: number,
action: VehicleAction
) {
startTime = performance.now();
const fixedInterval = ((unLoadDuration / vehicleCurrentLoad) * (1000 / isSpeedRef.current));
const unloadLoop = () => {
if (isPausedRef.current) {
pauseTimeRef.current ??= performance.now();
requestAnimationFrame(unloadLoop);
return;
}
if (pauseTimeRef.current) {
const pauseDuration = performance.now() - pauseTimeRef.current;
startTime += pauseDuration;
pauseTimeRef.current = null;
}
const elapsedTime = performance.now() - startTime;
const human = getHumanById(humanId);
if (elapsedTime >= fixedInterval) {
if (human && agvDetail &&
human.currentLoad < storageMaxCapacity &&
vehicleCurrentLoad > 0) {
decrementVehicleLoad(vehicleId, 1);
vehicleCurrentLoad -= 1;
const material = removeLastMaterial(vehicleId);
if (material) {
triggerPointActions(action, material.materialId);
}
if (vehicleCurrentLoad > 0 && human.currentLoad < storageMaxCapacity) {
startTime = performance.now();
requestAnimationFrame(unloadLoop);
}
}
} else {
requestAnimationFrame(unloadLoop);
}
};
const human = getHumanById(humanId);
if (human && vehicleCurrentLoad > 0 && human?.currentLoad < storageMaxCapacity) {
unloadLoop();
}
}
function handleMaterialDropToStorageUnit(model: StorageEventSchema) {
if (model) {
if (model.point.action.actionType === 'store') {