feat: Introduce animation components for worker, manufacturer, and operator humans, model animators, and a new vehicle state management store.
This commit is contained in:
@@ -60,14 +60,16 @@ export function ModelAnimator({ asset, gltfScene }: ModelAnimatorProps) {
|
|||||||
if (isPlaying && currentAction && !isPaused) {
|
if (isPlaying && currentAction && !isPaused) {
|
||||||
blendFactor.current = 0;
|
blendFactor.current = 0;
|
||||||
|
|
||||||
|
Object.values(actions.current).forEach((action) => {
|
||||||
|
if (action !== currentAction) {
|
||||||
|
action.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
currentAction.reset();
|
currentAction.reset();
|
||||||
currentAction.setLoop(loopAnimation ? THREE.LoopRepeat : THREE.LoopOnce, loopAnimation ? Infinity : 1);
|
currentAction.setLoop(loopAnimation ? THREE.LoopRepeat : THREE.LoopOnce, loopAnimation ? Infinity : 1);
|
||||||
currentAction.clampWhenFinished = true;
|
currentAction.clampWhenFinished = true;
|
||||||
|
|
||||||
if (previousAction && previousAction !== currentAction) {
|
|
||||||
previousAction.crossFadeTo(currentAction, blendDuration, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentAction.play();
|
currentAction.play();
|
||||||
mixerRef.current.addEventListener("finished", handleAnimationComplete);
|
mixerRef.current.addEventListener("finished", handleAnimationComplete);
|
||||||
setPreviousAnimation(current);
|
setPreviousAnimation(current);
|
||||||
|
|||||||
@@ -108,15 +108,8 @@ function ManufacturerAnimator({ path, handleCallBack, human, reset }: Readonly<M
|
|||||||
const isAligned = angle < 0.01;
|
const isAligned = angle < 0.01;
|
||||||
|
|
||||||
if (isAligned) {
|
if (isAligned) {
|
||||||
const distanceStep = delta * (speed * human.speed);
|
progressRef.current = Math.min(progressRef.current + delta * (speed * human.speed), totalDistance);
|
||||||
const previousProgress = progressRef.current;
|
incrementDistanceTraveled(human.modelUuid, delta * (speed * human.speed));
|
||||||
progressRef.current = Math.min(progressRef.current + distanceStep, totalDistance);
|
|
||||||
const actualStep = progressRef.current - previousProgress;
|
|
||||||
|
|
||||||
if (actualStep > 0) {
|
|
||||||
incrementDistanceTraveled(human.modelUuid, actualStep);
|
|
||||||
}
|
|
||||||
|
|
||||||
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
|
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
|
||||||
const position = start.clone().lerp(end, t);
|
const position = start.clone().lerp(end, t);
|
||||||
object.position.copy(position);
|
object.position.copy(position);
|
||||||
|
|||||||
@@ -116,15 +116,8 @@ function OperatorAnimator({ path, handleCallBack, human, reset }: Readonly<Worke
|
|||||||
const isAligned = angle < 0.01;
|
const isAligned = angle < 0.01;
|
||||||
|
|
||||||
if (isAligned) {
|
if (isAligned) {
|
||||||
const distanceStep = delta * (speed * human.speed);
|
progressRef.current = Math.min(progressRef.current + delta * (speed * human.speed), totalDistance);
|
||||||
const previousProgress = progressRef.current;
|
incrementDistanceTraveled(human.modelUuid, delta * (speed * human.speed));
|
||||||
progressRef.current = Math.min(progressRef.current + distanceStep, totalDistance);
|
|
||||||
const actualStep = progressRef.current - previousProgress;
|
|
||||||
|
|
||||||
if (actualStep > 0) {
|
|
||||||
incrementDistanceTraveled(human.modelUuid, actualStep);
|
|
||||||
}
|
|
||||||
|
|
||||||
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
|
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
|
||||||
const position = start.clone().lerp(end, t);
|
const position = start.clone().lerp(end, t);
|
||||||
object.position.copy(position);
|
object.position.copy(position);
|
||||||
|
|||||||
@@ -118,15 +118,8 @@ function WorkerAnimator({ path, handleCallBack, human, reset, startUnloadingProc
|
|||||||
const isAligned = angle < 0.01;
|
const isAligned = angle < 0.01;
|
||||||
|
|
||||||
if (isAligned) {
|
if (isAligned) {
|
||||||
const distanceStep = delta * (speed * human.speed);
|
progressRef.current = Math.min(progressRef.current + delta * (speed * human.speed), totalDistance);
|
||||||
const previousProgress = progressRef.current;
|
incrementDistanceTraveled(human.modelUuid, delta * (speed * human.speed));
|
||||||
progressRef.current = Math.min(progressRef.current + distanceStep, totalDistance);
|
|
||||||
const actualStep = progressRef.current - previousProgress;
|
|
||||||
|
|
||||||
if (actualStep > 0) {
|
|
||||||
incrementDistanceTraveled(human.modelUuid, actualStep);
|
|
||||||
}
|
|
||||||
|
|
||||||
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
|
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
|
||||||
const position = start.clone().lerp(end, t);
|
const position = start.clone().lerp(end, t);
|
||||||
object.position.copy(position);
|
object.position.copy(position);
|
||||||
|
|||||||
@@ -6,10 +6,7 @@ interface VehiclesStore {
|
|||||||
|
|
||||||
addVehicle: (productUuid: string, event: VehicleEventSchema) => void;
|
addVehicle: (productUuid: string, event: VehicleEventSchema) => void;
|
||||||
removeVehicle: (modelUuid: string) => void;
|
removeVehicle: (modelUuid: string) => void;
|
||||||
updateVehicle: (
|
updateVehicle: (modelUuid: string, updates: Partial<Omit<VehicleStatus, "modelUuid" | "productUuid">>) => void;
|
||||||
modelUuid: string,
|
|
||||||
updates: Partial<Omit<VehicleStatus, "modelUuid" | "productUuid">>
|
|
||||||
) => void;
|
|
||||||
addPathPoint: (modelUuid: string, pathKey: keyof VehicleAction["paths"], point: VehicleAction["paths"]["initPickup"][number]) => VehicleAction["paths"];
|
addPathPoint: (modelUuid: string, pathKey: keyof VehicleAction["paths"], point: VehicleAction["paths"]["initPickup"][number]) => VehicleAction["paths"];
|
||||||
updatePathPoint: (modelUuid: string, pathKey: keyof VehicleAction["paths"], pointId: string, updates: Partial<VehicleAction["paths"]["initPickup"][number]>) => VehicleAction["paths"];
|
updatePathPoint: (modelUuid: string, pathKey: keyof VehicleAction["paths"], pointId: string, updates: Partial<VehicleAction["paths"]["initPickup"][number]>) => VehicleAction["paths"];
|
||||||
deletePathPoint: (modelUuid: string, pathKey: keyof VehicleAction["paths"], pointId: string) => VehicleAction["paths"];
|
deletePathPoint: (modelUuid: string, pathKey: keyof VehicleAction["paths"], pointId: string) => VehicleAction["paths"];
|
||||||
@@ -22,17 +19,15 @@ interface VehiclesStore {
|
|||||||
incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void;
|
incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void;
|
||||||
decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void;
|
decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void;
|
||||||
setVehicleLoad: (modelUuid: string, load: number) => void;
|
setVehicleLoad: (modelUuid: string, load: number) => void;
|
||||||
setVehicleState: (
|
setVehicleState: (modelUuid: string, newState: VehicleStatus["state"]) => void;
|
||||||
modelUuid: string,
|
|
||||||
newState: VehicleStatus["state"]
|
|
||||||
) => void;
|
|
||||||
addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void;
|
addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void;
|
||||||
setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string; }[]) => void;
|
setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string }[]) => void;
|
||||||
removeLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined;
|
removeLastMaterial: (modelUuid: string) => { materialId: string; materialType: string } | undefined;
|
||||||
getLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined;
|
getLastMaterial: (modelUuid: string) => { materialId: string; materialType: string } | undefined;
|
||||||
clearCurrentMaterials: (modelUuid: string) => void;
|
clearCurrentMaterials: (modelUuid: string) => void;
|
||||||
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
incrementDistanceTraveled: (modelUuid: string, incrementBy: number) => void;
|
||||||
resetTime: (modelUuid: string) => void;
|
resetTime: (modelUuid: string) => void;
|
||||||
|
|
||||||
getVehicleById: (modelUuid: string) => VehicleStatus | undefined;
|
getVehicleById: (modelUuid: string) => VehicleStatus | undefined;
|
||||||
@@ -53,7 +48,7 @@ export const createVehicleStore = () => {
|
|||||||
state.vehicles.push({
|
state.vehicles.push({
|
||||||
...event,
|
...event,
|
||||||
productUuid,
|
productUuid,
|
||||||
currentPhase: 'stationed',
|
currentPhase: "stationed",
|
||||||
isActive: false,
|
isActive: false,
|
||||||
isPicking: false,
|
isPicking: false,
|
||||||
idleTime: 0,
|
idleTime: 0,
|
||||||
@@ -61,7 +56,7 @@ export const createVehicleStore = () => {
|
|||||||
currentLoad: 0,
|
currentLoad: 0,
|
||||||
currentMaterials: [],
|
currentMaterials: [],
|
||||||
distanceTraveled: 0,
|
distanceTraveled: 0,
|
||||||
state: 'idle'
|
state: "idle",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -69,9 +64,7 @@ export const createVehicleStore = () => {
|
|||||||
|
|
||||||
removeVehicle: (modelUuid) => {
|
removeVehicle: (modelUuid) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.vehicles = state.vehicles.filter(
|
state.vehicles = state.vehicles.filter((v) => v.modelUuid !== modelUuid);
|
||||||
(v) => v.modelUuid !== modelUuid
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -87,7 +80,7 @@ export const createVehicleStore = () => {
|
|||||||
addPathPoint: (modelUuid, pathKey, point) => {
|
addPathPoint: (modelUuid, pathKey, point) => {
|
||||||
let updatedPaths: VehicleAction["paths"] = { initPickup: [], pickupDrop: [], dropPickup: [] };
|
let updatedPaths: VehicleAction["paths"] = { initPickup: [], pickupDrop: [], dropPickup: [] };
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
|
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||||
if (vehicle) {
|
if (vehicle) {
|
||||||
const path = vehicle.point.action.paths[pathKey];
|
const path = vehicle.point.action.paths[pathKey];
|
||||||
path.push(point);
|
path.push(point);
|
||||||
@@ -100,10 +93,10 @@ export const createVehicleStore = () => {
|
|||||||
updatePathPoint: (modelUuid, pathKey, pointId, updates) => {
|
updatePathPoint: (modelUuid, pathKey, pointId, updates) => {
|
||||||
let updatedPaths: VehicleAction["paths"] = { initPickup: [], pickupDrop: [], dropPickup: [] };
|
let updatedPaths: VehicleAction["paths"] = { initPickup: [], pickupDrop: [], dropPickup: [] };
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
|
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||||
if (vehicle) {
|
if (vehicle) {
|
||||||
const path = vehicle.point.action.paths[pathKey];
|
const path = vehicle.point.action.paths[pathKey];
|
||||||
const index = path.findIndex(p => p.pointId === pointId);
|
const index = path.findIndex((p) => p.pointId === pointId);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
Object.assign(path[index], updates);
|
Object.assign(path[index], updates);
|
||||||
updatedPaths = vehicle.point.action.paths;
|
updatedPaths = vehicle.point.action.paths;
|
||||||
@@ -116,10 +109,10 @@ export const createVehicleStore = () => {
|
|||||||
deletePathPoint: (modelUuid, pathKey, pointId) => {
|
deletePathPoint: (modelUuid, pathKey, pointId) => {
|
||||||
let updatedPaths: VehicleAction["paths"] = { initPickup: [], pickupDrop: [], dropPickup: [] };
|
let updatedPaths: VehicleAction["paths"] = { initPickup: [], pickupDrop: [], dropPickup: [] };
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
|
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||||
if (vehicle) {
|
if (vehicle) {
|
||||||
const path = vehicle.point.action.paths[pathKey];
|
const path = vehicle.point.action.paths[pathKey];
|
||||||
vehicle.point.action.paths[pathKey] = path.filter(p => p.pointId !== pointId);
|
vehicle.point.action.paths[pathKey] = path.filter((p) => p.pointId !== pointId);
|
||||||
updatedPaths = vehicle.point.action.paths;
|
updatedPaths = vehicle.point.action.paths;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -134,7 +127,7 @@ export const createVehicleStore = () => {
|
|||||||
|
|
||||||
setCurrentPhase: (modelUuid, phase) => {
|
setCurrentPhase: (modelUuid, phase) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
|
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||||
if (vehicle) {
|
if (vehicle) {
|
||||||
vehicle.currentPhase = phase;
|
vehicle.currentPhase = phase;
|
||||||
}
|
}
|
||||||
@@ -223,7 +216,7 @@ export const createVehicleStore = () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
removeLastMaterial: (modelUuid) => {
|
removeLastMaterial: (modelUuid) => {
|
||||||
let removedMaterial: { materialId: string; materialType: string; } | undefined;
|
let removedMaterial: { materialId: string; materialType: string } | undefined;
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||||
if (vehicle) {
|
if (vehicle) {
|
||||||
@@ -239,14 +232,14 @@ export const createVehicleStore = () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getLastMaterial: (modelUuid) => {
|
getLastMaterial: (modelUuid) => {
|
||||||
let removedMaterial: { materialId: string; materialType: string; } | undefined;
|
let removedMaterial: { materialId: string; materialType: string } | undefined;
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||||
if (vehicle) {
|
if (vehicle) {
|
||||||
if (vehicle.currentMaterials.length > 0) {
|
if (vehicle.currentMaterials.length > 0) {
|
||||||
removedMaterial = {
|
removedMaterial = {
|
||||||
materialId: vehicle.currentMaterials[vehicle.currentMaterials.length - 1].materialId,
|
materialId: vehicle.currentMaterials[vehicle.currentMaterials.length - 1].materialId,
|
||||||
materialType: vehicle.currentMaterials[vehicle.currentMaterials.length - 1].materialType
|
materialType: vehicle.currentMaterials[vehicle.currentMaterials.length - 1].materialType,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,6 +274,15 @@ export const createVehicleStore = () => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
incrementDistanceTraveled: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||||
|
if (vehicle) {
|
||||||
|
vehicle.distanceTraveled += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
resetTime: (modelUuid) => {
|
resetTime: (modelUuid) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||||
@@ -307,7 +309,7 @@ export const createVehicleStore = () => {
|
|||||||
return get().vehicles.filter((v) => v.isActive);
|
return get().vehicles.filter((v) => v.isActive);
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export type VehicleStoreType = ReturnType<typeof createVehicleStore>;
|
export type VehicleStoreType = ReturnType<typeof createVehicleStore>;
|
||||||
|
|||||||
Reference in New Issue
Block a user