added ui for changing position of vehicles pickup-point and unloadPoint
This commit is contained in:
@@ -18,20 +18,20 @@ import Window from "../../assets/gltf-glb/window.glb";
|
||||
////////// Zustand State Imports //////////
|
||||
|
||||
import {
|
||||
useToggleView,
|
||||
useDeletePointOrLine,
|
||||
useMovePoint,
|
||||
useActiveLayer,
|
||||
useSocketStore,
|
||||
useWallVisibility,
|
||||
useRoofVisibility,
|
||||
useShadows,
|
||||
useUpdateScene,
|
||||
useWalls,
|
||||
useToolMode,
|
||||
useRefTextUpdate,
|
||||
useRenderDistance,
|
||||
useLimitDistance,
|
||||
useToggleView,
|
||||
useDeletePointOrLine,
|
||||
useMovePoint,
|
||||
useActiveLayer,
|
||||
useSocketStore,
|
||||
useWallVisibility,
|
||||
useRoofVisibility,
|
||||
useShadows,
|
||||
useUpdateScene,
|
||||
useWalls,
|
||||
useToolMode,
|
||||
useRefTextUpdate,
|
||||
useRenderDistance,
|
||||
useLimitDistance,
|
||||
} from "../../store/store";
|
||||
|
||||
////////// 3D Function Imports //////////
|
||||
@@ -56,300 +56,301 @@ import ZoneGroup from "./groups/zoneGroup";
|
||||
import useModuleStore from "../../store/useModuleStore";
|
||||
import MeasurementTool from "../scene/tools/measurementTool";
|
||||
import NavMesh from "../simulation/vehicle/navMesh/navMesh";
|
||||
import ProductionCapacity from "../../components/ui/analysis/ProductionCapacity";
|
||||
|
||||
export default function Builder() {
|
||||
const state = useThree<Types.ThreeState>(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
|
||||
const csg = useRef(); // Reference for CSG object, used for 3D modeling.
|
||||
const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects.
|
||||
const scene = useRef() as Types.RefScene; // Reference to the scene.
|
||||
const camera = useRef() as Types.RefCamera; // Reference to the camera object.
|
||||
const controls = useRef<any>(); // Reference to the controls object.
|
||||
const raycaster = useRef() as Types.RefRaycaster; // Reference for raycaster used for detecting objects being pointed at in the scene.
|
||||
const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control.
|
||||
const state = useThree<Types.ThreeState>(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
|
||||
const csg = useRef(); // Reference for CSG object, used for 3D modeling.
|
||||
const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects.
|
||||
const scene = useRef() as Types.RefScene; // Reference to the scene.
|
||||
const camera = useRef() as Types.RefCamera; // Reference to the camera object.
|
||||
const controls = useRef<any>(); // Reference to the controls object.
|
||||
const raycaster = useRef() as Types.RefRaycaster; // Reference for raycaster used for detecting objects being pointed at in the scene.
|
||||
const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control.
|
||||
|
||||
// Assigning the scene and camera from the Three.js state to the references.
|
||||
// Assigning the scene and camera from the Three.js state to the references.
|
||||
|
||||
scene.current = state.scene;
|
||||
camera.current = state.camera;
|
||||
controls.current = state.controls;
|
||||
raycaster.current = state.raycaster;
|
||||
scene.current = state.scene;
|
||||
camera.current = state.camera;
|
||||
controls.current = state.controls;
|
||||
raycaster.current = state.raycaster;
|
||||
|
||||
const plane = useRef<THREE.Mesh>(null); // Reference for a plane object for raycaster reference.
|
||||
const grid = useRef() as any; // Reference for a grid object for raycaster reference.
|
||||
const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line.
|
||||
const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end).
|
||||
const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc...
|
||||
const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active.
|
||||
const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point.
|
||||
const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start).
|
||||
const tempLoader = useRef() as Types.RefMesh; // Reference for a temporary loader for the floor items.
|
||||
const isTempLoader = useRef() as Types.RefBoolean; // Reference to check if a temporary loader is active.
|
||||
const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation.
|
||||
const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn.
|
||||
const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn.
|
||||
const onlyFloorline = useRef<Types.OnlyFloorLine>([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn.
|
||||
const onlyFloorlines = useRef<Types.OnlyFloorLines>([]); // Reference for all the floor lines that are ever drawn.
|
||||
const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw.
|
||||
const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not.
|
||||
const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed.
|
||||
const itemsGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the floor items (Gltf).
|
||||
const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors.
|
||||
const AttachedObject = useRef() as Types.RefMesh; // Reference for an object that is attached using dbl click for transform controls rotation.
|
||||
const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group.
|
||||
const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn.
|
||||
const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created.
|
||||
const floorGroupAisle = useRef() as Types.RefGroup;
|
||||
const zoneGroup = useRef() as Types.RefGroup;
|
||||
const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls.
|
||||
const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted.
|
||||
const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted.
|
||||
const hoveredDeletableFloorItem = useRef() as Types.RefMesh; // Reference for the currently hovered floor item that can be deleted.
|
||||
const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted.
|
||||
const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted.
|
||||
const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc...
|
||||
const plane = useRef<THREE.Mesh>(null); // Reference for a plane object for raycaster reference.
|
||||
const grid = useRef() as any; // Reference for a grid object for raycaster reference.
|
||||
const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line.
|
||||
const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end).
|
||||
const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc...
|
||||
const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active.
|
||||
const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point.
|
||||
const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start).
|
||||
const tempLoader = useRef() as Types.RefMesh; // Reference for a temporary loader for the floor items.
|
||||
const isTempLoader = useRef() as Types.RefBoolean; // Reference to check if a temporary loader is active.
|
||||
const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation.
|
||||
const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn.
|
||||
const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn.
|
||||
const onlyFloorline = useRef<Types.OnlyFloorLine>([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn.
|
||||
const onlyFloorlines = useRef<Types.OnlyFloorLines>([]); // Reference for all the floor lines that are ever drawn.
|
||||
const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw.
|
||||
const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not.
|
||||
const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed.
|
||||
const itemsGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the floor items (Gltf).
|
||||
const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors.
|
||||
const AttachedObject = useRef() as Types.RefMesh; // Reference for an object that is attached using dbl click for transform controls rotation.
|
||||
const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group.
|
||||
const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn.
|
||||
const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created.
|
||||
const floorGroupAisle = useRef() as Types.RefGroup;
|
||||
const zoneGroup = useRef() as Types.RefGroup;
|
||||
const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls.
|
||||
const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted.
|
||||
const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted.
|
||||
const hoveredDeletableFloorItem = useRef() as Types.RefMesh; // Reference for the currently hovered floor item that can be deleted.
|
||||
const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted.
|
||||
const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted.
|
||||
const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc...
|
||||
|
||||
const cursorPosition = new THREE.Vector3(); // 3D vector for storing the cursor position.
|
||||
const cursorPosition = new THREE.Vector3(); // 3D vector for storing the cursor position.
|
||||
|
||||
const [selectedItemsIndex, setSelectedItemsIndex] = useState<Types.Number | null>(null); // State for tracking the index of the selected item.
|
||||
const { activeLayer, setActiveLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx.
|
||||
const { toggleView, setToggleView } = useToggleView(); // State for toggling between 2D and 3D.
|
||||
const { toolMode, setToolMode } = useToolMode();
|
||||
const { movePoint, setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not.
|
||||
const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
|
||||
const { socket } = useSocketStore();
|
||||
const { roofVisibility, setRoofVisibility } = useRoofVisibility();
|
||||
const { wallVisibility, setWallVisibility } = useWallVisibility();
|
||||
const { shadows, setShadows } = useShadows();
|
||||
const { renderDistance, setRenderDistance } = useRenderDistance();
|
||||
const { limitDistance, setLimitDistance } = useLimitDistance();
|
||||
const { updateScene, setUpdateScene } = useUpdateScene();
|
||||
const { walls, setWalls } = useWalls();
|
||||
const { refTextupdate, setRefTextUpdate } = useRefTextUpdate();
|
||||
const { activeModule } = useModuleStore();
|
||||
const [selectedItemsIndex, setSelectedItemsIndex] =
|
||||
useState<Types.Number | null>(null); // State for tracking the index of the selected item.
|
||||
const { activeLayer, setActiveLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx.
|
||||
const { toggleView, setToggleView } = useToggleView(); // State for toggling between 2D and 3D.
|
||||
const { toolMode, setToolMode } = useToolMode();
|
||||
const { movePoint, setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not.
|
||||
const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
|
||||
const { socket } = useSocketStore();
|
||||
const { roofVisibility, setRoofVisibility } = useRoofVisibility();
|
||||
const { wallVisibility, setWallVisibility } = useWallVisibility();
|
||||
const { shadows, setShadows } = useShadows();
|
||||
const { renderDistance, setRenderDistance } = useRenderDistance();
|
||||
const { limitDistance, setLimitDistance } = useLimitDistance();
|
||||
const { updateScene, setUpdateScene } = useUpdateScene();
|
||||
const { walls, setWalls } = useWalls();
|
||||
const { refTextupdate, setRefTextUpdate } = useRefTextUpdate();
|
||||
const { activeModule } = useModuleStore();
|
||||
|
||||
// const loader = new GLTFLoader();
|
||||
// const dracoLoader = new DRACOLoader();
|
||||
// const loader = new GLTFLoader();
|
||||
// const dracoLoader = new DRACOLoader();
|
||||
|
||||
// dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
|
||||
// loader.setDRACOLoader(dracoLoader);
|
||||
// dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
|
||||
// loader.setDRACOLoader(dracoLoader);
|
||||
|
||||
////////// Assest Configuration Values //////////
|
||||
////////// Assest Configuration Values //////////
|
||||
|
||||
const AssetConfigurations: Types.AssetConfigurations = {
|
||||
arch: {
|
||||
modelUrl: arch,
|
||||
scale: [0.75, 0.75, 0.75],
|
||||
csgscale: [2, 4, 0.5],
|
||||
csgposition: [0, 2, 0],
|
||||
positionY: () => 0,
|
||||
type: "Fixed-Move",
|
||||
},
|
||||
door: {
|
||||
modelUrl: door,
|
||||
scale: [0.75, 0.75, 0.75],
|
||||
csgscale: [2, 4, 0.5],
|
||||
csgposition: [0, 2, 0],
|
||||
positionY: () => 0,
|
||||
type: "Fixed-Move",
|
||||
},
|
||||
window: {
|
||||
modelUrl: Window,
|
||||
scale: [0.75, 0.75, 0.75],
|
||||
csgscale: [5, 3, 0.5],
|
||||
csgposition: [0, 1.5, 0],
|
||||
positionY: (intersectionPoint) => intersectionPoint.point.y,
|
||||
type: "Free-Move",
|
||||
},
|
||||
};
|
||||
const AssetConfigurations: Types.AssetConfigurations = {
|
||||
arch: {
|
||||
modelUrl: arch,
|
||||
scale: [0.75, 0.75, 0.75],
|
||||
csgscale: [2, 4, 0.5],
|
||||
csgposition: [0, 2, 0],
|
||||
positionY: () => 0,
|
||||
type: "Fixed-Move",
|
||||
},
|
||||
door: {
|
||||
modelUrl: door,
|
||||
scale: [0.75, 0.75, 0.75],
|
||||
csgscale: [2, 4, 0.5],
|
||||
csgposition: [0, 2, 0],
|
||||
positionY: () => 0,
|
||||
type: "Fixed-Move",
|
||||
},
|
||||
window: {
|
||||
modelUrl: Window,
|
||||
scale: [0.75, 0.75, 0.75],
|
||||
csgscale: [5, 3, 0.5],
|
||||
csgposition: [0, 1.5, 0],
|
||||
positionY: (intersectionPoint) => intersectionPoint.point.y,
|
||||
type: "Free-Move",
|
||||
},
|
||||
};
|
||||
|
||||
////////// All Toggle's //////////
|
||||
////////// All Toggle's //////////
|
||||
|
||||
useEffect(() => {
|
||||
setRefTextUpdate((prevUpdate: number) => prevUpdate - 1);
|
||||
if (dragPointControls.current) {
|
||||
dragPointControls.current.enabled = false;
|
||||
}
|
||||
if (toggleView) {
|
||||
Layer2DVisibility(
|
||||
activeLayer,
|
||||
floorPlanGroup,
|
||||
floorPlanGroupLine,
|
||||
floorPlanGroupPoint,
|
||||
currentLayerPoint,
|
||||
dragPointControls
|
||||
);
|
||||
} else {
|
||||
setToolMode(null);
|
||||
setDeletePointOrLine(false);
|
||||
setMovePoint(false);
|
||||
loadWalls(lines, setWalls);
|
||||
setUpdateScene(true);
|
||||
line.current = [];
|
||||
}
|
||||
}, [toggleView]);
|
||||
useEffect(() => {
|
||||
setRefTextUpdate((prevUpdate: number) => prevUpdate - 1);
|
||||
if (dragPointControls.current) {
|
||||
dragPointControls.current.enabled = false;
|
||||
}
|
||||
if (toggleView) {
|
||||
Layer2DVisibility(
|
||||
activeLayer,
|
||||
floorPlanGroup,
|
||||
floorPlanGroupLine,
|
||||
floorPlanGroupPoint,
|
||||
currentLayerPoint,
|
||||
dragPointControls
|
||||
);
|
||||
} else {
|
||||
setToolMode(null);
|
||||
setDeletePointOrLine(false);
|
||||
setMovePoint(false);
|
||||
loadWalls(lines, setWalls);
|
||||
setUpdateScene(true);
|
||||
line.current = [];
|
||||
}
|
||||
}, [toggleView]);
|
||||
|
||||
useEffect(() => {
|
||||
THREE.Cache.clear();
|
||||
THREE.Cache.enabled = true;
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
THREE.Cache.clear();
|
||||
THREE.Cache.enabled = true;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email!.split("@")[1].split(".")[0];
|
||||
useEffect(() => {
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email!.split("@")[1].split(".")[0];
|
||||
|
||||
async function fetchVisibility() {
|
||||
const visibility = await findEnvironment(
|
||||
organization,
|
||||
localStorage.getItem("userId")!
|
||||
);
|
||||
if (visibility) {
|
||||
setRoofVisibility(visibility.roofVisibility);
|
||||
setWallVisibility(visibility.wallVisibility);
|
||||
setShadows(visibility.shadowVisibility);
|
||||
setRenderDistance(visibility.renderDistance);
|
||||
setLimitDistance(visibility.limitDistance);
|
||||
}
|
||||
}
|
||||
fetchVisibility();
|
||||
}, []);
|
||||
async function fetchVisibility() {
|
||||
const visibility = await findEnvironment(
|
||||
organization,
|
||||
localStorage.getItem("userId")!
|
||||
);
|
||||
if (visibility) {
|
||||
setRoofVisibility(visibility.roofVisibility);
|
||||
setWallVisibility(visibility.wallVisibility);
|
||||
setShadows(visibility.shadowVisibility);
|
||||
setRenderDistance(visibility.renderDistance);
|
||||
setLimitDistance(visibility.limitDistance);
|
||||
}
|
||||
}
|
||||
fetchVisibility();
|
||||
}, []);
|
||||
|
||||
////////// UseFrame is Here //////////
|
||||
////////// UseFrame is Here //////////
|
||||
|
||||
useFrame(() => {
|
||||
if (toolMode) {
|
||||
Draw(
|
||||
state,
|
||||
plane,
|
||||
cursorPosition,
|
||||
floorPlanGroupPoint,
|
||||
floorPlanGroupLine,
|
||||
snappedPoint,
|
||||
isSnapped,
|
||||
isSnappedUUID,
|
||||
line,
|
||||
lines,
|
||||
ispreSnapped,
|
||||
floorPlanGroup,
|
||||
ReferenceLineMesh,
|
||||
LineCreated,
|
||||
setRefTextUpdate,
|
||||
Tube,
|
||||
anglesnappedPoint,
|
||||
isAngleSnapped,
|
||||
toolMode
|
||||
);
|
||||
}
|
||||
});
|
||||
useFrame(() => {
|
||||
if (toolMode) {
|
||||
Draw(
|
||||
state,
|
||||
plane,
|
||||
cursorPosition,
|
||||
floorPlanGroupPoint,
|
||||
floorPlanGroupLine,
|
||||
snappedPoint,
|
||||
isSnapped,
|
||||
isSnappedUUID,
|
||||
line,
|
||||
lines,
|
||||
ispreSnapped,
|
||||
floorPlanGroup,
|
||||
ReferenceLineMesh,
|
||||
LineCreated,
|
||||
setRefTextUpdate,
|
||||
Tube,
|
||||
anglesnappedPoint,
|
||||
isAngleSnapped,
|
||||
toolMode
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
////////// Return //////////
|
||||
////////// Return //////////
|
||||
|
||||
return (
|
||||
<>
|
||||
<Ground grid={grid} plane={plane} />
|
||||
return (
|
||||
<>
|
||||
<Ground grid={grid} plane={plane} />
|
||||
|
||||
<DistanceText key={toggleView} />
|
||||
<DistanceText key={toggleView} />
|
||||
|
||||
<ReferenceDistanceText
|
||||
key={refTextupdate}
|
||||
line={ReferenceLineMesh.current}
|
||||
/>
|
||||
<ReferenceDistanceText
|
||||
key={refTextupdate}
|
||||
line={ReferenceLineMesh.current}
|
||||
/>
|
||||
|
||||
<SocketResponses
|
||||
floorPlanGroup={floorPlanGroup}
|
||||
lines={lines}
|
||||
floorGroup={floorGroup}
|
||||
floorGroupAisle={floorGroupAisle}
|
||||
scene={scene}
|
||||
onlyFloorlines={onlyFloorlines}
|
||||
AssetConfigurations={AssetConfigurations}
|
||||
itemsGroup={itemsGroup}
|
||||
isTempLoader={isTempLoader}
|
||||
tempLoader={tempLoader}
|
||||
currentLayerPoint={currentLayerPoint}
|
||||
floorPlanGroupPoint={floorPlanGroupPoint}
|
||||
floorPlanGroupLine={floorPlanGroupLine}
|
||||
zoneGroup={zoneGroup}
|
||||
dragPointControls={dragPointControls}
|
||||
/>
|
||||
<SocketResponses
|
||||
floorPlanGroup={floorPlanGroup}
|
||||
lines={lines}
|
||||
floorGroup={floorGroup}
|
||||
floorGroupAisle={floorGroupAisle}
|
||||
scene={scene}
|
||||
onlyFloorlines={onlyFloorlines}
|
||||
AssetConfigurations={AssetConfigurations}
|
||||
itemsGroup={itemsGroup}
|
||||
isTempLoader={isTempLoader}
|
||||
tempLoader={tempLoader}
|
||||
currentLayerPoint={currentLayerPoint}
|
||||
floorPlanGroupPoint={floorPlanGroupPoint}
|
||||
floorPlanGroupLine={floorPlanGroupLine}
|
||||
zoneGroup={zoneGroup}
|
||||
dragPointControls={dragPointControls}
|
||||
/>
|
||||
|
||||
<WallsAndWallItems
|
||||
CSGGroup={CSGGroup}
|
||||
AssetConfigurations={AssetConfigurations}
|
||||
setSelectedItemsIndex={setSelectedItemsIndex}
|
||||
selectedItemsIndex={selectedItemsIndex}
|
||||
currentWallItem={currentWallItem}
|
||||
csg={csg}
|
||||
lines={lines}
|
||||
hoveredDeletableWallItem={hoveredDeletableWallItem}
|
||||
/>
|
||||
<WallsAndWallItems
|
||||
CSGGroup={CSGGroup}
|
||||
AssetConfigurations={AssetConfigurations}
|
||||
setSelectedItemsIndex={setSelectedItemsIndex}
|
||||
selectedItemsIndex={selectedItemsIndex}
|
||||
currentWallItem={currentWallItem}
|
||||
csg={csg}
|
||||
lines={lines}
|
||||
hoveredDeletableWallItem={hoveredDeletableWallItem}
|
||||
/>
|
||||
|
||||
<FloorItemsGroup
|
||||
itemsGroup={itemsGroup}
|
||||
hoveredDeletableFloorItem={hoveredDeletableFloorItem}
|
||||
AttachedObject={AttachedObject}
|
||||
floorGroup={floorGroup}
|
||||
tempLoader={tempLoader}
|
||||
isTempLoader={isTempLoader}
|
||||
plane={plane}
|
||||
/>
|
||||
<FloorItemsGroup
|
||||
itemsGroup={itemsGroup}
|
||||
hoveredDeletableFloorItem={hoveredDeletableFloorItem}
|
||||
AttachedObject={AttachedObject}
|
||||
floorGroup={floorGroup}
|
||||
tempLoader={tempLoader}
|
||||
isTempLoader={isTempLoader}
|
||||
plane={plane}
|
||||
/>
|
||||
|
||||
<FloorGroup
|
||||
floorGroup={floorGroup}
|
||||
lines={lines}
|
||||
referencePole={referencePole}
|
||||
hoveredDeletablePillar={hoveredDeletablePillar}
|
||||
/>
|
||||
<FloorGroup
|
||||
floorGroup={floorGroup}
|
||||
lines={lines}
|
||||
referencePole={referencePole}
|
||||
hoveredDeletablePillar={hoveredDeletablePillar}
|
||||
/>
|
||||
|
||||
<FloorPlanGroup
|
||||
floorPlanGroup={floorPlanGroup}
|
||||
floorPlanGroupLine={floorPlanGroupLine}
|
||||
floorPlanGroupPoint={floorPlanGroupPoint}
|
||||
floorGroup={floorGroup}
|
||||
currentLayerPoint={currentLayerPoint}
|
||||
dragPointControls={dragPointControls}
|
||||
hoveredDeletablePoint={hoveredDeletablePoint}
|
||||
hoveredDeletableLine={hoveredDeletableLine}
|
||||
plane={plane}
|
||||
line={line}
|
||||
lines={lines}
|
||||
onlyFloorline={onlyFloorline}
|
||||
onlyFloorlines={onlyFloorlines}
|
||||
ReferenceLineMesh={ReferenceLineMesh}
|
||||
LineCreated={LineCreated}
|
||||
isSnapped={isSnapped}
|
||||
ispreSnapped={ispreSnapped}
|
||||
snappedPoint={snappedPoint}
|
||||
isSnappedUUID={isSnappedUUID}
|
||||
isAngleSnapped={isAngleSnapped}
|
||||
anglesnappedPoint={anglesnappedPoint}
|
||||
/>
|
||||
<FloorPlanGroup
|
||||
floorPlanGroup={floorPlanGroup}
|
||||
floorPlanGroupLine={floorPlanGroupLine}
|
||||
floorPlanGroupPoint={floorPlanGroupPoint}
|
||||
floorGroup={floorGroup}
|
||||
currentLayerPoint={currentLayerPoint}
|
||||
dragPointControls={dragPointControls}
|
||||
hoveredDeletablePoint={hoveredDeletablePoint}
|
||||
hoveredDeletableLine={hoveredDeletableLine}
|
||||
plane={plane}
|
||||
line={line}
|
||||
lines={lines}
|
||||
onlyFloorline={onlyFloorline}
|
||||
onlyFloorlines={onlyFloorlines}
|
||||
ReferenceLineMesh={ReferenceLineMesh}
|
||||
LineCreated={LineCreated}
|
||||
isSnapped={isSnapped}
|
||||
ispreSnapped={ispreSnapped}
|
||||
snappedPoint={snappedPoint}
|
||||
isSnappedUUID={isSnappedUUID}
|
||||
isAngleSnapped={isAngleSnapped}
|
||||
anglesnappedPoint={anglesnappedPoint}
|
||||
/>
|
||||
|
||||
<ZoneGroup />
|
||||
<ZoneGroup />
|
||||
|
||||
<FloorGroupAilse
|
||||
floorGroupAisle={floorGroupAisle}
|
||||
plane={plane}
|
||||
floorPlanGroupLine={floorPlanGroupLine}
|
||||
floorPlanGroupPoint={floorPlanGroupPoint}
|
||||
line={line}
|
||||
lines={lines}
|
||||
currentLayerPoint={currentLayerPoint}
|
||||
dragPointControls={dragPointControls}
|
||||
floorPlanGroup={floorPlanGroup}
|
||||
ReferenceLineMesh={ReferenceLineMesh}
|
||||
LineCreated={LineCreated}
|
||||
isSnapped={isSnapped}
|
||||
ispreSnapped={ispreSnapped}
|
||||
snappedPoint={snappedPoint}
|
||||
isSnappedUUID={isSnappedUUID}
|
||||
isAngleSnapped={isAngleSnapped}
|
||||
anglesnappedPoint={anglesnappedPoint}
|
||||
/>
|
||||
<FloorGroupAilse
|
||||
floorGroupAisle={floorGroupAisle}
|
||||
plane={plane}
|
||||
floorPlanGroupLine={floorPlanGroupLine}
|
||||
floorPlanGroupPoint={floorPlanGroupPoint}
|
||||
line={line}
|
||||
lines={lines}
|
||||
currentLayerPoint={currentLayerPoint}
|
||||
dragPointControls={dragPointControls}
|
||||
floorPlanGroup={floorPlanGroup}
|
||||
ReferenceLineMesh={ReferenceLineMesh}
|
||||
LineCreated={LineCreated}
|
||||
isSnapped={isSnapped}
|
||||
ispreSnapped={ispreSnapped}
|
||||
snappedPoint={snappedPoint}
|
||||
isSnappedUUID={isSnappedUUID}
|
||||
isAngleSnapped={isAngleSnapped}
|
||||
anglesnappedPoint={anglesnappedPoint}
|
||||
/>
|
||||
|
||||
<MeasurementTool />
|
||||
<MeasurementTool />
|
||||
|
||||
<NavMesh lines={lines} />
|
||||
|
||||
</>
|
||||
);
|
||||
<NavMesh lines={lines} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,24 +20,24 @@ export default function Scene() {
|
||||
);
|
||||
|
||||
return (
|
||||
<KeyboardControls map={map}>
|
||||
<Canvas
|
||||
eventPrefix="client"
|
||||
gl={{ powerPreference: "high-performance", antialias: true }}
|
||||
onContextMenu={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<Setup />
|
||||
<KeyboardControls map={map}>
|
||||
<Canvas
|
||||
eventPrefix="client"
|
||||
gl={{ powerPreference: "high-performance", antialias: true }}
|
||||
onContextMenu={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<Setup />
|
||||
|
||||
<Collaboration />
|
||||
<Collaboration />
|
||||
|
||||
<Builder />
|
||||
<Builder />
|
||||
|
||||
<Simulation />
|
||||
<Simulation />
|
||||
|
||||
<Visualization />
|
||||
</Canvas>
|
||||
</KeyboardControls>
|
||||
<Visualization />
|
||||
</Canvas>
|
||||
</KeyboardControls>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,233 +5,227 @@ import useModuleStore from "../../../../../store/useModuleStore";
|
||||
import { TransformControls } from "@react-three/drei";
|
||||
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
|
||||
import {
|
||||
useSelectedEventSphere,
|
||||
useSelectedEventData,
|
||||
useSelectedEventSphere,
|
||||
useSelectedEventData,
|
||||
} from "../../../../../store/simulation/useSimulationStore";
|
||||
|
||||
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();
|
||||
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 { selectedEventData, 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(() => {
|
||||
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"));
|
||||
}
|
||||
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
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
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" && (
|
||||
return (
|
||||
<>
|
||||
<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
|
||||
name="Event-Sphere"
|
||||
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
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
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
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
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
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{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
|
||||
name="Event-Sphere"
|
||||
uuid={point.uuid}
|
||||
ref={(el) => (sphereRefs.current[point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[point.uuid]
|
||||
);
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
if (selectedEventData?.data.type !== 'vehicle') {
|
||||
// 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
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
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
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
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
|
||||
name="Event-Sphere"
|
||||
uuid={event.point.uuid}
|
||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setSelectedEventSphere(
|
||||
sphereRefs.current[event.point.uuid]
|
||||
);
|
||||
}}
|
||||
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);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
export default PointsCreator;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
interface HandleAddEventToProductParams {
|
||||
selectedAsset: any; // Replace `any` with specific type if you have it
|
||||
addEvent: (productId: string, asset: any) => void;
|
||||
selectedProduct: {
|
||||
productId: string;
|
||||
productName: string;
|
||||
// Add other fields if needed
|
||||
};
|
||||
clearSelectedAsset: () => void;
|
||||
}
|
||||
|
||||
export const handleAddEventToProduct = ({
|
||||
selectedAsset,
|
||||
addEvent,
|
||||
selectedProduct,
|
||||
clearSelectedAsset,
|
||||
}: HandleAddEventToProductParams) => {
|
||||
console.log('selectedProduct: ', selectedProduct);
|
||||
if (selectedAsset) {
|
||||
addEvent(selectedProduct.productId, selectedAsset);
|
||||
// upsertProductOrEventApi({
|
||||
// productName: selectedProduct.productName,
|
||||
// productId: selectedProduct.productId,
|
||||
// eventDatas: selectedAsset
|
||||
// });
|
||||
clearSelectedAsset();
|
||||
}
|
||||
};
|
||||
@@ -8,7 +8,7 @@ function RoboticArmAnimator({ armUuid, HandleCallback, currentPhase, ikSolver, t
|
||||
const { armBots } = useArmBotStore();
|
||||
const { scene } = useThree();
|
||||
const restSpeed = 0.1;
|
||||
const restPosition = new THREE.Vector3(0, 2, 1.6);
|
||||
const restPosition = new THREE.Vector3(0, 1, -1.6);
|
||||
const initialCurveRef = useRef<THREE.CatmullRomCurve3 | null>(null);
|
||||
const initialStartPositionRef = useRef<THREE.Vector3 | null>(null);
|
||||
const [initialProgress, setInitialProgress] = useState(0);
|
||||
@@ -22,11 +22,12 @@ function RoboticArmAnimator({ armUuid, HandleCallback, currentPhase, ikSolver, t
|
||||
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
setCurrentPath(path)
|
||||
}, [path])
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
|
||||
}, [currentPath])
|
||||
|
||||
useFrame((_, delta) => {
|
||||
@@ -42,13 +43,13 @@ function RoboticArmAnimator({ armUuid, HandleCallback, currentPhase, ikSolver, t
|
||||
currentPath.map(point => new THREE.Vector3(point[0], point[1], point[2]))
|
||||
);
|
||||
|
||||
|
||||
const next = initialProgressRef.current + delta * 0.5;
|
||||
if (next >= 1) {
|
||||
bone.position.copy(restPosition);
|
||||
// bone.position.copy(restPosition);
|
||||
HandleCallback(); // Call the callback when the path is completed
|
||||
initialProgressRef.current = 0; // Set ref to 1 when done
|
||||
} else {
|
||||
|
||||
const point = curve.getPoint(next); // Get the interpolated point from the curve
|
||||
bone.position.copy(point); // Update the bone position along the curve
|
||||
initialProgressRef.current = next; // Update progress
|
||||
|
||||
@@ -16,6 +16,7 @@ interface Process {
|
||||
endPoint?: Vector3;
|
||||
speed: number;
|
||||
}
|
||||
|
||||
function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) {
|
||||
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
@@ -29,7 +30,7 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) {
|
||||
const groupRef = useRef<any>(null);
|
||||
const [processes, setProcesses] = useState<Process[]>([]);
|
||||
const [armBotCurvePoints, setArmBotCurvePoints] = useState({ start: [], end: [] })
|
||||
const restPosition = new THREE.Vector3(0, 2, 1.6);
|
||||
const restPosition = new THREE.Vector3(0, 1, -1.6);
|
||||
let armBotCurveRef = useRef<THREE.CatmullRomCurve3 | null>(null)
|
||||
const [path, setPath] = useState<[number, number, number][]>([]);
|
||||
|
||||
@@ -52,7 +53,7 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) {
|
||||
if (isPlaying) {
|
||||
//Moving armBot from initial point to rest position.
|
||||
if (!robot?.isActive && robot?.state == "idle" && currentPhase == "init") {
|
||||
|
||||
|
||||
setArmBotActive(robot.modelUuid, true)
|
||||
setArmBotState(robot.modelUuid, "running")
|
||||
setCurrentPhase("init-to-rest");
|
||||
@@ -62,11 +63,11 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) {
|
||||
setPath(curve.points.map(point => [point.x, point.y, point.z]));
|
||||
}
|
||||
}
|
||||
logStatus(robot.modelUuid, "Starting from init to rest")
|
||||
logStatus(robot.modelUuid, "Moving armBot from initial point to rest position.")
|
||||
}
|
||||
//Waiting for trigger.
|
||||
else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "rest" && !robot.currentAction) {
|
||||
|
||||
logStatus(robot.modelUuid, "Waiting to trigger CurrentAction")
|
||||
setTimeout(() => {
|
||||
addCurrentAction(robot.modelUuid, 'action-003');
|
||||
}, 3000);
|
||||
@@ -84,7 +85,7 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) {
|
||||
}
|
||||
}
|
||||
}
|
||||
logStatus(robot.modelUuid, "Starting from rest to start")
|
||||
logStatus(robot.modelUuid, "Moving armBot from rest point to start position.")
|
||||
}
|
||||
else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "picking" && robot.currentAction) {
|
||||
setArmBotActive(robot.modelUuid, true);
|
||||
@@ -98,10 +99,13 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) {
|
||||
new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2])
|
||||
);
|
||||
if (curve) {
|
||||
setPath(curve.points.map(point => [point.x, point.y, point.z]));
|
||||
setTimeout(() => {
|
||||
logStatus(robot.modelUuid, "picking the object");
|
||||
setPath(curve.points.map(point => [point.x, point.y, point.z]));
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
logStatus(robot.modelUuid, "Starting from start to end")
|
||||
logStatus(robot.modelUuid, "Moving armBot from start point to end position.")
|
||||
}
|
||||
else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "dropping" && robot.currentAction) {
|
||||
setArmBotActive(robot.modelUuid, true);
|
||||
@@ -112,10 +116,13 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) {
|
||||
let curve = createCurveBetweenTwoPoints(new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]), restPosition
|
||||
);
|
||||
if (curve) {
|
||||
setPath(curve.points.map(point => [point.x, point.y, point.z]));
|
||||
setTimeout(() => {
|
||||
logStatus(robot.modelUuid, "dropping the object");
|
||||
setPath(curve.points.map(point => [point.x, point.y, point.z]));
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
logStatus(robot.modelUuid, "Starting from end to rest")
|
||||
logStatus(robot.modelUuid, "Moving armBot from end point to rest position.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,28 +140,28 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) {
|
||||
|
||||
const HandleCallback = () => {
|
||||
if (robot.isActive && robot.state == "running" && currentPhase == "init-to-rest") {
|
||||
|
||||
logStatus(robot.modelUuid, "Callback triggered: rest");
|
||||
setArmBotActive(robot.modelUuid, false)
|
||||
setArmBotState(robot.modelUuid, "idle")
|
||||
setCurrentPhase("rest");
|
||||
setPath([])
|
||||
}
|
||||
else if (robot.isActive && robot.state == "running" && currentPhase == "rest-to-start") {
|
||||
|
||||
logStatus(robot.modelUuid, "Callback triggered: pick.");
|
||||
setArmBotActive(robot.modelUuid, false)
|
||||
setArmBotState(robot.modelUuid, "idle")
|
||||
setCurrentPhase("picking");
|
||||
setPath([])
|
||||
}
|
||||
else if (robot.isActive && robot.state == "running" && currentPhase == "start-to-end") {
|
||||
|
||||
logStatus(robot.modelUuid, "Callback triggered: drop.");
|
||||
setArmBotActive(robot.modelUuid, false)
|
||||
setArmBotState(robot.modelUuid, "idle")
|
||||
setCurrentPhase("dropping");
|
||||
setPath([])
|
||||
}
|
||||
else if (robot.isActive && robot.state == "running" && currentPhase == "end-to-rest") {
|
||||
|
||||
logStatus(robot.modelUuid, "Callback triggered: rest, cycle completed.");
|
||||
setArmBotActive(robot.modelUuid, false)
|
||||
setArmBotState(robot.modelUuid, "idle")
|
||||
setCurrentPhase("rest");
|
||||
@@ -163,12 +170,12 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) {
|
||||
}
|
||||
}
|
||||
const logStatus = (id: string, status: string) => {
|
||||
|
||||
// console.log(id + "," + status);
|
||||
console.log( status);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
<IKInstance modelUrl={armModel} setIkSolver={setIkSolver} ikSolver={ikSolver} robot={robot} groupRef={groupRef} processes={processes}
|
||||
setArmBotCurvePoints={setArmBotCurvePoints} />
|
||||
<RoboticArmAnimator armUuid={robot?.modelUuid} HandleCallback={HandleCallback}
|
||||
|
||||
@@ -15,6 +15,7 @@ type IKInstanceProps = {
|
||||
setArmBotCurvePoints: any
|
||||
};
|
||||
function IKInstance({ modelUrl, setIkSolver, ikSolver, robot, groupRef, processes, setArmBotCurvePoints }: IKInstanceProps) {
|
||||
|
||||
const { scene } = useThree();
|
||||
const gltf = useLoader(GLTFLoader, modelUrl, (loader) => {
|
||||
const draco = new DRACOLoader();
|
||||
@@ -64,16 +65,16 @@ function IKInstance({ modelUrl, setIkSolver, ikSolver, robot, groupRef, processe
|
||||
const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks);
|
||||
setIkSolver(solver);
|
||||
|
||||
const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05);
|
||||
const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05)
|
||||
|
||||
// scene.add(groupRef.current)
|
||||
// scene.add(helper)
|
||||
|
||||
|
||||
}, [gltf]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<group ref={groupRef} position={robot.position}>
|
||||
<group ref={groupRef} position={robot.position} rotation={robot.rotation}>
|
||||
<primitive
|
||||
uuid={"ArmBot-X200"}
|
||||
object={cloned}
|
||||
|
||||
@@ -7,18 +7,19 @@ function RoboticArm() {
|
||||
const { armBots, addArmBot, removeArmBot } = useArmBotStore();
|
||||
const { floorItems } = useFloorItems();
|
||||
|
||||
|
||||
const armBotStatusSample: RoboticArmEventSchema[] = [
|
||||
{
|
||||
state: "idle",
|
||||
modelUuid: "armbot-xyz-001",
|
||||
modelUuid: "3abf5d46-b59e-4e6b-9c02-a4634b64b82d",
|
||||
modelName: "ArmBot-X200",
|
||||
position: [91.94347308985614, 0, 6.742905194869091],
|
||||
rotation: [0, 0, 0],
|
||||
position: [0.20849215906958463, 0, 0.32079278127773675],
|
||||
rotation: [-1.3768690876192207e-15, 1.4883085074751308, 1.5407776675834467e-15],
|
||||
type: "roboticArm",
|
||||
speed: 1.5,
|
||||
point: {
|
||||
uuid: "point-123",
|
||||
position: [0, 1.5, 0],
|
||||
position: [0, 2.6, 0],
|
||||
rotation: [0, 0, 0],
|
||||
actions: [
|
||||
{
|
||||
@@ -26,9 +27,21 @@ function RoboticArm() {
|
||||
actionName: "Pick Component",
|
||||
actionType: "pickAndPlace",
|
||||
process: {
|
||||
startPoint: [5.52543010919071, 1, -8.433681161200905],
|
||||
endPoint: [10.52543010919071, 1, -12.433681161200905],
|
||||
startPoint: [-1, 2, 1],
|
||||
endPoint: [-2, 1, -1],
|
||||
},
|
||||
// process: {
|
||||
// "startPoint": [
|
||||
// 0.37114476008711866,
|
||||
// 1.9999999999999998,
|
||||
// 1.8418816116721384
|
||||
// ],
|
||||
// "endPoint": [
|
||||
// -0.42197069459490777,
|
||||
// 1,
|
||||
// -3.159515927851809
|
||||
// ]
|
||||
// },
|
||||
triggers: [
|
||||
{
|
||||
triggerUuid: "trigger-001",
|
||||
@@ -145,7 +158,7 @@ function RoboticArm() {
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
|
||||
removeArmBot(armBotStatusSample[0].modelUuid);
|
||||
addArmBot('123', armBotStatusSample[0]);
|
||||
// addArmBot('123', armBotStatusSample[1]);
|
||||
@@ -153,7 +166,7 @@ function RoboticArm() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
//
|
||||
|
||||
}, [armBots]);
|
||||
|
||||
return (
|
||||
|
||||
54
app/src/modules/simulation/ui/arm/PickDropPoints.tsx
Normal file
54
app/src/modules/simulation/ui/arm/PickDropPoints.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import React, { useRef } from "react";
|
||||
import * as THREE from "three";
|
||||
import { ThreeEvent } from "@react-three/fiber";
|
||||
|
||||
interface PickDropProps {
|
||||
position: number[];
|
||||
modelUuid: string;
|
||||
pointUuid: string;
|
||||
actionType: "pick" | "drop";
|
||||
actionUuid: string;
|
||||
gltfScene: THREE.Group;
|
||||
selectedPoint: THREE.Mesh | null;
|
||||
handlePointerDown: (e: ThreeEvent<PointerEvent>) => void;
|
||||
isSelected: boolean;
|
||||
}
|
||||
|
||||
const PickDropPoints: React.FC<PickDropProps> = ({
|
||||
position,
|
||||
modelUuid,
|
||||
pointUuid,
|
||||
actionType,
|
||||
actionUuid,
|
||||
gltfScene,
|
||||
selectedPoint,
|
||||
handlePointerDown,
|
||||
isSelected,
|
||||
}) => {
|
||||
const groupRef = useRef<THREE.Group>(null);
|
||||
|
||||
return (
|
||||
<group
|
||||
ref={groupRef}
|
||||
position={
|
||||
Array.isArray(position) && position.length === 3
|
||||
? new THREE.Vector3(...position)
|
||||
: new THREE.Vector3(0, 0, 0)
|
||||
}
|
||||
onPointerDown={(e) => {
|
||||
e.stopPropagation(); // Important to prevent event bubbling
|
||||
if (!isSelected) return;
|
||||
handlePointerDown(e);
|
||||
}}
|
||||
userData={{ modelUuid, pointUuid, actionType, actionUuid }}
|
||||
>
|
||||
<primitive
|
||||
object={gltfScene.clone()}
|
||||
position={[0, 0, 0]} // Ensure this stays at origin
|
||||
scale={[0.5, 0.5, 0.5]}
|
||||
/>
|
||||
</group>
|
||||
);
|
||||
};
|
||||
|
||||
export default PickDropPoints;
|
||||
131
app/src/modules/simulation/ui/arm/useDraggableGLTF.ts
Normal file
131
app/src/modules/simulation/ui/arm/useDraggableGLTF.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import { useRef } from "react";
|
||||
import * as THREE from "three";
|
||||
import { ThreeEvent, useThree } from "@react-three/fiber";
|
||||
|
||||
type OnUpdateCallback = (object: THREE.Object3D) => void;
|
||||
|
||||
export default function useDraggableGLTF(onUpdate: OnUpdateCallback) {
|
||||
const { camera, gl, controls, scene } = useThree();
|
||||
const activeObjRef = useRef<THREE.Object3D | null>(null);
|
||||
const planeRef = useRef<THREE.Plane>(
|
||||
new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)
|
||||
);
|
||||
const offsetRef = useRef<THREE.Vector3>(new THREE.Vector3());
|
||||
const initialPositionRef = useRef<THREE.Vector3>(new THREE.Vector3());
|
||||
|
||||
const raycaster = new THREE.Raycaster();
|
||||
const pointer = new THREE.Vector2();
|
||||
|
||||
const handlePointerDown = (e: ThreeEvent<PointerEvent>) => {
|
||||
e.stopPropagation();
|
||||
|
||||
let obj: THREE.Object3D | null = e.object;
|
||||
|
||||
// Traverse up until we find modelUuid in userData
|
||||
while (obj && !obj.userData?.modelUuid) {
|
||||
obj = obj.parent;
|
||||
}
|
||||
|
||||
if (!obj) return;
|
||||
|
||||
// Disable orbit controls while dragging
|
||||
if (controls) (controls as any).enabled = false;
|
||||
|
||||
activeObjRef.current = obj;
|
||||
initialPositionRef.current.copy(obj.position);
|
||||
|
||||
// Get world position
|
||||
const objectWorldPos = new THREE.Vector3();
|
||||
obj.getWorldPosition(objectWorldPos);
|
||||
|
||||
// Set plane at the object's Y level
|
||||
planeRef.current.set(new THREE.Vector3(0, 1, 0), -objectWorldPos.y);
|
||||
|
||||
// Convert pointer to NDC
|
||||
const rect = gl.domElement.getBoundingClientRect();
|
||||
pointer.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
|
||||
pointer.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
|
||||
|
||||
// Raycast to intersection
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
const intersection = new THREE.Vector3();
|
||||
raycaster.ray.intersectPlane(planeRef.current, intersection);
|
||||
|
||||
// Calculate offset
|
||||
offsetRef.current.copy(objectWorldPos).sub(intersection);
|
||||
|
||||
// Start listening for drag
|
||||
gl.domElement.addEventListener("pointermove", handlePointerMove);
|
||||
gl.domElement.addEventListener("pointerup", handlePointerUp);
|
||||
};
|
||||
|
||||
const handlePointerMove = (e: PointerEvent) => {
|
||||
if (!activeObjRef.current) return;
|
||||
|
||||
// Check if Shift key is pressed
|
||||
const isShiftKeyPressed = e.shiftKey;
|
||||
|
||||
// Get the mouse position relative to the canvas
|
||||
const rect = gl.domElement.getBoundingClientRect();
|
||||
pointer.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
|
||||
pointer.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
|
||||
|
||||
// Update raycaster to point to the mouse position
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
|
||||
// Create a vector to store intersection point
|
||||
const intersection = new THREE.Vector3();
|
||||
const intersects = raycaster.ray.intersectPlane(planeRef.current, intersection);
|
||||
if (!intersects) return;
|
||||
|
||||
// Add offset for dragging
|
||||
intersection.add(offsetRef.current);
|
||||
console.log('intersection: ', intersection);
|
||||
|
||||
// Get the parent's world matrix if exists
|
||||
const parent = activeObjRef.current.parent;
|
||||
const targetPosition = new THREE.Vector3();
|
||||
|
||||
if (isShiftKeyPressed) {
|
||||
console.log('isShiftKeyPressed: ', isShiftKeyPressed);
|
||||
// For Y-axis only movement, maintain original X and Z
|
||||
console.log('initialPositionRef: ', initialPositionRef);
|
||||
console.log('intersection.y: ', intersection);
|
||||
targetPosition.set(
|
||||
initialPositionRef.current.x,
|
||||
intersection.y,
|
||||
initialPositionRef.current.z
|
||||
);
|
||||
} else {
|
||||
// For free movement
|
||||
targetPosition.copy(intersection);
|
||||
}
|
||||
|
||||
// Convert world position to local if object is nested inside a parent
|
||||
if (parent) {
|
||||
parent.worldToLocal(targetPosition);
|
||||
}
|
||||
|
||||
// Update object position
|
||||
activeObjRef.current.position.copy(targetPosition);
|
||||
};
|
||||
|
||||
const handlePointerUp = () => {
|
||||
if (controls) (controls as any).enabled = true;
|
||||
|
||||
if (activeObjRef.current) {
|
||||
// Pass the updated position to the onUpdate callback to persist it
|
||||
onUpdate(activeObjRef.current);
|
||||
}
|
||||
|
||||
gl.domElement.removeEventListener("pointermove", handlePointerMove);
|
||||
gl.domElement.removeEventListener("pointerup", handlePointerUp);
|
||||
|
||||
activeObjRef.current = null;
|
||||
};
|
||||
|
||||
return { handlePointerDown };
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,302 +1,230 @@
|
||||
import React, { useRef, useEffect, useState } from "react";
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import startPoint from "../../../../assets/gltf-glb/arrow_green.glb";
|
||||
import startEnd from "../../../../assets/gltf-glb/arrow_red.glb";
|
||||
import { useGLTF } from "@react-three/drei";
|
||||
import { useSelectedEventSphere } from "../../../../store/simulation/useSimulationStore";
|
||||
import * as THREE from "three";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import { useVehicleStore } from "../../../../store/simulation/useVehicleStore";
|
||||
import { useGLTF } from '@react-three/drei';
|
||||
import { useFrame, useThree } from '@react-three/fiber';
|
||||
import { useSelectedEventSphere } from '../../../../store/simulation/useSimulationStore';
|
||||
import { useVehicleStore } from '../../../../store/simulation/useVehicleStore';
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
const VehicleUI = () => {
|
||||
const { scene: startScene } = useGLTF(startPoint) as any;
|
||||
const { scene: endScene } = useGLTF(startEnd) as any;
|
||||
const startMarker = useRef<THREE.Group>(null);
|
||||
const endMarker = useRef<THREE.Group>(null);
|
||||
const prevMousePos = useRef({ x: 0, y: 0 });
|
||||
const { selectedEventSphere } = useSelectedEventSphere();
|
||||
const { vehicles, updateVehicle } = useVehicleStore();
|
||||
const [startPosition, setStartPosition] = useState<[number, number, number]>([0, 0, 0]);
|
||||
const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 0, 0]);
|
||||
const [startRotation, setStartRotation] = useState<[number, number, number]>([0, 0, 0]);
|
||||
const [endRotation, setEndRotation] = useState<[number, number, number]>([0, 0, 0]);
|
||||
const [isDragging, setIsDragging] = useState<"start" | "end" | null>(null);
|
||||
const [isRotating, setIsRotating] = useState<"start" | "end" | null>(null);
|
||||
const { raycaster } = useThree();
|
||||
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0));
|
||||
const state: Types.ThreeState = useThree();
|
||||
const controls: any = state.controls;
|
||||
|
||||
type VehicleUIProps = {
|
||||
vehicleStatusSample: VehicleEventSchema[];
|
||||
setVehicleStatusSample: React.Dispatch<
|
||||
React.SetStateAction<VehicleEventSchema[]>
|
||||
>;
|
||||
vehicle: any
|
||||
};
|
||||
|
||||
const VehicleUI: React.FC<VehicleUIProps> = ({
|
||||
vehicleStatusSample,
|
||||
setVehicleStatusSample,
|
||||
vehicle
|
||||
}) => {
|
||||
const { scene: startScene } = useGLTF(startPoint) as any;
|
||||
const { scene: endScene } = useGLTF(startEnd) as any;
|
||||
const { camera, gl, controls } = useThree();
|
||||
const { selectedEventSphere } = useSelectedEventSphere();
|
||||
const { updateVehicle } = useVehicleStore();
|
||||
const startMarker = useRef<THREE.Group>(null);
|
||||
const endMarker = useRef<THREE.Group>(null);
|
||||
const hasInitialized = useRef<boolean>(false);
|
||||
const raycaster = useRef(new THREE.Raycaster());
|
||||
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Y = 0 plane
|
||||
const mouse = useRef(new THREE.Vector2());
|
||||
const prevMousePos = useRef({ x: 0, y: 0 });
|
||||
|
||||
const [draggedMarker, setDraggedMarker] = useState<"start" | "end" | null>(
|
||||
null
|
||||
);
|
||||
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
|
||||
const [isRotating, setIsRotating] = useState<boolean>(false);
|
||||
|
||||
|
||||
// Initialize start/end markers
|
||||
useEffect(() => {
|
||||
if (
|
||||
selectedEventSphere &&
|
||||
startMarker.current &&
|
||||
endMarker.current &&
|
||||
!hasInitialized.current
|
||||
) {
|
||||
startMarker.current.clear();
|
||||
endMarker.current.clear();
|
||||
|
||||
const startClone = startScene.clone();
|
||||
const endClone = endScene.clone();
|
||||
|
||||
startClone.name = "start-marker";
|
||||
endClone.name = "end-marker";
|
||||
|
||||
startClone.traverse((child: any) => {
|
||||
if (child.isMesh && child.name.toLowerCase().includes("handle")) {
|
||||
child.name = "handle";
|
||||
}
|
||||
});
|
||||
endClone.traverse((child: any) => {
|
||||
if (child.isMesh && child.name.toLowerCase().includes("handle")) {
|
||||
child.name = "handle";
|
||||
}
|
||||
});
|
||||
|
||||
startMarker.current.add(startClone);
|
||||
endMarker.current.add(endClone);
|
||||
|
||||
hasInitialized.current = true;
|
||||
}
|
||||
}, [selectedEventSphere, startScene, endScene]);
|
||||
|
||||
// Position start/end markers
|
||||
useEffect(() => {
|
||||
if (!selectedEventSphere || !startMarker.current || !endMarker.current)
|
||||
return;
|
||||
|
||||
const selectedVehicle = vehicleStatusSample.find(
|
||||
(vehicle) => vehicle.modelUuid === selectedEventSphere.userData.modelUuid
|
||||
);
|
||||
|
||||
if (selectedVehicle?.point?.action) {
|
||||
const { pickUpPoint, unLoadPoint } = selectedVehicle.point.action;
|
||||
|
||||
// Update start marker position
|
||||
if (pickUpPoint) {
|
||||
const localPos = new THREE.Vector3(
|
||||
pickUpPoint.x,
|
||||
pickUpPoint.y,
|
||||
pickUpPoint.z
|
||||
);
|
||||
localPos.y = 0; // Force y to 0
|
||||
startMarker.current.position.copy(localPos);
|
||||
} else {
|
||||
const defaultLocal = new THREE.Vector3(0, 0, 1.5);
|
||||
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
|
||||
defaultWorld.y = 0; // Force y to 0
|
||||
startMarker.current.position.copy(defaultWorld);
|
||||
}
|
||||
|
||||
// Update end marker position
|
||||
if (unLoadPoint) {
|
||||
const localPos = new THREE.Vector3(
|
||||
unLoadPoint.x,
|
||||
unLoadPoint.y,
|
||||
unLoadPoint.z
|
||||
useEffect(() => {
|
||||
if (!selectedEventSphere) return;
|
||||
const selectedVehicle = vehicles.find(
|
||||
(vehicle: any) => vehicle.modelUuid === selectedEventSphere.userData.modelUuid
|
||||
);
|
||||
|
||||
if (selectedVehicle?.point?.action) {
|
||||
const { pickUpPoint, unLoadPoint } = selectedVehicle.point.action;
|
||||
|
||||
localPos.y = 0; // Force y to 0
|
||||
endMarker.current.position.copy(localPos);
|
||||
} else {
|
||||
const defaultLocal = new THREE.Vector3(0, 0, -1.5);
|
||||
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
|
||||
defaultWorld.y = 0; // Force y to 0
|
||||
endMarker.current.position.copy(defaultWorld);
|
||||
}
|
||||
}
|
||||
}, [selectedEventSphere, vehicleStatusSample]);
|
||||
if (pickUpPoint) {
|
||||
const pickupPosition = new THREE.Vector3(
|
||||
pickUpPoint.position.x,
|
||||
pickUpPoint.position.y,
|
||||
pickUpPoint.position.z
|
||||
);
|
||||
const pickupRotation = new THREE.Vector3(
|
||||
pickUpPoint.rotation.x,
|
||||
pickUpPoint.rotation.y,
|
||||
pickUpPoint.rotation.z
|
||||
);
|
||||
pickupPosition.y = 0; // Force y to 0
|
||||
setStartPosition([pickupPosition.x, 0, pickupPosition.z]);
|
||||
setStartRotation([pickupRotation.x, pickupRotation.y, pickupRotation.z]);
|
||||
} else {
|
||||
const defaultLocal = new THREE.Vector3(0, 0, 1.5);
|
||||
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
|
||||
defaultWorld.y = 0; // Force y to 0
|
||||
setStartPosition([defaultWorld.x, 0, defaultWorld.z]);
|
||||
setStartRotation([0, 0, 0]);
|
||||
}
|
||||
|
||||
// Handle dragging and rotation
|
||||
const handlePointerDown = (e: any, markerType: "start" | "end") => {
|
||||
if (!selectedEventSphere) return;
|
||||
// Initialize end marker position and rotation
|
||||
if (unLoadPoint) {
|
||||
const unLoadPosition = new THREE.Vector3(
|
||||
unLoadPoint.position.x,
|
||||
unLoadPoint.position.y,
|
||||
unLoadPoint.position.z
|
||||
);
|
||||
const unLoadRotation = new THREE.Vector3(
|
||||
unLoadPoint.rotation.x,
|
||||
unLoadPoint.rotation.y,
|
||||
unLoadPoint.position.z
|
||||
);
|
||||
unLoadPosition.y = 0; // Force y to 0
|
||||
setEndPosition([unLoadPosition.x, 0, unLoadPosition.z]);
|
||||
setEndRotation([unLoadRotation.x, unLoadRotation.y, unLoadRotation.z]);
|
||||
} else {
|
||||
const defaultLocal = new THREE.Vector3(0, 0, -1.5);
|
||||
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
|
||||
defaultWorld.y = 0; // Force y to 0
|
||||
setEndPosition([defaultWorld.x, 0, defaultWorld.z]);
|
||||
setEndRotation([0, 0, 0]);
|
||||
}
|
||||
}
|
||||
}, [selectedEventSphere]);
|
||||
|
||||
if (e.object.name === "handle") {
|
||||
setIsRotating(true);
|
||||
prevMousePos.current = { x: e.clientX, y: e.clientY };
|
||||
if (controls) (controls as any).enabled = false;
|
||||
e.stopPropagation();
|
||||
setDraggedMarker(markerType);
|
||||
return;
|
||||
}
|
||||
useFrame(() => {
|
||||
if (!isDragging) return;
|
||||
const intersectPoint = new THREE.Vector3();
|
||||
const intersects = raycaster.ray.intersectPlane(plane.current, intersectPoint);
|
||||
|
||||
setDraggedMarker(markerType);
|
||||
if (controls) (controls as any).enabled = false;
|
||||
if (intersects) {
|
||||
intersectPoint.y = 0; // Force y to 0
|
||||
if (isDragging === "start") {
|
||||
setStartPosition([intersectPoint.x, 0, intersectPoint.z]);
|
||||
}
|
||||
if (isDragging === "end") {
|
||||
setEndPosition([intersectPoint.x, 0, intersectPoint.z]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const marker =
|
||||
markerType === "start" ? startMarker.current : endMarker.current;
|
||||
if (!marker) return;
|
||||
useFrame((state) => {
|
||||
if (!isRotating) return;
|
||||
|
||||
mouse.current.x = (e.clientX / gl.domElement.clientWidth) * 2 - 1;
|
||||
mouse.current.y = -(e.clientY / gl.domElement.clientHeight) * 2 + 1;
|
||||
const currentPointerX = state.pointer.x;
|
||||
const deltaX = currentPointerX - prevMousePos.current.x;
|
||||
prevMousePos.current.x = currentPointerX;
|
||||
|
||||
raycaster.current.setFromCamera(mouse.current, camera);
|
||||
const marker = isRotating === "start" ? startMarker.current : endMarker.current;
|
||||
|
||||
const intersectPoint = new THREE.Vector3();
|
||||
raycaster.current.ray.intersectPlane(plane.current, intersectPoint);
|
||||
if (marker) {
|
||||
const rotationSpeed = 10;
|
||||
marker.rotation.y -= deltaX * rotationSpeed;
|
||||
|
||||
const offset = new THREE.Vector3().subVectors(
|
||||
marker.position,
|
||||
intersectPoint
|
||||
);
|
||||
setDragOffset(offset);
|
||||
};
|
||||
|
||||
const handlePointerMove = (e: PointerEvent) => {
|
||||
if (!selectedEventSphere) return;
|
||||
|
||||
if (isRotating) {
|
||||
const deltaX = e.clientX - prevMousePos.current.x;
|
||||
prevMousePos.current = { x: e.clientX, y: e.clientY };
|
||||
|
||||
const rotationSpeed = 0.01;
|
||||
const marker =
|
||||
draggedMarker === "start" ? startMarker.current : endMarker.current;
|
||||
|
||||
if (marker) {
|
||||
marker.rotation.y -= deltaX * rotationSpeed;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!draggedMarker || !dragOffset) return;
|
||||
|
||||
mouse.current.x = (e.clientX / gl.domElement.clientWidth) * 2 - 1;
|
||||
mouse.current.y = -(e.clientY / gl.domElement.clientHeight) * 2 + 1;
|
||||
|
||||
raycaster.current.setFromCamera(mouse.current, camera);
|
||||
|
||||
const intersectPoint = new THREE.Vector3();
|
||||
raycaster.current.ray.intersectPlane(plane.current, intersectPoint);
|
||||
|
||||
if (!intersectPoint) return;
|
||||
|
||||
const newPos = {
|
||||
x: intersectPoint.x + dragOffset.x,
|
||||
y: 0,
|
||||
z: intersectPoint.z + dragOffset.z,
|
||||
};
|
||||
|
||||
|
||||
if (draggedMarker === "start" && startMarker.current) {
|
||||
startMarker.current.position.set(newPos.x, newPos.y, newPos.z);
|
||||
} else if (draggedMarker === "end" && endMarker.current) {
|
||||
endMarker.current.position.set(newPos.x, newPos.y, newPos.z);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePointerUp = () => {
|
||||
if (isRotating) {
|
||||
setIsRotating(false);
|
||||
if (controls) (controls as any).enabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedEventSphere || !draggedMarker || !dragOffset) {
|
||||
if (controls) (controls as any).enabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (controls) (controls as any).enabled = true;
|
||||
|
||||
const marker =
|
||||
draggedMarker === "start" ? startMarker.current : endMarker.current;
|
||||
if (!marker) return;
|
||||
|
||||
const worldPos = marker.position;
|
||||
|
||||
const updatedLocalPos = { x: worldPos.x, y: 0, z: worldPos.z };
|
||||
console.log('updatedLocalPos: ', updatedLocalPos);
|
||||
|
||||
|
||||
console.log('draggedMarker: ', draggedMarker);
|
||||
// setVehicleStatusSample((prev) =>
|
||||
// prev.map((vehicle) => {
|
||||
// if (
|
||||
// vehicle.modelUuid === selectedEventSphere.userData.modelUuid &&
|
||||
// selectedEventSphere
|
||||
// ) {
|
||||
// const updatedVehicle = {
|
||||
// ...vehicle,
|
||||
// point: {
|
||||
// ...vehicle.point,
|
||||
// action: {
|
||||
// ...vehicle.point?.action,
|
||||
// ...(draggedMarker === "start"
|
||||
// ? { pickUpPoint: updatedLocalPos }
|
||||
// : { unLoadPoint: updatedLocalPos }),
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// return updatedVehicle;
|
||||
// }
|
||||
// return vehicle;
|
||||
// })
|
||||
// );
|
||||
|
||||
updateVehicle(selectedEventSphere.userData.modelUuid, {
|
||||
point: {
|
||||
...vehicle?.point,
|
||||
action: {
|
||||
...vehicle?.point?.action,
|
||||
...(draggedMarker === "start"
|
||||
? { pickUpPoint: updatedLocalPos }
|
||||
: { unLoadPoint: updatedLocalPos }),
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
setDraggedMarker(null);
|
||||
setDragOffset(null);
|
||||
};
|
||||
const handlePointerDown = (e: any, state: "start" | "end", rotation: "start" | "end") => {
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("pointermove", handlePointerMove);
|
||||
window.addEventListener("pointerup", handlePointerUp);
|
||||
if (e.object.name === "handle") {
|
||||
const normalizedX = (e.clientX / window.innerWidth) * 2 - 1;
|
||||
const normalizedY = -(e.clientY / window.innerHeight) * 2 + 1;
|
||||
prevMousePos.current = { x: normalizedX, y: normalizedY };
|
||||
setIsRotating(rotation);
|
||||
if (controls) controls.enabled = false;
|
||||
setIsDragging(null);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("pointermove", handlePointerMove);
|
||||
window.removeEventListener("pointerup", handlePointerUp);
|
||||
} else {
|
||||
setIsDragging(state);
|
||||
setIsRotating(null);
|
||||
if (controls) controls.enabled = false;
|
||||
}
|
||||
};
|
||||
}, [draggedMarker, dragOffset, isRotating]);
|
||||
|
||||
if (!selectedEventSphere) {
|
||||
hasInitialized.current = false;
|
||||
return null;
|
||||
}
|
||||
const handlePointerUp = () => {
|
||||
console.log("nulll");
|
||||
controls.enabled = true;
|
||||
setIsDragging(null);
|
||||
setIsRotating(null);
|
||||
|
||||
return (
|
||||
<group>
|
||||
<group
|
||||
ref={startMarker}
|
||||
scale={draggedMarker === "start" ? [1.1, 1.1, 1.1] : [1, 1, 1]}
|
||||
onPointerDown={(e) => handlePointerDown(e, "start")}
|
||||
/>
|
||||
<group
|
||||
ref={endMarker}
|
||||
scale={draggedMarker === "end" ? [1.1, 1.1, 1.1] : [1, 1, 1]}
|
||||
onPointerDown={(e) => handlePointerDown(e, "end")}
|
||||
/>
|
||||
</group>
|
||||
);
|
||||
};
|
||||
if (selectedEventSphere?.userData.modelUuid) {
|
||||
const updatedVehicle = vehicles.find(
|
||||
(vehicle) => vehicle.modelUuid === selectedEventSphere.userData.modelUuid
|
||||
);
|
||||
|
||||
if (updatedVehicle) {
|
||||
updateVehicle(selectedEventSphere.userData.modelUuid, {
|
||||
point: {
|
||||
...updatedVehicle.point,
|
||||
action: {
|
||||
...updatedVehicle.point?.action,
|
||||
pickUpPoint: {
|
||||
position: {
|
||||
x: startPosition[0],
|
||||
y: startPosition[1],
|
||||
z: startPosition[2],
|
||||
},
|
||||
rotation: {
|
||||
x: startRotation[0],
|
||||
y: startRotation[1],
|
||||
z: startRotation[2],
|
||||
},
|
||||
},
|
||||
unLoadPoint: {
|
||||
position: {
|
||||
x: endPosition[0],
|
||||
y: endPosition[1],
|
||||
z: endPosition[2],
|
||||
},
|
||||
rotation: {
|
||||
x: endRotation[0],
|
||||
y: endRotation[1],
|
||||
z: endRotation[2],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
startPosition.length > 0 && endPosition.length > 0 ? (
|
||||
<mesh>
|
||||
<primitive
|
||||
name="start"
|
||||
object={startScene}
|
||||
ref={startMarker}
|
||||
position={startPosition}
|
||||
onPointerDown={(e: any) => {
|
||||
e.stopPropagation();
|
||||
handlePointerDown(e, "start", "start");
|
||||
}}
|
||||
onPointerUp={() => {
|
||||
handlePointerUp();
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
console.log("start pointermissed");
|
||||
handlePointerUp();
|
||||
}}
|
||||
/>
|
||||
|
||||
<primitive
|
||||
name="end"
|
||||
object={endScene}
|
||||
ref={endMarker}
|
||||
position={endPosition}
|
||||
onPointerDown={(e: any) => {
|
||||
e.stopPropagation();
|
||||
handlePointerDown(e, "end", "end");
|
||||
}}
|
||||
onPointerUp={() => {
|
||||
console.log("up");
|
||||
handlePointerUp();
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
console.log("end pointermissed");
|
||||
handlePointerUp();
|
||||
}}
|
||||
/>
|
||||
</mesh>
|
||||
) : null
|
||||
);
|
||||
}
|
||||
export default VehicleUI;
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ interface VehicleAnimatorProps {
|
||||
}
|
||||
|
||||
function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset }: VehicleAnimatorProps) {
|
||||
// console.log('path: ', path);
|
||||
const { decrementVehicleLoad } = useVehicleStore();
|
||||
const { isPaused } = usePauseButtonStore();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
@@ -193,7 +192,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{currentPath.length > 0 && (
|
||||
|
||||
@@ -51,10 +51,11 @@ function VehicleInstance({ agvDetail }: any) {
|
||||
|
||||
useEffect(() => {
|
||||
if (isPlaying) {
|
||||
|
||||
if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') {
|
||||
const toPickupPath = computePath(
|
||||
new THREE.Vector3(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]),
|
||||
agvDetail.point.action.pickUpPoint
|
||||
new THREE.Vector3(agvDetail?.position[0], agvDetail?.position[1], agvDetail?.position[2]),
|
||||
agvDetail?.point?.action?.pickUpPoint?.position
|
||||
);
|
||||
setPath(toPickupPath);
|
||||
setCurrentPhase('stationed-pickup');
|
||||
@@ -70,8 +71,8 @@ function VehicleInstance({ agvDetail }: any) {
|
||||
|
||||
if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity) {
|
||||
const toDrop = computePath(
|
||||
agvDetail.point.action.pickUpPoint,
|
||||
agvDetail.point.action.unLoadPoint
|
||||
agvDetail.point.action.pickUpPoint.position,
|
||||
agvDetail.point.action.unLoadPoint.position
|
||||
);
|
||||
setPath(toDrop);
|
||||
setCurrentPhase('pickup-drop');
|
||||
@@ -81,8 +82,8 @@ function VehicleInstance({ agvDetail }: any) {
|
||||
}
|
||||
} else if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'dropping' && agvDetail.currentLoad === 0) {
|
||||
const dropToPickup = computePath(
|
||||
agvDetail.point.action.unLoadPoint,
|
||||
agvDetail.point.action.pickUpPoint
|
||||
agvDetail.point.action.unLoadPoint.position,
|
||||
agvDetail.point.action.pickUpPoint.position
|
||||
);
|
||||
setPath(dropToPickup);
|
||||
setCurrentPhase('drop-pickup');
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
import React from 'react'
|
||||
import VehicleInstance from './instance/vehicleInstance'
|
||||
import { useVehicleStore } from '../../../../store/simulation/useVehicleStore'
|
||||
import VehicleUI from '../../ui/vehicle/vehicleUI';
|
||||
type VehicleUIProps = {
|
||||
vehicleStatusSample: VehicleEventSchema[];
|
||||
setVehicleStatusSample: React.Dispatch<
|
||||
React.SetStateAction<VehicleEventSchema[]>
|
||||
>;
|
||||
};
|
||||
const VehicleInstances: React.FC<VehicleUIProps> = ({
|
||||
vehicleStatusSample,
|
||||
setVehicleStatusSample,
|
||||
}) => {
|
||||
|
||||
function VehicleInstances() {
|
||||
|
||||
const { vehicles } = useVehicleStore();
|
||||
|
||||
@@ -19,14 +10,9 @@ const VehicleInstances: React.FC<VehicleUIProps> = ({
|
||||
<>
|
||||
|
||||
{vehicles.map((val: any, i: any) =>
|
||||
<>
|
||||
<VehicleInstance agvDetail={val} key={i} />
|
||||
<VehicleUI
|
||||
setVehicleStatusSample={setVehicleStatusSample}
|
||||
vehicleStatusSample={vehicleStatusSample}
|
||||
vehicle={val}
|
||||
/>
|
||||
</>
|
||||
|
||||
<VehicleInstance agvDetail={val} key={i} />
|
||||
|
||||
)}
|
||||
|
||||
</>
|
||||
|
||||
@@ -2,13 +2,16 @@ import React, { useEffect, useState } from "react";
|
||||
import VehicleInstances from "./instances/vehicleInstances";
|
||||
import { useVehicleStore } from "../../../store/simulation/useVehicleStore";
|
||||
import { useFloorItems } from "../../../store/store";
|
||||
import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
|
||||
import { useSelectedEventData, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
|
||||
import VehicleUI from "../ui/vehicle/vehicleUI";
|
||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||
function Vehicles() {
|
||||
|
||||
const { vehicles, addVehicle } = useVehicleStore();
|
||||
|
||||
const { floorItems } = useFloorItems()
|
||||
const { selectedEventSphere } = useSelectedEventSphere();
|
||||
const { selectedEventData } = useSelectedEventData();
|
||||
const { floorItems } = useFloorItems();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
|
||||
const [vehicleStatusSample, setVehicleStatusSample] = useState<
|
||||
VehicleEventSchema[]
|
||||
@@ -31,8 +34,8 @@ function Vehicles() {
|
||||
actionType: "travel",
|
||||
unLoadDuration: 10,
|
||||
loadCapacity: 2,
|
||||
pickUpPoint: { x: 98.71483985219794, y: 0, z: 28.66321267938962 },
|
||||
unLoadPoint: { x: 105.71483985219794, y: 0, z: 28.66321267938962 },
|
||||
pickUpPoint: { position: { x: 98.71483985219794, y: 0, z: 28.66321267938962 }, rotation: { x: 0, y: 0, z: 0 } },
|
||||
unLoadPoint: { position: { x: 105.71483985219794, y: 0, z: 28.66321267938962 }, rotation: { x: 0, y: 0, z: 0 } },
|
||||
triggers: [
|
||||
{
|
||||
triggerUuid: "trig-001",
|
||||
@@ -99,49 +102,49 @@ function Vehicles() {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
modelUuid: "cd7d0584-0684-42b4-b051-9e882c1914aa",
|
||||
modelName: "AGV",
|
||||
position: [105.90938758014703, 0, 31.584209911095215],
|
||||
rotation: [0, 0, 0],
|
||||
state: "idle",
|
||||
type: "vehicle",
|
||||
speed: 2.5,
|
||||
point: {
|
||||
uuid: "point-789",
|
||||
position: [0, 1, 0],
|
||||
rotation: [0, 0, 0],
|
||||
action: {
|
||||
actionUuid: "action-456",
|
||||
actionName: "Deliver to Zone A",
|
||||
actionType: "travel",
|
||||
unLoadDuration: 10,
|
||||
loadCapacity: 2,
|
||||
pickUpPoint: null,
|
||||
unLoadPoint: null,
|
||||
triggers: [
|
||||
{
|
||||
triggerUuid: "trig-001",
|
||||
triggerName: "Start Travel",
|
||||
triggerType: "onStart",
|
||||
delay: 0,
|
||||
triggeredAsset: {
|
||||
triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
|
||||
triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
|
||||
triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
|
||||
}
|
||||
},
|
||||
{
|
||||
triggerUuid: "trig-002",
|
||||
triggerName: "Complete Travel",
|
||||
triggerType: "onComplete",
|
||||
delay: 2,
|
||||
triggeredAsset: null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
// {
|
||||
// modelUuid: "cd7d0584-0684-42b4-b051-9e882c1914aa",
|
||||
// modelName: "AGV",
|
||||
// position: [105.90938758014703, 0, 31.584209911095215],
|
||||
// rotation: [0, 0, 0],
|
||||
// state: "idle",
|
||||
// type: "vehicle",
|
||||
// speed: 2.5,
|
||||
// point: {
|
||||
// uuid: "point-789",
|
||||
// position: [0, 1, 0],
|
||||
// rotation: [0, 0, 0],
|
||||
// action: {
|
||||
// actionUuid: "action-456",
|
||||
// actionName: "Deliver to Zone A",
|
||||
// actionType: "travel",
|
||||
// unLoadDuration: 10,
|
||||
// loadCapacity: 2,
|
||||
// pickUpPoint: null,
|
||||
// unLoadPoint: null,
|
||||
// triggers: [
|
||||
// {
|
||||
// triggerUuid: "trig-001",
|
||||
// triggerName: "Start Travel",
|
||||
// triggerType: "onStart",
|
||||
// delay: 0,
|
||||
// triggeredAsset: {
|
||||
// triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
|
||||
// triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
|
||||
// triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// triggerUuid: "trig-002",
|
||||
// triggerName: "Complete Travel",
|
||||
// triggerType: "onComplete",
|
||||
// delay: 2,
|
||||
// triggeredAsset: null
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// modelUuid: "e729a4f1-11d2-4778-8d6a-468f1b4f6b79",
|
||||
// modelName: "forklift",
|
||||
@@ -189,20 +192,20 @@ function Vehicles() {
|
||||
useEffect(() => {
|
||||
console.log("vehicles", vehicles);
|
||||
}, [vehicles])
|
||||
|
||||
useEffect(() => {
|
||||
addVehicle("123", vehicleStatusSample[0]);
|
||||
addVehicle('123', vehicleStatusSample[1]);
|
||||
addVehicle('123', vehicleStatusSample[2]);
|
||||
// addVehicle('123', vehicleStatusSample[2]);
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<VehicleInstances setVehicleStatusSample={setVehicleStatusSample}
|
||||
vehicleStatusSample={vehicleStatusSample} />
|
||||
{/* <VehicleUI
|
||||
setVehicleStatusSample={setVehicleStatusSample}
|
||||
vehicleStatusSample={vehicles}
|
||||
/> */}
|
||||
<VehicleInstances />
|
||||
{selectedEventSphere && selectedEventData?.data.type === "vehicle" && !isPlaying &&
|
||||
< VehicleUI />
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,15 +12,12 @@ import {
|
||||
useFloatingWidget,
|
||||
} from "../../store/visualization/useDroppedObjectsStore";
|
||||
import {
|
||||
useAsset3dWidget,
|
||||
useSocketStore,
|
||||
useWidgetSubOption,
|
||||
useZones,
|
||||
} from "../../store/store";
|
||||
import { getZone2dData } from "../../services/visulization/zone/getZoneData";
|
||||
import { generateUniqueId } from "../../functions/generateUniqueId";
|
||||
import { determinePosition } from "./functions/determinePosition";
|
||||
import { addingFloatingWidgets } from "../../services/visulization/zone/addFloatingWidgets";
|
||||
import SocketRealTimeViz from "./socket/realTimeVizSocket.dev";
|
||||
import RenderOverlay from "../../components/templates/Overlay";
|
||||
import ConfirmationPopup from "../../components/layout/confirmationPopup/ConfirmationPopup";
|
||||
@@ -68,20 +65,15 @@ const RealTimeVisulization: React.FC = () => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
const [droppedObjects, setDroppedObjects] = useState<any[]>([]);
|
||||
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
|
||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||
|
||||
const { rightSelect, setRightSelect } = useRightSelected();
|
||||
const { editWidgetOptions, setEditWidgetOptions } =
|
||||
useEditWidgetOptionsStore();
|
||||
const { setRightSelect } = useRightSelected();
|
||||
const { editWidgetOptions, setEditWidgetOptions } = useEditWidgetOptionsStore();
|
||||
const { rightClickSelected, setRightClickSelected } = useRightClickSelected();
|
||||
const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false);
|
||||
|
||||
// const [floatingWidgets, setFloatingWidgets] = useState<Record<string, { zoneName: string; zoneId: string; objects: any[] }>>({});
|
||||
const { floatingWidget, setFloatingWidget } = useFloatingWidget();
|
||||
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
|
||||
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
|
||||
const { setFloatingWidget } = useFloatingWidget();
|
||||
const { widgetSubOption } = useWidgetSubOption();
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
const { setSelectedChartId } = useWidgetStore();
|
||||
|
||||
@@ -99,11 +91,10 @@ const RealTimeVisulization: React.FC = () => {
|
||||
|
||||
useEffect(() => {
|
||||
async function GetZoneData() {
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const email = localStorage.getItem("email") ?? "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
try {
|
||||
const response = await getZone2dData(organization);
|
||||
// console.log('response: ', response);
|
||||
|
||||
if (!Array.isArray(response)) {
|
||||
return;
|
||||
@@ -125,7 +116,9 @@ const RealTimeVisulization: React.FC = () => {
|
||||
{}
|
||||
);
|
||||
setZonesData(formattedData);
|
||||
} catch (error) { }
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
GetZoneData();
|
||||
@@ -151,12 +144,10 @@ const RealTimeVisulization: React.FC = () => {
|
||||
});
|
||||
}, [selectedZone]);
|
||||
|
||||
// useEffect(() => {}, [floatingWidgets]);
|
||||
|
||||
const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
try {
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const email = localStorage.getItem("email") ?? "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
|
||||
const data = event.dataTransfer.getData("text/plain");
|
||||
@@ -172,8 +163,8 @@ const RealTimeVisulization: React.FC = () => {
|
||||
const relativeY = event.clientY - rect.top;
|
||||
|
||||
// Widget dimensions
|
||||
const widgetWidth = droppedData.width || 125;
|
||||
const widgetHeight = droppedData.height || 100;
|
||||
const widgetWidth = droppedData.width ?? 125;
|
||||
const widgetHeight = droppedData.height ?? 100;
|
||||
|
||||
// Center the widget at cursor
|
||||
const centerOffsetX = widgetWidth / 2;
|
||||
@@ -275,7 +266,7 @@ const RealTimeVisulization: React.FC = () => {
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
};
|
||||
}, [setRightClickSelected]);
|
||||
}, [setRightClickSelected, setRightSelect]);
|
||||
|
||||
const [canvasDimensions, setCanvasDimensions] = useState({
|
||||
width: 0,
|
||||
@@ -340,6 +331,7 @@ const RealTimeVisulization: React.FC = () => {
|
||||
borderRadius:
|
||||
isPlaying || activeModule !== "visualization" ? "" : "6px",
|
||||
}}
|
||||
role="application"
|
||||
onDrop={(event) => handleDrop(event)}
|
||||
onDragOver={(event) => event.preventDefault()}
|
||||
>
|
||||
|
||||
@@ -3,9 +3,8 @@ import Dropped3dWidgets from './widgets/3d/Dropped3dWidget'
|
||||
import ZoneCentreTarget from './zone/zoneCameraTarget'
|
||||
import ZoneAssets from './zone/zoneAssets'
|
||||
import MqttEvents from '../../services/factoryBuilder/mqtt/mqttEvents'
|
||||
import DrieHtmlTemp from './mqttTemp/drieHtmlTemp'
|
||||
|
||||
const Visualization = () => {
|
||||
const Visualization:React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user