feat: Implement Points management with PointsCreator component; enhance event handling and transform controls for simulation points
This commit is contained in:
@@ -184,24 +184,9 @@ async function handleModelLoad(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!data || !data.points) return;
|
if (!data || !data.points) return;
|
||||||
console.log('data: ', data);
|
|
||||||
|
|
||||||
const createMarker = (point: THREE.Vector3) => {
|
|
||||||
const sphere = new THREE.SphereGeometry(0.1, 15);
|
|
||||||
const material = new THREE.MeshStandardMaterial();
|
|
||||||
const mesh = new THREE.Mesh(sphere, material);
|
|
||||||
mesh.position.copy(point);
|
|
||||||
return mesh;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (data.points && data.points.length > 0) {
|
|
||||||
data.points.forEach((Point) => {
|
|
||||||
model.add(createMarker(Point));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedItem.type === "Conveyor") {
|
if (selectedItem.type === "Conveyor") {
|
||||||
const event: ConveyorEventSchema = {
|
const ConveyorEvent: ConveyorEventSchema = {
|
||||||
modelUuid: newFloorItem.modeluuid,
|
modelUuid: newFloorItem.modeluuid,
|
||||||
modelName: newFloorItem.modelname,
|
modelName: newFloorItem.modelname,
|
||||||
position: newFloorItem.position,
|
position: newFloorItem.position,
|
||||||
@@ -225,7 +210,85 @@ async function handleModelLoad(
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
addEvent(event);
|
addEvent(ConveyorEvent);
|
||||||
|
} else if (selectedItem.type === "Vehicle") {
|
||||||
|
const vehicleEvent: VehicleEventSchema = {
|
||||||
|
modelUuid: newFloorItem.modeluuid,
|
||||||
|
modelName: newFloorItem.modelname,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
|
state: "idle",
|
||||||
|
type: "vehicle",
|
||||||
|
speed: 1,
|
||||||
|
point: {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
||||||
|
rotation: [0, 0, 0],
|
||||||
|
action: {
|
||||||
|
actionUuid: THREE.MathUtils.generateUUID(),
|
||||||
|
actionName: "Vehicle Action",
|
||||||
|
actionType: "travel",
|
||||||
|
material: null,
|
||||||
|
unLoadDuration: 5,
|
||||||
|
loadCapacity: 10,
|
||||||
|
pickUpPoint: null,
|
||||||
|
unLoadPoint: null,
|
||||||
|
triggers: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addEvent(vehicleEvent);
|
||||||
|
} else if (selectedItem.type === "ArmBot") {
|
||||||
|
const roboticArmEvent: RoboticArmEventSchema = {
|
||||||
|
modelUuid: newFloorItem.modeluuid,
|
||||||
|
modelName: newFloorItem.modelname,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
|
state: "idle",
|
||||||
|
type: "roboticArm",
|
||||||
|
speed: 1,
|
||||||
|
point: {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
||||||
|
rotation: [0, 0, 0],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionUuid: THREE.MathUtils.generateUUID(),
|
||||||
|
actionName: "Pick and Place",
|
||||||
|
actionType: "pickAndPlace",
|
||||||
|
process: {
|
||||||
|
startPoint: "start-point-uuid",
|
||||||
|
endPoint: "end-point-uuid"
|
||||||
|
},
|
||||||
|
triggers: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addEvent(roboticArmEvent);
|
||||||
|
} else if (selectedItem.type === "Machine") {
|
||||||
|
const machineEvent: MachineEventSchema = {
|
||||||
|
modelUuid: newFloorItem.modeluuid,
|
||||||
|
modelName: newFloorItem.modelname,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
|
state: "idle",
|
||||||
|
type: "machine",
|
||||||
|
point: {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
||||||
|
rotation: [0, 0, 0],
|
||||||
|
action: {
|
||||||
|
actionUuid: THREE.MathUtils.generateUUID(),
|
||||||
|
actionName: "Process Action",
|
||||||
|
actionType: "process",
|
||||||
|
processTime: 10,
|
||||||
|
swapMaterial: "material-id",
|
||||||
|
triggers: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addEvent(machineEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
import * as THREE from 'three';
|
||||||
|
import { useEventsStore } from '../../../../../store/simulation/useEventsStore';
|
||||||
|
import useModuleStore from '../../../../../store/useModuleStore';
|
||||||
|
import { TransformControls } from '@react-three/drei';
|
||||||
|
import { detectModifierKeys } from '../../../../../utils/shortcutkeys/detectModifierKeys';
|
||||||
|
|
||||||
|
function PointsCreator() {
|
||||||
|
const { events, updatePoint, getPointByUuid } = useEventsStore();
|
||||||
|
const { activeModule } = useModuleStore();
|
||||||
|
const transformRef = useRef<any>(null);
|
||||||
|
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
||||||
|
const [selectedPoint, setSelectedPoint] = useState<THREE.Mesh | null>(null);
|
||||||
|
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTransformMode(null);
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
const keyCombination = detectModifierKeys(e);
|
||||||
|
if (!selectedPoint) 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);
|
||||||
|
}, [selectedPoint]);
|
||||||
|
|
||||||
|
const updatePointToState = (selectedPoint: THREE.Mesh) => {
|
||||||
|
let point = JSON.parse(JSON.stringify(getPointByUuid(selectedPoint.userData.modelUuid, selectedPoint.userData.pointUuid)));
|
||||||
|
if (point) {
|
||||||
|
point.position = [selectedPoint.position.x, selectedPoint.position.y, selectedPoint.position.z];
|
||||||
|
updatePoint(selectedPoint.userData.modelUuid, selectedPoint.userData.pointUuid, point)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{activeModule === 'simulation' &&
|
||||||
|
<>
|
||||||
|
<group name='EventPointsGroup' >
|
||||||
|
{events.map((event, i) => {
|
||||||
|
if (event.type === 'transfer') {
|
||||||
|
return (
|
||||||
|
<group key={i} position={new THREE.Vector3(...event.position)}>
|
||||||
|
{event.points.map((point, j) => (
|
||||||
|
<mesh
|
||||||
|
uuid={point.uuid}
|
||||||
|
ref={(el) => (sphereRefs.current[point.uuid] = el!)}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setSelectedPoint(sphereRefs.current[point.uuid]);
|
||||||
|
}}
|
||||||
|
onPointerMissed={() => {
|
||||||
|
setSelectedPoint(null);
|
||||||
|
}}
|
||||||
|
key={`${i}-${j}`}
|
||||||
|
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={i} position={new THREE.Vector3(...event.position)}>
|
||||||
|
<mesh
|
||||||
|
uuid={event.point.uuid}
|
||||||
|
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setSelectedPoint(sphereRefs.current[event.point.uuid]);
|
||||||
|
}}
|
||||||
|
onPointerMissed={() => {
|
||||||
|
setSelectedPoint(null);
|
||||||
|
}}
|
||||||
|
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={i} position={new THREE.Vector3(...event.position)}>
|
||||||
|
<mesh
|
||||||
|
uuid={event.point.uuid}
|
||||||
|
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setSelectedPoint(sphereRefs.current[event.point.uuid]);
|
||||||
|
}}
|
||||||
|
onPointerMissed={() => {
|
||||||
|
setSelectedPoint(null);
|
||||||
|
}}
|
||||||
|
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={i} position={new THREE.Vector3(...event.position)}>
|
||||||
|
<mesh
|
||||||
|
uuid={event.point.uuid}
|
||||||
|
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setSelectedPoint(sphereRefs.current[event.point.uuid]);
|
||||||
|
}}
|
||||||
|
onPointerMissed={() => {
|
||||||
|
setSelectedPoint(null);
|
||||||
|
}}
|
||||||
|
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>
|
||||||
|
{(selectedPoint && transformMode) &&
|
||||||
|
<TransformControls ref={transformRef} object={selectedPoint} mode={transformMode} onMouseUp={(e) => { updatePointToState(selectedPoint) }} />
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PointsCreator;
|
||||||
12
app/src/modules/simulation/events/points/points.tsx
Normal file
12
app/src/modules/simulation/events/points/points.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PointsCreator from './creator/pointsCreator'
|
||||||
|
|
||||||
|
function Points() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PointsCreator />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Points
|
||||||
@@ -2,6 +2,7 @@ import React, { useEffect } from 'react';
|
|||||||
import { useEventsStore } from '../../store/simulation/useEventsStore';
|
import { useEventsStore } from '../../store/simulation/useEventsStore';
|
||||||
import { useProductStore } from '../../store/simulation/useProductStore';
|
import { useProductStore } from '../../store/simulation/useProductStore';
|
||||||
import Vehicles from './vehicle/vehicles';
|
import Vehicles from './vehicle/vehicles';
|
||||||
|
import Points from './events/points/points';
|
||||||
|
|
||||||
function Simulation() {
|
function Simulation() {
|
||||||
const { events } = useEventsStore();
|
const { events } = useEventsStore();
|
||||||
@@ -12,12 +13,16 @@ function Simulation() {
|
|||||||
}, [events])
|
}, [events])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('products: ', products);
|
// console.log('products: ', products);
|
||||||
}, [products])
|
}, [products])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
|
<Points />
|
||||||
|
|
||||||
<Vehicles />
|
<Vehicles />
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ function Vehicles() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('vehicles: ', vehicles);
|
// console.log('vehicles: ', vehicles);
|
||||||
}, [vehicles])
|
}, [vehicles])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
app/src/types/simulationTypes.d.ts
vendored
2
app/src/types/simulationTypes.d.ts
vendored
@@ -119,7 +119,7 @@ interface StorageEventSchema extends AssetEventSchema {
|
|||||||
point: StoragePointSchema;
|
point: StoragePointSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema | [];
|
type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema;
|
||||||
|
|
||||||
type productsSchema = {
|
type productsSchema = {
|
||||||
productName: string;
|
productName: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user