diff --git a/app/src/components/layout/sidebarLeft/SideBarLeft.tsx b/app/src/components/layout/sidebarLeft/SideBarLeft.tsx
index dc412f7..e0b56d4 100644
--- a/app/src/components/layout/sidebarLeft/SideBarLeft.tsx
+++ b/app/src/components/layout/sidebarLeft/SideBarLeft.tsx
@@ -5,8 +5,8 @@ import Header from "./Header";
import useToggleStore from "../../../store/useUIToggleStore";
import Assets from "./Assets";
import useModuleStore from "../../../store/useModuleStore";
-import Widgets from ".//visualization/widgets/Widgets";
-import Templates from "../../../modules//visualization/template/Templates";
+import Widgets from "./visualization/widgets/Widgets";
+import Templates from "../../../modules/visualization/template/Templates";
import Search from "../../ui/inputs/Search";
const SideBarLeft: React.FC = () => {
diff --git a/app/src/components/layout/sidebarLeft/visualization/widgets/WidgetsFloating.tsx b/app/src/components/layout/sidebarLeft/visualization/widgets/WidgetsFloating.tsx
index 50d9712..b5ae0bb 100644
--- a/app/src/components/layout/sidebarLeft/visualization/widgets/WidgetsFloating.tsx
+++ b/app/src/components/layout/sidebarLeft/visualization/widgets/WidgetsFloating.tsx
@@ -5,11 +5,11 @@ import {
GlobeIcon,
WalletIcon,
} from "../../../../icons/3dChartIcons";
-import SimpleCard from "../../../../../modules//visualization/widgets/floating/cards/SimpleCard";
+import SimpleCard from "../../../../../modules/visualization/widgets/floating/cards/SimpleCard";
-import WarehouseThroughput from "../../../../../modules//visualization/widgets/floating/cards/WarehouseThroughput";
-import ProductivityDashboard from "../../../../../modules//visualization/widgets/floating/cards/ProductivityDashboard";
-import FleetEfficiency from "../../../../../modules//visualization/widgets/floating/cards/FleetEfficiency";
+import WarehouseThroughput from "../../../../../modules/visualization/widgets/floating/cards/WarehouseThroughput";
+import ProductivityDashboard from "../../../../../modules/visualization/widgets/floating/cards/ProductivityDashboard";
+import FleetEfficiency from "../../../../../modules/visualization/widgets/floating/cards/FleetEfficiency";
interface Widget {
id: string;
diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx
index b13944c..f5668bf 100644
--- a/app/src/components/layout/sidebarRight/SideBarRight.tsx
+++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx
@@ -1,173 +1,148 @@
-import React, { useEffect, useState } from "react";
+import React, { useEffect } from "react";
import Header from "./Header";
import useModuleStore, {
- useSubModuleStore,
+ useSubModuleStore,
} from "../../../store/useModuleStore";
import {
- AnalysisIcon,
- MechanicsIcon,
- PropertiesIcon,
- SimulationIcon,
+ AnalysisIcon,
+ MechanicsIcon,
+ PropertiesIcon,
+ SimulationIcon,
} from "../../icons/SimulationIcons";
import useToggleStore from "../../../store/useUIToggleStore";
import Visualization from "./visualization/Visualization";
import Analysis from "./analysis/Analysis";
import Simulations from "./simulation/Simulations";
import { useSelectedFloorItem } from "../../../store/store";
+import { useSelectedEventData, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
import GlobalProperties from "./properties/GlobalProperties";
import AsstePropertiies from "./properties/AssetProperties";
import ZoneProperties from "./properties/ZoneProperties";
import EventProperties from "./properties/eventProperties/EventProperties";
const SideBarRight: React.FC = () => {
- const { activeModule } = useModuleStore();
- const { toggleUI } = useToggleStore();
- const { subModule, setSubModule } = useSubModuleStore();
- const { selectedFloorItem } = useSelectedFloorItem();
+ const { activeModule } = useModuleStore();
+ const { toggleUI } = useToggleStore();
+ const { subModule, setSubModule } = useSubModuleStore();
+ const { selectedFloorItem } = useSelectedFloorItem();
+ const { selectedEventData } = useSelectedEventData();
+ const { selectedEventSphere } = useSelectedEventSphere();
- // Reset activeList whenever activeModule changes
- useEffect(() => {
- if (activeModule !== "simulation") setSubModule("properties");
- if (activeModule === "simulation") setSubModule("mechanics");
- }, [activeModule]);
+ // Reset activeList whenever activeModule changes
+ useEffect(() => {
+ if (activeModule !== "simulation") setSubModule("properties");
+ if (activeModule === "simulation") setSubModule("simulations");
+ }, [activeModule]);
- // romove late
- const dummyData = {
- assetType: "store",
- selectedPoint: {
- name: "Point A",
- uuid: "123e4567-e89b-12d3-a456-426614174000",
- actions: [
- {
- uuid: "action-1",
- name: "Action One",
- },
- {
- uuid: "action-2",
- name: "Action Two",
- },
- {
- uuid: "action-3",
- name: "Action Three",
- },
- ],
- },
- selectedItem: {
- item: {
- uuid: "item-1",
- name: "Item One",
- isUsed: false,
- },
- },
- setSelectedPoint: (value: string) => {
- console.log(`Selected point updated to: ${value}`);
- },
- selectedActionSphere: "Sphere A",
- };
+ useEffect(() => {
+ if (activeModule !== "mechanics" && selectedEventData && selectedEventSphere) {
+ setSubModule("mechanics");
+ } else {
+ if (activeModule === 'simulation') {
+ setSubModule("simulations");
+ }
+ };
+ }, [activeModule, selectedEventData, selectedEventSphere])
- return (
-
-
- {toggleUI && (
-
- {/* {activeModule === "builder" && ( */}
-
setSubModule("properties")}
- >
-
-
- {/* )} */}
- {activeModule === "simulation" && (
- <>
-
setSubModule("mechanics")}
- >
-
-
-
setSubModule("simulations")}
- >
-
-
-
setSubModule("analysis")}
- >
-
-
- >
- )}
+ return (
+
+
+ {toggleUI && (
+
+
setSubModule("properties")}
+ >
+
+
+ {activeModule === "simulation" && (
+ <>
+
setSubModule("mechanics")}
+ >
+
+
+
setSubModule("simulations")}
+ >
+
+
+
setSubModule("analysis")}
+ >
+
+
+ >
+ )}
+
+ )}
+ {/* process builder */}
+ {toggleUI &&
+ subModule === "properties" &&
+ activeModule !== "visualization" &&
+ !selectedFloorItem && (
+
+ )}
+ {toggleUI &&
+ subModule === "properties" &&
+ activeModule !== "visualization" &&
+ selectedFloorItem && (
+
+ )}
+ {toggleUI &&
+ subModule === "zoneProperties" &&
+ (activeModule === "builder" || activeModule === "simulation") && (
+
+ )}
+ {/* simulation */}
+ {toggleUI && activeModule === "simulation" && (
+ <>
+ {subModule === "simulations" && (
+
+ )}
+ {subModule === "mechanics" && selectedEventData && selectedEventSphere && (
+
+ )}
+ {subModule === "analysis" && (
+
+ )}
+ >
+ )}
+ {/* realtime visualization */}
+ {toggleUI && activeModule === "visualization" &&
}
- )}
- {/* process builder */}
- {toggleUI &&
- subModule === "properties" &&
- activeModule !== "visualization" &&
- !selectedFloorItem && (
-
- )}
- {toggleUI &&
- subModule === "properties" &&
- activeModule !== "visualization" &&
- selectedFloorItem && (
-
- )}
- {toggleUI &&
- subModule === "zoneProperties" &&
- (activeModule === "builder" || activeModule === "simulation") && (
-
- )}
- {/* simulation */}
-
- {toggleUI && activeModule === "simulation" && (
- <>
- {subModule === "mechanics" && (
-
- )}
- {subModule === "analysis" && (
-
- )}
- {subModule === "simulations" && (
-
- )}
- >
- )}
-
- {/* realtime visualization */}
- {toggleUI && activeModule === "visualization" &&
}
-
- );
+ );
};
-export default SideBarRight;
+export default SideBarRight;
\ No newline at end of file
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx
index c3ec6e7..6c44947 100644
--- a/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx
+++ b/app/src/components/layout/sidebarRight/properties/eventProperties/EventProperties.tsx
@@ -1,10 +1,10 @@
-import React, { useRef, useState } from "react";
+import React, { useEffect, useRef, useState } from "react";
import InputWithDropDown from "../../../../ui/inputs/InputWithDropDown";
import LabledDropdown from "../../../../ui/inputs/LabledDropdown";
import {
- AddIcon,
- RemoveIcon,
- ResizeHeightIcon,
+ AddIcon,
+ RemoveIcon,
+ ResizeHeightIcon,
} from "../../../../icons/ExportCommonIcons";
import RenameInput from "../../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../../functions/handleResizePannel";
@@ -20,191 +20,260 @@ import ProcessAction from "./actions/ProcessAction";
import StorageAction from "./actions/StorageAction";
import Trigger from "./trigger/Trigger";
-interface EventPropertiesProps {
- assetType: string;
- selectedPoint: {
- name: string;
- uuid: string;
- actions: {
- uuid: string;
- name: string;
- }[];
- };
- selectedItem: {
- item: {
- uuid: string;
- name: string;
- } | null;
- };
- setSelectedPoint: (value: string) => void;
- selectedActionSphere: string;
-}
+import { useSelectedEventData, useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
+import { useProductStore } from "../../../../../store/simulation/useProductStore";
-const EventProperties: React.FC
= ({
- assetType,
- selectedPoint,
- selectedItem,
- setSelectedPoint,
- selectedActionSphere,
-}) => {
- const actionsContainerRef = useRef(null);
+const EventProperties: React.FC = () => {
+ const actionsContainerRef = useRef(null);
- const [activeOption, setActiveOption] = useState("default");
- const [dummyactiveOption, setTypeOption] = useState("default");
+ const [activeOption, setActiveOption] = useState("default");
+ const [selectedItem, setSelectedItem] = useState<{ item: { uuid: string; name: string } | null; }>({ item: null });
+ const { selectedEventData } = useSelectedEventData();
+ const { getEventByModelUuid } = useProductStore();
+ const { selectedProduct } = useSelectedProduct();
- const getAvailableActions = () => {
- if (assetType === "conveyor") {
- return {
- defaultOption: "default",
- options: ["default", "spawn", "swap", "despawn"],
- };
- }
- if (assetType === "vehicle") {
- return {
- defaultOption: "travel",
- options: ["travel"],
- };
- }
- if (assetType === "roboticArm") {
- return {
- defaultOption: "pickAndPlace",
- options: ["pickAndPlace"],
- };
- }
- if (assetType === "machine") {
- return {
- defaultOption: "process",
- options: ["process"],
- };
- }
- if (assetType === "store") {
- return {
- defaultOption: "store",
- options: ["store", "spawn"],
- };
- } else {
- return {
- defaultOption: "default",
- options: ["default"],
- };
- }
- };
+ useEffect(() => {
+ const actions = getActions();
+ if (actions.length > 0 && !selectedItem.item) {
+ setSelectedItem({ item: actions[0] });
+ }
+ }, [selectedEventData]);
- return (
-
-
-
-
- {/*
- setTypeOption(option)}
- />
-
*/}
-
- {}}
- onChange={(value) => console.log(value)}
- />
-
-
- {}}
- onChange={(value) => console.log(value)}
- />
-
-
-
-
-
-
-
-
- {selectedPoint?.actions.map((action) => (
-
-
handleActionToggle(action.uuid)}
- >
-
-
- {selectedPoint?.actions.length > 1 && (
-
handleDeleteAction(action.uuid)}
- >
-
+ const getCurrentEventData = () => {
+ if (!selectedEventData?.data || !selectedProduct) return null;
+ const event = getEventByModelUuid(selectedProduct.productId, selectedEventData.data.modelUuid);
+ return event || null;
+ };
+
+ const getAssetType = () => {
+ const event = getCurrentEventData();
+ if (!event) return null;
+
+ switch (event.type) {
+ case 'transfer': return 'conveyor';
+ case 'vehicle': return 'vehicle';
+ case 'roboticArm': return 'roboticArm';
+ case 'machine': return 'machine';
+ case 'storageUnit': return 'storageUnit';
+ default: return null;
+ }
+ };
+
+ const getAvailableActions = () => {
+ switch (getAssetType()) {
+ case "conveyor":
+ return {
+ defaultOption: "default",
+ options: ["default", "spawn", "swap", "despawn"],
+ };
+ case "vehicle":
+ return {
+ defaultOption: "travel",
+ options: ["travel"],
+ };
+ case "roboticArm":
+ return {
+ defaultOption: "pickAndPlace",
+ options: ["pickAndPlace"],
+ };
+ case "machine":
+ return {
+ defaultOption: "process",
+ options: ["process"],
+ };
+ case "storageUnit":
+ return {
+ defaultOption: "store",
+ options: ["store", "spawn"],
+ };
+ default:
+ return {
+ defaultOption: "default",
+ options: ["default"],
+ };
+ }
+ };
+
+ // Get actions based on asset type
+ const getActions = () => {
+ if (!selectedEventData?.data) return [];
+
+ const event = selectedEventData.data;
+ switch (getAssetType()) {
+ case "conveyor":
+ return (event as ConveyorEventSchema).points
+ .find((point) => point.uuid === selectedEventData?.selectedPoint)
+ ?.action?.triggers.map((trigger) => ({
+ uuid: trigger.triggerUuid,
+ name: trigger.triggerName,
+ })) || [];
+ case "vehicle":
+ return (event as VehicleEventSchema).point.action.triggers.map(
+ (trigger) => ({
+ uuid: trigger.triggerUuid,
+ name: trigger.triggerName,
+ })
+ ) || [];
+ case "roboticArm":
+ return (event as RoboticArmEventSchema).point.actions.flatMap(
+ (action) =>
+ action.triggers.map((trigger) => ({
+ uuid: trigger.triggerUuid,
+ name: trigger.triggerName,
+ }))
+ ) || [];
+ case "machine":
+ return (event as MachineEventSchema).point.action.triggers.map(
+ (trigger) => ({
+ uuid: trigger.triggerUuid,
+ name: trigger.triggerName,
+ })
+ ) || [];
+ case "storageUnit":
+ return [
+ {
+ uuid: (event as StorageEventSchema).point.action.actionUuid,
+ name: (event as StorageEventSchema).point.action.actionName,
+ },
+ ];
+ default:
+ return [];
+ }
+ };
+
+ const handleActionToggle = (actionUuid: string) => {
+ const actions = getActions();
+ const selected = actions.find(action => action.uuid === actionUuid);
+ if (selected) {
+ setSelectedItem({ item: selected });
+ }
+ };
+
+ const handleDeleteAction = (actionUuid: string) => {
+
+ };
+
+ const actions = getActions();
+
+ const getSpeed = () => {
+ if (!selectedEventData) return "0.5";
+ if ("speed" in selectedEventData.data) return selectedEventData.data.speed.toString();
+ return "0.5";
+ };
+
+ return (
+ <>
+ {getCurrentEventData() &&
+
+
+
{selectedEventData?.data.modelName}
+
+
+
+
+ { }}
+ onChange={(value) => console.log(value)}
+ />
+
+
+
+ { }}
+ onChange={(value) => console.log(value)}
+ />
+
+
+
+ {getAssetType() === 'roboticArm' &&
+
+
+
+
+
+ {actions.map((action) => (
+
+
handleActionToggle(action.uuid)}
+ >
+
+
+ {actions.length > 1 && (
+
handleDeleteAction(action.uuid)}
+ >
+
+
+ )}
+
+ ))}
+
+
handleResize(e, actionsContainerRef)}
+ >
+
+
+
+
+
+ }
+
+
+
+
+
+
setActiveOption(option)}
+ />
+ {activeOption === "default" && }
+ {activeOption === "spawn" && }
+ {activeOption === "swap" && }
+ {activeOption === "despawn" && }
+ {activeOption === "travel" && }
+ {activeOption === "pickAndPlace" && }
+ {activeOption === "process" && }
+ {activeOption === "store" && }
+
+
+
+
- )}
- ))}
-
-
handleResize(e, actionsContainerRef)}
- >
-
-
-
-
-
-
-
-
-
-
-
setActiveOption(option)}
- />
- {activeOption === "default" && } {/* done */}
- {activeOption === "spawn" && } {/* done */}
- {activeOption === "swap" && } {/* done */}
- {activeOption === "despawn" && } {/* done */}
- {activeOption === "travel" && } {/* done */}
- {activeOption === "pickAndPlace" && } {/* done */}
- {activeOption === "process" && } {/* done */}
- {activeOption === "store" && } {/* done */}
-
-
-
-
-
-
- );
+ }
+ >
+ );
};
export default EventProperties;
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx
new file mode 100644
index 0000000..000a9d7
--- /dev/null
+++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/conveyorMechanics.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+
+function ConveyorMechanics() {
+ return (
+ <>
+ >
+ )
+}
+
+export default ConveyorMechanics
\ No newline at end of file
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx
new file mode 100644
index 0000000..b6e4fb9
--- /dev/null
+++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/machineMechanics.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+
+function MachineMechanics() {
+ return (
+ <>
+ >
+ )
+}
+
+export default MachineMechanics
\ No newline at end of file
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx
new file mode 100644
index 0000000..56e4c27
--- /dev/null
+++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/roboticArmMechanics.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+
+function RoboticArmMechanics() {
+ return (
+ <>
+ >
+ )
+}
+
+export default RoboticArmMechanics
\ No newline at end of file
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx
new file mode 100644
index 0000000..0cda40e
--- /dev/null
+++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/storageMechanics.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+
+function StorageMechanics() {
+ return (
+ <>
+ >
+ )
+}
+
+export default StorageMechanics
\ No newline at end of file
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx
new file mode 100644
index 0000000..cdb32c4
--- /dev/null
+++ b/app/src/components/layout/sidebarRight/properties/eventProperties/mechanics/vehicleMechanics.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+
+function VehicleMechanics() {
+ return (
+ <>
+ >
+ )
+}
+
+export default VehicleMechanics
\ No newline at end of file
diff --git a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
index cbb19fa..12a424c 100644
--- a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
+++ b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
@@ -7,9 +7,11 @@ import {
} from "../../../icons/ExportCommonIcons";
import RenameInput from "../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../functions/handleResizePannel";
-import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
+import { useSelectedAsset, useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { generateUUID } from "three/src/math/MathUtils";
+import RenderOverlay from "../../../templates/Overlay";
+import EditWidgetOption from "../../../ui/menu/EditWidgetOption";
interface Event {
pathName: string;
@@ -31,14 +33,9 @@ const List: React.FC
= ({ val }) => {
const Simulations: React.FC = () => {
const productsContainerRef = useRef(null);
- const { products, addProduct, removeProduct, renameProduct } = useProductStore();
+ const { products, addProduct, removeProduct, renameProduct, addEvent, removeEvent } = useProductStore();
const { selectedProduct, setSelectedProduct } = useSelectedProduct();
-
- useEffect(() => {
- if (products.length > 0 && selectedProduct.productId === '' && selectedProduct.productName === '') {
- setSelectedProduct(products[0].productId, products[0].productName);
- }
- }, [products, selectedProduct]);
+ const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const handleAddProduct = () => {
addProduct(`Product ${products.length + 1}`, generateUUID());
@@ -75,12 +72,26 @@ const Simulations: React.FC = () => {
}
};
+ const handleAddEventToProduct = () => {
+ if (selectedAsset) {
+ addEvent(selectedProduct.productId, selectedAsset);
+ clearSelectedAsset();
+ }
+ };
+
+ const handleRemoveEventFromProduct = () => {
+ if (selectedAsset) {
+ removeEvent(selectedProduct.productId, selectedAsset.modelUuid);
+ clearSelectedAsset();
+ }
+ };
+
const selectedProductData = products.find(
(product) => product.productId === selectedProduct.productId
);
- const events: Event[] = selectedProductData?.eventsData.map((event, index) => ({
- pathName: `${event.modelName} - ${event.type} #${index + 1}`,
+ const events: Event[] = selectedProductData?.eventsData.map((event) => ({
+ pathName: event.modelName,
})) || [];
return (
@@ -165,6 +176,21 @@ const Simulations: React.FC = () => {
+
+ {selectedAsset &&
+
+ {
+ if (option === 'Add to Product') {
+ handleAddEventToProduct();
+ } else {
+ handleRemoveEventFromProduct();
+ }
+ }}
+ />
+
+ }
);
};
diff --git a/app/src/components/layout/sidebarRight/visualization/design/Design.tsx b/app/src/components/layout/sidebarRight/visualization/design/Design.tsx
index 04a569a..234b936 100644
--- a/app/src/components/layout/sidebarRight/visualization/design/Design.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/design/Design.tsx
@@ -1,9 +1,9 @@
import { useState, useEffect, useRef } from "react";
import { useWidgetStore } from "../../../../../store/useWidgetStore";
-import ChartComponent from "../../../sidebarLeft//visualization/widgets/ChartComponent";
+import ChartComponent from "../../../sidebarLeft/visualization/widgets/ChartComponent";
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
import { WalletIcon } from "../../../../icons/3dChartIcons";
-import SimpleCard from "../../../../../modules//visualization/widgets/floating/cards/SimpleCard";
+import SimpleCard from "../../../../../modules/visualization/widgets/floating/cards/SimpleCard";
interface Widget {
id: string;
diff --git a/app/src/components/ui/Tools.tsx b/app/src/components/ui/Tools.tsx
index 70b1461..21ea6a7 100644
--- a/app/src/components/ui/Tools.tsx
+++ b/app/src/components/ui/Tools.tsx
@@ -15,7 +15,7 @@ import {
} from "../icons/ExportToolsIcons";
import { ArrowIcon, TickIcon } from "../icons/ExportCommonIcons";
import useModuleStore, { useThreeDStore } from "../../store/useModuleStore";
-import { handleSaveTemplate } from "../../modules//visualization/functions/handleSaveTemplate";
+import { handleSaveTemplate } from "../../modules/visualization/functions/handleSaveTemplate";
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
import useTemplateStore from "../../store/useTemplateStore";
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
diff --git a/app/src/components/ui/menu/EditWidgetOption.tsx b/app/src/components/ui/menu/EditWidgetOption.tsx
index 6fd1e94..eb937c8 100644
--- a/app/src/components/ui/menu/EditWidgetOption.tsx
+++ b/app/src/components/ui/menu/EditWidgetOption.tsx
@@ -1,23 +1,20 @@
import React, { useEffect } from "react";
import {
- useEditWidgetOptionsStore,
useLeftData,
- useRightClickSelected,
- useRightSelected,
useTopData,
} from "../../../store/visualization/useZone3DWidgetStore";
interface EditWidgetOptionProps {
options: string[];
+ onClick: (option: string) => void;
}
const EditWidgetOption: React.FC = ({
options,
+ onClick
}) => {
const { top } = useTopData();
const { left } = useLeftData();
- const { setRightSelect } = useRightSelected();
- const { setEditWidgetOptions } = useEditWidgetOptionsStore();
useEffect(() => {
@@ -38,10 +35,7 @@ const EditWidgetOption: React.FC = ({
{
- setRightSelect(option);
- setEditWidgetOptions(false);
- }}
+ onClick={() => onClick(option)}
>
{option}
diff --git a/app/src/modules/builder/builder.tsx b/app/src/modules/builder/builder.tsx
index e7f83e2..e5ff1c1 100644
--- a/app/src/modules/builder/builder.tsx
+++ b/app/src/modules/builder/builder.tsx
@@ -51,7 +51,7 @@ import Ground from "../scene/environment/ground";
// import ZoneGroup from "../groups/zoneGroup1";
import { findEnvironment } from "../../services/factoryBuilder/environment/findEnvironment";
import Layer2DVisibility from "./geomentries/layers/layer2DVisibility";
-import DrieHtmlTemp from "..//visualization/mqttTemp/drieHtmlTemp";
+import DrieHtmlTemp from "../visualization/mqttTemp/drieHtmlTemp";
import ZoneGroup from "./groups/zoneGroup";
import useModuleStore from "../../store/useModuleStore";
import MeasurementTool from "../scene/tools/measurementTool";
diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
index 8baacd9..1b3defa 100644
--- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
+++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
@@ -4,15 +4,32 @@ import { useEventsStore } from '../../../../../store/simulation/useEventsStore';
import useModuleStore from '../../../../../store/useModuleStore';
import { TransformControls } from '@react-three/drei';
import { detectModifierKeys } from '../../../../../utils/shortcutkeys/detectModifierKeys';
-import { useSelectedEventSphere } from '../../../../../store/simulation/useSimulationStore';
+import { useSelectedEventSphere, useSelectedEventData } from '../../../../../store/simulation/useSimulationStore';
function PointsCreator() {
- const { events, updatePoint, getPointByUuid } = useEventsStore();
+ 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 { setSelectedEventData, clearSelectedEventData } = useSelectedEventData();
+
+ useEffect(() => {
+ if (selectedEventSphere) {
+ const eventData = getEventByModelUuid(selectedEventSphere.userData.modelUuid);
+ if (eventData) {
+ setSelectedEventData(
+ eventData,
+ selectedEventSphere.userData.pointUuid
+ );
+ } else {
+ clearSelectedEventData();
+ }
+ } else {
+ clearSelectedEventData();
+ }
+ }, [selectedEventSphere]);
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
diff --git a/app/src/modules/simulation/products/products.tsx b/app/src/modules/simulation/products/products.tsx
index 2e9a16e..2ddd7d1 100644
--- a/app/src/modules/simulation/products/products.tsx
+++ b/app/src/modules/simulation/products/products.tsx
@@ -1,13 +1,18 @@
import React, { useEffect } from 'react'
import { useProductStore } from '../../../store/simulation/useProductStore'
import * as THREE from 'three';
+import { useSelectedProduct } from '../../../store/simulation/useSimulationStore';
function Products() {
const { products, addProduct } = useProductStore();
+ const { setSelectedProduct } = useSelectedProduct();
useEffect(() => {
if (products.length === 0) {
- addProduct('Product 1', THREE.MathUtils.generateUUID());
+ const id = THREE.MathUtils.generateUUID();
+ const name = 'Product 1';
+ addProduct(name, id);
+ setSelectedProduct(id, name);
}
}, [products])
diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx
index f02b066..4197716 100644
--- a/app/src/modules/simulation/simulation.tsx
+++ b/app/src/modules/simulation/simulation.tsx
@@ -10,39 +10,52 @@ import Machine from './machine/machine';
import StorageUnit from './storageUnit/storageUnit';
import Simulator from './simulator/simulator';
import Products from './products/products';
+import Trigger from './triggers/trigger';
+import useModuleStore from '../../store/useModuleStore';
function Simulation() {
+ const { activeModule } = useModuleStore();
const { events } = useEventsStore();
const { products } = useProductStore();
useEffect(() => {
- console.log('events: ', events);
+ // console.log('events: ', events);
}, [events])
useEffect(() => {
- // console.log('products: ', products);
+ console.log('products: ', products);
}, [products])
return (
<>
-
+ {activeModule === 'simulation' &&
-
+ <>
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+ >
+
+ }
>
)
diff --git a/app/src/modules/simulation/triggers/connector/triggerConnector.tsx b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx
new file mode 100644
index 0000000..b38e6dd
--- /dev/null
+++ b/app/src/modules/simulation/triggers/connector/triggerConnector.tsx
@@ -0,0 +1,126 @@
+import { useThree } from '@react-three/fiber'
+import React, { useEffect } from 'react'
+import { Object3D } from 'three';
+import { useSubModuleStore } from '../../../../store/useModuleStore';
+import { useLeftData, useTopData } from '../../../../store/visualization/useZone3DWidgetStore';
+import { useEventsStore } from '../../../../store/simulation/useEventsStore';
+import { useProductStore } from '../../../../store/simulation/useProductStore';
+import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
+import { useSelectedAsset } from '../../../../store/simulation/useSimulationStore';
+
+function TriggerConnector() {
+ const { gl, raycaster, scene } = useThree();
+ const { subModule } = useSubModuleStore();
+ const { setTop } = useTopData();
+ const { setLeft } = useLeftData();
+ const { getIsEventInProduct } = useProductStore();
+ const { getEventByModelUuid } = useEventsStore();
+ const { selectedProduct } = useSelectedProduct();
+ const { selectedAsset, setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
+
+ useEffect(() => {
+
+ const canvasElement = gl.domElement;
+
+ let drag = false;
+ let isRightMouseDown = false;
+
+ const onMouseDown = (evt: MouseEvent) => {
+ if (selectedAsset) {
+ clearSelectedAsset();
+ }
+ if (evt.button === 2) {
+ isRightMouseDown = true;
+ drag = false;
+ }
+ };
+
+ const onMouseUp = (evt: MouseEvent) => {
+ if (evt.button === 2) {
+ isRightMouseDown = false;
+ }
+ }
+
+ const onMouseMove = () => {
+ if (isRightMouseDown) {
+ drag = true;
+ }
+ };
+
+ const handleRightClick = (evt: MouseEvent) => {
+ if (drag) return;
+ evt.preventDefault();
+ const canvasElement = gl.domElement;
+ if (!canvasElement) return;
+
+ let intersects = raycaster.intersectObjects(scene.children, true);
+ 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;
+
+ while (currentObject) {
+ if (currentObject.name === "Scene") {
+ break;
+ }
+ currentObject = currentObject.parent as Object3D;
+ }
+ if (currentObject) {
+ const isInProduct = getIsEventInProduct(selectedProduct.productId, currentObject.uuid);
+
+ if (isInProduct) {
+ const event = getEventByModelUuid(currentObject.uuid);
+ if (event) {
+ setSelectedAsset(event)
+ const canvasRect = canvasElement.getBoundingClientRect();
+ const relativeX = evt.clientX - canvasRect.left;
+ const relativeY = evt.clientY - canvasRect.top;
+
+ setTop(relativeY);
+ setLeft(relativeX);
+ } else {
+ clearSelectedAsset()
+ }
+ } else {
+ const event = getEventByModelUuid(currentObject.uuid);
+ if (event) {
+ setSelectedAsset(event)
+ const canvasRect = canvasElement.getBoundingClientRect();
+ const relativeX = evt.clientX - canvasRect.left;
+ const relativeY = evt.clientY - canvasRect.top;
+
+ setTop(relativeY);
+ setLeft(relativeX);
+ } else {
+ clearSelectedAsset()
+ }
+ }
+
+ }
+ } else {
+ clearSelectedAsset()
+ }
+
+ };
+
+ if (subModule === 'simulations') {
+ canvasElement.addEventListener("mousedown", onMouseDown);
+ canvasElement.addEventListener("mouseup", onMouseUp);
+ canvasElement.addEventListener("mousemove", onMouseMove);
+ canvasElement.addEventListener('contextmenu', handleRightClick);
+ }
+
+ return () => {
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ canvasElement.removeEventListener('contextmenu', handleRightClick);
+ };
+
+ }, [gl, subModule, selectedProduct, selectedAsset]);
+
+ return (
+ <>
+ >
+ )
+}
+
+export default TriggerConnector
\ No newline at end of file
diff --git a/app/src/modules/simulation/triggers/temp.md b/app/src/modules/simulation/triggers/temp.md
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/modules/simulation/triggers/trigger.tsx b/app/src/modules/simulation/triggers/trigger.tsx
new file mode 100644
index 0000000..110da2e
--- /dev/null
+++ b/app/src/modules/simulation/triggers/trigger.tsx
@@ -0,0 +1,14 @@
+import React from 'react'
+import TriggerConnector from './connector/triggerConnector'
+
+function Trigger() {
+ return (
+ <>
+
+
+
+ >
+ )
+}
+
+export default Trigger
\ No newline at end of file
diff --git a/app/src/modules/visualization/RealTimeVisulization.tsx b/app/src/modules/visualization/RealTimeVisulization.tsx
index cd2c57c..30f0014 100644
--- a/app/src/modules/visualization/RealTimeVisulization.tsx
+++ b/app/src/modules/visualization/RealTimeVisulization.tsx
@@ -125,7 +125,7 @@ const RealTimeVisulization: React.FC = () => {
{}
);
setZonesData(formattedData);
- } catch (error) {}
+ } catch (error) { }
}
GetZoneData();
@@ -362,6 +362,10 @@ const RealTimeVisulization: React.FC = () => {
"RotateY",
"Delete",
]}
+ onClick={(e) => {
+ setRightSelect(e);
+ setEditWidgetOptions(false);
+ }}
/>
)}
diff --git a/app/src/services/visulization/zone/getSelect2dZoneData.ts b/app/src/services/visulization/zone/getSelect2dZoneData.ts
index b2c39e9..00d4dfe 100644
--- a/app/src/services/visulization/zone/getSelect2dZoneData.ts
+++ b/app/src/services/visulization/zone/getSelect2dZoneData.ts
@@ -7,7 +7,7 @@ export const getSelect2dZoneData = async (
) => {
try {
const response = await fetch(
- `${url_Backend_dwinzo}/api/v2/Zone/visualization/${ZoneId}?organization=${organization}`,
+ `${url_Backend_dwinzo}/api/v2/ZoneVisualization/${ZoneId}?organization=${organization}`,
{
method: "GET",
headers: {
diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts
index 81feb7f..91576c7 100644
--- a/app/src/store/simulation/useProductStore.ts
+++ b/app/src/store/simulation/useProductStore.ts
@@ -55,6 +55,11 @@ type ProductsStore = {
// Helper functions
getProductById: (productId: string) => { productName: string; productId: string; eventsData: EventsSchema[] } | undefined;
+ getEventByModelUuid: (productId: string, modelUuid: string) => EventsSchema | undefined;
+ getPointByUuid: (productId: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
+ getActionByUuid: (productId: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
+ getTriggerByUuid: (productId: string, triggerUuid: string) => TriggerSchema | undefined;
+ getIsEventInProduct: (productId: string, modelUuid: string) => boolean;
};
export const useProductStore = create()(
@@ -417,6 +422,89 @@ export const useProductStore = create()(
// Helper functions
getProductById: (productId) => {
return get().products.find(p => p.productId === productId);
+ },
+
+ getEventByModelUuid: (productId, modelUuid) => {
+ const product = get().getProductById(productId);
+ if (!product) return undefined;
+ return product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
+ },
+
+ getPointByUuid: (productId, modelUuid, pointUuid) => {
+ const event = get().getEventByModelUuid(productId, modelUuid);
+ if (!event) return undefined;
+
+ if ('points' in event) {
+ return (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
+ } else if ('point' in event && (event as any).point.uuid === pointUuid) {
+ return (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point;
+ }
+ return undefined;
+ },
+
+ getActionByUuid: (productId, actionUuid) => {
+ const product = get().products.find(p => p.productId === productId);
+ if (!product) return undefined;
+
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as ConveyorEventSchema).points) {
+ if (point.action?.actionUuid === actionUuid) {
+ return point.action;
+ }
+ }
+ } else if ('point' in event) {
+ const point = (event as any).point;
+ if ('action' in point && point.action?.actionUuid === actionUuid) {
+ return point.action;
+ } else if ('actions' in point) {
+ const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
+ if (action) return action;
+ }
+ }
+ }
+ return undefined;
+ },
+
+ getTriggerByUuid: (productId, triggerUuid) => {
+ const product = get().products.find(p => p.productId === productId);
+ if (!product) return undefined;
+
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as ConveyorEventSchema).points) {
+ for (const trigger of point.action?.triggers || []) {
+ if (trigger.triggerUuid === triggerUuid) {
+ return trigger;
+ }
+ }
+ }
+ } else if ('point' in event) {
+ const point = (event as any).point;
+ if ('action' in point) {
+ for (const trigger of point.action?.triggers || []) {
+ if (trigger.triggerUuid === triggerUuid) {
+ return trigger;
+ }
+ }
+ } else if ('actions' in point) {
+ for (const action of point.actions) {
+ for (const trigger of action.triggers || []) {
+ if (trigger.triggerUuid === triggerUuid) {
+ return trigger;
+ }
+ }
+ }
+ }
+ }
+ }
+ return undefined;
+ },
+
+ getIsEventInProduct: (productId, modelUuid) => {
+ const product = get().getProductById(productId);
+ if (!product) return false;
+ return product.eventsData.some(e => 'modelUuid' in e && e.modelUuid === modelUuid);
}
}))
);
diff --git a/app/src/store/simulation/useSimulationStore.ts b/app/src/store/simulation/useSimulationStore.ts
index 9c0fc00..ae6ac81 100644
--- a/app/src/store/simulation/useSimulationStore.ts
+++ b/app/src/store/simulation/useSimulationStore.ts
@@ -24,6 +24,50 @@ export const useSelectedEventSphere = create()(
}))
);
+interface SelectedEventDataState {
+ selectedEventData: { data: EventsSchema; selectedPoint: string } | undefined;
+ setSelectedEventData: (data: EventsSchema, selectedPoint: string) => void;
+ clearSelectedEventData: () => void;
+}
+
+export const useSelectedEventData = create()(
+ immer((set) => ({
+ selectedEventData: undefined,
+ setSelectedEventData: (data, selectedPoint) => {
+ set((state) => {
+ state.selectedEventData = { data, selectedPoint };
+ });
+ },
+ clearSelectedEventData: () => {
+ set((state) => {
+ state.selectedEventData = undefined;
+ });
+ },
+ }))
+);
+
+interface SelectedAssetState {
+ selectedAsset: EventsSchema | undefined;
+ setSelectedAsset: (EventData: EventsSchema) => void;
+ clearSelectedAsset: () => void;
+}
+
+export const useSelectedAsset = create()(
+ immer((set) => ({
+ selectedAsset: undefined,
+ setSelectedAsset: (EventData) => {
+ set((state) => {
+ state.selectedAsset = EventData;
+ });
+ },
+ clearSelectedAsset: () => {
+ set((state) => {
+ state.selectedAsset = undefined;
+ });
+ },
+ }))
+);
+
interface SelectedProductState {
selectedProduct: { productId: string; productName: string };
setSelectedProduct: (productId: string, productName: string) => void;
diff --git a/app/src/store/useModuleStore.ts b/app/src/store/useModuleStore.ts
index 1012792..3cc1d00 100644
--- a/app/src/store/useModuleStore.ts
+++ b/app/src/store/useModuleStore.ts
@@ -13,14 +13,17 @@ const useModuleStore = create((set) => ({
export default useModuleStore;
// New store for subModule
+
+type SubModule = 'properties' | 'simulations' | 'mechanics' | 'analysis' | 'zoneProperties';
+
interface SubModuleStore {
- subModule: string;
- setSubModule: (subModule: string) => void;
+ subModule: SubModule;
+ setSubModule: (subModule: SubModule) => void;
}
const useSubModuleStore = create((set) => ({
subModule: "properties", // Initial subModule state
- setSubModule: (subModule) => set({ subModule }), // Update subModule state
+ setSubModule: (value) => set({ subModule: value }), // Update subModule state
}));
export { useSubModuleStore };
diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts
index 1b99456..12c0dc2 100644
--- a/app/src/types/simulationTypes.d.ts
+++ b/app/src/types/simulationTypes.d.ts
@@ -25,7 +25,7 @@ interface ConveyorPointSchema {
action: {
actionUuid: string;
actionName: string;
- actionType: "default" | "spawn" | "swap" | "despawn";
+ actionType: "default" | "spawn" | "swap" | "delay" | "despawn";
material: string;
delay: number | "inherit";
spawnInterval: number | "inherit";
@@ -119,6 +119,8 @@ interface StorageEventSchema extends AssetEventSchema {
point: StoragePointSchema;
}
+type PointsScheme = ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema;
+
type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema;
type productsSchema = {