added arm ui
This commit is contained in:
@@ -1,169 +1,337 @@
|
||||
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';
|
||||
import { useSelectedEventSphere, useSelectedEventData } from '../../../../../store/simulation/useSimulationStore';
|
||||
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, useGLTF } from "@react-three/drei";
|
||||
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
|
||||
import {
|
||||
useSelectedEventSphere,
|
||||
useSelectedEventData,
|
||||
} from "../../../../../store/simulation/useSimulationStore";
|
||||
import PickDropPoints from "../../../../../components/ui/arm/PickDropPoints";
|
||||
|
||||
import armPick from "../../../../../assets/gltf-glb/arm_ui_pick.glb";
|
||||
import armDrop from "../../../../../assets/gltf-glb/arm_ui_drop.glb";
|
||||
import useDraggableGLTF from "../../../../../components/ui/arm/useDraggableGLTF";
|
||||
|
||||
interface Process {
|
||||
startPoint: number[] | null;
|
||||
endPoint: number[] | null;
|
||||
}
|
||||
|
||||
interface Action {
|
||||
actionUuid: string;
|
||||
actionName: string;
|
||||
actionType: string;
|
||||
process: Process;
|
||||
triggers: any[];
|
||||
}
|
||||
|
||||
interface Point {
|
||||
uuid: string;
|
||||
position: number[];
|
||||
rotation: number[];
|
||||
actions: Action[];
|
||||
}
|
||||
|
||||
interface RoboticArmEvent {
|
||||
modelUuid: string;
|
||||
modelName: string;
|
||||
position: number[];
|
||||
rotation: number[];
|
||||
state: string;
|
||||
type: string;
|
||||
speed: number;
|
||||
point: Point;
|
||||
}
|
||||
function PointsCreator() {
|
||||
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 { events, updatePoint, getPointByUuid, getEventByModelUuid } =
|
||||
useEventsStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedEventSphere) {
|
||||
const eventData = getEventByModelUuid(selectedEventSphere.userData.modelUuid);
|
||||
if (eventData) {
|
||||
setSelectedEventData(
|
||||
eventData,
|
||||
selectedEventSphere.userData.pointUuid
|
||||
);
|
||||
} else {
|
||||
clearSelectedEventData();
|
||||
const [armBotStatusSample, setArmBotStatusSample] = useState<
|
||||
RoboticArmEvent[]
|
||||
>([
|
||||
{
|
||||
modelUuid: "b3556818-9e46-48b0-a869-a75c92857125",
|
||||
modelName: "robotic_arm",
|
||||
position: [0, 0, 0],
|
||||
rotation: [0, 0, 0],
|
||||
state: "idle",
|
||||
type: "roboticArm",
|
||||
speed: 1.5,
|
||||
point: {
|
||||
uuid: "point-123",
|
||||
position: [0, 1.5, 0],
|
||||
rotation: [0, 0, 0],
|
||||
actions: [
|
||||
{
|
||||
actionUuid: "action-001",
|
||||
actionName: "Pick Component",
|
||||
actionType: "pickAndPlace",
|
||||
process: {
|
||||
startPoint: null,
|
||||
endPoint: null,
|
||||
},
|
||||
triggers: [],
|
||||
},
|
||||
{
|
||||
actionUuid: "action-002",
|
||||
actionName: "Pick Component",
|
||||
actionType: "pickAndPlace",
|
||||
process: {
|
||||
startPoint: null,
|
||||
endPoint: null,
|
||||
},
|
||||
triggers: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
modelUuid: "16a394c7-0808-4bdf-a5d3-e5ca141ffb9f",
|
||||
modelName: "arm without rig (1)",
|
||||
position: [0, 0, 0],
|
||||
rotation: [0, 0, 0],
|
||||
state: "idle",
|
||||
type: "roboticArm",
|
||||
speed: 1.5,
|
||||
point: {
|
||||
uuid: "point-123",
|
||||
position: [0, 1.5, 0],
|
||||
rotation: [0, 0, 0],
|
||||
actions: [
|
||||
{
|
||||
actionUuid: "action-001",
|
||||
actionName: "Pick Component",
|
||||
actionType: "pickAndPlace",
|
||||
process: {
|
||||
startPoint: null,
|
||||
endPoint: null,
|
||||
},
|
||||
triggers: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const armUiPick = useGLTF(armPick) as any;
|
||||
const armUiDrop = useGLTF(armDrop) as any;
|
||||
|
||||
const updatePointToState = (obj: THREE.Object3D) => {
|
||||
const { modelUuid, pointUuid, actionType, actionUuid } = obj.userData;
|
||||
const newPosition = obj.position.toArray();
|
||||
|
||||
setArmBotStatusSample((prev) =>
|
||||
prev.map((event) => {
|
||||
if (event.modelUuid === modelUuid) {
|
||||
const updatedActions = event.point.actions.map((action) => {
|
||||
if (action.actionUuid === actionUuid) {
|
||||
const updatedProcess = { ...action.process };
|
||||
if (actionType === "pick") {
|
||||
updatedProcess.startPoint = newPosition;
|
||||
} else if (actionType === "drop") {
|
||||
updatedProcess.endPoint = newPosition;
|
||||
}
|
||||
return {
|
||||
...action,
|
||||
process: updatedProcess,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
clearSelectedEventData();
|
||||
return action;
|
||||
});
|
||||
|
||||
return {
|
||||
...event,
|
||||
point: {
|
||||
...event.point,
|
||||
actions: updatedActions,
|
||||
},
|
||||
};
|
||||
}
|
||||
}, [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)
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
setSelectedEventSphere(sphereRefs.current[point.uuid]);
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
clearSelectedEventSphere();
|
||||
setTransformMode(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();
|
||||
setSelectedEventSphere(sphereRefs.current[event.point.uuid]);
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
clearSelectedEventSphere();
|
||||
setTransformMode(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();
|
||||
setSelectedEventSphere(sphereRefs.current[event.point.uuid]);
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
clearSelectedEventSphere();
|
||||
setTransformMode(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();
|
||||
setSelectedEventSphere(sphereRefs.current[event.point.uuid]);
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
clearSelectedEventSphere();
|
||||
setTransformMode(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>
|
||||
{(selectedEventSphere && transformMode) &&
|
||||
<TransformControls ref={transformRef} object={selectedEventSphere} mode={transformMode} onMouseUp={(e) => { updatePointToState(selectedEventSphere) }} />
|
||||
}
|
||||
</>
|
||||
}
|
||||
</>
|
||||
return event;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const { handlePointerDown } = useDraggableGLTF(updatePointToState);
|
||||
|
||||
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();
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedEventSphere) {
|
||||
const eventData = getEventByModelUuid(
|
||||
selectedEventSphere.userData.modelUuid
|
||||
);
|
||||
if (eventData) {
|
||||
setSelectedEventData(eventData, selectedEventSphere.userData.pointUuid);
|
||||
} else {
|
||||
clearSelectedEventData();
|
||||
}
|
||||
} else {
|
||||
clearSelectedEventData();
|
||||
}
|
||||
}, [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 [selectedPoint, setSelectedPoint] = useState<THREE.Mesh | null>(null);
|
||||
|
||||
const getDefaultPositions = (modelUuid: string) => {
|
||||
const modelData = getModelByUuid(modelUuid);
|
||||
if (modelData) {
|
||||
const baseX = modelData.position?.[0] || 0;
|
||||
const baseY = modelData.position?.[1] + 2.8 || 1.5;
|
||||
const baseZ = modelData.position?.[2] || 0;
|
||||
return {
|
||||
pick: [baseX, baseY, baseZ - 2.5],
|
||||
drop: [baseX, baseY, baseZ - 0.5],
|
||||
default: [baseX, baseY, baseZ - 1.5],
|
||||
};
|
||||
}
|
||||
return {
|
||||
pick: [0.5, 1.5, 0],
|
||||
drop: [-0.5, 1.5, 0],
|
||||
default: [0, 1.5, 0],
|
||||
};
|
||||
};
|
||||
|
||||
const getModelByUuid = (modelUuid: string) => {
|
||||
try {
|
||||
const modelsJson = localStorage.getItem("FloorItems");
|
||||
if (modelsJson) {
|
||||
const models = JSON.parse(modelsJson);
|
||||
return models.find((m: any) => m.modeluuid === modelUuid);
|
||||
}
|
||||
const storeModels = (useModuleStore.getState() as any).models || [];
|
||||
return storeModels.find((m: any) => m.modelUuid === modelUuid);
|
||||
} catch (error) {}
|
||||
return null;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log("armBotStatusSample: ", armBotStatusSample);
|
||||
}, [armBotStatusSample]);
|
||||
return (
|
||||
<>
|
||||
{activeModule === "simulation" && (
|
||||
<>
|
||||
<group name="EventPointsGroup">
|
||||
{armBotStatusSample.map((event, i) => {
|
||||
if (event.type === "roboticArm") {
|
||||
const defaultPositions = getDefaultPositions(event.modelUuid);
|
||||
const isSelected =
|
||||
selectedPoint?.userData?.modelUuid === event.modelUuid;
|
||||
|
||||
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();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
setSelectedPoint(e.object as THREE.Mesh);
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
clearSelectedEventSphere();
|
||||
setTransformMode(null);
|
||||
}}
|
||||
position={new THREE.Vector3(...defaultPositions.default)}
|
||||
userData={{
|
||||
modelUuid: event.modelUuid,
|
||||
pointUuid: event.point.uuid,
|
||||
}}
|
||||
>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial
|
||||
color={isSelected ? "yellow" : "green"}
|
||||
/>
|
||||
</mesh>
|
||||
{event.point.actions.map((action) => {
|
||||
if (action.actionType === "pickAndPlace") {
|
||||
const pickPosition =
|
||||
action.process.startPoint || defaultPositions.pick;
|
||||
const dropPosition =
|
||||
action.process.endPoint || defaultPositions.drop;
|
||||
|
||||
return (
|
||||
<React.Fragment key={action.actionUuid}>
|
||||
{/* Pick Point */}
|
||||
<PickDropPoints
|
||||
position={pickPosition}
|
||||
modelUuid={event.modelUuid}
|
||||
pointUuid={event.point.uuid}
|
||||
actionType="pick"
|
||||
actionUuid={action.actionUuid}
|
||||
gltfScene={armUiPick.scene}
|
||||
selectedPoint={selectedPoint}
|
||||
handlePointerDown={handlePointerDown}
|
||||
isSelected={isSelected}
|
||||
/>
|
||||
|
||||
{/* Drop Point */}
|
||||
<PickDropPoints
|
||||
position={dropPosition}
|
||||
modelUuid={event.modelUuid}
|
||||
pointUuid={event.point.uuid}
|
||||
actionType="drop"
|
||||
actionUuid={action.actionUuid}
|
||||
gltfScene={armUiDrop.scene}
|
||||
selectedPoint={selectedPoint}
|
||||
handlePointerDown={handlePointerDown}
|
||||
isSelected={isSelected}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</group>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</group>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default PointsCreator;
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user