Merge remote-tracking branch 'origin/main-dev' into feature/agv-edit
This commit is contained in:
@@ -3,12 +3,7 @@ import { useThree, useFrame } from '@react-three/fiber';
|
||||
import * as THREE from 'three';
|
||||
import { MaterialModel } from '../../../materials/instances/material/materialModel';
|
||||
|
||||
type MaterialAnimatorProps = {
|
||||
agvDetail: VehicleStatus;
|
||||
};
|
||||
|
||||
|
||||
const MaterialAnimator = ({ agvDetail }: MaterialAnimatorProps) => {
|
||||
const MaterialAnimator = ({ agvDetail }: { agvDetail: VehicleStatus }) => {
|
||||
const meshRef = useRef<any>(null!);
|
||||
const [hasLoad, setHasLoad] = useState(false);
|
||||
const { scene } = useThree();
|
||||
|
||||
@@ -71,7 +71,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
|
||||
}
|
||||
}, [isReset, isPlaying])
|
||||
|
||||
|
||||
const lastTimeRef = useRef(performance.now());
|
||||
|
||||
useFrame(() => {
|
||||
@@ -283,88 +282,6 @@ function DraggableSphere({
|
||||
);
|
||||
}
|
||||
|
||||
// function DraggableLineSegment({
|
||||
// index,
|
||||
// start,
|
||||
// end,
|
||||
// updatePoints,
|
||||
// isAnyDragging,
|
||||
// setIsAnyDragging,
|
||||
// }: {
|
||||
// index: number;
|
||||
// start: THREE.Vector3;
|
||||
// end: THREE.Vector3;
|
||||
// updatePoints: (i0: number, p0: THREE.Vector3, i1: number, p1: THREE.Vector3) => void;
|
||||
// isAnyDragging: string;
|
||||
// setIsAnyDragging: (val: string) => void;
|
||||
// }) {
|
||||
// const meshRef = useRef<THREE.Mesh>(null);
|
||||
// const { gl, raycaster, controls } = useThree();
|
||||
// const { activeTool } = useActiveTool();
|
||||
// const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
|
||||
// const dragStart = useRef<THREE.Vector3 | null>(null);
|
||||
|
||||
|
||||
// const onPointerDown = () => {
|
||||
// if (activeTool !== 'pen' || isAnyDragging) return; // <-- Skip if dragging sphere
|
||||
// setIsAnyDragging("line");
|
||||
// gl.domElement.style.cursor = 'grabbing';
|
||||
// if (controls) (controls as any).enabled = false;
|
||||
// };
|
||||
|
||||
// const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
|
||||
// if (isAnyDragging !== "line" || activeTool !== 'pen') return;
|
||||
|
||||
// const intersect = new THREE.Vector3();
|
||||
// if (raycaster.ray.intersectPlane(plane, intersect)) {
|
||||
// if (!dragStart.current) dragStart.current = intersect.clone();
|
||||
|
||||
// const offset = new THREE.Vector3().subVectors(intersect, dragStart.current);
|
||||
// const newStart = start.clone().add(offset);
|
||||
// const newEnd = end.clone().add(offset);
|
||||
// updatePoints(index, newStart, index + 1, newEnd);
|
||||
// }
|
||||
// };
|
||||
|
||||
// const onPointerUp = () => {
|
||||
// if (activeTool !== 'pen') return;
|
||||
// setIsAnyDragging("");
|
||||
// dragStart.current = null;
|
||||
// gl.domElement.style.cursor = 'default';
|
||||
// if (controls) (controls as any).enabled = true;
|
||||
// };
|
||||
// const noopRaycast = (raycaster: THREE.Raycaster, intersects: THREE.Intersection[]) => { };
|
||||
|
||||
// return (
|
||||
// <mesh
|
||||
// ref={meshRef}
|
||||
// onPointerDown={onPointerDown}
|
||||
// onPointerMove={onPointerMove}
|
||||
// onPointerUp={onPointerUp}
|
||||
// onPointerMissed={onPointerUp}
|
||||
// raycast={isAnyDragging === "point" ? noopRaycast : undefined} // ✅ Safe
|
||||
// >
|
||||
// <Line points={[start, end]} color="blue" lineWidth={5} />
|
||||
// </mesh>
|
||||
// );
|
||||
|
||||
|
||||
// // return (
|
||||
// // <mesh
|
||||
// // ref={meshRef}
|
||||
// // onPointerDown={onPointerDown}
|
||||
// // onPointerMove={onPointerMove}
|
||||
// // onPointerUp={onPointerUp}
|
||||
// // onPointerMissed={onPointerUp}
|
||||
// // // raycast={isAnyDragging === 'point' ? () => null : undefined}
|
||||
// // raycast={isAnyDragging === "point" ? () => { } : undefined}
|
||||
// // // pointerEvents={isAnyDragging === "point" ? "none" : "auto"} // ✅ the correct way
|
||||
// // >
|
||||
// // <Line points={[start, end]} color="blue" lineWidth={5} />
|
||||
// // </mesh>
|
||||
// // );
|
||||
// }
|
||||
|
||||
function DraggableLineSegment({
|
||||
index,
|
||||
start,
|
||||
@@ -426,207 +343,3 @@ function DraggableLineSegment({
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// These are recently edited files. Do not suggest code that has been deleted.
|
||||
// function DraggableSphere({
|
||||
// index,
|
||||
// position,
|
||||
// onMove,
|
||||
// isAnyDragging,
|
||||
// setIsAnyDragging,
|
||||
// }: {
|
||||
// index: number;
|
||||
// position: THREE.Vector3;
|
||||
// onMove: (index: number, pos: THREE.Vector3) => void;
|
||||
// isAnyDragging: boolean;
|
||||
// setIsAnyDragging: (val: boolean) => void;
|
||||
// }) {
|
||||
// const meshRef = useRef<THREE.Mesh>(null);
|
||||
// const { gl, controls, raycaster } = useThree();
|
||||
// const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); // XZ plane
|
||||
// const isDragging = useRef(false);
|
||||
// const { activeTool } = useActiveTool();
|
||||
|
||||
// const onPointerDown = (e: ThreeEvent<PointerEvent>) => {
|
||||
// if (activeTool !== 'pen') return;
|
||||
|
||||
// isDragging.current = true;
|
||||
// gl.domElement.style.cursor = 'grabbing';
|
||||
|
||||
// if (controls) {
|
||||
// (controls as any).enabled = false;
|
||||
// }
|
||||
// };
|
||||
|
||||
// const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
|
||||
// if (!isDragging.current || activeTool !== 'pen') return;
|
||||
|
||||
// const intersect = new THREE.Vector3();
|
||||
// if (raycaster.ray.intersectPlane(plane, intersect)) {
|
||||
// meshRef.current!.position.copy(intersect);
|
||||
// onMove(index, intersect);
|
||||
// }
|
||||
// };
|
||||
|
||||
// const onPointerUp = () => {
|
||||
// if (activeTool !== 'pen') return;
|
||||
|
||||
// isDragging.current = false;
|
||||
// gl.domElement.style.cursor = 'default';
|
||||
// if (controls) {
|
||||
// (controls as any).enabled = true;
|
||||
// }
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <mesh
|
||||
// ref={meshRef}
|
||||
// position={position}
|
||||
// onPointerDown={onPointerDown}
|
||||
// onPointerMove={onPointerMove}
|
||||
// onPointerUp={onPointerUp}
|
||||
// onPointerMissed={onPointerUp}
|
||||
// >
|
||||
// <sphereGeometry args={[0.2, 16, 16]} />
|
||||
// <meshStandardMaterial color="red" />
|
||||
// </mesh>
|
||||
// );
|
||||
// }
|
||||
|
||||
// function DraggableLineSegment({
|
||||
// index,
|
||||
// start,
|
||||
// end,
|
||||
// updatePoints,
|
||||
// isAnyDragging,
|
||||
// setIsAnyDragging,
|
||||
// }: {
|
||||
// index: number;
|
||||
// start: THREE.Vector3;
|
||||
// end: THREE.Vector3;
|
||||
// updatePoints: (i0: number, p0: THREE.Vector3, i1: number, p1: THREE.Vector3) => void;
|
||||
// isAnyDragging: boolean;
|
||||
// setIsAnyDragging: (val: boolean) => void;
|
||||
// }) {
|
||||
// const meshRef = useRef<THREE.Mesh>(null);
|
||||
// const { gl, camera, controls, raycaster } = useThree();
|
||||
// const { activeTool } = useActiveTool(); // 👈 Get active tool
|
||||
// const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
|
||||
// const isDragging = useRef(false);
|
||||
// const dragStart = useRef<THREE.Vector3 | null>(null);
|
||||
|
||||
// const onPointerDown = () => {
|
||||
// if (activeTool !== 'pen') return; // 👈 Only allow when tool is 'pen'
|
||||
|
||||
// isDragging.current = true;
|
||||
// gl.domElement.style.cursor = 'grabbing';
|
||||
// if (controls) (controls as any).enabled = false;
|
||||
// };
|
||||
|
||||
// const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
|
||||
// if (!isDragging.current || activeTool !== 'pen') return;
|
||||
|
||||
// const intersect = new THREE.Vector3();
|
||||
// if (raycaster.ray.intersectPlane(plane, intersect)) {
|
||||
// if (!dragStart.current) {
|
||||
// dragStart.current = intersect.clone();
|
||||
// }
|
||||
|
||||
// const offset = new THREE.Vector3().subVectors(intersect, dragStart.current);
|
||||
// const newStart = start.clone().add(offset);
|
||||
// const newEnd = end.clone().add(offset);
|
||||
// updatePoints(index, newStart, index + 1, newEnd);
|
||||
// }
|
||||
// };
|
||||
|
||||
// const onPointerUp = () => {
|
||||
// if (activeTool !== 'pen') return;
|
||||
|
||||
// isDragging.current = false;
|
||||
// dragStart.current = null;
|
||||
// gl.domElement.style.cursor = 'default';
|
||||
// if (controls) (controls as any).enabled = true;
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <mesh
|
||||
// ref={meshRef}
|
||||
// onPointerDown={onPointerDown}
|
||||
// onPointerMove={onPointerMove}
|
||||
// onPointerUp={onPointerUp}
|
||||
// onPointerMissed={onPointerUp}
|
||||
// >
|
||||
// <Line points={[start, end]} color="blue" lineWidth={10} />
|
||||
// </mesh>
|
||||
// );
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// return (
|
||||
// <>
|
||||
// {selectedPath === "auto" && <group>
|
||||
// {/* {currentPath.map((pos, i) => {
|
||||
// if (i < currentPath.length - 1) {
|
||||
// return (
|
||||
// <DraggableLineSegment
|
||||
// key={i}
|
||||
// index={i}
|
||||
// start={new THREE.Vector3(...currentPath[i])}
|
||||
// end={new THREE.Vector3(...currentPath[i + 1])}
|
||||
// updatePoints={(i0, p0, i1, p1) => {
|
||||
// const updated = [...currentPath];
|
||||
// updated[i0] = p0.toArray() as [number, number, number];
|
||||
// updated[i1] = p1.toArray() as [number, number, number];
|
||||
// setCurrentPath(updated);
|
||||
// }}
|
||||
// />
|
||||
// );
|
||||
// }
|
||||
// return null;
|
||||
// })} */}
|
||||
// {currentPath.length > 0 && (
|
||||
// <group onPointerMissed={() => { if (controls) (controls as any).enabled = true; }}>
|
||||
// <Line points={currentPath} color="blue" lineWidth={3} />
|
||||
// {currentPath.map((pos, i) => {
|
||||
// if (i < currentPath.length - 1) {
|
||||
// return (
|
||||
// <React.Fragment key={i}>
|
||||
// <DraggableSphere
|
||||
// key={i}
|
||||
// index={i}
|
||||
// position={new THREE.Vector3(...pos)}
|
||||
// onMove={updatePoint}
|
||||
// />
|
||||
// {/* <DraggableLineSegment
|
||||
// key={i}
|
||||
// index={i}
|
||||
// start={new THREE.Vector3(...currentPath[i])}
|
||||
// end={new THREE.Vector3(...currentPath[i + 1])}
|
||||
// updatePoints={(i0, p0, i1, p1) => {
|
||||
// const updated = [...currentPath];
|
||||
// updated[i0] = p0.toArray() as [number, number, number];
|
||||
// updated[i1] = p1.toArray() as [number, number, number];
|
||||
// setCurrentPath(updated);
|
||||
// }}
|
||||
// /> */}
|
||||
// </React.Fragment>
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// )}
|
||||
// </group >
|
||||
// )
|
||||
// }
|
||||
// </group >
|
||||
// }
|
||||
// </>
|
||||
// );
|
||||
@@ -1,21 +1,23 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import VehicleAnimator from '../animator/vehicleAnimator';
|
||||
import * as THREE from 'three';
|
||||
import { NavMeshQuery } from '@recast-navigation/core';
|
||||
import { useNavMesh, useSelectedPath } from '../../../../../store/builder/store';
|
||||
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
|
||||
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
|
||||
import MaterialAnimator from '../animator/materialAnimator';
|
||||
import { useSceneContext } from '../../../../scene/sceneContext';
|
||||
import { useProductContext } from '../../../products/productContext';
|
||||
import InteractivePoints from '../animator/interactivePoint';
|
||||
|
||||
import MaterialAnimator from '../animator/materialAnimator';
|
||||
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();
|
||||
@@ -149,7 +151,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
}
|
||||
}, [vehicles, currentPhase, path, isPlaying, selectedPath]);
|
||||
|
||||
|
||||
function animate(currentTime: number) {
|
||||
if (previousTimeRef.current === null) {
|
||||
previousTimeRef.current = currentTime;
|
||||
@@ -196,7 +197,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
};
|
||||
}, [agvDetail, isPlaying]);
|
||||
|
||||
|
||||
function handleCallBack() {
|
||||
if (currentPhase === 'stationed-pickup') {
|
||||
setCurrentPhase('picking');
|
||||
@@ -246,6 +246,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 +264,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') {
|
||||
@@ -527,10 +605,4 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
);
|
||||
}
|
||||
|
||||
export default VehicleInstance;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export default VehicleInstance;
|
||||
@@ -5,20 +5,20 @@ import { useSceneContext } from "../../../scene/sceneContext";
|
||||
import { useViewSceneStore } from "../../../../store/builder/store";
|
||||
|
||||
function VehicleInstances() {
|
||||
const { vehicleStore } = useSceneContext();
|
||||
const { vehicles } = vehicleStore();
|
||||
const { viewSceneLabels } = useViewSceneStore();
|
||||
const { vehicleStore } = useSceneContext();
|
||||
const { vehicles } = vehicleStore();
|
||||
const { viewSceneLabels } = useViewSceneStore();
|
||||
|
||||
return (
|
||||
<>
|
||||
{vehicles.map((vehicle: VehicleStatus) => (
|
||||
<React.Fragment key={vehicle.modelUuid}>
|
||||
<VehicleInstance agvDetail={vehicle} />
|
||||
{viewSceneLabels && <VehicleContentUi vehicle={vehicle} />}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{vehicles.map((vehicle: VehicleStatus) => (
|
||||
<React.Fragment key={vehicle.modelUuid}>
|
||||
<VehicleInstance agvDetail={vehicle} />
|
||||
{viewSceneLabels && <VehicleContentUi vehicle={vehicle} />}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default VehicleInstances;
|
||||
|
||||
Reference in New Issue
Block a user