Merge remote-tracking branch 'origin/simulation-agv-v2' into v2

This commit is contained in:
2025-05-08 13:45:50 +05:30
5 changed files with 386 additions and 240 deletions

View File

@@ -1,232 +1,372 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from "react";
import * as Types from "../../../../types/world/worldTypes"; import * as Types from "../../../../types/world/worldTypes";
import startPoint from "../../../../assets/gltf-glb/arrow_green.glb"; import startPoint from "../../../../assets/gltf-glb/arrow_green.glb";
import * as THREE from "three";
import startEnd from "../../../../assets/gltf-glb/arrow_red.glb"; import startEnd from "../../../../assets/gltf-glb/arrow_red.glb";
import { useGLTF } from '@react-three/drei'; import { useGLTF } from "@react-three/drei";
import { useFrame, useThree } from '@react-three/fiber'; import { useFrame, useThree } from "@react-three/fiber";
import { useSelectedEventSphere, useIsDragging, useIsRotating } from '../../../../store/simulation/useSimulationStore'; import {
import { useVehicleStore } from '../../../../store/simulation/useVehicleStore'; useSelectedEventSphere,
import { useProductStore } from '../../../../store/simulation/useProductStore'; useIsDragging,
import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore'; useIsRotating,
import { upsertProductOrEventApi } from '../../../../services/simulation/UpsertProductOrEventApi'; } from "../../../../store/simulation/useSimulationStore";
import { useVehicleStore } from "../../../../store/simulation/useVehicleStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
import { Box3, DoubleSide, Euler, Group, Mesh, Plane, Quaternion, Vector3 } from "three";
import { position } from "html2canvas/dist/types/css/property-descriptors/position";
const VehicleUI = () => { const VehicleUI = () => {
const { scene: startScene } = useGLTF(startPoint) as any; const { scene: startScene } = useGLTF(startPoint) as any;
const { scene: endScene } = useGLTF(startEnd) as any; const { scene: endScene } = useGLTF(startEnd) as any;
const startMarker = useRef<THREE.Group>(null); const startMarker = useRef<Group>(null);
const endMarker = useRef<THREE.Group>(null); const endMarker = useRef<Group>(null);
const prevMousePos = useRef({ x: 0, y: 0 }); const prevMousePos = useRef({ x: 0, y: 0 });
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventSphere } = useSelectedEventSphere();
const { selectedProduct } = useSelectedProduct(); const { selectedProduct } = useSelectedProduct();
const { getVehicleById } = useVehicleStore(); const { getVehicleById } = useVehicleStore();
const { updateEvent } = useProductStore(); const { updateEvent } = useProductStore();
const [startPosition, setStartPosition] = useState<[number, number, number]>([0, 0, 0]); const [startPosition, setStartPosition] = useState<[number, number, number]>([
const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 0, 0]); 0, 1, 0,
const [startRotation, setStartRotation] = useState<[number, number, number]>([0, 0, 0]); ]);
const [endRotation, setEndRotation] = useState<[number, number, number]>([0, 0, 0]);
const { isDragging, setIsDragging } = useIsDragging();
const { isRotating, setIsRotating } = useIsRotating();
const { raycaster } = useThree();
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0));
const state: Types.ThreeState = useThree();
const controls: any = state.controls;
const email = localStorage.getItem('email')
const organization = (email!.split("@")[1]).split(".")[0];
const updateBackend = ( const [endPosition, setEndPosition] = useState<[number, number, number]>([
productName: string, 0, 1, 0,
productId: string, ]);
organization: string, const [startRotation, setStartRotation] = useState<[number, number, number]>([
eventData: EventsSchema 0, 0, 0,
) => { ]);
upsertProductOrEventApi({
productName: productName,
productId: productId,
organization: organization,
eventDatas: eventData
})
}
useEffect(() => { const [endRotation, setEndRotation] = useState<[number, number, number]>([
if (!selectedEventSphere) return; 0, 0, 0,
const selectedVehicle = getVehicleById(selectedEventSphere.userData.modelUuid); ]);
const [steeringRotation, setSteeringRotation] = useState<
[number, number, number]
>([0, 0, 0]);
if (selectedVehicle?.point?.action) { const { isDragging, setIsDragging } = useIsDragging();
const { pickUpPoint, unLoadPoint } = selectedVehicle.point.action; const { isRotating, setIsRotating } = useIsRotating();
const { raycaster } = useThree();
const [point, setPoint] = useState<
[number, number, number]
>([0, 0, 0]);
const plane = useRef(new Plane(new Vector3(0, 1, 0), 0));
const [tubeRotation, setTubeRotation] = useState<boolean>(false);
const tubeRef = useRef<Group>(null);
const outerGroup = useRef<Group>(null);
const state: Types.ThreeState = useThree();
const controls: any = state.controls;
const [selectedVehicleData, setSelectedVechicleData] = useState<
{ position: [number, number, number], rotation: [number, number, number], }
>({ position: [0, 0, 0], rotation: [0, 0, 0], });
const CIRCLE_RADIUS = 0.8;
const email = localStorage.getItem("email");
const organization = email!.split("@")[1].split(".")[0];
if (pickUpPoint) { const updateBackend = (
setStartPosition([pickUpPoint.position.x, 0, pickUpPoint.position.z]); productName: string,
setStartRotation([pickUpPoint.rotation.x, pickUpPoint.rotation.y, pickUpPoint.rotation.z]); productId: string,
organization: string,
eventData: EventsSchema
) => {
upsertProductOrEventApi({
productName: productName,
productId: productId,
organization: organization,
eventDatas: eventData,
});
};
useEffect(() => {
if (!selectedEventSphere) return;
const selectedVehicle = getVehicleById(
selectedEventSphere.userData.modelUuid
);
if (selectedVehicle) {
setSelectedVechicleData({ position: selectedVehicle.position, rotation: selectedVehicle.rotation });
setPoint(selectedVehicle.point.position)
}
setTimeout(() => {
if (selectedVehicle?.point?.action) {
const { pickUpPoint, unLoadPoint, steeringAngle } = selectedVehicle.point.action;
if (pickUpPoint && outerGroup.current) {
const worldPos = new Vector3(
pickUpPoint.position.x,
pickUpPoint.position.y,
pickUpPoint.position.z
);
const localPosition = outerGroup.current.worldToLocal(worldPos.clone());
setStartPosition([localPosition.x, selectedVehicle.point.position[1], localPosition.z,
]);
setStartRotation([pickUpPoint.rotation.x, pickUpPoint.rotation.y, pickUpPoint.rotation.z,])
} else { } else {
const defaultLocal = new THREE.Vector3(0, 0, 1.5); setStartPosition([0, selectedVehicle.point.position[1] + 0.1, 1.5]);
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); setStartRotation([0, 0, 0]);
setStartPosition([defaultWorld.x, 0, defaultWorld.z]);
setStartRotation([0, 0, 0]);
} }
// end point
if (unLoadPoint && outerGroup.current) {
const worldPos = new Vector3(unLoadPoint.position.x, unLoadPoint.position.y, unLoadPoint.position.z);
const localPosition = outerGroup.current.worldToLocal(worldPos);
if (unLoadPoint) { setEndPosition([localPosition.x, selectedVehicle.point.position[1], localPosition.z]);
setEndPosition([unLoadPoint.position.x, 0, unLoadPoint.position.z]); setEndRotation([unLoadPoint.rotation.x, unLoadPoint.rotation.y, unLoadPoint.rotation.z,
setEndRotation([unLoadPoint.rotation.x, unLoadPoint.rotation.y, unLoadPoint.rotation.z]); ]);
} else { } else {
const defaultLocal = new THREE.Vector3(0, 0, -1.5); setEndPosition([0, selectedVehicle.point.position[1] + 0.1, -1.5]);
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); setEndRotation([0, 0, 0]);
setEndPosition([defaultWorld.x, 0, defaultWorld.z]);
setEndRotation([0, 0, 0]);
} }
} setSteeringRotation([0, steeringAngle, 0])
}, [selectedEventSphere]); }
}, 10);
useFrame(() => {
if (!isDragging) return;
const intersectPoint = new THREE.Vector3();
const intersects = raycaster.ray.intersectPlane(plane.current, intersectPoint);
if (intersects) {
if (isDragging === "start") {
setStartPosition([intersectPoint.x, 0, intersectPoint.z]);
}
if (isDragging === "end") {
setEndPosition([intersectPoint.x, 0, intersectPoint.z]);
}
}
});
useFrame((state) => {
if (!isRotating) return;
const currentPointerX = state.pointer.x;
const deltaX = currentPointerX - prevMousePos.current.x;
prevMousePos.current.x = currentPointerX;
const marker = isRotating === "start" ? startMarker.current : endMarker.current;
if (marker) {
const rotationSpeed = 10;
if (isRotating === 'start') {
const y = startRotation[1] + deltaX * rotationSpeed;
setStartRotation([0, y, 0]);
} else {
const y = endRotation[1] + deltaX * rotationSpeed;
setEndRotation([0, y, 0]);
}
}
});
const handlePointerDown = (e: any, state: "start" | "end", rotation: "start" | "end") => { }, [selectedEventSphere, outerGroup.current]);
if (e.object.name === "handle") { const handlePointerDown = (
const normalizedX = (e.clientX / window.innerWidth) * 2 - 1; e: any,
const normalizedY = -(e.clientY / window.innerHeight) * 2 + 1; state: "start" | "end",
prevMousePos.current = { x: normalizedX, y: normalizedY }; rotation: "start" | "end"
setIsRotating(rotation); ) => {
if (controls) controls.enabled = false; if (e.object.name === "handle") {
setIsDragging(null); const normalizedX = (e.clientX / window.innerWidth) * 2 - 1;
const normalizedY = -(e.clientY / window.innerHeight) * 2 + 1;
prevMousePos.current = { x: normalizedX, y: normalizedY };
setIsRotating(rotation);
if (controls) controls.enabled = false;
setIsDragging(null);
} else {
setIsDragging(state);
setIsRotating(null);
if (controls) controls.enabled = false;
}
};
} else { const handlePointerUp = () => {
setIsDragging(state); controls.enabled = true;
setIsRotating(null); setIsDragging(null);
if (controls) controls.enabled = false; setIsRotating(null);
}
};
const handlePointerUp = () => { if (selectedEventSphere?.userData.modelUuid) {
controls.enabled = true; const updatedVehicle = getVehicleById(
setIsDragging(null); selectedEventSphere.userData.modelUuid
setIsRotating(null); );
if (selectedEventSphere?.userData.modelUuid) { let globalStartPosition = null;
const updatedVehicle = getVehicleById(selectedEventSphere.userData.modelUuid); let globalEndPosition = null;
if (updatedVehicle) { if (outerGroup.current && startMarker.current && endMarker.current) {
const event = updateEvent(selectedProduct.productId, selectedEventSphere.userData.modelUuid, { const worldPosStart = new Vector3(...startPosition);
point: { globalStartPosition = outerGroup.current.localToWorld(worldPosStart.clone());
...updatedVehicle.point, const worldPosEnd = new Vector3(...endPosition);
action: { globalEndPosition = outerGroup.current.localToWorld(worldPosEnd.clone());
...updatedVehicle.point?.action, }
pickUpPoint: { if (updatedVehicle && globalEndPosition && globalStartPosition) {
position: { x: startPosition[0], y: startPosition[1], z: startPosition[2], }, const event = updateEvent(
rotation: { x: 0, y: startRotation[1], z: 0, }, selectedProduct.productId,
}, selectedEventSphere.userData.modelUuid,
unLoadPoint: { {
position: { x: endPosition[0], y: endPosition[1], z: endPosition[2], }, point: {
rotation: { x: 0, y: endRotation[1], z: 0, }, ...updatedVehicle.point,
}, action: {
...updatedVehicle.point?.action,
pickUpPoint: {
position: {
x: globalStartPosition.x,
y: 0,
z: globalStartPosition.z,
},
rotation: { x: 0, y: startRotation[1], z: 0 },
}, },
}, unLoadPoint: {
}) position: {
x: globalEndPosition.x,
y: 0,
z: globalEndPosition.z,
},
rotation: { x: 0, y: endRotation[1], z: 0 },
},
steeringAngle: steeringRotation[1]
},
},
}
);
if (event) { if (event) {
updateBackend( updateBackend(
selectedProduct.productName, selectedProduct.productName,
selectedProduct.productId, selectedProduct.productId,
organization, organization,
event event
); );
}
} }
} }
}; }
};
useEffect(() => { useFrame(() => {
const handleGlobalPointerUp = () => { if (!isDragging || !plane.current || !raycaster || !outerGroup.current) return;
setIsDragging(null); const intersectPoint = new Vector3();
setIsRotating(null); const intersects = raycaster.ray.intersectPlane(plane.current, intersectPoint);
if (controls) controls.enabled = true; if (!intersects) return;
handlePointerUp(); const localPoint = outerGroup?.current.worldToLocal(intersectPoint.clone());
}; if (isDragging === "start") {
if (startMarker.current) {
if (isDragging || isRotating) { }
window.addEventListener("pointerup", handleGlobalPointerUp); setStartPosition([localPoint.x, point[1], localPoint.z]);
} } else if (isDragging === "end") {
setEndPosition([localPoint.x, point[1], localPoint.z]);
}
});
return () => { useEffect(() => {
window.removeEventListener("pointerup", handleGlobalPointerUp); const handleGlobalPointerUp = () => {
}; setIsDragging(null);
}, [isDragging, isRotating, startPosition, startRotation, endPosition, endRotation]); setIsRotating(null);
setTubeRotation(false);
if (controls) controls.enabled = true;
handlePointerUp();
return ( };
startPosition.length > 0 && endPosition.length > 0 ? (
<mesh> if (isDragging || isRotating || tubeRotation) {
<primitive window.addEventListener("pointerup", handleGlobalPointerUp);
name="start" }
object={startScene}
ref={startMarker} return () => {
position={startPosition} window.removeEventListener("pointerup", handleGlobalPointerUp);
rotation={startRotation} };
onPointerDown={(e: any) => { }, [
e.stopPropagation(); isDragging, isRotating, startPosition, startRotation, endPosition, endRotation, tubeRotation, steeringRotation, outerGroup.current, tubeRef.current
handlePointerDown(e, "start", "start"); ]);
}}
onPointerMissed={() => {
controls.enabled = true; const prevSteeringY = useRef(0);
setIsDragging(null); useFrame((state) => {
setIsRotating(null); if (tubeRotation) {
}} const currentPointerX = state.pointer.x;
/> const deltaX = currentPointerX - prevMousePos.current.x;
prevMousePos.current.x = currentPointerX;
const marker = tubeRef.current;
if (marker) {
const rotationSpeed = 2;
marker.rotation.y += deltaX * rotationSpeed;
setSteeringRotation([marker.rotation.x, marker.rotation.y, marker.rotation.z]);
}
} else {
prevSteeringY.current = 0;
}
});
useFrame((state) => {
if (!isRotating) return;
const currentPointerX = state.pointer.x;
const deltaX = currentPointerX - prevMousePos.current.x;
prevMousePos.current.x = currentPointerX;
const marker =
isRotating === "start" ? startMarker.current : endMarker.current;
if (marker) {
const rotationSpeed = 10;
marker.rotation.y += deltaX * rotationSpeed;
if (isRotating === "start") {
setStartRotation([
marker.rotation.x,
marker.rotation.y,
marker.rotation.z,
]);
} else {
setEndRotation([
marker.rotation.x,
marker.rotation.y,
marker.rotation.z,
]);
}
}
});
return selectedVehicleData ? (
<group position={selectedVehicleData.position} rotation={selectedVehicleData.rotation} ref={outerGroup}>
<group
position={[0, 0, 0]}
ref={tubeRef}
rotation={steeringRotation}
onPointerDown={(e) => {
e.stopPropagation();
setTubeRotation(true);
prevMousePos.current.x = e.pointer.x;
controls.enabled = false;
}}
onPointerMissed={() => {
controls.enabled = true;
setTubeRotation(false);
}}
onPointerUp={() => {
controls.enabled = true;
setTubeRotation(false);
}}
>
(
<mesh
position={[0, point[1], 0]}
rotation={[-Math.PI / 2, 0, 0]}
name="steering"
>
<ringGeometry args={[CIRCLE_RADIUS, CIRCLE_RADIUS + 0.2, 36]} />
<meshBasicMaterial color="yellow" side={DoubleSide} />
<primitive
name="end"
object={endScene}
ref={endMarker}
position={endPosition}
rotation={endRotation}
onPointerDown={(e: any) => {
e.stopPropagation();
handlePointerDown(e, "end", "end");
}}
onPointerMissed={() => {
controls.enabled = true;
setIsDragging(null);
setIsRotating(null);
}}
/>
</mesh> </mesh>
) : null <mesh position={[0, point[1], CIRCLE_RADIUS + 0.24]} rotation={[Math.PI / 2, 0, 0]}>
); <coneGeometry args={[0.1, 0.3, 12]} />
} <meshBasicMaterial color="yellow" side={DoubleSide} />
</mesh>
)
</group>
{/* Start Marker */}
<primitive
name="startMarker"
object={startScene}
ref={startMarker}
position={startPosition}
rotation={startRotation}
onPointerDown={(e: any) => {
e.stopPropagation();
handlePointerDown(e, "start", "start");
}}
onPointerMissed={() => {
controls.enabled = true;
setIsDragging(null);
setIsRotating(null);
}}
/>
{/* End Marker */}
<primitive
name="endMarker"
object={endScene}
ref={endMarker}
position={endPosition}
rotation={endRotation}
onPointerDown={(e: any) => {
e.stopPropagation();
handlePointerDown(e, "end", "end");
}}
onPointerMissed={() => {
controls.enabled = true;
setIsDragging(null);
setIsRotating(null);
}}
/>
</group>
) : null;
};
export default VehicleUI; export default VehicleUI;

