feat: Extend simulation state types to include ArmBot events and update related components
- Updated RotateControls and SelectionControls to handle ArmBot events in simulation states. - Enhanced PathConnector to manage connections involving ArmBot and StaticMachine types. - Added ArmBotMechanics and StaticMachineMechanics components for managing properties of ArmBot and StaticMachine. - Modified types in worldTypes to include rotation for ArmBot and StaticMachine events. - Updated store to accommodate new ArmBot event types in simulation states.
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 { 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,21 @@ 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 { 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 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 +54,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
})
|
||||
};
|
||||
}
|
||||
// Handle incoming connections to Conveyor
|
||||
else if (path.modeluuid === toModelUUID) {
|
||||
return {
|
||||
...path,
|
||||
@@ -167,82 +161,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;
|
||||
});
|
||||
|
||||
@@ -252,10 +334,10 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
path.modeluuid === fromModelUUID || path.modeluuid === toModelUUID
|
||||
);
|
||||
|
||||
updateBackend(updatedPathDetails);
|
||||
// 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] : "";
|
||||
@@ -437,6 +519,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.");
|
||||
@@ -489,6 +634,15 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
};
|
||||
}, [camera, scene, raycaster, firstSelected, simulationStates]);
|
||||
|
||||
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) {
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
@@ -574,12 +728,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 +788,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
} else {
|
||||
isInvalidConnection = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (snappedSphere) {
|
||||
@@ -633,7 +826,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
});
|
||||
|
||||
return (
|
||||
<group name='simulationConnectionGroup' visible={!isPlaying} >
|
||||
<group name='simulationConnectionGroup' visible={!isPlaying}>
|
||||
{simulationStates.flatMap(path => {
|
||||
if (path.type === 'Conveyor') {
|
||||
return path.points.flatMap(point =>
|
||||
@@ -652,7 +845,6 @@ 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,
|
||||
@@ -662,6 +854,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
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()}
|
||||
@@ -676,7 +869,9 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
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,7 +884,6 @@ 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,
|
||||
@@ -699,6 +893,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
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()}
|
||||
@@ -713,6 +908,48 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
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="#42a5f5"
|
||||
lineWidth={4}
|
||||
dashed
|
||||
dashSize={0.75}
|
||||
dashScale={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
return [];
|
||||
})}
|
||||
|
||||
@@ -730,6 +967,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,114 @@ 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}
|
||||
rotation={path.rotation}
|
||||
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}
|
||||
rotation={path.rotation}
|
||||
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;
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user