simulation #45
2
app/.env
2
app/.env
@@ -11,7 +11,7 @@ REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000
|
|||||||
REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
|
REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
|
||||||
|
|
||||||
# Base URL for the asset library server, used for asset library images and model blob id.
|
# Base URL for the asset library server, used for asset library images and model blob id.
|
||||||
REACT_APP_SERVER_ASSET_LIBRARY_URL=192.168.0.111:3501
|
REACT_APP_SERVER_ASSET_LIBRARY_URL=185.100.212.76:50011
|
||||||
|
|
||||||
# base url for IoT socket server
|
# base url for IoT socket server
|
||||||
REACT_APP_IOT_SOCKET_SERVER_URL =185.100.212.76:5010
|
REACT_APP_IOT_SOCKET_SERVER_URL =185.100.212.76:5010
|
||||||
|
|||||||
BIN
app/src/assets/gltf-glb/box.glb
Normal file
BIN
app/src/assets/gltf-glb/box.glb
Normal file
Binary file not shown.
@@ -14,6 +14,7 @@ import {
|
|||||||
useSelectedActionSphere,
|
useSelectedActionSphere,
|
||||||
useSelectedPath,
|
useSelectedPath,
|
||||||
useSimulationPaths,
|
useSimulationPaths,
|
||||||
|
useSocketStore,
|
||||||
} from "../../../../store/store";
|
} from "../../../../store/store";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
@@ -26,6 +27,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
const { selectedPath, setSelectedPath } = useSelectedPath();
|
const { selectedPath, setSelectedPath } = useSelectedPath();
|
||||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||||
const { floorItems, setFloorItems } = useFloorItems();
|
const { floorItems, setFloorItems } = useFloorItems();
|
||||||
|
const { socket } = useSocketStore();
|
||||||
|
|
||||||
const actionsContainerRef = useRef<HTMLDivElement>(null);
|
const actionsContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const triggersContainerRef = useRef<HTMLDivElement>(null);
|
const triggersContainerRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -37,20 +39,28 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema => path.type === "Conveyor"
|
(path): path is Types.ConveyorEventsSchema => path.type === "Conveyor"
|
||||||
)
|
)
|
||||||
.flatMap((path) => path.points)
|
.flatMap((path) => path.points)
|
||||||
.find((point) => point.uuid === selectedActionSphere.point.uuid);
|
.find((point) => point.uuid === selectedActionSphere.points.uuid);
|
||||||
}, [selectedActionSphere, simulationPaths]);
|
}, [selectedActionSphere, simulationPaths]);
|
||||||
|
|
||||||
const updateBackend = async (updatedPath: Types.ConveyorEventsSchema | undefined) => {
|
const updateBackend = async (updatedPath: Types.ConveyorEventsSchema | undefined) => {
|
||||||
if (!updatedPath) return;
|
if (!updatedPath) return;
|
||||||
// const email = localStorage.getItem("email");
|
const email = localStorage.getItem("email");
|
||||||
// const organization = email ? email.split("@")[1].split(".")[0] : "";
|
const organization = email ? email.split("@")[1].split(".")[0] : "";
|
||||||
// console.log('updatedPath: ', updatedPath);
|
|
||||||
// const a = await setEventApi(
|
// await setEventApi(
|
||||||
// organization,
|
// organization,
|
||||||
// updatedPath.modeluuid,
|
// updatedPath.modeluuid,
|
||||||
// updatedPath.points
|
// { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
|
||||||
// );
|
// );
|
||||||
// console.log('a: ', a);
|
|
||||||
|
const data = {
|
||||||
|
organization: organization,
|
||||||
|
modeluuid: updatedPath.modeluuid,
|
||||||
|
eventData: { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v2:model-asset:updateEventData', data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleAddAction = () => {
|
const handleAddAction = () => {
|
||||||
@@ -61,7 +71,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
return {
|
return {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) => {
|
points: path.points.map((point) => {
|
||||||
if (point.uuid === selectedActionSphere.point.uuid) {
|
if (point.uuid === selectedActionSphere.points.uuid) {
|
||||||
const actionIndex = point.actions.length;
|
const actionIndex = point.actions.length;
|
||||||
const newAction = {
|
const newAction = {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -86,7 +96,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -102,7 +112,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
actions: point.actions.filter(
|
actions: point.actions.filter(
|
||||||
@@ -119,7 +129,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -135,7 +145,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
actions: point.actions.map((action) =>
|
actions: point.actions.map((action) =>
|
||||||
@@ -167,7 +177,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -181,7 +191,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema => path.type === "Conveyor"
|
(path): path is Types.ConveyorEventsSchema => path.type === "Conveyor"
|
||||||
)
|
)
|
||||||
.flatMap((path) => path.points)
|
.flatMap((path) => path.points)
|
||||||
.find((p) => p.uuid === selectedActionSphere.point.uuid)
|
.find((p) => p.uuid === selectedActionSphere.points.uuid)
|
||||||
?.actions.find((a) => a.uuid === uuid);
|
?.actions.find((a) => a.uuid === uuid);
|
||||||
|
|
||||||
if (updatedAction) {
|
if (updatedAction) {
|
||||||
@@ -202,7 +212,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
actions: point.actions.map((action) =>
|
actions: point.actions.map((action) =>
|
||||||
@@ -222,7 +232,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -249,7 +259,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
actions: point.actions.map((action) =>
|
actions: point.actions.map((action) =>
|
||||||
@@ -266,7 +276,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -285,7 +295,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
actions: point.actions.map((action) =>
|
actions: point.actions.map((action) =>
|
||||||
@@ -304,7 +314,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -323,7 +333,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -340,7 +350,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) => {
|
points: path.points.map((point) => {
|
||||||
if (point.uuid === selectedActionSphere.point.uuid) {
|
if (point.uuid === selectedActionSphere.points.uuid) {
|
||||||
const triggerIndex = point.triggers.length;
|
const triggerIndex = point.triggers.length;
|
||||||
const newTrigger = {
|
const newTrigger = {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -362,7 +372,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -378,7 +388,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
triggers: point.triggers.filter(
|
triggers: point.triggers.filter(
|
||||||
@@ -395,7 +405,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -411,7 +421,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
triggers: point.triggers.map((trigger) =>
|
triggers: point.triggers.map((trigger) =>
|
||||||
@@ -430,7 +440,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -456,7 +466,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
actions: point.actions.map((action) => ({
|
actions: point.actions.map((action) => ({
|
||||||
@@ -474,7 +484,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -502,7 +512,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
triggers: point.triggers.map((trigger) => ({
|
triggers: point.triggers.map((trigger) => ({
|
||||||
@@ -520,7 +530,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
@@ -547,7 +557,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
? {
|
? {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
triggers: point.triggers.map((trigger) =>
|
triggers: point.triggers.map((trigger) =>
|
||||||
@@ -566,7 +576,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||||||
(path): path is Types.ConveyorEventsSchema =>
|
(path): path is Types.ConveyorEventsSchema =>
|
||||||
path.type === "Conveyor" &&
|
path.type === "Conveyor" &&
|
||||||
path.points.some(
|
path.points.some(
|
||||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
(point) => point.uuid === selectedActionSphere.points.uuid
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
updateBackend(updatedPath);
|
updateBackend(updatedPath);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, { useRef, useMemo } from "react";
|
import React, { useRef, useMemo } from "react";
|
||||||
import { InfoIcon } from "../../../icons/ExportCommonIcons";
|
import { InfoIcon } from "../../../icons/ExportCommonIcons";
|
||||||
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
||||||
import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationPaths } from "../../../../store/store";
|
import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationPaths, useSocketStore } from "../../../../store/store";
|
||||||
import * as Types from '../../../../types/world/worldTypes';
|
import * as Types from '../../../../types/world/worldTypes';
|
||||||
import PositionInput from "../customInput/PositionInputs";
|
import PositionInput from "../customInput/PositionInputs";
|
||||||
|
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
||||||
|
|
||||||
const VehicleMechanics: React.FC = () => {
|
const VehicleMechanics: React.FC = () => {
|
||||||
const { selectedActionSphere } = useSelectedActionSphere();
|
const { selectedActionSphere } = useSelectedActionSphere();
|
||||||
@@ -11,46 +12,68 @@ const VehicleMechanics: React.FC = () => {
|
|||||||
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
|
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
|
||||||
const { editingPoint, setEditingPoint } = useEditingPoint();
|
const { editingPoint, setEditingPoint } = useEditingPoint();
|
||||||
const { previewPosition, setPreviewPosition } = usePreviewPosition();
|
const { previewPosition, setPreviewPosition } = usePreviewPosition();
|
||||||
|
const { socket } = useSocketStore();
|
||||||
|
|
||||||
const propertiesContainerRef = useRef<HTMLDivElement>(null);
|
const propertiesContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const { selectedPoint, connectedPointUuids } = useMemo(() => {
|
const { selectedPoint, connectedPointUuids } = useMemo(() => {
|
||||||
if (!selectedActionSphere?.point?.uuid) return { selectedPoint: null, connectedPointUuids: [] };
|
if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] };
|
||||||
|
|
||||||
const vehiclePaths = simulationPaths.filter(
|
const vehiclePaths = simulationPaths.filter(
|
||||||
(path): path is Types.VehicleEventsSchema => path.type === "Vehicle"
|
(path): path is Types.VehicleEventsSchema => path.type === "Vehicle"
|
||||||
);
|
);
|
||||||
|
|
||||||
const point = vehiclePaths.find(
|
const points = vehiclePaths.find(
|
||||||
(path) => path.point.uuid === selectedActionSphere.point.uuid
|
(path) => path.points.uuid === selectedActionSphere.points.uuid
|
||||||
)?.point;
|
)?.points;
|
||||||
|
|
||||||
if (!point) return { selectedPoint: null, connectedPointUuids: [] };
|
if (!points) return { selectedPoint: null, connectedPointUuids: [] };
|
||||||
|
|
||||||
const connectedUuids: string[] = [];
|
const connectedUuids: string[] = [];
|
||||||
if (point.connections?.targets) {
|
if (points.connections?.targets) {
|
||||||
point.connections.targets.forEach(target => {
|
points.connections.targets.forEach(target => {
|
||||||
connectedUuids.push(target.pointUUID);
|
connectedUuids.push(target.pointUUID);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedPoint: point,
|
selectedPoint: points,
|
||||||
connectedPointUuids: connectedUuids
|
connectedPointUuids: connectedUuids
|
||||||
};
|
};
|
||||||
}, [selectedActionSphere, simulationPaths]);
|
}, [selectedActionSphere, simulationPaths]);
|
||||||
|
|
||||||
const handleActionUpdate = React.useCallback((updatedAction: Partial<Types.VehicleEventsSchema['point']['actions']>) => {
|
const updateBackend = async (updatedPath: Types.VehicleEventsSchema | undefined) => {
|
||||||
if (!selectedActionSphere?.point?.uuid) return;
|
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 data = {
|
||||||
|
organization: organization,
|
||||||
|
modeluuid: updatedPath.modeluuid,
|
||||||
|
eventData: { type: "Vehicle", points: updatedPath.points }
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit('v2:model-asset:updateEventData', data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleActionUpdate = React.useCallback((updatedAction: Partial<Types.VehicleEventsSchema['points']['actions']>) => {
|
||||||
|
if (!selectedActionSphere?.points?.uuid) return;
|
||||||
|
|
||||||
const updatedPaths = simulationPaths.map((path) => {
|
const updatedPaths = simulationPaths.map((path) => {
|
||||||
if (path.type === "Vehicle" && path.point.uuid === selectedActionSphere.point.uuid) {
|
if (path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid) {
|
||||||
return {
|
return {
|
||||||
...path,
|
...path,
|
||||||
point: {
|
points: {
|
||||||
...path.point,
|
...path.points,
|
||||||
actions: {
|
actions: {
|
||||||
...path.point.actions,
|
...path.points.actions,
|
||||||
...updatedAction
|
...updatedAction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,14 +82,15 @@ const VehicleMechanics: React.FC = () => {
|
|||||||
return path;
|
return path;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatedPath = updatedPaths.find(
|
||||||
|
(path): path is Types.VehicleEventsSchema =>
|
||||||
|
path.type === "Vehicle" &&
|
||||||
|
path.points.uuid === selectedActionSphere.points.uuid
|
||||||
|
);
|
||||||
|
updateBackend(updatedPath);
|
||||||
|
|
||||||
setSimulationPaths(updatedPaths);
|
setSimulationPaths(updatedPaths);
|
||||||
}, [selectedActionSphere?.point?.uuid, simulationPaths, setSimulationPaths]);
|
}, [selectedActionSphere?.points?.uuid, simulationPaths, setSimulationPaths]);
|
||||||
|
|
||||||
const handleStartPointChange = React.useCallback((position: { x: number, y: number }) => {
|
|
||||||
}, [handleActionUpdate]);
|
|
||||||
|
|
||||||
const handleEndPointChange = React.useCallback((position: { x: number, y: number }) => {
|
|
||||||
}, [handleActionUpdate]);
|
|
||||||
|
|
||||||
const handleHitCountChange = React.useCallback((hitCount: number) => {
|
const handleHitCountChange = React.useCallback((hitCount: number) => {
|
||||||
handleActionUpdate({ hitCount });
|
handleActionUpdate({ hitCount });
|
||||||
@@ -77,14 +101,14 @@ const VehicleMechanics: React.FC = () => {
|
|||||||
}, [handleActionUpdate]);
|
}, [handleActionUpdate]);
|
||||||
|
|
||||||
const handleSpeedChange = React.useCallback((speed: number) => {
|
const handleSpeedChange = React.useCallback((speed: number) => {
|
||||||
if (!selectedActionSphere?.point?.uuid) return;
|
if (!selectedActionSphere?.points?.uuid) return;
|
||||||
|
|
||||||
const updatedPaths = simulationPaths.map((path) => {
|
const updatedPaths = simulationPaths.map((path) => {
|
||||||
if (path.type === "Vehicle" && path.point.uuid === selectedActionSphere.point.uuid) {
|
if (path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid) {
|
||||||
return {
|
return {
|
||||||
...path,
|
...path,
|
||||||
point: {
|
points: {
|
||||||
...path.point,
|
...path.points,
|
||||||
speed: speed
|
speed: speed
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -92,8 +116,15 @@ const VehicleMechanics: React.FC = () => {
|
|||||||
return path;
|
return path;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatedPath = updatedPaths.find(
|
||||||
|
(path): path is Types.VehicleEventsSchema =>
|
||||||
|
path.type === "Vehicle" &&
|
||||||
|
path.points.uuid === selectedActionSphere.points.uuid
|
||||||
|
);
|
||||||
|
updateBackend(updatedPath);
|
||||||
|
|
||||||
setSimulationPaths(updatedPaths);
|
setSimulationPaths(updatedPaths);
|
||||||
}, [selectedActionSphere?.point?.uuid, simulationPaths, setSimulationPaths]);
|
}, [selectedActionSphere?.points?.uuid, simulationPaths, setSimulationPaths]);
|
||||||
|
|
||||||
const handleStartEyeDropClick = () => {
|
const handleStartEyeDropClick = () => {
|
||||||
setEditingPoint('start');
|
setEditingPoint('start');
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
|
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
|
||||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
|
||||||
import { useActiveTool } from "../../../store/store";
|
import { useActiveTool } from "../../../store/store";
|
||||||
|
import {
|
||||||
|
useAnimationPlaySpeed,
|
||||||
|
usePauseButtonStore,
|
||||||
|
usePlayButtonStore,
|
||||||
|
useResetButtonStore,
|
||||||
|
} from "../../../store/usePlayButtonStore";
|
||||||
|
|
||||||
const SimulationPlayer: React.FC = () => {
|
const SimulationPlayer: React.FC = () => {
|
||||||
const [speed, setSpeed] = useState<number>(1);
|
const { speed, setSpeed } = useAnimationPlaySpeed();
|
||||||
const [playSimulation, setPlaySimulation] = useState(false);
|
const [playSimulation, setPlaySimulation] = useState(false);
|
||||||
const { setIsPlaying } = usePlayButtonStore();
|
const { setIsPlaying } = usePlayButtonStore();
|
||||||
const sliderRef = useRef<HTMLDivElement>(null);
|
const sliderRef = useRef<HTMLDivElement>(null);
|
||||||
const isDragging = useRef(false);
|
const isDragging = useRef(false);
|
||||||
const { setActiveTool } = useActiveTool();
|
const { setActiveTool } = useActiveTool();
|
||||||
|
const { isPaused, setIsPaused } = usePauseButtonStore();
|
||||||
|
const { isReset, setReset } = useResetButtonStore();
|
||||||
|
|
||||||
// Button functions
|
// Button functions
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
|
setReset(true);
|
||||||
setSpeed(1);
|
setSpeed(1);
|
||||||
};
|
};
|
||||||
const handlePlayStop = () => {
|
const handlePlayStop = () => {
|
||||||
|
setIsPaused(!isPaused);
|
||||||
setPlaySimulation(!playSimulation);
|
setPlaySimulation(!playSimulation);
|
||||||
};
|
};
|
||||||
const handleExit = () => {
|
const handleExit = () => {
|
||||||
@@ -30,7 +39,7 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const calculateHandlePosition = () => {
|
const calculateHandlePosition = () => {
|
||||||
return ((speed - 0.5) / (50 - 0.5)) * 100;
|
return ((speed - 0.5) / (8 - 0.5)) * 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseDown = () => {
|
const handleMouseDown = () => {
|
||||||
@@ -118,7 +127,7 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="0.5"
|
min="0.5"
|
||||||
max="50"
|
max="8"
|
||||||
step="0.1"
|
step="0.1"
|
||||||
value={speed}
|
value={speed}
|
||||||
onChange={handleSpeedChange}
|
onChange={handleSpeedChange}
|
||||||
@@ -126,7 +135,7 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="max-value">50x</div>
|
<div className="max-value">8x</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,13 +9,12 @@ import {
|
|||||||
useSelectedActionSphere,
|
useSelectedActionSphere,
|
||||||
useSimulationPaths,
|
useSimulationPaths,
|
||||||
} from "../../../store/store";
|
} from "../../../store/store";
|
||||||
|
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||||
|
|
||||||
const Agv = ({
|
const Agv = ({
|
||||||
lines,
|
lines,
|
||||||
plane,
|
|
||||||
}: {
|
}: {
|
||||||
lines: Types.RefLines;
|
lines: Types.RefLines;
|
||||||
plane: Types.RefMesh;
|
|
||||||
}) => {
|
}) => {
|
||||||
const [pathPoints, setPathPoints] = useState<
|
const [pathPoints, setPathPoints] = useState<
|
||||||
{
|
{
|
||||||
@@ -23,6 +22,7 @@ const Agv = ({
|
|||||||
modelSpeed: number;
|
modelSpeed: number;
|
||||||
bufferTime: number;
|
bufferTime: number;
|
||||||
points: { x: number; y: number; z: number }[];
|
points: { x: number; y: number; z: number }[];
|
||||||
|
hitCount: number;
|
||||||
}[]
|
}[]
|
||||||
>([]);
|
>([]);
|
||||||
const { simulationPaths } = useSimulationPaths();
|
const { simulationPaths } = useSimulationPaths();
|
||||||
@@ -34,7 +34,7 @@ const Agv = ({
|
|||||||
(val: any) => val.modelName === "agv"
|
(val: any) => val.modelName === "agv"
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("agvModels: ", agvModels);
|
|
||||||
let findMesh = agvModels.filter(
|
let findMesh = agvModels.filter(
|
||||||
(val: any) =>
|
(val: any) =>
|
||||||
val.modeluuid === selectedActionSphere?.path?.modeluuid &&
|
val.modeluuid === selectedActionSphere?.path?.modeluuid &&
|
||||||
@@ -43,18 +43,19 @@ const Agv = ({
|
|||||||
|
|
||||||
const result =
|
const result =
|
||||||
findMesh.length > 0 &&
|
findMesh.length > 0 &&
|
||||||
findMesh[0].type === "Vehicle" &&
|
findMesh[0].type === "Vehicle" &&
|
||||||
typeof findMesh[0].point?.actions.start === "object" &&
|
typeof findMesh[0].points?.actions.start === "object" &&
|
||||||
typeof findMesh[0].point?.actions.end === "object" &&
|
typeof findMesh[0].points?.actions.end === "object" &&
|
||||||
"x" in findMesh[0].point.actions.start &&
|
"x" in findMesh[0].points.actions.start &&
|
||||||
"y" in findMesh[0].point.actions.start &&
|
"y" in findMesh[0].points.actions.start &&
|
||||||
"x" in findMesh[0].point.actions.end &&
|
"x" in findMesh[0].points.actions.end &&
|
||||||
"y" in findMesh[0].point.actions.end
|
"y" in findMesh[0].points.actions.end
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
modelUuid: findMesh[0].modeluuid, // Ensure it's a number
|
modelUuid: findMesh[0].modeluuid, // Ensure it's a number
|
||||||
modelSpeed: findMesh[0].point.speed,
|
modelSpeed: findMesh[0].points.speed,
|
||||||
bufferTime: findMesh[0].point.actions.buffer,
|
bufferTime: findMesh[0].points.actions.buffer,
|
||||||
|
hitCount: findMesh[0].points.actions.hitCount,
|
||||||
points: [
|
points: [
|
||||||
{
|
{
|
||||||
x: findMesh[0].position[0],
|
x: findMesh[0].position[0],
|
||||||
@@ -62,14 +63,14 @@ const Agv = ({
|
|||||||
z: findMesh[0].position[2],
|
z: findMesh[0].position[2],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: findMesh[0].point.actions.start.x,
|
x: findMesh[0].points.actions.start.x,
|
||||||
y: 0,
|
y: 0,
|
||||||
z: findMesh[0].point.actions.start.y,
|
z: findMesh[0].points.actions.start.y,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: findMesh[0].point.actions.end.x,
|
x: findMesh[0].points.actions.end.x,
|
||||||
y: 0,
|
y: 0,
|
||||||
z: findMesh[0].point.actions.end.y,
|
z: findMesh[0].points.actions.end.y,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -106,12 +107,11 @@ const Agv = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PolygonGenerator groupRef={groupRef} lines={lines} plane={plane} />
|
<PolygonGenerator groupRef={groupRef} lines={lines} />
|
||||||
<NavMeshDetails
|
<NavMeshDetails
|
||||||
lines={lines}
|
lines={lines}
|
||||||
setNavMesh={setNavMesh}
|
setNavMesh={setNavMesh}
|
||||||
groupRef={groupRef}
|
groupRef={groupRef}
|
||||||
plane={plane}
|
|
||||||
/>
|
/>
|
||||||
{pathPoints.map((pair, i) => (
|
{pathPoints.map((pair, i) => (
|
||||||
<>
|
<>
|
||||||
@@ -122,6 +122,7 @@ const Agv = ({
|
|||||||
key={i}
|
key={i}
|
||||||
speed={pair.modelSpeed}
|
speed={pair.modelSpeed}
|
||||||
bufferTime={pair.bufferTime}
|
bufferTime={pair.bufferTime}
|
||||||
|
hitCount={pair.hitCount}
|
||||||
/>
|
/>
|
||||||
{/* {pair.points.length > 2 && (
|
{/* {pair.points.length > 2 && (
|
||||||
<>
|
<>
|
||||||
@@ -149,7 +150,12 @@ const Agv = ({
|
|||||||
)} */}
|
)} */}
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
<group ref={groupRef} visible={false} name="Meshes"></group>
|
<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>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,14 +10,12 @@ interface NavMeshDetailsProps {
|
|||||||
setNavMesh: (navMesh: any) => void;
|
setNavMesh: (navMesh: any) => void;
|
||||||
groupRef: React.MutableRefObject<THREE.Group | null>;
|
groupRef: React.MutableRefObject<THREE.Group | null>;
|
||||||
lines: Types.RefLines;
|
lines: Types.RefLines;
|
||||||
plane: Types.RefMesh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function NavMeshDetails({
|
export default function NavMeshDetails({
|
||||||
lines,
|
lines,
|
||||||
setNavMesh,
|
setNavMesh,
|
||||||
groupRef,
|
groupRef,
|
||||||
plane,
|
|
||||||
}: NavMeshDetailsProps) {
|
}: NavMeshDetailsProps) {
|
||||||
const { scene } = useThree();
|
const { scene } = useThree();
|
||||||
|
|
||||||
@@ -34,14 +32,13 @@ export default function NavMeshDetails({
|
|||||||
|
|
||||||
const [positions, indices] = getPositionsAndIndices(meshes);
|
const [positions, indices] = getPositionsAndIndices(meshes);
|
||||||
|
|
||||||
const cs = 0.25;
|
const cellSize = 0.35;
|
||||||
const ch = 0.69;
|
const cellHeight = 0.7;
|
||||||
const walkableRadius = 0.5;
|
const walkableRadius = 0.5;
|
||||||
|
|
||||||
const { success, navMesh } = generateSoloNavMesh(positions, indices, {
|
const { success, navMesh } = generateSoloNavMesh(positions, indices, {
|
||||||
cs,
|
cs: cellSize,
|
||||||
ch,
|
ch: cellHeight,
|
||||||
walkableRadius: Math.round(walkableRadius / ch),
|
walkableRadius: Math.round(walkableRadius / cellHeight),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!success || !navMesh) {
|
if (!success || !navMesh) {
|
||||||
@@ -50,10 +47,14 @@ export default function NavMeshDetails({
|
|||||||
|
|
||||||
setNavMesh(navMesh);
|
setNavMesh(navMesh);
|
||||||
|
|
||||||
|
scene.children
|
||||||
|
.filter((child) => child instanceof DebugDrawer)
|
||||||
|
.forEach((child) => scene.remove(child));
|
||||||
|
|
||||||
const debugDrawer = new DebugDrawer();
|
const debugDrawer = new DebugDrawer();
|
||||||
debugDrawer.drawNavMesh(navMesh);
|
debugDrawer.drawNavMesh(navMesh);
|
||||||
// scene.add(debugDrawer);
|
// scene.add(debugDrawer);
|
||||||
} catch (error) {}
|
} catch (error) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
initializeNavigation();
|
initializeNavigation();
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ interface PathNavigatorProps {
|
|||||||
id: string;
|
id: string;
|
||||||
speed: number;
|
speed: number;
|
||||||
bufferTime: number;
|
bufferTime: number;
|
||||||
|
hitCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PathNavigator({
|
export default function PathNavigator({
|
||||||
@@ -20,6 +21,7 @@ export default function PathNavigator({
|
|||||||
id,
|
id,
|
||||||
speed,
|
speed,
|
||||||
bufferTime,
|
bufferTime,
|
||||||
|
hitCount,
|
||||||
}: PathNavigatorProps) {
|
}: PathNavigatorProps) {
|
||||||
const [path, setPath] = useState<[number, number, number][]>([]);
|
const [path, setPath] = useState<[number, number, number][]>([]);
|
||||||
const progressRef = useRef(0);
|
const progressRef = useRef(0);
|
||||||
@@ -32,7 +34,7 @@ export default function PathNavigator({
|
|||||||
const [startPoint, setStartPoint] = useState(new THREE.Vector3());
|
const [startPoint, setStartPoint] = useState(new THREE.Vector3());
|
||||||
const isWaiting = useRef<boolean>(false); // Flag to track waiting state
|
const isWaiting = useRef<boolean>(false); // Flag to track waiting state
|
||||||
const delayTime = bufferTime;
|
const delayTime = bufferTime;
|
||||||
|
|
||||||
const movingForward = useRef<boolean>(true); // Tracks whether the object is moving forward
|
const movingForward = useRef<boolean>(true); // Tracks whether the object is moving forward
|
||||||
// Compute distances and total distance when the path changes
|
// Compute distances and total distance when the path changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -52,6 +54,7 @@ export default function PathNavigator({
|
|||||||
progressRef.current = 0;
|
progressRef.current = 0;
|
||||||
}, [path]);
|
}, [path]);
|
||||||
|
|
||||||
|
// Compute the path using NavMeshQuery
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!navMesh || selectedPoints.length === 0) return;
|
if (!navMesh || selectedPoints.length === 0) return;
|
||||||
|
|
||||||
@@ -119,17 +122,22 @@ export default function PathNavigator({
|
|||||||
if (!isWaiting.current) {
|
if (!isWaiting.current) {
|
||||||
isWaiting.current = true; // Set waiting flag
|
isWaiting.current = true; // Set waiting flag
|
||||||
|
|
||||||
setTimeout(() => {
|
if (movingForward.current) {
|
||||||
progressRef.current = 0; // Reset progress
|
// Moving forward: reached the end, wait for `delay`
|
||||||
movingForward.current = !movingForward.current; // Toggle direction
|
// console.log(
|
||||||
|
// "Reached end position. Waiting for delay:",
|
||||||
// Reverse the path and distances arrays
|
// delayTime,
|
||||||
path.reverse();
|
// "seconds"
|
||||||
distancesRef.current.reverse();
|
// );
|
||||||
|
setTimeout(() => {
|
||||||
// Reset the waiting flag
|
// After delay, reverse direction
|
||||||
isWaiting.current = false;
|
movingForward.current = false;
|
||||||
}, delayTime * 1000); // Convert seconds to milliseconds
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -154,7 +162,7 @@ export default function PathNavigator({
|
|||||||
findObject.position.copy(startPoint);
|
findObject.position.copy(startPoint);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{path.length > 0 && (
|
{path.length > 0 && (
|
||||||
|
|||||||
@@ -6,21 +6,12 @@ import arrayLinesToObject from "../geomentries/lines/lineConvertions/arrayLinesT
|
|||||||
interface PolygonGeneratorProps {
|
interface PolygonGeneratorProps {
|
||||||
groupRef: React.MutableRefObject<THREE.Group | null>;
|
groupRef: React.MutableRefObject<THREE.Group | null>;
|
||||||
lines: Types.RefLines;
|
lines: Types.RefLines;
|
||||||
plane: Types.RefMesh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PolygonGenerator({
|
export default function PolygonGenerator({
|
||||||
groupRef,
|
groupRef,
|
||||||
lines,
|
lines,
|
||||||
plane,
|
|
||||||
}: PolygonGeneratorProps) {
|
}: PolygonGeneratorProps) {
|
||||||
// const [rooms, setRooms] = useState<THREE.Vector3[][]>([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (groupRef.current && plane.current) {
|
|
||||||
groupRef.current.add(plane.current.clone());
|
|
||||||
}
|
|
||||||
}, [groupRef, plane]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let allLines = arrayLinesToObject(lines.current);
|
let allLines = arrayLinesToObject(lines.current);
|
||||||
@@ -37,13 +28,14 @@ export default function PolygonGenerator({
|
|||||||
uuid: point.uuid,
|
uuid: point.uuid,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!result || result.some((line) => !line)) {
|
if (!result || result.some((line) => !line)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lineFeatures = result?.map((line: any) =>
|
const lineFeatures = result?.map((line: any) =>
|
||||||
turf.lineString(line.map((p: any) => p?.position))
|
turf.lineString(line.map((p: any) => p?.position))
|
||||||
);
|
);
|
||||||
|
|
||||||
const polygons = turf.polygonize(turf.featureCollection(lineFeatures));
|
const polygons = turf.polygonize(turf.featureCollection(lineFeatures));
|
||||||
renderWallGeometry(wallPoints);
|
renderWallGeometry(wallPoints);
|
||||||
@@ -79,8 +71,8 @@ export default function PolygonGenerator({
|
|||||||
groupRef.current?.add(mesh);
|
groupRef.current?.add(mesh);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [lines.current]);
|
}, [lines.current]);
|
||||||
|
|
||||||
const renderWallGeometry = (walls: THREE.Vector3[][]) => {
|
const renderWallGeometry = (walls: THREE.Vector3[][]) => {
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ async function handleModelLoad(
|
|||||||
tempLoader.current = undefined;
|
tempLoader.current = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newFloorItem: Types.FloorItemType = {
|
const newFloorItem: Types.EventData = {
|
||||||
modeluuid: model.uuid,
|
modeluuid: model.uuid,
|
||||||
modelname: selectedItem.name,
|
modelname: selectedItem.name,
|
||||||
modelfileID: selectedItem.id,
|
modelfileID: selectedItem.id,
|
||||||
@@ -154,7 +154,7 @@ async function handleModelLoad(
|
|||||||
if (res.type === "Conveyor") {
|
if (res.type === "Conveyor") {
|
||||||
const pointUUIDs = res.points.map(() => THREE.MathUtils.generateUUID());
|
const pointUUIDs = res.points.map(() => THREE.MathUtils.generateUUID());
|
||||||
|
|
||||||
const backendEventData: Extract<Types.FloorItemType['eventData'], { type: 'Conveyor' }> = {
|
const backendEventData: Extract<Types.EventData['eventData'], { type: 'Conveyor' }> = {
|
||||||
type: 'Conveyor',
|
type: 'Conveyor',
|
||||||
points: res.points.map((point: any, index: number) => ({
|
points: res.points.map((point: any, index: number) => ({
|
||||||
uuid: pointUUIDs[index],
|
uuid: pointUUIDs[index],
|
||||||
@@ -167,7 +167,7 @@ async function handleModelLoad(
|
|||||||
material: 'Inherit',
|
material: 'Inherit',
|
||||||
delay: 'Inherit',
|
delay: 'Inherit',
|
||||||
spawnInterval: 'Inherit',
|
spawnInterval: 'Inherit',
|
||||||
isUsed: false
|
isUsed: true
|
||||||
}],
|
}],
|
||||||
triggers: [],
|
triggers: [],
|
||||||
connections: {
|
connections: {
|
||||||
@@ -189,7 +189,7 @@ async function handleModelLoad(
|
|||||||
// { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
// { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||||
// false,
|
// false,
|
||||||
// true,
|
// true,
|
||||||
// newFloorItem.eventData
|
// { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed }
|
||||||
// );
|
// );
|
||||||
|
|
||||||
// SOCKET
|
// SOCKET
|
||||||
@@ -206,8 +206,7 @@ async function handleModelLoad(
|
|||||||
eventData: backendEventData,
|
eventData: backendEventData,
|
||||||
socketId: socket.id
|
socketId: socket.id
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('data: ', data);
|
|
||||||
setFloorItems((prevItems) => {
|
setFloorItems((prevItems) => {
|
||||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||||
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||||
@@ -222,12 +221,25 @@ async function handleModelLoad(
|
|||||||
|
|
||||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
eventData as Types.ConveyorEventsSchema | Types.VehicleEventsSchema
|
eventData as Types.ConveyorEventsSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
socket.emit("v2:model-asset:add", data);
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
} else {
|
} else if (res.type === "Vehicle") {
|
||||||
|
|
||||||
|
const pointUUID = THREE.MathUtils.generateUUID();
|
||||||
|
|
||||||
|
const backendEventData: Extract<Types.EventData['eventData'], { type: 'Vehicle' }> = {
|
||||||
|
type: "Vehicle",
|
||||||
|
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 },
|
||||||
|
connections: { source: { modelUUID: model.uuid, pointUUID: pointUUID }, targets: [] },
|
||||||
|
speed: 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// API
|
// API
|
||||||
|
|
||||||
@@ -239,7 +251,8 @@ async function handleModelLoad(
|
|||||||
// newFloorItem.position,
|
// newFloorItem.position,
|
||||||
// { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
// { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||||
// false,
|
// false,
|
||||||
// true
|
// true,
|
||||||
|
// { type: backendEventData.type, points: backendEventData.points }
|
||||||
// );
|
// );
|
||||||
|
|
||||||
// SOCKET
|
// SOCKET
|
||||||
@@ -253,15 +266,26 @@ async function handleModelLoad(
|
|||||||
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
|
eventData: { type: backendEventData.type, points: backendEventData.points },
|
||||||
socketId: socket.id
|
socketId: socket.id
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const eventData: any = backendEventData;
|
||||||
|
eventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
eventData.modelName = newFloorItem.modelname;
|
||||||
|
eventData.position = newFloorItem.position;
|
||||||
|
|
||||||
setFloorItems((prevItems) => {
|
setFloorItems((prevItems) => {
|
||||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||||
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||||
return updatedItems;
|
return updatedItems;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||||
|
...(prevEvents || []),
|
||||||
|
eventData as Types.VehicleEventsSchema
|
||||||
|
]);
|
||||||
|
|
||||||
socket.emit("v2:model-asset:add", data);
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,6 @@ const FloorItemsGroup = ({
|
|||||||
}
|
}
|
||||||
gltfLoaderWorker.postMessage({ floorItems: data });
|
gltfLoaderWorker.postMessage({ floorItems: data });
|
||||||
} else {
|
} else {
|
||||||
console.log('data: ', data);
|
|
||||||
gltfLoaderWorker.postMessage({ floorItems: [] });
|
gltfLoaderWorker.postMessage({ floorItems: [] });
|
||||||
loadInitialFloorItems(itemsGroup, setFloorItems, setSimulationPaths);
|
loadInitialFloorItems(itemsGroup, setFloorItems, setSimulationPaths);
|
||||||
updateLoadingProgress(100);
|
updateLoadingProgress(100);
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ const CamModelsGroup = () => {
|
|||||||
socket.off("userDisConnectRespones");
|
socket.off("userDisConnectRespones");
|
||||||
socket.off("cameraUpdateResponse");
|
socket.off("cameraUpdateResponse");
|
||||||
};
|
};
|
||||||
}, [socket, activeUsers]);
|
}, [socket]);
|
||||||
|
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
|
|||||||
@@ -143,10 +143,6 @@ export default function SocketResponses({
|
|||||||
isVisible: data.data.isVisible,
|
isVisible: data.data.isVisible,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.data.eventData) {
|
|
||||||
newFloorItem.eventData = data.data.eventData;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFloorItems((prevItems: any) => {
|
setFloorItems((prevItems: any) => {
|
||||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||||
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||||
@@ -221,10 +217,6 @@ export default function SocketResponses({
|
|||||||
isVisible: data.data.isVisible,
|
isVisible: data.data.isVisible,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.data.eventData) {
|
|
||||||
newFloorItem.eventData = data.data.eventData;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFloorItems((prevItems: any) => {
|
setFloorItems((prevItems: any) => {
|
||||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||||
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ async function loadInitialFloorItems(
|
|||||||
localStorage.setItem("FloorItems", JSON.stringify(items));
|
localStorage.setItem("FloorItems", JSON.stringify(items));
|
||||||
await initializeDB();
|
await initializeDB();
|
||||||
|
|
||||||
if (items.message === "floorItems not found") return;
|
if (items.message === "floorItems not found") return;
|
||||||
|
|
||||||
if (items) {
|
if (items) {
|
||||||
const storedFloorItems: Types.FloorItems = items;
|
const storedFloorItems: Types.EventData[] = items;
|
||||||
const loader = new GLTFLoader();
|
const loader = new GLTFLoader();
|
||||||
const dracoLoader = new DRACOLoader();
|
const dracoLoader = new DRACOLoader();
|
||||||
|
|
||||||
@@ -53,7 +53,6 @@ async function loadInitialFloorItems(
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (const item of storedFloorItems) {
|
for (const item of storedFloorItems) {
|
||||||
console.log('item: ', item);
|
|
||||||
if (!item.modelfileID) return;
|
if (!item.modelfileID) return;
|
||||||
const itemPosition = new THREE.Vector3(item.position[0], item.position[1], item.position[2]);
|
const itemPosition = new THREE.Vector3(item.position[0], item.position[1], item.position[2]);
|
||||||
let storedPosition;
|
let storedPosition;
|
||||||
@@ -155,7 +154,7 @@ async function loadInitialFloorItems(
|
|||||||
|
|
||||||
function processLoadedModel(
|
function processLoadedModel(
|
||||||
gltf: any,
|
gltf: any,
|
||||||
item: Types.FloorItemType,
|
item: Types.EventData,
|
||||||
itemsGroup: Types.RefGroup,
|
itemsGroup: Types.RefGroup,
|
||||||
setFloorItems: Types.setFloorItemSetState,
|
setFloorItems: Types.setFloorItemSetState,
|
||||||
setSimulationPaths: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => void
|
setSimulationPaths: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => void
|
||||||
@@ -193,7 +192,7 @@ function processLoadedModel(
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (item.eventData || item.modelfileID === '67e3da19c2e8f37134526e6a') {
|
if (item.eventData) {
|
||||||
processEventData(item, setSimulationPaths);
|
processEventData(item, setSimulationPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +200,7 @@ function processLoadedModel(
|
|||||||
gsap.to(model.scale, { x: 1, y: 1, z: 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.FloorItemType, setSimulationPaths: any) {
|
function processEventData(item: Types.EventData, setSimulationPaths: any) {
|
||||||
|
|
||||||
if (item.eventData?.type === 'Conveyor') {
|
if (item.eventData?.type === 'Conveyor') {
|
||||||
|
|
||||||
@@ -215,29 +214,19 @@ function processEventData(item: Types.FloorItemType, setSimulationPaths: any) {
|
|||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
data as Types.ConveyorEventsSchema
|
data as Types.ConveyorEventsSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
const pointUUID = THREE.MathUtils.generateUUID();
|
const data: any = item.eventData;
|
||||||
const pointPosition = new THREE.Vector3(0, 1.3, 0);
|
data.modeluuid = item.modeluuid;
|
||||||
|
data.modelName = item.modelname;
|
||||||
|
data.position = item.position;
|
||||||
|
|
||||||
const newVehiclePath: Types.VehicleEventsSchema = {
|
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||||
modeluuid: item.modeluuid,
|
|
||||||
modelName: item.modelname,
|
|
||||||
type: 'Vehicle',
|
|
||||||
point: {
|
|
||||||
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: [] },
|
|
||||||
speed: 2,
|
|
||||||
},
|
|
||||||
position: [...item.position],
|
|
||||||
};
|
|
||||||
|
|
||||||
setSimulationPaths((prevEvents: (Types.VehicleEventsSchema)[]) => [
|
|
||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
newVehiclePath as Types.VehicleEventsSchema
|
data as Types.VehicleEventsSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -236,10 +236,91 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
|||||||
|
|
||||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
newEventData as Types.ConveyorEventsSchema | Types.VehicleEventsSchema
|
newEventData as Types.ConveyorEventsSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
socket.emit("v2:model-asset:add", data);
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
|
} else if (eventData.type === 'Vehicle' && eventData) {
|
||||||
|
const createVehiclePoint = () => {
|
||||||
|
const pointUUID = THREE.MathUtils.generateUUID();
|
||||||
|
const vehiclePoint = (eventData as Types.VehicleEventsSchema)?.points;
|
||||||
|
const hasActions = vehiclePoint?.actions !== undefined;
|
||||||
|
|
||||||
|
const defaultAction = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
name: 'Action 1',
|
||||||
|
type: 'Inherit',
|
||||||
|
start: {},
|
||||||
|
hitCount: 0,
|
||||||
|
end: {},
|
||||||
|
buffer: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
uuid: pointUUID,
|
||||||
|
position: vehiclePoint?.position,
|
||||||
|
actions: hasActions
|
||||||
|
? {
|
||||||
|
...vehiclePoint.actions,
|
||||||
|
uuid: THREE.MathUtils.generateUUID()
|
||||||
|
}
|
||||||
|
: defaultAction,
|
||||||
|
connections: {
|
||||||
|
source: { modelUUID: obj.uuid, pointUUID },
|
||||||
|
targets: []
|
||||||
|
},
|
||||||
|
speed: vehiclePoint?.speed || 1
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const backendEventData = {
|
||||||
|
type: 'Vehicle',
|
||||||
|
points: createVehiclePoint(),
|
||||||
|
speed: (eventData as Types.VehicleEventsSchema)?.points.speed
|
||||||
|
};
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// setFloorItemApi(
|
||||||
|
// organization,
|
||||||
|
// obj.uuid,
|
||||||
|
// obj.userData.name,
|
||||||
|
// obj.userData.modelId,
|
||||||
|
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||||
|
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||||
|
// false,
|
||||||
|
// true,
|
||||||
|
// { type: backendEventData.type, points: backendEventData.points }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization,
|
||||||
|
modeluuid: newFloorItem.modeluuid,
|
||||||
|
modelname: newFloorItem.modelname,
|
||||||
|
modelfileID: newFloorItem.modelfileID,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
|
isLocked: false,
|
||||||
|
isVisible: true,
|
||||||
|
eventData: backendEventData,
|
||||||
|
socketId: socket.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newEventData: any = backendEventData;
|
||||||
|
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
newEventData.modelName = newFloorItem.modelname;
|
||||||
|
newEventData.position = newFloorItem.position;
|
||||||
|
|
||||||
|
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||||
|
...(prevEvents || []),
|
||||||
|
newEventData as Types.VehicleEventsSchema
|
||||||
|
]);
|
||||||
|
|
||||||
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, u
|
|||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
|
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
||||||
|
|
||||||
const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedObjects, setpastedObjects, selectionGroup, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => {
|
const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedObjects, setpastedObjects, selectionGroup, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => {
|
||||||
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
||||||
@@ -182,16 +183,16 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
|||||||
|
|
||||||
//REST
|
//REST
|
||||||
|
|
||||||
// await setFloorItemApi(
|
// setFloorItemApi(
|
||||||
// organization,
|
// organization,
|
||||||
// obj.uuid,
|
// obj.uuid,
|
||||||
// obj.userData.name,
|
// obj.userData.name,
|
||||||
|
// obj.userData.modelId,
|
||||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||||
// obj.userData.modelId,
|
|
||||||
// false,
|
// false,
|
||||||
// true,
|
// true,
|
||||||
// backendEventData
|
// { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed }
|
||||||
// );
|
// );
|
||||||
|
|
||||||
//SOCKET
|
//SOCKET
|
||||||
@@ -217,10 +218,90 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
|||||||
|
|
||||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||||
...(prevEvents || []),
|
...(prevEvents || []),
|
||||||
newEventData as Types.ConveyorEventsSchema | Types.VehicleEventsSchema
|
newEventData as Types.ConveyorEventsSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
socket.emit("v2:model-asset:add", data);
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
|
} else if (eventData.type === 'Vehicle' && eventData) {
|
||||||
|
const createVehiclePoint = () => {
|
||||||
|
const pointUUID = THREE.MathUtils.generateUUID();
|
||||||
|
const vehiclePoint = (eventData as Types.VehicleEventsSchema)?.points;
|
||||||
|
const hasActions = vehiclePoint?.actions !== undefined;
|
||||||
|
|
||||||
|
const defaultAction = {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
name: 'Action 1',
|
||||||
|
type: 'Inherit',
|
||||||
|
start: {},
|
||||||
|
hitCount: 0,
|
||||||
|
end: {},
|
||||||
|
buffer: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
uuid: pointUUID,
|
||||||
|
position: vehiclePoint?.position,
|
||||||
|
actions: hasActions
|
||||||
|
? {
|
||||||
|
...vehiclePoint.actions,
|
||||||
|
uuid: THREE.MathUtils.generateUUID()
|
||||||
|
}
|
||||||
|
: defaultAction,
|
||||||
|
connections: {
|
||||||
|
source: { modelUUID: obj.uuid, pointUUID },
|
||||||
|
targets: []
|
||||||
|
},
|
||||||
|
speed: vehiclePoint?.speed || 2
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const backendEventData = {
|
||||||
|
type: 'Vehicle',
|
||||||
|
points: createVehiclePoint()
|
||||||
|
};
|
||||||
|
|
||||||
|
// API
|
||||||
|
|
||||||
|
// setFloorItemApi(
|
||||||
|
// organization,
|
||||||
|
// obj.uuid,
|
||||||
|
// obj.userData.name,
|
||||||
|
// obj.userData.modelId,
|
||||||
|
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||||
|
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||||
|
// false,
|
||||||
|
// true,
|
||||||
|
// { type: backendEventData.type, points: backendEventData.points }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization,
|
||||||
|
modeluuid: newFloorItem.modeluuid,
|
||||||
|
modelname: newFloorItem.modelname,
|
||||||
|
modelfileID: newFloorItem.modelfileID,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
|
isLocked: false,
|
||||||
|
isVisible: true,
|
||||||
|
eventData: backendEventData,
|
||||||
|
socketId: socket.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newEventData: any = backendEventData;
|
||||||
|
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
newEventData.modelName = newFloorItem.modelname;
|
||||||
|
newEventData.position = newFloorItem.position;
|
||||||
|
|
||||||
|
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||||
|
...(prevEvents || []),
|
||||||
|
newEventData as Types.VehicleEventsSchema
|
||||||
|
]);
|
||||||
|
|
||||||
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|||||||
@@ -238,7 +238,59 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
|||||||
return updatedEvents;
|
return updatedEvents;
|
||||||
});
|
});
|
||||||
|
|
||||||
// socket.emit("v2:model-asset:add", data);
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
} else if (eventData.type === 'Vehicle' && eventData) {
|
||||||
|
|
||||||
|
const backendEventData = {
|
||||||
|
type: 'Vehicle',
|
||||||
|
points: eventData.points
|
||||||
|
};
|
||||||
|
|
||||||
|
// REST
|
||||||
|
|
||||||
|
// await setFloorItemApi(
|
||||||
|
// organization,
|
||||||
|
// obj.uuid,
|
||||||
|
// obj.userData.name,
|
||||||
|
// obj.userData.modelId,
|
||||||
|
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||||
|
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||||
|
// false,
|
||||||
|
// true,
|
||||||
|
// backendEventData
|
||||||
|
// );
|
||||||
|
|
||||||
|
//SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization,
|
||||||
|
modeluuid: newFloorItem.modeluuid,
|
||||||
|
modelname: newFloorItem.modelname,
|
||||||
|
modelfileID: newFloorItem.modelfileID,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
|
isLocked: false,
|
||||||
|
isVisible: true,
|
||||||
|
eventData: backendEventData,
|
||||||
|
socketId: socket.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newEventData: any = backendEventData;
|
||||||
|
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
newEventData.modelName = newFloorItem.modelname;
|
||||||
|
newEventData.position = newFloorItem.position;
|
||||||
|
|
||||||
|
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||||
|
const updatedEvents = (prevEvents || []).map(event =>
|
||||||
|
event.modeluuid === newFloorItem.modeluuid
|
||||||
|
? { ...event, ...newEventData }
|
||||||
|
: event
|
||||||
|
);
|
||||||
|
return updatedEvents;
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, u
|
|||||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
|
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
||||||
|
|
||||||
function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {
|
function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {
|
||||||
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
||||||
@@ -197,15 +198,15 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
|||||||
speed: (eventData as Types.ConveyorEventsSchema)?.speed
|
speed: (eventData as Types.ConveyorEventsSchema)?.speed
|
||||||
};
|
};
|
||||||
|
|
||||||
//REST
|
// REST
|
||||||
|
|
||||||
// await setFloorItemApi(
|
// await setFloorItemApi(
|
||||||
// organization,
|
// organization,
|
||||||
// obj.uuid,
|
// obj.uuid,
|
||||||
// obj.userData.name,
|
// obj.userData.name,
|
||||||
|
// obj.userData.modelId,
|
||||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||||
// obj.userData.modelId,
|
|
||||||
// false,
|
// false,
|
||||||
// true,
|
// true,
|
||||||
// backendEventData
|
// backendEventData
|
||||||
@@ -241,7 +242,60 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
|||||||
return updatedEvents;
|
return updatedEvents;
|
||||||
});
|
});
|
||||||
|
|
||||||
// socket.emit("v2:model-asset:add", data);
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
|
} else if (eventData.type === 'Vehicle' && eventData) {
|
||||||
|
|
||||||
|
const backendEventData = {
|
||||||
|
type: 'Vehicle',
|
||||||
|
points: eventData.points
|
||||||
|
};
|
||||||
|
|
||||||
|
// REST
|
||||||
|
|
||||||
|
// await setFloorItemApi(
|
||||||
|
// organization,
|
||||||
|
// obj.uuid,
|
||||||
|
// obj.userData.name,
|
||||||
|
// obj.userData.modelId,
|
||||||
|
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||||
|
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||||
|
// false,
|
||||||
|
// true,
|
||||||
|
// backendEventData
|
||||||
|
// );
|
||||||
|
|
||||||
|
//SOCKET
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
organization,
|
||||||
|
modeluuid: newFloorItem.modeluuid,
|
||||||
|
modelname: newFloorItem.modelname,
|
||||||
|
modelfileID: newFloorItem.modelfileID,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||||
|
isLocked: false,
|
||||||
|
isVisible: true,
|
||||||
|
eventData: backendEventData,
|
||||||
|
socketId: socket.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newEventData: any = backendEventData;
|
||||||
|
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||||
|
newEventData.modelName = newFloorItem.modelname;
|
||||||
|
newEventData.position = newFloorItem.position;
|
||||||
|
|
||||||
|
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||||
|
const updatedEvents = (prevEvents || []).map(event =>
|
||||||
|
event.modeluuid === newFloorItem.modeluuid
|
||||||
|
? { ...event, ...newEventData }
|
||||||
|
: event
|
||||||
|
);
|
||||||
|
return updatedEvents;
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.emit("v2:model-asset:add", data);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export default function PostProcessing() {
|
|||||||
)}
|
)}
|
||||||
{selectedActionSphere && (
|
{selectedActionSphere && (
|
||||||
<Outline
|
<Outline
|
||||||
selection={[selectedActionSphere.point]}
|
selection={[selectedActionSphere.points]}
|
||||||
selectionLayer={10}
|
selectionLayer={10}
|
||||||
width={1000}
|
width={1000}
|
||||||
blendFunction={BlendFunction.ALPHA}
|
blendFunction={BlendFunction.ALPHA}
|
||||||
|
|||||||
@@ -367,7 +367,9 @@ export default function World() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{/* <DrieHtmlTemp itemsGroup={itemsGroup} /> */}
|
{/* <DrieHtmlTemp itemsGroup={itemsGroup} /> */}
|
||||||
{activeModule === "simulation" && <Agv lines={lines} plane={plane} />}
|
|
||||||
|
{activeModule === "simulation" && <Agv lines={lines} />}
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ import * as Types from '../../../types/world/worldTypes';
|
|||||||
import { QuadraticBezierLine } from '@react-three/drei';
|
import { QuadraticBezierLine } from '@react-three/drei';
|
||||||
import { useIsConnecting, useSimulationPaths } from '../../../store/store';
|
import { useIsConnecting, useSimulationPaths } from '../../../store/store';
|
||||||
import useModuleStore from '../../../store/useModuleStore';
|
import useModuleStore from '../../../store/useModuleStore';
|
||||||
|
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
||||||
|
|
||||||
function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject<THREE.Group> }) {
|
function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject<THREE.Group> }) {
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const { gl, raycaster, scene, pointer, camera } = useThree();
|
const { gl, raycaster, scene, pointer, camera } = useThree();
|
||||||
const { setIsConnecting } = useIsConnecting();
|
const { setIsConnecting } = useIsConnecting();
|
||||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||||
|
const { isPlaying } = usePlayButtonStore();
|
||||||
|
|
||||||
const [firstSelected, setFirstSelected] = useState<{
|
const [firstSelected, setFirstSelected] = useState<{
|
||||||
pathUUID: string;
|
pathUUID: string;
|
||||||
@@ -89,12 +91,12 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
// In the updatePathConnections function, modify the Vehicle handling section:
|
// In the updatePathConnections function, modify the Vehicle handling section:
|
||||||
else if (path.type === 'Vehicle') {
|
else if (path.type === 'Vehicle') {
|
||||||
// Handle outgoing connections from Vehicle
|
// Handle outgoing connections from Vehicle
|
||||||
if (path.modeluuid === fromPathUUID && path.point.uuid === fromPointUUID) {
|
if (path.modeluuid === fromPathUUID && path.points.uuid === fromPointUUID) {
|
||||||
const newTarget = {
|
const newTarget = {
|
||||||
pathUUID: toPathUUID,
|
pathUUID: toPathUUID,
|
||||||
pointUUID: toPointUUID
|
pointUUID: toPointUUID
|
||||||
};
|
};
|
||||||
const existingTargets = path.point.connections.targets || [];
|
const existingTargets = path.points.connections.targets || [];
|
||||||
|
|
||||||
// Check if target is a Conveyor
|
// Check if target is a Conveyor
|
||||||
const toPath = simulationPaths.find(p => p.modeluuid === toPathUUID);
|
const toPath = simulationPaths.find(p => p.modeluuid === toPathUUID);
|
||||||
@@ -115,10 +117,10 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
)) {
|
)) {
|
||||||
return {
|
return {
|
||||||
...path,
|
...path,
|
||||||
point: {
|
points: {
|
||||||
...path.point,
|
...path.points,
|
||||||
connections: {
|
connections: {
|
||||||
...path.point.connections,
|
...path.points.connections,
|
||||||
targets: [...existingTargets, newTarget]
|
targets: [...existingTargets, newTarget]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,12 +128,12 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Handle incoming connections to Vehicle
|
// Handle incoming connections to Vehicle
|
||||||
else if (path.modeluuid === toPathUUID && path.point.uuid === toPointUUID) {
|
else if (path.modeluuid === toPathUUID && path.points.uuid === toPointUUID) {
|
||||||
const reverseTarget = {
|
const reverseTarget = {
|
||||||
pathUUID: fromPathUUID,
|
pathUUID: fromPathUUID,
|
||||||
pointUUID: fromPointUUID
|
pointUUID: fromPointUUID
|
||||||
};
|
};
|
||||||
const existingTargets = path.point.connections.targets || [];
|
const existingTargets = path.points.connections.targets || [];
|
||||||
|
|
||||||
// Check if source is a Conveyor
|
// Check if source is a Conveyor
|
||||||
const fromPath = simulationPaths.find(p => p.modeluuid === fromPathUUID);
|
const fromPath = simulationPaths.find(p => p.modeluuid === fromPathUUID);
|
||||||
@@ -152,10 +154,10 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
)) {
|
)) {
|
||||||
return {
|
return {
|
||||||
...path,
|
...path,
|
||||||
point: {
|
points: {
|
||||||
...path.point,
|
...path.points,
|
||||||
connections: {
|
connections: {
|
||||||
...path.point.connections,
|
...path.points.connections,
|
||||||
targets: [...existingTargets, reverseTarget]
|
targets: [...existingTargets, reverseTarget]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,13 +217,13 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
|
|
||||||
let isStartOrEnd = false;
|
let isStartOrEnd = false;
|
||||||
|
|
||||||
if (intersected.userData.path.points) {
|
if (intersected.userData.path.points && intersected.userData.path.points.length > 1) {
|
||||||
isStartOrEnd = intersected.userData.path.points.length > 0 && (
|
isStartOrEnd = intersected.userData.path.points.length > 0 && (
|
||||||
sphereUUID === intersected.userData.path.points[0].uuid ||
|
sphereUUID === intersected.userData.path.points[0].uuid ||
|
||||||
sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid
|
sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid
|
||||||
);
|
);
|
||||||
} else if (intersected.userData.path.point) {
|
} else if (intersected.userData.path.points) {
|
||||||
isStartOrEnd = sphereUUID === intersected.userData.path.point.uuid;
|
isStartOrEnd = sphereUUID === intersected.userData.path.points.uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pathUUID) {
|
if (pathUUID) {
|
||||||
@@ -253,7 +255,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
||||||
);
|
);
|
||||||
} else if (path.type === 'Vehicle') {
|
} else if (path.type === 'Vehicle') {
|
||||||
return path.point.connections.targets.some(t =>
|
return path.points.connections.targets.some(t =>
|
||||||
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -269,7 +271,8 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
|
|
||||||
// For Vehicles, check if they're already connected to anything
|
// For Vehicles, check if they're already connected to anything
|
||||||
if (intersected.userData.path.type === 'Vehicle') {
|
if (intersected.userData.path.type === 'Vehicle') {
|
||||||
const vehicleConnections = intersected.userData.path.point.connections.targets.length;
|
console.log('intersected: ', intersected);
|
||||||
|
const vehicleConnections = intersected.userData.path.points.connections.targets.length;
|
||||||
if (vehicleConnections >= 1) {
|
if (vehicleConnections >= 1) {
|
||||||
console.log("Vehicle can only have one connection");
|
console.log("Vehicle can only have one connection");
|
||||||
return;
|
return;
|
||||||
@@ -418,7 +421,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
||||||
);
|
);
|
||||||
} else if (path.type === 'Vehicle') {
|
} else if (path.type === 'Vehicle') {
|
||||||
return path.point.connections.targets.some(t =>
|
return path.points.connections.targets.some(t =>
|
||||||
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
t.pathUUID === pathUUID && t.pointUUID === sphereUUID
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -440,7 +443,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
|
|
||||||
// Check vehicle connection rules
|
// Check vehicle connection rules
|
||||||
const isVehicleAtMaxConnections = pathData.type === 'Vehicle' &&
|
const isVehicleAtMaxConnections = pathData.type === 'Vehicle' &&
|
||||||
pathData.point.connections.targets.length >= 1;
|
pathData.points.connections.targets.length >= 1;
|
||||||
const isVehicleConnectingToNonConveyor =
|
const isVehicleConnectingToNonConveyor =
|
||||||
(firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
|
(firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
|
||||||
(secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor');
|
(secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor');
|
||||||
@@ -501,7 +504,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<group name='simulationConnectionGroup' visible={!isPlaying} >
|
||||||
{simulationPaths.flatMap(path => {
|
{simulationPaths.flatMap(path => {
|
||||||
if (path.type === 'Conveyor') {
|
if (path.type === 'Conveyor') {
|
||||||
return path.points.flatMap(point =>
|
return path.points.flatMap(point =>
|
||||||
@@ -545,8 +548,8 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else if (path.type === 'Vehicle') {
|
} else if (path.type === 'Vehicle') {
|
||||||
return path.point.connections.targets.map((target, index) => {
|
return path.points.connections.targets.map((target, index) => {
|
||||||
const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', path.point.uuid);
|
const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', path.points.uuid);
|
||||||
const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
|
const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID);
|
||||||
|
|
||||||
if (fromSphere && toSphere) {
|
if (fromSphere && toSphere) {
|
||||||
@@ -566,7 +569,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<QuadraticBezierLine
|
<QuadraticBezierLine
|
||||||
key={`${path.point.uuid}-${target.pointUUID}-${index}`}
|
key={`${path.points.uuid}-${target.pointUUID}-${index}`}
|
||||||
start={fromWorldPosition.toArray()}
|
start={fromWorldPosition.toArray()}
|
||||||
end={toWorldPosition.toArray()}
|
end={toWorldPosition.toArray()}
|
||||||
mid={midPoint.toArray()}
|
mid={midPoint.toArray()}
|
||||||
@@ -596,7 +599,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
dashScale={20}
|
dashScale={20}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</group>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import { useSubModuleStore } from "../../../store/useModuleStore";
|
import { useSubModuleStore } from "../../../store/useModuleStore";
|
||||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||||
|
import { setEventApi } from "../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
||||||
|
|
||||||
function PathCreation({
|
function PathCreation({
|
||||||
pathsGroupRef,
|
pathsGroupRef,
|
||||||
@@ -24,16 +25,12 @@ function PathCreation({
|
|||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { renderDistance } = useRenderDistance();
|
const { renderDistance } = useRenderDistance();
|
||||||
const { setSubModule } = useSubModuleStore();
|
const { setSubModule } = useSubModuleStore();
|
||||||
const { setSelectedActionSphere, selectedActionSphere } =
|
const { setSelectedActionSphere, selectedActionSphere } = useSelectedActionSphere();
|
||||||
useSelectedActionSphere();
|
|
||||||
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
|
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
|
||||||
const { editingPoint, setEditingPoint } = useEditingPoint();
|
const { editingPoint, setEditingPoint } = useEditingPoint();
|
||||||
const { previewPosition, setPreviewPosition } = usePreviewPosition();
|
const { previewPosition, setPreviewPosition } = usePreviewPosition();
|
||||||
const { raycaster, camera, pointer, gl } = useThree();
|
const { raycaster, camera, pointer, gl } = useThree();
|
||||||
const plane = useMemo(
|
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||||
() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
const { setSelectedPath } = useSelectedPath();
|
const { setSelectedPath } = useSelectedPath();
|
||||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||||
const { isConnecting } = useIsConnecting();
|
const { isConnecting } = useIsConnecting();
|
||||||
@@ -42,9 +39,7 @@ function PathCreation({
|
|||||||
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
||||||
const isMovingRef = useRef(false);
|
const isMovingRef = useRef(false);
|
||||||
const transformRef = useRef<any>(null);
|
const transformRef = useRef<any>(null);
|
||||||
const [transformMode, setTransformMode] = useState<
|
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
||||||
"translate" | "rotate" | null
|
|
||||||
>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTransformMode(null);
|
setTransformMode(null);
|
||||||
@@ -81,20 +76,20 @@ function PathCreation({
|
|||||||
return {
|
return {
|
||||||
...path,
|
...path,
|
||||||
points: path.points.map((point) =>
|
points: path.points.map((point) =>
|
||||||
point.uuid === selectedActionSphere.point.uuid
|
point.uuid === selectedActionSphere.points.uuid
|
||||||
? {
|
? {
|
||||||
...point,
|
...point,
|
||||||
position: [
|
position: [
|
||||||
selectedActionSphere.point.position.x,
|
selectedActionSphere.points.position.x,
|
||||||
selectedActionSphere.point.position.y,
|
selectedActionSphere.points.position.y,
|
||||||
selectedActionSphere.point.position.z,
|
selectedActionSphere.points.position.z,
|
||||||
],
|
],
|
||||||
rotation: [
|
rotation: [
|
||||||
selectedActionSphere.point.rotation.x,
|
selectedActionSphere.points.rotation.x,
|
||||||
selectedActionSphere.point.rotation.y,
|
selectedActionSphere.points.rotation.y,
|
||||||
selectedActionSphere.point.rotation.z,
|
selectedActionSphere.points.rotation.z,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
: point
|
: point
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
@@ -161,26 +156,37 @@ function PathCreation({
|
|||||||
};
|
};
|
||||||
}, [eyeDropMode, editingPoint, previewPosition]);
|
}, [eyeDropMode, editingPoint, previewPosition]);
|
||||||
|
|
||||||
|
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 handlePointUpdate = (
|
const handlePointUpdate = (
|
||||||
pointType: "start" | "end",
|
pointType: "start" | "end",
|
||||||
x: number,
|
x: number,
|
||||||
z: number
|
z: number
|
||||||
) => {
|
) => {
|
||||||
if (!selectedActionSphere?.point?.uuid) return;
|
if (!selectedActionSphere?.points?.uuid) return;
|
||||||
|
|
||||||
const updatedPaths = simulationPaths.map((path) => {
|
const updatedPaths = simulationPaths.map((path) => {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
path.type === "Vehicle" &&
|
path.type === "Vehicle" &&
|
||||||
path.point.uuid === selectedActionSphere.point.uuid
|
path.points.uuid === selectedActionSphere.points.uuid
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
...path,
|
...path,
|
||||||
point: {
|
points: {
|
||||||
...path.point,
|
...path.points,
|
||||||
actions: {
|
actions: {
|
||||||
...path.point.actions,
|
...path.points.actions,
|
||||||
[pointType]: {
|
[pointType]: {
|
||||||
...path.point.actions[pointType],
|
...path.points.actions[pointType],
|
||||||
x: x,
|
x: x,
|
||||||
y: z,
|
y: z,
|
||||||
},
|
},
|
||||||
@@ -191,6 +197,13 @@ function PathCreation({
|
|||||||
return path;
|
return path;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatedPath = updatedPaths.find(
|
||||||
|
(path): path is Types.VehicleEventsSchema =>
|
||||||
|
path.type === "Vehicle" &&
|
||||||
|
path.points.uuid === selectedActionSphere.points.uuid
|
||||||
|
);
|
||||||
|
updateBackend(updatedPath);
|
||||||
|
|
||||||
setSimulationPaths(updatedPaths);
|
setSimulationPaths(updatedPaths);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -239,12 +252,12 @@ function PathCreation({
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setSelectedActionSphere({
|
setSelectedActionSphere({
|
||||||
path,
|
path,
|
||||||
point: sphereRefs.current[point.uuid],
|
points: sphereRefs.current[point.uuid],
|
||||||
});
|
});
|
||||||
setSubModule("mechanics");
|
setSubModule("mechanics");
|
||||||
setSelectedPath(null);
|
setSelectedPath(null);
|
||||||
}}
|
}}
|
||||||
userData={{ point, path }}
|
userData={{ points, path }}
|
||||||
onPointerMissed={() => {
|
onPointerMissed={() => {
|
||||||
if (eyeDropMode) return;
|
if (eyeDropMode) return;
|
||||||
setSubModule("properties");
|
setSubModule("properties");
|
||||||
@@ -256,8 +269,8 @@ function PathCreation({
|
|||||||
index === 0
|
index === 0
|
||||||
? "orange"
|
? "orange"
|
||||||
: index === path.points.length - 1
|
: index === path.points.length - 1
|
||||||
? "blue"
|
? "blue"
|
||||||
: "green"
|
: "green"
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Sphere>
|
</Sphere>
|
||||||
@@ -318,23 +331,23 @@ function PathCreation({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Sphere
|
<Sphere
|
||||||
key={path.point.uuid}
|
key={path.points.uuid}
|
||||||
uuid={path.point.uuid}
|
uuid={path.points.uuid}
|
||||||
position={path.point.position}
|
position={path.points.position}
|
||||||
args={[0.15, 32, 32]}
|
args={[0.15, 32, 32]}
|
||||||
name="events-sphere"
|
name="events-sphere"
|
||||||
ref={(el) => (sphereRefs.current[path.point.uuid] = el!)}
|
ref={(el) => (sphereRefs.current[path.points.uuid] = el!)}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (isConnecting || eyeDropMode) return;
|
if (isConnecting || eyeDropMode) return;
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setSelectedActionSphere({
|
setSelectedActionSphere({
|
||||||
path,
|
path,
|
||||||
point: sphereRefs.current[path.point.uuid],
|
points: sphereRefs.current[path.points.uuid],
|
||||||
});
|
});
|
||||||
setSubModule("mechanics");
|
setSubModule("mechanics");
|
||||||
setSelectedPath(null);
|
setSelectedPath(null);
|
||||||
}}
|
}}
|
||||||
userData={{ point: path.point, path }}
|
userData={{ points: path.points, path }}
|
||||||
onPointerMissed={() => {
|
onPointerMissed={() => {
|
||||||
if (eyeDropMode) return;
|
if (eyeDropMode) return;
|
||||||
setSubModule("properties");
|
setSubModule("properties");
|
||||||
@@ -352,7 +365,7 @@ function PathCreation({
|
|||||||
{selectedActionSphere && transformMode && (
|
{selectedActionSphere && transformMode && (
|
||||||
<TransformControls
|
<TransformControls
|
||||||
ref={transformRef}
|
ref={transformRef}
|
||||||
object={selectedActionSphere.point}
|
object={selectedActionSphere.points}
|
||||||
mode={transformMode}
|
mode={transformMode}
|
||||||
onMouseUp={updateSimulationPaths}
|
onMouseUp={updateSimulationPaths}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,916 +0,0 @@
|
|||||||
// // animation-worker.js
|
|
||||||
// // This web worker handles animation calculations off the main thread
|
|
||||||
|
|
||||||
// /* eslint-disable no-restricted-globals */
|
|
||||||
// // The above disables the ESLint rule for this file since 'self' is valid in web workers
|
|
||||||
|
|
||||||
// // Store process data, animation states, and objects
|
|
||||||
// let processes = [];
|
|
||||||
// let animationStates = {};
|
|
||||||
// let lastTimestamp = 0;
|
|
||||||
|
|
||||||
// // Message handler for communication with main thread
|
|
||||||
// self.onmessage = function (event) {
|
|
||||||
// const { type, data } = event.data;
|
|
||||||
|
|
||||||
// switch (type) {
|
|
||||||
// case "initialize":
|
|
||||||
// processes = data.processes;
|
|
||||||
// initializeAnimationStates();
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// case "update":
|
|
||||||
// const { timestamp, isPlaying } = data;
|
|
||||||
// if (isPlaying) {
|
|
||||||
// const delta = (timestamp - lastTimestamp) / 1000; // Convert to seconds
|
|
||||||
// updateAnimations(delta, timestamp);
|
|
||||||
// }
|
|
||||||
// lastTimestamp = timestamp;
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// case "reset":
|
|
||||||
// resetAnimations();
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// case "togglePlay":
|
|
||||||
// // If resuming from pause, recalculate the time delta
|
|
||||||
// lastTimestamp = data.timestamp;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // Initialize animation states for all processes
|
|
||||||
// function initializeAnimationStates() {
|
|
||||||
// animationStates = {};
|
|
||||||
|
|
||||||
// processes.forEach((process) => {
|
|
||||||
// animationStates[process.id] = {
|
|
||||||
// spawnedObjects: {},
|
|
||||||
// nextSpawnTime: 0,
|
|
||||||
// objectIdCounter: 0,
|
|
||||||
// };
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Send initial states back to main thread
|
|
||||||
// self.postMessage({
|
|
||||||
// type: "statesInitialized",
|
|
||||||
// data: { animationStates },
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Reset all animations
|
|
||||||
// function resetAnimations() {
|
|
||||||
// initializeAnimationStates();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Find spawn point in a process
|
|
||||||
// function findSpawnPoint(process) {
|
|
||||||
// for (const path of process.paths || []) {
|
|
||||||
// for (const point of path.points || []) {
|
|
||||||
// const spawnAction = point.actions?.find(
|
|
||||||
// (a) => a.isUsed && a.type === "Spawn"
|
|
||||||
// );
|
|
||||||
// if (spawnAction) {
|
|
||||||
// return { point, path };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Create a new spawned object with proper initial position
|
|
||||||
// function createSpawnedObject(process, spawnPoint, currentTime, materialType) {
|
|
||||||
// // Extract spawn position from the actual spawn point
|
|
||||||
// const position = spawnPoint.point.position
|
|
||||||
// ? [...spawnPoint.point.position]
|
|
||||||
// : [0, 0, 0];
|
|
||||||
|
|
||||||
// // Get the path position and add it to the spawn point position
|
|
||||||
// const pathPosition = spawnPoint.path.pathPosition || [0, 0, 0];
|
|
||||||
// const absolutePosition = [
|
|
||||||
// position[0] + pathPosition[0],
|
|
||||||
// position[1] + pathPosition[1],
|
|
||||||
// position[2] + pathPosition[2],
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// id: `obj-${process.id}-${animationStates[process.id].objectIdCounter}`,
|
|
||||||
// position: absolutePosition,
|
|
||||||
// state: {
|
|
||||||
// currentIndex: 0,
|
|
||||||
// progress: 0,
|
|
||||||
// isAnimating: true,
|
|
||||||
// speed: process.speed || 1,
|
|
||||||
// isDelaying: false,
|
|
||||||
// delayStartTime: 0,
|
|
||||||
// currentDelayDuration: 0,
|
|
||||||
// delayComplete: false,
|
|
||||||
// currentPathIndex: 0,
|
|
||||||
// // Store the spawn point index to start animation from correct path point
|
|
||||||
// spawnPointIndex: getPointIndexInProcess(process, spawnPoint.point),
|
|
||||||
// },
|
|
||||||
// visible: true,
|
|
||||||
// materialType: materialType || "Default",
|
|
||||||
// spawnTime: currentTime,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Get the index of a point within the process animation path
|
|
||||||
// function getPointIndexInProcess(process, point) {
|
|
||||||
// if (!process.paths) return 0;
|
|
||||||
|
|
||||||
// let cumulativePoints = 0;
|
|
||||||
// for (const path of process.paths) {
|
|
||||||
// for (let i = 0; i < (path.points?.length || 0); i++) {
|
|
||||||
// if (path.points[i].uuid === point.uuid) {
|
|
||||||
// return cumulativePoints + i;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// cumulativePoints += path.points?.length || 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Get point data for current animation index
|
|
||||||
// function getPointDataForAnimationIndex(process, index) {
|
|
||||||
// if (!process.paths) return null;
|
|
||||||
|
|
||||||
// let cumulativePoints = 0;
|
|
||||||
// for (const path of process.paths) {
|
|
||||||
// const pointCount = path.points?.length || 0;
|
|
||||||
|
|
||||||
// if (index < cumulativePoints + pointCount) {
|
|
||||||
// const pointIndex = index - cumulativePoints;
|
|
||||||
// return path.points?.[pointIndex] || null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// cumulativePoints += pointCount;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Convert process paths to Vector3 format
|
|
||||||
// function getProcessPath(process) {
|
|
||||||
// return process.animationPath?.map((p) => ({ x: p.x, y: p.y, z: p.z })) || [];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Handle material swap for an object
|
|
||||||
// function handleMaterialSwap(processId, objectId, materialType) {
|
|
||||||
// const processState = animationStates[processId];
|
|
||||||
// if (!processState || !processState.spawnedObjects[objectId]) return;
|
|
||||||
|
|
||||||
// processState.spawnedObjects[objectId].materialType = materialType;
|
|
||||||
|
|
||||||
// // Notify main thread about material change
|
|
||||||
// self.postMessage({
|
|
||||||
// type: "materialChanged",
|
|
||||||
// data: {
|
|
||||||
// processId,
|
|
||||||
// objectId,
|
|
||||||
// materialType,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Handle point actions for an object
|
|
||||||
// function handlePointActions(processId, objectId, actions = [], currentTime) {
|
|
||||||
// let shouldStopAnimation = false;
|
|
||||||
// const processState = animationStates[processId];
|
|
||||||
|
|
||||||
// if (!processState || !processState.spawnedObjects[objectId]) return false;
|
|
||||||
|
|
||||||
// const objectState = processState.spawnedObjects[objectId];
|
|
||||||
|
|
||||||
// actions.forEach((action) => {
|
|
||||||
// if (!action.isUsed) return;
|
|
||||||
|
|
||||||
// switch (action.type) {
|
|
||||||
// case "Delay":
|
|
||||||
// if (objectState.state.isDelaying) return;
|
|
||||||
|
|
||||||
// const delayDuration =
|
|
||||||
// typeof action.delay === "number"
|
|
||||||
// ? action.delay
|
|
||||||
// : parseFloat(action.delay || "0");
|
|
||||||
|
|
||||||
// if (delayDuration > 0) {
|
|
||||||
// objectState.state.isDelaying = true;
|
|
||||||
// objectState.state.delayStartTime = currentTime;
|
|
||||||
// objectState.state.currentDelayDuration = delayDuration;
|
|
||||||
// objectState.state.delayComplete = false;
|
|
||||||
// shouldStopAnimation = true;
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// case "Despawn":
|
|
||||||
// delete processState.spawnedObjects[objectId];
|
|
||||||
// shouldStopAnimation = true;
|
|
||||||
|
|
||||||
// // Notify main thread about despawn
|
|
||||||
// self.postMessage({
|
|
||||||
// type: "objectDespawned",
|
|
||||||
// data: {
|
|
||||||
// processId,
|
|
||||||
// objectId,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// case "Swap":
|
|
||||||
// if (action.material) {
|
|
||||||
// handleMaterialSwap(processId, objectId, action.material);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
|
|
||||||
// default:
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return shouldStopAnimation;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Check if point has non-inherit actions
|
|
||||||
// function hasNonInheritActions(actions = []) {
|
|
||||||
// return actions.some((action) => action.isUsed && action.type !== "Inherit");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Calculate vector lerp (linear interpolation)
|
|
||||||
// function lerpVectors(v1, v2, alpha) {
|
|
||||||
// return {
|
|
||||||
// x: v1.x + (v2.x - v1.x) * alpha,
|
|
||||||
// y: v1.y + (v2.y - v1.y) * alpha,
|
|
||||||
// z: v1.z + (v2.z - v1.z) * alpha,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Calculate vector distance
|
|
||||||
// function distanceBetweenVectors(v1, v2) {
|
|
||||||
// const dx = v2.x - v1.x;
|
|
||||||
// const dy = v2.y - v1.y;
|
|
||||||
// const dz = v2.z - v1.z;
|
|
||||||
// return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Process spawn logic
|
|
||||||
// function processSpawns(currentTime) {
|
|
||||||
// processes.forEach((process) => {
|
|
||||||
// const processState = animationStates[process.id];
|
|
||||||
// if (!processState) return;
|
|
||||||
|
|
||||||
// const spawnPointData = findSpawnPoint(process);
|
|
||||||
// if (!spawnPointData || !spawnPointData.point.actions) return;
|
|
||||||
|
|
||||||
// const spawnAction = spawnPointData.point.actions.find(
|
|
||||||
// (a) => a.isUsed && a.type === "Spawn"
|
|
||||||
// );
|
|
||||||
// if (!spawnAction) return;
|
|
||||||
|
|
||||||
// const spawnInterval =
|
|
||||||
// typeof spawnAction.spawnInterval === "number"
|
|
||||||
// ? spawnAction.spawnInterval
|
|
||||||
// : parseFloat(spawnAction.spawnInterval || "0");
|
|
||||||
|
|
||||||
// if (currentTime >= processState.nextSpawnTime) {
|
|
||||||
// const newObject = createSpawnedObject(
|
|
||||||
// process,
|
|
||||||
// spawnPointData,
|
|
||||||
// currentTime,
|
|
||||||
// spawnAction.material || "Default"
|
|
||||||
// );
|
|
||||||
|
|
||||||
// processState.spawnedObjects[newObject.id] = newObject;
|
|
||||||
// processState.objectIdCounter++;
|
|
||||||
// processState.nextSpawnTime = currentTime + spawnInterval;
|
|
||||||
|
|
||||||
// // Notify main thread about new object
|
|
||||||
// self.postMessage({
|
|
||||||
// type: "objectSpawned",
|
|
||||||
// data: {
|
|
||||||
// processId: process.id,
|
|
||||||
// object: newObject,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Update all animations
|
|
||||||
// function updateAnimations(delta, currentTime) {
|
|
||||||
// // First handle spawning of new objects
|
|
||||||
// processSpawns(currentTime);
|
|
||||||
|
|
||||||
// // Then animate existing objects
|
|
||||||
// processes.forEach((process) => {
|
|
||||||
// const processState = animationStates[process.id];
|
|
||||||
// if (!processState) return;
|
|
||||||
|
|
||||||
// const path = getProcessPath(process);
|
|
||||||
// if (path.length < 2) return;
|
|
||||||
|
|
||||||
// const updatedObjects = {};
|
|
||||||
// let hasChanges = false;
|
|
||||||
|
|
||||||
// Object.entries(processState.spawnedObjects).forEach(([objectId, obj]) => {
|
|
||||||
// if (!obj.visible || !obj.state.isAnimating) return;
|
|
||||||
|
|
||||||
// const stateRef = obj.state;
|
|
||||||
|
|
||||||
// // Use the spawnPointIndex as starting point if it's the initial movement
|
|
||||||
// if (stateRef.currentIndex === 0 && stateRef.progress === 0) {
|
|
||||||
// stateRef.currentIndex = stateRef.spawnPointIndex || 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Get current point data
|
|
||||||
// const currentPointData = getPointDataForAnimationIndex(
|
|
||||||
// process,
|
|
||||||
// stateRef.currentIndex
|
|
||||||
// );
|
|
||||||
|
|
||||||
// // Execute actions when arriving at a new point
|
|
||||||
// if (stateRef.progress === 0 && currentPointData?.actions) {
|
|
||||||
// const shouldStop = handlePointActions(
|
|
||||||
// process.id,
|
|
||||||
// objectId,
|
|
||||||
// currentPointData.actions,
|
|
||||||
// currentTime
|
|
||||||
// );
|
|
||||||
// if (shouldStop) return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Handle delays
|
|
||||||
// if (stateRef.isDelaying) {
|
|
||||||
// if (
|
|
||||||
// currentTime - stateRef.delayStartTime >=
|
|
||||||
// stateRef.currentDelayDuration
|
|
||||||
// ) {
|
|
||||||
// stateRef.isDelaying = false;
|
|
||||||
// stateRef.delayComplete = true;
|
|
||||||
// } else {
|
|
||||||
// updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
|
|
||||||
// return; // Keep waiting
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const nextPointIdx = stateRef.currentIndex + 1;
|
|
||||||
// const isLastPoint = nextPointIdx >= path.length;
|
|
||||||
|
|
||||||
// if (isLastPoint) {
|
|
||||||
// if (currentPointData?.actions) {
|
|
||||||
// const shouldStop = !hasNonInheritActions(currentPointData.actions);
|
|
||||||
// if (shouldStop) {
|
|
||||||
// // Reached the end of path with no more actions
|
|
||||||
// delete processState.spawnedObjects[objectId];
|
|
||||||
|
|
||||||
// // Notify main thread to remove the object
|
|
||||||
// self.postMessage({
|
|
||||||
// type: "objectCompleted",
|
|
||||||
// data: {
|
|
||||||
// processId: process.id,
|
|
||||||
// objectId,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!isLastPoint) {
|
|
||||||
// const currentPos = path[stateRef.currentIndex];
|
|
||||||
// const nextPos = path[nextPointIdx];
|
|
||||||
// const distance = distanceBetweenVectors(currentPos, nextPos);
|
|
||||||
// const movement = stateRef.speed * delta;
|
|
||||||
|
|
||||||
// // Update progress based on distance and speed
|
|
||||||
// const oldProgress = stateRef.progress;
|
|
||||||
// stateRef.progress += movement / distance;
|
|
||||||
|
|
||||||
// if (stateRef.progress >= 1) {
|
|
||||||
// // Reached next point
|
|
||||||
// stateRef.currentIndex = nextPointIdx;
|
|
||||||
// stateRef.progress = 0;
|
|
||||||
// stateRef.delayComplete = false;
|
|
||||||
// obj.position = [nextPos.x, nextPos.y, nextPos.z];
|
|
||||||
// } else {
|
|
||||||
// // Interpolate position
|
|
||||||
// const lerpedPos = lerpVectors(currentPos, nextPos, stateRef.progress);
|
|
||||||
// obj.position = [lerpedPos.x, lerpedPos.y, lerpedPos.z];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Only send updates when there's meaningful movement
|
|
||||||
// if (Math.abs(oldProgress - stateRef.progress) > 0.01) {
|
|
||||||
// hasChanges = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // Update animation state with modified objects
|
|
||||||
// if (Object.keys(updatedObjects).length > 0) {
|
|
||||||
// processState.spawnedObjects = {
|
|
||||||
// ...processState.spawnedObjects,
|
|
||||||
// ...updatedObjects,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // Only send position updates when there are meaningful changes
|
|
||||||
// if (hasChanges) {
|
|
||||||
// self.postMessage({
|
|
||||||
// type: "positionsUpdated",
|
|
||||||
// data: {
|
|
||||||
// processId: process.id,
|
|
||||||
// objects: updatedObjects,
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// animation-worker.js
|
|
||||||
// This web worker handles animation calculations off the main thread
|
|
||||||
|
|
||||||
/* eslint-disable no-restricted-globals */
|
|
||||||
// The above disables the ESLint rule for this file since 'self' is valid in web workers
|
|
||||||
|
|
||||||
// Store process data, animation states, and objects
|
|
||||||
let processes = [];
|
|
||||||
let animationStates = {};
|
|
||||||
let lastTimestamp = 0;
|
|
||||||
let debugMode = true;
|
|
||||||
|
|
||||||
// Logger function for debugging
|
|
||||||
function log(...args) {
|
|
||||||
if (debugMode) {
|
|
||||||
self.postMessage({
|
|
||||||
type: "debug",
|
|
||||||
data: { message: args.join(' ') }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message handler for communication with main thread
|
|
||||||
self.onmessage = function (event) {
|
|
||||||
const { type, data } = event.data;
|
|
||||||
log(`Worker received message: ${type}`);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case "initialize":
|
|
||||||
processes = data.processes;
|
|
||||||
log(`Initialized with ${processes.length} processes`);
|
|
||||||
initializeAnimationStates();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "update":
|
|
||||||
const { timestamp, isPlaying } = data;
|
|
||||||
if (isPlaying) {
|
|
||||||
const delta = lastTimestamp === 0 ? 0.016 : (timestamp - lastTimestamp) / 1000; // Convert to seconds
|
|
||||||
updateAnimations(delta, timestamp);
|
|
||||||
}
|
|
||||||
lastTimestamp = timestamp;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "reset":
|
|
||||||
log("Resetting animations");
|
|
||||||
resetAnimations();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "togglePlay":
|
|
||||||
// If resuming from pause, recalculate the time delta
|
|
||||||
log(`Toggle play: ${data.isPlaying}`);
|
|
||||||
lastTimestamp = data.timestamp;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "setDebug":
|
|
||||||
debugMode = data.enabled;
|
|
||||||
log(`Debug mode: ${debugMode}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize animation states for all processes
|
|
||||||
function initializeAnimationStates() {
|
|
||||||
animationStates = {};
|
|
||||||
|
|
||||||
processes.forEach((process) => {
|
|
||||||
if (!process || !process.id) {
|
|
||||||
log("Invalid process found:", process);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
animationStates[process.id] = {
|
|
||||||
spawnedObjects: {},
|
|
||||||
nextSpawnTime: 0,
|
|
||||||
objectIdCounter: 0,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send initial states back to main thread
|
|
||||||
self.postMessage({
|
|
||||||
type: "statesInitialized",
|
|
||||||
data: { animationStates },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset all animations
|
|
||||||
function resetAnimations() {
|
|
||||||
initializeAnimationStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find spawn point in a process
|
|
||||||
function findSpawnPoint(process) {
|
|
||||||
if (!process || !process.paths) {
|
|
||||||
log(`No paths found for process ${process?.id}`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const path of process.paths) {
|
|
||||||
if (!path || !path.points) continue;
|
|
||||||
|
|
||||||
for (const point of path.points) {
|
|
||||||
if (!point || !point.actions) continue;
|
|
||||||
|
|
||||||
const spawnAction = point.actions.find(
|
|
||||||
(a) => a && a.isUsed && a.type === "Spawn"
|
|
||||||
);
|
|
||||||
if (spawnAction) {
|
|
||||||
return { point, path };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log(`No spawn points found for process ${process.id}`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new spawned object with proper initial position
|
|
||||||
function createSpawnedObject(process, spawnPoint, currentTime, materialType) {
|
|
||||||
// Extract spawn position from the actual spawn point
|
|
||||||
const position = spawnPoint.point.position
|
|
||||||
? [...spawnPoint.point.position]
|
|
||||||
: [0, 0, 0];
|
|
||||||
|
|
||||||
// Get the path position and add it to the spawn point position
|
|
||||||
const pathPosition = spawnPoint.path.pathPosition || [0, 0, 0];
|
|
||||||
const absolutePosition = [
|
|
||||||
position[0] + pathPosition[0],
|
|
||||||
position[1] + pathPosition[1],
|
|
||||||
position[2] + pathPosition[2],
|
|
||||||
];
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: `obj-${process.id}-${animationStates[process.id].objectIdCounter}`,
|
|
||||||
position: absolutePosition,
|
|
||||||
state: {
|
|
||||||
currentIndex: 0,
|
|
||||||
progress: 0,
|
|
||||||
isAnimating: true,
|
|
||||||
speed: process.speed || 1,
|
|
||||||
isDelaying: false,
|
|
||||||
delayStartTime: 0,
|
|
||||||
currentDelayDuration: 0,
|
|
||||||
delayComplete: false,
|
|
||||||
currentPathIndex: 0,
|
|
||||||
// Store the spawn point index to start animation from correct path point
|
|
||||||
spawnPointIndex: getPointIndexInProcess(process, spawnPoint.point),
|
|
||||||
},
|
|
||||||
visible: true,
|
|
||||||
materialType: materialType || "Default",
|
|
||||||
spawnTime: currentTime,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the index of a point within the process animation path
|
|
||||||
function getPointIndexInProcess(process, point) {
|
|
||||||
if (!process.paths) return 0;
|
|
||||||
|
|
||||||
let cumulativePoints = 0;
|
|
||||||
for (const path of process.paths) {
|
|
||||||
for (let i = 0; i < (path.points?.length || 0); i++) {
|
|
||||||
if (path.points[i].uuid === point.uuid) {
|
|
||||||
return cumulativePoints + i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cumulativePoints += path.points?.length || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get point data for current animation index
|
|
||||||
function getPointDataForAnimationIndex(process, index) {
|
|
||||||
if (!process.paths) return null;
|
|
||||||
|
|
||||||
let cumulativePoints = 0;
|
|
||||||
for (const path of process.paths) {
|
|
||||||
const pointCount = path.points?.length || 0;
|
|
||||||
|
|
||||||
if (index < cumulativePoints + pointCount) {
|
|
||||||
const pointIndex = index - cumulativePoints;
|
|
||||||
return path.points?.[pointIndex] || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
cumulativePoints += pointCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert process paths to Vector3 format
|
|
||||||
function getProcessPath(process) {
|
|
||||||
if (!process.animationPath) {
|
|
||||||
log(`No animation path for process ${process.id}`);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return process.animationPath.map((p) => ({ x: p.x, y: p.y, z: p.z })) || [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle material swap for an object
|
|
||||||
function handleMaterialSwap(processId, objectId, materialType) {
|
|
||||||
const processState = animationStates[processId];
|
|
||||||
if (!processState || !processState.spawnedObjects[objectId]) return;
|
|
||||||
|
|
||||||
processState.spawnedObjects[objectId].materialType = materialType;
|
|
||||||
|
|
||||||
// Notify main thread about material change
|
|
||||||
self.postMessage({
|
|
||||||
type: "materialChanged",
|
|
||||||
data: {
|
|
||||||
processId,
|
|
||||||
objectId,
|
|
||||||
materialType,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle point actions for an object
|
|
||||||
function handlePointActions(processId, objectId, actions = [], currentTime) {
|
|
||||||
let shouldStopAnimation = false;
|
|
||||||
const processState = animationStates[processId];
|
|
||||||
|
|
||||||
if (!processState || !processState.spawnedObjects[objectId]) return false;
|
|
||||||
|
|
||||||
const objectState = processState.spawnedObjects[objectId];
|
|
||||||
|
|
||||||
actions.forEach((action) => {
|
|
||||||
if (!action || !action.isUsed) return;
|
|
||||||
|
|
||||||
switch (action.type) {
|
|
||||||
case "Delay":
|
|
||||||
if (objectState.state.isDelaying) return;
|
|
||||||
|
|
||||||
const delayDuration =
|
|
||||||
typeof action.delay === "number"
|
|
||||||
? action.delay
|
|
||||||
: parseFloat(action.delay || "0");
|
|
||||||
|
|
||||||
if (delayDuration > 0) {
|
|
||||||
objectState.state.isDelaying = true;
|
|
||||||
objectState.state.delayStartTime = currentTime;
|
|
||||||
objectState.state.currentDelayDuration = delayDuration;
|
|
||||||
objectState.state.delayComplete = false;
|
|
||||||
shouldStopAnimation = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "Despawn":
|
|
||||||
delete processState.spawnedObjects[objectId];
|
|
||||||
shouldStopAnimation = true;
|
|
||||||
|
|
||||||
// Notify main thread about despawn
|
|
||||||
self.postMessage({
|
|
||||||
type: "objectDespawned",
|
|
||||||
data: {
|
|
||||||
processId,
|
|
||||||
objectId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "Swap":
|
|
||||||
if (action.material) {
|
|
||||||
handleMaterialSwap(processId, objectId, action.material);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return shouldStopAnimation;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if point has non-inherit actions
|
|
||||||
function hasNonInheritActions(actions = []) {
|
|
||||||
return actions.some((action) => action && action.isUsed && action.type !== "Inherit");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate vector lerp (linear interpolation)
|
|
||||||
function lerpVectors(v1, v2, alpha) {
|
|
||||||
return {
|
|
||||||
x: v1.x + (v2.x - v1.x) * alpha,
|
|
||||||
y: v1.y + (v2.y - v1.y) * alpha,
|
|
||||||
z: v1.z + (v2.z - v1.z) * alpha,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate vector distance
|
|
||||||
function distanceBetweenVectors(v1, v2) {
|
|
||||||
const dx = v2.x - v1.x;
|
|
||||||
const dy = v2.y - v1.y;
|
|
||||||
const dz = v2.z - v1.z;
|
|
||||||
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process spawn logic
|
|
||||||
function processSpawns(currentTime) {
|
|
||||||
processes.forEach((process) => {
|
|
||||||
const processState = animationStates[process.id];
|
|
||||||
if (!processState) return;
|
|
||||||
|
|
||||||
const spawnPointData = findSpawnPoint(process);
|
|
||||||
if (!spawnPointData || !spawnPointData.point.actions) return;
|
|
||||||
|
|
||||||
const spawnAction = spawnPointData.point.actions.find(
|
|
||||||
(a) => a.isUsed && a.type === "Spawn"
|
|
||||||
);
|
|
||||||
if (!spawnAction) return;
|
|
||||||
|
|
||||||
const spawnInterval =
|
|
||||||
typeof spawnAction.spawnInterval === "number"
|
|
||||||
? spawnAction.spawnInterval
|
|
||||||
: parseFloat(spawnAction.spawnInterval || "2"); // Default to 2 seconds if not specified
|
|
||||||
|
|
||||||
if (currentTime >= processState.nextSpawnTime) {
|
|
||||||
const newObject = createSpawnedObject(
|
|
||||||
process,
|
|
||||||
spawnPointData,
|
|
||||||
currentTime,
|
|
||||||
spawnAction.material || "Default"
|
|
||||||
);
|
|
||||||
|
|
||||||
processState.spawnedObjects[newObject.id] = newObject;
|
|
||||||
processState.objectIdCounter++;
|
|
||||||
processState.nextSpawnTime = currentTime + spawnInterval;
|
|
||||||
|
|
||||||
log(`Spawned object ${newObject.id} for process ${process.id}`);
|
|
||||||
|
|
||||||
// Notify main thread about new object
|
|
||||||
self.postMessage({
|
|
||||||
type: "objectSpawned",
|
|
||||||
data: {
|
|
||||||
processId: process.id,
|
|
||||||
object: newObject,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update all animations
|
|
||||||
function updateAnimations(delta, currentTime) {
|
|
||||||
// First handle spawning of new objects
|
|
||||||
processSpawns(currentTime);
|
|
||||||
|
|
||||||
// Then animate existing objects
|
|
||||||
processes.forEach((process) => {
|
|
||||||
const processState = animationStates[process.id];
|
|
||||||
if (!processState) return;
|
|
||||||
|
|
||||||
const path = getProcessPath(process);
|
|
||||||
if (path.length < 2) {
|
|
||||||
log(`Path too short for process ${process.id}, length: ${path.length}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedObjects = {};
|
|
||||||
let hasChanges = false;
|
|
||||||
|
|
||||||
Object.entries(processState.spawnedObjects).forEach(([objectId, obj]) => {
|
|
||||||
if (!obj.visible || !obj.state.isAnimating) return;
|
|
||||||
|
|
||||||
const stateRef = obj.state;
|
|
||||||
|
|
||||||
// Use the spawnPointIndex as starting point if it's the initial movement
|
|
||||||
if (stateRef.currentIndex === 0 && stateRef.progress === 0) {
|
|
||||||
stateRef.currentIndex = stateRef.spawnPointIndex || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current point data
|
|
||||||
const currentPointData = getPointDataForAnimationIndex(
|
|
||||||
process,
|
|
||||||
stateRef.currentIndex
|
|
||||||
);
|
|
||||||
|
|
||||||
// Execute actions when arriving at a new point
|
|
||||||
if (stateRef.progress === 0 && currentPointData?.actions) {
|
|
||||||
const shouldStop = handlePointActions(
|
|
||||||
process.id,
|
|
||||||
objectId,
|
|
||||||
currentPointData.actions,
|
|
||||||
currentTime
|
|
||||||
);
|
|
||||||
if (shouldStop) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle delays
|
|
||||||
if (stateRef.isDelaying) {
|
|
||||||
if (
|
|
||||||
currentTime - stateRef.delayStartTime >=
|
|
||||||
stateRef.currentDelayDuration
|
|
||||||
) {
|
|
||||||
stateRef.isDelaying = false;
|
|
||||||
stateRef.delayComplete = true;
|
|
||||||
} else {
|
|
||||||
updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
|
|
||||||
return; // Keep waiting
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const nextPointIdx = stateRef.currentIndex + 1;
|
|
||||||
const isLastPoint = nextPointIdx >= path.length;
|
|
||||||
|
|
||||||
if (isLastPoint) {
|
|
||||||
if (currentPointData?.actions) {
|
|
||||||
const shouldStop = !hasNonInheritActions(currentPointData.actions);
|
|
||||||
if (shouldStop) {
|
|
||||||
// Reached the end of path with no more actions
|
|
||||||
delete processState.spawnedObjects[objectId];
|
|
||||||
log(`Object ${objectId} completed path`);
|
|
||||||
|
|
||||||
// Notify main thread to remove the object
|
|
||||||
self.postMessage({
|
|
||||||
type: "objectCompleted",
|
|
||||||
data: {
|
|
||||||
processId: process.id,
|
|
||||||
objectId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isLastPoint) {
|
|
||||||
const currentPos = path[stateRef.currentIndex];
|
|
||||||
const nextPos = path[nextPointIdx];
|
|
||||||
const distance = distanceBetweenVectors(currentPos, nextPos);
|
|
||||||
|
|
||||||
// Ensure we don't divide by zero
|
|
||||||
if (distance > 0) {
|
|
||||||
const movement = stateRef.speed * delta;
|
|
||||||
|
|
||||||
// Update progress based on distance and speed
|
|
||||||
const oldProgress = stateRef.progress;
|
|
||||||
stateRef.progress += movement / distance;
|
|
||||||
|
|
||||||
if (stateRef.progress >= 1) {
|
|
||||||
// Reached next point
|
|
||||||
stateRef.currentIndex = nextPointIdx;
|
|
||||||
stateRef.progress = 0;
|
|
||||||
stateRef.delayComplete = false;
|
|
||||||
obj.position = [nextPos.x, nextPos.y, nextPos.z];
|
|
||||||
} else {
|
|
||||||
// Interpolate position
|
|
||||||
const lerpedPos = lerpVectors(currentPos, nextPos, stateRef.progress);
|
|
||||||
obj.position = [lerpedPos.x, lerpedPos.y, lerpedPos.z];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only send updates when there's meaningful movement
|
|
||||||
if (Math.abs(oldProgress - stateRef.progress) > 0.01) {
|
|
||||||
hasChanges = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Skip to next point if distance is zero
|
|
||||||
stateRef.currentIndex = nextPointIdx;
|
|
||||||
stateRef.progress = 0;
|
|
||||||
obj.position = [nextPos.x, nextPos.y, nextPos.z];
|
|
||||||
hasChanges = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update animation state with modified objects
|
|
||||||
if (Object.keys(updatedObjects).length > 0) {
|
|
||||||
processState.spawnedObjects = {
|
|
||||||
...processState.spawnedObjects,
|
|
||||||
...updatedObjects,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Only send position updates when there are meaningful changes
|
|
||||||
if (hasChanges) {
|
|
||||||
self.postMessage({
|
|
||||||
type: "positionsUpdated",
|
|
||||||
data: {
|
|
||||||
processId: process.id,
|
|
||||||
objects: updatedObjects,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -486,20 +486,20 @@ function convertToSimulationPath(
|
|||||||
modeluuid,
|
modeluuid,
|
||||||
points: [
|
points: [
|
||||||
{
|
{
|
||||||
uuid: path.point.uuid,
|
uuid: path.points.uuid,
|
||||||
position: path.point.position,
|
position: path.points.position,
|
||||||
actions: Array.isArray(path.point.actions)
|
actions: Array.isArray(path.points.actions)
|
||||||
? path.point.actions.map(normalizeAction)
|
? path.points.actions.map(normalizeAction)
|
||||||
: [normalizeAction(path.point.actions)],
|
: [normalizeAction(path.points.actions)],
|
||||||
connections: {
|
connections: {
|
||||||
targets: path.point.connections.targets.map((target) => ({
|
targets: path.points.connections.targets.map((target) => ({
|
||||||
pathUUID: target.pathUUID,
|
pathUUID: target.pathUUID,
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
pathPosition: path.position,
|
pathPosition: path.position,
|
||||||
speed: path.point.speed || 1,
|
speed: path.points.speed || 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
114
app/src/modules/simulation/process/processObjectRender.tsx
Normal file
114
app/src/modules/simulation/process/processObjectRender.tsx
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import React, { useRef, useEffect } from "react";
|
||||||
|
import { useFrame } from "@react-three/fiber";
|
||||||
|
import * as THREE from "three";
|
||||||
|
import { GLTF } from "three-stdlib";
|
||||||
|
import { Box3Helper } from "three";
|
||||||
|
import { SpawnedObject, ProcessData } from "./types";
|
||||||
|
|
||||||
|
interface ProcessObjectRendererProps {
|
||||||
|
objectId: string;
|
||||||
|
object: SpawnedObject;
|
||||||
|
process: ProcessData;
|
||||||
|
gltf: GLTF;
|
||||||
|
showBoundingBox?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ProcessObjectRenderer: React.FC<ProcessObjectRendererProps> = ({
|
||||||
|
objectId,
|
||||||
|
object,
|
||||||
|
process,
|
||||||
|
gltf,
|
||||||
|
showBoundingBox = false,
|
||||||
|
}) => {
|
||||||
|
const meshRef = useRef<THREE.Mesh>(null);
|
||||||
|
const boxHelperRef = useRef<THREE.Box3Helper | null>(null);
|
||||||
|
const boundingBoxRef = useRef<THREE.Box3>(new THREE.Box3());
|
||||||
|
|
||||||
|
// Issue 1: Can't assign to ref.current as it's read-only
|
||||||
|
useEffect(() => {
|
||||||
|
if (object.ref && meshRef.current) {
|
||||||
|
// Instead of direct assignment, we need to store the mesh reference another way
|
||||||
|
// Option 1: If you can modify the SpawnedObject interface, add a setMesh method
|
||||||
|
if (typeof (object as any).setMesh === 'function') {
|
||||||
|
(object as any).setMesh(meshRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option 2: Store the mesh in a property that isn't ref.current
|
||||||
|
// This requires modifying your SpawnedObject interface to include this property
|
||||||
|
(object as any).meshInstance = meshRef.current;
|
||||||
|
|
||||||
|
// Option 3: If you need to maintain compatibility, you could use Object.defineProperty
|
||||||
|
// But this is a hack and not recommended
|
||||||
|
// Object.defineProperty(object.ref, 'current', { value: meshRef.current, writable: true });
|
||||||
|
}
|
||||||
|
}, [object.ref]);
|
||||||
|
|
||||||
|
// Create a bounding box helper for visualization
|
||||||
|
useFrame(() => {
|
||||||
|
if (meshRef.current && showBoundingBox) {
|
||||||
|
// Update the bounding box to match the mesh position
|
||||||
|
if (!boxHelperRef.current) {
|
||||||
|
// Get the size of the mesh
|
||||||
|
const size = new THREE.Vector3(1, 1, 1);
|
||||||
|
|
||||||
|
// If the mesh has geometry, use its dimensions
|
||||||
|
if (meshRef.current.geometry) {
|
||||||
|
const box = new THREE.Box3().setFromObject(meshRef.current);
|
||||||
|
box.getSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new bounding box centered on the mesh
|
||||||
|
boundingBoxRef.current = new THREE.Box3().setFromCenterAndSize(
|
||||||
|
meshRef.current.position,
|
||||||
|
size
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create a helper to visualize the box
|
||||||
|
boxHelperRef.current = new Box3Helper(
|
||||||
|
boundingBoxRef.current,
|
||||||
|
new THREE.Color(0xff0000)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the helper to the scene
|
||||||
|
meshRef.current.parent?.add(boxHelperRef.current);
|
||||||
|
} else {
|
||||||
|
// Update the box position to match the mesh
|
||||||
|
boundingBoxRef.current.setFromCenterAndSize(
|
||||||
|
meshRef.current.position,
|
||||||
|
boundingBoxRef.current.getSize(new THREE.Vector3())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Force the helper to update
|
||||||
|
boxHelperRef.current.updateMatrixWorld(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (gltf?.scene) {
|
||||||
|
return (
|
||||||
|
<primitive
|
||||||
|
ref={meshRef}
|
||||||
|
object={gltf.scene.clone()}
|
||||||
|
position={[0, 0, 0]}
|
||||||
|
material={object.material}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue 2: Material color type problem
|
||||||
|
return (
|
||||||
|
<mesh ref={meshRef}>
|
||||||
|
<boxGeometry args={[1, 1, 1]} />
|
||||||
|
<meshStandardMaterial
|
||||||
|
// Fix the color property access
|
||||||
|
color={
|
||||||
|
object.material && 'color' in object.material
|
||||||
|
? (object.material as THREE.MeshStandardMaterial).color
|
||||||
|
: "#00ff00"
|
||||||
|
}
|
||||||
|
metalness={0.5}
|
||||||
|
roughness={0.3}
|
||||||
|
/>
|
||||||
|
</mesh>
|
||||||
|
);
|
||||||
|
};
|
||||||
79
app/src/modules/simulation/process/types.ts
Normal file
79
app/src/modules/simulation/process/types.ts
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import * as THREE from "three";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export interface ProcessPoint {
|
||||||
|
uuid: string;
|
||||||
|
position: number[];
|
||||||
|
actions?: PointAction[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PointAction {
|
||||||
|
type: string;
|
||||||
|
isUsed: boolean;
|
||||||
|
spawnInterval?: number | string;
|
||||||
|
material?: string;
|
||||||
|
delay?: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProcessData {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
paths?: {
|
||||||
|
points?: ProcessPoint[];
|
||||||
|
}[];
|
||||||
|
animationPath?: { x: number; y: number; z: number }[];
|
||||||
|
speed?: number;
|
||||||
|
customMaterials?: Record<string, THREE.Material>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProcessAnimationState {
|
||||||
|
spawnedObjects: Record<string, SpawnedObject | SpawnedObjectWithCollision>;
|
||||||
|
nextSpawnTime: number;
|
||||||
|
objectIdCounter: number;
|
||||||
|
isProcessDelaying: boolean;
|
||||||
|
processDelayStartTime: number;
|
||||||
|
processDelayDuration: number;
|
||||||
|
isCollisionPaused?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SpawnedObject {
|
||||||
|
ref: React.RefObject<THREE.Object3D>;
|
||||||
|
state: {
|
||||||
|
currentIndex: number;
|
||||||
|
progress: number;
|
||||||
|
isAnimating: boolean;
|
||||||
|
speed: number;
|
||||||
|
isDelaying: boolean;
|
||||||
|
delayStartTime: number;
|
||||||
|
currentDelayDuration: number;
|
||||||
|
delayComplete: boolean;
|
||||||
|
currentPathIndex: number;
|
||||||
|
};
|
||||||
|
visible: boolean;
|
||||||
|
material: THREE.Material;
|
||||||
|
currentMaterialType: string;
|
||||||
|
spawnTime: number;
|
||||||
|
position: THREE.Vector3;
|
||||||
|
collision?: {
|
||||||
|
boundingBox: THREE.Box3;
|
||||||
|
isColliding: boolean;
|
||||||
|
colliding: boolean; // Added this property
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// For use in your processAnimator.tsx
|
||||||
|
// Update the CollisionState interface to include all required properties
|
||||||
|
interface CollisionState {
|
||||||
|
boundingBox: THREE.Box3;
|
||||||
|
isColliding: boolean;
|
||||||
|
colliding: boolean; // This was missing
|
||||||
|
collidingWith: string[];
|
||||||
|
}
|
||||||
|
export interface SpawnedObjectWithCollision extends SpawnedObject {
|
||||||
|
collision: {
|
||||||
|
boundingBox: THREE.Box3;
|
||||||
|
isColliding: boolean;
|
||||||
|
colliding: boolean;
|
||||||
|
collidingWith: string[];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ function Simulation() {
|
|||||||
const [processes, setProcesses] = useState([]);
|
const [processes, setProcesses] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('simulationPaths: ', simulationPaths);
|
// console.log('simulationPaths: ', simulationPaths);
|
||||||
}, [simulationPaths]);
|
}, [simulationPaths]);
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) => {
|
// points: path.points.map((point) => {
|
||||||
// if (point.uuid === selectedActionSphere.point.uuid) {
|
// if (point.uuid === selectedActionSphere.points.uuid) {
|
||||||
// const actionIndex = point.actions.length;
|
// const actionIndex = point.actions.length;
|
||||||
// const newAction = {
|
// const newAction = {
|
||||||
// uuid: THREE.MathUtils.generateUUID(),
|
// uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) =>
|
// points: path.points.map((point) =>
|
||||||
// point.uuid === selectedActionSphere.point.uuid
|
// point.uuid === selectedActionSphere.points.uuid
|
||||||
// ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) }
|
// ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) }
|
||||||
// : point
|
// : point
|
||||||
// ),
|
// ),
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) =>
|
// points: path.points.map((point) =>
|
||||||
// point.uuid === selectedActionSphere.point.uuid
|
// point.uuid === selectedActionSphere.points.uuid
|
||||||
// ? {
|
// ? {
|
||||||
// ...point,
|
// ...point,
|
||||||
// actions: point.actions.map((action) =>
|
// actions: point.actions.map((action) =>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) =>
|
// points: path.points.map((point) =>
|
||||||
// point.uuid === selectedActionSphere.point.uuid
|
// point.uuid === selectedActionSphere.points.uuid
|
||||||
// ? {
|
// ? {
|
||||||
// ...point,
|
// ...point,
|
||||||
// actions: point.actions.map((action) =>
|
// actions: point.actions.map((action) =>
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) =>
|
// points: path.points.map((point) =>
|
||||||
// point.uuid === selectedActionSphere.point.uuid
|
// point.uuid === selectedActionSphere.points.uuid
|
||||||
// ? {
|
// ? {
|
||||||
// ...point,
|
// ...point,
|
||||||
// actions: point.actions.map((action) =>
|
// actions: point.actions.map((action) =>
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) =>
|
// points: path.points.map((point) =>
|
||||||
// point.uuid === selectedActionSphere.point.uuid
|
// point.uuid === selectedActionSphere.points.uuid
|
||||||
// ? {
|
// ? {
|
||||||
// ...point,
|
// ...point,
|
||||||
// actions: point.actions.map((action) =>
|
// actions: point.actions.map((action) =>
|
||||||
@@ -152,7 +152,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) => {
|
// points: path.points.map((point) => {
|
||||||
// if (point.uuid === selectedActionSphere.point.uuid) {
|
// if (point.uuid === selectedActionSphere.points.uuid) {
|
||||||
// const triggerIndex = point.triggers.length;
|
// const triggerIndex = point.triggers.length;
|
||||||
// const newTrigger = {
|
// const newTrigger = {
|
||||||
// uuid: THREE.MathUtils.generateUUID(),
|
// uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -176,7 +176,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) =>
|
// points: path.points.map((point) =>
|
||||||
// point.uuid === selectedActionSphere.point.uuid
|
// point.uuid === selectedActionSphere.points.uuid
|
||||||
// ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) }
|
// ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) }
|
||||||
// : point
|
// : point
|
||||||
// ),
|
// ),
|
||||||
@@ -191,7 +191,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) =>
|
// points: path.points.map((point) =>
|
||||||
// point.uuid === selectedActionSphere.point.uuid
|
// point.uuid === selectedActionSphere.points.uuid
|
||||||
// ? {
|
// ? {
|
||||||
// ...point,
|
// ...point,
|
||||||
// triggers: point.triggers.map((trigger) =>
|
// triggers: point.triggers.map((trigger) =>
|
||||||
@@ -217,7 +217,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) =>
|
// points: path.points.map((point) =>
|
||||||
// point.uuid === selectedActionSphere.point.uuid
|
// point.uuid === selectedActionSphere.points.uuid
|
||||||
// ? {
|
// ? {
|
||||||
// ...point,
|
// ...point,
|
||||||
// actions: point.actions.map((action) => ({
|
// actions: point.actions.map((action) => ({
|
||||||
@@ -238,7 +238,7 @@
|
|||||||
// const updatedPaths = simulationPaths.map((path) => ({
|
// const updatedPaths = simulationPaths.map((path) => ({
|
||||||
// ...path,
|
// ...path,
|
||||||
// points: path.points.map((point) =>
|
// points: path.points.map((point) =>
|
||||||
// point.uuid === selectedActionSphere.point.uuid
|
// point.uuid === selectedActionSphere.points.uuid
|
||||||
// ? {
|
// ? {
|
||||||
// ...point,
|
// ...point,
|
||||||
// triggers: point.triggers.map((trigger) => ({
|
// triggers: point.triggers.map((trigger) => ({
|
||||||
@@ -255,7 +255,7 @@
|
|||||||
|
|
||||||
// const selectedPoint = useMemo(() => {
|
// const selectedPoint = useMemo(() => {
|
||||||
// if (!selectedActionSphere) return null;
|
// if (!selectedActionSphere) return null;
|
||||||
// return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid);
|
// return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.points.uuid);
|
||||||
// }, [selectedActionSphere, simulationPaths]);
|
// }, [selectedActionSphere, simulationPaths]);
|
||||||
|
|
||||||
// const createPath = () => {
|
// const createPath = () => {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
let BackEnd_url = `http://${process.env.REACT_APP_SERVER_ASSET_LIBRARY_URL}`;
|
let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||||
export const getCategoryAsset = async (categoryName: any) => {
|
export const getCategoryAsset = async (categoryName: any) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${BackEnd_url}/api/v2/getCatagoryAssets/${categoryName}`,
|
`${BackEnd_url}/api/v2/getCategoryAssets/${categoryName}`,
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const setEventApi = async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error("Failed to set or update Floor Item");
|
throw new Error("Failed to set or Update Event Data");
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
|
|||||||
@@ -4,8 +4,32 @@ type PlayButtonStore = {
|
|||||||
isPlaying: boolean; // Updated state name to reflect the play/pause status more clearly
|
isPlaying: boolean; // Updated state name to reflect the play/pause status more clearly
|
||||||
setIsPlaying: (value: boolean) => void; // Updated setter function name for clarity
|
setIsPlaying: (value: boolean) => void; // Updated setter function name for clarity
|
||||||
};
|
};
|
||||||
|
type PauseButtonStore = {
|
||||||
|
isPaused: boolean; // Updated state name to reflect the play/pause status more clearly
|
||||||
|
setIsPaused: (value: boolean) => void; // Updated setter function name for clarity
|
||||||
|
};
|
||||||
|
type ResetButtonStore = {
|
||||||
|
isReset: boolean; // Updated state name to reflect the play/pause status more clearly
|
||||||
|
setReset: (value: boolean) => void; // Updated setter function name for clarity
|
||||||
|
};
|
||||||
|
interface AnimationSpeedState {
|
||||||
|
speed: number;
|
||||||
|
setSpeed: (value: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
export const usePlayButtonStore = create<PlayButtonStore>((set) => ({
|
export const usePlayButtonStore = create<PlayButtonStore>((set) => ({
|
||||||
isPlaying: false, // Default state for play/pause
|
isPlaying: false, // Default state for play/pause
|
||||||
setIsPlaying: (value) => set({ isPlaying: value }), // Update isPlaying state
|
setIsPlaying: (value) => set({ isPlaying: value }), // Update isPlaying state
|
||||||
}));
|
}));
|
||||||
|
export const useResetButtonStore = create<ResetButtonStore>((set) => ({
|
||||||
|
isReset: false, // Default state for play/pause
|
||||||
|
setReset: (value) => set({ isReset: value }), // Update isPlaying state
|
||||||
|
}));
|
||||||
|
export const usePauseButtonStore = create<PauseButtonStore>((set) => ({
|
||||||
|
isPaused: false, // Default state for play/pause
|
||||||
|
setIsPaused: (value) => set({ isPaused: value }), // Update isPlaying state
|
||||||
|
}));
|
||||||
|
export const useAnimationPlaySpeed = create<AnimationSpeedState>((set) => ({
|
||||||
|
speed: 1,
|
||||||
|
setSpeed: (value) => set({ speed: value }),
|
||||||
|
}));
|
||||||
|
|||||||
58
app/src/types/world/worldTypes.d.ts
vendored
58
app/src/types/world/worldTypes.d.ts
vendored
@@ -201,27 +201,6 @@ export type FloorItemType = {
|
|||||||
modelfileID: string;
|
modelfileID: string;
|
||||||
isLocked: boolean;
|
isLocked: boolean;
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
eventData?: {
|
|
||||||
type: 'Conveyor';
|
|
||||||
points: {
|
|
||||||
uuid: string;
|
|
||||||
position: [number, number, number];
|
|
||||||
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 }[] };
|
|
||||||
}[];
|
|
||||||
speed: number | string;
|
|
||||||
} | {
|
|
||||||
type: 'Vehicle';
|
|
||||||
point: {
|
|
||||||
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: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
|
|
||||||
speed: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Array of floor items for managing multiple objects on the floor
|
// Array of floor items for managing multiple objects on the floor
|
||||||
@@ -328,12 +307,43 @@ interface VehicleEventsSchema {
|
|||||||
modeluuid: string;
|
modeluuid: string;
|
||||||
modelName: string;
|
modelName: string;
|
||||||
type: 'Vehicle';
|
type: 'Vehicle';
|
||||||
point: {
|
points: {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
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 };
|
actions: { uuid: string; name: string; type: string; start: { x: number, y: number } | {}, hitCount: number, end: { x: number, y: number } | {}, buffer: number };
|
||||||
connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
|
connections: { source: { modelUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] };
|
||||||
speed: number;
|
speed: number;
|
||||||
};
|
};
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type EventData = {
|
||||||
|
modeluuid: string;
|
||||||
|
modelname: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
rotation: { x: number; y: number; z: number };
|
||||||
|
modelfileID: string;
|
||||||
|
isLocked: boolean;
|
||||||
|
isVisible: boolean;
|
||||||
|
eventData?: {
|
||||||
|
type: 'Conveyor';
|
||||||
|
points: {
|
||||||
|
uuid: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
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 }[] };
|
||||||
|
}[];
|
||||||
|
speed: number | string;
|
||||||
|
} | {
|
||||||
|
type: 'Vehicle';
|
||||||
|
points: {
|
||||||
|
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 }[] };
|
||||||
|
speed: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user