View File

@@ -25,6 +25,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
const completedRef = useRef<boolean>(false); const completedRef = useRef<boolean>(false);
const isPausedRef = useRef<boolean>(false); const isPausedRef = useRef<boolean>(false);
const pauseTimeRef = useRef<number | null>(null); const pauseTimeRef = useRef<number | null>(null);
const [objectRotation, setObjectRotation] = useState<{ x: number; y: number; z: number } | undefined>(agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 })
const [progress, setProgress] = useState<number>(0); const [progress, setProgress] = useState<number>(0);
const [restRotation, setRestingRotation] = useState<boolean>(true); const [restRotation, setRestingRotation] = useState<boolean>(true);
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
@@ -32,20 +33,19 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
let startTime: number; let startTime: number;
let fixedInterval: number; let fixedInterval: number;
let coveredDistance = progressRef.current; let coveredDistance = progressRef.current;
let objectRotation = (agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 }) as { x: number; y: number; z: number } | undefined;
useEffect(() => { useEffect(() => {
if (currentPhase === 'stationed-pickup' && path.length > 0) { if (currentPhase === 'stationed-pickup' && path.length > 0) {
setCurrentPath(path); setCurrentPath(path);
objectRotation = agvDetail.point.action?.pickUpPoint?.rotation setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation)
} else if (currentPhase === 'pickup-drop' && path.length > 0) { } else if (currentPhase === 'pickup-drop' && path.length > 0) {
objectRotation = agvDetail.point.action?.unLoadPoint?.rotation setObjectRotation(agvDetail.point.action?.unLoadPoint?.rotation)
setCurrentPath(path); setCurrentPath(path);
} else if (currentPhase === 'drop-pickup' && path.length > 0) { } else if (currentPhase === 'drop-pickup' && path.length > 0) {
objectRotation = agvDetail.point.action?.pickUpPoint?.rotation setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation)
setCurrentPath(path); setCurrentPath(path);
} }
}, [currentPhase, path]); }, [currentPhase, path, objectRotation]);
useEffect(() => { useEffect(() => {
setProgress(0); setProgress(0);
@@ -64,7 +64,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
coveredDistance = 0; coveredDistance = 0;
setReset(false); setReset(false);
setRestingRotation(true); setRestingRotation(true);
decrementVehicleLoad(agvDetail.modelUuid, 0);
isPausedRef.current = false; isPausedRef.current = false;
pauseTimeRef.current = 0; pauseTimeRef.current = 0;
const object = scene.getObjectByProperty('uuid', agvUuid); const object = scene.getObjectByProperty('uuid', agvUuid);
@@ -125,26 +124,30 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
if (isAligned) { if (isAligned) {
progressRef.current += delta * (speed * agvDetail.speed); progressRef.current += delta * (speed * agvDetail.speed);
coveredDistance = progressRef.current; coveredDistance = progressRef.current;
const t = (coveredDistance - accumulatedDistance) / segmentDistance; const t = (coveredDistance - accumulatedDistance) / segmentDistance;
const position = start.clone().lerp(end, t); const position = start.clone().lerp(end, t);
object.position.copy(position); object.position.copy(position);
} }
} }
if (progressRef.current >= totalDistance) { if (progressRef.current >= totalDistance) {
if (restRotation && objectRotation) { if (restRotation && objectRotation) {
const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(objectRotation.x, objectRotation.y, objectRotation.z)); 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 * 2); object.quaternion.slerp(targetQuaternion, delta * 2);
const angleDiff = object.quaternion.angleTo(targetQuaternion); if (object.quaternion.angleTo(targetQuaternion) < 0.01) {
if (angleDiff < 0.01) { object.quaternion.copy(targetQuaternion);
object.rotation.set(objectRotation.x, objectRotation.y, objectRotation.z); object.rotation.copy(targetEuler);
setRestingRotation(false); setRestingRotation(false);
} }
return; return;
} }
} }
if (progressRef.current >= totalDistance) { if (progressRef.current >= totalDistance) {
setRestingRotation(true); setRestingRotation(true);
progressRef.current = 0; progressRef.current = 0;
@@ -199,7 +202,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
return ( return (
<> <>
{currentPath.length > 0 && ( {currentPath.length > 0 && (
<group visible={false}> <group >
<Line points={currentPath} color="blue" lineWidth={3} /> <Line points={currentPath} color="blue" lineWidth={3} />
{currentPath.map((point, index) => ( {currentPath.map((point, index) => (
<mesh key={index} position={point}> <mesh key={index} position={point}>

View File

@@ -11,7 +11,7 @@ function VehicleInstance({ agvDetail }: { agvDetail: VehicleStatus }) {
const { navMesh } = useNavMesh(); const { navMesh } = useNavMesh();
const vehicleRef: any = useRef(); const vehicleRef: any = useRef();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { vehicles, setVehicleActive, setVehicleState, incrementVehicleLoad, setVehicleLoad, setMaterialType } = useVehicleStore(); const { vehicles, setVehicleActive, setVehicleState, incrementVehicleLoad, setMaterialType, setVehicleLoad } = useVehicleStore();
const [currentPhase, setCurrentPhase] = useState<string>('stationed'); const [currentPhase, setCurrentPhase] = useState<string>('stationed');
const [path, setPath] = useState<[number, number, number][]>([]); const [path, setPath] = useState<[number, number, number][]>([]);
let isIncrememtable = useRef<boolean>(true); let isIncrememtable = useRef<boolean>(true);

View File

@@ -28,15 +28,12 @@ function Vehicles() {
return ( return (
<> <>
<VehicleInstances /> <VehicleInstances />
{isVehicleSelected && selectedEventSphere && !isPlaying &&
{isVehicleSelected && !isPlaying && <VehicleUI />
< VehicleUI />
} }
</> </>
); );
} }
export default Vehicles; export default Vehicles;

View File

@@ -1,6 +1,5 @@
import { create } from "zustand";
import { create } from 'zustand'; import { immer } from "zustand/middleware/immer";
import { immer } from 'zustand/middleware/immer';
interface VehiclesStore { interface VehiclesStore {
vehicles: VehicleStatus[]; vehicles: VehicleStatus[];
@@ -9,7 +8,7 @@ interface VehiclesStore {
removeVehicle: (modelUuid: string) => void; removeVehicle: (modelUuid: string) => void;
updateVehicle: ( updateVehicle: (
modelUuid: string, modelUuid: string,
updates: Partial<Omit<VehicleStatus, 'modelUuid' | 'productId'>> updates: Partial<Omit<VehicleStatus, "modelUuid" | "productId">>
) => void; ) => void;
clearvehicles: () => void; clearvehicles: () => void;
@@ -18,7 +17,10 @@ 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: (modelUuid: string, newState: VehicleStatus['state']) => void; setVehicleState: (
modelUuid: string,
newState: VehicleStatus["state"]
) => void;
setMaterialType: (modelUuid: string, materialType: string | null) => void; setMaterialType: (modelUuid: string, materialType: string | null) => 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;
@@ -35,7 +37,9 @@ export const useVehicleStore = create<VehiclesStore>()(
addVehicle: (productId, event) => { addVehicle: (productId, event) => {
set((state) => { set((state) => {
const exists = state.vehicles.some(v => v.modelUuid === event.modelUuid); const exists = state.vehicles.some(
(v) => v.modelUuid === event.modelUuid
);
if (!exists) { if (!exists) {
state.vehicles.push({ state.vehicles.push({
...event, ...event,
@@ -53,13 +57,15 @@ export const useVehicleStore = create<VehiclesStore>()(
removeVehicle: (modelUuid) => { removeVehicle: (modelUuid) => {
set((state) => { set((state) => {
state.vehicles = state.vehicles.filter(v => v.modelUuid !== modelUuid); state.vehicles = state.vehicles.filter(
(v) => v.modelUuid !== modelUuid
);
}); });
}, },
updateVehicle: (modelUuid, updates) => { updateVehicle: (modelUuid, updates) => {
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) {
Object.assign(vehicle, updates); Object.assign(vehicle, updates);
} }
@@ -74,7 +80,7 @@ export const useVehicleStore = create<VehiclesStore>()(
setVehicleActive: (modelUuid, isActive) => { setVehicleActive: (modelUuid, isActive) => {
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.isActive = isActive; vehicle.isActive = isActive;
} }
@@ -83,7 +89,7 @@ export const useVehicleStore = create<VehiclesStore>()(
updateSteeringAngle: (modelUuid, steeringAngle) => { updateSteeringAngle: (modelUuid, steeringAngle) => {
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.point.action.steeringAngle = steeringAngle; vehicle.point.action.steeringAngle = steeringAngle;
} }
@@ -92,7 +98,7 @@ export const useVehicleStore = create<VehiclesStore>()(
incrementVehicleLoad: (modelUuid, incrementBy) => { incrementVehicleLoad: (modelUuid, incrementBy) => {
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.currentLoad += incrementBy; vehicle.currentLoad += incrementBy;
} }
@@ -101,7 +107,7 @@ export const useVehicleStore = create<VehiclesStore>()(
decrementVehicleLoad: (modelUuid, decrementBy) => { decrementVehicleLoad: (modelUuid, decrementBy) => {
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.currentLoad -= decrementBy; vehicle.currentLoad -= decrementBy;
} }
@@ -110,7 +116,7 @@ export const useVehicleStore = create<VehiclesStore>()(
setVehicleLoad: (modelUuid, load) => { setVehicleLoad: (modelUuid, load) => {
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.currentLoad = load; vehicle.currentLoad = load;
} }
@@ -119,7 +125,7 @@ export const useVehicleStore = create<VehiclesStore>()(
setVehicleState: (modelUuid, newState) => { setVehicleState: (modelUuid, newState) => {
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.state = newState; vehicle.state = newState;
} }
@@ -128,7 +134,7 @@ export const useVehicleStore = create<VehiclesStore>()(
setMaterialType: (modelUuid, materialType) => { setMaterialType: (modelUuid, materialType) => {
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.materialType = materialType; vehicle.materialType = materialType;
} }
@@ -137,7 +143,7 @@ export const useVehicleStore = create<VehiclesStore>()(
incrementActiveTime: (modelUuid, incrementBy) => { incrementActiveTime: (modelUuid, incrementBy) => {
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.activeTime += incrementBy; vehicle.activeTime += incrementBy;
} }
@@ -146,7 +152,7 @@ export const useVehicleStore = create<VehiclesStore>()(
incrementIdleTime: (modelUuid, incrementBy) => { incrementIdleTime: (modelUuid, incrementBy) => {
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.idleTime += incrementBy; vehicle.idleTime += incrementBy;
} }
@@ -154,19 +160,19 @@ export const useVehicleStore = create<VehiclesStore>()(
}, },
getVehicleById: (modelUuid) => { getVehicleById: (modelUuid) => {
return get().vehicles.find(v => v.modelUuid === modelUuid); return get().vehicles.find((v) => v.modelUuid === modelUuid);
}, },
getVehiclesByProduct: (productId) => { getVehiclesByProduct: (productId) => {
return get().vehicles.filter(v => v.productId === productId); return get().vehicles.filter((v) => v.productId === productId);
}, },
getVehiclesByState: (state) => { getVehiclesByState: (state) => {
return get().vehicles.filter(v => v.state === state); return get().vehicles.filter((v) => v.state === state);
}, },
getActiveVehicles: () => { getActiveVehicles: () => {
return get().vehicles.filter(v => v.isActive); return get().vehicles.filter((v) => v.isActive);
} },
})) }))
); );