feat: Enhance conveyor actions and event handling
- Added detailed logging for default conveyor actions in useConveyorActions. - Integrated play and reset button states into useActionHandler for better control flow. - Updated PointsCreator to conditionally render based on play state and improved event handling. - Modified MaterialAnimator to support pause and resume functionality based on play state. - Enhanced MaterialInstance to trigger actions upon animation completion. - Implemented material clearing logic in Materials component on reset or stop. - Updated Simulator to respect play and reset states during action handling. - Improved trigger handling logic to accommodate new event retrieval methods. - Added utility functions in useProductStore for fetching events by trigger and point UUIDs. - Created a new file for default action handling in conveyor actions.
This commit is contained in:
parent
6b0ee0ae79
commit
c89c4234a4
|
@ -49,7 +49,9 @@ const SimulationPlayer: React.FC = () => {
|
|||
// Button functions
|
||||
const handleReset = () => {
|
||||
setReset(true);
|
||||
setIsPaused(false);
|
||||
setSpeed(1);
|
||||
setPlaySimulation(false); // local state reset
|
||||
};
|
||||
const handlePlayStop = () => {
|
||||
setIsPaused(!isPaused);
|
||||
|
@ -58,6 +60,7 @@ const SimulationPlayer: React.FC = () => {
|
|||
const handleExit = () => {
|
||||
setPlaySimulation(false);
|
||||
setIsPlaying(false);
|
||||
setIsPaused(false);
|
||||
setActiveTool("cursor");
|
||||
};
|
||||
|
||||
|
|
|
@ -4,28 +4,44 @@ import { useFrame } from "@react-three/fiber";
|
|||
import { useMaterialStore } from "../../../../../store/simulation/useMaterialStore";
|
||||
import { useProductStore } from "../../../../../store/simulation/useProductStore";
|
||||
import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
|
||||
import { usePlayButtonStore, useAnimationPlaySpeed, usePauseButtonStore, useResetButtonStore } from "../../../../../store/usePlayButtonStore";
|
||||
|
||||
export function useSpawnHandler() {
|
||||
const { addMaterial } = useMaterialStore();
|
||||
const { getModelUuidByActionUuid, getPointUuidByActionUuid } = useProductStore();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
const lastSpawnTime = useRef<number | null>(null);
|
||||
const startTime = useRef<number | null>(null);
|
||||
const spawnCountRef = useRef<number>(0);
|
||||
const spawnParams = useRef<{
|
||||
interface SpawnInstance {
|
||||
lastSpawnTime: number | null;
|
||||
startTime: number;
|
||||
spawnCount: number;
|
||||
params: {
|
||||
material: string;
|
||||
intervalMs: number;
|
||||
totalCount: number;
|
||||
action: ConveyorAction;
|
||||
} | null>(null);
|
||||
};
|
||||
pauseStartTime: number;
|
||||
remainingTime: number;
|
||||
isPaused: boolean;
|
||||
}
|
||||
|
||||
const clearCurrentSpawn = useCallback(() => {
|
||||
lastSpawnTime.current = null;
|
||||
startTime.current = null;
|
||||
spawnCountRef.current = 0;
|
||||
spawnParams.current = null;
|
||||
export function useSpawnHandler() {
|
||||
const { addMaterial } = useMaterialStore();
|
||||
const { getModelUuidByActionUuid, getPointUuidByActionUuid } = useProductStore();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { isPaused } = usePauseButtonStore();
|
||||
const { speed } = useAnimationPlaySpeed();
|
||||
const { isReset } = useResetButtonStore();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
|
||||
const activeSpawns = useRef<Map<string, SpawnInstance>>(new Map());
|
||||
|
||||
const clearAllSpawns = useCallback(() => {
|
||||
activeSpawns.current.clear();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isReset) {
|
||||
clearAllSpawns();
|
||||
}
|
||||
}, [isReset, clearAllSpawns]);
|
||||
|
||||
const spawnLogStatus = (materialUuid: string, status: string) => {
|
||||
// console.log(`${materialUuid}, ${status}`);
|
||||
}
|
||||
|
@ -64,78 +80,121 @@ export function useSpawnHandler() {
|
|||
|
||||
addMaterial(newMaterial);
|
||||
return newMaterial;
|
||||
}, [addMaterial]);
|
||||
}, [addMaterial, getModelUuidByActionUuid, getPointUuidByActionUuid, selectedProduct.productId]);
|
||||
|
||||
useEffect(() => {
|
||||
const currentTime = performance.now();
|
||||
|
||||
activeSpawns.current.forEach((spawn) => {
|
||||
if (isPaused && !spawn.isPaused) {
|
||||
if (spawn.lastSpawnTime === null) {
|
||||
spawn.remainingTime = Math.max(0, spawn.params.intervalMs - (currentTime - spawn.startTime));
|
||||
} else {
|
||||
spawn.remainingTime = Math.max(0, spawn.params.intervalMs - (currentTime - spawn.lastSpawnTime));
|
||||
}
|
||||
spawn.pauseStartTime = currentTime;
|
||||
spawn.isPaused = true;
|
||||
} else if (!isPaused && spawn.isPaused) {
|
||||
if (spawn.remainingTime > 0) {
|
||||
if (spawn.lastSpawnTime === null) {
|
||||
spawn.startTime = currentTime - (spawn.params.intervalMs - spawn.remainingTime);
|
||||
} else {
|
||||
spawn.lastSpawnTime = currentTime - (spawn.params.intervalMs - spawn.remainingTime);
|
||||
}
|
||||
}
|
||||
spawn.isPaused = false;
|
||||
spawn.pauseStartTime = 0;
|
||||
spawn.remainingTime = 0;
|
||||
}
|
||||
});
|
||||
}, [isPaused]);
|
||||
|
||||
useFrame(() => {
|
||||
if (!spawnParams.current || !startTime.current) return;
|
||||
if (!isPlaying || isPaused || isReset) return;
|
||||
|
||||
const currentTime = performance.now();
|
||||
const { material, intervalMs, totalCount, action } = spawnParams.current;
|
||||
const isFirstSpawn = lastSpawnTime.current === null;
|
||||
const elapsed = currentTime - startTime.current;
|
||||
const completedActions: string[] = [];
|
||||
|
||||
// First spawn
|
||||
if (isFirstSpawn) {
|
||||
if (elapsed >= intervalMs) {
|
||||
const createdMaterial = createNewMaterial(material, action);
|
||||
if (createdMaterial) {
|
||||
spawnLogStatus(createdMaterial.materialId, `[${elapsed.toFixed(2)}ms] Spawned ${material} (1/${totalCount})`);
|
||||
activeSpawns.current.forEach((spawn, actionUuid) => {
|
||||
const { material, intervalMs, totalCount, action } = spawn.params;
|
||||
const isFirstSpawn = spawn.lastSpawnTime === null;
|
||||
|
||||
// First spawn
|
||||
if (isFirstSpawn) {
|
||||
const elapsed = currentTime - spawn.startTime;
|
||||
if (elapsed >= intervalMs) {
|
||||
const createdMaterial = createNewMaterial(material, action);
|
||||
if (createdMaterial) {
|
||||
spawnLogStatus(createdMaterial.materialId, `[${elapsed.toFixed(2)}ms] Spawned ${material} (1/${totalCount})`);
|
||||
}
|
||||
spawn.lastSpawnTime = currentTime;
|
||||
spawn.spawnCount = 1;
|
||||
|
||||
if (totalCount <= 1) {
|
||||
completedActions.push(actionUuid);
|
||||
}
|
||||
}
|
||||
lastSpawnTime.current = currentTime;
|
||||
spawnCountRef.current = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (totalCount <= 1) {
|
||||
clearCurrentSpawn();
|
||||
// Subsequent spawns
|
||||
if (spawn.lastSpawnTime !== null) {
|
||||
const timeSinceLast = currentTime - spawn.lastSpawnTime;
|
||||
if (timeSinceLast >= intervalMs) {
|
||||
const count = spawn.spawnCount + 1;
|
||||
const createdMaterial = createNewMaterial(material, action);
|
||||
if (createdMaterial) {
|
||||
spawnLogStatus(createdMaterial.materialId, `[${timeSinceLast.toFixed(2)}ms] Spawned ${material} (${count}/${totalCount})`);
|
||||
}
|
||||
spawn.lastSpawnTime = currentTime;
|
||||
spawn.spawnCount = count;
|
||||
|
||||
if (count >= totalCount) {
|
||||
completedActions.push(actionUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Subsequent spawns
|
||||
if (lastSpawnTime.current !== null) {
|
||||
const timeSinceLast = currentTime - lastSpawnTime.current;
|
||||
if (timeSinceLast >= intervalMs) {
|
||||
const count = spawnCountRef.current + 1;
|
||||
const createdMaterial = createNewMaterial(material, action);
|
||||
if (createdMaterial) {
|
||||
spawnLogStatus(createdMaterial.materialId, `[${elapsed.toFixed(2)}ms] Spawned ${material} (${count}/${totalCount})`);
|
||||
}
|
||||
lastSpawnTime.current = currentTime;
|
||||
spawnCountRef.current = count;
|
||||
|
||||
if (count >= totalCount) {
|
||||
clearCurrentSpawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
completedActions.forEach(actionUuid => {
|
||||
activeSpawns.current.delete(actionUuid);
|
||||
});
|
||||
});
|
||||
|
||||
const handleSpawn = useCallback((action: ConveyorAction) => {
|
||||
if (!action || action.actionType !== 'spawn') return;
|
||||
|
||||
const { material, spawnInterval = 0, spawnCount = 1 } = action;
|
||||
const { material, spawnInterval = 0, spawnCount = 1, actionUuid } = action;
|
||||
const intervalMs = spawnInterval * 1000;
|
||||
|
||||
clearCurrentSpawn();
|
||||
if (activeSpawns.current.has(actionUuid)) {
|
||||
activeSpawns.current.delete(actionUuid);
|
||||
}
|
||||
|
||||
spawnParams.current = {
|
||||
material,
|
||||
intervalMs,
|
||||
totalCount: spawnCount,
|
||||
action: action
|
||||
};
|
||||
|
||||
startTime.current = performance.now();
|
||||
}, [clearCurrentSpawn]);
|
||||
activeSpawns.current.set(actionUuid, {
|
||||
lastSpawnTime: null,
|
||||
startTime: performance.now(),
|
||||
spawnCount: 0,
|
||||
params: {
|
||||
material,
|
||||
intervalMs,
|
||||
totalCount: spawnCount,
|
||||
action: action
|
||||
},
|
||||
pauseStartTime: 0,
|
||||
remainingTime: 0,
|
||||
isPaused: false
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearCurrentSpawn();
|
||||
clearAllSpawns();
|
||||
};
|
||||
}, [clearCurrentSpawn]);
|
||||
}, [clearAllSpawns]);
|
||||
|
||||
return {
|
||||
handleSpawn,
|
||||
clearCurrentSpawn
|
||||
clearCurrentSpawn: clearAllSpawns
|
||||
};
|
||||
}
|
|
@ -5,7 +5,8 @@ export function useConveyorActions() {
|
|||
const { handleSpawn, clearCurrentSpawn } = useSpawnHandler();
|
||||
|
||||
const handleDefaultAction = useCallback((action: ConveyorAction) => {
|
||||
// console.log(`Default conveyor action ${action.actionUuid}`);
|
||||
console.log('action: ', action);
|
||||
console.log(`Default conveyor action ${action.actionUuid}`);
|
||||
}, []);
|
||||
|
||||
const handleSpawnAction = useCallback((action: ConveyorAction) => {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { usePlayButtonStore, useResetButtonStore } from "../../../store/usePlayButtonStore";
|
||||
import { useConveyorActions } from "./conveyor/useConveyorActions";
|
||||
import { useMachineActions } from "./machine/useMachineActions";
|
||||
import { useRoboticArmActions } from "./roboticArm/useRoboticArmActions";
|
||||
|
@ -6,6 +7,8 @@ import { useVehicleActions } from "./vehicle/useVehicleActions";
|
|||
import { useCallback, useEffect } from "react";
|
||||
|
||||
export function useActionHandler() {
|
||||
const { isReset } = useResetButtonStore();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { handleConveyorAction, cleanup: cleanupConveyor } = useConveyorActions();
|
||||
const { handleVehicleAction, cleanup: cleanupVehicle } = useVehicleActions();
|
||||
const { handleRoboticArmAction, cleanup: cleanupRoboticArm } = useRoboticArmActions();
|
||||
|
@ -52,7 +55,7 @@ export function useActionHandler() {
|
|||
return () => {
|
||||
cleanup();
|
||||
};
|
||||
}, [cleanup]);
|
||||
}, [cleanup, isReset, isPlaying]);
|
||||
|
||||
return {
|
||||
handleAction,
|
||||
|
|
|
@ -1,276 +1,265 @@
|
|||
import React, { useEffect, useRef, useState } from "react";
|
||||
import * as THREE from "three";
|
||||
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
|
||||
import useModuleStore, {
|
||||
useSubModuleStore,
|
||||
} from "../../../../../store/useModuleStore";
|
||||
import useModuleStore, { useSubModuleStore } from "../../../../../store/useModuleStore";
|
||||
import { TransformControls } from "@react-three/drei";
|
||||
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
|
||||
import {
|
||||
useSelectedEventSphere,
|
||||
useSelectedEventData,
|
||||
} from "../../../../../store/simulation/useSimulationStore";
|
||||
import { useSelectedEventSphere, useSelectedEventData, } from "../../../../../store/simulation/useSimulationStore";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import { usePlayButtonStore } from "../../../../../store/usePlayButtonStore";
|
||||
|
||||
function PointsCreator() {
|
||||
const { gl, raycaster, scene, pointer, camera } = useThree();
|
||||
const { subModule } = useSubModuleStore();
|
||||
const { events, updatePoint, getPointByUuid, getEventByModelUuid } =
|
||||
useEventsStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
const transformRef = useRef<any>(null);
|
||||
const [transformMode, setTransformMode] = useState<
|
||||
"translate" | "rotate" | null
|
||||
>(null);
|
||||
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
||||
const {
|
||||
selectedEventSphere,
|
||||
setSelectedEventSphere,
|
||||
clearSelectedEventSphere,
|
||||
} = useSelectedEventSphere();
|
||||
const { setSelectedEventData, clearSelectedEventData } =
|
||||
useSelectedEventData();
|
||||
const { gl, raycaster, scene, pointer, camera } = useThree();
|
||||
const { subModule } = useSubModuleStore();
|
||||
const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
const transformRef = useRef<any>(null);
|
||||
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
||||
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
||||
const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere, } = useSelectedEventSphere();
|
||||
const { setSelectedEventData, clearSelectedEventData } = useSelectedEventData();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedEventSphere) {
|
||||
const eventData = getEventByModelUuid(
|
||||
selectedEventSphere.userData.modelUuid
|
||||
);
|
||||
useEffect(() => {
|
||||
if (selectedEventSphere) {
|
||||
const eventData = getEventByModelUuid(
|
||||
selectedEventSphere.userData.modelUuid
|
||||
);
|
||||
|
||||
if (eventData) {
|
||||
setSelectedEventData(eventData, selectedEventSphere.userData.pointUuid);
|
||||
} else {
|
||||
clearSelectedEventData();
|
||||
}
|
||||
} else {
|
||||
clearSelectedEventData();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedEventSphere]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
const keyCombination = detectModifierKeys(e);
|
||||
if (!selectedEventSphere) return;
|
||||
if (keyCombination === "G") {
|
||||
setTransformMode((prev) => (prev === "translate" ? null : "translate"));
|
||||
}
|
||||
if (keyCombination === "R") {
|
||||
setTransformMode((prev) => (prev === "rotate" ? null : "rotate"));
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, [selectedEventSphere]);
|
||||
|
||||
const updatePointToState = (selectedEventSphere: THREE.Mesh) => {
|
||||
let point = JSON.parse(
|
||||
JSON.stringify(
|
||||
getPointByUuid(
|
||||
selectedEventSphere.userData.modelUuid,
|
||||
selectedEventSphere.userData.pointUuid
|
||||
)
|
||||
)
|
||||
);
|
||||
if (point) {
|
||||
point.position = [
|
||||
selectedEventSphere.position.x,
|
||||
selectedEventSphere.position.y,
|
||||
selectedEventSphere.position.z,
|
||||
];
|
||||
updatePoint(
|
||||
selectedEventSphere.userData.modelUuid,
|
||||
selectedEventSphere.userData.pointUuid,
|
||||
point
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const canvasElement = gl.domElement;
|
||||
|
||||
let drag = false;
|
||||
let isMouseDown = false;
|
||||
|
||||
const onMouseDown = () => {
|
||||
isMouseDown = true;
|
||||
drag = false;
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
if (selectedEventSphere && !drag) {
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
const intersects = raycaster
|
||||
.intersectObjects(scene.children, true)
|
||||
.filter((intersect) => intersect.object.name === "Event-Sphere");
|
||||
if (intersects.length === 0) {
|
||||
clearSelectedEventSphere();
|
||||
setTransformMode(null);
|
||||
if (eventData) {
|
||||
setSelectedEventData(eventData, selectedEventSphere.userData.pointUuid);
|
||||
} else {
|
||||
clearSelectedEventData();
|
||||
}
|
||||
} else {
|
||||
clearSelectedEventData();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedEventSphere]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
const keyCombination = detectModifierKeys(e);
|
||||
if (!selectedEventSphere) return;
|
||||
if (keyCombination === "G") {
|
||||
setTransformMode((prev) => (prev === "translate" ? null : "translate"));
|
||||
}
|
||||
if (keyCombination === "R") {
|
||||
setTransformMode((prev) => (prev === "rotate" ? null : "rotate"));
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, [selectedEventSphere]);
|
||||
|
||||
const updatePointToState = (selectedEventSphere: THREE.Mesh) => {
|
||||
let point = JSON.parse(
|
||||
JSON.stringify(
|
||||
getPointByUuid(
|
||||
selectedEventSphere.userData.modelUuid,
|
||||
selectedEventSphere.userData.pointUuid
|
||||
)
|
||||
)
|
||||
);
|
||||
if (point) {
|
||||
point.position = [
|
||||
selectedEventSphere.position.x,
|
||||
selectedEventSphere.position.y,
|
||||
selectedEventSphere.position.z,
|
||||
];
|
||||
updatePoint(
|
||||
selectedEventSphere.userData.modelUuid,
|
||||
selectedEventSphere.userData.pointUuid,
|
||||
point
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseMove = () => {
|
||||
if (isMouseDown) {
|
||||
drag = true;
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
const canvasElement = gl.domElement;
|
||||
|
||||
if (subModule === "mechanics") {
|
||||
canvasElement.addEventListener("mousedown", onMouseDown);
|
||||
canvasElement.addEventListener("mouseup", onMouseUp);
|
||||
canvasElement.addEventListener("mousemove", onMouseMove);
|
||||
}
|
||||
let drag = false;
|
||||
let isMouseDown = false;
|
||||
|
||||
return () => {
|
||||
canvasElement.removeEventListener("mousedown", onMouseDown);
|
||||
canvasElement.removeEventListener("mouseup", onMouseUp);
|
||||
canvasElement.removeEventListener("mousemove", onMouseMove);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [gl, subModule, selectedEventSphere]);
|
||||
const onMouseDown = () => {
|
||||
isMouseDown = true;
|
||||
drag = false;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeModule === "simulation" && (
|
||||
const onMouseUp = () => {
|
||||
if (selectedEventSphere && !drag) {
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
const intersects = raycaster
|
||||
.intersectObjects(scene.children, true)
|
||||
.filter((intersect) => intersect.object.name === "Event-Sphere");
|
||||
if (intersects.length === 0) {
|
||||
clearSelectedEventSphere();
|
||||
setTransformMode(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseMove = () => {
|
||||
if (isMouseDown) {
|
||||
drag = true;
|
||||
}
|
||||
};
|
||||
|
||||
if (subModule === "mechanics") {
|
||||
canvasElement.addEventListener("mousedown", onMouseDown);
|
||||
canvasElement.addEventListener("mouseup", onMouseUp);
|
||||
canvasElement.addEventListener("mousemove", onMouseMove);
|
||||
}
|
||||
|
||||
return () => {
|
||||
canvasElement.removeEventListener("mousedown", onMouseDown);
|
||||
canvasElement.removeEventListener("mouseup", onMouseUp);
|
||||
canvasElement.removeEventListener("mousemove", onMouseMove);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [gl, subModule, selectedEventSphere]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<group name="EventPointsGroup">
|
||||
{events.map((event, index) => {
|
||||
if (event.type === "transfer") {
|
||||
return (
|
||||
<group
|
||||
key={`${index}-${event.modelUuid}`}
|
||||
position={event.position}
|
||||
rotation={event.rotation}
|
||||
>
|
||||
{event.points.map((point, j) => (
|
||||
<mesh
|
||||
name="Event-Sphere"
|
||||
uuid={point.uuid}
|
||||
ref={(el) => (sphereRefs.current[point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[point.uuid]
|
||||
);
|
||||
}}
|
||||
key={`${index}-${point.uuid}`}
|
||||
position={new THREE.Vector3(...point.position)}
|
||||
userData={{
|
||||
modelUuid: event.modelUuid,
|
||||
pointUuid: point.uuid,
|
||||
}}
|
||||
>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial color="orange" />
|
||||
</mesh>
|
||||
))}
|
||||
</group>
|
||||
);
|
||||
} else if (event.type === "vehicle") {
|
||||
return (
|
||||
<group
|
||||
key={`${index}-${event.modelUuid}`}
|
||||
position={event.position}
|
||||
rotation={event.rotation}
|
||||
>
|
||||
<mesh
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
position={new THREE.Vector3(...event.point.position)}
|
||||
userData={{
|
||||
modelUuid: event.modelUuid,
|
||||
pointUuid: event.point.uuid,
|
||||
}}
|
||||
>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial color="blue" />
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
} else if (event.type === "roboticArm") {
|
||||
return (
|
||||
<group
|
||||
key={`${index}-${event.modelUuid}`}
|
||||
position={event.position}
|
||||
rotation={event.rotation}
|
||||
>
|
||||
<mesh
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
position={new THREE.Vector3(...event.point.position)}
|
||||
userData={{
|
||||
modelUuid: event.modelUuid,
|
||||
pointUuid: event.point.uuid,
|
||||
}}
|
||||
>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial color="green" />
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
} else if (event.type === "machine") {
|
||||
return (
|
||||
<group
|
||||
key={`${index}-${event.modelUuid}`}
|
||||
position={event.position}
|
||||
rotation={event.rotation}
|
||||
>
|
||||
<mesh
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
position={new THREE.Vector3(...event.point.position)}
|
||||
userData={{
|
||||
modelUuid: event.modelUuid,
|
||||
pointUuid: event.point.uuid,
|
||||
}}
|
||||
>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial color="purple" />
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</group>
|
||||
{selectedEventSphere && transformMode && (
|
||||
<TransformControls
|
||||
ref={transformRef}
|
||||
object={selectedEventSphere}
|
||||
mode={transformMode}
|
||||
onMouseUp={(e) => {
|
||||
updatePointToState(selectedEventSphere);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{activeModule === "simulation" && (
|
||||
<>
|
||||
<group name="EventPointsGroup" visible={!isPlaying}>
|
||||
{events.map((event, index) => {
|
||||
if (event.type === "transfer") {
|
||||
return (
|
||||
<group
|
||||
key={`${index}-${event.modelUuid}`}
|
||||
position={event.position}
|
||||
rotation={event.rotation}
|
||||
>
|
||||
{event.points.map((point, j) => (
|
||||
<mesh
|
||||
name="Event-Sphere"
|
||||
uuid={point.uuid}
|
||||
ref={(el) => (sphereRefs.current[point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[point.uuid]
|
||||
);
|
||||
}}
|
||||
key={`${index}-${point.uuid}`}
|
||||
position={new THREE.Vector3(...point.position)}
|
||||
userData={{
|
||||
modelUuid: event.modelUuid,
|
||||
pointUuid: point.uuid,
|
||||
}}
|
||||
>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial color="orange" />
|
||||
</mesh>
|
||||
))}
|
||||
</group>
|
||||
);
|
||||
} else if (event.type === "vehicle") {
|
||||
return (
|
||||
<group
|
||||
key={`${index}-${event.modelUuid}`}
|
||||
position={event.position}
|
||||
rotation={event.rotation}
|
||||
>
|
||||
<mesh
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
position={new THREE.Vector3(...event.point.position)}
|
||||
userData={{
|
||||
modelUuid: event.modelUuid,
|
||||
pointUuid: event.point.uuid,
|
||||
}}
|
||||
>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial color="blue" />
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
} else if (event.type === "roboticArm") {
|
||||
return (
|
||||
<group
|
||||
key={`${index}-${event.modelUuid}`}
|
||||
position={event.position}
|
||||
rotation={event.rotation}
|
||||
>
|
||||
<mesh
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
position={new THREE.Vector3(...event.point.position)}
|
||||
userData={{
|
||||
modelUuid: event.modelUuid,
|
||||
pointUuid: event.point.uuid,
|
||||
}}
|
||||
>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial color="green" />
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
} else if (event.type === "machine") {
|
||||
return (
|
||||
<group
|
||||
key={`${index}-${event.modelUuid}`}
|
||||
position={event.position}
|
||||
rotation={event.rotation}
|
||||
>
|
||||
<mesh
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
position={new THREE.Vector3(...event.point.position)}
|
||||
userData={{
|
||||
modelUuid: event.modelUuid,
|
||||
pointUuid: event.point.uuid,
|
||||
}}
|
||||
>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial color="purple" />
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</group>
|
||||
{selectedEventSphere && transformMode && (
|
||||
<TransformControls
|
||||
ref={transformRef}
|
||||
object={selectedEventSphere}
|
||||
mode={transformMode}
|
||||
onMouseUp={(e) => {
|
||||
updatePointToState(selectedEventSphere);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
export default PointsCreator;
|
||||
|
|
|
@ -1,26 +1,35 @@
|
|||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import * as THREE from 'three';
|
||||
import { useFrame, useThree } from '@react-three/fiber';
|
||||
import { usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
|
||||
|
||||
interface MaterialAnimatorProps {
|
||||
matRef: React.RefObject<THREE.Mesh>;
|
||||
material: MaterialSchema;
|
||||
speed: number; // units per second
|
||||
currentSpeed: number;
|
||||
onAnimationComplete?: () => void;
|
||||
}
|
||||
|
||||
function MaterialAnimator({
|
||||
matRef,
|
||||
material,
|
||||
speed,
|
||||
currentSpeed,
|
||||
onAnimationComplete
|
||||
}: MaterialAnimatorProps) {
|
||||
const { scene } = useThree();
|
||||
const [targetPosition, setTargetPosition] = useState<THREE.Vector3 | null>(null);
|
||||
const [isAnimating, setIsAnimating] = useState(false);
|
||||
const animationStartTime = useRef<number>(0);
|
||||
const startPosition = useRef<THREE.Vector3>(new THREE.Vector3());
|
||||
const totalDistance = useRef<number>(0);
|
||||
const animationState = useRef({
|
||||
startTime: 0,
|
||||
startPosition: new THREE.Vector3(),
|
||||
totalDistance: 0,
|
||||
pausedTime: 0,
|
||||
isPaused: false,
|
||||
lastFrameTime: 0
|
||||
});
|
||||
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { isPaused } = usePauseButtonStore();
|
||||
|
||||
const getWorldPosition = (uuid: string): THREE.Vector3 | null => {
|
||||
const obj = scene.getObjectByProperty('uuid', uuid);
|
||||
|
@ -30,37 +39,58 @@ function MaterialAnimator({
|
|||
return position;
|
||||
};
|
||||
|
||||
// Handle target position changes and play state
|
||||
useEffect(() => {
|
||||
if (!material.next?.pointUuid) {
|
||||
setTargetPosition(null);
|
||||
if (!isPlaying || !material.next?.pointUuid) {
|
||||
setIsAnimating(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const newTarget = getWorldPosition(material.next.pointUuid);
|
||||
if (newTarget && matRef.current) {
|
||||
startPosition.current.copy(matRef.current.position);
|
||||
totalDistance.current = startPosition.current.distanceTo(newTarget);
|
||||
animationStartTime.current = performance.now();
|
||||
animationState.current.startPosition.copy(matRef.current.position);
|
||||
animationState.current.totalDistance = animationState.current.startPosition.distanceTo(newTarget);
|
||||
animationState.current.startTime = performance.now() - animationState.current.pausedTime;
|
||||
animationState.current.pausedTime = 0;
|
||||
animationState.current.isPaused = false;
|
||||
setTargetPosition(newTarget);
|
||||
setIsAnimating(true);
|
||||
}
|
||||
}, [material.next?.pointUuid]);
|
||||
}, [material.next?.pointUuid, isPlaying]);
|
||||
|
||||
// Handle pause/unpause
|
||||
useEffect(() => {
|
||||
if (isPaused) {
|
||||
animationState.current.isPaused = true;
|
||||
setIsAnimating(false);
|
||||
// Record the time when paused
|
||||
animationState.current.pausedTime = performance.now() - animationState.current.startTime;
|
||||
} else {
|
||||
animationState.current.isPaused = false;
|
||||
if (isPlaying && targetPosition && !isAnimating) {
|
||||
// Resume from where we left off
|
||||
animationState.current.startTime = performance.now() - animationState.current.pausedTime;
|
||||
setIsAnimating(true);
|
||||
}
|
||||
}
|
||||
}, [isPaused]);
|
||||
|
||||
useFrame(() => {
|
||||
if (!matRef.current || !targetPosition || !isAnimating) return;
|
||||
if (!matRef.current || !targetPosition || !isAnimating || animationState.current.isPaused || !isPlaying) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentTime = performance.now();
|
||||
// Calculate elapsed time since animation start, minus any paused time
|
||||
const elapsed = (currentTime - animationState.current.startTime) / 1000;
|
||||
const progress = Math.min(1, (currentSpeed * elapsed) / animationState.current.totalDistance);
|
||||
|
||||
// Calculate exact position based on constant speed
|
||||
const elapsed = (performance.now() - animationStartTime.current) / 1000;
|
||||
const progress = Math.min(1, (speed * elapsed) / totalDistance.current);
|
||||
|
||||
matRef.current.position.lerpVectors(
|
||||
startPosition.current,
|
||||
animationState.current.startPosition,
|
||||
targetPosition,
|
||||
progress
|
||||
);
|
||||
|
||||
// Check if animation is complete
|
||||
if (progress >= 1) {
|
||||
matRef.current.position.copy(targetPosition);
|
||||
setIsAnimating(false);
|
||||
|
|
|
@ -5,12 +5,16 @@ import { useProductStore } from '../../../../../store/simulation/useProductStore
|
|||
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
|
||||
import { MaterialModel } from '../material/materialModel';
|
||||
import { useThree } from '@react-three/fiber';
|
||||
import { useAnimationPlaySpeed } from '../../../../../store/usePlayButtonStore';
|
||||
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
|
||||
|
||||
function MaterialInstance({ material }: { material: MaterialSchema }) {
|
||||
const matRef: any = useRef();
|
||||
const { scene } = useThree();
|
||||
const { getModelUuidByPointUuid, getPointByUuid, getEventByModelUuid } = useProductStore();
|
||||
const { getModelUuidByPointUuid, getPointByUuid, getEventByModelUuid, getActionByUuid } = useProductStore();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
const { speed } = useAnimationPlaySpeed();
|
||||
const { triggerPointActions } = useTriggerHandler();
|
||||
|
||||
const getWorldPositionFromScene = (pointUuid: string): THREE.Vector3 | null => {
|
||||
const pointObj = scene.getObjectByProperty("uuid", pointUuid);
|
||||
|
@ -21,32 +25,32 @@ function MaterialInstance({ material }: { material: MaterialSchema }) {
|
|||
return worldPosition;
|
||||
};
|
||||
|
||||
const { position, rotation, speed } = useMemo(() => {
|
||||
const { position, rotation, currentSpeed } = useMemo(() => {
|
||||
if (!material.current?.pointUuid) {
|
||||
return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), speed: 1 };
|
||||
return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), currentSpeed: 1 };
|
||||
}
|
||||
|
||||
const modelUuid = getModelUuidByPointUuid(selectedProduct.productId, material.current.pointUuid);
|
||||
if (!modelUuid) {
|
||||
return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), speed: 1 };
|
||||
return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), currentSpeed: 1 };
|
||||
}
|
||||
|
||||
const speed = getCurrentSpeed(selectedProduct.productId, modelUuid);
|
||||
const currentSpeed = getCurrentSpeed(selectedProduct.productId, modelUuid);
|
||||
|
||||
const point = getPointByUuid(selectedProduct.productId, modelUuid, material.current.pointUuid);
|
||||
if (!point) {
|
||||
return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), speed: 1 };
|
||||
return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), currentSpeed: 1 };
|
||||
}
|
||||
|
||||
const position = getWorldPositionFromScene(point.uuid);
|
||||
if (position) {
|
||||
return { position: position, rotation: new THREE.Vector3(0, 0, 0), speed: 1 };
|
||||
return { position: position, rotation: new THREE.Vector3(0, 0, 0), currentSpeed: 1 };
|
||||
}
|
||||
|
||||
return {
|
||||
position: new THREE.Vector3(...point.position),
|
||||
rotation: new THREE.Vector3(...point.rotation),
|
||||
speed: speed || 1
|
||||
currentSpeed: currentSpeed || 1
|
||||
};
|
||||
}, [material, getPointByUuid]);
|
||||
|
||||
|
@ -82,16 +86,25 @@ function MaterialInstance({ material }: { material: MaterialSchema }) {
|
|||
// console.log('material: ', material);
|
||||
}, [material])
|
||||
|
||||
const callTrigger = () => {
|
||||
const action = getActionByUuid(selectedProduct.productId, material.current.actionUuid)
|
||||
if (action) {
|
||||
triggerPointActions(action);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<MaterialModel matRef={matRef} materialType={material.materialType} position={position} />
|
||||
{material.isRendered &&
|
||||
<MaterialModel matRef={matRef} materialType={material.materialType} visible={material.isVisible} position={position} />
|
||||
}
|
||||
|
||||
<MaterialAnimator
|
||||
matRef={matRef}
|
||||
material={material}
|
||||
speed={speed}
|
||||
onAnimationComplete={() => { console.log('123');}}
|
||||
currentSpeed={currentSpeed * speed}
|
||||
onAnimationComplete={() => { callTrigger() }}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ function MaterialInstances() {
|
|||
const { materials } = useMaterialStore();
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('materials: ', materials);
|
||||
console.log('materials: ', materials);
|
||||
}, [materials])
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,11 +1,27 @@
|
|||
import React from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
import MaterialInstances from './instances/materialInstances'
|
||||
import { usePlayButtonStore, useResetButtonStore } from '../../../store/usePlayButtonStore';
|
||||
import { useMaterialStore } from '../../../store/simulation/useMaterialStore';
|
||||
|
||||
function Materials() {
|
||||
const { clearMaterials } = useMaterialStore();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { isReset } = useResetButtonStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (isReset || !isPlaying) {
|
||||
clearMaterials();
|
||||
}
|
||||
}, [isReset, isPlaying]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<MaterialInstances />
|
||||
{isPlaying &&
|
||||
|
||||
<MaterialInstances />
|
||||
|
||||
}
|
||||
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
import { useEffect } from 'react';
|
||||
import { useProductStore } from '../../../store/simulation/useProductStore';
|
||||
import { useActionHandler } from '../actions/useActionHandler';
|
||||
import { usePlayButtonStore, useResetButtonStore } from '../../../store/usePlayButtonStore';
|
||||
|
||||
function Simulator() {
|
||||
const { products } = useProductStore();
|
||||
const { handleAction } = useActionHandler();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { isReset } = useResetButtonStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isPlaying || isReset) return;
|
||||
|
||||
const executionOrder = determineExecutionOrder(products);
|
||||
executionOrder.forEach(point => {
|
||||
if ('actions' in point) {
|
||||
handleAction(point.actions[0]);
|
||||
} else {
|
||||
handleAction(point.action);
|
||||
}
|
||||
executionOrder.map(point => {
|
||||
const action = 'actions' in point ? point.actions[0] : point.action;
|
||||
handleAction(action);
|
||||
});
|
||||
}, [products, handleAction]);
|
||||
}, [products, handleAction, isPlaying, isReset]);
|
||||
|
||||
function determineExecutionOrder(products: productsSchema): PointsScheme[] {
|
||||
// Create maps for all events and points
|
||||
|
|
|
@ -10,6 +10,7 @@ import { handleAddEventToProduct } from "../../events/points/functions/handleAdd
|
|||
import { QuadraticBezierLine } from "@react-three/drei";
|
||||
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
|
||||
import { useDeleteTool } from "../../../../store/store";
|
||||
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
|
||||
|
||||
interface ConnectionLine {
|
||||
id: string;
|
||||
|
@ -29,6 +30,7 @@ function TriggerConnector() {
|
|||
const [helperlineColor, setHelperLineColor] = useState<string>("red");
|
||||
const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3; end: THREE.Vector3; mid: THREE.Vector3; } | null>(null);
|
||||
const { deleteTool } = useDeleteTool();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
|
||||
const [firstSelectedPoint, setFirstSelectedPoint] = useState<{
|
||||
productId: string;
|
||||
|
@ -424,7 +426,7 @@ function TriggerConnector() {
|
|||
};
|
||||
|
||||
return (
|
||||
<group name="simulationConnectionGroup" >
|
||||
<group name="simulationConnectionGroup" visible={!isPlaying}>
|
||||
{connections.map((connection) => {
|
||||
const startPoint = getWorldPositionFromScene(connection.startPointUuid);
|
||||
const endPoint = getWorldPositionFromScene(connection.endPointUuid);
|
||||
|
|
|
@ -1,13 +1,128 @@
|
|||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { useActionHandler } from '../../actions/useActionHandler';
|
||||
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||
import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
|
||||
import { useMaterialStore } from '../../../../store/simulation/useMaterialStore';
|
||||
|
||||
export function useTriggerHandler() {
|
||||
const { getActionByUuid } = useProductStore();
|
||||
const { getActionByUuid, getEventByTriggerUuid, getEventByModelUuid } = useProductStore();
|
||||
const { handleAction } = useActionHandler();
|
||||
const { getMaterialByCurrentModelUuid, setCurrentLocation, setNextLocation } = useMaterialStore();
|
||||
const { selectedProduct } = useSelectedProduct();
|
||||
|
||||
const handleTrigger = (trigger: TriggerSchema) => {
|
||||
const handleTrigger = (trigger: TriggerSchema, actionUuid: string) => {
|
||||
|
||||
// const fromEvent = getEventByTriggerUuid(selectedProduct.productId, trigger.triggerUuid);
|
||||
// console.log('fromEvent: ', fromEvent);
|
||||
|
||||
// const toEvent = getEventByModelUuid(selectedProduct.productId, trigger.triggeredAsset?.triggeredModel.modelUuid || '');
|
||||
// console.log('toEvent: ', toEvent);
|
||||
|
||||
// if (fromEvent?.type === 'transfer') {
|
||||
// if (toEvent?.type === 'transfer') {
|
||||
// // console.log('toEvent: ', toEvent.type);
|
||||
// // Transfer to Transfer
|
||||
// const action = getActionByUuid(selectedProduct.productId, trigger.triggeredAsset?.triggeredAction?.actionUuid || '');
|
||||
// if (action && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
|
||||
// const material = getMaterialByCurrentModelUuid(fromEvent.modelUuid);
|
||||
// if (material) {
|
||||
// if (material.next &&
|
||||
// action.triggers[0].triggeredAsset?.triggeredAction?.actionUuid &&
|
||||
// action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid) {
|
||||
|
||||
// setCurrentLocation(material.materialId, material.next);
|
||||
|
||||
// setNextLocation(material.materialId, {
|
||||
// modelUuid: toEvent.modelUuid,
|
||||
// pointUuid: action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid,
|
||||
// actionUuid: action.triggers[0].triggeredAsset?.triggeredAction?.actionUuid
|
||||
// });
|
||||
// }
|
||||
// handleAction(action);
|
||||
// }
|
||||
// }
|
||||
// } else if (toEvent?.type === 'vehicle') {
|
||||
// // Transfer to Vehicle
|
||||
|
||||
// } else if (toEvent?.type === 'machine') {
|
||||
// // Transfer to Machine
|
||||
|
||||
// } else if (toEvent?.type === 'roboticArm') {
|
||||
// // Transfer to Robotic Arm
|
||||
|
||||
// } else if (toEvent?.type === 'storageUnit') {
|
||||
// // Transfer to Storage Unit
|
||||
|
||||
// }
|
||||
// } else if (fromEvent?.type === 'vehicle') {
|
||||
// if (toEvent?.type === 'transfer') {
|
||||
// // Vehicle to Transfer
|
||||
|
||||
// } else if (toEvent?.type === 'vehicle') {
|
||||
// // Vehicle to Vehicle
|
||||
|
||||
// } else if (toEvent?.type === 'machine') {
|
||||
// // Vehicle to Machine
|
||||
|
||||
// } else if (toEvent?.type === 'roboticArm') {
|
||||
// // Vehicle to Robotic Arm
|
||||
|
||||
// } else if (toEvent?.type === 'storageUnit') {
|
||||
// // Vehicle to Storage Unit
|
||||
|
||||
// }
|
||||
// } else if (fromEvent?.type === 'machine') {
|
||||
// if (toEvent?.type === 'transfer') {
|
||||
// // Machine to Transfer
|
||||
|
||||
// } else if (toEvent?.type === 'vehicle') {
|
||||
// // Machine to Vehicle
|
||||
|
||||
// } else if (toEvent?.type === 'machine') {
|
||||
// // Machine to Machine
|
||||
|
||||
// } else if (toEvent?.type === 'roboticArm') {
|
||||
// // Machine to Robotic Arm
|
||||
|
||||
// } else if (toEvent?.type === 'storageUnit') {
|
||||
// // Machine to Storage Unit
|
||||
|
||||
// }
|
||||
// } else if (fromEvent?.type === 'roboticArm') {
|
||||
// if (toEvent?.type === 'transfer') {
|
||||
// // Robotic Arm to Transfer
|
||||
|
||||
// } else if (toEvent?.type === 'vehicle') {
|
||||
// // Robotic Arm to Vehicle
|
||||
|
||||
// } else if (toEvent?.type === 'machine') {
|
||||
// // Robotic Arm to Machine
|
||||
|
||||
// } else if (toEvent?.type === 'roboticArm') {
|
||||
// // Robotic Arm to Robotic Arm
|
||||
|
||||
// } else if (toEvent?.type === 'storageUnit') {
|
||||
// // Robotic Arm to Storage Unit
|
||||
|
||||
// }
|
||||
// } else if (fromEvent?.type === 'storageUnit') {
|
||||
// if (toEvent?.type === 'transfer') {
|
||||
// // Storage Unit to Transfer
|
||||
|
||||
// } else if (toEvent?.type === 'vehicle') {
|
||||
// // Storage Unit to Vehicle
|
||||
|
||||
// } else if (toEvent?.type === 'machine') {
|
||||
// // Storage Unit to Machine
|
||||
|
||||
// } else if (toEvent?.type === 'roboticArm') {
|
||||
// // Storage Unit to Robotic Arm
|
||||
|
||||
// } else if (toEvent?.type === 'storageUnit') {
|
||||
// // Storage Unit to Storage Unit
|
||||
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
const triggerPointActions = useCallback((action: Action) => {
|
||||
|
@ -18,7 +133,7 @@ export function useTriggerHandler() {
|
|||
case 'onStart':
|
||||
break;
|
||||
case 'onComplete':
|
||||
handleTrigger(trigger);
|
||||
handleTrigger(trigger, action.actionUuid);
|
||||
break;
|
||||
case 'onStop':
|
||||
break;
|
||||
|
|
|
@ -6,6 +6,7 @@ type MaterialsStore = {
|
|||
|
||||
addMaterial: (material: MaterialSchema) => MaterialSchema | undefined;
|
||||
removeMaterial: (materialId: string) => MaterialSchema | undefined;
|
||||
clearMaterials: () => void;
|
||||
updateMaterial: (materialId: string, updates: Partial<MaterialSchema>) => MaterialSchema | undefined;
|
||||
|
||||
setCurrentLocation: (
|
||||
|
@ -35,6 +36,7 @@ type MaterialsStore = {
|
|||
setIsRendered: (materialId: string, isRendered: boolean) => MaterialSchema | undefined;
|
||||
|
||||
getMaterialById: (materialId: string) => MaterialSchema | undefined;
|
||||
getMaterialByCurrentModelUuid: (currentModelUuid: string) => MaterialSchema | undefined;
|
||||
getMaterialsByPoint: (pointUuid: string) => MaterialSchema[];
|
||||
getMaterialsByModel: (modelUuid: string) => MaterialSchema[];
|
||||
};
|
||||
|
@ -63,6 +65,12 @@ export const useMaterialStore = create<MaterialsStore>()(
|
|||
return updatedMaterial;
|
||||
},
|
||||
|
||||
clearMaterials: () => {
|
||||
set((state) => {
|
||||
state.materials = [];
|
||||
});
|
||||
},
|
||||
|
||||
updateMaterial: (materialId, updates) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
|
@ -186,6 +194,10 @@ export const useMaterialStore = create<MaterialsStore>()(
|
|||
getMaterialById: (materialId) => {
|
||||
return get().materials.find(m => m.materialId === materialId);
|
||||
},
|
||||
|
||||
getMaterialByCurrentModelUuid: (currentModelUuid) => {
|
||||
return get().materials.find(m => m.current?.modelUuid === currentModelUuid);
|
||||
},
|
||||
|
||||
getMaterialsByPoint: (pointUuid) => {
|
||||
return get().materials.filter(m =>
|
||||
|
|
|
@ -61,6 +61,8 @@ type ProductsStore = {
|
|||
// Helper functions
|
||||
getProductById: (productId: string) => { productName: string; productId: string; eventDatas: EventsSchema[] } | undefined;
|
||||
getEventByModelUuid: (productId: string, modelUuid: string) => EventsSchema | undefined;
|
||||
getEventByTriggerUuid: (productId: string, triggerUuid: string) => EventsSchema | undefined;
|
||||
getEventByPointUuid: (productId: string, pointUuid: string) => EventsSchema | undefined;
|
||||
getPointByUuid: (productId: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
|
||||
getActionByUuid: (productId: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
|
||||
getModelUuidByPointUuid: (productId: string, actionUuid: string) => (string) | undefined;
|
||||
|
@ -540,6 +542,53 @@ export const useProductStore = create<ProductsStore>()(
|
|||
return product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
},
|
||||
|
||||
getEventByTriggerUuid: (productId, triggerUuid) => {
|
||||
const product = get().getProductById(productId);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action?.triggers?.some(t => t.triggerUuid === triggerUuid)) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point) {
|
||||
if (point.action?.triggers?.some((t: any) => t.triggerUuid === triggerUuid)) {
|
||||
return event;
|
||||
}
|
||||
} else if ('actions' in point) {
|
||||
for (const action of point.actions) {
|
||||
if (action.triggers?.some((t: any) => t.triggerUuid === triggerUuid)) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getEventByPointUuid: (productId, pointUuid) => {
|
||||
const product = get().getProductById(productId);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
if ((event as ConveyorEventSchema).points.some(p => p.uuid === pointUuid)) {
|
||||
return event;
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
if ((event as any).point?.uuid === pointUuid) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getPointByUuid: (productId, modelUuid, pointUuid) => {
|
||||
const event = get().getEventByModelUuid(productId, modelUuid);
|
||||
if (!event) return undefined;
|
||||
|
|
Loading…
Reference in New Issue