simulation #47
@@ -46,7 +46,7 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||
socket.on("connect", startStream);
|
||||
socket.on("lastOutput", (response) => {
|
||||
const responseData = response;
|
||||
console.log("responceeeeeeeeeee", response);
|
||||
|
||||
|
||||
setDatas(responseData);
|
||||
});
|
||||
@@ -76,7 +76,7 @@ const StateWorking: React.FC<StateWorkingProps> = ({ id, type, position, rotatio
|
||||
}
|
||||
}
|
||||
|
||||
console.log("dataaaaa", datas);
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
useFloorItems,
|
||||
useSelectedActionSphere,
|
||||
useSelectedPath,
|
||||
useSimulationPaths,
|
||||
useSimulationStates,
|
||||
useSocketStore,
|
||||
} from "../../../../store/store";
|
||||
import * as THREE from "three";
|
||||
@@ -25,7 +25,7 @@ import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAss
|
||||
const ConveyorMechanics: React.FC = () => {
|
||||
const { selectedActionSphere } = useSelectedActionSphere();
|
||||
const { selectedPath, setSelectedPath } = useSelectedPath();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore();
|
||||
|
||||
@@ -34,13 +34,13 @@ const ConveyorMechanics: React.FC = () => {
|
||||
|
||||
const selectedPoint = useMemo(() => {
|
||||
if (!selectedActionSphere) return null;
|
||||
return simulationPaths
|
||||
return simulationStates
|
||||
.filter(
|
||||
(path): path is Types.ConveyorEventsSchema => path.type === "Conveyor"
|
||||
)
|
||||
.flatMap((path) => path.points)
|
||||
.find((point) => point.uuid === selectedActionSphere.points.uuid);
|
||||
}, [selectedActionSphere, simulationPaths]);
|
||||
}, [selectedActionSphere, simulationStates]);
|
||||
|
||||
const updateBackend = async (updatedPath: Types.ConveyorEventsSchema | undefined) => {
|
||||
if (!updatedPath) return;
|
||||
@@ -66,7 +66,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
const handleAddAction = () => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) => {
|
||||
const updatedPaths = simulationStates.map((path) => {
|
||||
if (path.type === "Conveyor") {
|
||||
return {
|
||||
...path,
|
||||
@@ -101,13 +101,13 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
};
|
||||
|
||||
const handleDeleteAction = (uuid: string) => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -134,13 +134,13 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
};
|
||||
|
||||
const handleActionSelect = (uuid: string, actionType: string) => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -182,7 +182,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
|
||||
// Update the selected item to reflect changes
|
||||
if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) {
|
||||
@@ -207,7 +207,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
const handleMaterialSelect = (uuid: string, material: string) => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -237,7 +237,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
|
||||
// Update selected item if it's the current action
|
||||
if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) {
|
||||
@@ -254,7 +254,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
const handleDelayChange = (uuid: string, delay: number | string) => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -281,7 +281,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
};
|
||||
|
||||
const handleSpawnIntervalChange = (
|
||||
@@ -290,7 +290,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
) => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -319,13 +319,13 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
};
|
||||
|
||||
const handleSpeedChange = (speed: number | string) => {
|
||||
if (!selectedPath) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
|
||||
);
|
||||
|
||||
@@ -338,14 +338,14 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
|
||||
};
|
||||
|
||||
const handleAddTrigger = () => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -377,13 +377,13 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
};
|
||||
|
||||
const handleDeleteTrigger = (uuid: string) => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -410,13 +410,13 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
};
|
||||
|
||||
const handleTriggerSelect = (uuid: string, triggerType: string) => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -445,7 +445,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
|
||||
// Ensure the selectedItem is updated immediately
|
||||
const updatedTrigger = updatedPaths
|
||||
@@ -461,7 +461,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
// Update the toggle handlers to immediately update the selected item
|
||||
const handleActionToggle = (uuid: string) => {
|
||||
if (!selectedActionSphere) return;
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -489,7 +489,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
|
||||
// Immediately update the selected item if it's the one being toggled
|
||||
if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) {
|
||||
@@ -507,7 +507,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
const handleTriggerToggle = (uuid: string) => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -535,7 +535,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
|
||||
// Immediately update the selected item if it's the one being toggled
|
||||
if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) {
|
||||
@@ -552,7 +552,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
const handleTriggerBufferTimeChange = (uuid: string, bufferTime: number) => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
@@ -581,7 +581,7 @@ const ConveyorMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
|
||||
// Immediately update selectedItem if it's the currently selected trigger
|
||||
if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React, { useRef, useMemo } from "react";
|
||||
import { InfoIcon } from "../../../icons/ExportCommonIcons";
|
||||
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
||||
import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationPaths, useSocketStore } from "../../../../store/store";
|
||||
import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
|
||||
import * as Types from '../../../../types/world/worldTypes';
|
||||
import PositionInput from "../customInput/PositionInputs";
|
||||
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
||||
|
||||
const VehicleMechanics: React.FC = () => {
|
||||
const { selectedActionSphere } = useSelectedActionSphere();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
|
||||
const { editingPoint, setEditingPoint } = useEditingPoint();
|
||||
const { previewPosition, setPreviewPosition } = usePreviewPosition();
|
||||
@@ -19,7 +19,7 @@ const VehicleMechanics: React.FC = () => {
|
||||
const { selectedPoint, connectedPointUuids } = useMemo(() => {
|
||||
if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] };
|
||||
|
||||
const vehiclePaths = simulationPaths.filter(
|
||||
const vehiclePaths = simulationStates.filter(
|
||||
(path): path is Types.VehicleEventsSchema => path.type === "Vehicle"
|
||||
);
|
||||
|
||||
@@ -40,7 +40,7 @@ const VehicleMechanics: React.FC = () => {
|
||||
selectedPoint: points,
|
||||
connectedPointUuids: connectedUuids
|
||||
};
|
||||
}, [selectedActionSphere, simulationPaths]);
|
||||
}, [selectedActionSphere, simulationStates]);
|
||||
|
||||
const updateBackend = async (updatedPath: Types.VehicleEventsSchema | undefined) => {
|
||||
if (!updatedPath) return;
|
||||
@@ -66,7 +66,7 @@ const VehicleMechanics: React.FC = () => {
|
||||
const handleActionUpdate = React.useCallback((updatedAction: Partial<Types.VehicleEventsSchema['points']['actions']>) => {
|
||||
if (!selectedActionSphere?.points?.uuid) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) => {
|
||||
const updatedPaths = simulationStates.map((path) => {
|
||||
if (path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid) {
|
||||
return {
|
||||
...path,
|
||||
@@ -89,8 +89,8 @@ const VehicleMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
}, [selectedActionSphere?.points?.uuid, simulationPaths, setSimulationPaths]);
|
||||
setSimulationStates(updatedPaths);
|
||||
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
|
||||
|
||||
const handleHitCountChange = React.useCallback((hitCount: number) => {
|
||||
handleActionUpdate({ hitCount });
|
||||
@@ -103,7 +103,7 @@ const VehicleMechanics: React.FC = () => {
|
||||
const handleSpeedChange = React.useCallback((speed: number) => {
|
||||
if (!selectedActionSphere?.points?.uuid) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) => {
|
||||
const updatedPaths = simulationStates.map((path) => {
|
||||
if (path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid) {
|
||||
return {
|
||||
...path,
|
||||
@@ -123,8 +123,8 @@ const VehicleMechanics: React.FC = () => {
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
}, [selectedActionSphere?.points?.uuid, simulationPaths, setSimulationPaths]);
|
||||
setSimulationStates(updatedPaths);
|
||||
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
|
||||
|
||||
const handleStartEyeDropClick = () => {
|
||||
setEditingPoint('start');
|
||||
|
||||
@@ -50,6 +50,7 @@ export default function Dropped3dWidgets() {
|
||||
const rotationStartRef = useRef<[number, number, number]>([0, 0, 0]);
|
||||
const mouseStartRef = useRef<{ x: number; y: number }>({ x: 0, y: 0 });
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (activeModule !== "visualization") return;
|
||||
if (!selectedZone.zoneId) return;
|
||||
@@ -139,8 +140,6 @@ export default function Dropped3dWidgets() {
|
||||
|
||||
if (rightSelect === "Duplicate") {
|
||||
async function duplicateWidget() {
|
||||
|
||||
|
||||
const widgetToDuplicate = activeZoneWidgets.find((w: WidgetData) => w.id === rightClickSelected);
|
||||
if (!widgetToDuplicate) return;
|
||||
const newWidget: WidgetData = {
|
||||
@@ -154,12 +153,15 @@ export default function Dropped3dWidgets() {
|
||||
rotation: widgetToDuplicate.rotation || [0, 0, 0],
|
||||
};
|
||||
const adding3dWidget = {
|
||||
organization,
|
||||
organization: organization,
|
||||
widget: newWidget,
|
||||
zoneId: selectedZone.zoneId
|
||||
};
|
||||
let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget)
|
||||
console.log('response: ', response);
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-3D-widget:add", adding3dWidget);
|
||||
}
|
||||
// let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget)
|
||||
// console.log('response: ', response);
|
||||
|
||||
addWidget(selectedZone.zoneId, newWidget);
|
||||
setRightSelect(null);
|
||||
@@ -173,23 +175,20 @@ export default function Dropped3dWidgets() {
|
||||
try {
|
||||
const deleteWidget = {
|
||||
organization,
|
||||
widgetId: rightClickSelected,
|
||||
id: rightClickSelected,
|
||||
zoneId: selectedZone.zoneId,
|
||||
};
|
||||
|
||||
console.log('deleteWidget: ', deleteWidget);
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-3D-widget:delete", deleteWidget);
|
||||
}
|
||||
// Call the API to delete the widget
|
||||
const response = await delete3dWidgetApi(selectedZone.zoneId, organization, rightClickSelected);
|
||||
|
||||
|
||||
// if (response?.success) {
|
||||
// Remove from state only if API call succeeds
|
||||
// const response = await delete3dWidgetApi(selectedZone.zoneId, organization, rightClickSelected);
|
||||
setZoneWidgetData(
|
||||
selectedZone.zoneId,
|
||||
activeZoneWidgets.filter((w: WidgetData) => w.id !== rightClickSelected)
|
||||
);
|
||||
// } else {
|
||||
// console.error("Failed to delete widget:", response?.message);
|
||||
// }
|
||||
} catch (error) {
|
||||
console.error("Error deleting widget:", error);
|
||||
} finally {
|
||||
@@ -298,44 +297,60 @@ export default function Dropped3dWidgets() {
|
||||
|
||||
const handleMouseUp = () => {
|
||||
if (!rightClickSelected || !rightSelect) return;
|
||||
|
||||
const selectedZone = Object.keys(zoneWidgetData).find(zoneId =>
|
||||
zoneWidgetData[zoneId].some(widget => widget.id === rightClickSelected)
|
||||
);
|
||||
|
||||
if (!selectedZone) return;
|
||||
|
||||
const selectedWidget = zoneWidgetData[selectedZone].find(widget => widget.id === rightClickSelected);
|
||||
if (!selectedWidget) return;
|
||||
|
||||
|
||||
|
||||
// Format values to 2 decimal places
|
||||
const formatValues = (vals: number[]) => vals.map(val => parseFloat(val.toFixed(2)));
|
||||
|
||||
if (rightSelect === "Horizontal Move" || rightSelect === "Vertical Move") {
|
||||
console.log(`${rightSelect} Completed - Full Position:`, formatValues(selectedWidget.position));
|
||||
let lastPosition = formatValues(selectedWidget.position) as [number, number, number];
|
||||
// (async () => {
|
||||
// let response = await update3dWidget(selectedZone, organization, rightClickSelected, lastPosition);
|
||||
// console.log('response: ', response);
|
||||
// if (response) {
|
||||
// console.log("Widget position updated in API:", response);
|
||||
// }
|
||||
// })();
|
||||
let updatingPosition = {
|
||||
organization: organization,
|
||||
zoneId: selectedZone,
|
||||
id: rightClickSelected,
|
||||
position: lastPosition,
|
||||
}
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-3D-widget:modifyPositionRotation", updatingPosition);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
let response = await update3dWidget(selectedZone, organization, rightClickSelected, lastPosition);
|
||||
console.log('response: ', response);
|
||||
if (response) {
|
||||
console.log("Widget position updated in API:", response);
|
||||
}
|
||||
})();
|
||||
}
|
||||
else if (rightSelect.includes("Rotate")) {
|
||||
const rotation = selectedWidget.rotation || [0, 0, 0];
|
||||
console.log(`${rightSelect} Completed - Full Rotation:`, formatValues(rotation));
|
||||
let lastPosition = formatValues(rotation) as [number, number, number];
|
||||
console.log('lastPosition: ', lastPosition);
|
||||
|
||||
(async () => {
|
||||
let response = await update3dWidgetRotation(selectedZone, organization, rightClickSelected, lastPosition);
|
||||
console.log('response: ', response);
|
||||
if (response) {
|
||||
console.log("Widget position updated in API:", response);
|
||||
}
|
||||
})();
|
||||
let lastRotation = formatValues(rotation) as [number, number, number];
|
||||
// (async () => {
|
||||
// let response = await update3dWidgetRotation(selectedZone, organization, rightClickSelected, lastRotation);
|
||||
// console.log('response: ', response);
|
||||
// if (response) {
|
||||
// console.log("Widget position updated in API:", response);
|
||||
// }
|
||||
// })();
|
||||
let updatingRotation = {
|
||||
organization: organization,
|
||||
zoneId: selectedZone,
|
||||
id: rightClickSelected,
|
||||
rotation: lastRotation,
|
||||
}
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit("v2:viz-3D-widget:modifyPositionRotation", updatingRotation);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset selection
|
||||
|
||||
@@ -31,7 +31,6 @@ interface ListProps {
|
||||
}
|
||||
|
||||
const List: React.FC<ListProps> = ({ items = [], remove }) => {
|
||||
console.log("items: ", items);
|
||||
const { activeModule, setActiveModule } = useModuleStore();
|
||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||
const { setSubModule } = useSubModuleStore();
|
||||
|
||||
@@ -1,163 +1,68 @@
|
||||
import PolygonGenerator from "./polygonGenerator";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import * as THREE from "three";
|
||||
import * as Types from "../../../types/world/worldTypes";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Line } from "@react-three/drei";
|
||||
import { useNavMesh, useSimulationStates } from "../../../store/store";
|
||||
import PathNavigator from "./pathNavigator";
|
||||
import NavMeshDetails from "./navMeshDetails";
|
||||
import {
|
||||
useSelectedActionSphere,
|
||||
useSimulationPaths,
|
||||
} from "../../../store/store";
|
||||
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||
|
||||
const Agv = ({
|
||||
lines,
|
||||
}: {
|
||||
lines: Types.RefLines;
|
||||
}) => {
|
||||
const [pathPoints, setPathPoints] = useState<
|
||||
{
|
||||
modelUuid: string;
|
||||
modelSpeed: number;
|
||||
bufferTime: number;
|
||||
points: { x: number; y: number; z: number }[];
|
||||
hitCount: number;
|
||||
}[]
|
||||
>([]);
|
||||
const { simulationPaths } = useSimulationPaths();
|
||||
const { selectedActionSphere } = useSelectedActionSphere();
|
||||
useEffect(() => {
|
||||
if (!Array.isArray(simulationPaths)) {
|
||||
} else {
|
||||
let agvModels = simulationPaths.filter(
|
||||
(val: any) => val.modelName === "agv"
|
||||
);
|
||||
type PathPoints = {
|
||||
modelUuid: string;
|
||||
modelSpeed: number;
|
||||
bufferTime: number;
|
||||
points: { x: number; y: number; z: number }[];
|
||||
hitCount: number;
|
||||
};
|
||||
|
||||
|
||||
let findMesh = agvModels.filter(
|
||||
(val: any) =>
|
||||
val.modeluuid === selectedActionSphere?.path?.modeluuid &&
|
||||
val.type === "Vehicle"
|
||||
);
|
||||
const Agv = () => {
|
||||
const [pathPoints, setPathPoints] = useState<PathPoints[]>([]);
|
||||
const { simulationStates } = useSimulationStates();
|
||||
const { navMesh } = useNavMesh();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
|
||||
const result =
|
||||
findMesh.length > 0 &&
|
||||
findMesh[0].type === "Vehicle" &&
|
||||
typeof findMesh[0].points?.actions.start === "object" &&
|
||||
typeof findMesh[0].points?.actions.end === "object" &&
|
||||
"x" in findMesh[0].points.actions.start &&
|
||||
"y" in findMesh[0].points.actions.start &&
|
||||
"x" in findMesh[0].points.actions.end &&
|
||||
"y" in findMesh[0].points.actions.end
|
||||
? [
|
||||
{
|
||||
modelUuid: findMesh[0].modeluuid, // Ensure it's a number
|
||||
modelSpeed: findMesh[0].points.speed,
|
||||
bufferTime: findMesh[0].points.actions.buffer,
|
||||
hitCount: findMesh[0].points.actions.hitCount,
|
||||
points: [
|
||||
{
|
||||
x: findMesh[0].position[0],
|
||||
y: findMesh[0].position[1],
|
||||
z: findMesh[0].position[2],
|
||||
},
|
||||
{
|
||||
x: findMesh[0].points.actions.start.x,
|
||||
y: 0,
|
||||
z: findMesh[0].points.actions.start.y,
|
||||
},
|
||||
{
|
||||
x: findMesh[0].points.actions.end.x,
|
||||
y: 0,
|
||||
z: findMesh[0].points.actions.end.y,
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
: [];
|
||||
if (result.length > 0) {
|
||||
// setPathPoints((prev) => [...prev, ...result]);
|
||||
setPathPoints((prev) => {
|
||||
const existingIndex = prev.findIndex(
|
||||
(item) => item.modelUuid === result[0].modelUuid
|
||||
);
|
||||
useEffect(() => {
|
||||
if (simulationStates.length > 0) {
|
||||
|
||||
if (existingIndex !== -1) {
|
||||
const updatedPathPoints = [...prev];
|
||||
updatedPathPoints[existingIndex] = result[0];
|
||||
return updatedPathPoints;
|
||||
} else {
|
||||
return [...prev, ...result];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// setPathPoints((prev) => {
|
||||
// const existingUUIDs = new Set(prev.map((item) => item.uuid));
|
||||
// const newItems = result.filter(
|
||||
// (item) => !existingUUIDs.has(item.uuid)
|
||||
// );
|
||||
// return [...prev, ...newItems];
|
||||
// });
|
||||
}, [simulationPaths, selectedActionSphere]);
|
||||
const agvModels = simulationStates.filter((val) => val.modelName === "agv" && val.type === "Vehicle");
|
||||
|
||||
let groupRef = useRef() as Types.RefGroup;
|
||||
const [navMesh, setNavMesh] = useState();
|
||||
const newPathPoints = agvModels.filter((model: any) => model.points && model.points.actions && typeof model.points.actions.start === "object" && typeof model.points.actions.end === "object" && "x" in model.points.actions.start && "y" in model.points.actions.start && "x" in model.points.actions.end && "y" in model.points.actions.end)
|
||||
.map((model: any) => ({
|
||||
modelUuid: model.modeluuid,
|
||||
modelSpeed: model.points.speed,
|
||||
bufferTime: model.points.actions.buffer,
|
||||
hitCount: model.points.actions.hitCount,
|
||||
points: [
|
||||
{ x: model.position[0], y: model.position[1], z: model.position[2] },
|
||||
{ x: model.points.actions.start.x, y: 0, z: model.points.actions.start.y },
|
||||
{ x: model.points.actions.end.x, y: 0, z: model.points.actions.end.y },
|
||||
],
|
||||
}));
|
||||
|
||||
return (
|
||||
<>
|
||||
<PolygonGenerator groupRef={groupRef} lines={lines} />
|
||||
<NavMeshDetails
|
||||
lines={lines}
|
||||
setNavMesh={setNavMesh}
|
||||
groupRef={groupRef}
|
||||
/>
|
||||
{pathPoints.map((pair, i) => (
|
||||
<>
|
||||
<PathNavigator
|
||||
navMesh={navMesh}
|
||||
selectedPoints={pair.points}
|
||||
id={pair.modelUuid}
|
||||
key={i}
|
||||
speed={pair.modelSpeed}
|
||||
bufferTime={pair.bufferTime}
|
||||
hitCount={pair.hitCount}
|
||||
/>
|
||||
{/* {pair.points.length > 2 && (
|
||||
<>
|
||||
<mesh
|
||||
position={[
|
||||
pair.points[1].x,
|
||||
pair.points[1].y,
|
||||
pair.points[1].z,
|
||||
]}
|
||||
>
|
||||
<sphereGeometry args={[0.3, 15, 15]} />
|
||||
<meshStandardMaterial color="red" />
|
||||
</mesh>
|
||||
<mesh
|
||||
position={[
|
||||
pair.points[2].x,
|
||||
pair.points[2].y,
|
||||
pair.points[2].z,
|
||||
]}
|
||||
>
|
||||
<sphereGeometry args={[0.3, 15, 15]} />
|
||||
<meshStandardMaterial color="red" />
|
||||
</mesh>
|
||||
</>
|
||||
)} */}
|
||||
</>
|
||||
))}
|
||||
<group ref={groupRef} visible={false} name="Meshes">
|
||||
<mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} name="Plane" receiveShadow>
|
||||
<planeGeometry args={[300, 300]} />
|
||||
<meshBasicMaterial color={CONSTANTS.planeConfig.color} />
|
||||
</mesh>
|
||||
</group>
|
||||
</>
|
||||
);
|
||||
setPathPoints(newPathPoints);
|
||||
}
|
||||
}, [simulationStates]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{pathPoints.map((pair, i) => (
|
||||
<group key={i} visible={!isPlaying}>
|
||||
<PathNavigator
|
||||
navMesh={navMesh}
|
||||
pathPoints={pair.points}
|
||||
id={pair.modelUuid}
|
||||
speed={pair.modelSpeed}
|
||||
bufferTime={pair.bufferTime}
|
||||
hitCount={pair.hitCount}
|
||||
/>
|
||||
|
||||
{pair.points.slice(1).map((point, idx) => (
|
||||
<mesh position={[point.x, point.y, point.z]} key={idx}>
|
||||
<sphereGeometry args={[0.3, 15, 15]} />
|
||||
<meshStandardMaterial color="red" />
|
||||
</mesh>
|
||||
))}
|
||||
</group>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Agv;
|
||||
|
||||
31
app/src/modules/builder/agv/navMeshCreator.tsx
Normal file
31
app/src/modules/builder/agv/navMeshCreator.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { useRef } from "react";
|
||||
import { useNavMesh } from "../../../store/store";
|
||||
import PolygonGenerator from "./polygonGenerator";
|
||||
import NavMeshDetails from "./navMeshDetails";
|
||||
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||
import * as Types from "../../../types/world/worldTypes";
|
||||
|
||||
type NavMeshCreatorProps = {
|
||||
lines: Types.RefLines
|
||||
};
|
||||
|
||||
function NavMeshCreator({ lines }: NavMeshCreatorProps) {
|
||||
let groupRef = useRef() as Types.RefGroup;
|
||||
const { setNavMesh } = useNavMesh();
|
||||
|
||||
return (
|
||||
<>
|
||||
<PolygonGenerator groupRef={groupRef} lines={lines} />
|
||||
<NavMeshDetails lines={lines} setNavMesh={setNavMesh} groupRef={groupRef} />
|
||||
|
||||
<group ref={groupRef} visible={false} name="Meshes">
|
||||
<mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} name="Plane" receiveShadow>
|
||||
<planeGeometry args={[300, 300]} />
|
||||
<meshBasicMaterial color={CONSTANTS.planeConfig.color} />
|
||||
</mesh>
|
||||
</group>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default NavMeshCreator
|
||||
@@ -3,179 +3,207 @@ import * as THREE from "three";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { NavMeshQuery } from "@recast-navigation/core";
|
||||
import { Line } from "@react-three/drei";
|
||||
import { useActiveTool } from "../../../store/store";
|
||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||
|
||||
interface PathNavigatorProps {
|
||||
navMesh: any;
|
||||
selectedPoints: any;
|
||||
id: string;
|
||||
speed: number;
|
||||
bufferTime: number;
|
||||
hitCount: number;
|
||||
navMesh: any;
|
||||
pathPoints: any;
|
||||
id: string;
|
||||
speed: number;
|
||||
bufferTime: number;
|
||||
hitCount: number;
|
||||
}
|
||||
|
||||
export default function PathNavigator({
|
||||
navMesh,
|
||||
selectedPoints,
|
||||
id,
|
||||
speed,
|
||||
bufferTime,
|
||||
hitCount,
|
||||
navMesh,
|
||||
pathPoints,
|
||||
id,
|
||||
speed,
|
||||
bufferTime,
|
||||
hitCount
|
||||
}: PathNavigatorProps) {
|
||||
const [path, setPath] = useState<[number, number, number][]>([]);
|
||||
const progressRef = useRef(0);
|
||||
const distancesRef = useRef<number[]>([]);
|
||||
const totalDistanceRef = useRef(0);
|
||||
const currentSegmentIndex = useRef(0);
|
||||
const [stop, setStop] = useState<boolean>(true);
|
||||
const { scene } = useThree();
|
||||
const { isPlaying, setIsPlaying } = usePlayButtonStore();
|
||||
const [startPoint, setStartPoint] = useState(new THREE.Vector3());
|
||||
const isWaiting = useRef<boolean>(false); // Flag to track waiting state
|
||||
const delayTime = bufferTime;
|
||||
const [path, setPath] = useState<[number, number, number][]>([]);
|
||||
const [currentPhase, setCurrentPhase] = useState<'initial' | 'loop'>('initial');
|
||||
const [toPickupPath, setToPickupPath] = useState<[number, number, number][]>([]);
|
||||
const [pickupDropPath, setPickupDropPath] = useState<[number, number, number][]>([]);
|
||||
const [dropPickupPath, setDropPickupPath] = useState<[number, number, number][]>([]);
|
||||
const [initialPosition, setInitialPosition] = useState<THREE.Vector3 | null>(null);
|
||||
const [initialRotation, setInitialRotation] = useState<THREE.Euler | null>(null);
|
||||
|
||||
const movingForward = useRef<boolean>(true); // Tracks whether the object is moving forward
|
||||
// Compute distances and total distance when the path changes
|
||||
useEffect(() => {
|
||||
if (!scene || !id || path.length < 2) return;
|
||||
const distancesRef = useRef<number[]>([]);
|
||||
const totalDistanceRef = useRef(0);
|
||||
const progressRef = useRef(0);
|
||||
const isWaiting = useRef(false);
|
||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
let totalDistance = 0;
|
||||
const distances: number[] = [];
|
||||
for (let i = 0; i < path.length - 1; i++) {
|
||||
const start = new THREE.Vector3(...path[i]);
|
||||
const end = new THREE.Vector3(...path[i + 1]);
|
||||
const segmentDistance = start.distanceTo(end);
|
||||
distances.push(segmentDistance);
|
||||
totalDistance += segmentDistance;
|
||||
}
|
||||
distancesRef.current = distances;
|
||||
totalDistanceRef.current = totalDistance;
|
||||
progressRef.current = 0;
|
||||
}, [path]);
|
||||
const { scene } = useThree();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
|
||||
// Compute the path using NavMeshQuery
|
||||
useEffect(() => {
|
||||
if (!navMesh || selectedPoints.length === 0) return;
|
||||
useEffect(() => {
|
||||
const object = scene.getObjectByProperty("uuid", id);
|
||||
if (object) {
|
||||
setInitialPosition(object.position.clone());
|
||||
setInitialRotation(object.rotation.clone());
|
||||
}
|
||||
}, [scene, id]);
|
||||
|
||||
const allPoints = selectedPoints.flat();
|
||||
const computedPath: [number, number, number][] = [];
|
||||
const computePath = (start: any, end: any) => {
|
||||
try {
|
||||
const navMeshQuery = new NavMeshQuery(navMesh);
|
||||
const { path: segmentPath } = navMeshQuery.computePath(start, end);
|
||||
return segmentPath?.map(({ x, y, z }) => [x, y + 0.1, z] as [number, number, number]) || [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
for (let i = 0; i < allPoints.length - 1; i++) {
|
||||
const start = allPoints[i];
|
||||
setStartPoint(
|
||||
new THREE.Vector3(allPoints[0].x, allPoints[0].y, allPoints[0].z)
|
||||
);
|
||||
const resetState = () => {
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
timeoutRef.current = null;
|
||||
}
|
||||
|
||||
const end = allPoints[i + 1];
|
||||
setPath([]);
|
||||
setCurrentPhase('initial');
|
||||
setPickupDropPath([]);
|
||||
setDropPickupPath([]);
|
||||
distancesRef.current = [];
|
||||
totalDistanceRef.current = 0;
|
||||
progressRef.current = 0;
|
||||
isWaiting.current = false;
|
||||
|
||||
try {
|
||||
const navMeshQuery = new NavMeshQuery(navMesh);
|
||||
const { path: segmentPath } = navMeshQuery.computePath(start, end);
|
||||
if (initialPosition && initialRotation) {
|
||||
const object = scene.getObjectByProperty("uuid", id);
|
||||
if (object) {
|
||||
object.position.copy(initialPosition);
|
||||
object.rotation.copy(initialRotation);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (!segmentPath || segmentPath.length === 0) {
|
||||
continue;
|
||||
}
|
||||
useEffect(() => {
|
||||
if (!isPlaying) {
|
||||
resetState();
|
||||
}
|
||||
|
||||
computedPath.push(
|
||||
...segmentPath.map(({ x, y, z }): [number, number, number] => [
|
||||
x,
|
||||
y + 0.1,
|
||||
z,
|
||||
])
|
||||
);
|
||||
} catch (error) {}
|
||||
}
|
||||
if (!navMesh || pathPoints.length < 2) return;
|
||||
|
||||
if (computedPath.length > 0) {
|
||||
setPath(computedPath);
|
||||
currentSegmentIndex.current = 0;
|
||||
}
|
||||
}, [selectedPoints, navMesh]);
|
||||
useFrame((_, delta) => {
|
||||
if (!scene || !id || path.length < 2) return;
|
||||
const [pickup, drop] = pathPoints.slice(-2);
|
||||
const object = scene.getObjectByProperty("uuid", id);
|
||||
if (!object) return;
|
||||
|
||||
// Find the object in the scene by its UUID
|
||||
const findObject = scene.getObjectByProperty("uuid", id);
|
||||
if (!findObject) return;
|
||||
const currentPosition = { x: object.position.x, y: object.position.y, z: object.position.z };
|
||||
|
||||
if (isPlaying) {
|
||||
const fast = speed;
|
||||
progressRef.current += delta * fast;
|
||||
const toPickupPath = computePath(currentPosition, pickup);
|
||||
const pickupToDropPath = computePath(pickup, drop);
|
||||
const dropToPickupPath = computePath(drop, pickup);
|
||||
|
||||
let coveredDistance = progressRef.current;
|
||||
let accumulatedDistance = 0;
|
||||
let index = 0;
|
||||
if (toPickupPath.length && pickupToDropPath.length && dropToPickupPath.length) {
|
||||
setPickupDropPath(pickupToDropPath);
|
||||
setDropPickupPath(dropToPickupPath);
|
||||
setToPickupPath(toPickupPath);
|
||||
setPath(toPickupPath);
|
||||
setCurrentPhase('initial');
|
||||
}
|
||||
}, [navMesh, pathPoints, hitCount, isPlaying]);
|
||||
|
||||
// Determine the current segment of the path
|
||||
while (
|
||||
index < distancesRef.current.length &&
|
||||
coveredDistance > accumulatedDistance + distancesRef.current[index]
|
||||
) {
|
||||
accumulatedDistance += distancesRef.current[index];
|
||||
index++;
|
||||
}
|
||||
useEffect(() => {
|
||||
if (path.length < 2) return;
|
||||
|
||||
if (index >= distancesRef.current.length) {
|
||||
progressRef.current = totalDistanceRef.current;
|
||||
let total = 0;
|
||||
const segmentDistances = path.slice(0, -1).map((point, i) => {
|
||||
const dist = new THREE.Vector3(...point).distanceTo(new THREE.Vector3(...path[i + 1]));
|
||||
total += dist;
|
||||
return dist;
|
||||
});
|
||||
|
||||
if (!isWaiting.current) {
|
||||
isWaiting.current = true; // Set waiting flag
|
||||
distancesRef.current = segmentDistances;
|
||||
totalDistanceRef.current = total;
|
||||
progressRef.current = 0;
|
||||
isWaiting.current = false;
|
||||
}, [path]);
|
||||
|
||||
if (movingForward.current) {
|
||||
// Moving forward: reached the end, wait for `delay`
|
||||
// console.log(
|
||||
// "Reached end position. Waiting for delay:",
|
||||
// delayTime,
|
||||
// "seconds"
|
||||
// );
|
||||
setTimeout(() => {
|
||||
// After delay, reverse direction
|
||||
movingForward.current = false;
|
||||
progressRef.current = 0; // Reset progress
|
||||
path.reverse(); // Reverse the path
|
||||
distancesRef.current.reverse();
|
||||
isWaiting.current = false; // Reset waiting flag
|
||||
}, delayTime * 1000); // Wait for `delay` seconds
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
useFrame((_, delta) => {
|
||||
if (!isPlaying || path.length < 2 || !scene || !id) return;
|
||||
|
||||
// Interpolate position within the current segment
|
||||
const start = new THREE.Vector3(...path[index]);
|
||||
const end = new THREE.Vector3(...path[index + 1]);
|
||||
const segmentDistance = distancesRef.current[index];
|
||||
const object = scene.getObjectByProperty("uuid", id);
|
||||
if (!object) return;
|
||||
|
||||
const t = Math.min(
|
||||
(coveredDistance - accumulatedDistance) / segmentDistance,
|
||||
1
|
||||
); // Clamp t to avoid overshooting
|
||||
const position = start.clone().lerp(end, t);
|
||||
findObject.position.copy(position);
|
||||
const speedFactor = speed;
|
||||
progressRef.current += delta * speedFactor;
|
||||
|
||||
// Rotate the object to face the direction of movement
|
||||
const direction = new THREE.Vector3().subVectors(end, start).normalize();
|
||||
const targetYRotation = Math.atan2(direction.x, direction.z);
|
||||
findObject.rotation.y += (targetYRotation - findObject.rotation.y) * 0.1;
|
||||
} else {
|
||||
findObject.position.copy(startPoint);
|
||||
}
|
||||
});
|
||||
let covered = progressRef.current;
|
||||
let accumulated = 0;
|
||||
let index = 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
{path.length > 0 && (
|
||||
<>
|
||||
<Line points={path} color="blue" lineWidth={3} />
|
||||
{selectedPoints.map((val: any, i: any) => (
|
||||
<mesh position={[val[0], val[1] + 1, val[2]]} key={i}>
|
||||
<sphereGeometry args={[50, 5, 5]} />
|
||||
<meshBasicMaterial color={"red"} />
|
||||
</mesh>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
while (
|
||||
index < distancesRef.current.length &&
|
||||
covered > accumulated + distancesRef.current[index]
|
||||
) {
|
||||
accumulated += distancesRef.current[index];
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index >= distancesRef.current.length) {
|
||||
progressRef.current = totalDistanceRef.current;
|
||||
|
||||
if (!isWaiting.current) {
|
||||
isWaiting.current = true;
|
||||
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
if (currentPhase === 'initial') {
|
||||
setPath(pickupDropPath);
|
||||
setCurrentPhase('loop');
|
||||
} else {
|
||||
setPath(prevPath =>
|
||||
prevPath === pickupDropPath ? dropPickupPath : pickupDropPath
|
||||
);
|
||||
}
|
||||
|
||||
progressRef.current = 0;
|
||||
isWaiting.current = false;
|
||||
}, bufferTime * 1000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const start = new THREE.Vector3(...path[index]);
|
||||
const end = new THREE.Vector3(...path[index + 1]);
|
||||
const dist = distancesRef.current[index];
|
||||
const t = THREE.MathUtils.clamp((covered - accumulated) / dist, 0, 1);
|
||||
const position = start.clone().lerp(end, t);
|
||||
|
||||
object.position.copy(position);
|
||||
|
||||
const direction = new THREE.Vector3().subVectors(end, start).normalize();
|
||||
const targetRotationY = Math.atan2(direction.x, direction.z);
|
||||
|
||||
let angleDifference = targetRotationY - object.rotation.y;
|
||||
angleDifference = ((angleDifference + Math.PI) % (Math.PI * 2)) - Math.PI;
|
||||
object.rotation.y += angleDifference * 0.1;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<group name="path-navigator-lines" visible={!isPlaying} >
|
||||
{toPickupPath.length > 0 && (
|
||||
<Line points={toPickupPath} color="blue" lineWidth={3} dashed dashSize={0.75} dashScale={2} />
|
||||
)}
|
||||
|
||||
{pickupDropPath.length > 0 && (
|
||||
<Line points={pickupDropPath} color="red" lineWidth={3} />
|
||||
)}
|
||||
|
||||
{dropPickupPath.length > 0 && (
|
||||
<Line points={dropPickupPath} color="red" lineWidth={3} />
|
||||
)}
|
||||
</group>
|
||||
);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ async function addAssetModel(
|
||||
socket: Socket<any>,
|
||||
selectedItem: any,
|
||||
setSelectedItem: any,
|
||||
setSimulationPaths: any,
|
||||
setSimulationStates: any,
|
||||
plane: Types.RefMesh,
|
||||
): Promise<void> {
|
||||
|
||||
@@ -65,7 +65,7 @@ async function addAssetModel(
|
||||
const cachedModel = THREE.Cache.get(selectedItem.id);
|
||||
if (cachedModel) {
|
||||
// console.log(`[Cache] Fetching ${selectedItem.name}`);
|
||||
handleModelLoad(cachedModel, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationPaths, socket);
|
||||
handleModelLoad(cachedModel, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationStates, socket);
|
||||
return;
|
||||
} else {
|
||||
const cachedModelBlob = await retrieveGLTF(selectedItem.id);
|
||||
@@ -78,7 +78,7 @@ async function addAssetModel(
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
THREE.Cache.remove(blobUrl);
|
||||
THREE.Cache.add(selectedItem.id, gltf);
|
||||
handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationPaths, socket);
|
||||
handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationStates, socket);
|
||||
},
|
||||
() => {
|
||||
TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup);
|
||||
@@ -90,7 +90,7 @@ async function addAssetModel(
|
||||
const modelBlob = await fetch(`${url_Backend_dwinzo}/api/v1/AssetFile/${selectedItem.id}`).then((res) => res.blob());
|
||||
await storeGLTF(selectedItem.id, modelBlob);
|
||||
THREE.Cache.add(selectedItem.id, gltf);
|
||||
await handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationPaths, socket);
|
||||
await handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationStates, socket);
|
||||
},
|
||||
() => {
|
||||
TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup);
|
||||
@@ -113,7 +113,7 @@ async function handleModelLoad(
|
||||
tempLoader: Types.RefMesh,
|
||||
isTempLoader: Types.RefBoolean,
|
||||
setFloorItems: Types.setFloorItemSetState,
|
||||
setSimulationPaths: any,
|
||||
setSimulationStates: any,
|
||||
socket: Socket<any>
|
||||
) {
|
||||
const model = gltf.scene.clone();
|
||||
@@ -171,7 +171,7 @@ async function handleModelLoad(
|
||||
}],
|
||||
triggers: [],
|
||||
connections: {
|
||||
source: { pathUUID: model.uuid, pointUUID: pointUUIDs[index] },
|
||||
source: { modelUUID: model.uuid, pointUUID: pointUUIDs[index] },
|
||||
targets: []
|
||||
}
|
||||
})),
|
||||
@@ -219,7 +219,7 @@ async function handleModelLoad(
|
||||
eventData.position = newFloorItem.position;
|
||||
eventData.rotation = [model.rotation.x, model.rotation.y, model.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
eventData as Types.ConveyorEventsSchema
|
||||
]);
|
||||
@@ -235,7 +235,7 @@ async function handleModelLoad(
|
||||
points: {
|
||||
uuid: pointUUID,
|
||||
position: res.points.position as [number, number, number],
|
||||
actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Start', start: {}, hitCount: 1, end: {}, buffer: 0 },
|
||||
actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: '', start: {}, hitCount: 1, end: {}, buffer: 0 },
|
||||
connections: { source: { modelUUID: model.uuid, pointUUID: pointUUID }, targets: [] },
|
||||
speed: 2,
|
||||
}
|
||||
@@ -281,13 +281,50 @@ async function handleModelLoad(
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
eventData as Types.VehicleEventsSchema
|
||||
]);
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
|
||||
} else {
|
||||
|
||||
// API
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// newFloorItem.modeluuid,
|
||||
// newFloorItem.modelname,
|
||||
// newFloorItem.modelfileID,
|
||||
// newFloorItem.position,
|
||||
// { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||
// false,
|
||||
// true,
|
||||
// );
|
||||
|
||||
// SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id
|
||||
};
|
||||
|
||||
|
||||
setFloorItems((prevItems) => {
|
||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
}
|
||||
|
||||
gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
|
||||
|
||||
@@ -10,7 +10,7 @@ async function DeleteFloorItems(
|
||||
itemsGroup: Types.RefGroup,
|
||||
hoveredDeletableFloorItem: Types.RefMesh,
|
||||
setFloorItems: Types.setFloorItemSetState,
|
||||
setSimulationPaths: any,
|
||||
setSimulationStates: any,
|
||||
socket: Socket<any>
|
||||
): Promise<void> {
|
||||
|
||||
@@ -76,7 +76,7 @@ async function DeleteFloorItems(
|
||||
}
|
||||
setFloorItems(updatedItems);
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => {
|
||||
const updatedEvents = (prevEvents || []).filter(event => event.modeluuid !== removedItem.modeluuid);
|
||||
return updatedEvents;
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
useRenderDistance,
|
||||
useselectedFloorItem,
|
||||
useSelectedItem,
|
||||
useSimulationPaths,
|
||||
useSimulationStates,
|
||||
useSocketStore,
|
||||
useToggleView,
|
||||
useTransformMode,
|
||||
@@ -65,7 +65,7 @@ const FloorItemsGroup = ({
|
||||
const { setselectedFloorItem } = useselectedFloorItem();
|
||||
const { activeTool } = useActiveTool();
|
||||
const { selectedItem, setSelectedItem } = useSelectedItem();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const { setLoadingProgress } = useLoadingProgress();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { socket } = useSocketStore();
|
||||
@@ -111,7 +111,7 @@ const FloorItemsGroup = ({
|
||||
gltfLoaderWorker.postMessage({ floorItems: data });
|
||||
} else {
|
||||
gltfLoaderWorker.postMessage({ floorItems: [] });
|
||||
loadInitialFloorItems(itemsGroup, setFloorItems, setSimulationPaths);
|
||||
loadInitialFloorItems(itemsGroup, setFloorItems, setSimulationStates);
|
||||
updateLoadingProgress(100);
|
||||
}
|
||||
});
|
||||
@@ -130,7 +130,7 @@ const FloorItemsGroup = ({
|
||||
updateLoadingProgress(progress);
|
||||
|
||||
if (loadedAssets === totalAssets) {
|
||||
loadInitialFloorItems(itemsGroup, setFloorItems, setSimulationPaths);
|
||||
loadInitialFloorItems(itemsGroup, setFloorItems, setSimulationStates);
|
||||
updateLoadingProgress(100);
|
||||
}
|
||||
});
|
||||
@@ -248,7 +248,7 @@ const FloorItemsGroup = ({
|
||||
itemsGroup,
|
||||
hoveredDeletableFloorItem,
|
||||
setFloorItems,
|
||||
setSimulationPaths,
|
||||
setSimulationStates,
|
||||
socket
|
||||
);
|
||||
}
|
||||
@@ -374,7 +374,7 @@ const FloorItemsGroup = ({
|
||||
socket,
|
||||
selectedItem,
|
||||
setSelectedItem,
|
||||
setSimulationPaths,
|
||||
setSimulationStates,
|
||||
plane
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,203 +12,189 @@ import CollabUserIcon from "./collabUserIcon";
|
||||
import { getAvatarColor } from "./users/functions/getAvatarColor";
|
||||
|
||||
const CamModelsGroup = () => {
|
||||
let navigate = useNavigate();
|
||||
const groupRef = useRef<THREE.Group>(null);
|
||||
const email = localStorage.getItem("email");
|
||||
const { activeUsers, setActiveUsers } = useActiveUsers();
|
||||
const { socket } = useSocketStore();
|
||||
const loader = new GLTFLoader();
|
||||
const dracoLoader = new DRACOLoader();
|
||||
const [cams, setCams] = useState<any[]>([]);
|
||||
const [models, setModels] = useState<Record<string, { targetPosition: THREE.Vector3; targetRotation: THREE.Euler }>>({});
|
||||
const navigate = useNavigate();
|
||||
const groupRef = useRef<THREE.Group>(null);
|
||||
const email = localStorage.getItem("email");
|
||||
const { activeUsers, setActiveUsers } = useActiveUsers();
|
||||
const { socket } = useSocketStore();
|
||||
|
||||
dracoLoader.setDecoderPath("three/examples/jsm/libs/draco/gltf/");
|
||||
loader.setDRACOLoader(dracoLoader);
|
||||
const loader = new GLTFLoader();
|
||||
const dracoLoader = new DRACOLoader();
|
||||
dracoLoader.setDecoderPath("three/examples/jsm/libs/draco/gltf/");
|
||||
loader.setDRACOLoader(dracoLoader);
|
||||
|
||||
useEffect(() => {
|
||||
if (!email) {
|
||||
navigate("/");
|
||||
}
|
||||
if (!socket) return;
|
||||
const organization = email!.split("@")[1].split(".")[0];
|
||||
const [cams, setCams] = useState<any[]>([]);
|
||||
const [models, setModels] = useState<Record<string, { targetPosition: THREE.Vector3; targetRotation: THREE.Euler }>>({});
|
||||
|
||||
socket.on("userConnectResponse", (data: any) => {
|
||||
if (!groupRef.current) return;
|
||||
if (data.data.userData.email === email) return;
|
||||
if (socket.id === data.socketId || organization !== data.organization)
|
||||
return;
|
||||
const dedupeCams = (cams: any[]) => {
|
||||
const seen = new Set();
|
||||
return cams.filter((cam) => {
|
||||
if (seen.has(cam.uuid)) return false;
|
||||
seen.add(cam.uuid);
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
const model = groupRef.current.getObjectByProperty(
|
||||
"uuid",
|
||||
data.data.userData._id
|
||||
);
|
||||
if (model) {
|
||||
groupRef.current.remove(model);
|
||||
}
|
||||
loader.load(camModel, (gltf) => {
|
||||
const newModel = gltf.scene.clone();
|
||||
newModel.uuid = data.data.userData._id;
|
||||
newModel.position.set(
|
||||
data.data.position.x,
|
||||
data.data.position.y,
|
||||
data.data.position.z
|
||||
);
|
||||
newModel.rotation.set(
|
||||
data.data.rotation.x,
|
||||
data.data.rotation.y,
|
||||
data.data.rotation.z
|
||||
);
|
||||
newModel.userData = data.data.userData;
|
||||
setCams((prev) => [...prev, newModel]);
|
||||
setActiveUsers([...activeUsers, data.data.userData]);
|
||||
});
|
||||
});
|
||||
const dedupeUsers = (users: any[]) => {
|
||||
const seen = new Set();
|
||||
return users.filter((user) => {
|
||||
if (seen.has(user._id)) return false;
|
||||
seen.add(user._id);
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
// socket.on("users:online", (data: any) => {
|
||||
// console.log('users online: ', data);
|
||||
// })
|
||||
useEffect(() => {
|
||||
if (!email) navigate("/");
|
||||
|
||||
socket.on("userDisConnectResponse", (data: any) => {
|
||||
if (!groupRef.current) return;
|
||||
if (socket.id === data.socketId || organization !== data.organization)
|
||||
return;
|
||||
if (!socket) return;
|
||||
const organization = email!.split("@")[1].split(".")[0];
|
||||
|
||||
setCams((prev) =>
|
||||
prev.filter((cam) => cam.uuid !== data.data.userData._id)
|
||||
);
|
||||
setActiveUsers(
|
||||
activeUsers.filter((user: any) => user._id !== data.data.userData._id)
|
||||
);
|
||||
});
|
||||
socket.on("userConnectResponse", (data: any) => {
|
||||
if (!groupRef.current) return;
|
||||
if (data.data.userData.email === email) return;
|
||||
if (socket.id === data.socketId || organization !== data.organization) return;
|
||||
|
||||
socket.on("cameraUpdateResponse", (data: any) => {
|
||||
if (
|
||||
!groupRef.current ||
|
||||
socket.id === data.socketId ||
|
||||
organization !== data.organization
|
||||
)
|
||||
return;
|
||||
const model = groupRef.current.getObjectByProperty("uuid", data.data.userData._id);
|
||||
if (model) {
|
||||
groupRef.current.remove(model);
|
||||
}
|
||||
|
||||
setModels((prev) => ({
|
||||
...prev,
|
||||
[data.data.userId]: {
|
||||
targetPosition: new THREE.Vector3(
|
||||
data.data.position.x,
|
||||
data.data.position.y,
|
||||
data.data.position.z
|
||||
),
|
||||
targetRotation: new THREE.Euler(
|
||||
data.data.rotation.x,
|
||||
data.data.rotation.y,
|
||||
data.data.rotation.z
|
||||
),
|
||||
},
|
||||
}));
|
||||
});
|
||||
loader.load(camModel, (gltf) => {
|
||||
const newModel = gltf.scene.clone();
|
||||
newModel.uuid = data.data.userData._id;
|
||||
newModel.position.set(
|
||||
data.data.position.x,
|
||||
data.data.position.y,
|
||||
data.data.position.z
|
||||
);
|
||||
newModel.rotation.set(
|
||||
data.data.rotation.x,
|
||||
data.data.rotation.y,
|
||||
data.data.rotation.z
|
||||
);
|
||||
newModel.userData = data.data.userData;
|
||||
|
||||
return () => {
|
||||
socket.off("userConnectRespones");
|
||||
socket.off("userDisConnectRespones");
|
||||
socket.off("cameraUpdateResponse");
|
||||
};
|
||||
}, [socket]);
|
||||
setCams((prev) => dedupeCams([...prev, newModel]));
|
||||
setActiveUsers((prev: any) =>
|
||||
dedupeUsers([...prev, data.data.userData])
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("userDisConnectResponse", (data: any) => {
|
||||
if (!groupRef.current) return;
|
||||
if (socket.id === data.socketId || organization !== data.organization) return;
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log(activeUsers);
|
||||
// }, [activeUsers])
|
||||
setCams((prev) =>
|
||||
prev.filter((cam) => cam.uuid !== data.data.userData._id)
|
||||
);
|
||||
setActiveUsers((prev: any) =>
|
||||
prev.filter((user: any) => user._id !== data.data.userData._id)
|
||||
);
|
||||
});
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log(models);
|
||||
// }, [models])
|
||||
socket.on("cameraUpdateResponse", (data: any) => {
|
||||
if (
|
||||
!groupRef.current ||
|
||||
socket.id === data.socketId ||
|
||||
organization !== data.organization
|
||||
)
|
||||
return;
|
||||
|
||||
useFrame(() => {
|
||||
if (!groupRef.current) return;
|
||||
Object.keys(models).forEach((uuid) => {
|
||||
const model = groupRef.current!.getObjectByProperty("uuid", uuid);
|
||||
if (!model) return;
|
||||
setModels((prev) => ({
|
||||
...prev,
|
||||
[data.data.userId]: {
|
||||
targetPosition: new THREE.Vector3(
|
||||
data.data.position.x,
|
||||
data.data.position.y,
|
||||
data.data.position.z
|
||||
),
|
||||
targetRotation: new THREE.Euler(
|
||||
data.data.rotation.x,
|
||||
data.data.rotation.y,
|
||||
data.data.rotation.z
|
||||
),
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
const { targetPosition, targetRotation } = models[uuid];
|
||||
model.position.lerp(targetPosition, 0.1);
|
||||
model.rotation.x = THREE.MathUtils.lerp(
|
||||
model.rotation.x,
|
||||
targetRotation.x,
|
||||
0.1
|
||||
);
|
||||
model.rotation.y = THREE.MathUtils.lerp(
|
||||
model.rotation.y,
|
||||
targetRotation.y,
|
||||
0.1
|
||||
);
|
||||
model.rotation.z = THREE.MathUtils.lerp(
|
||||
model.rotation.z,
|
||||
targetRotation.z,
|
||||
0.1
|
||||
);
|
||||
});
|
||||
});
|
||||
return () => {
|
||||
socket.off("userConnectResponse");
|
||||
socket.off("userDisConnectResponse");
|
||||
socket.off("cameraUpdateResponse");
|
||||
};
|
||||
}, [socket]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!groupRef.current) return;
|
||||
const organization = email!.split("@")[1].split(".")[0];
|
||||
getActiveUsersData(organization).then((data) => {
|
||||
const filteredData = data.cameraDatas.filter(
|
||||
(camera: any) => camera.userData.email !== email
|
||||
);
|
||||
let a: any = [];
|
||||
if (filteredData.length > 0) {
|
||||
loader.load(camModel, (gltf) => {
|
||||
const newCams = filteredData.map((cam: any) => {
|
||||
const newModel = gltf.scene.clone();
|
||||
newModel.uuid = cam.userData._id;
|
||||
newModel.position.set(
|
||||
cam.position.x,
|
||||
cam.position.y,
|
||||
cam.position.z
|
||||
);
|
||||
newModel.rotation.set(
|
||||
cam.rotation.x,
|
||||
cam.rotation.y,
|
||||
cam.rotation.z
|
||||
);
|
||||
newModel.userData = cam.userData;
|
||||
a.push(cam.userData);
|
||||
return newModel;
|
||||
});
|
||||
setActiveUsers(a);
|
||||
setCams((prev) => [...prev, ...newCams]);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
useFrame(() => {
|
||||
if (!groupRef.current) return;
|
||||
Object.keys(models).forEach((uuid) => {
|
||||
const model = groupRef.current!.getObjectByProperty("uuid", uuid);
|
||||
if (!model) return;
|
||||
|
||||
return (
|
||||
<group ref={groupRef} name="Cam-Model-Group">
|
||||
{cams.map((cam, index) => (
|
||||
<primitive key={index} object={cam}>
|
||||
<Html
|
||||
as="div"
|
||||
center
|
||||
zIndexRange={[1, 0]}
|
||||
sprite
|
||||
style={{
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
fontFamily: "Arial, sans-serif",
|
||||
}}
|
||||
position={[-0.015, 0, 0.7]}
|
||||
>
|
||||
<CollabUserIcon
|
||||
userImage={""}
|
||||
userName={cam.userData.userName}
|
||||
index={index}
|
||||
color={getAvatarColor(index)}
|
||||
/>
|
||||
</Html>
|
||||
</primitive>
|
||||
))}
|
||||
</group>
|
||||
);
|
||||
const { targetPosition, targetRotation } = models[uuid];
|
||||
model.position.lerp(targetPosition, 0.1);
|
||||
model.rotation.x = THREE.MathUtils.lerp(model.rotation.x, targetRotation.x, 0.1);
|
||||
model.rotation.y = THREE.MathUtils.lerp(model.rotation.y, targetRotation.y, 0.1);
|
||||
model.rotation.z = THREE.MathUtils.lerp(model.rotation.z, targetRotation.z, 0.1);
|
||||
});
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!groupRef.current) return;
|
||||
const organization = email!.split("@")[1].split(".")[0];
|
||||
|
||||
getActiveUsersData(organization).then((data) => {
|
||||
const filteredData = data.cameraDatas.filter(
|
||||
(camera: any) => camera.userData.email !== email
|
||||
);
|
||||
|
||||
if (filteredData.length > 0) {
|
||||
loader.load(camModel, (gltf) => {
|
||||
const newCams = filteredData.map((cam: any) => {
|
||||
const newModel = gltf.scene.clone();
|
||||
newModel.uuid = cam.userData._id;
|
||||
newModel.position.set(cam.position.x, cam.position.y, cam.position.z);
|
||||
newModel.rotation.set(cam.rotation.x, cam.rotation.y, cam.rotation.z);
|
||||
newModel.userData = cam.userData;
|
||||
return newModel;
|
||||
});
|
||||
|
||||
const users = filteredData.map((cam: any) => cam.userData);
|
||||
setActiveUsers((prev: any) => dedupeUsers([...prev, ...users]));
|
||||
setCams((prev) => dedupeCams([...prev, ...newCams]));
|
||||
});
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<group ref={groupRef} name="Cam-Model-Group">
|
||||
{cams.map((cam, index) => (
|
||||
<primitive key={cam.uuid} object={cam}>
|
||||
<Html
|
||||
as="div"
|
||||
center
|
||||
zIndexRange={[1, 0]}
|
||||
sprite
|
||||
style={{
|
||||
color: "white",
|
||||
textAlign: "center",
|
||||
fontFamily: "Arial, sans-serif",
|
||||
}}
|
||||
position={[-0.015, 0, 0.7]}
|
||||
>
|
||||
<CollabUserIcon
|
||||
userImage={""}
|
||||
userName={cam.userData.userName}
|
||||
index={index}
|
||||
color={getAvatarColor(index)}
|
||||
/>
|
||||
</Html>
|
||||
</primitive>
|
||||
))}
|
||||
</group>
|
||||
);
|
||||
};
|
||||
|
||||
export default CamModelsGroup;
|
||||
|
||||
@@ -20,7 +20,24 @@ const CollabUserIcon: React.FC<CollabUserIconProps> = ({
|
||||
{userImage ? (
|
||||
<img className="user-image" src={userImage} alt={userName} />
|
||||
) : (
|
||||
<CustomAvatar name={userName} index={index} />
|
||||
<CustomAvatar name={userName} index={index} color={color} />
|
||||
// <div
|
||||
// className="user-image"
|
||||
// style={{
|
||||
// lineHeight: "30px",
|
||||
// textTransform: "uppercase",
|
||||
// textAlign: "center",
|
||||
// fontSize: "16px",
|
||||
// borderRadius: "50%",
|
||||
// backgroundColor: color,
|
||||
// overflow: "hidden",
|
||||
// backgroundSize: "cover",
|
||||
// backgroundPosition: "center",
|
||||
// color: "white",
|
||||
// fontWeight: "bold",
|
||||
// }}>
|
||||
// {userName[0]}
|
||||
// </div>
|
||||
)}
|
||||
</div>
|
||||
<div className="user-name" style={{ backgroundColor: color }}>
|
||||
|
||||
@@ -233,7 +233,7 @@ export default function SocketResponses({
|
||||
}
|
||||
|
||||
} else if (data.message === "Model updated successfully") {
|
||||
itemsGroup.current.children.forEach((item: THREE.Group) => {
|
||||
itemsGroup.current?.children.forEach((item: THREE.Group) => {
|
||||
if (item.uuid === data.data.modeluuid) {
|
||||
item.position.set(...data.data.position as [number, number, number]);
|
||||
item.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z);
|
||||
|
||||
@@ -7,6 +7,7 @@ interface AvatarProps {
|
||||
size?: number;
|
||||
index?: number;
|
||||
textColor?: string;
|
||||
color?: string; // Optional color prop for future use
|
||||
}
|
||||
|
||||
const CustomAvatar: React.FC<AvatarProps> = ({
|
||||
@@ -14,6 +15,7 @@ const CustomAvatar: React.FC<AvatarProps> = ({
|
||||
size = 100,
|
||||
index = 0,
|
||||
textColor = "#ffffff",
|
||||
color, // Optional color prop for future use
|
||||
}) => {
|
||||
const [imageSrc, setImageSrc] = useState<string | null>(null);
|
||||
|
||||
@@ -26,7 +28,7 @@ const CustomAvatar: React.FC<AvatarProps> = ({
|
||||
const initials = getInitials(name); // Convert name to initials if needed
|
||||
|
||||
// Draw background
|
||||
ctx.fillStyle = getAvatarColor(index);
|
||||
ctx.fillStyle = color || getAvatarColor(index); // Use color prop or generate color based on index
|
||||
ctx.fillRect(0, 0, size, size);
|
||||
|
||||
// Draw initials
|
||||
@@ -40,7 +42,7 @@ const CustomAvatar: React.FC<AvatarProps> = ({
|
||||
const dataURL = canvas.toDataURL("image/png");
|
||||
setImageSrc(dataURL);
|
||||
}
|
||||
}, [name, size, textColor]);
|
||||
}, [name, size, textColor, index]);
|
||||
|
||||
if (!imageSrc) {
|
||||
return null; // Return null while the image is being generated
|
||||
@@ -53,6 +55,18 @@ const CustomAvatar: React.FC<AvatarProps> = ({
|
||||
alt="User Avatar"
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
/>
|
||||
// <div
|
||||
// className="user-image"
|
||||
// style={{
|
||||
// width: size,
|
||||
// height: size,
|
||||
// borderRadius: "50%",
|
||||
// overflow: "hidden",
|
||||
// backgroundSize: "cover",
|
||||
// backgroundPosition: "center",
|
||||
// }}>
|
||||
// {name[0]}
|
||||
// </div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { getFloorAssets } from '../../../services/factoryBuilder/assest/floorAss
|
||||
async function loadInitialFloorItems(
|
||||
itemsGroup: Types.RefGroup,
|
||||
setFloorItems: Types.setFloorItemSetState,
|
||||
setSimulationPaths: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => void
|
||||
setSimulationStates: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => void
|
||||
): Promise<void> {
|
||||
if (!itemsGroup.current) return;
|
||||
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||
@@ -71,7 +71,7 @@ async function loadInitialFloorItems(
|
||||
const cachedModel = THREE.Cache.get(item.modelfileID!);
|
||||
if (cachedModel) {
|
||||
// console.log(`[Cache] Fetching ${item.modelname}`);
|
||||
processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems, setSimulationPaths);
|
||||
processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems, setSimulationStates);
|
||||
modelsLoaded++;
|
||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
||||
return;
|
||||
@@ -88,7 +88,7 @@ async function loadInitialFloorItems(
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
THREE.Cache.remove(blobUrl);
|
||||
THREE.Cache.add(item.modelfileID!, gltf);
|
||||
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, setSimulationPaths);
|
||||
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, setSimulationStates);
|
||||
modelsLoaded++;
|
||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
||||
},
|
||||
@@ -111,7 +111,7 @@ async function loadInitialFloorItems(
|
||||
const modelBlob = await fetch(modelUrl).then((res) => res.blob());
|
||||
await storeGLTF(item.modelfileID!, modelBlob);
|
||||
THREE.Cache.add(item.modelfileID!, gltf);
|
||||
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, setSimulationPaths);
|
||||
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, setSimulationStates);
|
||||
modelsLoaded++;
|
||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
||||
},
|
||||
@@ -137,8 +137,8 @@ async function loadInitialFloorItems(
|
||||
},
|
||||
]);
|
||||
|
||||
if (item.eventData) {
|
||||
processEventData(item, setSimulationPaths);
|
||||
if (item.eventData || item.modelfileID === '67e3db95c2e8f37134526fb2') {
|
||||
processEventData(item, setSimulationStates);
|
||||
}
|
||||
|
||||
modelsLoaded++;
|
||||
@@ -157,7 +157,7 @@ function processLoadedModel(
|
||||
item: Types.EventData,
|
||||
itemsGroup: Types.RefGroup,
|
||||
setFloorItems: Types.setFloorItemSetState,
|
||||
setSimulationPaths: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => void
|
||||
setSimulationStates: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => void
|
||||
) {
|
||||
const model = gltf;
|
||||
model.uuid = item.modeluuid;
|
||||
@@ -192,15 +192,15 @@ function processLoadedModel(
|
||||
},
|
||||
]);
|
||||
|
||||
if (item.eventData) {
|
||||
processEventData(item, setSimulationPaths);
|
||||
if (item.eventData || item.modelfileID === '67e3db95c2e8f37134526fb2') {
|
||||
processEventData(item, setSimulationStates);
|
||||
}
|
||||
|
||||
gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: 'power2.out' });
|
||||
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out' });
|
||||
}
|
||||
|
||||
function processEventData(item: Types.EventData, setSimulationPaths: any) {
|
||||
function processEventData(item: Types.EventData, setSimulationStates: any) {
|
||||
|
||||
if (item.eventData?.type === 'Conveyor') {
|
||||
|
||||
@@ -210,23 +210,46 @@ function processEventData(item: Types.EventData, setSimulationPaths: any) {
|
||||
data.position = item.position;
|
||||
data.rotation = [item.rotation.x, item.rotation.y, item.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
data as Types.ConveyorEventsSchema
|
||||
]);
|
||||
|
||||
} else {
|
||||
} else if (item.eventData?.type === 'Vehicle') {
|
||||
|
||||
const data: any = item.eventData;
|
||||
data.modeluuid = item.modeluuid;
|
||||
data.modelName = item.modelname;
|
||||
data.position = item.position;
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
data as Types.VehicleEventsSchema
|
||||
]);
|
||||
|
||||
} else if (item.modelfileID === '67e3db95c2e8f37134526fb2') {
|
||||
|
||||
const pointUUID = THREE.MathUtils.generateUUID();
|
||||
const pointPosition = new THREE.Vector3(0, 1.75, 0);
|
||||
|
||||
const staticMachine: Types.StaticMachineEventsSchema = {
|
||||
modeluuid: item.modeluuid,
|
||||
modelName: item.modelname,
|
||||
type: "StaticMachine",
|
||||
points: {
|
||||
uuid: pointUUID,
|
||||
position: [pointPosition.x, pointPosition.y, pointPosition.z],
|
||||
actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', buffer: 'Inherit', material: 'Inherit', isUsed: false },
|
||||
triggers: { uuid: THREE.MathUtils.generateUUID(), name: 'Trigger 1', type: 'OnComplete' },
|
||||
connections: { source: { modelUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] },
|
||||
},
|
||||
position: item.position
|
||||
};
|
||||
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
staticMachine as Types.StaticMachineEventsSchema
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as THREE from "three";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { toast } from "react-toastify";
|
||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
@@ -10,7 +10,7 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
||||
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
||||
const { toggleView } = useToggleView();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore()
|
||||
@@ -151,7 +151,7 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | undefined = simulationPaths.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | undefined = simulationStates.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "default";
|
||||
@@ -183,7 +183,7 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
||||
: [defaultAction],
|
||||
triggers: (eventData as Types.ConveyorEventsSchema)?.points[index].triggers,
|
||||
connections: {
|
||||
source: { pathUUID: obj.uuid, pointUUID },
|
||||
source: { modelUUID: obj.uuid, pointUUID },
|
||||
targets: []
|
||||
}
|
||||
};
|
||||
@@ -224,17 +224,17 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
eventData: { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed },
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
const newEventData: any = { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed };
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
newEventData as Types.ConveyorEventsSchema
|
||||
]);
|
||||
@@ -277,7 +277,6 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
||||
const backendEventData = {
|
||||
type: 'Vehicle',
|
||||
points: createVehiclePoint(),
|
||||
speed: (eventData as Types.VehicleEventsSchema)?.points.speed
|
||||
};
|
||||
|
||||
// API
|
||||
@@ -305,16 +304,16 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
newEventData as Types.VehicleEventsSchema
|
||||
]);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as THREE from "three";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { toast } from "react-toastify";
|
||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
@@ -11,7 +11,7 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
||||
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
||||
const { toggleView } = useToggleView();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore();
|
||||
@@ -132,7 +132,7 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | undefined = simulationPaths.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | undefined = simulationStates.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "default";
|
||||
@@ -165,7 +165,7 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
||||
: [defaultAction],
|
||||
triggers: (eventData as Types.ConveyorEventsSchema)?.points[index].triggers,
|
||||
connections: {
|
||||
source: { pathUUID: obj.uuid, pointUUID },
|
||||
source: { modelUUID: newFloorItem.modeluuid, pointUUID },
|
||||
targets: []
|
||||
}
|
||||
};
|
||||
@@ -206,17 +206,17 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
eventData: { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed },
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
const newEventData: any = { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed };
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
newEventData as Types.ConveyorEventsSchema
|
||||
]);
|
||||
@@ -286,16 +286,16 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
newEventData as Types.VehicleEventsSchema
|
||||
]);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as THREE from "three";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||
import { toast } from "react-toastify";
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
@@ -12,7 +12,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||
|
||||
const { toggleView } = useToggleView();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore();
|
||||
const itemsData = useRef<Types.FloorItems>([]);
|
||||
@@ -180,12 +180,12 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | undefined = simulationPaths.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | undefined = simulationStates.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "default";
|
||||
|
||||
if (eventData) {
|
||||
if (eventData && eventData.type !== 'StaticMachine') {
|
||||
if (eventData.type === 'Conveyor' && eventData) {
|
||||
|
||||
const backendEventData = {
|
||||
@@ -205,7 +205,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// backendEventData
|
||||
// { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed }
|
||||
// );
|
||||
|
||||
//SOCKET
|
||||
@@ -219,17 +219,17 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
eventData: { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed },
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
const newEventData: any = { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed };
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => {
|
||||
const updatedEvents = (prevEvents || []).map(event =>
|
||||
event.modeluuid === newFloorItem.modeluuid
|
||||
? { ...event, ...newEventData }
|
||||
@@ -257,7 +257,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// false,
|
||||
// true,
|
||||
// backendEventData
|
||||
// { type: backendEventData.type, points: backendEventData.points }
|
||||
// );
|
||||
|
||||
//SOCKET
|
||||
@@ -271,16 +271,16 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => {
|
||||
const updatedEvents = (prevEvents || []).map(event =>
|
||||
event.modeluuid === newFloorItem.modeluuid
|
||||
? { ...event, ...newEventData }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as THREE from "three";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||
import { toast } from "react-toastify";
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
@@ -13,7 +13,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||
|
||||
const { toggleView } = useToggleView();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore();
|
||||
const itemsData = useRef<Types.FloorItems>([]);
|
||||
@@ -184,12 +184,12 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | undefined = simulationPaths.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema | undefined = simulationStates.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "default";
|
||||
|
||||
if (eventData) {
|
||||
if (eventData && eventData.type !== 'StaticMachine') {
|
||||
if (eventData.type === 'Conveyor' && eventData) {
|
||||
|
||||
const backendEventData = {
|
||||
@@ -209,7 +209,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// false,
|
||||
// true,
|
||||
// backendEventData
|
||||
// { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed }
|
||||
// );
|
||||
|
||||
//SOCKET
|
||||
@@ -223,17 +223,17 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
eventData: { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed },
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
const newEventData: any = { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed };
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => {
|
||||
const updatedEvents = (prevEvents || []).map(event =>
|
||||
event.modeluuid === newFloorItem.modeluuid
|
||||
? { ...event, ...newEventData }
|
||||
@@ -262,7 +262,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// false,
|
||||
// true,
|
||||
// backendEventData
|
||||
// { type: backendEventData.type, points: backendEventData.points }
|
||||
// );
|
||||
|
||||
//SOCKET
|
||||
@@ -276,16 +276,16 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => {
|
||||
const updatedEvents = (prevEvents || []).map(event =>
|
||||
event.modeluuid === newFloorItem.modeluuid
|
||||
? { ...event, ...newEventData }
|
||||
@@ -299,7 +299,6 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
//REST
|
||||
|
||||
// await setFloorItemApi(
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox";
|
||||
import { SelectionHelper } from "./selectionHelper";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import BoundingBox from "./boundingBoxHelper";
|
||||
import { toast } from "react-toastify";
|
||||
// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
|
||||
@@ -20,7 +20,7 @@ const SelectionControls: React.FC = () => {
|
||||
const itemsGroupRef = useRef<THREE.Group | undefined>(undefined);
|
||||
const selectionGroup = useRef() as Types.RefGroup;
|
||||
const { toggleView } = useToggleView();
|
||||
const { setSimulationPaths } = useSimulationPaths();
|
||||
const { setSimulationStates } = useSimulationStates();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const [movedObjects, setMovedObjects] = useState<THREE.Object3D[]>([]);
|
||||
const [rotatedObjects, setRotatedObjects] = useState<THREE.Object3D[]>([]);
|
||||
@@ -240,7 +240,7 @@ const SelectionControls: React.FC = () => {
|
||||
}
|
||||
});
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||
setSimulationStates((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => {
|
||||
const updatedEvents = (prevEvents || []).filter(event => event.modeluuid !== selectedMesh.uuid);
|
||||
return updatedEvents;
|
||||
});
|
||||
|
||||
@@ -53,8 +53,8 @@ import { findEnvironment } from "../../../services/factoryBuilder/environment/fi
|
||||
import Layer2DVisibility from "../../builder/geomentries/layers/layer2DVisibility";
|
||||
import DrieHtmlTemp from "../mqttTemp/drieHtmlTemp";
|
||||
import ZoneGroup from "../../builder/groups/zoneGroup";
|
||||
import Agv from "../../builder/agv/agv";
|
||||
import useModuleStore from "../../../store/useModuleStore";
|
||||
import NavMeshCreator from "../../builder/agv/navMeshCreator";
|
||||
|
||||
export default function World() {
|
||||
const state = useThree<Types.ThreeState>(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
|
||||
@@ -368,7 +368,7 @@ export default function World() {
|
||||
|
||||
{/* <DrieHtmlTemp itemsGroup={itemsGroup} /> */}
|
||||
|
||||
{activeModule === "simulation" && <Agv lines={lines} />}
|
||||
<NavMeshCreator lines={lines} />
|
||||
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useFloorItems, useSimulationPaths } from '../../../store/store';
|
||||
import { useFloorItems, useSimulationStates } from '../../../store/store';
|
||||
import * as THREE from 'three';
|
||||
import * as Types from '../../../types/world/worldTypes';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
function Behaviour() {
|
||||
const { setSimulationPaths } = useSimulationPaths();
|
||||
const { setSimulationStates } = useSimulationStates();
|
||||
const { floorItems } = useFloorItems();
|
||||
|
||||
useEffect(() => {
|
||||
const newPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[] = [];
|
||||
const newPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[] = [];
|
||||
|
||||
// floorItems.forEach((item: Types.FloorItemType) => {
|
||||
// if (item.modelfileID === "672a090f80d91ac979f4d0bd") {
|
||||
@@ -31,7 +31,7 @@ function Behaviour() {
|
||||
// rotation: [0, 0, 0],
|
||||
// actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
|
||||
// triggers: [],
|
||||
// connections: { source: { pathUUID: item.modeluuid, pointUUID: point1UUID }, targets: [] },
|
||||
// connections: { source: { modelUUID: item.modeluuid, pointUUID: point1UUID }, targets: [] },
|
||||
// },
|
||||
// {
|
||||
// uuid: middlePointUUID,
|
||||
@@ -39,7 +39,7 @@ function Behaviour() {
|
||||
// rotation: [0, 0, 0],
|
||||
// actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
|
||||
// triggers: [],
|
||||
// connections: { source: { pathUUID: item.modeluuid, pointUUID: middlePointUUID }, targets: [] },
|
||||
// connections: { source: { modelUUID: item.modeluuid, pointUUID: middlePointUUID }, targets: [] },
|
||||
// },
|
||||
// {
|
||||
// uuid: point2UUID,
|
||||
@@ -47,7 +47,7 @@ function Behaviour() {
|
||||
// rotation: [0, 0, 0],
|
||||
// actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
|
||||
// triggers: [],
|
||||
// connections: { source: { pathUUID: item.modeluuid, pointUUID: point2UUID }, targets: [] },
|
||||
// connections: { source: { modelUUID: item.modeluuid, pointUUID: point2UUID }, targets: [] },
|
||||
// },
|
||||
// ],
|
||||
// position: [...item.position],
|
||||
@@ -68,7 +68,7 @@ function Behaviour() {
|
||||
// uuid: pointUUID,
|
||||
// position: [pointPosition.x, pointPosition.y, pointPosition.z],
|
||||
// actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Start', start: {}, hitCount: 1, end: {}, buffer: 0 },
|
||||
// connections: { source: { pathUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] },
|
||||
// connections: { source: { modelUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] },
|
||||
// speed: 2,
|
||||
// },
|
||||
// position: [...item.position],
|
||||
@@ -78,7 +78,7 @@ function Behaviour() {
|
||||
// }
|
||||
// });
|
||||
|
||||
// setSimulationPaths(newPaths);
|
||||
// setSimulationStates(newPaths);
|
||||
// console.log('floorItems: ', floorItems);
|
||||
}, [floorItems]);
|
||||
|
||||
|
||||
@@ -3,19 +3,21 @@ import React, { useEffect, useState } from 'react';
|
||||
import * as THREE from 'three';
|
||||
import * as Types from '../../../types/world/worldTypes';
|
||||
import { QuadraticBezierLine } from '@react-three/drei';
|
||||
import { useIsConnecting, useSimulationPaths } from '../../../store/store';
|
||||
import { useIsConnecting, useSimulationStates, useSocketStore } from '../../../store/store';
|
||||
import useModuleStore from '../../../store/useModuleStore';
|
||||
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
||||
import { setEventApi } from '../../../services/factoryBuilder/assest/floorAsset/setEventsApt';
|
||||
|
||||
function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject<THREE.Group> }) {
|
||||
const { activeModule } = useModuleStore();
|
||||
const { gl, raycaster, scene, pointer, camera } = useThree();
|
||||
const { setIsConnecting } = useIsConnecting();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { socket } = useSocketStore();
|
||||
|
||||
const [firstSelected, setFirstSelected] = useState<{
|
||||
pathUUID: string;
|
||||
modelUUID: string;
|
||||
sphereUUID: string;
|
||||
position: THREE.Vector3;
|
||||
isCorner: boolean;
|
||||
@@ -24,26 +26,26 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
const [helperlineColor, setHelperLineColor] = useState<string>('red');
|
||||
|
||||
const updatePathConnections = (
|
||||
fromPathUUID: string,
|
||||
fromModelUUID: string,
|
||||
fromPointUUID: string,
|
||||
toPathUUID: string,
|
||||
toModelUUID: string,
|
||||
toPointUUID: string
|
||||
) => {
|
||||
const updatedPaths = simulationPaths.map(path => {
|
||||
const updatedPaths = simulationStates.map(path => {
|
||||
if (path.type === 'Conveyor') {
|
||||
if (path.modeluuid === fromPathUUID) {
|
||||
if (path.modeluuid === fromModelUUID) {
|
||||
return {
|
||||
...path,
|
||||
points: path.points.map(point => {
|
||||
if (point.uuid === fromPointUUID) {
|
||||
const newTarget = {
|
||||
pathUUID: toPathUUID,
|
||||
modelUUID: toModelUUID,
|
||||
pointUUID: toPointUUID
|
||||
};
|
||||
const existingTargets = point.connections.targets || [];
|
||||
|
||||
if (!existingTargets.some(target =>
|
||||
target.pathUUID === newTarget.pathUUID &&
|
||||
target.modelUUID === newTarget.modelUUID &&
|
||||
target.pointUUID === newTarget.pointUUID
|
||||
)) {
|
||||
return {
|
||||
@@ -59,19 +61,19 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
})
|
||||
};
|
||||
}
|
||||
else if (path.modeluuid === toPathUUID) {
|
||||
else if (path.modeluuid === toModelUUID) {
|
||||
return {
|
||||
...path,
|
||||
points: path.points.map(point => {
|
||||
if (point.uuid === toPointUUID) {
|
||||
const reverseTarget = {
|
||||
pathUUID: fromPathUUID,
|
||||
modelUUID: fromModelUUID,
|
||||
pointUUID: fromPointUUID
|
||||
};
|
||||
const existingTargets = point.connections.targets || [];
|
||||
|
||||
if (!existingTargets.some(target =>
|
||||
target.pathUUID === reverseTarget.pathUUID &&
|
||||
target.modelUUID === reverseTarget.modelUUID &&
|
||||
target.pointUUID === reverseTarget.pointUUID
|
||||
)) {
|
||||
return {
|
||||
@@ -88,18 +90,17 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
};
|
||||
}
|
||||
}
|
||||
// In the updatePathConnections function, modify the Vehicle handling section:
|
||||
else if (path.type === 'Vehicle') {
|
||||
// Handle outgoing connections from Vehicle
|
||||
if (path.modeluuid === fromPathUUID && path.points.uuid === fromPointUUID) {
|
||||
if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
|
||||
const newTarget = {
|
||||
pathUUID: toPathUUID,
|
||||
modelUUID: toModelUUID,
|
||||
pointUUID: toPointUUID
|
||||
};
|
||||
const existingTargets = path.points.connections.targets || [];
|
||||
|
||||
// Check if target is a Conveyor
|
||||
const toPath = simulationPaths.find(p => p.modeluuid === toPathUUID);
|
||||
const toPath = simulationStates.find(p => p.modeluuid === toModelUUID);
|
||||
if (toPath?.type !== 'Conveyor') {
|
||||
console.log("Vehicle can only connect to Conveyors");
|
||||
return path;
|
||||
@@ -112,7 +113,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
}
|
||||
|
||||
if (!existingTargets.some(target =>
|
||||
target.pathUUID === newTarget.pathUUID &&
|
||||
target.modelUUID === newTarget.modelUUID &&
|
||||
target.pointUUID === newTarget.pointUUID
|
||||
)) {
|
||||
return {
|
||||
@@ -128,15 +129,15 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
}
|
||||
}
|
||||
// Handle incoming connections to Vehicle
|
||||
else if (path.modeluuid === toPathUUID && path.points.uuid === toPointUUID) {
|
||||
else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
|
||||
const reverseTarget = {
|
||||
pathUUID: fromPathUUID,
|
||||
modelUUID: fromModelUUID,
|
||||
pointUUID: fromPointUUID
|
||||
};
|
||||
const existingTargets = path.points.connections.targets || [];
|
||||
|
||||
// Check if source is a Conveyor
|
||||
const fromPath = simulationPaths.find(p => p.modeluuid === fromPathUUID);
|
||||
const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID);
|
||||
if (fromPath?.type !== 'Conveyor') {
|
||||
console.log("Vehicle can only connect to Conveyors");
|
||||
return path;
|
||||
@@ -149,7 +150,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
}
|
||||
|
||||
if (!existingTargets.some(target =>
|
||||
target.pathUUID === reverseTarget.pathUUID &&
|
||||
target.modelUUID === reverseTarget.modelUUID &&
|
||||
target.pointUUID === reverseTarget.pointUUID
|
||||
)) {
|
||||
return {
|
||||
@@ -166,14 +167,139 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
}
|
||||
return path;
|
||||
}
|
||||
// else if (path.type === 'StaticMachine') {
|
||||
// if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
|
||||
// const newTarget = {
|
||||
// modelUUID: toModelUUID,
|
||||
// pointUUID: toPointUUID
|
||||
// };
|
||||
// const existingTargets = path.points.connections.targets || [];
|
||||
|
||||
// // Check if target is an ArmBot
|
||||
// const toPath = simulationStates.find(p => p.modeluuid === toModelUUID);
|
||||
// if (toPath?.type !== 'ArmBot') {
|
||||
// console.log("StaticMachine can only connect to ArmBot");
|
||||
// return path;
|
||||
// }
|
||||
|
||||
// // Check if already has a connection
|
||||
// if (existingTargets.length >= 1) {
|
||||
// console.log("StaticMachine can have only one connection");
|
||||
// return path;
|
||||
// }
|
||||
|
||||
// if (!existingTargets.some(target =>
|
||||
// target.modelUUID === newTarget.modelUUID &&
|
||||
// target.pointUUID === newTarget.pointUUID
|
||||
// )) {
|
||||
// return {
|
||||
// ...path,
|
||||
// points: {
|
||||
// ...path.points,
|
||||
// connections: {
|
||||
// ...path.points.connections,
|
||||
// targets: [...existingTargets, newTarget]
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// // Handle incoming connections to StaticMachine
|
||||
// else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
|
||||
// const reverseTarget = {
|
||||
// modelUUID: fromModelUUID,
|
||||
// pointUUID: fromPointUUID
|
||||
// };
|
||||
// const existingTargets = path.points.connections.targets || [];
|
||||
|
||||
// // Check if source is an ArmBot
|
||||
// const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID);
|
||||
// if (fromPath?.type !== 'ArmBot') {
|
||||
// console.log("StaticMachine can only connect to ArmBot");
|
||||
// return path;
|
||||
// }
|
||||
|
||||
// // Check if already has a connection
|
||||
// if (existingTargets.length >= 1) {
|
||||
// console.log("StaticMachine can have only one connection");
|
||||
// return path;
|
||||
// }
|
||||
|
||||
// if (!existingTargets.some(target =>
|
||||
// target.modelUUID === reverseTarget.modelUUID &&
|
||||
// target.pointUUID === reverseTarget.pointUUID
|
||||
// )) {
|
||||
// return {
|
||||
// ...path,
|
||||
// points: {
|
||||
// ...path.points,
|
||||
// connections: {
|
||||
// ...path.points.connections,
|
||||
// targets: [...existingTargets, reverseTarget]
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// return path;
|
||||
// }
|
||||
return path;
|
||||
});
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
|
||||
const updatedPathDetails = updatedPaths.filter(path =>
|
||||
path.modeluuid === fromModelUUID || path.modeluuid === toModelUUID
|
||||
);
|
||||
|
||||
updateBackend(updatedPathDetails);
|
||||
};
|
||||
|
||||
const handleAddConnection = (fromPathUUID: string, fromUUID: string, toPathUUID: string, toUUID: string) => {
|
||||
updatePathConnections(fromPathUUID, fromUUID, toPathUUID, toUUID);
|
||||
const updateBackend = async (updatedPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]) => {
|
||||
if (updatedPaths.length === 0) return;
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "";
|
||||
|
||||
updatedPaths.forEach(async (updatedPath) => {
|
||||
if (updatedPath.type === 'Conveyor') {
|
||||
|
||||
// await setEventApi(
|
||||
// organization,
|
||||
// updatedPath.modeluuid,
|
||||
// { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
|
||||
// );
|
||||
|
||||
const data = {
|
||||
organization: organization,
|
||||
modeluuid: updatedPath.modeluuid,
|
||||
eventData: { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
|
||||
}
|
||||
|
||||
socket.emit('v2:model-asset:updateEventData', data);
|
||||
|
||||
} else if (updatedPath.type === 'Vehicle') {
|
||||
|
||||
// await setEventApi(
|
||||
// organization,
|
||||
// updatedPath.modeluuid,
|
||||
// { type: "Vehicle", points: updatedPath.points }
|
||||
// );
|
||||
|
||||
const data = {
|
||||
organization: organization,
|
||||
modeluuid: updatedPath.modeluuid,
|
||||
eventData: { type: "Vehicle", points: updatedPath.points }
|
||||
}
|
||||
|
||||
socket.emit('v2:model-asset:updateEventData', data);
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
const handleAddConnection = (fromModelUUID: string, fromUUID: string, toModelUUID: string, toUUID: string) => {
|
||||
updatePathConnections(fromModelUUID, fromUUID, toModelUUID, toUUID);
|
||||
setFirstSelected(null);
|
||||
setCurrentLine(null);
|
||||
setIsConnecting(false);
|
||||
@@ -210,7 +336,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
const intersected = intersects[0].object;
|
||||
|
||||
if (intersected.name.includes("events-sphere")) {
|
||||
const pathUUID = intersected.userData.path.modeluuid;
|
||||
const modelUUID = intersected.userData.path.modeluuid;
|
||||
const sphereUUID = intersected.uuid;
|
||||
const worldPosition = new THREE.Vector3();
|
||||
intersected.getWorldPosition(worldPosition);
|
||||
@@ -226,9 +352,9 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
isStartOrEnd = sphereUUID === intersected.userData.path.points.uuid;
|
||||
}
|
||||
|
||||
if (pathUUID) {
|
||||
const firstPath = simulationPaths.find(p => p.modeluuid === firstSelected?.pathUUID);
|
||||
const secondPath = simulationPaths.find(p => p.modeluuid === pathUUID);
|
||||
if (modelUUID) {
|
||||
const firstPath = simulationStates.find(p => p.modeluuid === firstSelected?.modelUUID);
|
||||
const secondPath = simulationStates.find(p => p.modeluuid === modelUUID);
|
||||
|
||||
// Prevent vehicle-to-vehicle connections
|
||||
if (firstPath && secondPath && firstPath.type === 'Vehicle' && secondPath.type === 'Vehicle') {
|
||||
@@ -240,23 +366,23 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
if (firstPath && secondPath &&
|
||||
firstPath.type === 'Conveyor' &&
|
||||
secondPath.type === 'Conveyor' &&
|
||||
!firstSelected?.isCorner) {
|
||||
console.log("Conveyor middle points can only connect to non-conveyor paths");
|
||||
(!firstSelected?.isCorner || !isStartOrEnd)) {
|
||||
console.log("Conveyor connections must be between start/end points");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this specific connection already exists
|
||||
const isDuplicateConnection = firstSelected
|
||||
? simulationPaths.some(path => {
|
||||
if (path.modeluuid === firstSelected.pathUUID) {
|
||||
? simulationStates.some(path => {
|
||||
if (path.modeluuid === firstSelected.modelUUID) {
|
||||
if (path.type === 'Conveyor') {
|
||||
const point = path.points.find(p => p.uuid === firstSelected.sphereUUID);
|
||||
return point?.connections.targets.some(t =>
|
||||
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
||||
t.modelUUID === modelUUID && t.pointUUID === sphereUUID
|
||||
);
|
||||
} else if (path.type === 'Vehicle') {
|
||||
return path.points.connections.targets.some(t =>
|
||||
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
||||
t.modelUUID === modelUUID && t.pointUUID === sphereUUID
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -281,7 +407,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
|
||||
// For non-Vehicle paths, check if already connected
|
||||
if (intersected.userData.path.type !== 'Vehicle') {
|
||||
const isAlreadyConnected = simulationPaths.some(path => {
|
||||
const isAlreadyConnected = simulationStates.some(path => {
|
||||
if (path.type === 'Conveyor') {
|
||||
return path.points.some(point =>
|
||||
point.uuid === sphereUUID &&
|
||||
@@ -306,7 +432,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
}
|
||||
|
||||
// Prevent same-path connections
|
||||
if (firstSelected.pathUUID === pathUUID) {
|
||||
if (firstSelected.modelUUID === modelUUID) {
|
||||
console.log("Cannot connect spheres on the same path.");
|
||||
return;
|
||||
}
|
||||
@@ -319,15 +445,15 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
|
||||
// All checks passed - make the connection
|
||||
handleAddConnection(
|
||||
firstSelected.pathUUID,
|
||||
firstSelected.modelUUID,
|
||||
firstSelected.sphereUUID,
|
||||
pathUUID,
|
||||
modelUUID,
|
||||
sphereUUID
|
||||
);
|
||||
} else {
|
||||
// First selection - just store it
|
||||
setFirstSelected({
|
||||
pathUUID,
|
||||
modelUUID,
|
||||
sphereUUID,
|
||||
position: worldPosition,
|
||||
isCorner: isStartOrEnd
|
||||
@@ -361,7 +487,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
canvasElement.removeEventListener("mousemove", onMouseMove);
|
||||
canvasElement.removeEventListener("contextmenu", onContextMenu);
|
||||
};
|
||||
}, [camera, scene, raycaster, firstSelected, simulationPaths]);
|
||||
}, [camera, scene, raycaster, firstSelected, simulationStates]);
|
||||
|
||||
useFrame(() => {
|
||||
if (firstSelected) {
|
||||
@@ -375,7 +501,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
);
|
||||
|
||||
let point: THREE.Vector3 | null = null;
|
||||
let snappedSphere: { sphereUUID: string, position: THREE.Vector3, pathUUID: string, isCorner: boolean } | null = null;
|
||||
let snappedSphere: { sphereUUID: string, position: THREE.Vector3, modelUUID: string, isCorner: boolean } | null = null;
|
||||
let isInvalidConnection = false;
|
||||
|
||||
if (intersects.length > 0) {
|
||||
@@ -395,10 +521,10 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
const spherePosition = new THREE.Vector3();
|
||||
sphere.getWorldPosition(spherePosition);
|
||||
const pathData = sphere.userData.path;
|
||||
const pathUUID = pathData.modeluuid;
|
||||
const modelUUID = pathData.modeluuid;
|
||||
|
||||
const firstPath = simulationPaths.find(p => p.modeluuid === firstSelected.pathUUID);
|
||||
const secondPath = simulationPaths.find(p => p.modeluuid === pathUUID);
|
||||
const firstPath = simulationStates.find(p => p.modeluuid === firstSelected.modelUUID);
|
||||
const secondPath = simulationStates.find(p => p.modeluuid === modelUUID);
|
||||
const isVehicleToVehicle = firstPath?.type === 'Vehicle' && secondPath?.type === 'Vehicle';
|
||||
|
||||
// Inside the useFrame hook, where we check for snapped spheres:
|
||||
@@ -413,16 +539,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
!firstSelected.isCorner);
|
||||
|
||||
// Check for duplicate connection (regardless of path type)
|
||||
const isDuplicateConnection = simulationPaths.some(path => {
|
||||
if (path.modeluuid === firstSelected.pathUUID) {
|
||||
const isDuplicateConnection = simulationStates.some(path => {
|
||||
if (path.modeluuid === firstSelected.modelUUID) {
|
||||
if (path.type === 'Conveyor') {
|
||||
const point = path.points.find(p => p.uuid === firstSelected.sphereUUID);
|
||||
return point?.connections.targets.some(t =>
|
||||
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
||||
t.modelUUID === modelUUID && t.pointUUID === sphereUUID
|
||||
);
|
||||
} else if (path.type === 'Vehicle') {
|
||||
return path.points.connections.targets.some(t =>
|
||||
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
||||
t.modelUUID === modelUUID && t.pointUUID === sphereUUID
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -431,7 +557,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
|
||||
// For non-Vehicle paths, check if already connected
|
||||
const isNonVehicleAlreadyConnected = pathData.type !== 'Vehicle' &&
|
||||
simulationPaths.some(path => {
|
||||
simulationStates.some(path => {
|
||||
if (path.type === 'Conveyor') {
|
||||
return path.points.some(point =>
|
||||
point.uuid === sphereUUID &&
|
||||
@@ -455,13 +581,16 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
!isVehicleAtMaxConnections &&
|
||||
!isVehicleConnectingToNonConveyor &&
|
||||
firstSelected.sphereUUID !== sphereUUID &&
|
||||
firstSelected.pathUUID !== pathUUID &&
|
||||
(firstSelected.isCorner || isConnectable)
|
||||
firstSelected.modelUUID !== modelUUID &&
|
||||
(firstSelected.isCorner || isConnectable) &&
|
||||
!(firstPath?.type === 'Conveyor' &&
|
||||
pathData.type === 'Conveyor' &&
|
||||
!(firstSelected.isCorner && isConnectable))
|
||||
) {
|
||||
snappedSphere = {
|
||||
sphereUUID,
|
||||
position: spherePosition,
|
||||
pathUUID,
|
||||
modelUUID,
|
||||
isCorner: isConnectable
|
||||
};
|
||||
} else {
|
||||
@@ -505,11 +634,11 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
||||
|
||||
return (
|
||||
<group name='simulationConnectionGroup' visible={!isPlaying} >
|
||||
{simulationPaths.flatMap(path => {
|
||||
{simulationStates.flatMap(path => {
|
||||
if (path.type === 'Conveyor') {
|
||||
return path.points.flatMap(point =>
|
||||
point.connections.targets.map((target, index) => {
|
||||
const targetPath = simulationPaths.find(p => p.modeluuid === target.pathUUID);
|
||||
const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
|
||||
if (targetPath?.type === 'Vehicle') return null;
|
||||
|
||||
const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid);
|
||||
|
||||
@@ -3,375 +3,340 @@ import * as Types from "../../../types/world/worldTypes";
|
||||
import { useRef, useState, useEffect, useMemo } from "react";
|
||||
import { Sphere, TransformControls } from "@react-three/drei";
|
||||
import {
|
||||
useEditingPoint,
|
||||
useEyeDropMode,
|
||||
useIsConnecting,
|
||||
usePreviewPosition,
|
||||
useRenderDistance,
|
||||
useSelectedActionSphere,
|
||||
useSelectedPath,
|
||||
useSimulationPaths,
|
||||
useEditingPoint,
|
||||
useEyeDropMode,
|
||||
useIsConnecting,
|
||||
usePreviewPosition,
|
||||
useRenderDistance,
|
||||
useSelectedActionSphere,
|
||||
useSelectedPath,
|
||||
useSimulationStates,
|
||||
} from "../../../store/store";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useSubModuleStore } from "../../../store/useModuleStore";
|
||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||
import { setEventApi } from "../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
||||
|
||||
function PathCreation({
|
||||
pathsGroupRef,
|
||||
}: {
|
||||
pathsGroupRef: React.MutableRefObject<THREE.Group>;
|
||||
}) {
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { renderDistance } = useRenderDistance();
|
||||
const { setSubModule } = useSubModuleStore();
|
||||
const { setSelectedActionSphere, selectedActionSphere } = useSelectedActionSphere();
|
||||
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
|
||||
const { editingPoint, setEditingPoint } = useEditingPoint();
|
||||
const { previewPosition, setPreviewPosition } = usePreviewPosition();
|
||||
const { raycaster, camera, pointer, gl } = useThree();
|
||||
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||
const { setSelectedPath } = useSelectedPath();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { isConnecting } = useIsConnecting();
|
||||
function PathCreation({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObject<THREE.Group>; }) {
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { renderDistance } = useRenderDistance();
|
||||
const { setSubModule } = useSubModuleStore();
|
||||
const { setSelectedActionSphere, selectedActionSphere } = useSelectedActionSphere();
|
||||
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
|
||||
const { editingPoint, setEditingPoint } = useEditingPoint();
|
||||
const { previewPosition, setPreviewPosition } = usePreviewPosition();
|
||||
const { raycaster, camera, pointer, gl } = useThree();
|
||||
const { setSelectedPath } = useSelectedPath();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const { isConnecting } = useIsConnecting();
|
||||
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||
|
||||
const groupRefs = useRef<{ [key: string]: THREE.Group }>({});
|
||||
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
||||
const isMovingRef = useRef(false);
|
||||
const transformRef = useRef<any>(null);
|
||||
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
||||
const groupRefs = useRef<{ [key: string]: THREE.Group }>({});
|
||||
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
||||
const isMovingRef = useRef(false);
|
||||
const transformRef = useRef<any>(null);
|
||||
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
setTransformMode(null);
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (!selectedActionSphere) return;
|
||||
if (e.key === "g") {
|
||||
setTransformMode((prev) => (prev === "translate" ? null : "translate"));
|
||||
}
|
||||
if (e.key === "r") {
|
||||
setTransformMode((prev) => (prev === "rotate" ? null : "rotate"));
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
setTransformMode(null);
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (!selectedActionSphere) return;
|
||||
if (e.key === "g") {
|
||||
setTransformMode((prev) => (prev === "translate" ? null : "translate"));
|
||||
}
|
||||
if (e.key === "r") {
|
||||
setTransformMode((prev) => (prev === "rotate" ? null : "rotate"));
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, [selectedActionSphere]);
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, [selectedActionSphere]);
|
||||
|
||||
useFrame(() => {
|
||||
Object.values(groupRefs.current).forEach((group) => {
|
||||
if (group) {
|
||||
const distance = new THREE.Vector3(
|
||||
...group.position.toArray()
|
||||
).distanceTo(camera.position);
|
||||
group.visible = ((distance <= renderDistance) && !isPlaying);
|
||||
}
|
||||
});
|
||||
});
|
||||
useFrame(() => {
|
||||
Object.values(groupRefs.current).forEach((group) => {
|
||||
if (group) {
|
||||
const distance = new THREE.Vector3(
|
||||
...group.position.toArray()
|
||||
).distanceTo(camera.position);
|
||||
group.visible = ((distance <= renderDistance) && !isPlaying);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const updateSimulationPaths = () => {
|
||||
if (!selectedActionSphere) return;
|
||||
const updateSimulationPaths = () => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
const updatedPaths = simulationPaths.map((path) => {
|
||||
if (path.type === "Conveyor") {
|
||||
return {
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.points.uuid
|
||||
? {
|
||||
...point,
|
||||
position: [
|
||||
selectedActionSphere.points.position.x,
|
||||
selectedActionSphere.points.position.y,
|
||||
selectedActionSphere.points.position.z,
|
||||
],
|
||||
rotation: [
|
||||
selectedActionSphere.points.rotation.x,
|
||||
selectedActionSphere.points.rotation.y,
|
||||
selectedActionSphere.points.rotation.z,
|
||||
],
|
||||
}
|
||||
: point
|
||||
),
|
||||
};
|
||||
}
|
||||
return path;
|
||||
}) as Types.ConveyorEventsSchema[];
|
||||
const updatedPaths = simulationStates.map((path) => {
|
||||
if (path.type === "Conveyor") {
|
||||
return {
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.points.uuid
|
||||
? {
|
||||
...point,
|
||||
position: [
|
||||
selectedActionSphere.points.position.x,
|
||||
selectedActionSphere.points.position.y,
|
||||
selectedActionSphere.points.position.z,
|
||||
],
|
||||
rotation: [
|
||||
selectedActionSphere.points.rotation.x,
|
||||
selectedActionSphere.points.rotation.y,
|
||||
selectedActionSphere.points.rotation.z,
|
||||
],
|
||||
}
|
||||
: point
|
||||
),
|
||||
};
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
}) as Types.ConveyorEventsSchema[];
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
};
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path) => path.type === "Conveyor" && path.points.some((point) => point.uuid === selectedActionSphere.points.uuid)
|
||||
);
|
||||
|
||||
useFrame(() => {
|
||||
if (eyeDropMode) {
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
const intersectionPoint = new THREE.Vector3();
|
||||
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||
// console.log("Updated Path:", updatedPath);
|
||||
|
||||
if (point) {
|
||||
setPreviewPosition({ x: point.x, y: point.z });
|
||||
}
|
||||
} else {
|
||||
setPreviewPosition(null);
|
||||
}
|
||||
});
|
||||
setSimulationStates(updatedPaths);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!camera) return;
|
||||
const canvasElement = gl.domElement;
|
||||
canvasElement.tabIndex = 0;
|
||||
useFrame(() => {
|
||||
if (eyeDropMode) {
|
||||
raycaster.setFromCamera(pointer, camera);
|
||||
const intersectionPoint = new THREE.Vector3();
|
||||
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
|
||||
|
||||
const onPointerDown = () => {
|
||||
isMovingRef.current = false;
|
||||
};
|
||||
if (point) {
|
||||
setPreviewPosition({ x: point.x, y: point.z });
|
||||
}
|
||||
} else {
|
||||
setPreviewPosition(null);
|
||||
}
|
||||
});
|
||||
|
||||
const onPointerMove = () => {
|
||||
isMovingRef.current = true;
|
||||
};
|
||||
useEffect(() => {
|
||||
if (!camera) return;
|
||||
const canvasElement = gl.domElement;
|
||||
canvasElement.tabIndex = 0;
|
||||
|
||||
const onPointerUp = (event: PointerEvent) => {
|
||||
if (
|
||||
!isMovingRef.current &&
|
||||
eyeDropMode &&
|
||||
event.button === 0 &&
|
||||
previewPosition
|
||||
) {
|
||||
event.preventDefault();
|
||||
if (editingPoint) {
|
||||
handlePointUpdate(editingPoint, previewPosition.x, previewPosition.y);
|
||||
setEditingPoint(null);
|
||||
setEyeDropMode(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
const onPointerDown = () => {
|
||||
isMovingRef.current = false;
|
||||
};
|
||||
|
||||
if (eyeDropMode) {
|
||||
canvasElement.addEventListener("pointerdown", onPointerDown);
|
||||
canvasElement.addEventListener("pointermove", onPointerMove);
|
||||
canvasElement.addEventListener("pointerup", onPointerUp);
|
||||
}
|
||||
const onPointerMove = () => {
|
||||
isMovingRef.current = true;
|
||||
};
|
||||
|
||||
return () => {
|
||||
canvasElement.removeEventListener("pointerdown", onPointerDown);
|
||||
canvasElement.removeEventListener("pointermove", onPointerMove);
|
||||
canvasElement.removeEventListener("pointerup", onPointerUp);
|
||||
};
|
||||
}, [eyeDropMode, editingPoint, previewPosition]);
|
||||
const onPointerUp = (event: PointerEvent) => {
|
||||
if (
|
||||
!isMovingRef.current &&
|
||||
eyeDropMode &&
|
||||
event.button === 0 &&
|
||||
previewPosition
|
||||
) {
|
||||
event.preventDefault();
|
||||
if (editingPoint) {
|
||||
handlePointUpdate(editingPoint, previewPosition.x, previewPosition.y);
|
||||
setEditingPoint(null);
|
||||
setEyeDropMode(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const updateBackend = async (updatedPath: Types.VehicleEventsSchema | undefined) => {
|
||||
if (!updatedPath) return;
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "";
|
||||
await setEventApi(
|
||||
organization,
|
||||
updatedPath.modeluuid,
|
||||
{ type: "Vehicle", points: updatedPath.points }
|
||||
);
|
||||
}
|
||||
if (eyeDropMode) {
|
||||
canvasElement.addEventListener("pointerdown", onPointerDown);
|
||||
canvasElement.addEventListener("pointermove", onPointerMove);
|
||||
canvasElement.addEventListener("pointerup", onPointerUp);
|
||||
}
|
||||
|
||||
const handlePointUpdate = (
|
||||
pointType: "start" | "end",
|
||||
x: number,
|
||||
z: number
|
||||
) => {
|
||||
if (!selectedActionSphere?.points?.uuid) return;
|
||||
const updatedPaths = simulationPaths.map((path) => {
|
||||
return () => {
|
||||
canvasElement.removeEventListener("pointerdown", onPointerDown);
|
||||
canvasElement.removeEventListener("pointermove", onPointerMove);
|
||||
canvasElement.removeEventListener("pointerup", onPointerUp);
|
||||
};
|
||||
}, [eyeDropMode, editingPoint, previewPosition]);
|
||||
|
||||
if (
|
||||
path.type === "Vehicle" &&
|
||||
path.points.uuid === selectedActionSphere.points.uuid
|
||||
) {
|
||||
return {
|
||||
...path,
|
||||
points: {
|
||||
...path.points,
|
||||
actions: {
|
||||
...path.points.actions,
|
||||
[pointType]: {
|
||||
...path.points.actions[pointType],
|
||||
x: x,
|
||||
y: z,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
return path;
|
||||
});
|
||||
const updateBackend = async (updatedPath: Types.VehicleEventsSchema | undefined) => {
|
||||
if (!updatedPath) return;
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "";
|
||||
await setEventApi(
|
||||
organization,
|
||||
updatedPath.modeluuid,
|
||||
{ type: "Vehicle", points: updatedPath.points }
|
||||
);
|
||||
}
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.VehicleEventsSchema =>
|
||||
path.type === "Vehicle" &&
|
||||
path.points.uuid === selectedActionSphere.points.uuid
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
const handlePointUpdate = (pointType: "start" | "end", x: number, z: number) => {
|
||||
if (!selectedActionSphere?.points?.uuid) return;
|
||||
const updatedPaths = simulationStates.map((path) => {
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
};
|
||||
if (path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid) {
|
||||
return {
|
||||
...path,
|
||||
points: {
|
||||
...path.points,
|
||||
actions: {
|
||||
...path.points.actions,
|
||||
[pointType]: { ...path.points.actions[pointType], x: x, y: z, },
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
return path;
|
||||
});
|
||||
|
||||
return (
|
||||
<group visible={!isPlaying} name="simulation-simulationPaths-group" ref={pathsGroupRef}>
|
||||
{simulationPaths.map((path) => {
|
||||
if (path.type === "Conveyor") {
|
||||
const points = path.points.map(
|
||||
(point) => new THREE.Vector3(...point.position)
|
||||
);
|
||||
const updatedPath = updatedPaths.find((path): path is Types.VehicleEventsSchema => path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
return (
|
||||
<group
|
||||
name={`${path.modeluuid}-event-path`}
|
||||
key={path.modeluuid}
|
||||
ref={(el) => (groupRefs.current[path.modeluuid] = el!)}
|
||||
position={path.position}
|
||||
rotation={path.rotation}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedPath({
|
||||
path,
|
||||
group: groupRefs.current[path.modeluuid],
|
||||
});
|
||||
setSelectedActionSphere(null);
|
||||
setTransformMode(null);
|
||||
setSubModule("mechanics");
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSelectedPath(null);
|
||||
setSubModule("properties");
|
||||
}}
|
||||
>
|
||||
{path.points.map((point, index) => (
|
||||
<Sphere
|
||||
key={point.uuid}
|
||||
uuid={point.uuid}
|
||||
position={point.position}
|
||||
args={[0.15, 32, 32]}
|
||||
name="events-sphere"
|
||||
ref={(el) => (sphereRefs.current[point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedActionSphere({
|
||||
path,
|
||||
points: sphereRefs.current[point.uuid],
|
||||
});
|
||||
setSubModule("mechanics");
|
||||
setSelectedPath(null);
|
||||
}}
|
||||
userData={{ points, path }}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSubModule("properties");
|
||||
setSelectedActionSphere(null);
|
||||
}}
|
||||
>
|
||||
<meshStandardMaterial
|
||||
color={
|
||||
index === 0
|
||||
? "orange"
|
||||
: index === path.points.length - 1
|
||||
? "blue"
|
||||
: "green"
|
||||
}
|
||||
/>
|
||||
</Sphere>
|
||||
))}
|
||||
setSimulationStates(updatedPaths);
|
||||
};
|
||||
|
||||
{points.slice(0, -1).map((point, index) => {
|
||||
const nextPoint = points[index + 1];
|
||||
const segmentCurve = new THREE.CatmullRomCurve3([
|
||||
point,
|
||||
nextPoint,
|
||||
]);
|
||||
const tubeGeometry = new THREE.TubeGeometry(
|
||||
segmentCurve,
|
||||
20,
|
||||
0.1,
|
||||
16,
|
||||
false
|
||||
);
|
||||
return (
|
||||
<group visible={!isPlaying} name="simulation-simulationStates-group" ref={pathsGroupRef}>
|
||||
{simulationStates.map((path) => {
|
||||
if (path.type === "Conveyor") {
|
||||
const points = path.points.map(
|
||||
(point) => new THREE.Vector3(...point.position)
|
||||
);
|
||||
|
||||
return (
|
||||
<mesh
|
||||
name="event-connection-tube"
|
||||
key={`tube-${index}`}
|
||||
geometry={tubeGeometry}
|
||||
>
|
||||
<meshStandardMaterial
|
||||
transparent
|
||||
opacity={0.9}
|
||||
color="red"
|
||||
/>
|
||||
</mesh>
|
||||
);
|
||||
})}
|
||||
</group>
|
||||
);
|
||||
} else if (path.type === "Vehicle") {
|
||||
return (
|
||||
<group
|
||||
name={`${path.modeluuid}-vehicle-path`}
|
||||
key={path.modeluuid}
|
||||
ref={(el) => (groupRefs.current[path.modeluuid] = el!)}
|
||||
position={path.position}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedPath({
|
||||
path,
|
||||
group: groupRefs.current[path.modeluuid],
|
||||
});
|
||||
setSelectedActionSphere(null);
|
||||
setTransformMode(null);
|
||||
setSubModule("mechanics");
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSelectedPath(null);
|
||||
setSubModule("properties");
|
||||
}}
|
||||
>
|
||||
<Sphere
|
||||
key={path.points.uuid}
|
||||
uuid={path.points.uuid}
|
||||
position={path.points.position}
|
||||
args={[0.15, 32, 32]}
|
||||
name="events-sphere"
|
||||
ref={(el) => (sphereRefs.current[path.points.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedActionSphere({
|
||||
path,
|
||||
points: sphereRefs.current[path.points.uuid],
|
||||
});
|
||||
setSubModule("mechanics");
|
||||
setSelectedPath(null);
|
||||
}}
|
||||
userData={{ points: path.points, path }}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSubModule("properties");
|
||||
setSelectedActionSphere(null);
|
||||
}}
|
||||
>
|
||||
<meshStandardMaterial color="purple" />
|
||||
</Sphere>
|
||||
</group>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
return (
|
||||
<group
|
||||
name={`${path.modeluuid}-${path.type}-path`}
|
||||
key={path.modeluuid}
|
||||
ref={(el) => (groupRefs.current[path.modeluuid] = el!)}
|
||||
position={path.position}
|
||||
rotation={path.rotation}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedPath({
|
||||
path,
|
||||
group: groupRefs.current[path.modeluuid],
|
||||
});
|
||||
setSelectedActionSphere(null);
|
||||
setTransformMode(null);
|
||||
setSubModule("mechanics");
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSelectedPath(null);
|
||||
setSubModule("properties");
|
||||
}}
|
||||
>
|
||||
{path.points.map((point, index) => (
|
||||
<Sphere
|
||||
key={point.uuid}
|
||||
uuid={point.uuid}
|
||||
position={point.position}
|
||||
args={[0.15, 32, 32]}
|
||||
name="events-sphere"
|
||||
ref={(el) => (sphereRefs.current[point.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedActionSphere({
|
||||
path,
|
||||
points: sphereRefs.current[point.uuid],
|
||||
});
|
||||
setSubModule("mechanics");
|
||||
setSelectedPath(null);
|
||||
}}
|
||||
userData={{ points, path }}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSubModule("properties");
|
||||
setSelectedActionSphere(null);
|
||||
}}
|
||||
>
|
||||
<meshStandardMaterial
|
||||
color={index === 0 ? "orange" : index === path.points.length - 1 ? "blue" : "green"}
|
||||
/>
|
||||
</Sphere>
|
||||
))}
|
||||
|
||||
{selectedActionSphere && transformMode && (
|
||||
<TransformControls
|
||||
ref={transformRef}
|
||||
object={selectedActionSphere.points}
|
||||
mode={transformMode}
|
||||
onMouseUp={updateSimulationPaths}
|
||||
/>
|
||||
)}
|
||||
</group>
|
||||
);
|
||||
{points.slice(0, -1).map((point, index) => {
|
||||
const nextPoint = points[index + 1];
|
||||
const segmentCurve = new THREE.CatmullRomCurve3([point, nextPoint,]);
|
||||
const tubeGeometry = new THREE.TubeGeometry(segmentCurve, 20, 0.1, 16, false);
|
||||
|
||||
return (
|
||||
<mesh name="event-connection-tube" key={`tube-${index}`} geometry={tubeGeometry}>
|
||||
<meshStandardMaterial transparent opacity={0.9} color="red" />
|
||||
</mesh>
|
||||
);
|
||||
})}
|
||||
</group>
|
||||
);
|
||||
} else if (path.type === "Vehicle" || path.type === "StaticMachine") {
|
||||
return (
|
||||
<group
|
||||
name={`${path.modeluuid}-${path.type}-path`}
|
||||
key={path.modeluuid}
|
||||
ref={(el) => (groupRefs.current[path.modeluuid] = el!)}
|
||||
position={path.position}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedPath({
|
||||
path,
|
||||
group: groupRefs.current[path.modeluuid],
|
||||
});
|
||||
setSelectedActionSphere(null);
|
||||
setTransformMode(null);
|
||||
setSubModule("mechanics");
|
||||
}}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSelectedPath(null);
|
||||
setSubModule("properties");
|
||||
}}
|
||||
>
|
||||
<Sphere
|
||||
key={path.points.uuid}
|
||||
uuid={path.points.uuid}
|
||||
position={path.points.position}
|
||||
args={[0.15, 32, 32]}
|
||||
name="events-sphere"
|
||||
ref={(el) => (sphereRefs.current[path.points.uuid] = el!)}
|
||||
onClick={(e) => {
|
||||
if (isConnecting || eyeDropMode) return;
|
||||
e.stopPropagation();
|
||||
setSelectedActionSphere({
|
||||
path,
|
||||
points: sphereRefs.current[path.points.uuid],
|
||||
});
|
||||
setSubModule("mechanics");
|
||||
setSelectedPath(null);
|
||||
}}
|
||||
userData={{ points: path.points, path }}
|
||||
onPointerMissed={() => {
|
||||
if (eyeDropMode) return;
|
||||
setSubModule("properties");
|
||||
setSelectedActionSphere(null);
|
||||
}}
|
||||
>
|
||||
<meshStandardMaterial color="purple" />
|
||||
</Sphere>
|
||||
</group>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
|
||||
{selectedActionSphere && transformMode && (
|
||||
<TransformControls
|
||||
ref={transformRef}
|
||||
object={selectedActionSphere.points}
|
||||
mode={transformMode}
|
||||
onMouseUp={updateSimulationPaths}
|
||||
/>
|
||||
)}
|
||||
</group>
|
||||
);
|
||||
}
|
||||
|
||||
export default PathCreation;
|
||||
|
||||
@@ -29,8 +29,8 @@ interface ProcessPoint {
|
||||
rotation: number[];
|
||||
actions: PointAction[];
|
||||
connections: {
|
||||
source: { pathUUID: string; pointUUID: string };
|
||||
targets: { pathUUID: string; pointUUID: string }[];
|
||||
source: { modelUUID: string; pointUUID: string };
|
||||
targets: { modelUUID: string; pointUUID: string }[];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// useCallback,
|
||||
// useRef,
|
||||
// } from "react";
|
||||
// import { useSimulationPaths } from "../../../store/store";
|
||||
// import { useSimulationStates } from "../../../store/store";
|
||||
// import * as THREE from "three";
|
||||
// import { useThree } from "@react-three/fiber";
|
||||
// import {
|
||||
@@ -29,7 +29,7 @@
|
||||
// position: [number, number, number];
|
||||
// actions: PointAction[];
|
||||
// connections: {
|
||||
// targets: Array<{ pathUUID: string }>;
|
||||
// targets: Array<{ modelUUID: string }>;
|
||||
// };
|
||||
// }
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
// actions: point.actions.map(normalizeAction), // Preserve exact actions
|
||||
// connections: {
|
||||
// targets: point.connections.targets.map((target) => ({
|
||||
// pathUUID: target.pathUUID,
|
||||
// modelUUID: target.modelUUID,
|
||||
// })),
|
||||
// },
|
||||
// })),
|
||||
@@ -94,7 +94,7 @@
|
||||
// : [normalizeAction(path.point.actions)],
|
||||
// connections: {
|
||||
// targets: path.point.connections.targets.map((target) => ({
|
||||
// pathUUID: target.pathUUID,
|
||||
// modelUUID: target.modelUUID,
|
||||
// })),
|
||||
// },
|
||||
// },
|
||||
@@ -137,18 +137,18 @@
|
||||
// // Check if current last connects to next last (requires reversal)
|
||||
// const connectsToLast = currentLastPoint.connections.targets.some(
|
||||
// (target) =>
|
||||
// target.pathUUID === nextPath.modeluuid &&
|
||||
// target.modelUUID === nextPath.modeluuid &&
|
||||
// nextLastPoint.connections.targets.some(
|
||||
// (t) => t.pathUUID === currentPath.modeluuid
|
||||
// (t) => t.modelUUID === currentPath.modeluuid
|
||||
// )
|
||||
// );
|
||||
|
||||
// // Check if current last connects to next first (no reversal needed)
|
||||
// const connectsToFirst = currentLastPoint.connections.targets.some(
|
||||
// (target) =>
|
||||
// target.pathUUID === nextPath.modeluuid &&
|
||||
// target.modelUUID === nextPath.modeluuid &&
|
||||
// nextFirstPoint.connections.targets.some(
|
||||
// (t) => t.pathUUID === currentPath.modeluuid
|
||||
// (t) => t.modelUUID === currentPath.modeluuid
|
||||
// )
|
||||
// );
|
||||
|
||||
@@ -249,10 +249,10 @@
|
||||
// // Process outgoing connections
|
||||
// for (const point of currentPath.points) {
|
||||
// for (const target of point.connections.targets) {
|
||||
// if (!visited.has(target.pathUUID)) {
|
||||
// const targetPath = pathMap.get(target.pathUUID);
|
||||
// if (!visited.has(target.modelUUID)) {
|
||||
// const targetPath = pathMap.get(target.modelUUID);
|
||||
// if (targetPath) {
|
||||
// visited.add(target.pathUUID);
|
||||
// visited.add(target.modelUUID);
|
||||
// queue.push(targetPath);
|
||||
// }
|
||||
// }
|
||||
@@ -264,7 +264,7 @@
|
||||
// if (!visited.has(uuid)) {
|
||||
// const hasConnectionToCurrent = path.points.some((point) =>
|
||||
// point.connections.targets.some(
|
||||
// (t) => t.pathUUID === currentPath.modeluuid
|
||||
// (t) => t.modelUUID === currentPath.modeluuid
|
||||
// )
|
||||
// );
|
||||
// if (hasConnectionToCurrent) {
|
||||
@@ -312,19 +312,19 @@
|
||||
|
||||
// const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
|
||||
// ({ onProcessesCreated }) => {
|
||||
// const { simulationPaths } = useSimulationPaths();
|
||||
// const { simulationStates } = useSimulationStates();
|
||||
// const { createProcessesFromPaths } = useProcessCreation();
|
||||
// const prevPathsRef = useRef<SimulationPath[]>([]);
|
||||
// const prevProcessesRef = useRef<Process[]>([]);
|
||||
|
||||
// const convertedPaths = useMemo((): SimulationPath[] => {
|
||||
// if (!simulationPaths) return [];
|
||||
// return simulationPaths.map((path) =>
|
||||
// if (!simulationStates) return [];
|
||||
// return simulationStates.map((path) =>
|
||||
// convertToSimulationPath(
|
||||
// path as ConveyorEventsSchema | VehicleEventsSchema
|
||||
// )
|
||||
// );
|
||||
// }, [simulationPaths]);
|
||||
// }, [simulationStates]);
|
||||
|
||||
// const pathsDependency = useMemo(() => {
|
||||
// if (!convertedPaths) return null;
|
||||
@@ -335,7 +335,7 @@
|
||||
// ),
|
||||
// connections: path.points
|
||||
// .flatMap((p: PathPoint) =>
|
||||
// p.connections.targets.map((t: { pathUUID: string }) => t.pathUUID)
|
||||
// p.connections.targets.map((t: { modelUUID: string }) => t.modelUUID)
|
||||
// )
|
||||
// .join(","),
|
||||
// }));
|
||||
@@ -404,7 +404,7 @@ import React, {
|
||||
useCallback,
|
||||
useRef,
|
||||
} from "react";
|
||||
import { useSimulationPaths } from "../../../store/store";
|
||||
import { useSimulationStates } from "../../../store/store";
|
||||
import * as THREE from "three";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import {
|
||||
@@ -428,11 +428,12 @@ export interface PathPoint {
|
||||
position: [number, number, number];
|
||||
actions: PointAction[];
|
||||
connections: {
|
||||
targets: Array<{ pathUUID: string }>;
|
||||
targets: Array<{ modelUUID: string }>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SimulationPath {
|
||||
type: string;
|
||||
modeluuid: string;
|
||||
points: PathPoint[];
|
||||
pathPosition: [number, number, number];
|
||||
@@ -464,6 +465,7 @@ function convertToSimulationPath(
|
||||
|
||||
if (path.type === "Conveyor") {
|
||||
return {
|
||||
type: path.type,
|
||||
modeluuid,
|
||||
points: path.points.map((point) => ({
|
||||
uuid: point.uuid,
|
||||
@@ -471,7 +473,7 @@ function convertToSimulationPath(
|
||||
actions: point.actions.map(normalizeAction), // Preserve exact actions
|
||||
connections: {
|
||||
targets: point.connections.targets.map((target) => ({
|
||||
pathUUID: target.pathUUID,
|
||||
modelUUID: target.modelUUID,
|
||||
})),
|
||||
},
|
||||
})),
|
||||
@@ -483,6 +485,7 @@ function convertToSimulationPath(
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: path.type,
|
||||
modeluuid,
|
||||
points: [
|
||||
{
|
||||
@@ -493,7 +496,7 @@ function convertToSimulationPath(
|
||||
: [normalizeAction(path.points.actions)],
|
||||
connections: {
|
||||
targets: path.points.connections.targets.map((target) => ({
|
||||
pathUUID: target.pathUUID,
|
||||
modelUUID: target.modelUUID,
|
||||
})),
|
||||
},
|
||||
},
|
||||
@@ -536,18 +539,18 @@ function shouldReverseNextPath(
|
||||
// Check if current last connects to next last (requires reversal)
|
||||
const connectsToLast = currentLastPoint.connections.targets.some(
|
||||
(target) =>
|
||||
target.pathUUID === nextPath.modeluuid &&
|
||||
target.modelUUID === nextPath.modeluuid &&
|
||||
nextLastPoint.connections.targets.some(
|
||||
(t) => t.pathUUID === currentPath.modeluuid
|
||||
(t) => t.modelUUID === currentPath.modeluuid
|
||||
)
|
||||
);
|
||||
|
||||
// Check if current last connects to next first (no reversal needed)
|
||||
const connectsToFirst = currentLastPoint.connections.targets.some(
|
||||
(target) =>
|
||||
target.pathUUID === nextPath.modeluuid &&
|
||||
target.modelUUID === nextPath.modeluuid &&
|
||||
nextFirstPoint.connections.targets.some(
|
||||
(t) => t.pathUUID === currentPath.modeluuid
|
||||
(t) => t.modelUUID === currentPath.modeluuid
|
||||
)
|
||||
);
|
||||
|
||||
@@ -614,6 +617,7 @@ export function useProcessCreation() {
|
||||
const [processes, setProcesses] = useState<Process[]>([]);
|
||||
|
||||
const hasSpawnAction = useCallback((path: SimulationPath): boolean => {
|
||||
if (path.type !== "Conveyor") return false;
|
||||
return path.points.some((point) =>
|
||||
point.actions.some((action) => action.type.toLowerCase() === "spawn")
|
||||
);
|
||||
@@ -674,10 +678,10 @@ export function useProcessCreation() {
|
||||
// Process outgoing connections
|
||||
for (const point of currentPath.points) {
|
||||
for (const target of point.connections.targets) {
|
||||
if (!visited.has(target.pathUUID)) {
|
||||
const targetPath = pathMap.get(target.pathUUID);
|
||||
if (!visited.has(target.modelUUID)) {
|
||||
const targetPath = pathMap.get(target.modelUUID);
|
||||
if (targetPath) {
|
||||
visited.add(target.pathUUID);
|
||||
visited.add(target.modelUUID);
|
||||
queue.push(targetPath);
|
||||
}
|
||||
}
|
||||
@@ -689,7 +693,7 @@ export function useProcessCreation() {
|
||||
if (!visited.has(uuid)) {
|
||||
const hasConnectionToCurrent = path.points.some((point) =>
|
||||
point.connections.targets.some(
|
||||
(t) => t.pathUUID === currentPath.modeluuid
|
||||
(t) => t.modelUUID === currentPath.modeluuid
|
||||
)
|
||||
);
|
||||
if (hasConnectionToCurrent) {
|
||||
@@ -737,19 +741,19 @@ export function useProcessCreation() {
|
||||
|
||||
const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
|
||||
({ onProcessesCreated }) => {
|
||||
const { simulationPaths } = useSimulationPaths();
|
||||
const { simulationStates } = useSimulationStates();
|
||||
const { createProcessesFromPaths } = useProcessCreation();
|
||||
const prevPathsRef = useRef<SimulationPath[]>([]);
|
||||
const prevProcessesRef = useRef<Process[]>([]);
|
||||
|
||||
const convertedPaths = useMemo((): SimulationPath[] => {
|
||||
if (!simulationPaths) return [];
|
||||
return simulationPaths.map((path) =>
|
||||
if (!simulationStates) return [];
|
||||
return simulationStates.map((path) =>
|
||||
convertToSimulationPath(
|
||||
path as ConveyorEventsSchema | VehicleEventsSchema
|
||||
)
|
||||
);
|
||||
}, [simulationPaths]);
|
||||
}, [simulationStates]);
|
||||
|
||||
// Enhanced dependency tracking that includes action types
|
||||
const pathsDependency = useMemo(() => {
|
||||
@@ -764,7 +768,7 @@ const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
|
||||
.join(","),
|
||||
connections: path.points
|
||||
.flatMap((p: PathPoint) =>
|
||||
p.connections.targets.map((t: { pathUUID: string }) => t.pathUUID)
|
||||
p.connections.targets.map((t: { modelUUID: string }) => t.modelUUID)
|
||||
)
|
||||
.join(","),
|
||||
}));
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useState, useEffect, useRef, useMemo } from "react";
|
||||
import {
|
||||
useSelectedActionSphere,
|
||||
useSelectedPath,
|
||||
useSimulationPaths,
|
||||
useSimulationStates,
|
||||
} from "../../store/store";
|
||||
import * as THREE from "three";
|
||||
import Behaviour from "./behaviour/behaviour";
|
||||
@@ -15,12 +15,12 @@ import Agv from "../builder/agv/agv";
|
||||
function Simulation() {
|
||||
const { activeModule } = useModuleStore();
|
||||
const pathsGroupRef = useRef() as React.MutableRefObject<THREE.Group>;
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
const [processes, setProcesses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('simulationPaths: ', simulationPaths);
|
||||
}, [simulationPaths]);
|
||||
// console.log('simulationStates: ', simulationStates);
|
||||
}, [simulationStates]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (selectedActionSphere) {
|
||||
@@ -42,7 +42,7 @@ function Simulation() {
|
||||
<PathCreation pathsGroupRef={pathsGroupRef} />
|
||||
<PathConnector pathsGroupRef={pathsGroupRef} />
|
||||
<ProcessContainer />
|
||||
{/* <Agv /> */}
|
||||
<Agv />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// import { useMemo, useState } from 'react';
|
||||
// import { useSelectedActionSphere, useToggleView, useSimulationPaths, useSelectedPath, useStartSimulation, useDrawMaterialPath } from '../../store/store';
|
||||
// import { useSelectedActionSphere, useToggleView, useSimulationStates, useSelectedPath, useStartSimulation, useDrawMaterialPath } from '../../store/store';
|
||||
// import * as THREE from 'three';
|
||||
// import useModuleStore from '../../store/useModuleStore';
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
// const { startSimulation, setStartSimulation } = useStartSimulation();
|
||||
// const { selectedActionSphere } = useSelectedActionSphere();
|
||||
// const { selectedPath, setSelectedPath } = useSelectedPath();
|
||||
// const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
// const { simulationStates, setSimulationStates } = useSimulationStates();
|
||||
// const { drawMaterialPath, setDrawMaterialPath } = useDrawMaterialPath();
|
||||
// const [activeButton, setActiveButton] = useState<string | null>(null);
|
||||
|
||||
// const handleAddAction = () => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) => {
|
||||
// if (point.uuid === selectedActionSphere.points.uuid) {
|
||||
@@ -37,13 +37,13 @@
|
||||
// }),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const handleDeleteAction = (uuid: string) => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) =>
|
||||
// point.uuid === selectedActionSphere.points.uuid
|
||||
@@ -52,13 +52,13 @@
|
||||
// ),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const handleActionSelect = (uuid: string, actionType: string) => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) =>
|
||||
// point.uuid === selectedActionSphere.points.uuid
|
||||
@@ -72,13 +72,13 @@
|
||||
// ),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const handleMaterialSelect = (uuid: string, material: string) => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) =>
|
||||
// point.uuid === selectedActionSphere.points.uuid
|
||||
@@ -92,13 +92,13 @@
|
||||
// ),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const handleDelayChange = (uuid: string, delay: number | string) => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) =>
|
||||
// point.uuid === selectedActionSphere.points.uuid
|
||||
@@ -112,13 +112,13 @@
|
||||
// ),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) =>
|
||||
// point.uuid === selectedActionSphere.points.uuid
|
||||
@@ -132,24 +132,24 @@
|
||||
// ),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const handleSpeedChange = (speed: number) => {
|
||||
// if (!selectedPath) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) =>
|
||||
// const updatedPaths = simulationStates.map((path) =>
|
||||
// path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
|
||||
// );
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
|
||||
// };
|
||||
|
||||
// const handleAddTrigger = () => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) => {
|
||||
// if (point.uuid === selectedActionSphere.points.uuid) {
|
||||
@@ -167,13 +167,13 @@
|
||||
// }),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const handleDeleteTrigger = (uuid: string) => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) =>
|
||||
// point.uuid === selectedActionSphere.points.uuid
|
||||
@@ -182,13 +182,13 @@
|
||||
// ),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const handleTriggerSelect = (uuid: string, triggerType: string) => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) =>
|
||||
// point.uuid === selectedActionSphere.points.uuid
|
||||
@@ -202,7 +202,7 @@
|
||||
// ),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const handleResetPath = () => {
|
||||
@@ -214,7 +214,7 @@
|
||||
// const handleActionToggle = (uuid: string) => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) =>
|
||||
// point.uuid === selectedActionSphere.points.uuid
|
||||
@@ -229,13 +229,13 @@
|
||||
// ),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const handleTriggerToggle = (uuid: string) => {
|
||||
// if (!selectedActionSphere) return;
|
||||
|
||||
// const updatedPaths = simulationPaths.map((path) => ({
|
||||
// const updatedPaths = simulationStates.map((path) => ({
|
||||
// ...path,
|
||||
// points: path.points.map((point) =>
|
||||
// point.uuid === selectedActionSphere.points.uuid
|
||||
@@ -250,13 +250,13 @@
|
||||
// ),
|
||||
// }));
|
||||
|
||||
// setSimulationPaths(updatedPaths);
|
||||
// setSimulationStates(updatedPaths);
|
||||
// };
|
||||
|
||||
// const selectedPoint = useMemo(() => {
|
||||
// if (!selectedActionSphere) return null;
|
||||
// return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.points.uuid);
|
||||
// }, [selectedActionSphere, simulationPaths]);
|
||||
// return simulationStates.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.points.uuid);
|
||||
// }, [selectedActionSphere, simulationStates]);
|
||||
|
||||
// const createPath = () => {
|
||||
// setActiveButton(activeButton !== 'addMaterialPath' ? 'addMaterialPath' : null);
|
||||
|
||||
@@ -11,13 +11,13 @@ type PathPoint = {
|
||||
};
|
||||
|
||||
type PathCreatorProps = {
|
||||
simulationPaths: PathPoint[][];
|
||||
setSimulationPaths: React.Dispatch<React.SetStateAction<PathPoint[][]>>;
|
||||
simulationStates: PathPoint[][];
|
||||
setSimulationStates: React.Dispatch<React.SetStateAction<PathPoint[][]>>;
|
||||
connections: { start: PathPoint; end: PathPoint }[];
|
||||
setConnections: React.Dispatch<React.SetStateAction<{ start: PathPoint; end: PathPoint }[]>>
|
||||
};
|
||||
|
||||
const PathCreator = ({ simulationPaths, setSimulationPaths, connections, setConnections }: PathCreatorProps) => {
|
||||
const PathCreator = ({ simulationStates, setSimulationStates, connections, setConnections }: PathCreatorProps) => {
|
||||
const { camera, scene, raycaster, pointer, gl } = useThree();
|
||||
const { drawMaterialPath } = useDrawMaterialPath();
|
||||
|
||||
@@ -71,7 +71,7 @@ const PathCreator = ({ simulationPaths, setSimulationPaths, connections, setConn
|
||||
e.preventDefault();
|
||||
if (drag || e.button === 0) return;
|
||||
if (currentPath.length > 1) {
|
||||
setSimulationPaths((prevPaths) => [...prevPaths, currentPath]);
|
||||
setSimulationStates((prevPaths) => [...prevPaths, currentPath]);
|
||||
}
|
||||
setCurrentPath([]);
|
||||
setTemporaryPoint(null);
|
||||
@@ -125,7 +125,7 @@ const PathCreator = ({ simulationPaths, setSimulationPaths, connections, setConn
|
||||
canvasElement.addEventListener("contextmenu", onContextMenu);
|
||||
} else {
|
||||
if (currentPath.length > 1) {
|
||||
setSimulationPaths((prevPaths) => [...prevPaths, currentPath]);
|
||||
setSimulationStates((prevPaths) => [...prevPaths, currentPath]);
|
||||
}
|
||||
setCurrentPath([]);
|
||||
setTemporaryPoint(null);
|
||||
@@ -179,25 +179,25 @@ const PathCreator = ({ simulationPaths, setSimulationPaths, connections, setConn
|
||||
if (selectedPoint) {
|
||||
const updatedPosition = e.target.object.position.clone();
|
||||
const updatedRotation = e.target.object.quaternion.clone();
|
||||
const updatedPaths = simulationPaths.map((path) =>
|
||||
const updatedPaths = simulationStates.map((path) =>
|
||||
path.map((p) =>
|
||||
p.uuid === selectedPoint.uuid ? { ...p, position: updatedPosition, rotation: updatedRotation } : p
|
||||
)
|
||||
);
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSimulationStates(updatedPaths);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const meshContext = (uuid: string) => {
|
||||
const pathIndex = simulationPaths.findIndex(path => path.some(point => point.uuid === uuid));
|
||||
const pathIndex = simulationStates.findIndex(path => path.some(point => point.uuid === uuid));
|
||||
if (pathIndex === -1) return;
|
||||
|
||||
const clickedPoint = simulationPaths[pathIndex].find(point => point.uuid === uuid);
|
||||
const clickedPoint = simulationStates[pathIndex].find(point => point.uuid === uuid);
|
||||
if (!clickedPoint) return;
|
||||
|
||||
const isStart = simulationPaths[pathIndex][0].uuid === uuid;
|
||||
const isEnd = simulationPaths[pathIndex][simulationPaths[pathIndex].length - 1].uuid === uuid;
|
||||
const isStart = simulationStates[pathIndex][0].uuid === uuid;
|
||||
const isEnd = simulationStates[pathIndex][simulationStates[pathIndex].length - 1].uuid === uuid;
|
||||
|
||||
if (pathIndex === 0 && isStart) {
|
||||
console.log("The first-ever point is not connectable.");
|
||||
@@ -285,8 +285,8 @@ const PathCreator = ({ simulationPaths, setSimulationPaths, connections, setConn
|
||||
return (
|
||||
<>
|
||||
<group name='pathObjects'>
|
||||
{/* Render finalized simulationPaths */}
|
||||
{simulationPaths.map((path, pathIndex) => (
|
||||
{/* Render finalized simulationStates */}
|
||||
{simulationStates.map((path, pathIndex) => (
|
||||
<group key={`path-line-${pathIndex}`}>
|
||||
<Line
|
||||
name={`path-line-${pathIndex}`}
|
||||
@@ -299,7 +299,7 @@ const PathCreator = ({ simulationPaths, setSimulationPaths, connections, setConn
|
||||
))}
|
||||
|
||||
{/* Render finalized points */}
|
||||
{simulationPaths.map((path) =>
|
||||
{simulationStates.map((path) =>
|
||||
path.map((point) => (
|
||||
<mesh
|
||||
key={`path-point-${point.uuid}`}
|
||||
|
||||
@@ -10,13 +10,13 @@ type PathPoint = {
|
||||
};
|
||||
|
||||
function Simulation() {
|
||||
const [simulationPaths, setSimulationPaths] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }[][]>([]);
|
||||
const [simulationStates, setSimulationStates] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }[][]>([]);
|
||||
const [connections, setConnections] = useState<{ start: PathPoint; end: PathPoint }[]>([]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PathCreator simulationPaths={simulationPaths} setSimulationPaths={setSimulationPaths} connections={connections} setConnections={setConnections} />
|
||||
{simulationPaths.map((path, index) => (
|
||||
<PathCreator simulationStates={simulationStates} setSimulationStates={setSimulationStates} connections={connections} setConnections={setConnections} />
|
||||
{simulationStates.map((path, index) => (
|
||||
<PathFlow key={index} path={path} connections={connections} />
|
||||
))}
|
||||
</>
|
||||
|
||||
@@ -5,6 +5,14 @@ import { useDroppedObjectsStore } from "../../store/useDroppedObjectsStore";
|
||||
import { useZoneWidgetStore } from "../../store/useZone3DWidgetStore";
|
||||
import useTemplateStore from "../../store/useTemplateStore";
|
||||
|
||||
type WidgetData = {
|
||||
id: string;
|
||||
type: string;
|
||||
position: [number, number, number];
|
||||
rotation?: [number, number, number];
|
||||
tempPosition?: [number, number, number];
|
||||
};
|
||||
|
||||
export default function SocketRealTimeViz() {
|
||||
const { visualizationSocket } = useSocketStore();
|
||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||
@@ -14,6 +22,7 @@ export default function SocketRealTimeViz() {
|
||||
const { addWidget } = useZoneWidgetStore()
|
||||
const { templates, removeTemplate } = useTemplateStore();
|
||||
const { setTemplates } = useTemplateStore();
|
||||
const { zoneWidgetData, setZoneWidgetData, updateWidgetPosition, updateWidgetRotation } = useZoneWidgetStore();
|
||||
|
||||
useEffect(() => {
|
||||
const email = localStorage.getItem("email") || "";
|
||||
@@ -132,14 +141,36 @@ export default function SocketRealTimeViz() {
|
||||
});
|
||||
//add 3D Widget response
|
||||
visualizationSocket.on("viz-widget3D:response:updates", (add3DWidget: any) => {
|
||||
console.log('add3DWidget: ', add3DWidget);
|
||||
|
||||
console.log('add3DWidget: ', add3DWidget);
|
||||
if (add3DWidget.success) {
|
||||
console.log('add3DWidget: ', add3DWidget);
|
||||
if (add3DWidget.message === "Widget created successfully") {
|
||||
addWidget(add3DWidget.data.zoneId, add3DWidget.data.widget);
|
||||
}
|
||||
}
|
||||
});
|
||||
//delete 3D Widget response
|
||||
visualizationSocket.on("viz-widget3D:response:delete", (delete3DWidget: any) => {
|
||||
console.log('delete3DWidget: ', delete3DWidget);
|
||||
// "3DWidget delete unsuccessfull"
|
||||
if (delete3DWidget.success && delete3DWidget.message === "3DWidget delete successfull") {
|
||||
const activeZoneWidgets = zoneWidgetData[delete3DWidget.data.zoneId] || [];
|
||||
setZoneWidgetData(
|
||||
delete3DWidget.data.zoneId,
|
||||
activeZoneWidgets.filter((w: WidgetData) => w.id !== delete3DWidget.data.id)
|
||||
);
|
||||
}
|
||||
});
|
||||
//update3D widget response
|
||||
visualizationSocket.on("viz-widget3D:response:modifyPositionRotation", (update3DWidget: any) => {
|
||||
console.log('update3DWidget: ', update3DWidget);
|
||||
|
||||
if (update3DWidget.success && update3DWidget.message==="widget update successfully") {
|
||||
updateWidgetPosition(update3DWidget.data.zoneId, update3DWidget.data.widget.id, update3DWidget.data.widget.position);
|
||||
updateWidgetRotation(update3DWidget.data.zoneId, update3DWidget.data.widget.id, update3DWidget.data.widget.rotation);
|
||||
}
|
||||
});
|
||||
// add Template response
|
||||
visualizationSocket.on("viz-template:response:add", (addingTemplate: any) => {
|
||||
console.log('addingTemplate: ', addingTemplate);
|
||||
|
||||
@@ -26,7 +26,7 @@ export const findEnvironment = async (organization: string, userId: string) => {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
40,
|
||||
true
|
||||
);
|
||||
return userpos;
|
||||
|
||||
@@ -14,7 +14,7 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
|
||||
const socket = io(
|
||||
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder`,
|
||||
{
|
||||
reconnection: false,
|
||||
reconnection: true,
|
||||
auth: { email, organization },
|
||||
}
|
||||
);
|
||||
@@ -22,7 +22,7 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
|
||||
const visualizationSocket = io(
|
||||
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization`,
|
||||
{
|
||||
reconnection: false,
|
||||
reconnection: true,
|
||||
auth: { email, organization },
|
||||
}
|
||||
);
|
||||
@@ -302,7 +302,13 @@ export const useDrieTemp = create<any>((set: any) => ({
|
||||
|
||||
export const useActiveUsers = create<any>((set: any) => ({
|
||||
activeUsers: [],
|
||||
setActiveUsers: (x: any) => set({ activeUsers: x }),
|
||||
setActiveUsers: (callback: (prev: any[]) => any[] | any[]) =>
|
||||
set((state: { activeUsers: any[] }) => ({
|
||||
activeUsers:
|
||||
typeof callback === "function"
|
||||
? callback(state.activeUsers)
|
||||
: callback,
|
||||
})),
|
||||
}));
|
||||
|
||||
export const useDrieUIValue = create<any>((set: any) => ({
|
||||
@@ -341,24 +347,29 @@ export const useSelectedPath = create<any>((set: any) => ({
|
||||
}));
|
||||
|
||||
interface SimulationPathsStore {
|
||||
simulationPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[];
|
||||
setSimulationPaths: (
|
||||
simulationStates: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[];
|
||||
setSimulationStates: (
|
||||
paths:
|
||||
| (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]
|
||||
| ((prev: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]
|
||||
) => (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[])
|
||||
| (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]
|
||||
| ((prev: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[]
|
||||
) => (Types.ConveyorEventsSchema | Types.VehicleEventsSchema | Types.StaticMachineEventsSchema)[])
|
||||
) => void;
|
||||
}
|
||||
|
||||
export const useSimulationPaths = create<SimulationPathsStore>((set) => ({
|
||||
simulationPaths: [],
|
||||
setSimulationPaths: (paths) =>
|
||||
export const useSimulationStates = create<SimulationPathsStore>((set) => ({
|
||||
simulationStates: [],
|
||||
setSimulationStates: (paths) =>
|
||||
set((state) => ({
|
||||
simulationPaths:
|
||||
typeof paths === "function" ? paths(state.simulationPaths) : paths,
|
||||
simulationStates:
|
||||
typeof paths === "function" ? paths(state.simulationStates) : paths,
|
||||
})),
|
||||
}))
|
||||
|
||||
export const useNavMesh = create<any>((set: any) => ({
|
||||
navMesh: null,
|
||||
setNavMesh: (x: any) => set({ navMesh: x }),
|
||||
}));
|
||||
|
||||
export const useIsConnecting = create<any>((set: any) => ({
|
||||
isConnecting: false,
|
||||
setIsConnecting: (x: any) => set({ isConnecting: x }),
|
||||
|
||||
40
app/src/types/world/worldTypes.d.ts
vendored
40
app/src/types/world/worldTypes.d.ts
vendored
@@ -271,10 +271,10 @@ export type RefCSM = React.MutableRefObject<CSM>;
|
||||
export type RefCSMHelper = React.MutableRefObject<CSMHelper>;
|
||||
|
||||
interface PathConnection {
|
||||
fromPathUUID: string;
|
||||
fromModelUUID: string;
|
||||
fromUUID: string;
|
||||
toConnections: {
|
||||
toPathUUID: string;
|
||||
toModelUUID: string;
|
||||
toUUID: string;
|
||||
}[];
|
||||
}
|
||||
@@ -296,7 +296,7 @@ interface ConveyorEventsSchema {
|
||||
rotation: [number, number, number];
|
||||
actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
|
||||
triggers: { uuid: string; name: string; type: string; isUsed: boolean; bufferTime: number }[] | [];
|
||||
connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
|
||||
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
||||
}[];
|
||||
position: [number, number, number];
|
||||
rotation: [number, number, number];
|
||||
@@ -311,12 +311,40 @@ interface VehicleEventsSchema {
|
||||
uuid: string;
|
||||
position: [number, number, number];
|
||||
actions: { uuid: string; name: string; type: string; start: { x: number, y: number } | {}, hitCount: number, end: { x: number, y: number } | {}, buffer: number };
|
||||
connections: { source: { modelUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
|
||||
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
||||
speed: number;
|
||||
};
|
||||
position: [number, number, number];
|
||||
}
|
||||
|
||||
interface StaticMachineEventsSchema {
|
||||
modeluuid: string;
|
||||
modelName: string;
|
||||
type: 'StaticMachine';
|
||||
points: {
|
||||
uuid: string;
|
||||
position: [number, number, number];
|
||||
actions: { uuid: string; name: string; buffer: number | string; material: string; isUsed: boolean };
|
||||
triggers: { uuid: string; name: string; type: string };
|
||||
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
||||
};
|
||||
position: [number, number, number];
|
||||
}
|
||||
|
||||
interface ArmBotEventsSchema {
|
||||
modeluuid: string;
|
||||
modelName: string;
|
||||
type: 'ArmBot';
|
||||
points: {
|
||||
uuid: string;
|
||||
position: [number, number, number];
|
||||
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[] };
|
||||
triggers: { uuid: string; name: string; type: string };
|
||||
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
||||
};
|
||||
position: [number, number, number];
|
||||
}
|
||||
|
||||
export type EventData = {
|
||||
modeluuid: string;
|
||||
modelname: string;
|
||||
@@ -333,7 +361,7 @@ export type EventData = {
|
||||
rotation: [number, number, number];
|
||||
actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
|
||||
triggers: { uuid: string; name: string; type: string; isUsed: boolean; bufferTime: number }[] | [];
|
||||
connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
|
||||
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
||||
}[];
|
||||
speed: number | string;
|
||||
} | {
|
||||
@@ -342,7 +370,7 @@ export type EventData = {
|
||||
uuid: string;
|
||||
position: [number, number, number];
|
||||
actions: { uuid: string; name: string; type: string; start: { x: number, y: number } | {}, hitCount: number, end: { x: number, y: number } | {}, buffer: number };
|
||||
connections: { source: { modelUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
|
||||
connections: { source: { modelUUID: string; pointUUID: string }; targets: { modelUUID: string; pointUUID: string }[] };
|
||||
speed: number;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user