"updated single flow"
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { useFrame, useThree } from '@react-three/fiber';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import * as THREE from 'three';
|
||||
import * as Types from '../../../types/world/worldTypes';
|
||||
import { QuadraticBezierLine } from '@react-three/drei';
|
||||
import { useIsConnecting, useSimulationStates, useSocketStore } from '../../../store/store';
|
||||
import { useDeleteTool, useIsConnecting, useRenderDistance, useSimulationStates, useSocketStore } from '../../../store/store';
|
||||
import useModuleStore from '../../../store/useModuleStore';
|
||||
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
||||
import { setEventApi } from '../../../services/factoryBuilder/assest/floorAsset/setEventsApt';
|
||||
@@ -11,28 +11,23 @@ import { setEventApi } from '../../../services/factoryBuilder/assest/floorAsset/
|
||||
function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject<THREE.Group> }) {
|
||||
const { activeModule } = useModuleStore();
|
||||
const { gl, raycaster, scene, pointer, camera } = useThree();
|
||||
const { deleteTool } = useDeleteTool();
|
||||
const { renderDistance } = useRenderDistance();
|
||||
const { setIsConnecting } = useIsConnecting();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { socket } = useSocketStore();
|
||||
const groupRefs = useRef<{ [key: string]: any }>({});
|
||||
|
||||
const [firstSelected, setFirstSelected] = useState<{
|
||||
modelUUID: string;
|
||||
sphereUUID: string;
|
||||
position: THREE.Vector3;
|
||||
isCorner: boolean;
|
||||
} | null>(null);
|
||||
const [firstSelected, setFirstSelected] = useState<{ modelUUID: string; sphereUUID: string; position: THREE.Vector3; isCorner: boolean; } | null>(null);
|
||||
const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3, end: THREE.Vector3, mid: THREE.Vector3 } | null>(null);
|
||||
const [helperlineColor, setHelperLineColor] = useState<string>('red');
|
||||
const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
|
||||
|
||||
const updatePathConnections = (
|
||||
fromModelUUID: string,
|
||||
fromPointUUID: string,
|
||||
toModelUUID: string,
|
||||
toPointUUID: string
|
||||
) => {
|
||||
const updatePathConnections = (fromModelUUID: string, fromPointUUID: string, toModelUUID: string, toPointUUID: string) => {
|
||||
const updatedPaths = simulationStates.map(path => {
|
||||
if (path.type === 'Conveyor') {
|
||||
// Handle outgoing connections from Conveyor
|
||||
if (path.modeluuid === fromModelUUID) {
|
||||
return {
|
||||
...path,
|
||||
@@ -61,6 +56,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
})
|
||||
};
|
||||
}
|
||||
// Handle incoming connections to Conveyor
|
||||
else if (path.modeluuid === toModelUUID) {
|
||||
return {
|
||||
...path,
|
||||
@@ -167,82 +163,170 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
}
|
||||
return path;
|
||||
}
|
||||
// else if (path.type === 'StaticMachine') {
|
||||
// if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
|
||||
// const newTarget = {
|
||||
// modelUUID: toModelUUID,
|
||||
// pointUUID: toPointUUID
|
||||
// };
|
||||
// const existingTargets = path.points.connections.targets || [];
|
||||
else if (path.type === 'StaticMachine') {
|
||||
// Handle outgoing connections from StaticMachine
|
||||
if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
|
||||
const newTarget = {
|
||||
modelUUID: toModelUUID,
|
||||
pointUUID: toPointUUID
|
||||
};
|
||||
|
||||
// // Check if target is an ArmBot
|
||||
// const toPath = simulationStates.find(p => p.modeluuid === toModelUUID);
|
||||
// if (toPath?.type !== 'ArmBot') {
|
||||
// console.log("StaticMachine can only connect to ArmBot");
|
||||
// return path;
|
||||
// }
|
||||
// Ensure target is an ArmBot
|
||||
const toPath = simulationStates.find(p => p.modeluuid === toModelUUID);
|
||||
if (toPath?.type !== 'ArmBot') {
|
||||
console.log("StaticMachine can only connect to ArmBot");
|
||||
return path;
|
||||
}
|
||||
|
||||
// // Check if already has a connection
|
||||
// if (existingTargets.length >= 1) {
|
||||
// console.log("StaticMachine can have only one connection");
|
||||
// return path;
|
||||
// }
|
||||
const existingTargets = path.points.connections.targets || [];
|
||||
|
||||
// if (!existingTargets.some(target =>
|
||||
// target.modelUUID === newTarget.modelUUID &&
|
||||
// target.pointUUID === newTarget.pointUUID
|
||||
// )) {
|
||||
// return {
|
||||
// ...path,
|
||||
// points: {
|
||||
// ...path.points,
|
||||
// connections: {
|
||||
// ...path.points.connections,
|
||||
// targets: [...existingTargets, newTarget]
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// // Handle incoming connections to StaticMachine
|
||||
// else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
|
||||
// const reverseTarget = {
|
||||
// modelUUID: fromModelUUID,
|
||||
// pointUUID: fromPointUUID
|
||||
// };
|
||||
// const existingTargets = path.points.connections.targets || [];
|
||||
// Allow only one connection
|
||||
if (existingTargets.length >= 1) {
|
||||
console.log("StaticMachine can only have one connection");
|
||||
return path;
|
||||
}
|
||||
|
||||
// // Check if source is an ArmBot
|
||||
// const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID);
|
||||
// if (fromPath?.type !== 'ArmBot') {
|
||||
// console.log("StaticMachine can only connect to ArmBot");
|
||||
// return path;
|
||||
// }
|
||||
if (!existingTargets.some(target =>
|
||||
target.modelUUID === newTarget.modelUUID &&
|
||||
target.pointUUID === newTarget.pointUUID
|
||||
)) {
|
||||
return {
|
||||
...path,
|
||||
points: {
|
||||
...path.points,
|
||||
connections: {
|
||||
...path.points.connections,
|
||||
targets: [...existingTargets, newTarget]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// // Check if already has a connection
|
||||
// if (existingTargets.length >= 1) {
|
||||
// console.log("StaticMachine can have only one connection");
|
||||
// return path;
|
||||
// }
|
||||
// Handle incoming connections to StaticMachine
|
||||
else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
|
||||
const reverseTarget = {
|
||||
modelUUID: fromModelUUID,
|
||||
pointUUID: fromPointUUID
|
||||
};
|
||||
|
||||
const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID);
|
||||
if (fromPath?.type !== 'ArmBot') {
|
||||
console.log("StaticMachine can only be connected from ArmBot");
|
||||
return path;
|
||||
}
|
||||
|
||||
const existingTargets = path.points.connections.targets || [];
|
||||
|
||||
if (existingTargets.length >= 1) {
|
||||
console.log("StaticMachine can only have one connection");
|
||||
return path;
|
||||
}
|
||||
|
||||
if (!existingTargets.some(target =>
|
||||
target.modelUUID === reverseTarget.modelUUID &&
|
||||
target.pointUUID === reverseTarget.pointUUID
|
||||
)) {
|
||||
return {
|
||||
...path,
|
||||
points: {
|
||||
...path.points,
|
||||
connections: {
|
||||
...path.points.connections,
|
||||
targets: [...existingTargets, reverseTarget]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
else if (path.type === 'ArmBot') {
|
||||
// Handle outgoing connections from ArmBot
|
||||
if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
|
||||
const newTarget = {
|
||||
modelUUID: toModelUUID,
|
||||
pointUUID: toPointUUID
|
||||
};
|
||||
|
||||
const toPath = simulationStates.find(p => p.modeluuid === toModelUUID);
|
||||
if (!toPath) return path;
|
||||
|
||||
const existingTargets = path.points.connections.targets || [];
|
||||
|
||||
// Check if connecting to a StaticMachine and already connected to one
|
||||
const alreadyConnectedToStatic = existingTargets.some(target => {
|
||||
const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
|
||||
return targetPath?.type === 'StaticMachine';
|
||||
});
|
||||
|
||||
if (toPath.type === 'StaticMachine') {
|
||||
if (alreadyConnectedToStatic) {
|
||||
console.log("ArmBot can only connect to one StaticMachine");
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
if (!existingTargets.some(target =>
|
||||
target.modelUUID === newTarget.modelUUID &&
|
||||
target.pointUUID === newTarget.pointUUID
|
||||
)) {
|
||||
return {
|
||||
...path,
|
||||
points: {
|
||||
...path.points,
|
||||
connections: {
|
||||
...path.points.connections,
|
||||
targets: [...existingTargets, newTarget]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Handle incoming connections to ArmBot
|
||||
else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
|
||||
const reverseTarget = {
|
||||
modelUUID: fromModelUUID,
|
||||
pointUUID: fromPointUUID
|
||||
};
|
||||
|
||||
const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID);
|
||||
if (!fromPath) return path;
|
||||
|
||||
const existingTargets = path.points.connections.targets || [];
|
||||
|
||||
const alreadyConnectedFromStatic = existingTargets.some(target => {
|
||||
const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
|
||||
return targetPath?.type === 'StaticMachine';
|
||||
});
|
||||
|
||||
if (fromPath.type === 'StaticMachine') {
|
||||
if (alreadyConnectedFromStatic) {
|
||||
console.log("ArmBot can only be connected from one StaticMachine");
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
if (!existingTargets.some(target =>
|
||||
target.modelUUID === reverseTarget.modelUUID &&
|
||||
target.pointUUID === reverseTarget.pointUUID
|
||||
)) {
|
||||
return {
|
||||
...path,
|
||||
points: {
|
||||
...path.points,
|
||||
connections: {
|
||||
...path.points.connections,
|
||||
targets: [...existingTargets, reverseTarget]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
// if (!existingTargets.some(target =>
|
||||
// target.modelUUID === reverseTarget.modelUUID &&
|
||||
// target.pointUUID === reverseTarget.pointUUID
|
||||
// )) {
|
||||
// return {
|
||||
// ...path,
|
||||
// points: {
|
||||
// ...path.points,
|
||||
// connections: {
|
||||
// ...path.points.connections,
|
||||
// targets: [...existingTargets, reverseTarget]
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// return path;
|
||||
// }
|
||||
return path;
|
||||
});
|
||||
|
||||
@@ -255,7 +339,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
updateBackend(updatedPathDetails);
|
||||
};
|
||||
|
||||
const updateBackend = async (updatedPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => {
|
||||
const updateBackend = async (updatedPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | Types.ArmBotEventsSchema)[]) => {
|
||||
if (updatedPaths.length === 0) return;
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "";
|
||||
@@ -293,6 +377,38 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
|
||||
socket.emit('v2:model-asset:updateEventData', data);
|
||||
|
||||
} else if (updatedPath.type === 'StaticMachine') {
|
||||
|
||||
// await setEventApi(
|
||||
// organization,
|
||||
// updatedPath.modeluuid,
|
||||
// { type: "StaticMachine", points: updatedPath.points }
|
||||
// );
|
||||
|
||||
const data = {
|
||||
organization: organization,
|
||||
modeluuid: updatedPath.modeluuid,
|
||||
eventData: { type: "StaticMachine", points: updatedPath.points }
|
||||
}
|
||||
|
||||
socket.emit('v2:model-asset:updateEventData', data);
|
||||
|
||||
} else if (updatedPath.type === 'ArmBot') {
|
||||
|
||||
// await setEventApi(
|
||||
// organization,
|
||||
// updatedPath.modeluuid,
|
||||
// { type: "ArmBot", points: updatedPath.points }
|
||||
// );
|
||||
|
||||
const data = {
|
||||
organization: organization,
|
||||
modeluuid: updatedPath.modeluuid,
|
||||
eventData: { type: "ArmBot", points: updatedPath.points }
|
||||
}
|
||||
|
||||
socket.emit('v2:model-asset:updateEventData', data);
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
@@ -397,7 +513,6 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
|
||||
// For Vehicles, check if they're already connected to anything
|
||||
if (intersected.userData.path.type === 'Vehicle') {
|
||||
console.log('intersected: ', intersected);
|
||||
const vehicleConnections = intersected.userData.path.points.connections.targets.length;
|
||||
if (vehicleConnections >= 1) {
|
||||
console.log("Vehicle can only have one connection");
|
||||
@@ -437,6 +552,69 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if StaticMachine is involved in the connection
|
||||
if ((firstPath?.type === 'StaticMachine' && secondPath?.type !== 'ArmBot') ||
|
||||
(secondPath?.type === 'StaticMachine' && firstPath?.type !== 'ArmBot')) {
|
||||
console.log("StaticMachine can only connect to ArmBot");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if StaticMachine already has a connection
|
||||
if (firstPath?.type === 'StaticMachine') {
|
||||
const staticConnections = firstPath.points.connections.targets.length;
|
||||
if (staticConnections >= 1) {
|
||||
console.log("StaticMachine can only have one connection");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (secondPath?.type === 'StaticMachine') {
|
||||
const staticConnections = secondPath.points.connections.targets.length;
|
||||
if (staticConnections >= 1) {
|
||||
console.log("StaticMachine can only have one connection");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if ArmBot is involved
|
||||
if ((firstPath?.type === 'ArmBot' && secondPath?.type === 'StaticMachine') ||
|
||||
(secondPath?.type === 'ArmBot' && firstPath?.type === 'StaticMachine')) {
|
||||
|
||||
const armBotPath = firstPath?.type === 'ArmBot' ? firstPath : secondPath;
|
||||
const staticPath = firstPath?.type === 'StaticMachine' ? firstPath : secondPath;
|
||||
|
||||
const armBotConnections = armBotPath.points.connections.targets || [];
|
||||
const alreadyConnectedToStatic = armBotConnections.some(target => {
|
||||
const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
|
||||
return targetPath?.type === 'StaticMachine';
|
||||
});
|
||||
|
||||
if (alreadyConnectedToStatic) {
|
||||
console.log("ArmBot can only connect to one StaticMachine");
|
||||
return;
|
||||
}
|
||||
|
||||
const staticConnections = staticPath.points.connections.targets.length;
|
||||
if (staticConnections >= 1) {
|
||||
console.log("StaticMachine can only have one connection");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent ArmBot ↔ ArmBot
|
||||
if (firstPath?.type === 'ArmBot' && secondPath?.type === 'ArmBot') {
|
||||
console.log("Cannot connect two ArmBots together");
|
||||
return;
|
||||
}
|
||||
|
||||
// If one is ArmBot, ensure the other is StaticMachine or Conveyor
|
||||
if (firstPath?.type === 'ArmBot' || secondPath?.type === 'ArmBot') {
|
||||
const otherType = firstPath?.type === 'ArmBot' ? secondPath?.type : firstPath?.type;
|
||||
if (otherType !== 'StaticMachine' && otherType !== 'Conveyor') {
|
||||
console.log("ArmBot can only connect to Conveyors or one StaticMachine");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// At least one must be start/end point
|
||||
if (!firstSelected.isCorner && !isStartOrEnd) {
|
||||
console.log("At least one of the selected spheres must be a start or end point.");
|
||||
@@ -444,20 +622,10 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
}
|
||||
|
||||
// All checks passed - make the connection
|
||||
handleAddConnection(
|
||||
firstSelected.modelUUID,
|
||||
firstSelected.sphereUUID,
|
||||
modelUUID,
|
||||
sphereUUID
|
||||
);
|
||||
handleAddConnection(firstSelected.modelUUID, firstSelected.sphereUUID, modelUUID, sphereUUID);
|
||||
} else {
|
||||
// First selection - just store it
|
||||
setFirstSelected({
|
||||
modelUUID,
|
||||
sphereUUID,
|
||||
position: worldPosition,
|
||||
isCorner: isStartOrEnd
|
||||
});
|
||||
setFirstSelected({ modelUUID, sphereUUID, position: worldPosition, isCorner: isStartOrEnd });
|
||||
setIsConnecting(true);
|
||||
}
|
||||
}
|
||||
@@ -470,7 +638,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
}
|
||||
};
|
||||
|
||||
if (activeModule === 'simulation') {
|
||||
if (activeModule === 'simulation' && !deleteTool) {
|
||||
canvasElement.addEventListener("mousedown", onMouseDown);
|
||||
canvasElement.addEventListener("mouseup", onMouseUp);
|
||||
canvasElement.addEventListener("mousemove", onMouseMove);
|
||||
@@ -487,7 +655,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
canvasElement.removeEventListener("mousemove", onMouseMove);
|
||||
canvasElement.removeEventListener("contextmenu", onContextMenu);
|
||||
};
|
||||
}, [camera, scene, raycaster, firstSelected, simulationStates]);
|
||||
}, [camera, scene, raycaster, firstSelected, simulationStates, deleteTool]);
|
||||
|
||||
useFrame(() => {
|
||||
Object.values(groupRefs.current).forEach((group) => {
|
||||
if (group) {
|
||||
const distance = new THREE.Vector3(...group.position.toArray()).distanceTo(camera.position);
|
||||
group.visible = ((distance <= renderDistance) && !isPlaying);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
useFrame(() => {
|
||||
if (firstSelected) {
|
||||
@@ -511,9 +688,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
}
|
||||
}
|
||||
|
||||
const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) =>
|
||||
obj.object.name.includes("events-sphere")
|
||||
);
|
||||
const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) => obj.object.name.includes("events-sphere"));
|
||||
|
||||
if (sphereIntersects.length > 0) {
|
||||
const sphere = sphereIntersects[0].object;
|
||||
@@ -528,15 +703,21 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
const isVehicleToVehicle = firstPath?.type === 'Vehicle' && secondPath?.type === 'Vehicle';
|
||||
|
||||
// Inside the useFrame hook, where we check for snapped spheres:
|
||||
const isConnectable = (pathData.type === 'Vehicle' ||
|
||||
const isConnectable = (
|
||||
pathData.type === 'Vehicle' ||
|
||||
pathData.type === 'ArmBot' ||
|
||||
(pathData.points.length > 0 && (
|
||||
sphereUUID === pathData.points[0].uuid ||
|
||||
sphereUUID === pathData.points[pathData.points.length - 1].uuid
|
||||
))) &&
|
||||
sphereUUID === pathData.points[pathData.points.length - 1].uuid ||
|
||||
(pathData.type === 'Conveyor' && firstPath?.type === 'ArmBot') // Allow ArmBot to connect to middle points
|
||||
))
|
||||
) &&
|
||||
!isVehicleToVehicle &&
|
||||
!(firstPath?.type === 'Conveyor' &&
|
||||
!(
|
||||
firstPath?.type === 'Conveyor' &&
|
||||
pathData.type === 'Conveyor' &&
|
||||
!firstSelected.isCorner);
|
||||
!firstSelected.isCorner
|
||||
);
|
||||
|
||||
// Check for duplicate connection (regardless of path type)
|
||||
const isDuplicateConnection = simulationStates.some(path => {
|
||||
@@ -574,12 +755,50 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
(firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
|
||||
(secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor');
|
||||
|
||||
// Check if StaticMachine is connecting to non-ArmBot
|
||||
const isStaticMachineToNonArmBot =
|
||||
(firstPath?.type === 'StaticMachine' && secondPath?.type !== 'ArmBot') ||
|
||||
(secondPath?.type === 'StaticMachine' && firstPath?.type !== 'ArmBot');
|
||||
|
||||
// Check if StaticMachine already has a connection
|
||||
const isStaticMachineAtMaxConnections =
|
||||
(firstPath?.type === 'StaticMachine' && firstPath.points.connections.targets.length >= 1) ||
|
||||
(secondPath?.type === 'StaticMachine' && secondPath.points.connections.targets.length >= 1);
|
||||
|
||||
// Check if ArmBot is connecting to StaticMachine
|
||||
const isArmBotToStaticMachine =
|
||||
(firstPath?.type === 'ArmBot' && secondPath?.type === 'StaticMachine') ||
|
||||
(secondPath?.type === 'ArmBot' && firstPath?.type === 'StaticMachine');
|
||||
|
||||
// Prevent multiple StaticMachine connections to ArmBot
|
||||
let isArmBotAlreadyConnectedToStatic = false;
|
||||
if (isArmBotToStaticMachine) {
|
||||
const armBotPath = firstPath?.type === 'ArmBot' ? firstPath : secondPath;
|
||||
isArmBotAlreadyConnectedToStatic = armBotPath.points.connections.targets.some(target => {
|
||||
const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
|
||||
return targetPath?.type === 'StaticMachine';
|
||||
});
|
||||
}
|
||||
|
||||
// Prevent ArmBot to ArmBot
|
||||
const isArmBotToArmBot = firstPath?.type === 'ArmBot' && secondPath?.type === 'ArmBot';
|
||||
|
||||
// If ArmBot is involved, other must be Conveyor or StaticMachine
|
||||
const isArmBotToInvalidType = (firstPath?.type === 'ArmBot' || secondPath?.type === 'ArmBot') &&
|
||||
!(firstPath?.type === 'Conveyor' || firstPath?.type === 'StaticMachine' ||
|
||||
secondPath?.type === 'Conveyor' || secondPath?.type === 'StaticMachine');
|
||||
|
||||
if (
|
||||
!isDuplicateConnection &&
|
||||
!isVehicleToVehicle &&
|
||||
!isNonVehicleAlreadyConnected &&
|
||||
!isVehicleAtMaxConnections &&
|
||||
!isVehicleConnectingToNonConveyor &&
|
||||
!isStaticMachineToNonArmBot &&
|
||||
!isStaticMachineAtMaxConnections &&
|
||||
!isArmBotToArmBot &&
|
||||
!isArmBotToInvalidType &&
|
||||
!isArmBotAlreadyConnectedToStatic &&
|
||||
firstSelected.sphereUUID !== sphereUUID &&
|
||||
firstSelected.modelUUID !== modelUUID &&
|
||||
(firstSelected.isCorner || isConnectable) &&
|
||||
@@ -596,6 +815,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
} else {
|
||||
isInvalidConnection = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (snappedSphere) {
|
||||
@@ -632,14 +852,144 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
}
|
||||
});
|
||||
|
||||
const removeConnections = (connection1: { model: string; point: string }, connection2: { model: string; point: string }) => {
|
||||
const updatedStates = simulationStates.map(state => {
|
||||
// Handle Conveyor (which has multiple points)
|
||||
if (state.type === 'Conveyor') {
|
||||
const updatedConveyor: Types.ConveyorEventsSchema = {
|
||||
...state,
|
||||
points: state.points.map(point => {
|
||||
// Check if this point is either connection1 or connection2
|
||||
if ((state.modeluuid === connection1.model && point.uuid === connection1.point) ||
|
||||
(state.modeluuid === connection2.model && point.uuid === connection2.point)) {
|
||||
|
||||
return {
|
||||
...point,
|
||||
connections: {
|
||||
...point.connections,
|
||||
targets: point.connections.targets.filter(target => {
|
||||
// Remove the target that matches the other connection
|
||||
return !(
|
||||
(target.modelUUID === connection1.model && target.pointUUID === connection1.point) ||
|
||||
(target.modelUUID === connection2.model && target.pointUUID === connection2.point)
|
||||
);
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
return point;
|
||||
})
|
||||
};
|
||||
return updatedConveyor;
|
||||
}
|
||||
// Handle Vehicle
|
||||
else if (state.type === 'Vehicle') {
|
||||
if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) ||
|
||||
(state.modeluuid === connection2.model && state.points.uuid === connection2.point)) {
|
||||
|
||||
const updatedVehicle: Types.VehicleEventsSchema = {
|
||||
...state,
|
||||
points: {
|
||||
...state.points,
|
||||
connections: {
|
||||
...state.points.connections,
|
||||
targets: state.points.connections.targets.filter(target => {
|
||||
return !(
|
||||
(target.modelUUID === connection1.model && target.pointUUID === connection1.point) ||
|
||||
(target.modelUUID === connection2.model && target.pointUUID === connection2.point)
|
||||
);
|
||||
})
|
||||
},
|
||||
// Ensure all required Vehicle point properties are included
|
||||
speed: state.points.speed,
|
||||
actions: state.points.actions
|
||||
}
|
||||
};
|
||||
return updatedVehicle;
|
||||
}
|
||||
}
|
||||
// Handle StaticMachine
|
||||
else if (state.type === 'StaticMachine') {
|
||||
if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) ||
|
||||
(state.modeluuid === connection2.model && state.points.uuid === connection2.point)) {
|
||||
|
||||
const updatedStaticMachine: Types.StaticMachineEventsSchema = {
|
||||
...state,
|
||||
points: {
|
||||
...state.points,
|
||||
connections: {
|
||||
...state.points.connections,
|
||||
targets: state.points.connections.targets.filter(target => {
|
||||
return !(
|
||||
(target.modelUUID === connection1.model && target.pointUUID === connection1.point) ||
|
||||
(target.modelUUID === connection2.model && target.pointUUID === connection2.point)
|
||||
);
|
||||
})
|
||||
},
|
||||
// Ensure all required StaticMachine point properties are included
|
||||
actions: state.points.actions,
|
||||
triggers: state.points.triggers
|
||||
}
|
||||
};
|
||||
return updatedStaticMachine;
|
||||
}
|
||||
}
|
||||
// Handle ArmBot
|
||||
else if (state.type === 'ArmBot') {
|
||||
if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) ||
|
||||
(state.modeluuid === connection2.model && state.points.uuid === connection2.point)) {
|
||||
|
||||
const updatedArmBot: Types.ArmBotEventsSchema = {
|
||||
...state,
|
||||
points: {
|
||||
...state.points,
|
||||
connections: {
|
||||
...state.points.connections,
|
||||
targets: state.points.connections.targets.filter(target => {
|
||||
return !(
|
||||
(target.modelUUID === connection1.model && target.pointUUID === connection1.point) ||
|
||||
(target.modelUUID === connection2.model && target.pointUUID === connection2.point)
|
||||
);
|
||||
})
|
||||
},
|
||||
actions: {
|
||||
...state.points.actions,
|
||||
processes: state.points.actions.processes?.filter(process => {
|
||||
return !(
|
||||
process.startPoint === connection1.point ||
|
||||
process.endPoint === connection1.point ||
|
||||
process.startPoint === connection2.point ||
|
||||
process.endPoint === connection2.point
|
||||
);
|
||||
}) || []
|
||||
},
|
||||
triggers: state.points.triggers
|
||||
}
|
||||
};
|
||||
return updatedArmBot;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
});
|
||||
|
||||
const updatedPaths = updatedStates.filter(state =>
|
||||
state.modeluuid === connection1.model || state.modeluuid === connection2.model
|
||||
);
|
||||
|
||||
updateBackend(updatedPaths);
|
||||
|
||||
setSimulationStates(updatedStates);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<group name='simulationConnectionGroup' visible={!isPlaying} >
|
||||
<group name='simulationConnectionGroup' visible={!isPlaying}>
|
||||
{simulationStates.flatMap(path => {
|
||||
if (path.type === 'Conveyor') {
|
||||
return path.points.flatMap(point =>
|
||||
point.connections.targets.map((target, index) => {
|
||||
const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
|
||||
if (targetPath?.type === 'Vehicle') return null;
|
||||
if (targetPath?.type !== 'Conveyor' && targetPath?.type !== 'ArmBot') return null;
|
||||
|
||||
const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid);
|
||||
const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
|
||||
@@ -652,31 +1002,48 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
|
||||
const distance = fromWorldPosition.distanceTo(toWorldPosition);
|
||||
const heightFactor = Math.max(0.5, distance * 0.2);
|
||||
|
||||
const midPoint = new THREE.Vector3(
|
||||
(fromWorldPosition.x + toWorldPosition.x) / 2,
|
||||
Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor,
|
||||
(fromWorldPosition.z + toWorldPosition.z) / 2
|
||||
);
|
||||
const midPoint = new THREE.Vector3((fromWorldPosition.x + toWorldPosition.x) / 2, Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, (fromWorldPosition.z + toWorldPosition.z) / 2);
|
||||
|
||||
return (
|
||||
<QuadraticBezierLine
|
||||
key={`${point.uuid}-${target.pointUUID}-${index}`}
|
||||
ref={(el) => (groupRefs.current[`${point.uuid}-${target.pointUUID}-${index}`] = el!)}
|
||||
start={fromWorldPosition.toArray()}
|
||||
end={toWorldPosition.toArray()}
|
||||
mid={midPoint.toArray()}
|
||||
color="white"
|
||||
color={
|
||||
deleteTool && hoveredLineKey === `${point.uuid}-${target.pointUUID}-${index}`
|
||||
? 'red'
|
||||
: targetPath?.type === 'ArmBot'
|
||||
? '#42a5f5'
|
||||
: 'white'
|
||||
}
|
||||
lineWidth={4}
|
||||
dashed
|
||||
dashed={(deleteTool && hoveredLineKey === `${point.uuid}-${target.pointUUID}-${index}`) ? false : true}
|
||||
dashSize={0.75}
|
||||
dashScale={20}
|
||||
onPointerOver={() => setHoveredLineKey(`${point.uuid}-${target.pointUUID}-${index}`)}
|
||||
onPointerOut={() => setHoveredLineKey(null)}
|
||||
onClick={() => {
|
||||
if (deleteTool) {
|
||||
|
||||
const connection1 = { model: path.modeluuid, point: point.uuid }
|
||||
const connection2 = { model: target.modelUUID, point: target.pointUUID }
|
||||
|
||||
removeConnections(connection1, connection2)
|
||||
|
||||
}
|
||||
}}
|
||||
userData={target}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
);
|
||||
} else if (path.type === 'Vehicle') {
|
||||
}
|
||||
|
||||
if (path.type === 'Vehicle') {
|
||||
return path.points.connections.targets.map((target, index) => {
|
||||
const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', path.points.uuid);
|
||||
const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
|
||||
@@ -689,30 +1056,97 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
|
||||
const distance = fromWorldPosition.distanceTo(toWorldPosition);
|
||||
const heightFactor = Math.max(0.5, distance * 0.2);
|
||||
|
||||
const midPoint = new THREE.Vector3(
|
||||
(fromWorldPosition.x + toWorldPosition.x) / 2,
|
||||
Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor,
|
||||
(fromWorldPosition.z + toWorldPosition.z) / 2
|
||||
);
|
||||
const midPoint = new THREE.Vector3((fromWorldPosition.x + toWorldPosition.x) / 2, Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, (fromWorldPosition.z + toWorldPosition.z) / 2);
|
||||
|
||||
return (
|
||||
<QuadraticBezierLine
|
||||
key={`${path.points.uuid}-${target.pointUUID}-${index}`}
|
||||
ref={(el) => (groupRefs.current[`${path.points.uuid}-${target.pointUUID}-${index}`] = el!)}
|
||||
start={fromWorldPosition.toArray()}
|
||||
end={toWorldPosition.toArray()}
|
||||
mid={midPoint.toArray()}
|
||||
color="orange"
|
||||
color={
|
||||
deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`
|
||||
? 'red'
|
||||
: 'orange'
|
||||
}
|
||||
lineWidth={4}
|
||||
dashed
|
||||
dashed={(deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`) ? false : true}
|
||||
dashSize={0.75}
|
||||
dashScale={20}
|
||||
onPointerOver={() => setHoveredLineKey(`${path.points.uuid}-${target.pointUUID}-${index}`)}
|
||||
onPointerOut={() => setHoveredLineKey(null)}
|
||||
onClick={() => {
|
||||
if (deleteTool) {
|
||||
|
||||
const connection1 = { model: path.modeluuid, point: path.points.uuid }
|
||||
const connection2 = { model: target.modelUUID, point: target.pointUUID }
|
||||
|
||||
removeConnections(connection1, connection2)
|
||||
}
|
||||
}}
|
||||
userData={target}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
if (path.type === 'StaticMachine') {
|
||||
return path.points.connections.targets.map((target, index) => {
|
||||
const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
|
||||
if (targetPath?.type !== 'ArmBot') return null;
|
||||
|
||||
const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', path.points.uuid);
|
||||
const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
|
||||
|
||||
if (fromSphere && toSphere) {
|
||||
const fromWorldPosition = new THREE.Vector3();
|
||||
const toWorldPosition = new THREE.Vector3();
|
||||
fromSphere.getWorldPosition(fromWorldPosition);
|
||||
toSphere.getWorldPosition(toWorldPosition);
|
||||
|
||||
const distance = fromWorldPosition.distanceTo(toWorldPosition);
|
||||
const heightFactor = Math.max(0.5, distance * 0.2);
|
||||
const midPoint = new THREE.Vector3((fromWorldPosition.x + toWorldPosition.x) / 2, Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, (fromWorldPosition.z + toWorldPosition.z) / 2);
|
||||
|
||||
return (
|
||||
<QuadraticBezierLine
|
||||
key={`${path.points.uuid}-${target.pointUUID}-${index}`}
|
||||
ref={(el) => (groupRefs.current[`${path.points.uuid}-${target.pointUUID}-${index}`] = el!)}
|
||||
start={fromWorldPosition.toArray()}
|
||||
end={toWorldPosition.toArray()}
|
||||
mid={midPoint.toArray()}
|
||||
color={
|
||||
deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`
|
||||
? 'red'
|
||||
: '#42a5f5'
|
||||
}
|
||||
lineWidth={4}
|
||||
dashed={(deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}`) ? false : true}
|
||||
dashSize={0.75}
|
||||
dashScale={20}
|
||||
onPointerOver={() => setHoveredLineKey(`${path.points.uuid}-${target.pointUUID}-${index}`)}
|
||||
onPointerOut={() => setHoveredLineKey(null)}
|
||||
onClick={() => {
|
||||
if (deleteTool) {
|
||||
|
||||
const connection1 = { model: path.modeluuid, point: path.points.uuid }
|
||||
const connection2 = { model: target.modelUUID, point: target.pointUUID }
|
||||
|
||||
removeConnections(connection1, connection2)
|
||||
|
||||
}
|
||||
}}
|
||||
userData={target}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
return [];
|
||||
})}
|
||||
|
||||
@@ -730,6 +1164,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
)}
|
||||
</group>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
export default PathConnector;
|
||||
@@ -206,6 +206,7 @@ function PathCreation({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObjec
|
||||
return (
|
||||
<group
|
||||
name={`${path.modeluuid}-${path.type}-path`}
|
||||
uuid={path.modeluuid}
|
||||
key={path.modeluuid}
|
||||
ref={(el) => (groupRefs.current[path.modeluuid] = el!)}
|
||||
position={path.position}
|
||||
@@ -271,10 +272,11 @@ function PathCreation({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObjec
|
||||
})}
|
||||
</group>
|
||||
);
|
||||
} else if (path.type === "Vehicle" || path.type === "StaticMachine") {
|
||||
} else if (path.type === "Vehicle") {
|
||||
return (
|
||||
<group
|
||||
name={`${path.modeluuid}-${path.type}-path`}
|
||||
uuid={path.modeluuid}
|
||||
key={path.modeluuid}
|
||||
ref={(el) => (groupRefs.current[path.modeluuid] = el!)}
|
||||
position={path.position}
|
||||
@@ -323,6 +325,112 @@ function PathCreation({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObjec
|
||||
</Sphere>
|
||||
</group>
|
||||
);
|
||||
} else if (path.type === "StaticMachine") {
|
||||
return (
|
||||
<group
|
||||
name={`${path.modeluuid}-${path.type}-path`}
|
||||
uuid={path.modeluuid}
|
||||
key={path.modeluuid}
|
||||
ref={(el) => (groupRefs.current[path.modeluuid] = el!)}
|
||||
position={path.position}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedPath({
|
||||
path,
|
||||
group: groupRefs.current[path.modeluuid],
|
||||
});
|
||||
setSelectedActionSphere(null);
|
||||
setTransformMode(null);
|
||||
setSubModule("mechanics");
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSelectedPath(null);
|
||||
setSubModule("properties");
|
||||
}}
|
||||
>
|
||||
<Sphere
|
||||
key={path.points.uuid}
|
||||
uuid={path.points.uuid}
|
||||
position={path.points.position}
|
||||
args={[0.15, 32, 32]}
|
||||
name="events-sphere"
|
||||
ref={(el) => (sphereRefs.current[path.points.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedActionSphere({
|
||||
path,
|
||||
points: sphereRefs.current[path.points.uuid],
|
||||
});
|
||||
setSubModule("mechanics");
|
||||
setSelectedPath(null);
|
||||
}}
|
||||
userData={{ points: path.points, path }}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSubModule("properties");
|
||||
setSelectedActionSphere(null);
|
||||
}}
|
||||
>
|
||||
<meshStandardMaterial color="yellow" />
|
||||
</Sphere>
|
||||
</group>
|
||||
);
|
||||
} else if (path.type === "ArmBot") {
|
||||
return (
|
||||
<group
|
||||
name={`${path.modeluuid}-${path.type}-path`}
|
||||
uuid={path.modeluuid}
|
||||
key={path.modeluuid}
|
||||
ref={(el) => (groupRefs.current[path.modeluuid] = el!)}
|
||||
position={path.position}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedPath({
|
||||
path,
|
||||
group: groupRefs.current[path.modeluuid],
|
||||
});
|
||||
setSelectedActionSphere(null);
|
||||
setTransformMode(null);
|
||||
setSubModule("mechanics");
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSelectedPath(null);
|
||||
setSubModule("properties");
|
||||
}}
|
||||
>
|
||||
<Sphere
|
||||
key={path.points.uuid}
|
||||
uuid={path.points.uuid}
|
||||
position={path.points.position}
|
||||
args={[0.15, 32, 32]}
|
||||
name="events-sphere"
|
||||
ref={(el) => (sphereRefs.current[path.points.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedActionSphere({
|
||||
path,
|
||||
points: sphereRefs.current[path.points.uuid],
|
||||
});
|
||||
setSubModule("mechanics");
|
||||
setSelectedPath(null);
|
||||
}}
|
||||
userData={{ points: path.points, path }}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSubModule("properties");
|
||||
setSelectedActionSphere(null);
|
||||
}}
|
||||
>
|
||||
<meshStandardMaterial color="pink" />
|
||||
</Sphere>
|
||||
</group>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
|
||||
@@ -9,17 +9,20 @@ import { useProcessAnimation } from "./useProcessAnimations";
|
||||
import ProcessObject from "./processObject";
|
||||
import { ProcessData } from "./types";
|
||||
import { useSimulationStates } from "../../../store/store";
|
||||
import { retrieveGLTF } from "../../../utils/indexDB/idbUtils";
|
||||
|
||||
interface ProcessContainerProps {
|
||||
processes: ProcessData[];
|
||||
setProcesses: React.Dispatch<React.SetStateAction<any[]>>;
|
||||
agvRef: any;
|
||||
MaterialRef: any;
|
||||
}
|
||||
|
||||
const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||
processes,
|
||||
setProcesses,
|
||||
agvRef,
|
||||
MaterialRef,
|
||||
}) => {
|
||||
const gltf = useLoader(GLTFLoader, crate) as GLTF;
|
||||
const groupRef = useRef<THREE.Group>(null);
|
||||
@@ -44,11 +47,57 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||
() => ({
|
||||
Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
|
||||
Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
|
||||
Default: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
|
||||
// Default: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
|
||||
Default: new THREE.MeshStandardMaterial(),
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// Update material references for all spawned objects
|
||||
Object.entries(animationStates).forEach(([processId, processState]) => {
|
||||
Object.keys(processState.spawnedObjects).forEach((objectId) => {
|
||||
const entry = {
|
||||
processId,
|
||||
objectId,
|
||||
};
|
||||
|
||||
const materialType =
|
||||
processState.spawnedObjects[objectId]?.currentMaterialType;
|
||||
|
||||
if (!materialType) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matRefArray = MaterialRef.current;
|
||||
|
||||
// Find existing material group
|
||||
const existing = matRefArray.find(
|
||||
(entryGroup: { material: string; objects: any[] }) =>
|
||||
entryGroup.material === materialType
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
// Check if this processId + objectId already exists
|
||||
const alreadyExists = existing.objects.some(
|
||||
(o: any) =>
|
||||
o.processId === entry.processId && o.objectId === entry.objectId
|
||||
);
|
||||
|
||||
if (!alreadyExists) {
|
||||
existing.objects.push(entry);
|
||||
}
|
||||
} else {
|
||||
// Create new group for this material type
|
||||
matRefArray.push({
|
||||
material: materialType,
|
||||
objects: [entry],
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}, [animationStates, MaterialRef, agvRef]);
|
||||
|
||||
// In processAnimator.tsx - only the relevant spawn logic part that needs fixes
|
||||
|
||||
useFrame(() => {
|
||||
@@ -252,14 +301,39 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||
const nextPointIdx = stateRef.currentIndex + 1;
|
||||
const isLastPoint = nextPointIdx >= path.length;
|
||||
|
||||
// if (isLastPoint) {
|
||||
// if (currentPointData?.actions) {
|
||||
// const shouldStop = !hasNonInheritActions(
|
||||
// currentPointData.actions
|
||||
// );
|
||||
// if (shouldStop) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (isLastPoint) {
|
||||
if (currentPointData?.actions) {
|
||||
const shouldStop = !hasNonInheritActions(
|
||||
const hasNonInherit = hasNonInheritActions(
|
||||
currentPointData.actions
|
||||
);
|
||||
if (shouldStop) {
|
||||
if (!hasNonInherit) {
|
||||
// Remove the object if all actions are inherit
|
||||
updatedObjects[objectId] = {
|
||||
...obj,
|
||||
visible: false,
|
||||
state: { ...stateRef, isAnimating: false },
|
||||
};
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// No actions at last point - remove the object
|
||||
updatedObjects[objectId] = {
|
||||
...obj,
|
||||
visible: false,
|
||||
state: { ...stateRef, isAnimating: false },
|
||||
};
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,6 +403,7 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
|
||||
.filter(([_, obj]) => obj.visible)
|
||||
.map(([objectId, obj]) => {
|
||||
const process = processedProcesses.find((p) => p.id === processId);
|
||||
|
||||
const renderAs = process?.renderAs || "custom";
|
||||
|
||||
return (
|
||||
|
||||
@@ -6,18 +6,24 @@ interface ProcessContainerProps {
|
||||
processes: any[];
|
||||
setProcesses: React.Dispatch<React.SetStateAction<any[]>>;
|
||||
agvRef: any;
|
||||
MaterialRef: any;
|
||||
}
|
||||
|
||||
const ProcessContainer: React.FC<ProcessContainerProps> = ({
|
||||
processes,
|
||||
setProcesses,
|
||||
agvRef
|
||||
agvRef,
|
||||
MaterialRef,
|
||||
}) => {
|
||||
console.log("processes: ", processes);
|
||||
return (
|
||||
<>
|
||||
<ProcessCreator onProcessesCreated={setProcesses} />
|
||||
<ProcessAnimator processes={processes} setProcesses={setProcesses} agvRef={agvRef}/>
|
||||
<ProcessAnimator
|
||||
processes={processes}
|
||||
setProcesses={setProcesses}
|
||||
agvRef={agvRef}
|
||||
MaterialRef={MaterialRef}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -25,7 +25,6 @@ interface EnhancedProcessAnimationState extends ProcessAnimationState {
|
||||
pointId: string;
|
||||
objectId: string;
|
||||
triggerId: string;
|
||||
hasSpawnedZeroIntervalObject?: boolean;
|
||||
}>;
|
||||
}
|
||||
|
||||
@@ -139,7 +138,6 @@ export const useProcessAnimation = (
|
||||
processDelayDuration: 0,
|
||||
triggerCounts,
|
||||
triggerLogs: [],
|
||||
hasSpawnedZeroIntervalObject: false, // Initialize the new property
|
||||
};
|
||||
});
|
||||
|
||||
@@ -453,7 +451,7 @@ export const useProcessAnimation = (
|
||||
|
||||
// Increment expectedHitCount if not playing
|
||||
if (!vehicleEntry.isplaying) {
|
||||
vehicleEntry.expectedHitCount = processTotalHits + 1;
|
||||
vehicleEntry.expectedHitCount = processTotalHits;
|
||||
}
|
||||
|
||||
// Set vehicle's hitCount to the processTotalHits
|
||||
|
||||
@@ -18,6 +18,7 @@ function Simulation() {
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const [processes, setProcesses] = useState<any[]>([]);
|
||||
const agvRef = useRef([]);
|
||||
const MaterialRef = useRef([]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -26,8 +27,17 @@ function Simulation() {
|
||||
<>
|
||||
<PathCreation pathsGroupRef={pathsGroupRef} />
|
||||
<PathConnector pathsGroupRef={pathsGroupRef} />
|
||||
<ProcessContainer processes={processes} setProcesses={setProcesses} agvRef={agvRef} />
|
||||
<Agv processes={processes} agvRef={agvRef} />
|
||||
<ProcessContainer
|
||||
processes={processes}
|
||||
setProcesses={setProcesses}
|
||||
agvRef={agvRef}
|
||||
MaterialRef={MaterialRef}
|
||||
/>
|
||||
<Agv
|
||||
processes={processes}
|
||||
agvRef={agvRef}
|
||||
MaterialRef={MaterialRef}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user