completed init movement for human

This commit is contained in:
2025-07-03 18:01:11 +05:30
parent 1e715cee50
commit 7cf82629e9
16 changed files with 302 additions and 567 deletions

View File

@@ -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() {
<section>
<ActionsList
selectedPointData={selectedPointData}
multipleAction
multipleAction={false}
handleAddAction={handleAddAction}
handleDeleteAction={handleDeleteAction}
/>
@@ -511,69 +228,20 @@ function HumanMechanics() {
{selectedAction.actionId && currentAction && (
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput
value={selectedAction.actionName || ""}
canEdit={false}
/>
<RenameInput value={selectedAction.actionName || ""} canEdit={false} />
</div>
<div className="selected-actions-list">
<LabledDropdown
label="Action Type"
defaultOption={activeOption}
options={availableActions.options}
options={["worker"]}
onSelect={handleSelectActionType}
disabled={true}
/>
</div>
<AnimationList
animationOptions={animationOptions}
animationSequences={currentAction?.animationSequences || []}
onAddAnimation={handleAddAnimation}
onRemoveAnimation={handleRemoveAnimation}
handleAnimationSelect={handleAnimationSelect}
handleRenameAnimation={handleRenameAnimation}
/>
{selectedAnimation && (
<>
<div className="selected-actions-header">
<RenameInput
value={selectedAnimation.animationName || ""}
canEdit={false}
/>
</div>
<div className="animation-controls">
<LabledDropdown
label="Animation Type"
defaultOption={selectedAnimation.animationType}
options={["behaviour", "animatedTravel"]}
onSelect={(type) =>
handleAnimationTypeChange(
selectedAnimation.animationUuid,
type as "behaviour" | "animatedTravel"
)
}
/>
<LabledDropdown
label="Animation"
defaultOption={selectedAnimation.animation || ''}
options={animationOptions}
onSelect={handleChooseAnimation}
disabled={true}
/>
{selectedAnimation.animationType === "animatedTravel" && (
<PickAndPlaceAction
clearPoints={() => handleClearPoints(selectedAnimation.animationUuid)}
/>
)}
</div>
</>
)}
<PickAndPlaceAction clearPoints={handleClearPoints} />
<div className="tirgger">
<Trigger
selectedPointData={selectedPointData as any}
type={"Human"}
/>
<Trigger selectedPointData={selectedPointData as any} type="Human" />
</div>
</div>
)}

View File

@@ -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);

View File

@@ -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: []
}
}
}

View File

@@ -30,7 +30,7 @@ export const handleAddEventToProduct = ({
projectId: projectId || '',
eventDatas: event
}).then((data) => {
console.log(data);
// console.log(data);
})
if (clearSelectedAsset) {

View File

@@ -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() {
});
}
});
});
}
}
});

View File

@@ -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
}

View File

@@ -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);

View File

@@ -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<HumanAnimatorProps>) {
const { humanStore } = useSceneContext();
const { getHumanById } = humanStore();
const { isPaused } = usePauseButtonStore();
const { isPlaying } = usePlayButtonStore();
const { speed } = useAnimationPlaySpeed();
const { isReset, setReset } = useResetButtonStore();
const progressRef = useRef<number>(0);
const movingForward = useRef<boolean>(true);
const completedRef = useRef<boolean>(false);
const [objectRotation, setObjectRotation] = useState<[number, number, number] | null>(human.point?.action?.pickUpPoint?.rotation || [0, 0, 0])
const [restRotation, setRestingRotation] = useState<boolean>(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
<group >
<Line points={currentPath} color="blue" lineWidth={3} />
{currentPath.map((point, index) => (
<mesh key={index} position={point}>
<sphereGeometry args={[0.1, 16, 16]} />
<meshStandardMaterial color="red" />
</mesh>
))}
</group>
)}
</>
)
}
export default HumanAnimator

View File

@@ -1,10 +0,0 @@
import React from 'react'
function HumanAnimator() {
return (
<>
</>
)
}
export default HumanAnimator

View File

@@ -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 (
<>
<HumanAnimator />
<HumanAnimator
path={path}
handleCallBack={handleCallBack}
currentPhase={currentPhase}
human={human}
reset={reset}
startUnloadingProcess={startUnloadingProcess}
/>
</>
)

View File

@@ -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;

View File

@@ -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);
})
}

View File

@@ -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(() => {

View File

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

View File

@@ -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<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]>
updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['action']>
) => EventsSchema | undefined;
// Trigger-level actionss

View File

@@ -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;