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

@@ -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') {