setSubModule("properties")}
>
@@ -83,25 +82,22 @@ const SideBarRight: React.FC = () => {
{activeModule === "simulation" && (
<>
setSubModule("mechanics")}
>
setSubModule("simulations")}
>
setSubModule("analysis")}
>
diff --git a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
index 2a12734..cbb19fa 100644
--- a/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
+++ b/app/src/components/layout/sidebarRight/simulation/Simulations.tsx
@@ -1,147 +1,172 @@
-import React, { useRef, useState } from "react";
+import React, { useEffect, useRef } from "react";
import {
- AddIcon,
- ArrowIcon,
- RemoveIcon,
- ResizeHeightIcon,
+ AddIcon,
+ ArrowIcon,
+ RemoveIcon,
+ ResizeHeightIcon,
} from "../../../icons/ExportCommonIcons";
import RenameInput from "../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../functions/handleResizePannel";
+import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
+import { useProductStore } from "../../../../store/simulation/useProductStore";
+import { generateUUID } from "three/src/math/MathUtils";
-interface Path {
- pathName: string; // Represents the name of the path
- Children: string[]; // Represents the list of child points
+interface Event {
+ pathName: string;
}
-interface DropListProps {
- val: Path; // Use the Path interface for the val prop
+interface ListProps {
+ val: Event;
}
-const DropList: React.FC
= ({ val }) => {
- const [openDrop, setOpenDrop] = useState(false);
- return (
-
-
{
- setOpenDrop(!openDrop);
- }}
- >
- {val.pathName}
-
-
- {val.Children && openDrop && (
-
- {val.Children.map((child, index) => (
-
- {child}
+const List: React.FC
= ({ val }) => {
+ return (
+
- )}
-
- );
+ );
};
const Simulations: React.FC = () => {
- const productsContainerRef = useRef
(null);
- const [productsList, setProductsList] = useState([]);
- const [selectedItem, setSelectedItem] = useState();
+ const productsContainerRef = useRef(null);
+ const { products, addProduct, removeProduct, renameProduct } = useProductStore();
+ const { selectedProduct, setSelectedProduct } = useSelectedProduct();
- const handleAddAction = () => {
- setProductsList([...productsList, `Product ${productsList.length + 1}`]);
- };
+ useEffect(() => {
+ if (products.length > 0 && selectedProduct.productId === '' && selectedProduct.productName === '') {
+ setSelectedProduct(products[0].productId, products[0].productName);
+ }
+ }, [products, selectedProduct]);
- const handleRemoveAction = (index: number) => {
- setProductsList(productsList.filter((_, i) => i !== index));
- if (selectedItem === productsList[index]) {
- setSelectedItem("");
- }
- };
+ const handleAddProduct = () => {
+ addProduct(`Product ${products.length + 1}`, generateUUID());
+ };
- const Value = [
- { pathName: "Path 1", Children: ["Point 1", "Point 2"] },
- { pathName: "Path 2", Children: ["Point 1", "Point 2"] },
- { pathName: "Path 3", Children: ["Point 1", "Point 2"] },
- ];
+ const handleRemoveProduct = (productId: string) => {
+ const currentIndex = products.findIndex(p => p.productId === productId);
+ const isSelected = selectedProduct.productId === productId;
- return (
-
-
Simulations
-
-
-
-
-
- {productsList.map((action, index) => (
-
-
setSelectedItem(action)}
- >
-
-
-
-
handleRemoveAction(index)}
- >
-
-
+ const updatedProducts = products.filter(p => p.productId !== productId);
+
+ if (isSelected) {
+ if (updatedProducts.length > 0) {
+ let newSelectedIndex = currentIndex;
+ if (currentIndex >= updatedProducts.length) {
+ newSelectedIndex = updatedProducts.length - 1;
+ }
+ setSelectedProduct(
+ updatedProducts[newSelectedIndex].productId,
+ updatedProducts[newSelectedIndex].productName
+ );
+ } else {
+ setSelectedProduct('', '');
+ }
+ }
+
+ removeProduct(productId);
+ };
+
+ const handleRenameProduct = (productId: string, newName: string) => {
+ renameProduct(productId, newName);
+ if (selectedProduct.productId === productId) {
+ setSelectedProduct(productId, newName);
+ }
+ };
+
+ const selectedProductData = products.find(
+ (product) => product.productId === selectedProduct.productId
+ );
+
+ const events: Event[] = selectedProductData?.eventsData.map((event, index) => ({
+ pathName: `${event.modelName} - ${event.type} #${index + 1}`,
+ })) || [];
+
+ return (
+
+
Simulations
+
+
+
+
+
+ {products.map((product, index) => (
+
+
setSelectedProduct(product.productId, product.productName)}
+ >
+
+ handleRenameProduct(product.productId, newName)}
+ />
+
+ {products.length > 1 && (
+
handleRemoveProduct(product.productId)}
+ >
+
+
+ )}
+
+ ))}
+
+
handleResize(e, productsContainerRef)}
+ >
+
+
+
+
+
+
+
+ {events.map((event, index) => (
+
+ ))}
+
+
+
+
+ Need to Compare Layout?
+
+
+ Click 'Compare' to review and analyze the layout differences between them.
+
+
+
+
- ))}
-
handleResize(e, productsContainerRef)}
- >
-
-
-
-
-
- {Value.map((val, index) => (
-
- ))}
-
-
-
- Need to Compare Layout?
-
-
- Click 'Compare' to review and analyze the layout
- differences between them.
-
-
-
-
-
-
-
- );
+ );
};
export default Simulations;
diff --git a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts
index e88dc3c..2378bf3 100644
--- a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts
+++ b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts
@@ -8,10 +8,12 @@ import * as Types from "../../../types/world/worldTypes";
import { initializeDB, retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils';
import { getCamera } from '../../../services/factoryBuilder/camera/getCameraApi';
import { getFloorAssets } from '../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
+import PointsCalculator from '../../simulation/events/points/functions/pointsCalculator';
async function loadInitialFloorItems(
itemsGroup: Types.RefGroup,
setFloorItems: Types.setFloorItemSetState,
+ addEvent: (event: EventsSchema) => void,
): Promise
{
if (!itemsGroup.current) return;
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
@@ -70,7 +72,7 @@ async function loadInitialFloorItems(
const cachedModel = THREE.Cache.get(item.modelfileID!);
if (cachedModel) {
// console.log(`[Cache] Fetching ${item.modelname}`);
- processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems);
+ processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems, addEvent);
modelsLoaded++;
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
return;
@@ -85,7 +87,7 @@ async function loadInitialFloorItems(
URL.revokeObjectURL(blobUrl);
THREE.Cache.remove(blobUrl);
THREE.Cache.add(item.modelfileID!, gltf);
- processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems);
+ processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, addEvent);
modelsLoaded++;
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
},
@@ -106,7 +108,7 @@ async function loadInitialFloorItems(
const modelBlob = await fetch(modelUrl).then((res) => res.blob());
await storeGLTF(item.modelfileID!, modelBlob);
THREE.Cache.add(item.modelfileID!, gltf);
- processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems);
+ processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, addEvent);
modelsLoaded++;
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
},
@@ -148,8 +150,9 @@ function processLoadedModel(
item: Types.FloorItemType,
itemsGroup: Types.RefGroup,
setFloorItems: Types.setFloorItemSetState,
+ addEvent: (event: EventsSchema) => void,
) {
- const model = gltf;
+ const model = gltf.clone();
model.uuid = item.modeluuid;
model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid };
@@ -182,6 +185,243 @@ function processLoadedModel(
},
]);
+ if (item.modelfileID === "a1ee92554935007b10b3eb05") {
+ const data = PointsCalculator(
+ 'Vehicle',
+ gltf.clone(),
+ new THREE.Vector3(...model.rotation)
+ );
+
+ if (!data || !data.points) return;
+
+ const vehicleEvent: VehicleEventSchema = {
+ modelUuid: item.modeluuid,
+ modelName: item.modelname,
+ position: item.position,
+ rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
+ state: "idle",
+ type: "vehicle",
+ speed: 1,
+ point: {
+ uuid: THREE.MathUtils.generateUUID(),
+ position: [data.points[0].x, data.points[0].y, data.points[0].z],
+ rotation: [0, 0, 0],
+ action: {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: "Vehicle Action",
+ actionType: "travel",
+ material: null,
+ unLoadDuration: 5,
+ loadCapacity: 10,
+ pickUpPoint: null,
+ unLoadPoint: null,
+ triggers: []
+ }
+ }
+ };
+ addEvent(vehicleEvent);
+ } else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") {
+ const data = PointsCalculator(
+ 'Conveyor',
+ gltf.clone(),
+ new THREE.Vector3(...model.rotation)
+ );
+
+ if (!data || !data.points) return;
+
+ const ConveyorEvent: ConveyorEventSchema = {
+ modelUuid: item.modeluuid,
+ modelName: item.modelname,
+ position: item.position,
+ rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
+ state: "idle",
+ type: "transfer",
+ speed: 1,
+ points: data.points.map((point: THREE.Vector3, index: number) => ({
+ uuid: THREE.MathUtils.generateUUID(),
+ position: [point.x, point.y, point.z],
+ rotation: [0, 0, 0],
+ action: {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: `Action ${index}`,
+ actionType: 'default',
+ material: 'inherit',
+ delay: 0,
+ spawnInterval: 5,
+ spawnCount: 1,
+ triggers: []
+ }
+ }))
+ };
+ addEvent(ConveyorEvent);
+ } else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") {
+ // const data = PointsCalculator(
+ // 'Conveyor',
+ // gltf.clone(),
+ // new THREE.Vector3(...model.rotation)
+ // );
+
+ // if (!data || !data.points) return;
+
+ // const points: ConveyorPointSchema[] = data.points.map((point: THREE.Vector3, index: number) => {
+ // const actionUuid = THREE.MathUtils.generateUUID();
+ // return {
+ // uuid: THREE.MathUtils.generateUUID(),
+ // position: [point.x, point.y, point.z],
+ // rotation: [0, 0, 0],
+ // action: {
+ // actionUuid,
+ // actionName: `Action ${index}`,
+ // actionType: 'default',
+ // material: 'inherit',
+ // delay: 0,
+ // spawnInterval: 5,
+ // spawnCount: 1,
+ // triggers: []
+ // }
+ // };
+ // });
+
+ // points.forEach((point, index) => {
+ // if (index < points.length - 1) {
+ // const nextPoint = points[index + 1];
+ // point.action.triggers.push({
+ // triggerUuid: THREE.MathUtils.generateUUID(),
+ // triggerName: `Trigger 1`,
+ // triggerType: "onComplete",
+ // delay: 0,
+ // triggeredAsset: {
+ // triggeredModel: {
+ // modelName: item.modelname,
+ // modelUuid: item.modeluuid
+ // },
+ // triggeredPoint: {
+ // pointName: `Point ${index + 1}`,
+ // pointUuid: nextPoint.uuid
+ // },
+ // triggeredAction: {
+ // actionName: nextPoint.action.actionName,
+ // actionUuid: nextPoint.action.actionUuid
+ // }
+ // }
+ // });
+ // }
+ // });
+
+ // const ConveyorEvent: ConveyorEventSchema = {
+ // modelUuid: item.modeluuid,
+ // modelName: item.modelname,
+ // position: item.position,
+ // rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
+ // state: "idle",
+ // type: "transfer",
+ // speed: 1,
+ // points
+ // };
+ // addEvent(ConveyorEvent);
+ } else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") {
+ const data = PointsCalculator(
+ 'Conveyor',
+ gltf.clone(),
+ new THREE.Vector3(...model.rotation)
+ );
+
+ if (!data || !data.points) return;
+
+ const ConveyorEvent: ConveyorEventSchema = {
+ modelUuid: item.modeluuid,
+ modelName: item.modelname,
+ position: item.position,
+ rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
+ state: "idle",
+ type: "transfer",
+ speed: 1,
+ points: data.points.map((point: THREE.Vector3, index: number) => ({
+ uuid: THREE.MathUtils.generateUUID(),
+ position: [point.x, point.y, point.z],
+ rotation: [0, 0, 0],
+ action: {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: `Action ${index}`,
+ actionType: 'default',
+ material: 'inherit',
+ delay: 0,
+ spawnInterval: 5,
+ spawnCount: 1,
+ triggers: []
+ }
+ }))
+ };
+ addEvent(ConveyorEvent);
+ } else if (item.modelfileID === "29dee78715ad5b853f5c346d") {
+ const data = PointsCalculator(
+ 'StaticMachine',
+ gltf.clone(),
+ new THREE.Vector3(...model.rotation)
+ );
+
+ if (!data || !data.points) return;
+
+ const machineEvent: MachineEventSchema = {
+ modelUuid: item.modeluuid,
+ modelName: item.modelname,
+ position: item.position,
+ rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
+ state: "idle",
+ type: "machine",
+ point: {
+ uuid: THREE.MathUtils.generateUUID(),
+ position: [data.points[0].x, data.points[0].y, data.points[0].z],
+ rotation: [0, 0, 0],
+ action: {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: "Process Action",
+ actionType: "process",
+ processTime: 10,
+ swapMaterial: "material-id",
+ triggers: []
+ }
+ }
+ };
+ addEvent(machineEvent);
+ } else if (item.modelfileID === "52e6681fbb743a890d96c914") {
+ const data = PointsCalculator(
+ 'ArmBot',
+ gltf.clone(),
+ new THREE.Vector3(...model.rotation)
+ );
+
+ if (!data || !data.points) return;
+
+ const roboticArmEvent: RoboticArmEventSchema = {
+ modelUuid: item.modeluuid,
+ modelName: item.modelname,
+ position: item.position,
+ rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
+ state: "idle",
+ type: "roboticArm",
+ speed: 1,
+ point: {
+ uuid: THREE.MathUtils.generateUUID(),
+ position: [data.points[0].x, data.points[0].y, data.points[0].z],
+ rotation: [0, 0, 0],
+ actions: [
+ {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: "Pick and Place",
+ actionType: "pickAndPlace",
+ process: {
+ startPoint: [0, 0, 0],
+ endPoint: [0, 0, 0]
+ },
+ triggers: []
+ }
+ ]
+ }
+ };
+ addEvent(roboticArmEvent);
+ }
+
gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: 'power2.out' });
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out' });
}
diff --git a/app/src/modules/builder/geomentries/assets/addAssetModel.ts b/app/src/modules/builder/geomentries/assets/addAssetModel.ts
index 193dd41..670c7b5 100644
--- a/app/src/modules/builder/geomentries/assets/addAssetModel.ts
+++ b/app/src/modules/builder/geomentries/assets/addAssetModel.ts
@@ -10,7 +10,7 @@ import { retrieveGLTF, storeGLTF } from '../../../../utils/indexDB/idbUtils';
import { Socket } from 'socket.io-client';
import * as CONSTANTS from '../../../../types/world/worldConstants';
import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
-import PointsCalculator from '../../../simulation/events/points/pointsCalculator';
+import PointsCalculator from '../../../simulation/events/points/functions/pointsCalculator';
async function addAssetModel(
raycaster: THREE.Raycaster,
@@ -266,7 +266,7 @@ async function handleModelLoad(
}
};
addEvent(roboticArmEvent);
- } else if (selectedItem.type === "Machine") {
+ } else if (selectedItem.type === "StaticMachine") {
const machineEvent: MachineEventSchema = {
modelUuid: newFloorItem.modeluuid,
modelName: newFloorItem.modelname,
diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx
index 2a3c2cc..241f628 100644
--- a/app/src/modules/builder/groups/floorItemsGroup.tsx
+++ b/app/src/modules/builder/groups/floorItemsGroup.tsx
@@ -75,7 +75,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
gltfLoaderWorker.postMessage({ floorItems: data });
} else {
gltfLoaderWorker.postMessage({ floorItems: [] });
- loadInitialFloorItems(itemsGroup, setFloorItems);
+ loadInitialFloorItems(itemsGroup, setFloorItems, addEvent);
updateLoadingProgress(100);
}
});
@@ -94,7 +94,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
updateLoadingProgress(progress);
if (loadedAssets === totalAssets) {
- loadInitialFloorItems(itemsGroup, setFloorItems);
+ loadInitialFloorItems(itemsGroup, setFloorItems, addEvent);
updateLoadingProgress(100);
}
});
diff --git a/app/src/modules/scene/postProcessing/postProcessing.tsx b/app/src/modules/scene/postProcessing/postProcessing.tsx
index d3245fb..dd5607a 100644
--- a/app/src/modules/scene/postProcessing/postProcessing.tsx
+++ b/app/src/modules/scene/postProcessing/postProcessing.tsx
@@ -2,90 +2,107 @@ import * as THREE from "three";
import { EffectComposer, N8AO, Outline } from "@react-three/postprocessing";
import { BlendFunction } from "postprocessing";
import {
- useDeletableFloorItem,
- useSelectedWallItem,
- useSelectedFloorItem,
+ useDeletableFloorItem,
+ useSelectedWallItem,
+ useSelectedFloorItem,
} from "../../../store/store";
import * as Types from "../../../types/world/worldTypes";
import * as CONSTANTS from "../../../types/world/worldConstants";
import { useEffect } from "react";
+import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
export default function PostProcessing() {
- const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
- const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
- const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
+ const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
+ const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
+ const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
+ const { selectedEventSphere } = useSelectedEventSphere();
- function flattenChildren(children: any[]) {
- const allChildren: any[] = [];
- children.forEach((child) => {
- allChildren.push(child);
- if (child.children && child.children.length > 0) {
- allChildren.push(...flattenChildren(child.children));
- }
- });
- return allChildren;
- }
+ function flattenChildren(children: any[]) {
+ const allChildren: any[] = [];
+ children.forEach((child) => {
+ allChildren.push(child);
+ if (child.children && child.children.length > 0) {
+ allChildren.push(...flattenChildren(child.children));
+ }
+ });
+ return allChildren;
+ }
- return (
- <>
-
-
- {deletableFloorItem && (
-
- )}
- {selectedWallItem && (
- child.name !== "CSG_REF"
- )}
- selectionLayer={10}
- width={3000}
- blendFunction={BlendFunction.ALPHA}
- edgeStrength={5}
- resolutionScale={2}
- pulseSpeed={0}
- visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
- hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
- blur={true}
- xRay={true}
- />
- )}
- {selectedFloorItem && (
-
- )}
-
- >
- );
+ return (
+ <>
+
+
+ {deletableFloorItem && (
+
+ )}
+ {selectedWallItem && (
+ child.name !== "CSG_REF"
+ )}
+ selectionLayer={10}
+ width={3000}
+ blendFunction={BlendFunction.ALPHA}
+ edgeStrength={5}
+ resolutionScale={2}
+ pulseSpeed={0}
+ visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
+ hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
+ blur={true}
+ xRay={true}
+ />
+ )}
+ {selectedFloorItem && (
+
+ )}
+ {selectedEventSphere && (
+
+ )}
+
+ >
+ );
}
diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
index 335f1f5..8baacd9 100644
--- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
+++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx
@@ -4,20 +4,20 @@ 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';
function PointsCreator() {
const { events, updatePoint, getPointByUuid } = useEventsStore();
const { activeModule } = useModuleStore();
const transformRef = useRef(null);
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
- const [selectedPoint, setSelectedPoint] = useState(null);
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
+ const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere } = useSelectedEventSphere();
useEffect(() => {
- setTransformMode(null);
const handleKeyDown = (e: KeyboardEvent) => {
const keyCombination = detectModifierKeys(e);
- if (!selectedPoint) return;
+ if (!selectedEventSphere) return;
if (keyCombination === "G") {
setTransformMode((prev) => (prev === "translate" ? null : "translate"));
}
@@ -28,13 +28,13 @@ function PointsCreator() {
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
- }, [selectedPoint]);
+ }, [selectedEventSphere]);
- const updatePointToState = (selectedPoint: THREE.Mesh) => {
- let point = JSON.parse(JSON.stringify(getPointByUuid(selectedPoint.userData.modelUuid, selectedPoint.userData.pointUuid)));
+ const updatePointToState = (selectedEventSphere: THREE.Mesh) => {
+ let point = JSON.parse(JSON.stringify(getPointByUuid(selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid)));
if (point) {
- point.position = [selectedPoint.position.x, selectedPoint.position.y, selectedPoint.position.z];
- updatePoint(selectedPoint.userData.modelUuid, selectedPoint.userData.pointUuid, point)
+ point.position = [selectedEventSphere.position.x, selectedEventSphere.position.y, selectedEventSphere.position.z];
+ updatePoint(selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid, point)
}
}
@@ -53,10 +53,11 @@ function PointsCreator() {
ref={(el) => (sphereRefs.current[point.uuid] = el!)}
onClick={(e) => {
e.stopPropagation();
- setSelectedPoint(sphereRefs.current[point.uuid]);
+ setSelectedEventSphere(sphereRefs.current[point.uuid]);
}}
onPointerMissed={() => {
- setSelectedPoint(null);
+ clearSelectedEventSphere();
+ setTransformMode(null);
}}
key={`${i}-${j}`}
position={new THREE.Vector3(...point.position)}
@@ -76,10 +77,11 @@ function PointsCreator() {
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
onClick={(e) => {
e.stopPropagation();
- setSelectedPoint(sphereRefs.current[event.point.uuid]);
+ setSelectedEventSphere(sphereRefs.current[event.point.uuid]);
}}
onPointerMissed={() => {
- setSelectedPoint(null);
+ clearSelectedEventSphere();
+ setTransformMode(null);
}}
position={new THREE.Vector3(...event.point.position)}
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
@@ -97,10 +99,11 @@ function PointsCreator() {
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
onClick={(e) => {
e.stopPropagation();
- setSelectedPoint(sphereRefs.current[event.point.uuid]);
+ setSelectedEventSphere(sphereRefs.current[event.point.uuid]);
}}
onPointerMissed={() => {
- setSelectedPoint(null);
+ clearSelectedEventSphere();
+ setTransformMode(null);
}}
position={new THREE.Vector3(...event.point.position)}
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
@@ -118,10 +121,11 @@ function PointsCreator() {
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
onClick={(e) => {
e.stopPropagation();
- setSelectedPoint(sphereRefs.current[event.point.uuid]);
+ setSelectedEventSphere(sphereRefs.current[event.point.uuid]);
}}
onPointerMissed={() => {
- setSelectedPoint(null);
+ clearSelectedEventSphere();
+ setTransformMode(null);
}}
position={new THREE.Vector3(...event.point.position)}
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
@@ -136,8 +140,8 @@ function PointsCreator() {
}
})}
- {(selectedPoint && transformMode) &&
- { updatePointToState(selectedPoint) }} />
+ {(selectedEventSphere && transformMode) &&
+ { updatePointToState(selectedEventSphere) }} />
}
>
}
diff --git a/app/src/modules/simulation/events/points/pointsCalculator.ts b/app/src/modules/simulation/events/points/functions/pointsCalculator.ts
similarity index 96%
rename from app/src/modules/simulation/events/points/pointsCalculator.ts
rename to app/src/modules/simulation/events/points/functions/pointsCalculator.ts
index 86d368e..ccc2dbb 100644
--- a/app/src/modules/simulation/events/points/pointsCalculator.ts
+++ b/app/src/modules/simulation/events/points/functions/pointsCalculator.ts
@@ -1,5 +1,5 @@
import * as THREE from 'three';
-import { Group } from '../../../../types/world/worldTypes';
+import { Group } from '../../../../../types/world/worldTypes';
function PointsCalculator(
type: string,
diff --git a/app/src/modules/simulation/machine/instances/machineInstance/machineInstance.tsx b/app/src/modules/simulation/machine/instances/machineInstance/machineInstance.tsx
new file mode 100644
index 0000000..edb825f
--- /dev/null
+++ b/app/src/modules/simulation/machine/instances/machineInstance/machineInstance.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+
+function MachineInstance() {
+ return (
+ <>
+ >
+ )
+}
+
+export default MachineInstance
\ No newline at end of file
diff --git a/app/src/modules/simulation/machine/instances/machineInstances.tsx b/app/src/modules/simulation/machine/instances/machineInstances.tsx
new file mode 100644
index 0000000..b0c2c9f
--- /dev/null
+++ b/app/src/modules/simulation/machine/instances/machineInstances.tsx
@@ -0,0 +1,14 @@
+import React from 'react'
+import MachineInstance from './machineInstance/machineInstance'
+
+function MachineInstances() {
+ return (
+ <>
+
+
+
+ >
+ )
+}
+
+export default MachineInstances
\ No newline at end of file
diff --git a/app/src/modules/simulation/machine/machine.tsx b/app/src/modules/simulation/machine/machine.tsx
new file mode 100644
index 0000000..32c3b8e
--- /dev/null
+++ b/app/src/modules/simulation/machine/machine.tsx
@@ -0,0 +1,14 @@
+import React from 'react'
+import MachineInstances from './instances/machineInstances'
+
+function Machine() {
+ return (
+ <>
+
+
+
+ >
+ )
+}
+
+export default Machine
\ No newline at end of file
diff --git a/app/src/modules/simulation/products/products.tsx b/app/src/modules/simulation/products/products.tsx
new file mode 100644
index 0000000..2e9a16e
--- /dev/null
+++ b/app/src/modules/simulation/products/products.tsx
@@ -0,0 +1,20 @@
+import React, { useEffect } from 'react'
+import { useProductStore } from '../../../store/simulation/useProductStore'
+import * as THREE from 'three';
+
+function Products() {
+ const { products, addProduct } = useProductStore();
+
+ useEffect(() => {
+ if (products.length === 0) {
+ addProduct('Product 1', THREE.MathUtils.generateUUID());
+ }
+ }, [products])
+
+ return (
+ <>
+ >
+ )
+}
+
+export default Products
\ No newline at end of file
diff --git a/app/src/modules/simulation/roboticArm/roboticArm.tsx b/app/src/modules/simulation/roboticArm/roboticArm.tsx
index 1270d93..02a1690 100644
--- a/app/src/modules/simulation/roboticArm/roboticArm.tsx
+++ b/app/src/modules/simulation/roboticArm/roboticArm.tsx
@@ -1,6 +1,5 @@
import React from 'react'
import RoboticArmInstances from './instances/roboticArmInstances';
-import IkInstances from './instances/ikInstances';
function RoboticArm() {
return (
diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx
index b7bf36d..f02b066 100644
--- a/app/src/modules/simulation/simulation.tsx
+++ b/app/src/modules/simulation/simulation.tsx
@@ -5,13 +5,18 @@ import Vehicles from './vehicle/vehicles';
import Points from './events/points/points';
import Conveyor from './conveyor/conveyor';
import RoboticArm from './roboticArm/roboticArm';
+import Materials from './materials/materials';
+import Machine from './machine/machine';
+import StorageUnit from './storageUnit/storageUnit';
+import Simulator from './simulator/simulator';
+import Products from './products/products';
function Simulation() {
const { events } = useEventsStore();
const { products } = useProductStore();
useEffect(() => {
- // console.log('events: ', events);
+ console.log('events: ', events);
}, [events])
useEffect(() => {
@@ -23,11 +28,21 @@ function Simulation() {
+
+
+
+
+
+
-
+
+
+
+
+
>
)
diff --git a/app/src/modules/simulation/simulator/simulator.tsx b/app/src/modules/simulation/simulator/simulator.tsx
new file mode 100644
index 0000000..8cc22d6
--- /dev/null
+++ b/app/src/modules/simulation/simulator/simulator.tsx
@@ -0,0 +1,11 @@
+import React from 'react'
+
+function Simulator() {
+ return (
+ <>
+
+ >
+ )
+}
+
+export default Simulator
\ No newline at end of file
diff --git a/app/src/modules/simulation/storageUnit/instances/storageUnitInstance/storageUnitInstance.tsx b/app/src/modules/simulation/storageUnit/instances/storageUnitInstance/storageUnitInstance.tsx
new file mode 100644
index 0000000..29d404e
--- /dev/null
+++ b/app/src/modules/simulation/storageUnit/instances/storageUnitInstance/storageUnitInstance.tsx
@@ -0,0 +1,10 @@
+import React from 'react'
+
+function storageUnitInstance() {
+ return (
+ <>
+ >
+ )
+}
+
+export default storageUnitInstance
\ No newline at end of file
diff --git a/app/src/modules/simulation/storageUnit/instances/storageUnitInstances.tsx b/app/src/modules/simulation/storageUnit/instances/storageUnitInstances.tsx
new file mode 100644
index 0000000..d79b5d8
--- /dev/null
+++ b/app/src/modules/simulation/storageUnit/instances/storageUnitInstances.tsx
@@ -0,0 +1,14 @@
+import React from 'react'
+import StorageUnitInstance from './storageUnitInstance/storageUnitInstance'
+
+function StorageUnitInstances() {
+ return (
+ <>
+
+
+
+ >
+ )
+}
+
+export default StorageUnitInstances
\ No newline at end of file
diff --git a/app/src/modules/simulation/storageUnit/storageUnit.tsx b/app/src/modules/simulation/storageUnit/storageUnit.tsx
new file mode 100644
index 0000000..eee0875
--- /dev/null
+++ b/app/src/modules/simulation/storageUnit/storageUnit.tsx
@@ -0,0 +1,14 @@
+import React from 'react'
+import StorageUnitInstances from './instances/storageUnitInstances'
+
+function StorageUnit() {
+ return (
+ <>
+
+
+
+ >
+ )
+}
+
+export default StorageUnit
\ No newline at end of file
diff --git a/app/src/store/simulation/useArmBotStore.ts b/app/src/store/simulation/useArmBotStore.ts
index 493a068..d907f21 100644
--- a/app/src/store/simulation/useArmBotStore.ts
+++ b/app/src/store/simulation/useArmBotStore.ts
@@ -17,6 +17,9 @@ interface ArmBotStore {
addAction: (modelUuid: string, action: RoboticArmPointSchema['actions'][number]) => void;
removeAction: (modelUuid: string, actionUuid: string) => void;
+ updateStartPoint: (modelUuid: string, actionUuid: string, startPoint: [number, number, number] | null) => void;
+ updateEndPoint: (modelUuid: string, actionUuid: string, endPoint: [number, number, number] | null) => void;
+
setArmBotActive: (modelUuid: string, isActive: boolean) => void;
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
@@ -106,6 +109,30 @@ export const useArmBotStore = create()(
});
},
+ updateStartPoint: (modelUuid, actionUuid, startPoint) => {
+ set((state) => {
+ const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
+ if (armBot) {
+ const action = armBot.point.actions.find(a => a.actionUuid === actionUuid);
+ if (action) {
+ action.process.startPoint = startPoint;
+ }
+ }
+ });
+ },
+
+ updateEndPoint: (modelUuid, actionUuid, endPoint) => {
+ set((state) => {
+ const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
+ if (armBot) {
+ const action = armBot.point.actions.find(a => a.actionUuid === actionUuid);
+ if (action) {
+ action.process.endPoint = endPoint;
+ }
+ }
+ });
+ },
+
setArmBotActive: (modelUuid, isActive) => {
set((state) => {
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
diff --git a/app/src/store/simulation/useMaterialStore.ts b/app/src/store/simulation/useMaterialStore.ts
new file mode 100644
index 0000000..56a35a7
--- /dev/null
+++ b/app/src/store/simulation/useMaterialStore.ts
@@ -0,0 +1,76 @@
+import { create } from 'zustand';
+import { immer } from 'zustand/middleware/immer';
+
+type MaterialsStore = {
+ materials: MaterialsSchema;
+
+ addMaterial: (material: MaterialSchema) => void;
+ removeMaterial: (materialId: string) => void;
+ updateMaterial: (materialId: string, updates: Partial) => void;
+
+ setStartTime: (materialId: string, startTime: string) => void;
+ setEndTime: (materialId: string, endTime: string) => void;
+ setCost: (materialId: string, cost: number) => void;
+ setWeight: (materialId: string, weight: number) => void;
+
+ getMaterialById: (materialId: string) => MaterialSchema | undefined;
+};
+
+export const useMaterialStore = create()(
+ immer((set, get) => ({
+ materials: [],
+
+ addMaterial: (material) => {
+ set((state) => {
+ state.materials.push(material);
+ });
+ },
+
+ removeMaterial: (materialId) => {
+ set((state) => {
+ state.materials = state.materials.filter(m => m.materialId !== materialId);
+ });
+ },
+
+ updateMaterial: (materialId, updates) => {
+ set((state) => {
+ const material = state.materials.find(m => m.materialId === materialId);
+ if (material) {
+ Object.assign(material, updates);
+ }
+ });
+ },
+
+ setStartTime: (materialId, startTime) => {
+ set((state) => {
+ const material = state.materials.find(m => m.materialId === materialId);
+ if (material) material.startTime = startTime;
+ });
+ },
+
+ setEndTime: (materialId, endTime) => {
+ set((state) => {
+ const material = state.materials.find(m => m.materialId === materialId);
+ if (material) material.endTime = endTime;
+ });
+ },
+
+ setCost: (materialId, cost) => {
+ set((state) => {
+ const material = state.materials.find(m => m.materialId === materialId);
+ if (material) material.cost = cost;
+ });
+ },
+
+ setWeight: (materialId, weight) => {
+ set((state) => {
+ const material = state.materials.find(m => m.materialId === materialId);
+ if (material) material.weight = weight;
+ });
+ },
+
+ getMaterialById: (materialId) => {
+ return get().materials.find(m => m.materialId === materialId);
+ },
+ }))
+);
diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts
index 41a13f6..81feb7f 100644
--- a/app/src/store/simulation/useProductStore.ts
+++ b/app/src/store/simulation/useProductStore.ts
@@ -48,6 +48,11 @@ type ProductsStore = {
updates: Partial
) => void;
+ // Renaming functions
+ renameProduct: (productId: string, newName: string) => void;
+ renameAction: (actionUuid: string, newName: string) => void;
+ renameTrigger: (triggerUuid: string, newName: string) => void;
+
// Helper functions
getProductById: (productId: string) => { productName: string; productId: string; eventsData: EventsSchema[] } | undefined;
};
@@ -331,6 +336,84 @@ export const useProductStore = create()(
});
},
+ // Renaming functions
+ renameProduct: (productId, newName) => {
+ set((state) => {
+ const product = state.products.find(p => p.productId === productId);
+ if (product) {
+ product.productName = newName;
+ }
+ });
+ },
+
+ renameAction: (actionUuid, newName) => {
+ set((state) => {
+ for (const product of state.products) {
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as ConveyorEventSchema).points) {
+ if (point.action && point.action.actionUuid === actionUuid) {
+ point.action.actionName = newName;
+ return;
+ }
+ }
+ } else if ('point' in event) {
+ const point = (event as any).point;
+ if ('action' in point && point.action.actionUuid === actionUuid) {
+ point.action.actionName = newName;
+ return;
+ } else if ('actions' in point) {
+ const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
+ if (action) {
+ action.actionName = newName;
+ return;
+ }
+ }
+ }
+ }
+ }
+ });
+ },
+
+ renameTrigger: (triggerUuid, newName) => {
+ set((state) => {
+ for (const product of state.products) {
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as ConveyorEventSchema).points) {
+ if (point.action && 'triggers' in point.action) {
+ const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
+ if (trigger) {
+ trigger.triggerName = newName;
+ return;
+ }
+ }
+ }
+ } else if ('point' in event) {
+ const point = (event as any).point;
+ if ('action' in point && 'triggers' in point.action) {
+ const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
+ if (trigger) {
+ trigger.triggerName = newName;
+ return;
+ }
+ } else if ('actions' in point) {
+ for (const action of point.actions) {
+ if ('triggers' in action) {
+ const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
+ if (trigger) {
+ trigger.triggerName = newName;
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ });
+ },
+
// Helper functions
getProductById: (productId) => {
return get().products.find(p => p.productId === productId);
diff --git a/app/src/store/simulation/useSimulationStore.ts b/app/src/store/simulation/useSimulationStore.ts
new file mode 100644
index 0000000..9c0fc00
--- /dev/null
+++ b/app/src/store/simulation/useSimulationStore.ts
@@ -0,0 +1,49 @@
+import { create } from 'zustand';
+import { immer } from 'zustand/middleware/immer';
+import * as THREE from 'three';
+
+interface SelectedEventSphereState {
+ selectedEventSphere: THREE.Mesh | null;
+ setSelectedEventSphere: (mesh: THREE.Mesh | null) => void;
+ clearSelectedEventSphere: () => void;
+}
+
+export const useSelectedEventSphere = create()(
+ immer((set) => ({
+ selectedEventSphere: null,
+ setSelectedEventSphere: (mesh) => {
+ set((state) => {
+ state.selectedEventSphere = mesh;
+ });
+ },
+ clearSelectedEventSphere: () => {
+ set((state) => {
+ state.selectedEventSphere = null;
+ });
+ },
+ }))
+);
+
+interface SelectedProductState {
+ selectedProduct: { productId: string; productName: string };
+ setSelectedProduct: (productId: string, productName: string) => void;
+ clearSelectedProduct: () => void;
+}
+
+export const useSelectedProduct = create()(
+ immer((set) => ({
+ selectedProduct: { productId: '', productName: '' },
+ setSelectedProduct: (productId, productName) => {
+ set((state) => {
+ state.selectedProduct.productId = productId;
+ state.selectedProduct.productName = productName;
+ });
+ },
+ clearSelectedProduct: () => {
+ set((state) => {
+ state.selectedProduct.productId = '';
+ state.selectedProduct.productName = '';
+ });
+ },
+ }))
+);
\ No newline at end of file
diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts
index f6b0a0c..1b99456 100644
--- a/app/src/types/simulationTypes.d.ts
+++ b/app/src/types/simulationTypes.d.ts
@@ -168,4 +168,17 @@ interface StorageUnitStatus extends StorageEventSchema {
idleTime: number;
activeTime: number;
currentLoad: number;
-}
\ No newline at end of file
+}
+
+interface MaterialSchema {
+ materialId: string;
+ materialName: string;
+ materialType: string;
+ isActive: boolean;
+ startTime?: string;
+ endTime?: string;
+ cost?: number;
+ weight?: number;
+}
+
+type MaterialsSchema = MaterialSchema[];
\ No newline at end of file