From f46f29b88cf814ed166f32a8b285921b389eff71 Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Fri, 28 Mar 2025 19:10:49 +0530 Subject: [PATCH] Add MQTT URL to environment variables and refactor simulation components --- app/.env | 3 + .../layout/sidebarRight/SideBarRight.tsx | 16 +- .../mechanics/ConveyorMechanics.tsx | 586 +++++++++++++++ .../mechanics/MachineMechanics.tsx | 533 ------------- .../mechanics/VehicleMechanics.tsx | 561 ++++++++++++++ .../modules/builder/agv/navMeshDetails.tsx | 12 +- app/src/modules/builder/agv/pathNavigator.tsx | 2 +- .../modules/builder/agv/polygonGenerator.tsx | 76 +- app/src/modules/collaboration/collabCams.tsx | 2 +- app/src/modules/scene/scene.tsx | 4 - .../simulation/behaviour/behaviour.tsx | 58 +- .../modules/simulation/path/pathConnector.tsx | 312 +++++--- .../modules/simulation/path/pathCreation.tsx | 203 +++-- app/src/modules/simulation/simulation.tsx | 2 +- app/src/modules/simulation/simulationUI.tsx | 698 +++++++++--------- app/src/pages/Project.tsx | 1 - .../factoryBuilder/mqtt/mqttEvents.ts | 5 +- app/src/store/store.ts | 29 +- app/src/types/world/worldTypes.d.ts | 32 + 19 files changed, 1971 insertions(+), 1164 deletions(-) create mode 100644 app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx delete mode 100644 app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx create mode 100644 app/src/components/layout/sidebarRight/mechanics/VehicleMechanics.tsx diff --git a/app/.env b/app/.env index db5ccb6..81bd26d 100644 --- a/app/.env +++ b/app/.env @@ -9,3 +9,6 @@ REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000 # Base URL for the server marketplace API. REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011 + +# Base URL for the server mqtt. +REACT_APP_SERVER_MQTT_URL=185.100.212.76:23457 diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index 0efe99b..3ba5595 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -10,7 +10,7 @@ import { SimulationIcon, } from "../../icons/SimulationIcons"; import useToggleStore from "../../../store/useUIToggleStore"; -import MachineMechanics from "./mechanics/MachineMechanics"; +import ConveyorMechanics from "./mechanics/ConveyorMechanics"; import Visualization from "./visualization/Visualization"; import Analysis from "./analysis/Analysis"; import Simulations from "./simulation/Simulations"; @@ -18,6 +18,7 @@ import { useSelectedActionSphere } from "../../../store/store"; import GlobalProperties from "./properties/GlobalProperties"; import AsstePropertiies from "./properties/AssetProperties"; import ZoneProperties from "./properties/ZoneProperties"; +import VehicleMechanics from "./mechanics/VehicleMechanics"; const SideBarRight: React.FC = () => { const { activeModule } = useModuleStore(); @@ -98,17 +99,24 @@ const SideBarRight: React.FC = () => { {toggleUI && activeModule === "simulation" && ( <> - {subModule === "mechanics" && selectedActionSphere && ( + {subModule === "mechanics" && selectedActionSphere && selectedActionSphere.path.type === "Conveyor" && (
- + +
+
+ )} + {subModule === "mechanics" && selectedActionSphere && selectedActionSphere.path.type === "Vehicle" && ( +
+
+ {/* */}
)} {subModule === "mechanics" && !selectedActionSphere && (
- {/* */} +
)} diff --git a/app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx new file mode 100644 index 0000000..a1f8bf3 --- /dev/null +++ b/app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx @@ -0,0 +1,586 @@ +import React, { useRef, useState, useMemo, useEffect } from "react"; +import { + AddIcon, + InfoIcon, + RemoveIcon, + ResizeHeightIcon, +} from "../../../icons/ExportCommonIcons"; +import RenameInput from "../../../ui/inputs/RenameInput"; +import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; +import LabledDropdown from "../../../ui/inputs/LabledDropdown"; +import RegularDropDown from "../../../ui/inputs/RegularDropDown"; +import { handleResize } from "../../../../functions/handleResizePannel"; +import EyeDropInput from "../../../ui/inputs/EyeDropInput"; +import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from "../../../../store/store"; +import * as THREE from 'three'; +import * as Types from '../../../../types/world/worldTypes'; +import InputToggle from "../../../ui/inputs/InputToggle"; + +const ConveyorMechanics: React.FC = () => { + const { selectedActionSphere } = useSelectedActionSphere(); + const { selectedPath, setSelectedPath } = useSelectedPath(); + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); + + const actionsContainerRef = useRef(null); + const triggersContainerRef = useRef(null); + + const selectedPoint = useMemo(() => { + if (!selectedActionSphere) return null; + return simulationPaths + .filter((path): path is Types.ConveyorEventsSchema => path.type === "Conveyor") + .flatMap((path) => path.points) + .find((point) => point.uuid === selectedActionSphere.point.uuid); + }, [selectedActionSphere, simulationPaths]); + + const handleAddAction = () => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => { + if (path.type === "Conveyor") { + return { + ...path, + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const actionIndex = point.actions.length; + const newAction = { + uuid: THREE.MathUtils.generateUUID(), + name: `Action ${actionIndex + 1}`, + type: 'Inherit', + material: 'Inherit', + delay: 'Inherit', + spawnInterval: 'Inherit', + isUsed: false + }; + + return { ...point, actions: [...point.actions, newAction] }; + } + return point; + }), + }; + } + return path; + }); + + setSimulationPaths(updatedPaths); + }; + + const handleDeleteAction = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleActionSelect = (uuid: string, actionType: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid + ? { + ...action, + type: actionType, + material: actionType === 'Spawn' || actionType === 'Swap' ? 'Inherit' : action.material, + delay: actionType === 'Delay' ? 'Inherit' : action.delay, + spawnInterval: actionType === 'Spawn' ? 'Inherit' : action.spawnInterval + } + : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Update the selected item to reflect changes + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + const updatedAction = updatedPaths + .filter((path): path is Types.ConveyorEventsSchema => path.type === "Conveyor") + .flatMap(path => path.points) + .find(p => p.uuid === selectedActionSphere.point.uuid) + ?.actions.find(a => a.uuid === uuid); + + if (updatedAction) { + setSelectedItem({ + type: "action", + item: updatedAction + }); + } + } + }; + + // Modified handleMaterialSelect to ensure it only applies to relevant action types + const handleMaterialSelect = (uuid: string, material: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid && + (action.type === 'Spawn' || action.type === 'Swap') + ? { ...action, material } + : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Update selected item if it's the current action + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + material + } + }); + } + }; + + const handleDelayChange = (uuid: string, delay: number | string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, delay } : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, spawnInterval } : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleSpeedChange = (speed: number) => { + if (!selectedPath) return; + + const updatedPaths = simulationPaths.map((path) => + path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path + ); + + setSimulationPaths(updatedPaths); + setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); + }; + + const handleAddTrigger = () => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const triggerIndex = point.triggers.length; + const newTrigger = { + uuid: THREE.MathUtils.generateUUID(), + name: `Trigger ${triggerIndex + 1}`, + type: '', + isUsed: false + }; + + return { ...point, triggers: [...point.triggers, newTrigger] }; + } + return point; + }), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleDeleteTrigger = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleTriggerSelect = (uuid: string, triggerType: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + triggers: point.triggers.map((trigger) => + trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + // Update the toggle handlers to immediately update the selected item + const handleActionToggle = (uuid: string) => { + if (!selectedActionSphere) return; + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => ({ + ...action, + isUsed: action.uuid === uuid ? !action.isUsed : false, + })), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Immediately update the selected item if it's the one being toggled + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + isUsed: !selectedItem.item.isUsed + } + }); + } + }; + + // Do the same for trigger toggle + const handleTriggerToggle = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + triggers: point.triggers.map((trigger) => ({ + ...trigger, + isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, + })), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Immediately update the selected item if it's the one being toggled + if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + isUsed: !selectedItem.item.isUsed + } + }); + } + }; + + const [selectedItem, setSelectedItem] = useState<{ type: "action" | "trigger"; item: any; } | null>(null); + + useEffect(() => { + setSelectedItem(null); // Reset selectedItem when selectedActionSphere changes + }, [selectedActionSphere]); + + return ( +
+
+ {selectedActionSphere?.path?.modelName || "point name not found"} +
+ +
+ {!selectedPath && + <> +
+
+
Actions
+
+ Add +
+
+
+
+ {selectedPoint?.actions.map((action) => ( +
+
setSelectedItem({ type: "action", item: action })} + > + +
+
handleDeleteAction(action.uuid)} + > + +
+
+ ))} +
+
handleResize(e, actionsContainerRef)} + > + +
+
+
+
+
+
Triggers
+
+ Add +
+
+
+
+ {selectedPoint?.triggers.map((trigger) => ( +
+
setSelectedItem({ type: "trigger", item: trigger })} + > + +
+
handleDeleteTrigger(trigger.uuid)} + > + +
+
+ ))} +
+
handleResize(e, triggersContainerRef)} + > + +
+
+
+ + } + +
+ {selectedItem && ( + <> +
{selectedItem.item.name}
+ + {selectedItem.type === "action" && ( + <> + handleActionToggle(selectedItem.item.uuid)} + /> + handleActionSelect(selectedItem.item.uuid, option)} + /> + + {/* Only show material dropdown for Spawn/Swap actions */} + {(selectedItem.item.type === 'Spawn' || selectedItem.item.type === 'Swap') && ( + handleMaterialSelect(selectedItem.item.uuid, option)} + /> + )} + + {/* Only show delay input for Delay actions */} + {selectedItem.item.type === 'Delay' && ( + { + const numValue = parseInt(value); + handleDelayChange( + selectedItem.item.uuid, + !value ? 'Inherit' : numValue + ); + }} + /> + )} + + {/* Only show spawn interval for Spawn actions */} + {selectedItem.item.type === 'Spawn' && ( + { + handleSpawnIntervalChange(selectedItem.item.uuid, (value === "") ? "Inherit" : parseInt(value)); + }} + /> + + )} + + )} + + {selectedItem.type === "trigger" && ( + <> + handleTriggerToggle(selectedItem.item.uuid)} + /> + + handleTriggerSelect(selectedItem.item.uuid, option)} + /> + + )} + + )} + + {selectedPath && !selectedItem && ( +
+ handleSpeedChange(parseFloat(value))} + /> +
+ )} +
+
+ + By selecting points, you can create events and triggers. +
+
+
+ ); +}; + +export default ConveyorMechanics; \ No newline at end of file diff --git a/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx deleted file mode 100644 index e1ecfb3..0000000 --- a/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx +++ /dev/null @@ -1,533 +0,0 @@ -import React, { useRef, useState, useMemo, useEffect } from "react"; -import { - AddIcon, - InfoIcon, - RemoveIcon, - ResizeHeightIcon, -} from "../../../icons/ExportCommonIcons"; -import RenameInput from "../../../ui/inputs/RenameInput"; -import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; -import LabledDropdown from "../../../ui/inputs/LabledDropdown"; -import RegularDropDown from "../../../ui/inputs/RegularDropDown"; -import { handleResize } from "../../../../functions/handleResizePannel"; -import EyeDropInput from "../../../ui/inputs/EyeDropInput"; -import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from "../../../../store/store"; -import * as THREE from 'three'; -import InputToggle from "../../../ui/inputs/InputToggle"; - -const MachineMechanics: React.FC = () => { - const { selectedActionSphere } = useSelectedActionSphere(); - const { selectedPath, setSelectedPath } = useSelectedPath(); - const { simulationPaths, setSimulationPaths } = useSimulationPaths(); - - const actionsContainerRef = useRef(null); - const triggersContainerRef = useRef(null); - - const selectedPoint = useMemo(() => { - if (!selectedActionSphere) return null; - return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid); - }, [selectedActionSphere, simulationPaths]); - - const handleAddAction = () => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => { - if (point.uuid === selectedActionSphere.point.uuid) { - const actionIndex = point.actions.length; - const newAction = { - uuid: THREE.MathUtils.generateUUID(), - name: `Action ${actionIndex + 1}`, - type: 'Inherit', - material: 'Inherit', - delay: 'Inherit', - spawnInterval: 'Inherit', - isUsed: false - }; - - return { ...point, actions: [...point.actions, newAction] }; - } - return point; - }), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleDeleteAction = (uuid: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleActionSelect = (uuid: string, actionType: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid - ? { - ...action, - type: actionType, - // Reset dependent fields when type changes - material: actionType === 'Spawn' || actionType === 'Swap' ? 'Inherit' : action.material, - delay: actionType === 'Delay' ? 'Inherit' : action.delay, - spawnInterval: actionType === 'Spawn' ? 'Inherit' : action.spawnInterval - } - : action - ), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - - // Update the selected item to reflect changes - if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { - const updatedAction = updatedPaths - .flatMap(path => path.points) - .find(p => p.uuid === selectedActionSphere.point.uuid) - ?.actions.find(a => a.uuid === uuid); - - if (updatedAction) { - setSelectedItem({ - type: "action", - item: updatedAction - }); - } - } - }; - - // Modified handleMaterialSelect to ensure it only applies to relevant action types - const handleMaterialSelect = (uuid: string, material: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid && - (action.type === 'Spawn' || action.type === 'Swap') - ? { ...action, material } - : action - ), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - - // Update selected item if it's the current action - if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { - setSelectedItem({ - ...selectedItem, - item: { - ...selectedItem.item, - material - } - }); - } - }; - - const handleDelayChange = (uuid: string, delay: number | string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, delay } : action - ), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, spawnInterval } : action - ), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleSpeedChange = (speed: number) => { - if (!selectedPath) return; - - const updatedPaths = simulationPaths.map((path) => - path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path - ); - - setSimulationPaths(updatedPaths); - setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); - }; - - const handleAddTrigger = () => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => { - if (point.uuid === selectedActionSphere.point.uuid) { - const triggerIndex = point.triggers.length; - const newTrigger = { - uuid: THREE.MathUtils.generateUUID(), - name: `Trigger ${triggerIndex + 1}`, - type: '', - isUsed: false - }; - - return { ...point, triggers: [...point.triggers, newTrigger] }; - } - return point; - }), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleDeleteTrigger = (uuid: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - const handleTriggerSelect = (uuid: string, triggerType: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - triggers: point.triggers.map((trigger) => - trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger - ), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - }; - - // Update the toggle handlers to immediately update the selected item - const handleActionToggle = (uuid: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => ({ - ...action, - isUsed: action.uuid === uuid ? !action.isUsed : false, - })), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - - // Immediately update the selected item if it's the one being toggled - if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { - setSelectedItem({ - ...selectedItem, - item: { - ...selectedItem.item, - isUsed: !selectedItem.item.isUsed - } - }); - } - }; - - // Do the same for trigger toggle - const handleTriggerToggle = (uuid: string) => { - if (!selectedActionSphere) return; - - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - triggers: point.triggers.map((trigger) => ({ - ...trigger, - isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, - })), - } - : point - ), - })); - - setSimulationPaths(updatedPaths); - - // Immediately update the selected item if it's the one being toggled - if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) { - setSelectedItem({ - ...selectedItem, - item: { - ...selectedItem.item, - isUsed: !selectedItem.item.isUsed - } - }); - } - }; - - const [selectedItem, setSelectedItem] = useState<{ type: "action" | "trigger"; item: any; } | null>(null); - - useEffect(() => { - setSelectedItem(null); // Reset selectedItem when selectedActionSphere changes - }, [selectedActionSphere]); - - return ( -
-
- {selectedActionSphere?.path?.modelName || "point name not found"} -
- -
-
-
-
Actions
-
- Add -
-
-
-
- {selectedPoint?.actions.map((action) => ( -
-
setSelectedItem({ type: "action", item: action })} - > - -
-
handleDeleteAction(action.uuid)} - > - -
-
- ))} -
-
handleResize(e, actionsContainerRef)} - > - -
-
-
-
-
-
Triggers
-
- Add -
-
-
-
- {selectedPoint?.triggers.map((trigger) => ( -
-
setSelectedItem({ type: "trigger", item: trigger })} - > - -
-
handleDeleteTrigger(trigger.uuid)} - > - -
-
- ))} -
-
handleResize(e, triggersContainerRef)} - > - -
-
-
-
- {selectedItem && ( - <> -
{selectedItem.item.name}
- - {selectedItem.type === "action" && ( - <> - handleActionToggle(selectedItem.item.uuid)} - /> - handleActionSelect(selectedItem.item.uuid, option)} - /> - - {/* Only show material dropdown for Spawn/Swap actions */} - {(selectedItem.item.type === 'Spawn' || selectedItem.item.type === 'Swap') && ( - handleMaterialSelect(selectedItem.item.uuid, option)} - /> - )} - - {/* Only show delay input for Delay actions */} - {selectedItem.item.type === 'Delay' && ( - { - const numValue = parseInt(value); - handleDelayChange( - selectedItem.item.uuid, - !value ? 'Inherit' : numValue - ); - }} - /> - )} - - {/* Only show spawn interval for Spawn actions */} - {selectedItem.item.type === 'Spawn' && ( - { - handleSpawnIntervalChange(selectedItem.item.uuid, (value === "") ? "Inherit" : parseInt(value)); - }} - /> - - )} - - )} - - {selectedItem.type === "trigger" && ( - <> - handleTriggerToggle(selectedItem.item.uuid)} - /> - - handleTriggerSelect(selectedItem.item.uuid, option)} - /> - - )} - - )} - - {selectedPath && !selectedItem && ( -
- handleSpeedChange(parseFloat(value))} - /> -
- )} -
-
- - By selecting points, you can create events and triggers. -
-
-
- ); -}; - -export default MachineMechanics; \ No newline at end of file diff --git a/app/src/components/layout/sidebarRight/mechanics/VehicleMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/VehicleMechanics.tsx new file mode 100644 index 0000000..7d3ffb0 --- /dev/null +++ b/app/src/components/layout/sidebarRight/mechanics/VehicleMechanics.tsx @@ -0,0 +1,561 @@ +import React, { useRef, useState, useMemo, useEffect } from "react"; +import { + AddIcon, + InfoIcon, + RemoveIcon, + ResizeHeightIcon, +} from "../../../icons/ExportCommonIcons"; +import RenameInput from "../../../ui/inputs/RenameInput"; +import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; +import LabledDropdown from "../../../ui/inputs/LabledDropdown"; +import RegularDropDown from "../../../ui/inputs/RegularDropDown"; +import { handleResize } from "../../../../functions/handleResizePannel"; +import EyeDropInput from "../../../ui/inputs/EyeDropInput"; +import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from "../../../../store/store"; +import * as THREE from 'three'; +import * as Types from '../../../../types/world/worldTypes'; +import InputToggle from "../../../ui/inputs/InputToggle"; + +const VehicleMechanics: React.FC = () => { + const { selectedActionSphere } = useSelectedActionSphere(); + const { selectedPath, setSelectedPath } = useSelectedPath(); + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); + + const actionsContainerRef = useRef(null); + const triggersContainerRef = useRef(null); + + const selectedPoint = useMemo(() => { + if (!selectedActionSphere) return null; + return simulationPaths + .filter((path): path is Types.ConveyorEventsSchema => path.type === "Conveyor") + .flatMap((path) => path.points) + .find((point) => point.uuid === selectedActionSphere.point.uuid); + }, [selectedActionSphere, simulationPaths]); + + const handleAddAction = () => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => { + if (path.type === "Conveyor") { + return { + ...path, + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const actionIndex = point.actions.length; + const newAction = { + uuid: THREE.MathUtils.generateUUID(), + name: `Action ${actionIndex + 1}`, + type: 'Inherit', + material: 'Inherit', + delay: 'Inherit', + spawnInterval: 'Inherit', + isUsed: false + }; + + return { ...point, actions: [...point.actions, newAction] }; + } + return point; + }), + }; + } + return path; + }); + + setSimulationPaths(updatedPaths); + }; + + const handleDeleteAction = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleActionSelect = (uuid: string, actionType: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid + ? { + ...action, + type: actionType, + material: actionType === 'Spawn' || actionType === 'Swap' ? 'Inherit' : action.material, + delay: actionType === 'Delay' ? 'Inherit' : action.delay, + spawnInterval: actionType === 'Spawn' ? 'Inherit' : action.spawnInterval + } + : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Update the selected item to reflect changes + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + const updatedAction = updatedPaths + .filter((path): path is Types.ConveyorEventsSchema => path.type === "Conveyor") + .flatMap(path => path.points) + .find(p => p.uuid === selectedActionSphere.point.uuid) + ?.actions.find(a => a.uuid === uuid); + + if (updatedAction) { + setSelectedItem({ + type: "action", + item: updatedAction + }); + } + } + }; + + // Modified handleMaterialSelect to ensure it only applies to relevant action types + const handleMaterialSelect = (uuid: string, material: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid && + (action.type === 'Spawn' || action.type === 'Swap') + ? { ...action, material } + : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Update selected item if it's the current action + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + material + } + }); + } + }; + + const handleDelayChange = (uuid: string, delay: number | string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, delay } : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => + action.uuid === uuid ? { ...action, spawnInterval } : action + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleSpeedChange = (speed: number) => { + if (!selectedPath) return; + + const updatedPaths = simulationPaths.map((path) => + path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path + ); + + setSimulationPaths(updatedPaths); + setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); + }; + + const handleAddTrigger = () => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const triggerIndex = point.triggers.length; + const newTrigger = { + uuid: THREE.MathUtils.generateUUID(), + name: `Trigger ${triggerIndex + 1}`, + type: '', + isUsed: false + }; + + return { ...point, triggers: [...point.triggers, newTrigger] }; + } + return point; + }), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleDeleteTrigger = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + const handleTriggerSelect = (uuid: string, triggerType: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + triggers: point.triggers.map((trigger) => + trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger + ), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + }; + + // Update the toggle handlers to immediately update the selected item + const handleActionToggle = (uuid: string) => { + if (!selectedActionSphere) return; + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + actions: point.actions.map((action) => ({ + ...action, + isUsed: action.uuid === uuid ? !action.isUsed : false, + })), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Immediately update the selected item if it's the one being toggled + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + isUsed: !selectedItem.item.isUsed + } + }); + } + }; + + // Do the same for trigger toggle + const handleTriggerToggle = (uuid: string) => { + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => + path.type === "Conveyor" + ? { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + triggers: point.triggers.map((trigger) => ({ + ...trigger, + isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, + })), + } + : point + ), + } + : path + ); + + setSimulationPaths(updatedPaths); + + // Immediately update the selected item if it's the one being toggled + if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + isUsed: !selectedItem.item.isUsed + } + }); + } + }; + + const [selectedItem, setSelectedItem] = useState<{ type: "action" | "trigger"; item: any; } | null>(null); + + useEffect(() => { + setSelectedItem(null); // Reset selectedItem when selectedActionSphere changes + }, [selectedActionSphere]); + + return ( +
+
+ {selectedActionSphere?.path?.modelName || "point name not found"} +
+ +
+
+
+
Actions
+
+ Add +
+
+
+
+ <> + {console.log(selectedPoint)} + +
+
handleResize(e, actionsContainerRef)} + > + +
+
+
+
+
+
Triggers
+
+ Add +
+
+
+
+ {selectedPoint?.triggers.map((trigger) => ( +
+
setSelectedItem({ type: "trigger", item: trigger })} + > + +
+
handleDeleteTrigger(trigger.uuid)} + > + +
+
+ ))} +
+
handleResize(e, triggersContainerRef)} + > + +
+
+
+
+ {selectedItem && ( + <> +
{selectedItem.item.name}
+ + {selectedItem.type === "action" && ( + <> + handleActionToggle(selectedItem.item.uuid)} + /> + handleActionSelect(selectedItem.item.uuid, option)} + /> + + {/* Only show material dropdown for Spawn/Swap actions */} + {(selectedItem.item.type === 'Spawn' || selectedItem.item.type === 'Swap') && ( + handleMaterialSelect(selectedItem.item.uuid, option)} + /> + )} + + {/* Only show delay input for Delay actions */} + {selectedItem.item.type === 'Delay' && ( + { + const numValue = parseInt(value); + handleDelayChange( + selectedItem.item.uuid, + !value ? 'Inherit' : numValue + ); + }} + /> + )} + + {/* Only show spawn interval for Spawn actions */} + {selectedItem.item.type === 'Spawn' && ( + { + handleSpawnIntervalChange(selectedItem.item.uuid, (value === "") ? "Inherit" : parseInt(value)); + }} + /> + + )} + + )} + + {selectedItem.type === "trigger" && ( + <> + handleTriggerToggle(selectedItem.item.uuid)} + /> + + handleTriggerSelect(selectedItem.item.uuid, option)} + /> + + )} + + )} + + {selectedPath && !selectedItem && ( +
+ handleSpeedChange(parseFloat(value))} + /> +
+ )} +
+
+ + By selecting points, you can create events and triggers. +
+
+
+ ); +}; + +export default VehicleMechanics; \ No newline at end of file diff --git a/app/src/modules/builder/agv/navMeshDetails.tsx b/app/src/modules/builder/agv/navMeshDetails.tsx index c941011..571be5a 100644 --- a/app/src/modules/builder/agv/navMeshDetails.tsx +++ b/app/src/modules/builder/agv/navMeshDetails.tsx @@ -34,15 +34,11 @@ export default function NavMeshDetails({ const [positions, indices] = getPositionsAndIndices(meshes); - const cs = 0.5; + const cs = 0.25; const ch = 0.5; - const walkableRadius = 0.89; + const walkableRadius = 0.5; - const { success, navMesh } = generateSoloNavMesh(positions, indices, { - cs, - ch, - walkableRadius: Math.round(walkableRadius / ch), - }); + const { success, navMesh } = generateSoloNavMesh(positions, indices, { cs, ch, walkableRadius: Math.round(walkableRadius / ch), }); if (!success || !navMesh) { return; @@ -53,7 +49,7 @@ export default function NavMeshDetails({ const debugDrawer = new DebugDrawer(); debugDrawer.drawNavMesh(navMesh); // scene.add(debugDrawer); - } catch (error) {} + } catch (error) { } }; initializeNavigation(); diff --git a/app/src/modules/builder/agv/pathNavigator.tsx b/app/src/modules/builder/agv/pathNavigator.tsx index 4193fb7..25d3af0 100644 --- a/app/src/modules/builder/agv/pathNavigator.tsx +++ b/app/src/modules/builder/agv/pathNavigator.tsx @@ -86,7 +86,7 @@ export default function PathNavigator({ return ( <> - {path.length > 0 && } + {/* {path.length > 0 && } */} {path.length > 0 && ( 0 ? path[0] : [0, 0.1, 0]}> diff --git a/app/src/modules/builder/agv/polygonGenerator.tsx b/app/src/modules/builder/agv/polygonGenerator.tsx index 1eca588..8682371 100644 --- a/app/src/modules/builder/agv/polygonGenerator.tsx +++ b/app/src/modules/builder/agv/polygonGenerator.tsx @@ -43,66 +43,46 @@ export default function PolygonGenerator({ const lineFeatures = result?.map((line: any) => turf.lineString(line.map((p: any) => p?.position)) - ); + ); const polygons = turf.polygonize(turf.featureCollection(lineFeatures)); renderWallGeometry(wallPoints); - let union: any = []; + if (polygons.features.length > 1) { + polygons.features.forEach((feature) => { + if (feature.geometry.type === "Polygon") { - polygons.features.forEach((feature) => { - union.push(feature); - }); + const shape = new THREE.Shape(); + const coords = feature.geometry.coordinates[0]; - if (union.length > 1) { - const unionResult = turf.union(turf.featureCollection(union)); + shape.moveTo(coords[0][0], coords[0][1]); - if (unionResult?.geometry.type === "MultiPolygon") { - unionResult.geometry.coordinates.forEach((poly) => { - const coordinates = poly[0].map(([x, z]) => { - return new THREE.Vector3(x, 0, z); - }); - renderBoxGeometry(coordinates); - }); - } else if (unionResult?.geometry.type === "Polygon") { - const coordinates = unionResult.geometry.coordinates[0].map( - ([x, z]) => { - return new THREE.Vector3(x, 0, z); + for (let i = 1; i < coords.length; i++) { + shape.lineTo(coords[i][0], coords[i][1]); } - ); - renderBoxGeometry(coordinates); - } - } else if (union.length === 1) { - const coordinates = union[0].geometry.coordinates[0].map( - ([x, z]: [number, number]) => { - return new THREE.Vector3(x, 0, z); + shape.lineTo(coords[0][0], coords[0][1]); + + const extrudeSettings = { + depth: 5, + bevelEnabled: false, + }; + + const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); + + const material = new THREE.MeshBasicMaterial({ color: "blue", transparent: true, opacity: 0.5 }); + const mesh = new THREE.Mesh(geometry, material); + mesh.rotateX(Math.PI / 2); + mesh.name = "agv-collider"; + mesh.position.y = 5; + + mesh.receiveShadow = true; + groupRef.current?.add(mesh); } - ); - // setRooms((prevRooms) => [...prevRooms, coordinates]); + }); + } }, [lines.current]); - const renderBoxGeometry = (coordinates: THREE.Vector3[]) => { - const minX = Math.min(...coordinates.map((p) => p.x)); - const maxX = Math.max(...coordinates.map((p) => p.x)); - const minZ = Math.min(...coordinates.map((p) => p.z)); - const maxZ = Math.max(...coordinates.map((p) => p.z)); - - const width = maxX - minX; - const depth = maxZ - minZ; - const height = 3; - - const geometry = new THREE.BoxGeometry(width, height, depth); - const material = new THREE.MeshBasicMaterial({ - color: "#ff66cc", - visible: false, - }); - - const mesh = new THREE.Mesh(geometry, material); - mesh.position.set((minX + maxX) / 2, height / 2, (minZ + maxZ) / 2); - groupRef.current?.add(mesh); - }; - const renderWallGeometry = (walls: THREE.Vector3[][]) => { walls.forEach((wall) => { if (wall.length < 2) return; diff --git a/app/src/modules/collaboration/collabCams.tsx b/app/src/modules/collaboration/collabCams.tsx index da20b34..9d5475e 100644 --- a/app/src/modules/collaboration/collabCams.tsx +++ b/app/src/modules/collaboration/collabCams.tsx @@ -78,7 +78,7 @@ const CamModelsGroup = () => { socket.off('userDisConnectRespones'); socket.off('cameraUpdateResponse'); }; - }, [socket]); + }, [socket, activeUsers]); useFrame(() => { if (!groupRef.current) return; diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index 8ceeb2e..9b13a54 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -49,7 +49,6 @@ export default function Scene() { - {/* */} @@ -58,9 +57,6 @@ export default function Scene() { - - - ); } diff --git a/app/src/modules/simulation/behaviour/behaviour.tsx b/app/src/modules/simulation/behaviour/behaviour.tsx index d7a08af..2854172 100644 --- a/app/src/modules/simulation/behaviour/behaviour.tsx +++ b/app/src/modules/simulation/behaviour/behaviour.tsx @@ -1,43 +1,29 @@ -import { useFloorItems } from '../../../store/store'; +import { useFloorItems, useSimulationPaths } from '../../../store/store'; import * as THREE from 'three'; import * as Types from '../../../types/world/worldTypes'; import { useEffect } from 'react'; -interface Path { - modeluuid: string; - modelName: string; - points: { - uuid: string; - position: [number, number, number]; - rotation: [number, number, number]; - actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; - triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; - connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] }; - }[]; - pathPosition: [number, number, number]; - pathRotation: [number, number, number]; - speed: number; -} - -function Behaviour({ setSimulationPaths }: { setSimulationPaths: any }) { +function Behaviour() { + const { setSimulationPaths } = useSimulationPaths(); const { floorItems } = useFloorItems(); useEffect(() => { - const newPaths: Path[] = []; + const newPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[] = []; floorItems.forEach((item: Types.FloorItemType) => { - if (item.modelfileID === "6633215057b31fe671145959") { - const point1Position = new THREE.Vector3(0, 1.25, 3.3); - const middlePointPosition = new THREE.Vector3(0, 1.25, 0); - const point2Position = new THREE.Vector3(0, 1.25, -3.3); + if (item.modelfileID === "672a090f80d91ac979f4d0bd") { + const point1Position = new THREE.Vector3(0, 0.85, 2.2); + const middlePointPosition = new THREE.Vector3(0, 0.85, 0); + const point2Position = new THREE.Vector3(0, 0.85, -2.2); const point1UUID = THREE.MathUtils.generateUUID(); const middlePointUUID = THREE.MathUtils.generateUUID(); const point2UUID = THREE.MathUtils.generateUUID(); - const newPath: Path = { + const newPath: Types.ConveyorEventsSchema = { modeluuid: item.modeluuid, modelName: item.modelname, + type: 'Conveyor', points: [ { uuid: point1UUID, @@ -64,12 +50,32 @@ function Behaviour({ setSimulationPaths }: { setSimulationPaths: any }) { connections: { source: { pathUUID: item.modeluuid, pointUUID: point2UUID }, targets: [] }, }, ], - pathPosition: [...item.position], - pathRotation: [item.rotation.x, item.rotation.y, item.rotation.z], + assetPosition: [...item.position], + assetRotation: [item.rotation.x, item.rotation.y, item.rotation.z], speed: 1, }; newPaths.push(newPath); + } else if (item.modelfileID === "67e3da19c2e8f37134526e6a") { + const pointUUID = THREE.MathUtils.generateUUID(); + const pointPosition = new THREE.Vector3(0, 1.3, 0); + + const newVehiclePath: Types.VehicleEventsSchema = { + modeluuid: item.modeluuid, + modelName: item.modelname, + type: 'Vehicle', + point: { + uuid: pointUUID, + position: [pointPosition.x, pointPosition.y, pointPosition.z], + actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Start', start: THREE.MathUtils.generateUUID(), hitCount: 1, end: THREE.MathUtils.generateUUID(), buffer: 0, isUsed: false }], + triggers: [], + connections: { source: { pathUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] }, + }, + assetPosition: [...item.position], + speed: 2, + }; + + newPaths.push(newVehiclePath); } }); diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx index 93172b7..8df718c 100644 --- a/app/src/modules/simulation/path/pathConnector.tsx +++ b/app/src/modules/simulation/path/pathConnector.tsx @@ -1,6 +1,7 @@ import { useFrame, useThree } from '@react-three/fiber'; import React, { useEffect, useState } from 'react'; import * as THREE from 'three'; +import * as Types from '../../../types/world/worldTypes'; import { QuadraticBezierLine } from '@react-three/drei'; import { useIsConnecting, useSimulationPaths } from '../../../store/store'; import useModuleStore from '../../../store/useModuleStore'; @@ -27,61 +28,113 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec toPointUUID: string ) => { const updatedPaths = simulationPaths.map(path => { - if (path.modeluuid === fromPathUUID) { - return { - ...path, - points: path.points.map(point => { - if (point.uuid === fromPointUUID) { - const newTarget = { - pathUUID: toPathUUID, - pointUUID: toPointUUID - }; - const existingTargets = point.connections.targets || []; - - if (!existingTargets.some(target => - target.pathUUID === newTarget.pathUUID && - target.pointUUID === newTarget.pointUUID - )) { - return { - ...point, - connections: { - ...point.connections, - targets: [...existingTargets, newTarget] - } + if (path.type === 'Conveyor') { + if (path.modeluuid === fromPathUUID) { + return { + ...path, + points: path.points.map(point => { + if (point.uuid === fromPointUUID) { + const newTarget = { + pathUUID: toPathUUID, + pointUUID: toPointUUID }; + const existingTargets = point.connections.targets || []; + + if (!existingTargets.some(target => + target.pathUUID === newTarget.pathUUID && + target.pointUUID === newTarget.pointUUID + )) { + return { + ...point, + connections: { + ...point.connections, + targets: [...existingTargets, newTarget] + } + }; + } } - } - return point; - }) - }; + return point; + }) + }; + } + else if (path.modeluuid === toPathUUID) { + return { + ...path, + points: path.points.map(point => { + if (point.uuid === toPointUUID) { + const reverseTarget = { + pathUUID: fromPathUUID, + pointUUID: fromPointUUID + }; + const existingTargets = point.connections.targets || []; + + if (!existingTargets.some(target => + target.pathUUID === reverseTarget.pathUUID && + target.pointUUID === reverseTarget.pointUUID + )) { + return { + ...point, + connections: { + ...point.connections, + targets: [...existingTargets, reverseTarget] + } + }; + } + } + return point; + }) + }; + } } - else if (path.modeluuid === toPathUUID) { - return { - ...path, - points: path.points.map(point => { - if (point.uuid === toPointUUID) { - const reverseTarget = { - pathUUID: fromPathUUID, - pointUUID: fromPointUUID - }; - const existingTargets = point.connections.targets || []; + else if (path.type === 'Vehicle') { + // Handle outgoing connections from Vehicle + if (path.modeluuid === fromPathUUID && path.point.uuid === fromPointUUID) { + const newTarget = { + pathUUID: toPathUUID, + pointUUID: toPointUUID + }; + const existingTargets = path.point.connections.targets || []; - if (!existingTargets.some(target => - target.pathUUID === reverseTarget.pathUUID && - target.pointUUID === reverseTarget.pointUUID - )) { - return { - ...point, - connections: { - ...point.connections, - targets: [...existingTargets, reverseTarget] - } - }; + if (!existingTargets.some(target => + target.pathUUID === newTarget.pathUUID && + target.pointUUID === newTarget.pointUUID + )) { + return { + ...path, + point: { + ...path.point, + connections: { + ...path.point.connections, + targets: [...existingTargets, newTarget] + } } - } - return point; - }) - }; + }; + } + } + // Handle incoming connections to Vehicle + else if (path.modeluuid === toPathUUID && path.point.uuid === toPointUUID) { + const reverseTarget = { + pathUUID: fromPathUUID, + pointUUID: fromPointUUID + }; + const existingTargets = path.point.connections.targets || []; + + if (!existingTargets.some(target => + target.pathUUID === reverseTarget.pathUUID && + target.pointUUID === reverseTarget.pointUUID + )) { + return { + ...path, + point: { + ...path.point, + connections: { + ...path.point.connections, + targets: [...existingTargets, reverseTarget] + } + } + }; + } + } } return path; }); @@ -126,25 +179,43 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec if (intersects.length > 0) { const intersected = intersects[0].object; - if (intersected.name.includes("action-sphere")) { + if (intersected.name.includes("events-sphere")) { const pathUUID = intersected.userData.path.modeluuid; const sphereUUID = intersected.uuid; const worldPosition = new THREE.Vector3(); intersected.getWorldPosition(worldPosition); - const isStartOrEnd = intersected.userData.path.points.length > 0 && ( - sphereUUID === intersected.userData.path.points[0].uuid || - sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid - ); + let isStartOrEnd = false; + + if (intersected.userData.path.points) { + isStartOrEnd = intersected.userData.path.points.length > 0 && ( + sphereUUID === intersected.userData.path.points[0].uuid || + sphereUUID === intersected.userData.path.points[intersected.userData.path.points.length - 1].uuid + ); + } else if (intersected.userData.path.point) { + isStartOrEnd = sphereUUID === intersected.userData.path.point.uuid; + } if (pathUUID) { - // Check if sphere is already connected - const isAlreadyConnected = simulationPaths.some(path => - path.points.some(point => - point.uuid === sphereUUID && - point.connections.targets.length > 0 - ) - ); + const firstPath = simulationPaths.find(p => p.modeluuid === firstSelected?.pathUUID); + const secondPath = simulationPaths.find(p => p.modeluuid === pathUUID); + + if (firstPath && secondPath && firstPath.type === 'Vehicle' && secondPath.type === 'Vehicle') { + console.log("Cannot connect two vehicle paths together"); + return; + } + const isAlreadyConnected = simulationPaths.some(path => { + if (path.type === 'Conveyor') { + return path.points.some(point => + point.uuid === sphereUUID && + point.connections.targets.length > 0 + ); + } else if (path.type === 'Vehicle') { + return path.point.uuid === sphereUUID && + path.point.connections.targets.length > 0; + } + return false; + }); if (isAlreadyConnected) { console.log("Sphere is already connected. Ignoring."); @@ -211,6 +282,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec 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.userData.isPathObject && !(intersect.object.type === "GridHelper") @@ -229,7 +301,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) => - obj.object.name.includes("action-sphere") + obj.object.name.includes("events-sphere") ); if (sphereIntersects.length > 0) { @@ -237,27 +309,45 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec const sphereUUID = sphere.uuid; const spherePosition = new THREE.Vector3(); sphere.getWorldPosition(spherePosition); - const pathUUID = sphere.userData.path.modeluuid; + const pathData = sphere.userData.path; + const pathUUID = pathData.modeluuid; - const isStartOrEnd = sphere.userData.path.points.length > 0 && ( - sphereUUID === sphere.userData.path.points[0].uuid || - sphereUUID === sphere.userData.path.points[sphere.userData.path.points.length - 1].uuid - ); + const firstPath = simulationPaths.find(p => p.modeluuid === firstSelected.pathUUID); + const secondPath = simulationPaths.find(p => p.modeluuid === pathUUID); + const isVehicleToVehicle = firstPath?.type === 'Vehicle' && secondPath?.type === 'Vehicle'; - const isAlreadyConnected = simulationPaths.some(path => - path.points.some(point => - point.uuid === sphereUUID && - point.connections.targets.length > 0 - ) - ); + const isConnectable = (pathData.type === 'Vehicle' || + (pathData.points.length > 0 && ( + sphereUUID === pathData.points[0].uuid || + sphereUUID === pathData.points[pathData.points.length - 1].uuid + ))) && !isVehicleToVehicle; + + const isAlreadyConnected = simulationPaths.some(path => { + if (path.type === 'Conveyor') { + return path.points.some(point => + point.uuid === sphereUUID && + point.connections.targets.length > 0 + ); + } else if (path.type === 'Vehicle') { + return path.point.uuid === sphereUUID && + path.point.connections.targets.length > 0; + } + return false; + }); if ( !isAlreadyConnected && + !isVehicleToVehicle && firstSelected.sphereUUID !== sphereUUID && firstSelected.pathUUID !== pathUUID && - (firstSelected.isCorner || isStartOrEnd) + (firstSelected.isCorner || isConnectable) ) { - snappedSphere = { sphereUUID, position: spherePosition, pathUUID, isCorner: isStartOrEnd }; + snappedSphere = { + sphereUUID, + position: spherePosition, + pathUUID, + isCorner: isConnectable + }; } else { isInvalidConnection = true; } @@ -281,8 +371,13 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec end: point, mid: midPoint, }); + console.log({ + start: firstSelected.position, + end: point, + mid: midPoint, + }); - setIsConnecting(true); + // setIsConnecting(true); if (sphereIntersects.length > 0) { setHelperLineColor(isInvalidConnection ? 'red' : '#6cf542'); @@ -299,13 +394,53 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } }); - // Render connections from simulationPaths return ( <> - {simulationPaths.flatMap(path => - path.points.flatMap(point => - point.connections.targets.map((target, index) => { - const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid); + {simulationPaths.flatMap(path => { + if (path.type === 'Conveyor') { + return path.points.flatMap(point => + point.connections.targets.map((target, index) => { + const targetPath = simulationPaths.find(p => p.modeluuid === target.pathUUID); + if (targetPath?.type === 'Vehicle') return null; + + const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', point.uuid); + const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID); + + if (fromSphere && toSphere) { + const fromWorldPosition = new THREE.Vector3(); + const toWorldPosition = new THREE.Vector3(); + fromSphere.getWorldPosition(fromWorldPosition); + toSphere.getWorldPosition(toWorldPosition); + + const distance = fromWorldPosition.distanceTo(toWorldPosition); + const heightFactor = Math.max(0.5, distance * 0.2); + + const midPoint = new THREE.Vector3( + (fromWorldPosition.x + toWorldPosition.x) / 2, + Math.max(fromWorldPosition.y, toWorldPosition.y) + heightFactor, + (fromWorldPosition.z + toWorldPosition.z) / 2 + ); + + return ( + + ); + } + return null; + }) + ); + } else if (path.type === 'Vehicle') { + return path.point.connections.targets.map((target, index) => { + const fromSphere = pathsGroupRef.current?.getObjectByProperty('uuid', path.point.uuid); const toSphere = pathsGroupRef.current?.getObjectByProperty('uuid', target.pointUUID); if (fromSphere && toSphere) { @@ -325,22 +460,23 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec return ( ); } return null; - }) - ) - )} + }); + } + return []; + })} {currentLine && ( { if (!selectedActionSphere) return; - const updatedPaths: Path[] = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - position: [ - selectedActionSphere.point.position.x, - selectedActionSphere.point.position.y, - selectedActionSphere.point.position.z, - ], - rotation: [ - selectedActionSphere.point.rotation.x, - selectedActionSphere.point.rotation.y, - selectedActionSphere.point.rotation.z, - ] - } - : point - ), - })); + const updatedPaths = simulationPaths.map((path) => { + if (path.type === "Conveyor") { + return { + ...path, + points: path.points.map((point) => + point.uuid === selectedActionSphere.point.uuid + ? { + ...point, + position: [ + selectedActionSphere.point.position.x, + selectedActionSphere.point.position.y, + selectedActionSphere.point.position.z, + ], + rotation: [ + selectedActionSphere.point.rotation.x, + selectedActionSphere.point.rotation.y, + selectedActionSphere.point.rotation.z, + ] + } + : point + ), + }; + } + return path; + }) as ConveyorEventsSchema[]; setSimulationPaths(updatedPaths); }; return ( - + {simulationPaths.map((path) => { - const points = path.points.map(point => new THREE.Vector3(...point.position)); + if (path.type === 'Conveyor') { + const points = path.points.map(point => new THREE.Vector3(...point.position)); - return ( - (groupRefs.current[path.modeluuid] = el!)} - position={path.pathPosition} - rotation={path.pathRotation} - onClick={(e) => { - if (isConnecting) return; - e.stopPropagation(); - setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); - setSelectedActionSphere(null); - setTransformMode(null); - setSubModule('mechanics'); - }} - onPointerMissed={() => { - setSelectedPath(null); - setSubModule('properties'); - }} - > - {path.points.map((point, index) => ( + return ( + (groupRefs.current[path.modeluuid] = el!)} + position={path.assetPosition} + rotation={path.assetRotation} + onClick={(e) => { + if (isConnecting) return; + e.stopPropagation(); + setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); + setSelectedActionSphere(null); + setTransformMode(null); + setSubModule('mechanics'); + }} + onPointerMissed={() => { + setSelectedPath(null); + setSubModule('properties'); + }} + > + {path.points.map((point, index) => ( + (sphereRefs.current[point.uuid] = el!)} + onClick={(e) => { + if (isConnecting) return; + e.stopPropagation(); + setSelectedActionSphere({ + path, + point: sphereRefs.current[point.uuid] + }); + setSubModule('mechanics'); + setSelectedPath(null); + }} + userData={{ point, path }} + onPointerMissed={() => { + setSubModule('properties'); + setSelectedActionSphere(null); + }} + > + + + ))} + + {points.slice(0, -1).map((point, index) => { + const nextPoint = points[index + 1]; + const segmentCurve = new THREE.CatmullRomCurve3([point, nextPoint]); + const tubeGeometry = new THREE.TubeGeometry(segmentCurve, 20, 0.1, 16, false); + + return ( + + + + ); + })} + + ); + } else if (path.type === 'Vehicle') { + return ( + (groupRefs.current[path.modeluuid] = el!)} + position={path.assetPosition} + onClick={(e) => { + if (isConnecting) return; + e.stopPropagation(); + setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); + setSelectedActionSphere(null); + setTransformMode(null); + setSubModule('mechanics'); + }} + onPointerMissed={() => { + setSelectedPath(null); + setSubModule('properties'); + }} + > (sphereRefs.current[point.uuid] = el!)} + name='events-sphere' + ref={el => (sphereRefs.current[path.point.uuid] = el!)} onClick={(e) => { if (isConnecting) return; e.stopPropagation(); setSelectedActionSphere({ path, - point: sphereRefs.current[point.uuid] + point: sphereRefs.current[path.point.uuid] }); setSubModule('mechanics'); setSelectedPath(null); }} - userData={{ point, path }} + userData={{ point: path.point, path }} onPointerMissed={() => { setSubModule('properties'); - setSelectedActionSphere(null) + setSelectedActionSphere(null); }} > - + - ))} - - {points.slice(0, -1).map((point, index) => { - const nextPoint = points[index + 1]; - const segmentCurve = new THREE.CatmullRomCurve3([point, nextPoint]); - const tubeGeometry = new THREE.TubeGeometry(segmentCurve, 20, 0.1, 16, false); - - return ( - - - - ); - })} - - ); + + ); + } + return null; })} {selectedActionSphere && transformMode && ( @@ -163,7 +220,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject ref={transformRef} object={selectedActionSphere.point} mode={transformMode} - onObjectChange={updateSimulationPaths} + onMouseUp={updateSimulationPaths} /> )} diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx index fab1042..10934fb 100644 --- a/app/src/modules/simulation/simulation.tsx +++ b/app/src/modules/simulation/simulation.tsx @@ -31,7 +31,7 @@ function Simulation() { return ( <> - + {activeModule === 'simulation' && ( <> diff --git a/app/src/modules/simulation/simulationUI.tsx b/app/src/modules/simulation/simulationUI.tsx index 3a84134..0ce9fc2 100644 --- a/app/src/modules/simulation/simulationUI.tsx +++ b/app/src/modules/simulation/simulationUI.tsx @@ -1,409 +1,409 @@ -import { useMemo, useState } from 'react'; -import { useSelectedActionSphere, useToggleView, useSimulationPaths, useSelectedPath, useStartSimulation, useDrawMaterialPath } from '../../store/store'; -import * as THREE from 'three'; -import useModuleStore from '../../store/useModuleStore'; +// import { useMemo, useState } from 'react'; +// import { useSelectedActionSphere, useToggleView, useSimulationPaths, useSelectedPath, useStartSimulation, useDrawMaterialPath } from '../../store/store'; +// import * as THREE from 'three'; +// import useModuleStore from '../../store/useModuleStore'; -function SimulationUI() { - const { ToggleView } = useToggleView(); - const { activeModule } = useModuleStore(); - const { startSimulation, setStartSimulation } = useStartSimulation(); - const { selectedActionSphere } = useSelectedActionSphere(); - const { selectedPath, setSelectedPath } = useSelectedPath(); - const { simulationPaths, setSimulationPaths } = useSimulationPaths(); - const { drawMaterialPath, setDrawMaterialPath } = useDrawMaterialPath(); - const [activeButton, setActiveButton] = useState(null); +// function SimulationUI() { +// const { ToggleView } = useToggleView(); +// const { activeModule } = useModuleStore(); +// const { startSimulation, setStartSimulation } = useStartSimulation(); +// const { selectedActionSphere } = useSelectedActionSphere(); +// const { selectedPath, setSelectedPath } = useSelectedPath(); +// const { simulationPaths, setSimulationPaths } = useSimulationPaths(); +// const { drawMaterialPath, setDrawMaterialPath } = useDrawMaterialPath(); +// const [activeButton, setActiveButton] = useState(null); - const handleAddAction = () => { - if (!selectedActionSphere) return; +// const handleAddAction = () => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => { - if (point.uuid === selectedActionSphere.point.uuid) { - const actionIndex = point.actions.length; - const newAction = { - uuid: THREE.MathUtils.generateUUID(), - name: `Action ${actionIndex + 1}`, // Assign action name based on index - type: 'Inherit', - material: 'Inherit', - delay: 'Inherit', - spawnInterval: 'Inherit', - isUsed: false - }; +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => { +// if (point.uuid === selectedActionSphere.point.uuid) { +// const actionIndex = point.actions.length; +// const newAction = { +// uuid: THREE.MathUtils.generateUUID(), +// name: `Action ${actionIndex + 1}`, // Assign action name based on index +// type: 'Inherit', +// material: 'Inherit', +// delay: 'Inherit', +// spawnInterval: 'Inherit', +// isUsed: false +// }; - return { ...point, actions: [...point.actions, newAction] }; - } - return point; - }), - })); +// return { ...point, actions: [...point.actions, newAction] }; +// } +// return point; +// }), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleDeleteAction = (uuid: string) => { - if (!selectedActionSphere) return; +// const handleDeleteAction = (uuid: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleActionSelect = (uuid: string, actionType: string) => { - if (!selectedActionSphere) return; +// const handleActionSelect = (uuid: string, actionType: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, type: actionType } : action - ), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// actions: point.actions.map((action) => +// action.uuid === uuid ? { ...action, type: actionType } : action +// ), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleMaterialSelect = (uuid: string, material: string) => { - if (!selectedActionSphere) return; +// const handleMaterialSelect = (uuid: string, material: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, material } : action - ), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// actions: point.actions.map((action) => +// action.uuid === uuid ? { ...action, material } : action +// ), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleDelayChange = (uuid: string, delay: number | string) => { - if (!selectedActionSphere) return; +// const handleDelayChange = (uuid: string, delay: number | string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, delay } : action - ), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// actions: point.actions.map((action) => +// action.uuid === uuid ? { ...action, delay } : action +// ), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { - if (!selectedActionSphere) return; +// const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => - action.uuid === uuid ? { ...action, spawnInterval } : action - ), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// actions: point.actions.map((action) => +// action.uuid === uuid ? { ...action, spawnInterval } : action +// ), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleSpeedChange = (speed: number) => { - if (!selectedPath) return; +// const handleSpeedChange = (speed: number) => { +// if (!selectedPath) return; - const updatedPaths = simulationPaths.map((path) => - path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path - ); +// const updatedPaths = simulationPaths.map((path) => +// path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path +// ); - setSimulationPaths(updatedPaths); - setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); - }; +// setSimulationPaths(updatedPaths); +// setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } }); +// }; - const handleAddTrigger = () => { - if (!selectedActionSphere) return; +// const handleAddTrigger = () => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => { - if (point.uuid === selectedActionSphere.point.uuid) { - const triggerIndex = point.triggers.length; - const newTrigger = { - uuid: THREE.MathUtils.generateUUID(), - name: `Trigger ${triggerIndex + 1}`, // Assign name based on index - type: '', - isUsed: false - }; +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => { +// if (point.uuid === selectedActionSphere.point.uuid) { +// const triggerIndex = point.triggers.length; +// const newTrigger = { +// uuid: THREE.MathUtils.generateUUID(), +// name: `Trigger ${triggerIndex + 1}`, // Assign name based on index +// type: '', +// isUsed: false +// }; - return { ...point, triggers: [...point.triggers, newTrigger] }; - } - return point; - }), - })); +// return { ...point, triggers: [...point.triggers, newTrigger] }; +// } +// return point; +// }), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleDeleteTrigger = (uuid: string) => { - if (!selectedActionSphere) return; +// const handleDeleteTrigger = (uuid: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleTriggerSelect = (uuid: string, triggerType: string) => { - if (!selectedActionSphere) return; +// const handleTriggerSelect = (uuid: string, triggerType: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - triggers: point.triggers.map((trigger) => - trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger - ), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// triggers: point.triggers.map((trigger) => +// trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger +// ), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleResetPath = () => { - if (!selectedPath) return; +// const handleResetPath = () => { +// if (!selectedPath) return; - }; +// }; - const handleActionToggle = (uuid: string) => { - if (!selectedActionSphere) return; +// const handleActionToggle = (uuid: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - actions: point.actions.map((action) => ({ - ...action, - isUsed: action.uuid === uuid ? !action.isUsed : false, - })), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// actions: point.actions.map((action) => ({ +// ...action, +// isUsed: action.uuid === uuid ? !action.isUsed : false, +// })), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const handleTriggerToggle = (uuid: string) => { - if (!selectedActionSphere) return; +// const handleTriggerToggle = (uuid: string) => { +// if (!selectedActionSphere) return; - const updatedPaths = simulationPaths.map((path) => ({ - ...path, - points: path.points.map((point) => - point.uuid === selectedActionSphere.point.uuid - ? { - ...point, - triggers: point.triggers.map((trigger) => ({ - ...trigger, - isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, - })), - } - : point - ), - })); +// const updatedPaths = simulationPaths.map((path) => ({ +// ...path, +// points: path.points.map((point) => +// point.uuid === selectedActionSphere.point.uuid +// ? { +// ...point, +// triggers: point.triggers.map((trigger) => ({ +// ...trigger, +// isUsed: trigger.uuid === uuid ? !trigger.isUsed : false, +// })), +// } +// : point +// ), +// })); - setSimulationPaths(updatedPaths); - }; +// setSimulationPaths(updatedPaths); +// }; - const selectedPoint = useMemo(() => { - if (!selectedActionSphere) return null; - return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid); - }, [selectedActionSphere, simulationPaths]); +// const selectedPoint = useMemo(() => { +// if (!selectedActionSphere) return null; +// return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid); +// }, [selectedActionSphere, simulationPaths]); - const createPath = () => { - setActiveButton(activeButton !== 'addMaterialPath' ? 'addMaterialPath' : null); - setDrawMaterialPath(!drawMaterialPath); - } +// const createPath = () => { +// setActiveButton(activeButton !== 'addMaterialPath' ? 'addMaterialPath' : null); +// setDrawMaterialPath(!drawMaterialPath); +// } - return ( - <> - {activeModule === "simulation" && ( -
- {!ToggleView && ( - <> - +// return ( +// <> +// {activeModule === "simulation" && ( +//
+// {!ToggleView && ( +// <> +// -
- {!ToggleView && } -
+//
+// {!ToggleView && } +//
- {selectedPath && ( -
- - handleSpeedChange(parseFloat(e.target.value))} - /> -
- )} +// {selectedPath && ( +//
+// +// handleSpeedChange(parseFloat(e.target.value))} +// /> +//
+// )} - {selectedActionSphere && ( -
- - +// {selectedActionSphere && ( +//
+// +// - {selectedPoint?.actions.map((action) => ( -
- - - +// {selectedPoint?.actions.map((action) => ( +//
+// +// +// - {(action.type === 'Spawn' || action.type === 'Swap') && ( -
- -
- )} +// {(action.type === 'Spawn' || action.type === 'Swap') && ( +//
+// +//
+// )} - {action.type === 'Delay' && ( -
- - handleDelayChange(action.uuid, parseInt(e.target.value) || 'Inherit')} - /> +// {action.type === 'Delay' && ( +//
+// +// handleDelayChange(action.uuid, parseInt(e.target.value) || 'Inherit')} +// /> -
- )} +//
+// )} - {action.type === 'Spawn' && ( -
- - handleSpawnIntervalChange(action.uuid, parseInt(e.target.value) || 'Inherit')} - /> +// {action.type === 'Spawn' && ( +//
+// +// handleSpawnIntervalChange(action.uuid, parseInt(e.target.value) || 'Inherit')} +// /> -
- )} -
-
- ))} +//
+// )} +//
+//
+// ))} -
+//
- {selectedPoint?.triggers.map((trigger) => ( -
- - - -
-
- ))} +// {selectedPoint?.triggers.map((trigger) => ( +//
+// +// +// +//
+//
+// ))} -
- )} +//
+// )} - {selectedPath && ( -
- -
- )} - - )} -
- )} - - ); -} +// {selectedPath && ( +//
+// +//
+// )} +// +// )} +//
+// )} +// +// ); +// } -export default SimulationUI; \ No newline at end of file +// export default SimulationUI; \ No newline at end of file diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx index 1046ea2..a7800e1 100644 --- a/app/src/pages/Project.tsx +++ b/app/src/pages/Project.tsx @@ -64,7 +64,6 @@ const Project: React.FC = () => { {activeModule === "market" && } {activeModule !== "market" && } - {/* */} {isPlaying && activeModule === "simulation" && } ); diff --git a/app/src/services/factoryBuilder/mqtt/mqttEvents.ts b/app/src/services/factoryBuilder/mqtt/mqttEvents.ts index cd79484..41175ca 100644 --- a/app/src/services/factoryBuilder/mqtt/mqttEvents.ts +++ b/app/src/services/factoryBuilder/mqtt/mqttEvents.ts @@ -6,10 +6,7 @@ const MqttEvents = () => { const { setTouch, setTemperature, setHumidity } = useDrieUIValue(); useEffect(() => { - const client = mqtt.connect("ws://192.168.0.192:1884", { - username: "gabby", - password: "gabby" - }); + const client = mqtt.connect(`ws://${process.env.REACT_APP_SERVER_MQTT_URL}`); client.subscribe("touch"); client.subscribe("temperature"); diff --git a/app/src/store/store.ts b/app/src/store/store.ts index 8b8e544..eb2fac4 100644 --- a/app/src/store/store.ts +++ b/app/src/store/store.ts @@ -2,7 +2,6 @@ import * as THREE from "three"; import * as Types from "../types/world/worldTypes"; import { create } from "zustand"; import { io } from "socket.io-client"; -import { ComponentType, SVGProps } from "react"; export const useSocketStore = create((set: any, get: any) => ({ socket: null, @@ -31,8 +30,8 @@ export const useSocketStore = create((set: any, get: any) => ({ })); export const useLoadingProgress = create<{ loadingProgress: number; setLoadingProgress: (x: number) => void }>((set) => ({ - loadingProgress: 1, - setLoadingProgress: (x: number) => set({ loadingProgress: x }), + loadingProgress: 1, + setLoadingProgress: (x: number) => set({ loadingProgress: x }), })); export const useOrganization = create((set: any) => ({ @@ -311,30 +310,14 @@ export const useSelectedPath = create((set: any) => ({ setSelectedPath: (x: any) => set({ selectedPath: x }), })); -interface Path { - modeluuid: string; - modelName: string; - points: { - uuid: string; - position: [number, number, number]; - rotation: [number, number, number]; - actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; - triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; - connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] }; - }[]; - pathPosition: [number, number, number]; - pathRotation: [number, number, number]; - speed: number; -} - interface SimulationPathsStore { - simulationPaths: Path[]; - setSimulationPaths: (paths: Path[]) => void; + simulationPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]; + setSimulationPaths: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => void; } export const useSimulationPaths = create((set) => ({ - simulationPaths: [], - setSimulationPaths: (paths: Path[]) => set({ simulationPaths: paths }), + simulationPaths: [], + setSimulationPaths: (paths) => set({ simulationPaths: paths }), })); export const useIsConnecting = create((set: any) => ({ diff --git a/app/src/types/world/worldTypes.d.ts b/app/src/types/world/worldTypes.d.ts index c1e7128..2fcbd4f 100644 --- a/app/src/types/world/worldTypes.d.ts +++ b/app/src/types/world/worldTypes.d.ts @@ -284,4 +284,36 @@ interface ConnectionStore { setConnections: (connections: PathConnection[]) => void; addConnection: (newConnection: PathConnection) => void; removeConnection: (fromUUID: string, toUUID: string) => void; +} + +interface ConveyorEventsSchema { + modeluuid: string; + modelName: string; + type: 'Conveyor'; + points: { + uuid: string; + position: [number, number, number]; + rotation: [number, number, number]; + actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; + triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; + connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] }; + }[]; + assetPosition: [number, number, number]; + assetRotation: [number, number, number]; + speed: number; +} + +interface VehicleEventsSchema { + modeluuid: string; + modelName: string; + type: 'Vehicle'; + point: { + uuid: string; + position: [number, number, number]; + actions: { uuid: string; name: string; type: string; start: string, hitCount: number, end: string, buffer: number; isUsed: boolean }[] | []; + triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; + connections: { source: { pathUUID: string; pointUUID: string }; targets: { pathUUID: string; pointUUID: string }[] }; + }; + assetPosition: [number, number, number]; + speed: number; } \ No newline at end of file