diff --git a/app/src/modules/scene/controls/selectionControls/moveControls.tsx b/app/src/modules/scene/controls/selectionControls/moveControls.tsx
index d371806..cc9ce50 100644
--- a/app/src/modules/scene/controls/selectionControls/moveControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/moveControls.tsx
@@ -9,6 +9,7 @@ import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifie
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
+import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
@@ -16,10 +17,28 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
const { toggleView } = useToggleView();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
+ const { selectedProduct } = useSelectedProduct();
const { floorItems, setFloorItems } = useFloorItems();
const { socket } = useSocketStore();
const itemsData = useRef
([]);
+ const email = localStorage.getItem('email')
+ const organization = (email!.split("@")[1]).split(".")[0];
+
+ const updateBackend = (
+ productName: string,
+ productId: string,
+ organization: string,
+ eventData: EventsSchema
+ ) => {
+ upsertProductOrEventApi({
+ productName: productName,
+ productId: productId,
+ organization: organization,
+ eventDatas: eventData
+ })
+ }
+
useEffect(() => {
if (!camera || !scene || toggleView || !itemsGroupRef.current) return;
@@ -190,10 +209,19 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
})
}
if (productData) {
- useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, {
+ const event = useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
+
+ if (event) {
+ updateBackend(
+ selectedProduct.productName,
+ selectedProduct.productId,
+ organization,
+ event
+ );
+ }
}
}
@@ -203,9 +231,6 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
return updatedItems;
});
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "default";
-
//REST
// await setFloorItemApi(
diff --git a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
index 08667b4..7ea7045 100644
--- a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
@@ -8,6 +8,7 @@ import * as Types from "../../../../types/world/worldTypes";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
+import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
@@ -15,10 +16,28 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
const { toggleView } = useToggleView();
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
+ const { selectedProduct } = useSelectedProduct();
const { floorItems, setFloorItems } = useFloorItems();
const { socket } = useSocketStore();
const itemsData = useRef([]);
+ const email = localStorage.getItem('email')
+ const organization = (email!.split("@")[1]).split(".")[0];
+
+ const updateBackend = (
+ productName: string,
+ productId: string,
+ organization: string,
+ eventData: EventsSchema
+ ) => {
+ upsertProductOrEventApi({
+ productName: productName,
+ productId: productId,
+ organization: organization,
+ eventDatas: eventData
+ })
+ }
+
const prevPointerPosition = useRef(null);
useEffect(() => {
@@ -190,10 +209,19 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
})
}
if (productData) {
- useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, {
+ const event = useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modelUuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
+
+ if (event) {
+ updateBackend(
+ selectedProduct.productName,
+ selectedProduct.productId,
+ organization,
+ event
+ );
+ }
}
}
@@ -203,9 +231,6 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
return updatedItems;
});
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "default";
-
//REST
// await setFloorItemApi(
diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
index e4eaafb..5037f75 100644
--- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
+++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
@@ -1,22 +1,29 @@
import React, { useEffect, useRef, useState } from "react";
import * as THREE from "three";
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
-import useModuleStore from "../../../../../store/useModuleStore";
+import useModuleStore, { useSubModuleStore } from "../../../../../store/useModuleStore";
import { TransformControls } from "@react-three/drei";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
import {
useSelectedEventSphere,
useSelectedEventData,
+ useIsDragging,
+ useIsRotating,
} from "../../../../../store/simulation/useSimulationStore";
+import { useThree } from "@react-three/fiber";
function PointsCreator() {
+ const { gl, raycaster, scene, pointer, camera } = useThree();
+ const { subModule } = useSubModuleStore();
const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore();
const { activeModule } = useModuleStore();
const transformRef = useRef(null);
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere, } = useSelectedEventSphere();
- const { selectedEventData, setSelectedEventData, clearSelectedEventData } = useSelectedEventData();
+ const { selectedEventData,setSelectedEventData, clearSelectedEventData } = useSelectedEventData();
+ const { isDragging } = useIsDragging();
+ const { isRotating } = useIsRotating();
useEffect(() => {
if (selectedEventSphere) {
@@ -75,6 +82,53 @@ function PointsCreator() {
}
};
+ useEffect(() => {
+ const canvasElement = gl.domElement;
+
+ let drag = false;
+ let isMouseDown = false;
+
+ const onMouseDown = () => {
+ isMouseDown = true;
+ drag = false;
+ };
+
+ const onMouseUp = () => {
+ if (selectedEventSphere && !drag) {
+ raycaster.setFromCamera(pointer, camera);
+ const intersects = raycaster
+ .intersectObjects(scene.children, true)
+ .filter(
+ (intersect) =>
+ intersect.object.name === ('Event-Sphere')
+ );
+ if (intersects.length === 0) {
+ clearSelectedEventSphere();
+ setTransformMode(null);
+ }
+ }
+ }
+
+ const onMouseMove = () => {
+ if (isMouseDown) {
+ drag = true;
+ }
+ };
+
+ if (subModule === 'mechanics') {
+ canvasElement.addEventListener("mousedown", onMouseDown);
+ canvasElement.addEventListener("mouseup", onMouseUp);
+ canvasElement.addEventListener("mousemove", onMouseMove);
+ }
+
+ return () => {
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ };
+
+ }, [gl, subModule, selectedEventSphere]);
+
return (
<>
{activeModule === "simulation" && (
@@ -133,10 +187,6 @@ function PointsCreator() {
sphereRefs.current[event.point.uuid]
);
}}
- onPointerMissed={() => {
- clearSelectedEventSphere();
- setTransformMode(null);
- }}
position={new THREE.Vector3(...event.point.position)}
userData={{
modelUuid: event.modelUuid,
diff --git a/app/src/modules/simulation/machine/machine.tsx b/app/src/modules/simulation/machine/machine.tsx
index 32c3b8e..e9d2dea 100644
--- a/app/src/modules/simulation/machine/machine.tsx
+++ b/app/src/modules/simulation/machine/machine.tsx
@@ -1,7 +1,43 @@
-import React from 'react'
+import React, { useEffect } from 'react'
import MachineInstances from './instances/machineInstances'
+import { useMachineStore } from '../../../store/simulation/useMachineStore'
+import { useSelectedProduct } from '../../../store/simulation/useSimulationStore';
function Machine() {
+ const { addMachine, addCurrentAction, removeMachine } = useMachineStore();
+ const { selectedProduct } = useSelectedProduct();
+
+ const machineSample: MachineEventSchema[] = [
+ {
+ modelUuid: "machine-1234-5678-9012",
+ modelName: "CNC Milling Machine",
+ position: [10, 0, 5],
+ rotation: [0, 0, 0],
+ state: "idle",
+ type: "machine",
+ point: {
+ uuid: "machine-point-9876-5432-1098",
+ position: [10, 0.5, 5.2],
+ rotation: [0, 0, 0],
+ action: {
+ actionUuid: "machine-action-2468-1357-8024",
+ actionName: "Metal Processing",
+ actionType: "process",
+ processTime: 10,
+ swapMaterial: "steel",
+ triggers: []
+ }
+ }
+ }
+ ];
+
+ useEffect(() => {
+ removeMachine(machineSample[0].modelUuid);
+ addMachine(selectedProduct.productId, machineSample[0]);
+
+ // addCurrentAction(machineSample[0].modelUuid, machineSample[0].point.action.actionUuid);
+ }, [])
+
return (
<>
diff --git a/app/src/modules/simulation/products/events/addOrRemoveEventsInProducts.tsx b/app/src/modules/simulation/products/events/addOrRemoveEventsInProducts.tsx
index 9eececc..715aa37 100644
--- a/app/src/modules/simulation/products/events/addOrRemoveEventsInProducts.tsx
+++ b/app/src/modules/simulation/products/events/addOrRemoveEventsInProducts.tsx
@@ -53,7 +53,17 @@ function AddOrRemoveEventsInProducts() {
const canvasElement = gl.domElement;
if (!canvasElement) return;
- let intersects = raycaster.intersectObjects(scene.children, true);
+ const intersects = raycaster
+ .intersectObjects(scene.children, true)
+ .filter(
+ (intersect) =>
+ !intersect.object.name.includes("Roof") &&
+ !intersect.object.name.includes("MeasurementReference") &&
+ !intersect.object.name.includes("agv-collider") &&
+ !(intersect.object.type === "GridHelper") &&
+ !(intersect.object?.parent?.name.includes('zones')) &&
+ !(intersect.object?.parent?.name.includes('Zone'))
+ );
if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) {
let currentObject = intersects[0].object;
@@ -116,6 +126,7 @@ function AddOrRemoveEventsInProducts() {
};
}, [gl, subModule, selectedProduct, selectedAsset]);
+
return (
<>>
)
diff --git a/app/src/modules/simulation/products/products.tsx b/app/src/modules/simulation/products/products.tsx
index ee1ac42..921dd96 100644
--- a/app/src/modules/simulation/products/products.tsx
+++ b/app/src/modules/simulation/products/products.tsx
@@ -7,7 +7,7 @@ import { upsertProductOrEventApi } from '../../../services/simulation/UpsertProd
import { getAllProductsApi } from '../../../services/simulation/getallProductsApi';
function Products() {
- const { products, addProduct, setProducts } = useProductStore();
+ const { addProduct, setProducts } = useProductStore();
const { setSelectedProduct } = useSelectedProduct();
useEffect(() => {
@@ -27,9 +27,6 @@ function Products() {
})
}, [])
- useEffect(() => {
- }, [])
-
return (
<>
diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx
index ff5e7e3..d4b7eaa 100644
--- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx
+++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx
@@ -258,6 +258,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
}
const logStatus = (id: string, status: string) => {
//
+
}
return (
diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx
index 5ca0ec5..757a9ef 100644
--- a/app/src/modules/simulation/simulation.tsx
+++ b/app/src/modules/simulation/simulation.tsx
@@ -23,7 +23,7 @@ function Simulation() {
}, [events])
useEffect(() => {
- // console.log('products: ', products);
+ console.log('products: ', products);
}, [products])
return (
diff --git a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx
index efefa0c..dcb46f4 100644
--- a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx
+++ b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx
@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from "react";
-import { useThree } from "@react-three/fiber";
+import { useFrame, useThree } from "@react-three/fiber";
import * as THREE from "three";
import { useSubModuleStore } from "../../../../store/useModuleStore";
import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
@@ -7,21 +7,28 @@ import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
import { handleAddEventToProduct } from "../../events/points/functions/handleAddEventToProduct";
+import { QuadraticBezierLine } from "@react-three/drei";
+import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
+import { useDeleteTool } from "../../../../store/store";
interface ConnectionLine {
id: string;
- start: THREE.Vector3;
- end: THREE.Vector3;
- mid: THREE.Vector3;
+ startPointUuid: string;
+ endPointUuid: string;
trigger: TriggerSchema;
}
function TriggerConnector() {
- const { gl, raycaster, scene } = useThree();
+ const { gl, raycaster, scene, pointer, camera } = useThree();
const { subModule } = useSubModuleStore();
- const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, addEvent, getEventByModelUuid } = useProductStore();
+ const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, removeTrigger, addEvent, getEventByModelUuid, getProductById } = useProductStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const { selectedProduct } = useSelectedProduct();
+ const [hoveredLineKey, setHoveredLineKey] = useState(null);
+ const groupRefs = useRef>({});
+ const [helperlineColor, setHelperLineColor] = useState("red");
+ const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3; end: THREE.Vector3; mid: THREE.Vector3; } | null>(null);
+ const { deleteTool } = useDeleteTool();
const [firstSelectedPoint, setFirstSelectedPoint] = useState<{
productId: string;
@@ -32,52 +39,99 @@ function TriggerConnector() {
const [connections, setConnections] = useState([]);
+ const email = localStorage.getItem('email')
+ const organization = (email!.split("@")[1]).split(".")[0];
+
+ const updateBackend = (
+ productName: string,
+ productId: string,
+ organization: string,
+ eventData: EventsSchema
+ ) => {
+ upsertProductOrEventApi({
+ productName: productName,
+ productId: productId,
+ organization: organization,
+ eventDatas: eventData
+ })
+ }
+
useEffect(() => {
const newConnections: ConnectionLine[] = [];
- products.forEach(product => {
- product.eventDatas.forEach(event => {
- if ('points' in event) {
- event.points.forEach(point => {
- if ('action' in point && point.action?.triggers) {
- point.action.triggers.forEach(trigger => {
- if (trigger.triggeredAsset) {
- const targetPoint = getPointByUuid(
- product.productId,
- trigger.triggeredAsset.triggeredModel.modelUuid,
- trigger.triggeredAsset.triggeredPoint.pointUuid
- );
+ const product = getProductById(selectedProduct.productId);
+ if (!product || products.length === 0) return;
- if (targetPoint) {
- const startPos = new THREE.Vector3(...point.position);
- const endPos = new THREE.Vector3(...targetPoint.position);
- const midPos = new THREE.Vector3()
- .addVectors(startPos, endPos)
- .multiplyScalar(0.5)
- .add(new THREE.Vector3(0, 2, 0));
-
- newConnections.push({
- id: `${point.uuid}-${targetPoint.uuid}-${trigger.triggerUuid}`,
- start: startPos,
- end: endPos,
- mid: midPos,
- trigger
- });
- }
- }
+ product.eventDatas.forEach(event => {
+ // Handle Conveyor points
+ if (event.type === "transfer" && 'points' in event) {
+ event.points.forEach(point => {
+ if (point.action?.triggers) {
+ point.action.triggers.forEach(trigger => {
+ if (trigger.triggeredAsset) {
+ newConnections.push({
+ id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
+ startPointUuid: point.uuid,
+ endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
+ trigger
+ });
+ }
+ });
+ }
+ });
+ }
+ // Handle Vehicle point
+ else if (event.type === "vehicle" && 'point' in event) {
+ const point = event.point;
+ if (point.action?.triggers) {
+ point.action.triggers.forEach(trigger => {
+ if (trigger.triggeredAsset) {
+ newConnections.push({
+ id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
+ startPointUuid: point.uuid,
+ endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
+ trigger
});
}
});
}
- });
+ }
+ // Handle Robotic Arm points
+ else if (event.type === "roboticArm" && 'point' in event) {
+ const point = event.point;
+ point.actions?.forEach(action => {
+ action.triggers?.forEach(trigger => {
+ if (trigger.triggeredAsset) {
+ newConnections.push({
+ id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
+ startPointUuid: point.uuid,
+ endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
+ trigger
+ });
+ }
+ });
+ });
+ }
+ // Handle Machine point
+ else if (event.type === "machine" && 'point' in event) {
+ const point = event.point;
+ if (point.action?.triggers) {
+ point.action.triggers.forEach(trigger => {
+ if (trigger.triggeredAsset) {
+ newConnections.push({
+ id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
+ startPointUuid: point.uuid,
+ endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
+ trigger
+ });
+ }
+ });
+ }
+ }
});
setConnections(newConnections);
- }, [products]);
-
- useEffect(() => {
- console.log('connections: ', connections);
- }, connections)
+ }, [products, selectedProduct.productId]);
useEffect(() => {
const canvasElement = gl.domElement;
@@ -111,15 +165,31 @@ function TriggerConnector() {
if (drag) return;
evt.preventDefault();
- const intersects = raycaster.intersectObjects(scene.children, true);
- if (intersects.length === 0) return;
+ const intersects = raycaster
+ .intersectObjects(scene.children, true)
+ .filter(
+ (intersect) =>
+ intersect.object.name === ('Event-Sphere')
+ );
+ if (intersects.length === 0) {
+ setFirstSelectedPoint(null);
+ return;
+ };
const currentObject = intersects[0].object;
- if (!currentObject || currentObject.name !== 'Event-Sphere') return;
+ if (!currentObject || currentObject.name !== 'Event-Sphere') {
+ setFirstSelectedPoint(null);
+ return;
+ };
const modelUuid = currentObject.userData.modelUuid;
const pointUuid = currentObject.userData.pointUuid;
+ if (firstSelectedPoint && firstSelectedPoint.pointUuid === pointUuid) {
+ setFirstSelectedPoint(null);
+ return;
+ }
+
if (selectedProduct && getIsEventInProduct(selectedProduct.productId, modelUuid)) {
const point = getPointByUuid(
@@ -128,7 +198,12 @@ function TriggerConnector() {
pointUuid
);
- if (!point) return;
+ const event = getEventByModelUuid(selectedProduct.productId, modelUuid);
+
+ if (!point || !event) {
+ setFirstSelectedPoint(null);
+ return;
+ };
let actionUuid: string | undefined;
if ('action' in point && point.action) {
@@ -152,12 +227,12 @@ function TriggerConnector() {
delay: 0,
triggeredAsset: {
triggeredModel: {
- modelName: currentObject.parent?.parent?.name || 'Unknown',
+ modelName: event.modelName || 'Unknown',
modelUuid: modelUuid
},
triggeredPoint: {
- pointName: currentObject.name,
- pointUuid: pointUuid
+ pointName: 'Point',
+ pointUuid: point.uuid
},
triggeredAction: actionUuid ? {
actionName: getActionByUuid(selectedProduct.productId, actionUuid)?.actionName || 'Action',
@@ -167,7 +242,16 @@ function TriggerConnector() {
};
if (firstSelectedPoint.actionUuid) {
- addTrigger(firstSelectedPoint.actionUuid, trigger);
+ const event = addTrigger(selectedProduct.productId, firstSelectedPoint.actionUuid, trigger);
+
+ if (event) {
+ updateBackend(
+ selectedProduct.productName,
+ selectedProduct.productId,
+ organization,
+ event
+ );
+ }
}
setFirstSelectedPoint(null);
}
@@ -184,7 +268,12 @@ function TriggerConnector() {
pointUuid
);
- if (!point) return;
+ const event = getEventByModelUuid(selectedProduct.productId, modelUuid);
+
+ if (!point || !event) {
+ setFirstSelectedPoint(null);
+ return;
+ };
let actionUuid: string | undefined;
if ('action' in point && point.action) {
@@ -200,12 +289,12 @@ function TriggerConnector() {
delay: 0,
triggeredAsset: {
triggeredModel: {
- modelName: currentObject.parent?.parent?.name || 'Unknown',
+ modelName: event.modelName || 'Unknown',
modelUuid: modelUuid
},
triggeredPoint: {
- pointName: currentObject.name,
- pointUuid: pointUuid
+ pointName: 'Point',
+ pointUuid: point.uuid
},
triggeredAction: actionUuid ? {
actionName: getActionByUuid(selectedProduct.productId, actionUuid)?.actionName || 'Action',
@@ -215,13 +304,24 @@ function TriggerConnector() {
};
if (firstSelectedPoint.actionUuid) {
- addTrigger(firstSelectedPoint.actionUuid, trigger);
+ const event = addTrigger(selectedProduct.productId, firstSelectedPoint.actionUuid, trigger);
+
+ if (event) {
+ updateBackend(
+ selectedProduct.productName,
+ selectedProduct.productId,
+ organization,
+ event
+ );
+ }
}
setFirstSelectedPoint(null);
+ } else if (firstSelectedPoint) {
+ setFirstSelectedPoint(null);
}
};
- if (subModule === 'simulations') {
+ if (subModule === 'simulations' && !deleteTool) {
canvasElement.addEventListener("mousedown", onMouseDown);
canvasElement.addEventListener("mouseup", onMouseUp);
canvasElement.addEventListener("mousemove", onMouseMove);
@@ -235,11 +335,149 @@ function TriggerConnector() {
canvasElement.removeEventListener('contextmenu', handleRightClick);
};
- }, [gl, subModule, selectedProduct, firstSelectedPoint]);
+ }, [gl, subModule, selectedProduct, firstSelectedPoint, deleteTool]);
+
+
+ useFrame(() => {
+ if (firstSelectedPoint) {
+ raycaster.setFromCamera(pointer, camera);
+ const intersects = raycaster.intersectObjects(scene.children, true).filter(
+ (intersect) =>
+ !intersect.object.name.includes("Roof") &&
+ !intersect.object.name.includes("agv-collider") &&
+ !intersect.object.name.includes("MeasurementReference") &&
+ !intersect.object.parent?.name.includes("Zone") &&
+ !(intersect.object.type === "GridHelper") &&
+ !(intersect.object.type === "Line2")
+ );
+
+ let point: THREE.Vector3 | null = null;
+
+ if (intersects.length > 0) {
+ point = intersects[0].point;
+ if (point.y < 0.05) {
+ point = new THREE.Vector3(point.x, 0.05, point.z);
+ }
+ }
+
+ const sphereIntersects = raycaster.intersectObjects(scene.children, true).filter((intersect) => intersect.object.name === ('Event-Sphere'));
+
+ if (sphereIntersects.length > 0 && sphereIntersects[0].object.uuid === firstSelectedPoint.pointUuid) {
+ setHelperLineColor('red');
+ setCurrentLine(null);
+ return;
+ }
+
+ const startPoint = getWorldPositionFromScene(firstSelectedPoint.pointUuid);
+
+ if (point && startPoint) {
+ if (sphereIntersects.length > 0) {
+ point = sphereIntersects[0].object.getWorldPosition(new THREE.Vector3());
+ }
+ const distance = startPoint.distanceTo(point);
+ const heightFactor = Math.max(0.5, distance * 0.2);
+ const midPoint = new THREE.Vector3(
+ (startPoint.x + point.x) / 2,
+ Math.max(startPoint.y, point.y) + heightFactor,
+ (startPoint.z + point.z) / 2
+ );
+
+ const endPoint = point;
+
+ setCurrentLine({
+ start: startPoint,
+ mid: midPoint,
+ end: endPoint,
+ });
+
+ setHelperLineColor(sphereIntersects.length > 0 ? "#6cf542" : "red");
+ } else {
+ setCurrentLine(null);
+ }
+ } else {
+ setCurrentLine(null);
+ }
+
+ })
+
+ const getWorldPositionFromScene = (pointUuid: string): THREE.Vector3 | null => {
+ const pointObj = scene.getObjectByProperty("uuid", pointUuid);
+ if (!pointObj) return null;
+
+ const worldPosition = new THREE.Vector3();
+ pointObj.getWorldPosition(worldPosition);
+ return worldPosition;
+ };
+
+ const removeConnection = (connection: ConnectionLine) => {
+ if (connection.trigger.triggerUuid) {
+ const event = removeTrigger(selectedProduct.productId, connection.trigger.triggerUuid);
+ if (event) {
+ updateBackend(
+ selectedProduct.productName,
+ selectedProduct.productId,
+ organization,
+ event
+ );
+ }
+ }
+ };
return (
- <>
- >
+
+ {connections.map((connection) => {
+ const startPoint = getWorldPositionFromScene(connection.startPointUuid);
+ const endPoint = getWorldPositionFromScene(connection.endPointUuid);
+
+ if (!startPoint || !endPoint) return null;
+
+ const distance = startPoint.distanceTo(endPoint);
+ const heightFactor = Math.max(0.5, distance * 0.2);
+ const midPoint = new THREE.Vector3(
+ (startPoint.x + endPoint.x) / 2,
+ Math.max(startPoint.y, endPoint.y) + heightFactor,
+ (startPoint.z + endPoint.z) / 2
+ );
+
+ return (
+ (groupRefs.current[connection.id] = el!)}
+ start={startPoint.toArray()}
+ end={endPoint.toArray()}
+ mid={midPoint.toArray()}
+ color={deleteTool && hoveredLineKey === connection.id ? "red" : "#42a5f5"}
+ lineWidth={4}
+ dashed={deleteTool && hoveredLineKey === connection.id ? false : true}
+ dashSize={0.75}
+ dashScale={20}
+ onPointerOver={() => setHoveredLineKey(connection.id)}
+ onPointerOut={() => setHoveredLineKey(null)}
+ onClick={() => {
+ if (deleteTool) {
+ setHoveredLineKey(null);
+ setCurrentLine(null);
+ removeConnection(connection);
+ }
+ }}
+ userData={connection.trigger}
+ />
+ );
+ })}
+
+ {currentLine && (
+
+ )}
+
);
}
diff --git a/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx b/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx
index 5dec724..2a124cd 100644
--- a/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx
+++ b/app/src/modules/simulation/ui/vehicle/vehicleUI.tsx
@@ -1,12 +1,16 @@
import React, { useEffect, useRef, useState } from 'react';
+import * as Types from "../../../../types/world/worldTypes";
import startPoint from "../../../../assets/gltf-glb/arrow_green.glb";
-import startEnd from "../../../../assets/gltf-glb/arrow_red.glb";
import * as THREE from "three";
+import startEnd from "../../../../assets/gltf-glb/arrow_red.glb";
import { useGLTF } from '@react-three/drei';
import { useFrame, useThree } from '@react-three/fiber';
-import { useSelectedEventSphere } from '../../../../store/simulation/useSimulationStore';
+import { useSelectedEventSphere, useIsDragging, useIsRotating } from '../../../../store/simulation/useSimulationStore';
import { useVehicleStore } from '../../../../store/simulation/useVehicleStore';
-import * as Types from "../../../../types/world/worldTypes";
+import { useProductStore } from '../../../../store/simulation/useProductStore';
+import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
+import { upsertProductOrEventApi } from '../../../../services/simulation/UpsertProductOrEventApi';
+
const VehicleUI = () => {
const { scene: startScene } = useGLTF(startPoint) as any;
const { scene: endScene } = useGLTF(startEnd) as any;
@@ -14,67 +18,60 @@ const VehicleUI = () => {
const endMarker = useRef(null);
const prevMousePos = useRef({ x: 0, y: 0 });
const { selectedEventSphere } = useSelectedEventSphere();
- const { vehicles, updateVehicle } = useVehicleStore();
+ const { selectedProduct } = useSelectedProduct();
+ const { getVehicleById } = useVehicleStore();
+ const { updateEvent } = useProductStore();
const [startPosition, setStartPosition] = useState<[number, number, number]>([0, 0, 0]);
const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 0, 0]);
const [startRotation, setStartRotation] = useState<[number, number, number]>([0, 0, 0]);
const [endRotation, setEndRotation] = useState<[number, number, number]>([0, 0, 0]);
- const [isDragging, setIsDragging] = useState<"start" | "end" | null>(null);
- const [isRotating, setIsRotating] = useState<"start" | "end" | null>(null);
+ const { isDragging, setIsDragging } = useIsDragging();
+ const { isRotating, setIsRotating } = useIsRotating();
const { raycaster } = useThree();
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0));
const state: Types.ThreeState = useThree();
const controls: any = state.controls;
+ const email = localStorage.getItem('email')
+ const organization = (email!.split("@")[1]).split(".")[0];
+
+ const updateBackend = (
+ productName: string,
+ productId: string,
+ organization: string,
+ eventData: EventsSchema
+ ) => {
+ upsertProductOrEventApi({
+ productName: productName,
+ productId: productId,
+ organization: organization,
+ eventDatas: eventData
+ })
+ }
+
useEffect(() => {
if (!selectedEventSphere) return;
- const selectedVehicle = vehicles.find(
- (vehicle: any) => vehicle.modelUuid === selectedEventSphere.userData.modelUuid
- );
+ const selectedVehicle = getVehicleById(selectedEventSphere.userData.modelUuid);
if (selectedVehicle?.point?.action) {
const { pickUpPoint, unLoadPoint } = selectedVehicle.point.action;
if (pickUpPoint) {
- const pickupPosition = new THREE.Vector3(
- pickUpPoint.position.x,
- pickUpPoint.position.y,
- pickUpPoint.position.z
- );
- const pickupRotation = new THREE.Vector3(
- pickUpPoint.rotation.x,
- pickUpPoint.rotation.y,
- pickUpPoint.rotation.z
- );
- pickupPosition.y = 0;
- setStartPosition([pickupPosition.x, 0, pickupPosition.z]);
- setStartRotation([pickupRotation.x, pickupRotation.y, pickupRotation.z]);
+ setStartPosition([pickUpPoint.position.x, 0, pickUpPoint.position.z]);
+ setStartRotation([pickUpPoint.rotation.x, pickUpPoint.rotation.y, pickUpPoint.rotation.z]);
} else {
const defaultLocal = new THREE.Vector3(0, 0, 1.5);
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
- defaultWorld.y = 0;
setStartPosition([defaultWorld.x, 0, defaultWorld.z]);
setStartRotation([0, 0, 0]);
}
if (unLoadPoint) {
- const unLoadPosition = new THREE.Vector3(
- unLoadPoint.position.x,
- unLoadPoint.position.y,
- unLoadPoint.position.z
- );
- const unLoadRotation = new THREE.Vector3(
- unLoadPoint.rotation.x,
- unLoadPoint.rotation.y,
- unLoadPoint.position.z
- );
- unLoadPosition.y = 0; // Force y to 0
- setEndPosition([unLoadPosition.x, 0, unLoadPosition.z]);
- setEndRotation([unLoadRotation.x, unLoadRotation.y, unLoadRotation.z]);
+ setEndPosition([unLoadPoint.position.x, 0, unLoadPoint.position.z]);
+ setEndRotation([unLoadPoint.rotation.x, unLoadPoint.rotation.y, unLoadPoint.rotation.z]);
} else {
const defaultLocal = new THREE.Vector3(0, 0, -1.5);
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
- defaultWorld.y = 0; // Force y to 0
setEndPosition([defaultWorld.x, 0, defaultWorld.z]);
setEndRotation([0, 0, 0]);
}
@@ -87,7 +84,6 @@ const VehicleUI = () => {
const intersects = raycaster.ray.intersectPlane(plane.current, intersectPoint);
if (intersects) {
- intersectPoint.y = 0; // Force y to 0
if (isDragging === "start") {
setStartPosition([intersectPoint.x, 0, intersectPoint.z]);
}
@@ -108,12 +104,12 @@ const VehicleUI = () => {
if (marker) {
const rotationSpeed = 10;
- marker.rotation.y += deltaX * rotationSpeed;
if (isRotating === 'start') {
- setStartRotation([marker.rotation.x, marker.rotation.y, marker.rotation.z])
+ const y = startRotation[1] + deltaX * rotationSpeed;
+ setStartRotation([0, y, 0]);
} else {
-
- setEndRotation([marker.rotation.x, marker.rotation.y, marker.rotation.z])
+ const y = endRotation[1] + deltaX * rotationSpeed;
+ setEndRotation([0, y, 0]);
}
}
});
@@ -142,43 +138,34 @@ const VehicleUI = () => {
setIsRotating(null);
if (selectedEventSphere?.userData.modelUuid) {
- const updatedVehicle = vehicles.find(
- (vehicle) => vehicle.modelUuid === selectedEventSphere.userData.modelUuid
- );
+ const updatedVehicle = getVehicleById(selectedEventSphere.userData.modelUuid);
if (updatedVehicle) {
- updateVehicle(selectedEventSphere.userData.modelUuid, {
+ const event = updateEvent(selectedProduct.productId, selectedEventSphere.userData.modelUuid, {
point: {
...updatedVehicle.point,
action: {
...updatedVehicle.point?.action,
pickUpPoint: {
- position: {
- x: startPosition[0],
- y: startPosition[1],
- z: startPosition[2],
- },
- rotation: {
- x: startRotation[0],
- y: startRotation[1],
- z: startRotation[2],
- },
+ position: { x: startPosition[0], y: startPosition[1], z: startPosition[2], },
+ rotation: { x: 0, y: startRotation[1], z: 0, },
},
unLoadPoint: {
- position: {
- x: endPosition[0],
- y: endPosition[1],
- z: endPosition[2],
- },
- rotation: {
- x: endRotation[0],
- y: endRotation[1],
- z: endRotation[2],
- },
+ position: { x: endPosition[0], y: endPosition[1], z: endPosition[2], },
+ rotation: { x: 0, y: endRotation[1], z: 0, },
},
},
},
- });
+ })
+
+ if (event) {
+ updateBackend(
+ selectedProduct.productName,
+ selectedProduct.productId,
+ organization,
+ event
+ );
+ }
}
}
};
@@ -208,6 +195,7 @@ const VehicleUI = () => {
object={startScene}
ref={startMarker}
position={startPosition}
+ rotation={startRotation}
onPointerDown={(e: any) => {
e.stopPropagation();
handlePointerDown(e, "start", "start");
@@ -224,6 +212,7 @@ const VehicleUI = () => {
object={endScene}
ref={endMarker}
position={endPosition}
+ rotation={endRotation}
onPointerDown={(e: any) => {
e.stopPropagation();
handlePointerDown(e, "end", "end");
diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx
index 2f0b235..9ca7355 100644
--- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx
+++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx
@@ -11,7 +11,7 @@ interface VehicleAnimatorProps {
reset: () => void;
currentPhase: string;
agvUuid: number;
- agvDetail: any;
+ agvDetail: VehicleStatus;
}
function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset }: VehicleAnimatorProps) {
@@ -32,7 +32,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
let startTime: number;
let fixedInterval: number;
let coveredDistance = progressRef.current;
- let objectRotation = (agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 }) as { x: number; y: number; z: number };
+ let objectRotation = (agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 }) as { x: number; y: number; z: number } | undefined;
useEffect(() => {
@@ -67,10 +67,9 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
setRestingRotation(true);
decrementVehicleLoad(agvDetail.modelUuid, 0);
const object = scene.getObjectByProperty('uuid', agvUuid);
- console.log('currentPhase: ', currentPhase);
if (object) {
object.position.set(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]);
- object.rotation.set(objectRotation.x, objectRotation.y, objectRotation.z);
+ object.rotation.set(agvDetail.rotation[0], agvDetail.rotation[1], agvDetail.rotation[2]);
}
}
}, [isReset, isPlaying])
@@ -132,7 +131,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
}
if (progressRef.current >= totalDistance) {
- if (restRotation) {
+ if (restRotation && objectRotation) {
const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(objectRotation.x, objectRotation.y, objectRotation.z));
object.quaternion.slerp(targetQuaternion, delta * 2);
const angleDiff = object.quaternion.angleTo(targetQuaternion);
diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx
index 6a81d3a..412a4ba 100644
--- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx
+++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx
@@ -30,7 +30,8 @@ function VehicleInstance({ agvDetail }: any) {
);
function vehicleStatus(modelId: string, status: string) {
- // console.log(`${modelId} , ${status});
+ // console.log(`${modelId} , ${status}`);
+
}
// Function to reset everything
@@ -44,7 +45,7 @@ function VehicleInstance({ agvDetail }: any) {
const increment = () => {
if (isIncrememtable.current) {
- incrementVehicleLoad(agvDetail.modelUuid, 2);
+ incrementVehicleLoad(agvDetail.modelUuid, 10);
isIncrememtable.current = false;
}
}
@@ -69,6 +70,7 @@ function VehicleInstance({ agvDetail }: any) {
increment();
}, 5000);
+
if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity) {
const toDrop = computePath(
agvDetail.point.action.pickUpPoint.position,
diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx
index 7badec5..19f049c 100644
--- a/app/src/modules/simulation/vehicle/vehicles.tsx
+++ b/app/src/modules/simulation/vehicle/vehicles.tsx
@@ -1,220 +1,48 @@
-import React, { useEffect, useState } from "react";
+import React, { useEffect } from "react";
import VehicleInstances from "./instances/vehicleInstances";
import { useVehicleStore } from "../../../store/simulation/useVehicleStore";
-import { useFloorItems } from "../../../store/store";
-import { useSelectedEventData, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
+import { useSelectedEventData, useSelectedEventSphere, useSelectedProduct } from "../../../store/simulation/useSimulationStore";
import VehicleUI from "../ui/vehicle/vehicleUI";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
-function Vehicles() {
+import { useProductStore } from "../../../store/simulation/useProductStore";
- const { vehicles, addVehicle } = useVehicleStore();
+function Vehicles() {
+ const { products, getProductById } = useProductStore();
+ const { selectedProduct } = useSelectedProduct();
+ const { vehicles, addVehicle, clearvehicles } = useVehicleStore();
const { selectedEventSphere } = useSelectedEventSphere();
const { selectedEventData } = useSelectedEventData();
- const { floorItems } = useFloorItems();
const { isPlaying } = usePlayButtonStore();
- const [vehicleStatusSample, setVehicleStatusSample] = useState<
- VehicleEventSchema[]
- >([
- {
- modelUuid: "9356f710-4727-4b50-bdb2-9c1e747ecc74",
- modelName: "AGV",
- position: [97.9252965204558, 0, 37.96138815638661],
- rotation: [0, 0, 0],
- state: "idle",
- type: "vehicle",
- speed: 2.5,
- point: {
- uuid: "point-789",
- position: [0, 1, 0],
- rotation: [0, 0, 0],
- action: {
- actionUuid: "action-456",
- actionName: "Deliver to Zone A",
- actionType: "travel",
- unLoadDuration: 10,
- loadCapacity: 2,
- steeringAngle:0,
- pickUpPoint: { position: { x: 98.71483985219794, y: 0, z: 28.66321267938962 }, rotation: { x: 0, y: 0, z: 0 } },
- unLoadPoint: { position: { x: 105.71483985219794, y: 0, z: 28.66321267938962 }, rotation: { x: 0, y: 0, z: 0 } },
- triggers: [
- {
- triggerUuid: "trig-001",
- triggerName: "Start Travel",
- triggerType: "onComplete",
- delay: 0,
- triggeredAsset: {
- triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
- triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
- triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
- }
- },
- {
- triggerUuid: "trig-002",
- triggerName: "Complete Travel",
- triggerType: "onComplete",
- delay: 2,
- triggeredAsset: null
- }
- ]
- }
+ useEffect(() => {
+ if (selectedProduct.productId) {
+ const product = getProductById(selectedProduct.productId);
+ if (product) {
+ clearvehicles();
+ product.eventDatas.forEach(events => {
+ if (events.type === 'vehicle') {
+ addVehicle(selectedProduct.productId, events);
+ }
+ });
}
- },
- {
- modelUuid: "b06960bb-3d2e-41f7-a646-335f389c68b4",
- modelName: "AGV",
- position: [89.61609306554463, 0, 33.634136622267356],
- rotation: [0, 0, 0],
- state: "idle",
- type: "vehicle",
- speed: 2.5,
- point: {
- uuid: "point-789",
- position: [0, 1, 0],
- rotation: [0, 0, 0],
- action: {
- actionUuid: "action-456",
- actionName: "Deliver to Zone A",
- actionType: "travel",
- unLoadDuration: 10,
- loadCapacity: 2,
- steeringAngle:0,
- pickUpPoint: null,
- unLoadPoint: null,
- triggers: [
- {
- triggerUuid: "trig-001",
- triggerName: "Start Travel",
- triggerType: "onStart",
- delay: 0,
- triggeredAsset: {
- triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
- triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
- triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
- }
- },
- {
- triggerUuid: "trig-002",
- triggerName: "Complete Travel",
- triggerType: "onComplete",
- delay: 2,
- triggeredAsset: null
- }
- ]
- }
- }
- },
- // {
- // modelUuid: "cd7d0584-0684-42b4-b051-9e882c1914aa",
- // modelName: "AGV",
- // position: [105.90938758014703, 0, 31.584209911095215],
- // rotation: [0, 0, 0],
- // state: "idle",
- // type: "vehicle",
- // speed: 2.5,
- // point: {
- // uuid: "point-789",
- // position: [0, 1, 0],
- // rotation: [0, 0, 0],
- // action: {
- // actionUuid: "action-456",
- // actionName: "Deliver to Zone A",
- // actionType: "travel",
- // unLoadDuration: 10,
- // loadCapacity: 2,
- // steeringAngle:0,
- // pickUpPoint: null,
- // unLoadPoint: null,
- // triggers: [
- // {
- // triggerUuid: "trig-001",
- // triggerName: "Start Travel",
- // triggerType: "onStart",
- // delay: 0,
- // triggeredAsset: {
- // triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
- // triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
- // triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
- // }
- // },
- // {
- // triggerUuid: "trig-002",
- // triggerName: "Complete Travel",
- // triggerType: "onComplete",
- // delay: 2,
- // triggeredAsset: null
- // }
- // ]
- // }
- // }
- // },
- // {
- // modelUuid: "e729a4f1-11d2-4778-8d6a-468f1b4f6b79",
- // modelName: "forklift",
- // position: [98.85729337188162, 0, 38.36616546567653],
- // rotation: [0, 0, 0],
- // state: "idle",
- // type: "vehicle",
- // speed: 2.5,
- // point: {
- // uuid: "point-789",
- // position: [0, 1, 0],
- // rotation: [0, 0, 0],
- // action: {
- // actionUuid: "action-456",
- // actionName: "Deliver to Zone A",
- // actionType: "travel",
- // unLoadDuration: 15,
- // loadCapacity: 5,
- // steeringAngle:0,
- // pickUpPoint: null,
- // unLoadPoint: null,
- // triggers: [
- // {
- // triggerUuid: "trig-001",
- // triggerName: "Start Travel",
- // triggerType: "onStart",
- // delay: 0,
- // triggeredAsset: {
- // triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
- // triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
- // triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
- // }
- // },
- // {
- // triggerUuid: "trig-002",
- // triggerName: "Complete Travel",
- // triggerType: "onComplete",
- // delay: 2,
- // triggeredAsset: null
- // }
- // ]
- // }
- // }
- // }
- ]);
+ }
+ }, [selectedProduct, products]);
+
useEffect(() => {
// console.log('vehicles: ', vehicles);
}, [vehicles])
- useEffect(() => {
- addVehicle("123", vehicleStatusSample[0]);
- addVehicle('123', vehicleStatusSample[1]);
- // addVehicle('123', vehicleStatusSample[2]);
- }, []);
-
-
return (
<>
+
+
{selectedEventSphere && selectedEventData?.data.type === "vehicle" && !isPlaying &&
< VehicleUI />
}
+
>
);
}
-export default Vehicles;
-
-
-
+export default Vehicles;
\ No newline at end of file
diff --git a/app/src/modules/visualization/RealTimeVisulization.tsx b/app/src/modules/visualization/RealTimeVisulization.tsx
index 05f7371..56e3054 100644
--- a/app/src/modules/visualization/RealTimeVisulization.tsx
+++ b/app/src/modules/visualization/RealTimeVisulization.tsx
@@ -11,10 +11,7 @@ import {
useDroppedObjectsStore,
useFloatingWidget,
} from "../../store/visualization/useDroppedObjectsStore";
-import {
- useSocketStore,
- useWidgetSubOption,
-} from "../../store/store";
+import { useSocketStore, useWidgetSubOption } from "../../store/store";
import { getZone2dData } from "../../services/visulization/zone/getZoneData";
import { generateUniqueId } from "../../functions/generateUniqueId";
import { determinePosition } from "./functions/determinePosition";
@@ -76,6 +73,7 @@ const RealTimeVisulization: React.FC = () => {
const { widgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore();
const { setSelectedChartId } = useWidgetStore();
+ const [waitingPanels, setWaitingPanels] = useState(null);
OuterClick({
contextClassName: [
@@ -377,6 +375,8 @@ const RealTimeVisulization: React.FC = () => {
setHiddenPanels={setHiddenPanels}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
+ waitingPanels={waitingPanels}
+ setWaitingPanels={setWaitingPanels}
/>
)}
@@ -385,6 +385,7 @@ const RealTimeVisulization: React.FC = () => {
setSelectedZone={setSelectedZone}
hiddenPanels={hiddenPanels}
setZonesData={setZonesData}
+ waitingPanels={waitingPanels}
/>
>
)}
diff --git a/app/src/modules/visualization/widgets/panel/AddButtons.tsx b/app/src/modules/visualization/widgets/panel/AddButtons.tsx
index 4877824..6968c2e 100644
--- a/app/src/modules/visualization/widgets/panel/AddButtons.tsx
+++ b/app/src/modules/visualization/widgets/panel/AddButtons.tsx
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useState } from "react";
import {
CleanPannel,
EyeIcon,
@@ -6,8 +6,6 @@ import {
} from "../../../../components/icons/RealTimeVisulationIcons";
import { AddIcon } from "../../../../components/icons/ExportCommonIcons";
import { useSocketStore } from "../../../../store/store";
-import { clearPanel } from "../../../../services/visulization/zone/clearPanel";
-import { lockPanel } from "../../../../services/visulization/zone/lockPanel";
// Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right";
@@ -57,6 +55,8 @@ interface ButtonsProps {
>;
hiddenPanels: HiddenPanels; // Updated prop type
setHiddenPanels: React.Dispatch>; // Updated prop type
+ waitingPanels: any;
+ setWaitingPanels: any;
}
const AddButtons: React.FC = ({
@@ -64,6 +64,8 @@ const AddButtons: React.FC = ({
setSelectedZone,
setHiddenPanels,
hiddenPanels,
+ waitingPanels,
+ setWaitingPanels,
}) => {
const { visualizationSocket } = useSocketStore();
@@ -174,65 +176,62 @@ const AddButtons: React.FC = ({
// Function to handle "+" button click
const handlePlusButtonClick = async (side: Side) => {
+ const zoneId = selectedZone.zoneId;
+
if (selectedZone.activeSides.includes(side)) {
- console.log("open");
- // Panel already exists: Remove widgets from that side and update activeSides
- const email = localStorage.getItem("email") || "";
- const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value
+ // Already active: Schedule removal
- // Remove all widgets associated with the side and update active sides
- const cleanedWidgets = selectedZone.widgets.filter(
- (widget) => widget.panel !== side
- );
- const newActiveSides = selectedZone.activeSides.filter((s) => s !== side);
+ setWaitingPanels(side); // Mark as waiting
- const updatedZone = {
- ...selectedZone,
- widgets: cleanedWidgets,
- activeSides: newActiveSides,
- panelOrder: newActiveSides,
- };
+ setTimeout(() => {
+ console.log("Removing after wait...");
- let deletePanel = {
- organization: organization,
- panelName: side,
- zoneId: selectedZone.zoneId,
- };
- if (visualizationSocket) {
- visualizationSocket.emit("v2:viz-panel:delete", deletePanel);
- }
- setSelectedZone(updatedZone);
-
- if (hiddenPanels[selectedZone.zoneId]?.includes(side)) {
- setHiddenPanels((prev) => ({
- ...prev,
- [selectedZone.zoneId]: prev[selectedZone.zoneId].filter(
- (s) => s !== side
- ),
- }));
- }
-
- // if(hiddenPanels[selectedZone.zoneId].includes(side))
-
- // API call to delete the panel
- // try {
- // const response = await deletePanelApi(selectedZone.zoneId, side, organization);
- //
- // if (response.message === "Panel deleted successfully") {
- // } else {
- //
- // }
- // } catch (error) {
- //
- // }
- } else {
- // Panel does not exist: Create panel
- try {
- // Get email and organization safely with a default fallback
const email = localStorage.getItem("email") || "";
- const organization = email?.split("@")[1]?.split(".")[0];
+ const organization = email?.split("@")[1]?.split(".")[0] || "";
+
+ // Remove widgets for that side
+ const cleanedWidgets = selectedZone.widgets.filter(
+ (widget) => widget.panel !== side
+ );
+ const newActiveSides = selectedZone.activeSides.filter(
+ (s) => s !== side
+ );
+
+ const updatedZone = {
+ ...selectedZone,
+ widgets: cleanedWidgets,
+ activeSides: newActiveSides,
+ panelOrder: newActiveSides,
+ };
+
+ const deletePanel = {
+ organization,
+ panelName: side,
+ zoneId,
+ };
+
+ if (visualizationSocket) {
+ visualizationSocket.emit("v2:viz-panel:delete", deletePanel);
+ }
+
+ setSelectedZone(updatedZone);
+
+ if (hiddenPanels[zoneId]?.includes(side)) {
+ setHiddenPanels((prev) => ({
+ ...prev,
+ [zoneId]: prev[zoneId].filter((s) => s !== side),
+ }));
+ }
+
+ // Remove from waiting state
+ setWaitingPanels(null);
+ }, 500); // Wait for 2 seconds
+ } else {
+ // Panel does not exist: Add it
+ try {
+ const email = localStorage.getItem("email") || "";
+ const organization = email?.split("@")[1]?.split(".")[0] || "";
- // Prevent duplicate side entries
const newActiveSides = selectedZone.activeSides.includes(side)
? [...selectedZone.activeSides]
: [...selectedZone.activeSides, side];
@@ -242,32 +241,31 @@ const AddButtons: React.FC = ({
activeSides: newActiveSides,
panelOrder: newActiveSides,
};
- let addPanel = {
- organization: organization,
- zoneId: selectedZone.zoneId,
+
+ const addPanel = {
+ organization,
+ zoneId,
panelOrder: newActiveSides,
};
+
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-panel:add", addPanel);
}
- setSelectedZone(updatedZone);
- // API call to create panels
- // const response = await panelData(organization, selectedZone.zoneId, newActiveSides);
- //
- // if (response.message === "Panels created successfully") {
- // } else {
- //
- // }
- } catch (error) {}
+ setSelectedZone(updatedZone);
+ } catch (error) {
+ console.error("Error adding panel:", error);
+ }
}
};
+
return (
<>
{(["top", "right", "bottom", "left"] as Side[]).map((side) => (
{/* "+" Button */}
+