diff --git a/app/src/components/layout/sidebarLeft/SideBarLeft.tsx b/app/src/components/layout/sidebarLeft/SideBarLeft.tsx
index e0b56d4..dc412f7 100644
--- a/app/src/components/layout/sidebarLeft/SideBarLeft.tsx
+++ b/app/src/components/layout/sidebarLeft/SideBarLeft.tsx
@@ -5,8 +5,8 @@ import Header from "./Header";
import useToggleStore from "../../../store/useUIToggleStore";
import Assets from "./Assets";
import useModuleStore from "../../../store/useModuleStore";
-import Widgets from "./visualization/widgets/Widgets";
-import Templates from "../../../modules/visualization/template/Templates";
+import Widgets from ".//visualization/widgets/Widgets";
+import Templates from "../../../modules//visualization/template/Templates";
import Search from "../../ui/inputs/Search";
const SideBarLeft: React.FC = () => {
diff --git a/app/src/components/layout/sidebarLeft/visualization/widgets/WidgetsFloating.tsx b/app/src/components/layout/sidebarLeft/visualization/widgets/WidgetsFloating.tsx
index b5ae0bb..50d9712 100644
--- a/app/src/components/layout/sidebarLeft/visualization/widgets/WidgetsFloating.tsx
+++ b/app/src/components/layout/sidebarLeft/visualization/widgets/WidgetsFloating.tsx
@@ -5,11 +5,11 @@ import {
GlobeIcon,
WalletIcon,
} from "../../../../icons/3dChartIcons";
-import SimpleCard from "../../../../../modules/visualization/widgets/floating/cards/SimpleCard";
+import SimpleCard from "../../../../../modules//visualization/widgets/floating/cards/SimpleCard";
-import WarehouseThroughput from "../../../../../modules/visualization/widgets/floating/cards/WarehouseThroughput";
-import ProductivityDashboard from "../../../../../modules/visualization/widgets/floating/cards/ProductivityDashboard";
-import FleetEfficiency from "../../../../../modules/visualization/widgets/floating/cards/FleetEfficiency";
+import WarehouseThroughput from "../../../../../modules//visualization/widgets/floating/cards/WarehouseThroughput";
+import ProductivityDashboard from "../../../../../modules//visualization/widgets/floating/cards/ProductivityDashboard";
+import FleetEfficiency from "../../../../../modules//visualization/widgets/floating/cards/FleetEfficiency";
interface Widget {
id: string;
diff --git a/app/src/components/layout/sidebarRight/Header.tsx b/app/src/components/layout/sidebarRight/Header.tsx
index 6922314..f9f48fb 100644
--- a/app/src/components/layout/sidebarRight/Header.tsx
+++ b/app/src/components/layout/sidebarRight/Header.tsx
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
import { AppDockIcon } from "../../icons/HeaderIcons";
import orgImg from "../../../assets/orgTemp.png";
import { useActiveUsers } from "../../../store/store";
-import { getAvatarColor } from "../../../modules/collaboration/users/functions/getAvatarColor";
+import { getAvatarColor } from "../../../functions/users/functions/getAvatarColor";
import { ActiveUser } from "../../../types/users";
import CollaborationPopup from "../../templates/CollaborationPopup";
diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx
index f991478..125cef9 100644
--- a/app/src/components/layout/sidebarRight/SideBarRight.tsx
+++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx
@@ -10,25 +10,19 @@ import {
SimulationIcon,
} from "../../icons/SimulationIcons";
import useToggleStore from "../../../store/useUIToggleStore";
-import ConveyorMechanics from "./mechanics/ConveyorMechanics";
import Visualization from "./visualization/Visualization";
import Analysis from "./analysis/Analysis";
import Simulations from "./simulation/Simulations";
import {
- useSelectedActionSphere,
useSelectedFloorItem,
} from "../../../store/store";
import GlobalProperties from "./properties/GlobalProperties";
import AsstePropertiies from "./properties/AssetProperties";
import ZoneProperties from "./properties/ZoneProperties";
-import VehicleMechanics from "./mechanics/VehicleMechanics";
-import StaticMachineMechanics from "./mechanics/StaticMachineMechanics";
-import ArmBotMechanics from "./mechanics/ArmBotMechanics";
const SideBarRight: React.FC = () => {
const { activeModule } = useModuleStore();
const { toggleUI } = useToggleStore();
- const { selectedActionSphere } = useSelectedActionSphere();
const { subModule, setSubModule } = useSubModuleStore();
const { selectedFloorItem } = useSelectedFloorItem();
// Reset activeList whenever activeModule changes
@@ -112,46 +106,9 @@ const SideBarRight: React.FC = () => {
{toggleUI && activeModule === "simulation" && (
<>
- {subModule === "mechanics" &&
- selectedActionSphere &&
- selectedActionSphere.path.type === "Conveyor" && (
-
- )}
- {subModule === "mechanics" &&
- selectedActionSphere &&
- selectedActionSphere.path.type === "Vehicle" && (
-
- )}
- {subModule === "mechanics" &&
- selectedActionSphere &&
- selectedActionSphere.path.type === "StaticMachine" && (
-
- )}
- {subModule === "mechanics" &&
- selectedActionSphere &&
- selectedActionSphere.path.type === "ArmBot" && (
-
- )}
- {subModule === "mechanics" && !selectedActionSphere && (
+ {subModule === "mechanics" && (
)}
diff --git a/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx
deleted file mode 100644
index 70e297b..0000000
--- a/app/src/components/layout/sidebarRight/mechanics/ArmBotMechanics.tsx
+++ /dev/null
@@ -1,411 +0,0 @@
-import React, { useRef, useMemo, useCallback, useState } from "react";
-import { InfoIcon, AddIcon, RemoveIcon, ResizeHeightIcon } from "../../../icons/ExportCommonIcons";
-import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
-import { useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
-import * as SimulationTypes from '../../../../types/simulationTypes';
-import LabledDropdown from "../../../ui/inputs/LabledDropdown";
-import { handleResize } from "../../../../functions/handleResizePannel";
-
-interface ConnectedModel {
- modelUUID: string;
- modelName: string;
- points: {
- uuid: string;
- position: [number, number, number];
- index?: number;
- }[];
- triggers?: {
- uuid: string;
- name: string;
- type: string;
- isUsed: boolean;
- }[];
-}
-
-const ArmBotMechanics: React.FC = () => {
- const { selectedActionSphere } = useSelectedActionSphere();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const { socket } = useSocketStore();
- const [selectedProcessIndex, setSelectedProcessIndex] = useState(null);
- const actionsContainerRef = useRef(null);
-
- // Get connected models and their triggers
- const connectedModels = useMemo(() => {
- if (!selectedActionSphere?.points?.uuid) return [];
-
- const armBotPaths = simulationStates.filter(
- (path): path is SimulationTypes.ArmBotEventsSchema => path.type === "ArmBot"
- );
-
- const currentPoint = armBotPaths.find(
- (path) => path.points.uuid === selectedActionSphere.points.uuid
- )?.points;
-
- if (!currentPoint?.connections?.targets) return [];
-
- return currentPoint.connections.targets.reduce((acc, target) => {
- const connectedModel = simulationStates.find(
- (model) => model.modeluuid === target.modelUUID
- );
-
- if (!connectedModel) return acc;
-
- let triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] = [];
- let points: { uuid: string; position: [number, number, number] }[] = [];
-
- if (connectedModel.type === "Conveyor") {
- const conveyor = connectedModel as SimulationTypes.ConveyorEventsSchema;
-
- const connectedPointUUIDs = currentPoint?.connections?.targets
- .filter(t => t.modelUUID === connectedModel.modeluuid)
- .map(t => t.pointUUID) || [];
-
- points = conveyor.points
- .map((point, idx) => ({
- uuid: point.uuid,
- position: point.position,
- index: idx
- }))
- .filter(point => connectedPointUUIDs.includes(point.uuid));
-
-
- triggers = conveyor.points.flatMap(p => p.triggers?.filter(t => t.isUsed) || []);
- }
- else if (connectedModel.type === "StaticMachine") {
- const staticMachine = connectedModel as SimulationTypes.StaticMachineEventsSchema;
-
- points = [{
- uuid: staticMachine.points.uuid,
- position: staticMachine.points.position
- }];
-
- triggers = staticMachine.points.triggers ?
- [{
- uuid: staticMachine.points.triggers.uuid,
- name: staticMachine.points.triggers.name,
- type: staticMachine.points.triggers.type,
- isUsed: true // StaticMachine triggers are always considered used
- }] : [];
- }
-
- if (!acc.some(m => m.modelUUID === connectedModel.modeluuid)) {
- acc.push({
- modelUUID: connectedModel.modeluuid,
- modelName: connectedModel.modelName,
- points,
- triggers
- });
- }
-
- return acc;
- }, []);
- }, [selectedActionSphere, simulationStates]);
-
- // Get triggers from connected models
- const connectedTriggers = useMemo(() => {
- return connectedModels.flatMap(model =>
- (model.triggers || []).map(trigger => ({
- ...trigger,
- displayName: `${model.modelName} - ${trigger.name}`,
- modelUUID: model.modelUUID
- }))
- );
- }, [connectedModels]);
-
- // Get all points from connected models
- const connectedPoints = useMemo(() => {
- return connectedModels.flatMap(model =>
- model.points.map(point => ({
- ...point,
- displayName: `${model.modelName} - Point${typeof point.index === 'number' ? ` ${point.index}` : ''}`,
- modelUUID: model.modelUUID
- }))
- );
- }, [connectedModels]);
-
-
- const { selectedPoint } = useMemo(() => {
- if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null };
-
- const armBotPaths = simulationStates.filter(
- (path): path is SimulationTypes.ArmBotEventsSchema => path.type === "ArmBot"
- );
-
- const points = armBotPaths.find(
- (path) => path.points.uuid === selectedActionSphere.points.uuid
- )?.points;
-
- return {
- selectedPoint: points || null
- };
- }, [selectedActionSphere, simulationStates]);
-
- const updateBackend = async (updatedPath: SimulationTypes.ArmBotEventsSchema | undefined) => {
- if (!updatedPath) return;
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "";
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: { type: "ArmBot", points: updatedPath.points }
- }
-
- socket.emit('v2:model-asset:updateEventData', data);
- }
-
- const handleActionUpdate = useCallback((updatedAction: Partial) => {
- if (!selectedActionSphere?.points?.uuid || !selectedPoint) return;
-
- const updatedPaths = simulationStates.map((path) => {
- if (path.type === "ArmBot" && path.points.uuid === selectedActionSphere.points.uuid) {
- return {
- ...path,
- points: {
- ...path.points,
- actions: {
- ...path.points.actions,
- ...updatedAction
- }
- }
- };
- }
- return path;
- });
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ArmBotEventsSchema =>
- path.type === "ArmBot" &&
- path.points.uuid === selectedActionSphere.points.uuid
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- }, [selectedActionSphere?.points?.uuid, selectedPoint, simulationStates, setSimulationStates]);
-
- const handleSpeedChange = useCallback((speed: number) => {
- handleActionUpdate({ speed });
- }, [handleActionUpdate]);
-
- const handleProcessChange = useCallback((processes: SimulationTypes.ArmBotEventsSchema['points']['actions']['processes']) => {
- handleActionUpdate({ processes });
- }, [handleActionUpdate]);
-
- const handleAddProcess = useCallback(() => {
- if (!selectedPoint) return;
-
- const newProcess: any = {
- triggerId: "",
- startPoint: "",
- endPoint: ""
- };
-
- const updatedProcesses = selectedPoint.actions.processes ? [...selectedPoint.actions.processes, newProcess] : [newProcess];
-
- handleProcessChange(updatedProcesses);
- setSelectedProcessIndex(updatedProcesses.length - 1);
- }, [selectedPoint, handleProcessChange]);
-
- const handleDeleteProcess = useCallback((index: number) => {
- if (!selectedPoint?.actions.processes) return;
-
- const updatedProcesses = [...selectedPoint.actions.processes];
- updatedProcesses.splice(index, 1);
-
- handleProcessChange(updatedProcesses);
-
- // Reset selection if deleting the currently selected process
- if (selectedProcessIndex === index) {
- setSelectedProcessIndex(null);
- } else if (selectedProcessIndex !== null && selectedProcessIndex > index) {
- // Adjust selection index if needed
- setSelectedProcessIndex(selectedProcessIndex - 1);
- }
- }, [selectedPoint, selectedProcessIndex, handleProcessChange]);
-
- const handleTriggerSelect = useCallback((displayName: string, index: number) => {
- const availableOptions = getFilteredTriggerOptions(index);
- const selectedDisplayIndex = availableOptions.indexOf(displayName);
-
- const filteredTriggers = connectedTriggers.filter(trigger =>
- !selectedPoint?.actions.processes
- ?.filter((_, i) => i !== index)
- .map(p => p.triggerId)
- .includes(trigger.uuid)
- );
-
- const selected = filteredTriggers[selectedDisplayIndex];
-
- if (!selected || !selectedPoint?.actions.processes) return;
-
- const oldProcess = selectedPoint.actions.processes[index];
-
- const updatedProcesses = [...selectedPoint.actions.processes];
- updatedProcesses[index] = {
- ...oldProcess,
- triggerId: selected.uuid,
- startPoint: oldProcess.startPoint || "",
- endPoint: oldProcess.endPoint || ""
- };
-
- handleProcessChange(updatedProcesses);
- }, [connectedTriggers, selectedPoint, handleProcessChange]);
-
- const handleStartPointSelect = useCallback((displayName: string, index: number) => {
- if (!selectedPoint?.actions.processes) return;
-
- const point = connectedPoints.find(p => p.displayName === displayName);
- if (!point) return;
-
- const updatedProcesses = [...selectedPoint.actions.processes];
- updatedProcesses[index] = {
- ...updatedProcesses[index],
- startPoint: point.uuid
- };
-
- handleProcessChange(updatedProcesses);
- }, [selectedPoint, connectedPoints, handleProcessChange]);
-
- const handleEndPointSelect = useCallback((displayName: string, index: number) => {
- if (!selectedPoint?.actions.processes) return;
-
- const point = connectedPoints.find(p => p.displayName === displayName);
- if (!point) return;
-
- const updatedProcesses = [...selectedPoint.actions.processes];
- updatedProcesses[index] = {
- ...updatedProcesses[index],
- endPoint: point.uuid
- };
-
- handleProcessChange(updatedProcesses);
- }, [selectedPoint, connectedPoints, handleProcessChange]);
-
- const getProcessByIndex = useCallback((index: number) => {
- if (!selectedPoint?.actions.processes || index >= selectedPoint.actions.processes.length) return null;
- return selectedPoint.actions.processes[index];
- }, [selectedPoint]);
-
- const getFilteredTriggerOptions = (currentIndex: number) => {
- const usedTriggerUUIDs = selectedPoint?.actions.processes?.filter((_, i) => i !== currentIndex).map(p => p.triggerId).filter(Boolean) ?? [];
-
- return connectedTriggers.filter(trigger => !usedTriggerUUIDs.includes(trigger.uuid)).map(trigger => trigger.displayName);
- };
-
- return (
-
-
- {selectedActionSphere?.path?.modelName || "ArmBot point not found"}
-
-
-
-
-
ArmBot Properties
-
- {selectedPoint && (
- <>
-
handleSpeedChange(parseFloat(value))}
- />
-
-
-
-
-
- {selectedPoint.actions.processes?.map((process, index) => (
-
-
setSelectedProcessIndex(index)}
- >
- Process {index + 1}
-
-
handleDeleteProcess(index)}
- >
-
-
-
- ))}
-
-
handleResize(e, actionsContainerRef)}
- >
-
-
-
-
-
- {selectedProcessIndex !== null && (
-
-
- t.uuid === getProcessByIndex(selectedProcessIndex)?.triggerId
- )?.displayName || 'Select a trigger'
- }
- onSelect={(value) => handleTriggerSelect(value, selectedProcessIndex)}
- options={getFilteredTriggerOptions(selectedProcessIndex)}
- />
-
-
- p.uuid === getProcessByIndex(selectedProcessIndex)?.startPoint
- )?.displayName || 'Select start point'
- }
- onSelect={(value) => handleStartPointSelect(value, selectedProcessIndex)}
- options={connectedPoints.map(point => point.displayName)}
- />
-
-
- p.uuid === getProcessByIndex(selectedProcessIndex)?.endPoint
- )?.displayName || 'Select end point'
- }
- onSelect={(value) => handleEndPointSelect(value, selectedProcessIndex)}
- options={connectedPoints.map(point => point.displayName)}
- />
-
- )}
- >
- )}
-
-
-
-
- Configure ArmBot properties and trigger-based processes.
-
-
-
- );
-};
-
-export default React.memo(ArmBotMechanics);
\ No newline at end of file
diff --git a/app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx
deleted file mode 100644
index 5e84d10..0000000
--- a/app/src/components/layout/sidebarRight/mechanics/ConveyorMechanics.tsx
+++ /dev/null
@@ -1,879 +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 { handleResize } from "../../../../functions/handleResizePannel";
-import {
- useFloorItems,
- useSelectedActionSphere,
- useSelectedPath,
- useSimulationStates,
- useSocketStore,
-} from "../../../../store/store";
-import * as THREE from "three";
-import * as SimulationTypes from "../../../../types/simulationTypes";
-import InputToggle from "../../../ui/inputs/InputToggle";
-import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
-import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
-
-const ConveyorMechanics: React.FC = () => {
- const { selectedActionSphere } = useSelectedActionSphere();
- const { selectedPath, setSelectedPath } = useSelectedPath();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const { floorItems, setFloorItems } = useFloorItems();
- const { socket } = useSocketStore();
-
- const actionsContainerRef = useRef(null);
- const triggersContainerRef = useRef(null);
-
- const selectedPoint = useMemo(() => {
- if (!selectedActionSphere) return null;
- return simulationStates
- .filter(
- (path): path is SimulationTypes.ConveyorEventsSchema => path.type === "Conveyor"
- )
- .flatMap((path) => path.points)
- .find((point) => point.uuid === selectedActionSphere.points.uuid);
- }, [selectedActionSphere, simulationStates]);
-
- const updateBackend = async (updatedPath: SimulationTypes.ConveyorEventsSchema | undefined) => {
- if (!updatedPath) return;
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "";
-
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
- }
-
- socket.emit('v2:model-asset:updateEventData', data);
-
- }
-
- const handleAddAction = () => {
- if (!selectedActionSphere) return;
-
- const updatedPaths = simulationStates.map((path) => {
- if (path.type === "Conveyor") {
- return {
- ...path,
- points: path.points.map((point) => {
- if (point.uuid === selectedActionSphere.points.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;
- });
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- };
-
- const handleDeleteAction = (uuid: string) => {
- if (!selectedActionSphere) return;
-
- const updatedPaths = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.points.uuid
- ? {
- ...point,
- actions: point.actions.filter(
- (action) => action.uuid !== uuid
- ),
- }
- : point
- ),
- }
- : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- };
-
- const handleActionSelect = (uuid: string, actionType: string) => {
- if (!selectedActionSphere) return;
-
- const updatedPaths = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.points.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
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
-
- // Update the selected item to reflect changes
- if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) {
- const updatedAction = updatedPaths
- .filter(
- (path): path is SimulationTypes.ConveyorEventsSchema => path.type === "Conveyor"
- )
- .flatMap((path) => path.points)
- .find((p) => p.uuid === selectedActionSphere.points.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 = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.points.uuid
- ? {
- ...point,
- actions: point.actions.map((action) =>
- action.uuid === uuid &&
- (action.type === "Spawn" || action.type === "Swap")
- ? { ...action, material }
- : action
- ),
- }
- : point
- ),
- }
- : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(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 = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.points.uuid
- ? {
- ...point,
- actions: point.actions.map((action) =>
- action.uuid === uuid ? { ...action, delay } : action
- ),
- }
- : point
- ),
- }
- : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- };
-
- const handleSpawnIntervalChange = (
- uuid: string,
- spawnInterval: number | string
- ) => {
- if (!selectedActionSphere) return;
-
- const updatedPaths = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.points.uuid
- ? {
- ...point,
- actions: point.actions.map((action) =>
- action.uuid === uuid
- ? { ...action, spawnInterval }
- : action
- ),
- }
- : point
- ),
- }
- : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- };
-
- const handleSpeedChange = (speed: number | string) => {
- if (!selectedPath) return;
-
- const updatedPaths = simulationStates.map((path) =>
- path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.modeluuid === selectedPath.path.modeluuid
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
- };
-
- const handleAddTrigger = () => {
- if (!selectedActionSphere) return;
-
- const updatedPaths = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) => {
- if (point.uuid === selectedActionSphere.points.uuid) {
- const triggerIndex = point.triggers.length;
- const newTrigger = {
- uuid: THREE.MathUtils.generateUUID(),
- name: `Trigger ${triggerIndex + 1}`,
- type: "",
- bufferTime: 0,
- isUsed: false,
- };
-
- return { ...point, triggers: [...point.triggers, newTrigger] };
- }
- return point;
- }),
- }
- : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- };
-
- const handleDeleteTrigger = (uuid: string) => {
- if (!selectedActionSphere) return;
-
- const updatedPaths = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.points.uuid
- ? {
- ...point,
- triggers: point.triggers.filter(
- (trigger) => trigger.uuid !== uuid
- ),
- }
- : point
- ),
- }
- : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- };
-
- const handleTriggerSelect = (uuid: string, triggerType: string) => {
- if (!selectedActionSphere) return;
-
- const updatedPaths = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.points.uuid
- ? {
- ...point,
- triggers: point.triggers.map((trigger) =>
- trigger.uuid === uuid
- ? { ...trigger, type: triggerType }
- : trigger
- ),
- }
- : point
- ),
- }
- : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
-
- // Ensure the selectedItem is updated immediately
- const updatedTrigger = updatedPaths
- .flatMap((path) => (path.type === "Conveyor" ? path.points : []))
- .flatMap((point) => point.triggers)
- .find((trigger) => trigger.uuid === uuid);
-
- if (updatedTrigger) {
- setSelectedItem({ type: "trigger", item: updatedTrigger });
- }
- };
-
- // Update the toggle handlers to immediately update the selected item
- const handleActionToggle = (uuid: string) => {
- if (!selectedActionSphere) return;
- const updatedPaths = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.points.uuid
- ? {
- ...point,
- actions: point.actions.map((action) => ({
- ...action,
- isUsed: action.uuid === uuid ? !action.isUsed : false,
- })),
- }
- : point
- ),
- }
- : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(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 = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.points.uuid
- ? {
- ...point,
- triggers: point.triggers.map((trigger) => ({
- ...trigger,
- isUsed: trigger.uuid === uuid ? !trigger.isUsed : false,
- })),
- }
- : point
- ),
- }
- : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(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 handleTriggerBufferTimeChange = (uuid: string, bufferTime: number) => {
- if (!selectedActionSphere) return;
-
- const updatedPaths = simulationStates.map((path) =>
- path.type === "Conveyor"
- ? {
- ...path,
- points: path.points.map((point) =>
- point.uuid === selectedActionSphere.points.uuid
- ? {
- ...point,
- triggers: point.triggers.map((trigger) =>
- trigger.uuid === uuid
- ? { ...trigger, bufferTime }
- : trigger
- ),
- }
- : point
- ),
- }
- : path
- );
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.ConveyorEventsSchema =>
- path.type === "Conveyor" &&
- path.points.some(
- (point) => point.uuid === selectedActionSphere.points.uuid
- )
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
-
- // Immediately update selectedItem if it's the currently selected trigger
- if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) {
- setSelectedItem({
- ...selectedItem,
- item: {
- ...selectedItem.item,
- bufferTime,
- },
- });
- }
- };
-
- const [selectedItem, setSelectedItem] = useState<{
- type: "action" | "trigger";
- item: any;
- } | null>(null);
-
- useEffect(() => {
- setSelectedItem(null);
- }, [selectedActionSphere]);
-
- return (
-
- {!selectedPath && (
-
- {selectedActionSphere?.path?.modelName || "point name not found"}
-
- )}
-
- {selectedPath && (
-
- {selectedPath.path.modelName || "path name not found"}
-
- )}
-
-
- {!selectedPath && (
- <>
-
-
-
-
- {selectedPoint?.actions.map((action) => (
-
-
- setSelectedItem({ type: "action", item: action })
- }
- >
-
-
-
-
handleDeleteAction(action.uuid)}
- >
-
-
-
- ))}
-
-
handleResize(e, actionsContainerRef)}
- >
-
-
-
-
-
-
-
-
- {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)
- }
- />
-
- {selectedItem.item.type === "Buffer" && (
- {
- handleTriggerBufferTimeChange(
- selectedItem.item.uuid,
- parseInt(value)
- );
- }}
- />
- )}
- >
- )}
- >
- )}
-
- {selectedPath && !selectedItem && (
-
-
- handleSpeedChange(value === "" ? "Inherit" : parseInt(value))
- }
- />
-
- )}
-
- {!selectedPath && (
-
-
- Configure the point's action and trigger properties.
-
- )}
- {selectedPath && (
-
-
- Configure the path properties.
-
- )}
-
-
- );
-};
-
-export default ConveyorMechanics;
diff --git a/app/src/components/layout/sidebarRight/mechanics/StaticMachineMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/StaticMachineMechanics.tsx
deleted file mode 100644
index 6342bac..0000000
--- a/app/src/components/layout/sidebarRight/mechanics/StaticMachineMechanics.tsx
+++ /dev/null
@@ -1,188 +0,0 @@
-import React, { useRef, useMemo, useCallback } from "react";
-import { InfoIcon } from "../../../icons/ExportCommonIcons";
-import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
-import { useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
-import * as SimulationTypes from '../../../../types/simulationTypes';
-import LabledDropdown from "../../../ui/inputs/LabledDropdown";
-import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
-
-const StaticMachineMechanics: React.FC = () => {
- const { selectedActionSphere } = useSelectedActionSphere();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const { socket } = useSocketStore();
-
- const propertiesContainerRef = useRef(null);
-
- const { selectedPoint, connectedPointUuids } = useMemo(() => {
- if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] };
-
- const staticMachinePaths = simulationStates.filter(
- (path): path is SimulationTypes.StaticMachineEventsSchema => path.type === "StaticMachine"
- );
-
- const points = staticMachinePaths.find(
- (path) => path.points.uuid === selectedActionSphere.points.uuid
- )?.points;
-
- if (!points) return { selectedPoint: null, connectedPointUuids: [] };
-
- const connectedUuids: string[] = [];
- if (points.connections?.targets) {
- points.connections.targets.forEach(target => {
- connectedUuids.push(target.pointUUID);
- });
- }
-
- return {
- selectedPoint: points,
- connectedPointUuids: connectedUuids
- };
- }, [selectedActionSphere, simulationStates]);
-
- const updateBackend = async (updatedPath: SimulationTypes.StaticMachineEventsSchema | undefined) => {
- if (!updatedPath) return;
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "";
-
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "Vehicle", points: updatedPath.points }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: { type: "StaticMachine", points: updatedPath.points }
- }
-
- socket.emit('v2:model-asset:updateEventData', data);
- }
-
- const handleActionUpdate = useCallback((updatedAction: Partial) => {
- if (!selectedActionSphere?.points?.uuid) return;
-
- const updatedPaths = simulationStates.map((path) => {
- if (path.type === "StaticMachine" && path.points.uuid === selectedActionSphere.points.uuid) {
- return {
- ...path,
- points: {
- ...path.points,
- actions: {
- ...path.points.actions,
- ...updatedAction
- }
- }
- };
- }
- return path;
- });
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.StaticMachineEventsSchema =>
- path.type === "StaticMachine" &&
- path.points.uuid === selectedActionSphere.points.uuid
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- }, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
-
- const handleBufferChange = useCallback((buffer: number) => {
- handleActionUpdate({ buffer });
- }, [handleActionUpdate]);
-
- const handleMaterialChange = useCallback((material: string) => {
- handleActionUpdate({ material });
- }, [handleActionUpdate]);
-
- const handleTriggerChange = useCallback((updatedTrigger: Partial) => {
- if (!selectedActionSphere?.points?.uuid) return;
-
- const updatedPaths = simulationStates.map((path) => {
- if (path.type === "StaticMachine" && path.points.uuid === selectedActionSphere.points.uuid) {
- return {
- ...path,
- points: {
- ...path.points,
- triggers: {
- ...path.points.triggers,
- ...updatedTrigger
- }
- }
- };
- }
- return path;
- });
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.StaticMachineEventsSchema =>
- path.type === "StaticMachine" &&
- path.points.uuid === selectedActionSphere.points.uuid
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- }, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
-
- const handleTriggerTypeChange = useCallback((type: string) => {
- handleTriggerChange({ type });
- }, [handleTriggerChange]);
-
- return (
-
-
- {selectedActionSphere?.path?.modelName || "Machine point not found"}
-
-
-
-
-
-
Machine Properties
-
- {selectedPoint && (
- <>
-
handleBufferChange(parseInt(value))}
- />
-
- handleMaterialChange(value)}
- options={["Inherit", "Crate", "Box"]}
- />
-
- handleTriggerTypeChange(value)}
- options={["OnComplete", "OnStart"]}
- />
-
- {/* {
- // Implement reset functionality if needed
- }}
- /> */}
- >
- )}
-
-
-
-
- Configure machine interaction properties and triggers.
-
-
-
- );
-};
-
-export default React.memo(StaticMachineMechanics);
\ 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
deleted file mode 100644
index 147d5cb..0000000
--- a/app/src/components/layout/sidebarRight/mechanics/VehicleMechanics.tsx
+++ /dev/null
@@ -1,265 +0,0 @@
-import React, { useRef, useMemo } from "react";
-import { InfoIcon } from "../../../icons/ExportCommonIcons";
-import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
-import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
-import * as SimulationTypes from '../../../../types/simulationTypes';
-import PositionInput from "../customInput/PositionInputs";
-import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
-import LabeledButton from "../../../ui/inputs/LabledButton";
-
-const VehicleMechanics: React.FC = () => {
- const { selectedActionSphere } = useSelectedActionSphere();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
- const { editingPoint, setEditingPoint } = useEditingPoint();
- const { previewPosition, setPreviewPosition } = usePreviewPosition();
- const { socket } = useSocketStore();
-
- const propertiesContainerRef = useRef(null);
-
- const { selectedPoint, connectedPointUuids } = useMemo(() => {
- if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] };
-
- const vehiclePaths = simulationStates.filter(
- (path): path is SimulationTypes.VehicleEventsSchema => path.type === "Vehicle"
- );
-
- const points = vehiclePaths.find(
- (path) => path.points.uuid === selectedActionSphere.points.uuid
- )?.points;
-
- if (!points) return { selectedPoint: null, connectedPointUuids: [] };
-
- const connectedUuids: string[] = [];
- if (points.connections?.targets) {
- points.connections.targets.forEach(target => {
- connectedUuids.push(target.pointUUID);
- });
- }
-
- return {
- selectedPoint: points,
- connectedPointUuids: connectedUuids
- };
- }, [selectedActionSphere, simulationStates]);
-
- const updateBackend = async (updatedPath: SimulationTypes.VehicleEventsSchema | undefined) => {
- if (!updatedPath) return;
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "";
-
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "Vehicle", points: updatedPath.points }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: { type: "Vehicle", points: updatedPath.points }
- }
-
- socket.emit('v2:model-asset:updateEventData', data);
-
- }
-
- const handleActionUpdate = React.useCallback((updatedAction: Partial) => {
- if (!selectedActionSphere?.points?.uuid) return;
-
- const updatedPaths = simulationStates.map((path) => {
- if (path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid) {
- return {
- ...path,
- points: {
- ...path.points,
- actions: {
- ...path.points.actions,
- ...updatedAction
- }
- }
- };
- }
- return path;
- });
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.VehicleEventsSchema =>
- path.type === "Vehicle" &&
- path.points.uuid === selectedActionSphere.points.uuid
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- }, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
-
- const handleHitCountChange = React.useCallback((hitCount: number) => {
- handleActionUpdate({ hitCount });
- }, [handleActionUpdate]);
-
- const handleBufferChange = React.useCallback((buffer: number) => {
- handleActionUpdate({ buffer });
- }, [handleActionUpdate]);
-
- const handleSpeedChange = React.useCallback((speed: number) => {
- if (!selectedActionSphere?.points?.uuid) return;
-
- const updatedPaths = simulationStates.map((path) => {
- if (path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid) {
- return {
- ...path,
- points: {
- ...path.points,
- speed: speed
- }
- };
- }
- return path;
- });
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.VehicleEventsSchema =>
- path.type === "Vehicle" &&
- path.points.uuid === selectedActionSphere.points.uuid
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- }, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
-
-
- const ResetVehicleState = React.useCallback(() => {
- if (!selectedActionSphere?.points?.uuid) return;
-
- const updatedPaths = simulationStates.map((state) => {
- if (state.type === "Vehicle" && state.points.uuid === selectedActionSphere.points.uuid) {
- return {
- ...state,
- points: {
- ...state.points,
- actions: { ...state.points.actions, start: {}, end: {} }
- }
- };
- }
- return state;
- });
-
- const updatedPath = updatedPaths.find(
- (path): path is SimulationTypes.VehicleEventsSchema =>
- path.type === "Vehicle" &&
- path.points.uuid === selectedActionSphere.points.uuid
- );
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- }, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
-
- const handleStartEyeDropClick = () => {
- setEditingPoint('start');
- setEyeDropMode(true);
- };
-
- const handleEndEyeDropClick = () => {
- setEditingPoint('end');
- setEyeDropMode(true);
- };
-
- return (
-
-
- {selectedActionSphere?.path?.modelName || "Vehicle point not found"}
-
-
-
-
-
Vehicle Properties
-
- {selectedPoint && (
- <>
-
{ }}
- disabled={true}
- value1={
- editingPoint === 'start' && previewPosition
- ? parseFloat(previewPosition.x.toFixed(4))
- : selectedPoint.actions.start && 'x' in selectedPoint.actions.start
- ? parseFloat(selectedPoint.actions.start.x.toFixed(4))
- : 0
- }
- value2={
- editingPoint === 'start' && previewPosition
- ? parseFloat(previewPosition.y.toFixed(4))
- : selectedPoint.actions.start && 'y' in selectedPoint.actions.start
- ? parseFloat(selectedPoint.actions.start.y.toFixed(4))
- : 0
- }
-
- isEyedrop={true}
- handleEyeDropClick={handleStartEyeDropClick}
- />
-
- { }}
- disabled={true}
- value1={
- editingPoint === 'end' && previewPosition
- ? parseFloat(previewPosition.x.toFixed(4))
- : selectedPoint.actions.end && 'x' in selectedPoint.actions.end
- ? parseFloat(selectedPoint.actions.end.x.toFixed(4))
- : 0
- }
- value2={
- editingPoint === 'end' && previewPosition
- ? parseFloat(previewPosition.y.toFixed(4))
- : selectedPoint.actions.end && 'y' in selectedPoint.actions.end
- ? parseFloat(selectedPoint.actions.end.y.toFixed(4))
- : 0
- }
- isEyedrop={true}
- handleEyeDropClick={handleEndEyeDropClick}
- />
-
- {
- ResetVehicleState();
- }}
- />
-
- handleHitCountChange(parseInt(value))}
- />
-
- handleBufferChange(parseInt(value))}
- />
-
- handleSpeedChange(parseFloat(value))}
- />
- >
- )}
-
-
-
-
- Configure vehicle's movement and interaction properties.
-
-
-
- );
-};
-
-export default React.memo(VehicleMechanics);
\ No newline at end of file
diff --git a/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx b/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx
index ab1430c..9cd9a7c 100644
--- a/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx
+++ b/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx
@@ -3,7 +3,7 @@ import RenameInput from "../../../ui/inputs/RenameInput";
import Vector3Input from "../customInput/Vector3Input";
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
import { useEditPosition, usezonePosition, useZones, usezoneTarget } from "../../../../store/store";
-import { zoneCameraUpdate } from "../../../../services/realTimeVisulization/zoneData/zoneCameraUpdation";
+import { zoneCameraUpdate } from "../../../../services/visulization/zone/zoneCameraUpdation";
const ZoneProperties: React.FC = () => {
const { Edit, setEdit } = useEditPosition();
diff --git a/app/src/components/layout/sidebarRight/visualization/design/Design.tsx b/app/src/components/layout/sidebarRight/visualization/design/Design.tsx
index 234b936..04a569a 100644
--- a/app/src/components/layout/sidebarRight/visualization/design/Design.tsx
+++ b/app/src/components/layout/sidebarRight/visualization/design/Design.tsx
@@ -1,9 +1,9 @@
import { useState, useEffect, useRef } from "react";
import { useWidgetStore } from "../../../../../store/useWidgetStore";
-import ChartComponent from "../../../sidebarLeft/visualization/widgets/ChartComponent";
+import ChartComponent from "../../../sidebarLeft//visualization/widgets/ChartComponent";
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
import { WalletIcon } from "../../../../icons/3dChartIcons";
-import SimpleCard from "../../../../../modules/visualization/widgets/floating/cards/SimpleCard";
+import SimpleCard from "../../../../../modules//visualization/widgets/floating/cards/SimpleCard";
interface Widget {
id: string;
diff --git a/app/src/components/ui/Tools.tsx b/app/src/components/ui/Tools.tsx
index 0f125ad..cf5bb17 100644
--- a/app/src/components/ui/Tools.tsx
+++ b/app/src/components/ui/Tools.tsx
@@ -15,7 +15,7 @@ import {
} from "../icons/ExportToolsIcons";
import { ArrowIcon, TickIcon } from "../icons/ExportCommonIcons";
import useModuleStore, { useThreeDStore } from "../../store/useModuleStore";
-import { handleSaveTemplate } from "../../modules/visualization/functions/handleSaveTemplate";
+import { handleSaveTemplate } from "../../modules//visualization/functions/handleSaveTemplate";
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
import useTemplateStore from "../../store/useTemplateStore";
import { useSelectedZoneStore } from "../../store/useZoneStore";
diff --git a/app/src/components/ui/list/DropDownList.tsx b/app/src/components/ui/list/DropDownList.tsx
index b2f05b9..f29475e 100644
--- a/app/src/components/ui/list/DropDownList.tsx
+++ b/app/src/components/ui/list/DropDownList.tsx
@@ -4,7 +4,6 @@ import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
import { useFloorItems, useZones } from "../../../store/store";
import { useSelectedZoneStore } from "../../../store/useZoneStore";
-import { getZone2dData } from "../../../services/realTimeVisulization/zoneData/getZoneData";
interface DropDownListProps {
value?: string; // Value to display in the DropDownList
diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx
index 49e86f4..efcf328 100644
--- a/app/src/components/ui/list/List.tsx
+++ b/app/src/components/ui/list/List.tsx
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
import RenameInput from "../inputs/RenameInput";
import { useSelectedZoneStore } from "../../../store/useZoneStore";
-import { getZoneData } from "../../../services/realTimeVisulization/zoneData/getZones";
+import { getZoneData } from "../../../services/visulization/zone/getZones";
import useModuleStore, {
useSubModuleStore,
} from "../../../store/useModuleStore";
@@ -14,7 +14,7 @@ import {
} from "../../icons/ExportCommonIcons";
import { useThree } from "@react-three/fiber";
import { useFloorItems, useZoneAssetId, useZones } from "../../../store/store";
-import { zoneCameraUpdate } from "../../../services/realTimeVisulization/zoneData/zoneCameraUpdation";
+import { zoneCameraUpdate } from "../../../services/visulization/zone/zoneCameraUpdation";
import { setFloorItemApi } from "../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
interface Asset {
diff --git a/app/src/modules/collaboration/collabUserIcon.tsx b/app/src/functions/collabUserIcon.tsx
similarity index 95%
rename from app/src/modules/collaboration/collabUserIcon.tsx
rename to app/src/functions/collabUserIcon.tsx
index a8738ce..9e6802b 100644
--- a/app/src/modules/collaboration/collabUserIcon.tsx
+++ b/app/src/functions/collabUserIcon.tsx
@@ -1,31 +1,31 @@
-import React from "react";
-import CustomAvatar from "./users/Avatar";
-
-interface CollabUserIconProps {
- userName: string;
- userImage?: string;
- color: string;
-}
-
-const CollabUserIcon: React.FC = ({
- userImage,
- userName,
- color,
-}) => {
- return (
-
-
- {userImage ? (
-

- ) : (
-
- )}
-
-
- {userName}
-
-
- );
-};
-
-export default CollabUserIcon;
+import React from "react";
+import CustomAvatar from "./users/Avatar";
+
+interface CollabUserIconProps {
+ userName: string;
+ userImage?: string;
+ color: string;
+}
+
+const CollabUserIcon: React.FC = ({
+ userImage,
+ userName,
+ color,
+}) => {
+ return (
+
+
+ {userImage ? (
+

+ ) : (
+
+ )}
+
+
+ {userName}
+
+
+ );
+};
+
+export default CollabUserIcon;
diff --git a/app/src/modules/collaboration/users/Avatar.tsx b/app/src/functions/users/Avatar.tsx
similarity index 100%
rename from app/src/modules/collaboration/users/Avatar.tsx
rename to app/src/functions/users/Avatar.tsx
diff --git a/app/src/modules/collaboration/users/functions/getAvatarColor.ts b/app/src/functions/users/functions/getAvatarColor.ts
similarity index 100%
rename from app/src/modules/collaboration/users/functions/getAvatarColor.ts
rename to app/src/functions/users/functions/getAvatarColor.ts
diff --git a/app/src/modules/collaboration/users/functions/getInitials.ts b/app/src/functions/users/functions/getInitials.ts
similarity index 100%
rename from app/src/modules/collaboration/users/functions/getInitials.ts
rename to app/src/functions/users/functions/getInitials.ts
diff --git a/app/src/modules/scene/IntialLoad/loadInitialFloorItems.ts b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts
similarity index 68%
rename from app/src/modules/scene/IntialLoad/loadInitialFloorItems.ts
rename to app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts
index 7ca7db9..e88dc3c 100644
--- a/app/src/modules/scene/IntialLoad/loadInitialFloorItems.ts
+++ b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts
@@ -1,270 +1,202 @@
-import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
-import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
-import gsap from 'gsap';
-import * as THREE from 'three';
-import * as CONSTANTS from '../../../types/world/worldConstants';
-import { toast } from 'react-toastify';
-import * as Types from "../../../types/world/worldTypes";
-import * as SimulationTypes from "../../../types/simulationTypes";
-import { initializeDB, retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils';
-import { getCamera } from '../../../services/factoryBuilder/camera/getCameraApi';
-import { getFloorAssets } from '../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
-
-async function loadInitialFloorItems(
- itemsGroup: Types.RefGroup,
- setFloorItems: Types.setFloorItemSetState,
- setSimulationStates: (paths: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => void
-): Promise {
- if (!itemsGroup.current) return;
- let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
- const email = localStorage.getItem('email');
- const organization = (email!.split("@")[1]).split(".")[0];
-
- const items = await getFloorAssets(organization);
- localStorage.setItem("FloorItems", JSON.stringify(items));
- await initializeDB();
-
- if (items.message === "floorItems not found") return;
-
- if (items) {
- const storedFloorItems: SimulationTypes.EventData[] = items;
- const loader = new GLTFLoader();
- const dracoLoader = new DRACOLoader();
-
- dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
- loader.setDRACOLoader(dracoLoader);
-
- let modelsLoaded = 0;
- const modelsToLoad = storedFloorItems.length;
-
- const camData = await getCamera(organization, localStorage.getItem('userId')!);
- let storedPosition;
- if (camData && camData.position) {
- storedPosition = camData?.position;
- } else {
- storedPosition = new THREE.Vector3(0, 40, 30);
- }
- if (!storedPosition) return;
- const cameraPosition = new THREE.Vector3(storedPosition.x, storedPosition.y, storedPosition.z);
-
- storedFloorItems.sort((a, b) => {
- const aPosition = new THREE.Vector3(a.position[0], a.position[1], a.position[2]);
- const bPosition = new THREE.Vector3(b.position[0], b.position[1], b.position[2]);
- return cameraPosition.distanceTo(aPosition) - cameraPosition.distanceTo(bPosition);
- });
-
- for (const item of storedFloorItems) {
- if (!item.modelfileID) return;
- const itemPosition = new THREE.Vector3(item.position[0], item.position[1], item.position[2]);
- let storedPosition;
- if (localStorage.getItem("cameraPosition")) {
- storedPosition = JSON.parse(localStorage.getItem("cameraPosition")!);
- } else {
- storedPosition = new THREE.Vector3(0, 40, 30);
- }
-
- const cameraPosition = new THREE.Vector3(storedPosition.x, storedPosition.y, storedPosition.z);
-
- if (cameraPosition.distanceTo(itemPosition) < 50) {
- await new Promise(async (resolve) => {
-
- // Check Three.js Cache
- const cachedModel = THREE.Cache.get(item.modelfileID!);
- if (cachedModel) {
- // console.log(`[Cache] Fetching ${item.modelname}`);
- processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems, setSimulationStates);
- modelsLoaded++;
- checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
- return;
- }
-
- // Check IndexedDB
- const indexedDBModel = await retrieveGLTF(item.modelfileID!);
- if (indexedDBModel) {
- // console.log(`[IndexedDB] Fetching ${item.modelname}`);
- const blobUrl = URL.createObjectURL(indexedDBModel);
- loader.load(blobUrl, (gltf) => {
- URL.revokeObjectURL(blobUrl);
- THREE.Cache.remove(blobUrl);
- THREE.Cache.add(item.modelfileID!, gltf);
- processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, setSimulationStates);
- modelsLoaded++;
- checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
- },
- undefined,
- (error) => {
- toast.error(`[IndexedDB] Error loading ${item.modelname}:`);
- URL.revokeObjectURL(blobUrl);
- resolve();
- }
- );
- return;
- }
-
- // Fetch from Backend
- // console.log(`[Backend] Fetching ${item.modelname}`);
- const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${item.modelfileID!}`;
- loader.load(modelUrl, async (gltf) => {
- 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, setSimulationStates);
- modelsLoaded++;
- checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
- },
- undefined,
- (error) => {
- toast.error(`[Backend] Error loading ${item.modelname}:`);
- resolve();
- }
- );
- });
- } else {
- // console.log(`Item ${item.modelname} is not near`);
- setFloorItems((prevItems) => [
- ...(prevItems || []),
- {
- modeluuid: item.modeluuid,
- modelname: item.modelname,
- position: item.position,
- rotation: item.rotation,
- modelfileID: item.modelfileID,
- isLocked: item.isLocked,
- isVisible: item.isVisible,
- },
- ]);
-
- if (item.eventData) {
- processEventData(item, setSimulationStates);
- }
-
- modelsLoaded++;
- checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, () => { });
- }
- }
-
- // Dispose loader after all models
- dracoLoader.dispose();
- }
-}
-
-
-function processLoadedModel(
- gltf: any,
- item: SimulationTypes.EventData,
- itemsGroup: Types.RefGroup,
- setFloorItems: Types.setFloorItemSetState,
- setSimulationStates: (paths: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => void
-) {
- const model = gltf;
- model.uuid = item.modeluuid;
- model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
- model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid };
- model.position.set(...item.position);
- model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z);
-
- model.traverse((child: any) => {
- if (child.isMesh) {
- // Clone the material to ensure changes are independent
- // child.material = child.material.clone();
-
- child.castShadow = true;
- child.receiveShadow = true;
- }
- });
-
-
- itemsGroup?.current?.add(model);
-
- setFloorItems((prevItems) => [
- ...(prevItems || []),
- {
- modeluuid: item.modeluuid,
- modelname: item.modelname,
- position: item.position,
- rotation: item.rotation,
- modelfileID: item.modelfileID,
- isLocked: item.isLocked,
- isVisible: item.isVisible,
- },
- ]);
-
- if (item.eventData) {
- processEventData(item, setSimulationStates);
- }
-
- 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' });
-}
-
-function processEventData(item: SimulationTypes.EventData, setSimulationStates: any) {
-
- if (item.eventData?.type === 'Conveyor') {
-
- const data: any = item.eventData;
- data.modeluuid = item.modeluuid;
- data.modelName = item.modelname;
- data.position = item.position;
- data.rotation = [item.rotation.x, item.rotation.y, item.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- data as SimulationTypes.ConveyorEventsSchema
- ]);
-
- } else if (item.eventData?.type === 'Vehicle') {
-
- const data: any = item.eventData;
- data.modeluuid = item.modeluuid;
- data.modelName = item.modelname;
- data.position = item.position;
- data.rotation = [item.rotation.x, item.rotation.y, item.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- data as SimulationTypes.VehicleEventsSchema
- ]);
-
- } else if (item.eventData?.type === 'StaticMachine') {
-
- const data: any = item.eventData;
- data.modeluuid = item.modeluuid;
- data.modelName = item.modelname;
- data.position = item.position;
- data.rotation = [item.rotation.x, item.rotation.y, item.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- data as SimulationTypes.StaticMachineEventsSchema
- ]);
-
- } else if (item.eventData?.type === 'ArmBot') {
-
- const data: any = item.eventData;
- data.modeluuid = item.modeluuid;
- data.modelName = item.modelname;
- data.position = item.position;
- data.rotation = [item.rotation.x, item.rotation.y, item.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- data as SimulationTypes.ArmBotEventsSchema
- ]);
-
- }
-}
-
-function checkLoadingCompletion(
- modelsLoaded: number,
- modelsToLoad: number,
- dracoLoader: DRACOLoader,
- resolve: () => void
-) {
- if (modelsLoaded === modelsToLoad) {
- toast.success("Models Loaded!");
- dracoLoader.dispose();
- }
- resolve();
-}
-
+import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
+import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
+import gsap from 'gsap';
+import * as THREE from 'three';
+import * as CONSTANTS from '../../../types/world/worldConstants';
+import { toast } from 'react-toastify';
+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';
+
+async function loadInitialFloorItems(
+ itemsGroup: Types.RefGroup,
+ setFloorItems: Types.setFloorItemSetState,
+): Promise {
+ if (!itemsGroup.current) return;
+ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
+ const email = localStorage.getItem('email');
+ const organization = (email!.split("@")[1]).split(".")[0];
+
+ const items = await getFloorAssets(organization);
+ localStorage.setItem("FloorItems", JSON.stringify(items));
+ await initializeDB();
+
+ if (items.message === "floorItems not found") return;
+
+ if (items) {
+ const storedFloorItems: Types.FloorItems = items;
+ const loader = new GLTFLoader();
+ const dracoLoader = new DRACOLoader();
+
+ dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
+ loader.setDRACOLoader(dracoLoader);
+
+ let modelsLoaded = 0;
+ const modelsToLoad = storedFloorItems.length;
+
+ const camData = await getCamera(organization, localStorage.getItem('userId')!);
+ let storedPosition;
+ if (camData && camData.position) {
+ storedPosition = camData?.position;
+ } else {
+ storedPosition = new THREE.Vector3(0, 40, 30);
+ }
+ if (!storedPosition) return;
+ const cameraPosition = new THREE.Vector3(storedPosition.x, storedPosition.y, storedPosition.z);
+
+ storedFloorItems.sort((a, b) => {
+ const aPosition = new THREE.Vector3(a.position[0], a.position[1], a.position[2]);
+ const bPosition = new THREE.Vector3(b.position[0], b.position[1], b.position[2]);
+ return cameraPosition.distanceTo(aPosition) - cameraPosition.distanceTo(bPosition);
+ });
+
+ for (const item of storedFloorItems) {
+ if (!item.modelfileID) return;
+ const itemPosition = new THREE.Vector3(item.position[0], item.position[1], item.position[2]);
+ let storedPosition;
+ if (localStorage.getItem("cameraPosition")) {
+ storedPosition = JSON.parse(localStorage.getItem("cameraPosition")!);
+ } else {
+ storedPosition = new THREE.Vector3(0, 40, 30);
+ }
+
+ const cameraPosition = new THREE.Vector3(storedPosition.x, storedPosition.y, storedPosition.z);
+
+ if (cameraPosition.distanceTo(itemPosition) < 50) {
+ await new Promise(async (resolve) => {
+
+ // Check Three.js Cache
+ const cachedModel = THREE.Cache.get(item.modelfileID!);
+ if (cachedModel) {
+ // console.log(`[Cache] Fetching ${item.modelname}`);
+ processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems);
+ modelsLoaded++;
+ checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
+ return;
+ }
+
+ // Check IndexedDB
+ const indexedDBModel = await retrieveGLTF(item.modelfileID!);
+ if (indexedDBModel) {
+ // console.log(`[IndexedDB] Fetching ${item.modelname}`);
+ const blobUrl = URL.createObjectURL(indexedDBModel);
+ loader.load(blobUrl, (gltf) => {
+ URL.revokeObjectURL(blobUrl);
+ THREE.Cache.remove(blobUrl);
+ THREE.Cache.add(item.modelfileID!, gltf);
+ processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems);
+ modelsLoaded++;
+ checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
+ },
+ undefined,
+ (error) => {
+ toast.error(`[IndexedDB] Error loading ${item.modelname}:`);
+ URL.revokeObjectURL(blobUrl);
+ resolve();
+ }
+ );
+ return;
+ }
+
+ // Fetch from Backend
+ // console.log(`[Backend] Fetching ${item.modelname}`);
+ const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${item.modelfileID!}`;
+ loader.load(modelUrl, async (gltf) => {
+ 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);
+ modelsLoaded++;
+ checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
+ },
+ undefined,
+ (error) => {
+ toast.error(`[Backend] Error loading ${item.modelname}:`);
+ resolve();
+ }
+ );
+ });
+ } else {
+ // console.log(`Item ${item.modelname} is not near`);
+ setFloorItems((prevItems) => [
+ ...(prevItems || []),
+ {
+ modeluuid: item.modeluuid,
+ modelname: item.modelname,
+ position: item.position,
+ rotation: item.rotation,
+ modelfileID: item.modelfileID,
+ isLocked: item.isLocked,
+ isVisible: item.isVisible,
+ },
+ ]);
+
+ modelsLoaded++;
+ checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, () => { });
+ }
+ }
+
+ // Dispose loader after all models
+ dracoLoader.dispose();
+ }
+}
+
+
+function processLoadedModel(
+ gltf: any,
+ item: Types.FloorItemType,
+ itemsGroup: Types.RefGroup,
+ setFloorItems: Types.setFloorItemSetState,
+) {
+ const model = gltf;
+ model.uuid = item.modeluuid;
+ model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
+ model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid };
+ model.position.set(...item.position);
+ model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z);
+
+ model.traverse((child: any) => {
+ if (child.isMesh) {
+ // Clone the material to ensure changes are independent
+ // child.material = child.material.clone();
+
+ child.castShadow = true;
+ child.receiveShadow = true;
+ }
+ });
+
+
+ itemsGroup?.current?.add(model);
+
+ setFloorItems((prevItems) => [
+ ...(prevItems || []),
+ {
+ modeluuid: item.modeluuid,
+ modelname: item.modelname,
+ position: item.position,
+ rotation: item.rotation,
+ modelfileID: item.modelfileID,
+ isLocked: item.isLocked,
+ isVisible: item.isVisible,
+ },
+ ]);
+
+ 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' });
+}
+
+function checkLoadingCompletion(
+ modelsLoaded: number,
+ modelsToLoad: number,
+ dracoLoader: DRACOLoader,
+ resolve: () => void
+) {
+ if (modelsLoaded === modelsToLoad) {
+ toast.success("Models Loaded!");
+ dracoLoader.dispose();
+ }
+ resolve();
+}
+
export default loadInitialFloorItems;
\ No newline at end of file
diff --git a/app/src/modules/scene/IntialLoad/loadInitialLine.ts b/app/src/modules/builder/IntialLoad/loadInitialLine.ts
similarity index 97%
rename from app/src/modules/scene/IntialLoad/loadInitialLine.ts
rename to app/src/modules/builder/IntialLoad/loadInitialLine.ts
index 231d5aa..f8c3132 100644
--- a/app/src/modules/scene/IntialLoad/loadInitialLine.ts
+++ b/app/src/modules/builder/IntialLoad/loadInitialLine.ts
@@ -1,30 +1,30 @@
-import addLineToScene from '../../builder/geomentries/lines/addLineToScene';
-import * as CONSTANTS from '../../../types/world/worldConstants';
-import * as Types from "../../../types/world/worldTypes";
-
-function loadInitialLine(
- floorPlanGroupLine: Types.RefGroup,
- lines: Types.RefLines
-): void {
-
- if (!floorPlanGroupLine.current) return
-
- ////////// Load the Lines initially if there are any //////////
-
- floorPlanGroupLine.current.children = [];
- lines.current.forEach((line) => {
- let colour;
- if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.wallName) {
- colour = CONSTANTS.lineConfig.wallColor;
- } else if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.floorName) {
- colour = CONSTANTS.lineConfig.floorColor;
- } else if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.aisleName) {
- colour = CONSTANTS.lineConfig.aisleColor;
- }
- if (colour) {
- addLineToScene(line[0][0], line[1][0], colour, line, floorPlanGroupLine);
- }
- });
-}
-
-export default loadInitialLine;
+import addLineToScene from '../../builder/geomentries/lines/addLineToScene';
+import * as CONSTANTS from '../../../types/world/worldConstants';
+import * as Types from "../../../types/world/worldTypes";
+
+function loadInitialLine(
+ floorPlanGroupLine: Types.RefGroup,
+ lines: Types.RefLines
+): void {
+
+ if (!floorPlanGroupLine.current) return
+
+ ////////// Load the Lines initially if there are any //////////
+
+ floorPlanGroupLine.current.children = [];
+ lines.current.forEach((line) => {
+ let colour;
+ if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.wallName) {
+ colour = CONSTANTS.lineConfig.wallColor;
+ } else if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.floorName) {
+ colour = CONSTANTS.lineConfig.floorColor;
+ } else if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.aisleName) {
+ colour = CONSTANTS.lineConfig.aisleColor;
+ }
+ if (colour) {
+ addLineToScene(line[0][0], line[1][0], colour, line, floorPlanGroupLine);
+ }
+ });
+}
+
+export default loadInitialLine;
diff --git a/app/src/modules/scene/IntialLoad/loadInitialPoint.ts b/app/src/modules/builder/IntialLoad/loadInitialPoint.ts
similarity index 97%
rename from app/src/modules/scene/IntialLoad/loadInitialPoint.ts
rename to app/src/modules/builder/IntialLoad/loadInitialPoint.ts
index f042427..7dfdf1d 100644
--- a/app/src/modules/scene/IntialLoad/loadInitialPoint.ts
+++ b/app/src/modules/builder/IntialLoad/loadInitialPoint.ts
@@ -1,87 +1,87 @@
-import * as THREE from 'three';
-
-import * as CONSTANTS from '../../../types/world/worldConstants';
-import * as Types from "../../../types/world/worldTypes";
-
-////////// Load the Boxes initially if there are any //////////
-
-function loadInitialPoint(
- lines: Types.RefLines,
- floorPlanGroupPoint: Types.RefGroup,
- currentLayerPoint: Types.RefMeshArray,
- dragPointControls: Types.RefDragControl
-): void {
-
- if (!floorPlanGroupPoint.current) return
-
- floorPlanGroupPoint.current.children = [];
- currentLayerPoint.current = [];
- lines.current.forEach((line) => {
- const colour = getPointColor(line[0][3]);
- line.forEach((pointData) => {
- const [point, id] = pointData;
-
- /////////// Check if a box with this id already exists //////////
-
- const existingBox = floorPlanGroupPoint.current?.getObjectByProperty('uuid', id);
- if (existingBox) {
- return;
- }
-
- const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale);
- const material = new THREE.ShaderMaterial({
- uniforms: {
- uColor: { value: new THREE.Color(colour) }, // Blue color for the border
- uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square
- },
- vertexShader: `
- varying vec2 vUv;
-
- void main() {
- vUv = uv;
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
- }
- `,
- fragmentShader: `
- varying vec2 vUv;
- uniform vec3 uColor;
- uniform vec3 uInnerColor;
-
- void main() {
- // Define the size of the white square as a proportion of the face
- float borderThickness = 0.2; // Adjust this value for border thickness
- if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness &&
- vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
- gl_FragColor = vec4(uInnerColor, 1.0); // White inner square
- } else {
- gl_FragColor = vec4(uColor, 1.0); // Blue border
- }
- }
- `,
- });
- const box = new THREE.Mesh(geometry, material);
- box.name = "point";
- box.uuid = id;
- box.userData = { type: line[0][3], color: colour };
- box.position.set(point.x, point.y, point.z);
- currentLayerPoint.current.push(box);
-
- floorPlanGroupPoint.current?.add(box);
- });
- });
-
- function getPointColor(lineType: string | undefined): string {
- switch (lineType) {
- case CONSTANTS.lineConfig.wallName: return CONSTANTS.pointConfig.wallOuterColor;
- case CONSTANTS.lineConfig.floorName: return CONSTANTS.pointConfig.floorOuterColor;
- case CONSTANTS.lineConfig.aisleName: return CONSTANTS.pointConfig.aisleOuterColor;
- default: return CONSTANTS.pointConfig.defaultOuterColor;
- }
- }
-
- if (dragPointControls.current) {
- dragPointControls.current!.objects = currentLayerPoint.current;
- }
-}
-
-export default loadInitialPoint;
+import * as THREE from 'three';
+
+import * as CONSTANTS from '../../../types/world/worldConstants';
+import * as Types from "../../../types/world/worldTypes";
+
+////////// Load the Boxes initially if there are any //////////
+
+function loadInitialPoint(
+ lines: Types.RefLines,
+ floorPlanGroupPoint: Types.RefGroup,
+ currentLayerPoint: Types.RefMeshArray,
+ dragPointControls: Types.RefDragControl
+): void {
+
+ if (!floorPlanGroupPoint.current) return
+
+ floorPlanGroupPoint.current.children = [];
+ currentLayerPoint.current = [];
+ lines.current.forEach((line) => {
+ const colour = getPointColor(line[0][3]);
+ line.forEach((pointData) => {
+ const [point, id] = pointData;
+
+ /////////// Check if a box with this id already exists //////////
+
+ const existingBox = floorPlanGroupPoint.current?.getObjectByProperty('uuid', id);
+ if (existingBox) {
+ return;
+ }
+
+ const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale);
+ const material = new THREE.ShaderMaterial({
+ uniforms: {
+ uColor: { value: new THREE.Color(colour) }, // Blue color for the border
+ uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square
+ },
+ vertexShader: `
+ varying vec2 vUv;
+
+ void main() {
+ vUv = uv;
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
+ }
+ `,
+ fragmentShader: `
+ varying vec2 vUv;
+ uniform vec3 uColor;
+ uniform vec3 uInnerColor;
+
+ void main() {
+ // Define the size of the white square as a proportion of the face
+ float borderThickness = 0.2; // Adjust this value for border thickness
+ if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness &&
+ vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
+ gl_FragColor = vec4(uInnerColor, 1.0); // White inner square
+ } else {
+ gl_FragColor = vec4(uColor, 1.0); // Blue border
+ }
+ }
+ `,
+ });
+ const box = new THREE.Mesh(geometry, material);
+ box.name = "point";
+ box.uuid = id;
+ box.userData = { type: line[0][3], color: colour };
+ box.position.set(point.x, point.y, point.z);
+ currentLayerPoint.current.push(box);
+
+ floorPlanGroupPoint.current?.add(box);
+ });
+ });
+
+ function getPointColor(lineType: string | undefined): string {
+ switch (lineType) {
+ case CONSTANTS.lineConfig.wallName: return CONSTANTS.pointConfig.wallOuterColor;
+ case CONSTANTS.lineConfig.floorName: return CONSTANTS.pointConfig.floorOuterColor;
+ case CONSTANTS.lineConfig.aisleName: return CONSTANTS.pointConfig.aisleOuterColor;
+ default: return CONSTANTS.pointConfig.defaultOuterColor;
+ }
+ }
+
+ if (dragPointControls.current) {
+ dragPointControls.current!.objects = currentLayerPoint.current;
+ }
+}
+
+export default loadInitialPoint;
diff --git a/app/src/modules/scene/IntialLoad/loadInitialWallItems.ts b/app/src/modules/builder/IntialLoad/loadInitialWallItems.ts
similarity index 97%
rename from app/src/modules/scene/IntialLoad/loadInitialWallItems.ts
rename to app/src/modules/builder/IntialLoad/loadInitialWallItems.ts
index c5184bb..34273af 100644
--- a/app/src/modules/scene/IntialLoad/loadInitialWallItems.ts
+++ b/app/src/modules/builder/IntialLoad/loadInitialWallItems.ts
@@ -1,54 +1,54 @@
-import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
-
-import * as Types from "../../../types/world/worldTypes";
-import { getWallItems } from '../../../services/factoryBuilder/assest/wallAsset/getWallItemsApi';
-
-////////// Load the Wall Items's intially of there is any //////////
-
-async function loadInitialWallItems(
- setWallItems: Types.setWallItemSetState,
- AssetConfigurations: Types.AssetConfigurations
-): Promise {
-
- const email = localStorage.getItem('email')
- const organization = (email!.split("@")[1]).split(".")[0];
-
- const items = await getWallItems(organization);
-
- localStorage.setItem("WallItems", JSON.stringify(items));
- if (items.length > 0) {
- const storedWallItems: Types.wallItems = items;
-
- const loadedWallItems = await Promise.all(storedWallItems.map(async (item) => {
- const loader = new GLTFLoader();
- return new Promise((resolve) => {
- loader.load(AssetConfigurations[item.modelname!].modelUrl, (gltf) => {
- const model = gltf.scene;
- model.uuid = item.modeluuid!;
-
- model.children[0].children.forEach((child: any) => {
- if (child.name !== "CSG_REF") {
- child.castShadow = true;
- child.receiveShadow = true;
- }
- });
-
- resolve({
- type: item.type,
- model: model,
- modelname: item.modelname,
- scale: item.scale,
- csgscale: item.csgscale,
- csgposition: item.csgposition,
- position: item.position,
- quaternion: item.quaternion,
- });
- });
- });
- }));
-
- setWallItems(loadedWallItems);
- }
-}
-
-export default loadInitialWallItems;
+import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
+
+import * as Types from "../../../types/world/worldTypes";
+import { getWallItems } from '../../../services/factoryBuilder/assest/wallAsset/getWallItemsApi';
+
+////////// Load the Wall Items's intially of there is any //////////
+
+async function loadInitialWallItems(
+ setWallItems: Types.setWallItemSetState,
+ AssetConfigurations: Types.AssetConfigurations
+): Promise {
+
+ const email = localStorage.getItem('email')
+ const organization = (email!.split("@")[1]).split(".")[0];
+
+ const items = await getWallItems(organization);
+
+ localStorage.setItem("WallItems", JSON.stringify(items));
+ if (items.length > 0) {
+ const storedWallItems: Types.wallItems = items;
+
+ const loadedWallItems = await Promise.all(storedWallItems.map(async (item) => {
+ const loader = new GLTFLoader();
+ return new Promise((resolve) => {
+ loader.load(AssetConfigurations[item.modelname!].modelUrl, (gltf) => {
+ const model = gltf.scene;
+ model.uuid = item.modeluuid!;
+
+ model.children[0].children.forEach((child: any) => {
+ if (child.name !== "CSG_REF") {
+ child.castShadow = true;
+ child.receiveShadow = true;
+ }
+ });
+
+ resolve({
+ type: item.type,
+ model: model,
+ modelname: item.modelname,
+ scale: item.scale,
+ csgscale: item.csgscale,
+ csgposition: item.csgposition,
+ position: item.position,
+ quaternion: item.quaternion,
+ });
+ });
+ });
+ }));
+
+ setWallItems(loadedWallItems);
+ }
+}
+
+export default loadInitialWallItems;
diff --git a/app/src/modules/builder/agv/agv.tsx b/app/src/modules/builder/agv/agv.tsx
deleted file mode 100644
index faa344b..0000000
--- a/app/src/modules/builder/agv/agv.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import { useEffect, useRef, useState } from "react";
-import { Line } from "@react-three/drei";
-import {
- useNavMesh,
- usePlayAgv,
- useSimulationStates,
-} from "../../../store/store";
-import PathNavigator from "./pathNavigator";
-import { useAnimationPlaySpeed, usePlayButtonStore, useResetButtonStore } from "../../../store/usePlayButtonStore";
-
-type PathPoints = {
- modelUuid: string;
- modelSpeed: number;
- bufferTime: number;
- points: { x: number; y: number; z: number }[];
- hitCount: number;
-};
-interface ProcessContainerProps {
- processes: any[];
- agvRef: any;
- MaterialRef: any;
-}
-
-const Agv: React.FC = ({
- processes,
- agvRef,
- MaterialRef,
-}) => {
- const [pathPoints, setPathPoints] = useState([]);
- const { simulationStates } = useSimulationStates();
- const { navMesh } = useNavMesh();
- const { isPlaying } = usePlayButtonStore();
- const { isReset, setReset } = useResetButtonStore();
- const { speed } = useAnimationPlaySpeed();
- const globalSpeed = useRef(1);
-
- useEffect(() => { globalSpeed.current = speed }, [speed])
-
- useEffect(() => {
- if (!isPlaying || isReset) {
- agvRef.current = [];
- }
- }, [isPlaying, isReset])
-
- useEffect(() => {
- if (simulationStates.length > 0) {
- const agvModels = simulationStates.filter(
- (val) => val.modelName === "agv" && val.type === "Vehicle"
- );
-
- const newPathPoints = agvModels
- .filter(
- (model: any) =>
- model.points &&
- model.points.actions &&
- typeof model.points.actions.start === "object" &&
- typeof model.points.actions.end === "object" &&
- "x" in model.points.actions.start &&
- "y" in model.points.actions.start &&
- "x" in model.points.actions.end &&
- "y" in model.points.actions.end
- )
- .map((model: any) => ({
- modelUuid: model.modeluuid,
- modelSpeed: model.points.speed,
- bufferTime: model.points.actions.buffer,
- hitCount: model.points.actions.hitCount,
- points: [
- { x: model.position[0], y: model.position[1], z: model.position[2], },
- { x: model.points.actions.start.x, y: 0, z: model.points.actions.start.y, },
- { x: model.points.actions.end.x, y: 0, z: model.points.actions.end.y, },
- ],
- }));
-
- setPathPoints(newPathPoints);
- }
- }, [simulationStates]);
-
- return (
- <>
- {pathPoints.map((pair, i) => (
-
-
-
- {pair.points.slice(1).map((point, idx) => (
-
-
-
-
- ))}
-
- ))}
- >
- );
-};
-
-export default Agv;
diff --git a/app/src/modules/builder/agv/navMeshCreator.tsx b/app/src/modules/builder/agv/navMeshCreator.tsx
deleted file mode 100644
index c0f8808..0000000
--- a/app/src/modules/builder/agv/navMeshCreator.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { useRef } from "react";
-import { useNavMesh } from "../../../store/store";
-import PolygonGenerator from "./polygonGenerator";
-import NavMeshDetails from "./navMeshDetails";
-import * as CONSTANTS from "../../../types/world/worldConstants";
-import * as Types from "../../../types/world/worldTypes";
-
-type NavMeshCreatorProps = {
- lines: Types.RefLines
-};
-
-function NavMeshCreator({ lines }: NavMeshCreatorProps) {
- let groupRef = useRef() as Types.RefGroup;
- const { setNavMesh } = useNavMesh();
-
- return (
- <>
-
-
-
-
-
-
-
-
-
- >
- )
-}
-
-export default NavMeshCreator
\ No newline at end of file
diff --git a/app/src/modules/builder/agv/navMeshDetails.tsx b/app/src/modules/builder/agv/navMeshDetails.tsx
deleted file mode 100644
index 697d89b..0000000
--- a/app/src/modules/builder/agv/navMeshDetails.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import React, { useEffect, useState } from "react";
-import { init as initRecastNavigation } from "@recast-navigation/core";
-import { generateSoloNavMesh } from "@recast-navigation/generators";
-import { DebugDrawer, getPositionsAndIndices } from "@recast-navigation/three";
-import { useThree } from "@react-three/fiber";
-import * as THREE from "three";
-import * as Types from "../../../types/world/worldTypes";
-
-interface NavMeshDetailsProps {
- setNavMesh: (navMesh: any) => void;
- groupRef: React.MutableRefObject;
- lines: Types.RefLines;
-}
-
-export default function NavMeshDetails({
- lines,
- setNavMesh,
- groupRef,
-}: NavMeshDetailsProps) {
- const { scene } = useThree();
-
- useEffect(() => {
- const initializeNavigation = async () => {
- try {
- await initRecastNavigation();
-
- if (!groupRef.current || groupRef.current.children.length === 0) {
- return;
- }
-
- const meshes = groupRef?.current?.children as THREE.Mesh[];
-
- const [positions, indices] = getPositionsAndIndices(meshes);
-
- const cellSize = 0.2;
- const cellHeight = 0.7;
- const walkableRadius = 0.5;
- const { success, navMesh } = generateSoloNavMesh(positions, indices, {
- cs: cellSize,
- ch: cellHeight,
- walkableRadius: Math.round(walkableRadius / cellHeight),
- });
-
- if (!success || !navMesh) {
- return;
- }
-
- setNavMesh(navMesh);
-
- scene.children
- .filter((child) => child instanceof DebugDrawer)
- .forEach((child) => scene.remove(child));
-
- const debugDrawer = new DebugDrawer();
- debugDrawer.drawNavMesh(navMesh);
- // scene.add(debugDrawer);
- } catch (error) { }
- };
-
- initializeNavigation();
- }, [scene, groupRef, lines.current]);
-
- return null;
-}
diff --git a/app/src/modules/builder/agv/pathNavigator.tsx b/app/src/modules/builder/agv/pathNavigator.tsx
deleted file mode 100644
index c1aac29..0000000
--- a/app/src/modules/builder/agv/pathNavigator.tsx
+++ /dev/null
@@ -1,480 +0,0 @@
-import React, { useEffect, useState, useRef, useMemo } from "react";
-import * as THREE from "three";
-import { useFrame, useThree } from "@react-three/fiber";
-import { NavMeshQuery } from "@recast-navigation/core";
-import { Line } from "@react-three/drei";
-import {
- useAnimationPlaySpeed,
- usePlayButtonStore,
-} from "../../../store/usePlayButtonStore";
-import { usePlayAgv } from "../../../store/store";
-
-interface PathNavigatorProps {
- navMesh: any;
- pathPoints: any;
- id: string;
- speed: number;
- globalSpeed: number;
- bufferTime: number;
- hitCount: number;
- processes: any[];
- agvRef: any;
- MaterialRef: any;
-}
-interface AGVData {
- processId: string;
- vehicleId: string;
- hitCount: number;
- totalHits: number;
-}
-type Phase = "initial" | "toDrop" | "toPickup";
-type MaterialType = "Box" | "Crate";
-export default function PathNavigator({
- navMesh,
- pathPoints,
- id,
- speed,
- globalSpeed,
- bufferTime,
- hitCount,
- processes,
- agvRef,
- MaterialRef,
-}: PathNavigatorProps) {
- const [currentPhase, setCurrentPhase] = useState("initial");
- const [path, setPath] = useState<[number, number, number][]>([]);
- const [toPickupPath, setToPickupPath] = useState<[number, number, number][]>(
- []
- );
- const [pickupDropPath, setPickupDropPath] = useState<
- [number, number, number][]
- >([]);
- const [dropPickupPath, setDropPickupPath] = useState<
- [number, number, number][]
- >([]);
- const [initialPosition, setInitialPosition] = useState(
- null
- );
- const [initialRotation, setInitialRotation] = useState(
- null
- );
- const [boxVisible, setBoxVisible] = useState(false);
-
- const distancesRef = useRef([]);
- const totalDistanceRef = useRef(0);
- const progressRef = useRef(0);
- const isWaiting = useRef(false);
- const timeoutRef = useRef(null);
- const hasStarted = useRef(false);
- const hasReachedPickup = useRef(false);
-
- const { scene } = useThree();
- const { isPlaying } = usePlayButtonStore();
- const { PlayAgv, setPlayAgv } = usePlayAgv();
-
- const boxRef = useRef(null);
-
- const baseMaterials = useMemo(
- () => ({
- Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
- Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
- Default: new THREE.MeshStandardMaterial({ color: 0xcccccc }),
- }),
- []
- );
-
- useEffect(() => {
- const object = scene.getObjectByProperty("uuid", id);
- if (object) {
- setInitialPosition(object.position.clone());
- setInitialRotation(object.rotation.clone());
- }
- }, [scene, id]);
-
- const computePath = (start: any, end: any) => {
- try {
- const navMeshQuery = new NavMeshQuery(navMesh);
- const { path: segmentPath } = navMeshQuery.computePath(start, end);
- return (
- segmentPath?.map(
- ({ x, y, z }) => [x, y + 0.1, z] as [number, number, number]
- ) || []
- );
- } catch {
- return [];
- }
- };
-
- const resetState = () => {
- if (timeoutRef.current) {
- clearTimeout(timeoutRef.current);
- timeoutRef.current = null;
- }
-
- setPath([]);
- setCurrentPhase("initial");
- setToPickupPath([]);
- setPickupDropPath([]);
- setDropPickupPath([]);
- setBoxVisible(false);
- distancesRef.current = [];
- totalDistanceRef.current = 0;
- progressRef.current = 0;
- isWaiting.current = false;
- hasStarted.current = false;
- hasReachedPickup.current = false;
-
- if (initialPosition && initialRotation) {
- const object = scene.getObjectByProperty("uuid", id);
- if (object) {
- object.position.copy(initialPosition);
- object.rotation.copy(initialRotation);
- }
- }
- };
-
- useEffect(() => {
- if (!isPlaying) {
- resetState();
- }
-
- if (!navMesh || pathPoints.length < 2) return;
-
- const [pickup, drop] = pathPoints.slice(-2);
-
- const object = scene.getObjectByProperty("uuid", id);
- if (!object) return;
-
- const currentPosition = object.position;
-
- const toPickupPath = computePath(currentPosition, pickup);
- const pickupToDropPath = computePath(pickup, drop);
- const dropToPickupPath = computePath(drop, pickup);
-
- if (
- toPickupPath.length &&
- pickupToDropPath.length &&
- dropToPickupPath.length
- ) {
- setPickupDropPath(pickupToDropPath);
- setDropPickupPath(dropToPickupPath);
- setToPickupPath(toPickupPath);
- setPath(toPickupPath);
- setCurrentPhase("initial");
- }
- }, [navMesh, pathPoints, hitCount, isPlaying, PlayAgv]);
-
- useEffect(() => {
- if (path.length < 2) return;
-
- let total = 0;
- const segmentDistances = path.slice(0, -1).map((point, i) => {
- const dist = new THREE.Vector3(...point).distanceTo(
- new THREE.Vector3(...path[i + 1])
- );
- total += dist;
- return dist;
- });
-
- distancesRef.current = segmentDistances;
- totalDistanceRef.current = total;
- progressRef.current = 0;
- isWaiting.current = false;
- }, [path]);
-
- function logAgvStatus(id: string, status: string) {
- // console.log(
- // `AGV ${id}: ${status}`
-
- // );
- }
-
- function findProcessByTargetModelUUID(processes: any, targetModelUUID: any) {
- for (const process of processes) {
- for (const path of process.paths) {
- for (const point of path.points) {
- if (
- point.connections?.targets?.some(
- (target: any) => target.modelUUID === targetModelUUID
- )
- ) {
- return process.id;
- }
- }
- }
- }
- return null;
- }
-
- useEffect(() => {
- if (!scene || !boxRef || !processes || !MaterialRef.current) return;
-
- const existingObject = scene.getObjectByProperty("uuid", id);
- if (!existingObject) return;
-
- if (boxRef.current?.parent) {
- boxRef.current.parent.remove(boxRef.current);
- boxRef.current = null;
- }
-
- if (boxVisible) {
- const matchedProcess = findProcessByTargetModelUUID(processes, id);
- let materialType: "Box" | "Crate" | "Default" = "Default";
-
- if (matchedProcess) {
- const materialEntry = MaterialRef.current.find((item: any) =>
- item.objects.some((obj: any) => obj.processId === matchedProcess)
- );
- if (materialEntry) {
- materialType = materialEntry.material;
- }
- }
-
- const boxGeometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
- const boxMesh = new THREE.Mesh(boxGeometry, baseMaterials[materialType]);
- boxMesh.position.y = 1;
- boxMesh.name = `box-${id}`;
- existingObject.add(boxMesh);
- boxRef.current = boxMesh;
- }
-
- return () => {
- if (boxRef.current?.parent) {
- boxRef.current.parent.remove(boxRef.current);
- }
- };
- }, [processes, MaterialRef, boxVisible, scene, id, baseMaterials]);
-
- useFrame((_, delta) => {
- const currentAgv = (agvRef.current || []).find(
- (agv: AGVData) => agv.vehicleId === id
- );
-
- if (!scene || !id || !isPlaying) return;
-
- const object = scene.getObjectByProperty("uuid", id);
- if (!object) return;
-
- if (isPlaying && !hasStarted.current) {
- hasStarted.current = false;
- progressRef.current = 0;
- isWaiting.current = false;
- if (timeoutRef.current) {
- clearTimeout(timeoutRef.current);
- timeoutRef.current = null;
- }
- }
-
- const isAgvReady = () => {
- if (!agvRef.current || agvRef.current.length === 0) return false;
- if (!currentAgv) return false;
-
- return currentAgv.isActive && hitCount >= currentAgv.maxHitCount;
- };
-
- if (isPlaying && !hasStarted.current && toPickupPath.length > 0) {
- setBoxVisible(false);
- const startPoint = new THREE.Vector3(...toPickupPath[0]);
- object.position.copy(startPoint);
-
- if (toPickupPath.length > 1) {
- const nextPoint = new THREE.Vector3(...toPickupPath[1]);
- const direction = nextPoint.clone().sub(startPoint).normalize();
- object.rotation.y = Math.atan2(direction.x, direction.z);
- }
-
- hasStarted.current = true;
- progressRef.current = 0;
- hasReachedPickup.current = false;
- setToPickupPath(toPickupPath.slice(-1));
- logAgvStatus(id, "Started from station, heading to pickup");
- return;
- }
-
- if (isPlaying && currentPhase === "initial" && !hasReachedPickup.current) {
- const reached = moveAlongPath(
- object,
- path,
- distancesRef.current,
- speed,
- delta,
- progressRef
- );
-
- if (reached) {
- hasReachedPickup.current = true;
- if (currentAgv) {
- currentAgv.status = "picking";
- }
- logAgvStatus(id, "Reached pickup point, Waiting for material");
- }
- return;
- }
-
- if (isPlaying && currentAgv?.isActive && currentPhase === "initial") {
- if (!isAgvReady()) return;
- setTimeout(() => {
- setBoxVisible(true);
- setPath([...pickupDropPath]);
- setCurrentPhase("toDrop");
- progressRef.current = 0;
- logAgvStatus(id, "Started from pickup point, heading to drop point");
- if (currentAgv) {
- currentAgv.status = "toDrop";
- }
- }, 0);
- return;
- }
-
- if (isPlaying && currentPhase === "toDrop") {
- const reached = moveAlongPath(
- object,
- path,
- distancesRef.current,
- speed,
- delta,
- progressRef
- );
-
- if (reached && !isWaiting.current) {
- isWaiting.current = true;
- logAgvStatus(id, "Reached drop point");
- if (currentAgv) {
- currentAgv.status = "droping";
- currentAgv.hitCount = currentAgv.hitCount--;
- }
- timeoutRef.current = setTimeout(() => {
- setPath([...dropPickupPath]);
- setCurrentPhase("toPickup");
- progressRef.current = 0;
- isWaiting.current = false;
- setBoxVisible(false);
- if (currentAgv) {
- currentAgv.status = "toPickup";
- }
- logAgvStatus(
- id,
- "Started from droping point, heading to pickup point"
- );
- }, bufferTime * 1000);
- }
- return;
- }
-
- if (isPlaying && currentPhase === "toPickup") {
- const reached = moveAlongPath(
- object,
- path,
- distancesRef.current,
- speed,
- delta,
- progressRef
- );
-
- if (reached) {
- if (currentAgv) {
- currentAgv.isActive = false;
- }
- setCurrentPhase("initial");
- if (currentAgv) {
- currentAgv.status = "picking";
- }
- logAgvStatus(id, "Reached pickup point again, cycle complete");
- }
- return;
- }
-
- moveAlongPath(
- object,
- path,
- distancesRef.current,
- speed,
- delta,
- progressRef
- );
- });
-
- function moveAlongPath(
- object: THREE.Object3D,
- path: [number, number, number][],
- distances: number[],
- speed: number,
- delta: number,
- progressRef: React.MutableRefObject
- ): boolean {
- if (path.length < 2) return false;
-
- progressRef.current += delta * (speed * globalSpeed);
- let covered = progressRef.current;
- let accumulated = 0;
- let index = 0;
-
- for (; index < distances.length; index++) {
- const dist = distances[index];
- if (accumulated + dist >= covered) break;
- accumulated += dist;
- }
-
- if (index >= path.length - 1) {
- if (path.length > 1) {
- const lastDirection = new THREE.Vector3(...path[path.length - 1])
- .sub(new THREE.Vector3(...path[path.length - 2]))
- .normalize();
- object.rotation.y = Math.atan2(lastDirection.x, lastDirection.z);
- }
- return true;
- }
-
- const start = new THREE.Vector3(...path[index]);
- const end = new THREE.Vector3(...path[index + 1]);
- const dist = distances[index];
-
- const t = THREE.MathUtils.clamp((covered - accumulated) / dist, 0, 1);
- object.position.copy(start.clone().lerp(end, t));
-
- if (dist > 0.1) {
- const targetDirection = end.clone().sub(start).normalize();
- const targetRotationY = Math.atan2(targetDirection.x, targetDirection.z);
-
- const rotationSpeed = Math.min(5 * delta, 1);
- object.rotation.y = THREE.MathUtils.lerp(
- object.rotation.y,
- targetRotationY,
- rotationSpeed
- );
- }
-
- return false;
- }
-
- useEffect(() => {
- return () => {
- if (timeoutRef.current) {
- clearTimeout(timeoutRef.current);
- }
- };
- }, []);
-
- return (
-
- {toPickupPath.length > 0 && (
-
- )}
-
- {pickupDropPath.length > 0 && (
-
- )}
-
- {dropPickupPath.length > 0 && (
-
- )}
-
- );
-}
diff --git a/app/src/modules/builder/agv/polygonGenerator.tsx b/app/src/modules/builder/agv/polygonGenerator.tsx
deleted file mode 100644
index 2462018..0000000
--- a/app/src/modules/builder/agv/polygonGenerator.tsx
+++ /dev/null
@@ -1,118 +0,0 @@
-import * as THREE from "three";
-import { useEffect, useState } from "react";
-import * as turf from "@turf/turf";
-import * as Types from "../../../types/world/worldTypes";
-import arrayLinesToObject from "../geomentries/lines/lineConvertions/arrayLinesToObject";
-interface PolygonGeneratorProps {
- groupRef: React.MutableRefObject;
- lines: Types.RefLines;
-}
-
-export default function PolygonGenerator({
- groupRef,
- lines,
-}: PolygonGeneratorProps) {
-
- useEffect(() => {
- let allLines = arrayLinesToObject(lines.current);
- const wallLines = allLines?.filter((line) => line?.type === "WallLine");
- const aisleLines = allLines?.filter((line) => line?.type === "AisleLine");
-
- const wallPoints = wallLines
- .map((pair) => pair?.line.map((vals) => vals.position))
- .filter((wall): wall is THREE.Vector3[] => !!wall);
-
- const result = aisleLines.map((pair) =>
- pair?.line.map((point) => ({
- position: [point.position.x, point.position.z],
- uuid: point.uuid,
- }))
- );
-
- if (!result || result.some((line) => !line)) {
- return;
- }
-
- const lineFeatures = result?.map((line: any) =>
- turf.lineString(line.map((p: any) => p?.position))
- );
-
- const polygons = turf.polygonize(turf.featureCollection(lineFeatures));
- renderWallGeometry(wallPoints);
-
- if (polygons.features.length > 1) {
- polygons.features.forEach((feature) => {
- if (feature.geometry.type === "Polygon") {
-
- const shape = new THREE.Shape();
- const coords = feature.geometry.coordinates[0];
-
- shape.moveTo(coords[0][0], coords[0][1]);
-
- for (let i = 1; i < coords.length; i++) {
- shape.lineTo(coords[i][0], coords[i][1]);
- }
- 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);
- }
- });
- }
-
- }, [lines.current]);
-
- const renderWallGeometry = (walls: THREE.Vector3[][]) => {
- walls.forEach((wall) => {
- if (wall.length < 2) return;
-
- for (let i = 0; i < wall.length - 1; i++) {
- const start = new THREE.Vector3(wall[i].x, wall[i].y, wall[i].z);
- const end = new THREE.Vector3(
- wall[i + 1].x,
- wall[i + 1].y,
- wall[i + 1].z
- );
-
- const wallHeight = 10;
- const direction = new THREE.Vector3().subVectors(end, start);
- const length = direction.length();
- direction.normalize();
-
- const wallGeometry = new THREE.BoxGeometry(length, wallHeight);
- const wallMaterial = new THREE.MeshBasicMaterial({
- color: "#aaa",
- transparent: true,
- opacity: 0.5,
- });
-
- const wallMesh = new THREE.Mesh(wallGeometry, wallMaterial);
- const midPoint = new THREE.Vector3()
- .addVectors(start, end)
- .multiplyScalar(0.5);
- wallMesh.position.set(midPoint.x, wallHeight / 2, midPoint.z);
-
- const quaternion = new THREE.Quaternion();
- quaternion.setFromUnitVectors(new THREE.Vector3(1, 0, 0), direction);
- wallMesh.quaternion.copy(quaternion);
-
- groupRef.current?.add(wallMesh);
- }
- });
- };
-
- return null;
-}
diff --git a/app/src/modules/scene/world/world.tsx b/app/src/modules/builder/builder.tsx
similarity index 88%
rename from app/src/modules/scene/world/world.tsx
rename to app/src/modules/builder/builder.tsx
index dcd1adb..cfc5dcd 100644
--- a/app/src/modules/scene/world/world.tsx
+++ b/app/src/modules/builder/builder.tsx
@@ -1,374 +1,373 @@
-////////// Three and React Three Fiber Imports //////////
-
-import * as THREE from "three";
-import { useEffect, useRef, useState } from "react";
-import { useThree, useFrame } from "@react-three/fiber";
-
-////////// Component Imports //////////
-
-import DistanceText from "../../builder/geomentries/lines/distanceText/distanceText";
-import ReferenceDistanceText from "../../builder/geomentries/lines/distanceText/referenceDistanceText";
-
-////////// Assests Imports //////////
-
-import arch from "../../../assets/gltf-glb/arch.glb";
-import door from "../../../assets/gltf-glb/door.glb";
-import Window from "../../../assets/gltf-glb/window.glb";
-
-////////// Zustand State Imports //////////
-
-import {
- useToggleView,
- useDeletePointOrLine,
- useMovePoint,
- useActiveLayer,
- useSocketStore,
- useWallVisibility,
- useRoofVisibility,
- useShadows,
- useUpdateScene,
- useWalls,
- useToolMode,
- useRefTextUpdate,
- useRenderDistance,
- useLimitDistance,
-} from "../../../store/store";
-
-////////// 3D Function Imports //////////
-
-import loadWalls from "../../builder/geomentries/walls/loadWalls";
-
-import * as Types from "../../../types/world/worldTypes";
-
-import SocketResponses from "../../collaboration/socketResponses.dev";
-import FloorItemsGroup from "../../builder/groups/floorItemsGroup";
-import FloorPlanGroup from "../../builder/groups/floorPlanGroup";
-import FloorGroup from "../../builder/groups/floorGroup";
-import FloorGroupAilse from "../../builder/groups/floorGroupAisle";
-import Draw from "../../builder/functions/draw";
-import WallsAndWallItems from "../../builder/groups/wallsAndWallItems";
-import Ground from "../environment/ground";
-// import ZoneGroup from "../groups/zoneGroup1";
-import { findEnvironment } from "../../../services/factoryBuilder/environment/findEnvironment";
-import Layer2DVisibility from "../../builder/geomentries/layers/layer2DVisibility";
-import DrieHtmlTemp from "../mqttTemp/drieHtmlTemp";
-import ZoneGroup from "../../builder/groups/zoneGroup";
-import useModuleStore from "../../../store/useModuleStore";
-import NavMeshCreator from "../../builder/agv/navMeshCreator";
-
-export default function World() {
- const state = useThree(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
- const csg = useRef(); // Reference for CSG object, used for 3D modeling.
- const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects.
- const scene = useRef() as Types.RefScene; // Reference to the scene.
- const camera = useRef() as Types.RefCamera; // Reference to the camera object.
- const controls = useRef(); // Reference to the controls object.
- const raycaster = useRef() as Types.RefRaycaster; // Reference for raycaster used for detecting objects being pointed at in the scene.
- const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control.
-
- // Assigning the scene and camera from the Three.js state to the references.
-
- scene.current = state.scene;
- camera.current = state.camera;
- controls.current = state.controls;
- raycaster.current = state.raycaster;
-
- const plane = useRef(null); // Reference for a plane object for raycaster reference.
- const grid = useRef() as any; // Reference for a grid object for raycaster reference.
- const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line.
- const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end).
- const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc...
- const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active.
- const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point.
- const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start).
- const tempLoader = useRef() as Types.RefMesh; // Reference for a temporary loader for the floor items.
- const isTempLoader = useRef() as Types.RefBoolean; // Reference to check if a temporary loader is active.
- const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation.
- const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn.
- const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn.
- const onlyFloorline = useRef([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn.
- const onlyFloorlines = useRef([]); // Reference for all the floor lines that are ever drawn.
- const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw.
- const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not.
- const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed.
- const itemsGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the floor items (Gltf).
- const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors.
- const AttachedObject = useRef() as Types.RefMesh; // Reference for an object that is attached using dbl click for transform controls rotation.
- const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group.
- const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn.
- const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created.
- const floorGroupAisle = useRef() as Types.RefGroup;
- const zoneGroup = useRef() as Types.RefGroup;
- const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls.
- const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted.
- const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted.
- const hoveredDeletableFloorItem = useRef() as Types.RefMesh; // Reference for the currently hovered floor item that can be deleted.
- const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted.
- const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted.
- const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc...
-
- const cursorPosition = new THREE.Vector3(); // 3D vector for storing the cursor position.
-
- const [selectedItemsIndex, setSelectedItemsIndex] = useState(null); // State for tracking the index of the selected item.
- const { activeLayer, setActiveLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx.
- const { toggleView, setToggleView } = useToggleView(); // State for toggling between 2D and 3D.
- const { toolMode, setToolMode } = useToolMode();
- const { movePoint, setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not.
- const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
- const { socket } = useSocketStore();
- const { roofVisibility, setRoofVisibility } = useRoofVisibility();
- const { wallVisibility, setWallVisibility } = useWallVisibility();
- const { shadows, setShadows } = useShadows();
- const { renderDistance, setRenderDistance } = useRenderDistance();
- const { limitDistance, setLimitDistance } = useLimitDistance();
- const { updateScene, setUpdateScene } = useUpdateScene();
- const { walls, setWalls } = useWalls();
- const { refTextupdate, setRefTextUpdate } = useRefTextUpdate();
- const { activeModule } = useModuleStore();
-
- // const loader = new GLTFLoader();
- // const dracoLoader = new DRACOLoader();
-
- // dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
- // loader.setDRACOLoader(dracoLoader);
-
- ////////// Assest Configuration Values //////////
-
- const AssetConfigurations: Types.AssetConfigurations = {
- arch: {
- modelUrl: arch,
- scale: [0.75, 0.75, 0.75],
- csgscale: [2, 4, 0.5],
- csgposition: [0, 2, 0],
- positionY: () => 0,
- type: "Fixed-Move",
- },
- door: {
- modelUrl: door,
- scale: [0.75, 0.75, 0.75],
- csgscale: [2, 4, 0.5],
- csgposition: [0, 2, 0],
- positionY: () => 0,
- type: "Fixed-Move",
- },
- window: {
- modelUrl: Window,
- scale: [0.75, 0.75, 0.75],
- csgscale: [5, 3, 0.5],
- csgposition: [0, 1.5, 0],
- positionY: (intersectionPoint) => intersectionPoint.point.y,
- type: "Free-Move",
- },
- };
-
- ////////// All Toggle's //////////
-
- useEffect(() => {
- setRefTextUpdate((prevUpdate: number) => prevUpdate - 1);
- if (dragPointControls.current) {
- dragPointControls.current.enabled = false;
- }
- if (toggleView) {
- Layer2DVisibility(
- activeLayer,
- floorPlanGroup,
- floorPlanGroupLine,
- floorPlanGroupPoint,
- currentLayerPoint,
- dragPointControls
- );
- } else {
- setToolMode(null);
- setDeletePointOrLine(false);
- setMovePoint(false);
- loadWalls(lines, setWalls);
- setUpdateScene(true);
- line.current = [];
- }
- }, [toggleView]);
-
- useEffect(() => {
- THREE.Cache.clear();
- THREE.Cache.enabled = true;
- }, []);
-
- useEffect(() => {
- const email = localStorage.getItem("email");
- const organization = email!.split("@")[1].split(".")[0];
-
- async function fetchVisibility() {
- const visibility = await findEnvironment(
- organization,
- localStorage.getItem("userId")!
- );
- if (visibility) {
- setRoofVisibility(visibility.roofVisibility);
- setWallVisibility(visibility.wallVisibility);
- setShadows(visibility.shadowVisibility);
- setRenderDistance(visibility.renderDistance);
- setLimitDistance(visibility.limitDistance);
- }
- }
- fetchVisibility();
- }, []);
-
- ////////// UseFrame is Here //////////
-
- useFrame(() => {
- if (toolMode) {
- Draw(
- state,
- plane,
- cursorPosition,
- floorPlanGroupPoint,
- floorPlanGroupLine,
- snappedPoint,
- isSnapped,
- isSnappedUUID,
- line,
- lines,
- ispreSnapped,
- floorPlanGroup,
- ReferenceLineMesh,
- LineCreated,
- setRefTextUpdate,
- Tube,
- anglesnappedPoint,
- isAngleSnapped,
- toolMode
- );
- }
- });
-
- ////////// Return //////////
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* */}
-
-
-
-
-
- {/* */}
-
-
-
- >
- );
-}
+////////// Three and React Three Fiber Imports //////////
+
+import * as THREE from "three";
+import { useEffect, useRef, useState } from "react";
+import { useThree, useFrame } from "@react-three/fiber";
+
+////////// Component Imports //////////
+
+import DistanceText from "./geomentries/lines/distanceText/distanceText";
+import ReferenceDistanceText from "./geomentries/lines/distanceText/referenceDistanceText";
+
+////////// Assests Imports //////////
+
+import arch from "../../assets/gltf-glb/arch.glb";
+import door from "../../assets/gltf-glb/door.glb";
+import Window from "../../assets/gltf-glb/window.glb";
+
+////////// Zustand State Imports //////////
+
+import {
+ useToggleView,
+ useDeletePointOrLine,
+ useMovePoint,
+ useActiveLayer,
+ useSocketStore,
+ useWallVisibility,
+ useRoofVisibility,
+ useShadows,
+ useUpdateScene,
+ useWalls,
+ useToolMode,
+ useRefTextUpdate,
+ useRenderDistance,
+ useLimitDistance,
+} from "../../store/store";
+
+////////// 3D Function Imports //////////
+
+import loadWalls from "./geomentries/walls/loadWalls";
+
+import * as Types from "../../types/world/worldTypes";
+
+import SocketResponses from "../collaboration/socketResponses.dev";
+import FloorItemsGroup from "./groups/floorItemsGroup";
+import FloorPlanGroup from "./groups/floorPlanGroup";
+import FloorGroup from "./groups/floorGroup";
+import FloorGroupAilse from "./groups/floorGroupAisle";
+import Draw from "./functions/draw";
+import WallsAndWallItems from "./groups/wallsAndWallItems";
+import Ground from "../scene/environment/ground";
+// import ZoneGroup from "../groups/zoneGroup1";
+import { findEnvironment } from "../../services/factoryBuilder/environment/findEnvironment";
+import Layer2DVisibility from "./geomentries/layers/layer2DVisibility";
+import DrieHtmlTemp from "..//visualization/mqttTemp/drieHtmlTemp";
+import ZoneGroup from "./groups/zoneGroup";
+import useModuleStore from "../../store/useModuleStore";
+import MeasurementTool from "../scene/tools/measurementTool";
+
+export default function Builder() {
+ const state = useThree(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
+ const csg = useRef(); // Reference for CSG object, used for 3D modeling.
+ const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects.
+ const scene = useRef() as Types.RefScene; // Reference to the scene.
+ const camera = useRef() as Types.RefCamera; // Reference to the camera object.
+ const controls = useRef(); // Reference to the controls object.
+ const raycaster = useRef() as Types.RefRaycaster; // Reference for raycaster used for detecting objects being pointed at in the scene.
+ const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control.
+
+ // Assigning the scene and camera from the Three.js state to the references.
+
+ scene.current = state.scene;
+ camera.current = state.camera;
+ controls.current = state.controls;
+ raycaster.current = state.raycaster;
+
+ const plane = useRef(null); // Reference for a plane object for raycaster reference.
+ const grid = useRef() as any; // Reference for a grid object for raycaster reference.
+ const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line.
+ const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end).
+ const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc...
+ const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active.
+ const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point.
+ const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start).
+ const tempLoader = useRef() as Types.RefMesh; // Reference for a temporary loader for the floor items.
+ const isTempLoader = useRef() as Types.RefBoolean; // Reference to check if a temporary loader is active.
+ const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation.
+ const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn.
+ const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn.
+ const onlyFloorline = useRef([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn.
+ const onlyFloorlines = useRef([]); // Reference for all the floor lines that are ever drawn.
+ const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw.
+ const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not.
+ const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed.
+ const itemsGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the floor items (Gltf).
+ const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors.
+ const AttachedObject = useRef() as Types.RefMesh; // Reference for an object that is attached using dbl click for transform controls rotation.
+ const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group.
+ const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn.
+ const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created.
+ const floorGroupAisle = useRef() as Types.RefGroup;
+ const zoneGroup = useRef() as Types.RefGroup;
+ const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls.
+ const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted.
+ const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted.
+ const hoveredDeletableFloorItem = useRef() as Types.RefMesh; // Reference for the currently hovered floor item that can be deleted.
+ const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted.
+ const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted.
+ const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc...
+
+ const cursorPosition = new THREE.Vector3(); // 3D vector for storing the cursor position.
+
+ const [selectedItemsIndex, setSelectedItemsIndex] = useState(null); // State for tracking the index of the selected item.
+ const { activeLayer, setActiveLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx.
+ const { toggleView, setToggleView } = useToggleView(); // State for toggling between 2D and 3D.
+ const { toolMode, setToolMode } = useToolMode();
+ const { movePoint, setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not.
+ const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
+ const { socket } = useSocketStore();
+ const { roofVisibility, setRoofVisibility } = useRoofVisibility();
+ const { wallVisibility, setWallVisibility } = useWallVisibility();
+ const { shadows, setShadows } = useShadows();
+ const { renderDistance, setRenderDistance } = useRenderDistance();
+ const { limitDistance, setLimitDistance } = useLimitDistance();
+ const { updateScene, setUpdateScene } = useUpdateScene();
+ const { walls, setWalls } = useWalls();
+ const { refTextupdate, setRefTextUpdate } = useRefTextUpdate();
+ const { activeModule } = useModuleStore();
+
+ // const loader = new GLTFLoader();
+ // const dracoLoader = new DRACOLoader();
+
+ // dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
+ // loader.setDRACOLoader(dracoLoader);
+
+ ////////// Assest Configuration Values //////////
+
+ const AssetConfigurations: Types.AssetConfigurations = {
+ arch: {
+ modelUrl: arch,
+ scale: [0.75, 0.75, 0.75],
+ csgscale: [2, 4, 0.5],
+ csgposition: [0, 2, 0],
+ positionY: () => 0,
+ type: "Fixed-Move",
+ },
+ door: {
+ modelUrl: door,
+ scale: [0.75, 0.75, 0.75],
+ csgscale: [2, 4, 0.5],
+ csgposition: [0, 2, 0],
+ positionY: () => 0,
+ type: "Fixed-Move",
+ },
+ window: {
+ modelUrl: Window,
+ scale: [0.75, 0.75, 0.75],
+ csgscale: [5, 3, 0.5],
+ csgposition: [0, 1.5, 0],
+ positionY: (intersectionPoint) => intersectionPoint.point.y,
+ type: "Free-Move",
+ },
+ };
+
+ ////////// All Toggle's //////////
+
+ useEffect(() => {
+ setRefTextUpdate((prevUpdate: number) => prevUpdate - 1);
+ if (dragPointControls.current) {
+ dragPointControls.current.enabled = false;
+ }
+ if (toggleView) {
+ Layer2DVisibility(
+ activeLayer,
+ floorPlanGroup,
+ floorPlanGroupLine,
+ floorPlanGroupPoint,
+ currentLayerPoint,
+ dragPointControls
+ );
+ } else {
+ setToolMode(null);
+ setDeletePointOrLine(false);
+ setMovePoint(false);
+ loadWalls(lines, setWalls);
+ setUpdateScene(true);
+ line.current = [];
+ }
+ }, [toggleView]);
+
+ useEffect(() => {
+ THREE.Cache.clear();
+ THREE.Cache.enabled = true;
+ }, []);
+
+ useEffect(() => {
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
+
+ async function fetchVisibility() {
+ const visibility = await findEnvironment(
+ organization,
+ localStorage.getItem("userId")!
+ );
+ if (visibility) {
+ setRoofVisibility(visibility.roofVisibility);
+ setWallVisibility(visibility.wallVisibility);
+ setShadows(visibility.shadowVisibility);
+ setRenderDistance(visibility.renderDistance);
+ setLimitDistance(visibility.limitDistance);
+ }
+ }
+ fetchVisibility();
+ }, []);
+
+ ////////// UseFrame is Here //////////
+
+ useFrame(() => {
+ if (toolMode) {
+ Draw(
+ state,
+ plane,
+ cursorPosition,
+ floorPlanGroupPoint,
+ floorPlanGroupLine,
+ snappedPoint,
+ isSnapped,
+ isSnappedUUID,
+ line,
+ lines,
+ ispreSnapped,
+ floorPlanGroup,
+ ReferenceLineMesh,
+ LineCreated,
+ setRefTextUpdate,
+ Tube,
+ anglesnappedPoint,
+ isAngleSnapped,
+ toolMode
+ );
+ }
+ });
+
+ ////////// Return //////////
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* */}
+
+
+
+
+
+
+
+ {/* */}
+ >
+ );
+}
diff --git a/app/src/modules/builder/geomentries/assets/addAssetModel.ts b/app/src/modules/builder/geomentries/assets/addAssetModel.ts
index 29b0627..5a42404 100644
--- a/app/src/modules/builder/geomentries/assets/addAssetModel.ts
+++ b/app/src/modules/builder/geomentries/assets/addAssetModel.ts
@@ -5,12 +5,10 @@ import { toast } from 'react-toastify';
import TempLoader from './tempLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import * as Types from "../../../../types/world/worldTypes";
-import * as SimulationTypes from "../../../../types/simulationTypes";
import { retrieveGLTF, storeGLTF } from '../../../../utils/indexDB/idbUtils';
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
import { Socket } from 'socket.io-client';
import * as CONSTANTS from '../../../../types/world/worldConstants';
-import { getAssetEventType } from '../../../../services/simulation/getAssetEventType';
import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
async function addAssetModel(
@@ -25,7 +23,6 @@ async function addAssetModel(
socket: Socket,
selectedItem: any,
setSelectedItem: any,
- setSimulationStates: any,
plane: Types.RefMesh,
): Promise {
@@ -66,7 +63,7 @@ async function addAssetModel(
const cachedModel = THREE.Cache.get(selectedItem.id);
if (cachedModel) {
// console.log(`[Cache] Fetching ${selectedItem.name}`);
- handleModelLoad(cachedModel, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationStates, socket);
+ handleModelLoad(cachedModel, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket);
return;
} else {
const cachedModelBlob = await retrieveGLTF(selectedItem.id);
@@ -79,7 +76,7 @@ async function addAssetModel(
URL.revokeObjectURL(blobUrl);
THREE.Cache.remove(blobUrl);
THREE.Cache.add(selectedItem.id, gltf);
- handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationStates, socket);
+ handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket);
},
() => {
TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup);
@@ -91,7 +88,7 @@ async function addAssetModel(
const modelBlob = await fetch(`${url_Backend_dwinzo}/api/v2/AssetFile/${selectedItem.id}`).then((res) => res.blob());
await storeGLTF(selectedItem.id, modelBlob);
THREE.Cache.add(selectedItem.id, gltf);
- await handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationStates, socket);
+ await handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket);
},
() => {
TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup);
@@ -114,7 +111,6 @@ async function handleModelLoad(
tempLoader: Types.RefMesh,
isTempLoader: Types.RefBoolean,
setFloorItems: Types.setFloorItemSetState,
- setSimulationStates: any,
socket: Socket
) {
const model = gltf.scene.clone();
@@ -137,7 +133,7 @@ async function handleModelLoad(
tempLoader.current = undefined;
}
- const newFloorItem: SimulationTypes.EventData = {
+ const newFloorItem: Types.FloorItemType = {
modeluuid: model.uuid,
modelname: selectedItem.name,
modelfileID: selectedItem.id,
@@ -150,316 +146,44 @@ async function handleModelLoad(
const email = localStorage.getItem("email");
const organization = email ? email.split("@")[1].split(".")[0] : "";
- getAssetEventType(selectedItem.id, organization).then(async (res) => {
+ // API
- if (res.type === "Conveyor") {
- const pointUUIDs = res.points.map(() => THREE.MathUtils.generateUUID());
+ // await setFloorItemApi(
+ // organization,
+ // newFloorItem.modeluuid,
+ // newFloorItem.modelname,
+ // newFloorItem.modelfileID,
+ // newFloorItem.position,
+ // { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
+ // false,
+ // true,
+ // );
- const backendEventData: Extract = {
- type: 'Conveyor',
- points: res.points.map((point: any, index: number) => ({
- uuid: pointUUIDs[index],
- position: point.position as [number, number, number],
- rotation: point.rotation as [number, number, number],
- actions: [{
- uuid: THREE.MathUtils.generateUUID(),
- name: 'Action 1',
- type: 'Inherit',
- material: 'Inherit',
- delay: 'Inherit',
- spawnInterval: 'Inherit',
- isUsed: true
- }],
- triggers: [],
- connections: {
- source: { modelUUID: model.uuid, pointUUID: pointUUIDs[index] },
- targets: []
- }
- })),
- speed: 'Inherit'
- };
+ // SOCKET
- // API
-
- // await setFloorItemApi(
- // organization,
- // newFloorItem.modeluuid,
- // newFloorItem.modelname,
- // newFloorItem.modelfileID,
- // newFloorItem.position,
- // { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed }
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: backendEventData,
- socketId: socket.id
- };
-
- setFloorItems((prevItems) => {
- const updatedItems = [...(prevItems || []), newFloorItem];
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
-
- const eventData: any = backendEventData;
- eventData.modeluuid = newFloorItem.modeluuid;
- eventData.modelName = newFloorItem.modelname;
- eventData.position = newFloorItem.position;
- eventData.rotation = [model.rotation.x, model.rotation.y, model.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- eventData as SimulationTypes.ConveyorEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (res.type === "Vehicle") {
-
- const pointUUID = THREE.MathUtils.generateUUID();
-
- const backendEventData: Extract = {
- type: "Vehicle",
- points: {
- uuid: pointUUID,
- position: res.points.position as [number, number, number],
- rotation: res.points.rotation as [number, number, number],
- actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: '', start: {}, hitCount: 1, end: {}, buffer: 0 },
- connections: { source: { modelUUID: model.uuid, pointUUID: pointUUID }, targets: [] },
- speed: 2,
- }
- }
-
- // API
-
- // await setFloorItemApi(
- // organization,
- // newFloorItem.modeluuid,
- // newFloorItem.modelname,
- // newFloorItem.modelfileID,
- // newFloorItem.position,
- // { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id
- };
-
- const eventData: any = backendEventData;
- eventData.modeluuid = newFloorItem.modeluuid;
- eventData.modelName = newFloorItem.modelname;
- eventData.position = newFloorItem.position;
-
- setFloorItems((prevItems) => {
- const updatedItems = [...(prevItems || []), newFloorItem];
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- eventData as SimulationTypes.VehicleEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (res.type === "StaticMachine") {
-
- const pointUUID = THREE.MathUtils.generateUUID();
-
- const backendEventData: Extract = {
- type: "StaticMachine",
- points: {
- uuid: pointUUID,
- position: res.points.position as [number, number, number],
- rotation: res.points.rotation as [number, number, number],
- actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', buffer: 0, material: 'Inherit' },
- triggers: { uuid: THREE.MathUtils.generateUUID(), name: 'Trigger 1', type: 'OnComplete' },
- connections: { source: { modelUUID: model.uuid, pointUUID: pointUUID }, targets: [] },
- }
- }
-
- // API
-
- // await setFloorItemApi(
- // organization,
- // newFloorItem.modeluuid,
- // newFloorItem.modelname,
- // newFloorItem.modelfileID,
- // newFloorItem.position,
- // { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id
- };
-
- const eventData: any = backendEventData;
- eventData.modeluuid = newFloorItem.modeluuid;
- eventData.modelName = newFloorItem.modelname;
- eventData.position = newFloorItem.position;
- eventData.rotation = [model.rotation.x, model.rotation.y, model.rotation.z];
-
- setFloorItems((prevItems) => {
- const updatedItems = [...(prevItems || []), newFloorItem];
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- eventData as SimulationTypes.StaticMachineEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (res.type === "ArmBot") {
-
- const pointUUID = THREE.MathUtils.generateUUID();
-
- const backendEventData: Extract = {
- type: "ArmBot",
- points: {
- uuid: pointUUID,
- position: res.points.position as [number, number, number],
- rotation: res.points.rotation as [number, number, number],
- actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', speed: 0.2, processes: [] },
- triggers: { uuid: THREE.MathUtils.generateUUID(), name: 'Trigger 1', type: 'OnComplete' },
- connections: { source: { modelUUID: model.uuid, pointUUID: pointUUID }, targets: [] },
- }
- }
-
- // API
-
- // await setFloorItemApi(
- // organization,
- // newFloorItem.modeluuid,
- // newFloorItem.modelname,
- // newFloorItem.modelfileID,
- // newFloorItem.position,
- // { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id
- };
-
- const eventData: any = backendEventData;
- eventData.modeluuid = newFloorItem.modeluuid;
- eventData.modelName = newFloorItem.modelname;
- eventData.position = newFloorItem.position;
- eventData.rotation = [model.rotation.x, model.rotation.y, model.rotation.z];
-
- setFloorItems((prevItems) => {
- const updatedItems = [...(prevItems || []), newFloorItem];
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- eventData as SimulationTypes.ArmBotEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else {
-
- // API
-
- // await setFloorItemApi(
- // organization,
- // newFloorItem.modeluuid,
- // newFloorItem.modelname,
- // newFloorItem.modelfileID,
- // newFloorItem.position,
- // { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
- // false,
- // true,
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
- isLocked: false,
- isVisible: true,
- socketId: socket.id
- };
+ const data = {
+ organization,
+ modeluuid: newFloorItem.modeluuid,
+ modelname: newFloorItem.modelname,
+ modelfileID: newFloorItem.modelfileID,
+ position: newFloorItem.position,
+ rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
+ isLocked: false,
+ isVisible: true,
+ socketId: socket.id
+ };
- setFloorItems((prevItems) => {
- const updatedItems = [...(prevItems || []), newFloorItem];
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
-
- socket.emit("v2:model-asset:add", data);
- }
-
- gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
- gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } });
+ setFloorItems((prevItems) => {
+ const updatedItems = [...(prevItems || []), newFloorItem];
+ localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
+ return updatedItems;
});
+
+ socket.emit("v2:model-asset:add", data);
+
+ gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
+ gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } });
}
export default addAssetModel;
diff --git a/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts b/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts
index dbd7e9b..18136b3 100644
--- a/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts
+++ b/app/src/modules/builder/geomentries/assets/deleteFloorItems.ts
@@ -2,7 +2,6 @@ import { toast } from 'react-toastify';
import * as THREE from 'three';
import * as Types from "../../../../types/world/worldTypes";
-import * as SimulationTypes from "../../../../types/simulationTypes";
// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
import { Socket } from 'socket.io-client';
import { getFloorAssets } from '../../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
@@ -11,7 +10,6 @@ async function DeleteFloorItems(
itemsGroup: Types.RefGroup,
hoveredDeletableFloorItem: Types.RefMesh,
setFloorItems: Types.setFloorItemSetState,
- setSimulationStates: any,
socket: Socket
): Promise {
@@ -77,11 +75,6 @@ async function DeleteFloorItems(
}
setFloorItems(updatedItems);
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- const updatedEvents = (prevEvents || []).filter(event => event.modeluuid !== removedItem.modeluuid);
- return updatedEvents;
- });
-
toast.success("Model Removed!");
}
}
diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx
index acc284f..99d3291 100644
--- a/app/src/modules/builder/groups/floorItemsGroup.tsx
+++ b/app/src/modules/builder/groups/floorItemsGroup.tsx
@@ -1,5 +1,5 @@
import { useFrame, useThree } from "@react-three/fiber";
-import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteTool, useFloorItems, useLoadingProgress, useRenderDistance, useSelectedFloorItem, useSelectedItem, useSimulationStates, useSocketStore, useToggleView, useTransformMode, } from "../../../store/store";
+import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteTool, useFloorItems, useLoadingProgress, useRenderDistance, useSelectedFloorItem, useSelectedItem, useSocketStore, useToggleView, useTransformMode, } from "../../../store/store";
import assetVisibility from "../geomentries/assets/assetVisibility";
import { useEffect } from "react";
import * as THREE from "three";
@@ -11,7 +11,7 @@ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import DeletableHoveredFloorItems from "../geomentries/assets/deletableHoveredFloorItems";
import DeleteFloorItems from "../geomentries/assets/deleteFloorItems";
-import loadInitialFloorItems from "../../scene/IntialLoad/loadInitialFloorItems";
+import loadInitialFloorItems from "../IntialLoad/loadInitialFloorItems";
import addAssetModel from "../geomentries/assets/addAssetModel";
import { getFloorAssets } from "../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi";
import useModuleStore from "../../../store/useModuleStore";
@@ -32,7 +32,6 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
const { setSelectedFloorItem } = useSelectedFloorItem();
const { activeTool } = useActiveTool();
const { selectedItem, setSelectedItem } = useSelectedItem();
- const { simulationStates, setSimulationStates } = useSimulationStates();
const { setLoadingProgress } = useLoadingProgress();
const { activeModule } = useModuleStore();
const { socket } = useSocketStore();
@@ -73,7 +72,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
gltfLoaderWorker.postMessage({ floorItems: data });
} else {
gltfLoaderWorker.postMessage({ floorItems: [] });
- loadInitialFloorItems(itemsGroup, setFloorItems, setSimulationStates);
+ loadInitialFloorItems(itemsGroup, setFloorItems);
updateLoadingProgress(100);
}
});
@@ -92,7 +91,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
updateLoadingProgress(progress);
if (loadedAssets === totalAssets) {
- loadInitialFloorItems(itemsGroup, setFloorItems, setSimulationStates);
+ loadInitialFloorItems(itemsGroup, setFloorItems);
updateLoadingProgress(100);
}
});
@@ -192,9 +191,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
if (drag) return;
if (deleteTool) {
- DeleteFloorItems(itemsGroup, hoveredDeletableFloorItem, setFloorItems, setSimulationStates, socket);
-
- // Remove EventData if there are any in the asset.
+ DeleteFloorItems(itemsGroup, hoveredDeletableFloorItem, setFloorItems, socket);
}
const Mode = transformMode;
@@ -278,7 +275,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
if (!event.dataTransfer?.files[0]) return;
if (selectedItem.id !== "" && event.dataTransfer?.files[0]) {
- addAssetModel(raycaster, state.camera, state.pointer, floorGroup, setFloorItems, itemsGroup, isTempLoader, tempLoader, socket, selectedItem, setSelectedItem, setSimulationStates, plane);
+ addAssetModel(raycaster, state.camera, state.pointer, floorGroup, setFloorItems, itemsGroup, isTempLoader, tempLoader, socket, selectedItem, setSelectedItem, plane);
}
};
diff --git a/app/src/modules/builder/groups/floorPlanGroup.tsx b/app/src/modules/builder/groups/floorPlanGroup.tsx
index 6369e1e..12d75f0 100644
--- a/app/src/modules/builder/groups/floorPlanGroup.tsx
+++ b/app/src/modules/builder/groups/floorPlanGroup.tsx
@@ -9,15 +9,14 @@ import removeReferenceLine from "../geomentries/lines/removeReferenceLine";
import DeleteLayer from "../geomentries/layers/deleteLayer";
import { getLines } from "../../../services/factoryBuilder/lines/getLinesApi";
import objectLinesToArray from "../geomentries/lines/lineConvertions/objectLinesToArray";
-import loadInitialPoint from "../../scene/IntialLoad/loadInitialPoint";
-import loadInitialLine from "../../scene/IntialLoad/loadInitialLine";
+import loadInitialPoint from "../IntialLoad/loadInitialPoint";
+import loadInitialLine from "../IntialLoad/loadInitialLine";
import deletePoint from "../geomentries/points/deletePoint";
import deleteLine from "../geomentries/lines/deleteLine";
import drawWall from "../geomentries/lines/drawWall";
import drawOnlyFloor from "../geomentries/floors/drawOnlyFloor";
import addDragControl from "../eventDeclaration/dragControlDeclaration";
-
const FloorPlanGroup = ({ floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, floorGroup, currentLayerPoint, dragPointControls, hoveredDeletablePoint, hoveredDeletableLine, plane, line, lines, onlyFloorline, onlyFloorlines, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => {
const state = useThree();
const { scene, camera, gl, raycaster, controls } = state;
diff --git a/app/src/modules/builder/groups/wallItemsGroup.tsx b/app/src/modules/builder/groups/wallItemsGroup.tsx
index cdc326e..43845e7 100644
--- a/app/src/modules/builder/groups/wallItemsGroup.tsx
+++ b/app/src/modules/builder/groups/wallItemsGroup.tsx
@@ -7,7 +7,7 @@ import * as THREE from "three";
import { useThree } from "@react-three/fiber";
import handleMeshMissed from "../eventFunctions/handleMeshMissed";
import DeleteWallItems from "../geomentries/walls/deleteWallItems";
-import loadInitialWallItems from "../../scene/IntialLoad/loadInitialWallItems";
+import loadInitialWallItems from "../IntialLoad/loadInitialWallItems";
import AddWallItems from "../geomentries/walls/addWallItems";
import useModuleStore from "../../../store/useModuleStore";
@@ -37,51 +37,6 @@ const WallItemsGroup = ({ currentWallItem, AssetConfigurations, hoveredDeletable
////////// Update the Rotation value changes in the selected item //////////
- useEffect(() => {
- if (objectScale.x && objectScale.y && objectScale.z) {
- let ScaledWallItems: Types.wallItems = [];
- wallItems.forEach((items: any) => {
- if (items.model?.uuid === currentWallItem.current?.parent?.uuid) {
- items.scale = [objectScale.x, objectScale.y, objectScale.z];
- }
- ScaledWallItems.push(items);
- });
- setWallItems(ScaledWallItems);
- }
- }, [objectScale]);
-
- useEffect(() => {
- if (objectPosition.x && objectPosition.y && objectPosition.z) {
- let ScaledWallItems: Types.wallItems = [];
- wallItems.forEach((items: any) => {
- if (items.model?.uuid === currentWallItem.current?.parent?.uuid) {
- items.position = [objectPosition.x, objectPosition.y, objectPosition.z];
- }
- ScaledWallItems.push(items);
- });
- setWallItems(ScaledWallItems);
- }
- }, [objectPosition]);
-
- useEffect(() => {
- if (objectRotation.x && objectRotation.y && objectRotation.z) {
- let ScaledWallItems: Types.wallItems = [];
- wallItems.forEach((items: any) => {
- if (items.model?.uuid === currentWallItem.current?.parent?.uuid) {
- const radiansX = objectRotation.x * (Math.PI / 180);
- const radiansY = objectRotation.y * (Math.PI / 180);
- const radiansZ = objectRotation.z * (Math.PI / 180);
- const quaternion = new THREE.Quaternion().setFromEuler(
- new THREE.Euler(radiansX, radiansY, radiansZ)
- );
- items.quaternion = [quaternion.x, quaternion.y, quaternion.z, quaternion.w];
- }
- ScaledWallItems.push(items);
- });
- setWallItems(ScaledWallItems);
- }
- }, [objectRotation]);
-
useEffect(() => {
const canvasElement = state.gl.domElement;
function handlePointerMove(e: any) {
diff --git a/app/src/modules/collaboration/camera/collabCams.tsx b/app/src/modules/collaboration/camera/collabCams.tsx
new file mode 100644
index 0000000..63ab2a1
--- /dev/null
+++ b/app/src/modules/collaboration/camera/collabCams.tsx
@@ -0,0 +1,231 @@
+import * as THREE from "three";
+import { useEffect, useRef, useState } from "react";
+import { useFrame } from "@react-three/fiber";
+import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
+import camModel from "../../assets/gltf-glb/camera face 2.gltf";
+import getActiveUsersData from "../../../services/factoryBuilder/collab/getActiveUsers";
+import { useActiveUsers, useSocketStore } from "../../../store/store";
+import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
+import { useNavigate } from "react-router-dom";
+import { Html } from "@react-three/drei";
+import CollabUserIcon from "../../../functions/collabUserIcon";
+import { getAvatarColor } from "../../../functions/users/functions/getAvatarColor";
+import useModuleStore from "../../../store/useModuleStore";
+
+const CamModelsGroup = () => {
+ const navigate = useNavigate();
+ const groupRef = useRef(null);
+ const email = localStorage.getItem("email");
+ const { setActiveUsers } = useActiveUsers();
+ const { socket } = useSocketStore();
+ const { activeModule } = useModuleStore();
+
+ const loader = new GLTFLoader();
+ const dracoLoader = new DRACOLoader();
+ dracoLoader.setDecoderPath("three/examples/jsm/libs/draco/gltf/");
+ loader.setDRACOLoader(dracoLoader);
+
+ const [cams, setCams] = useState([]);
+ const [models, setModels] = useState>({});
+
+ const dedupeCams = (cams: any[]) => {
+ const seen = new Set();
+ return cams.filter((cam) => {
+ if (seen.has(cam.uuid)) return false;
+ seen.add(cam.uuid);
+ return true;
+ });
+ };
+
+ const dedupeUsers = (users: any[]) => {
+ const seen = new Set();
+ return users.filter((user) => {
+ if (seen.has(user._id)) return false;
+ seen.add(user._id);
+ return true;
+ });
+ };
+
+ useEffect(() => {
+ if (!email) navigate("/");
+
+ if (!socket) return;
+ const organization = email!.split("@")[1].split(".")[0];
+
+ socket.on("userConnectResponse", (data: any) => {
+ if (!groupRef.current) return;
+ if (data.data.userData.email === email) return;
+ if (socket.id === data.socketId || organization !== data.organization)
+ return;
+
+ const model = groupRef.current.getObjectByProperty(
+ "uuid",
+ data.data.userData._id
+ );
+ if (model) {
+ groupRef.current.remove(model);
+ }
+
+ loader.load(camModel, (gltf) => {
+ const newModel = gltf.scene.clone();
+ newModel.uuid = data.data.userData._id;
+ newModel.position.set(
+ data.data.position.x,
+ data.data.position.y,
+ data.data.position.z
+ );
+ newModel.rotation.set(
+ data.data.rotation.x,
+ data.data.rotation.y,
+ data.data.rotation.z
+ );
+ newModel.userData = data.data.userData;
+
+ setCams((prev) => dedupeCams([...prev, newModel]));
+ setActiveUsers((prev: any) =>
+ dedupeUsers([...prev, data.data.userData])
+ );
+ });
+ });
+
+ socket.on("userDisConnectResponse", (data: any) => {
+ if (!groupRef.current) return;
+ if (socket.id === data.socketId || organization !== data.organization)
+ return;
+
+ setCams((prev) =>
+ prev.filter((cam) => cam.uuid !== data.data.userData._id)
+ );
+ setActiveUsers((prev: any) =>
+ prev.filter((user: any) => user._id !== data.data.userData._id)
+ );
+ });
+
+ socket.on("cameraUpdateResponse", (data: any) => {
+ if (
+ !groupRef.current ||
+ socket.id === data.socketId ||
+ organization !== data.organization
+ )
+ return;
+
+ setModels((prev) => ({
+ ...prev,
+ [data.data.userId]: {
+ targetPosition: new THREE.Vector3(
+ data.data.position.x,
+ data.data.position.y,
+ data.data.position.z
+ ),
+ targetRotation: new THREE.Euler(
+ data.data.rotation.x,
+ data.data.rotation.y,
+ data.data.rotation.z
+ ),
+ },
+ }));
+ });
+
+ return () => {
+ socket.off("userConnectResponse");
+ socket.off("userDisConnectResponse");
+ socket.off("cameraUpdateResponse");
+ };
+ }, [socket]);
+
+ useFrame(() => {
+ if (!groupRef.current) return;
+ Object.keys(models).forEach((uuid) => {
+ const model = groupRef.current!.getObjectByProperty("uuid", uuid);
+ if (!model) return;
+
+ const { targetPosition, targetRotation } = models[uuid];
+ model.position.lerp(targetPosition, 0.1);
+ model.rotation.x = THREE.MathUtils.lerp(
+ model.rotation.x,
+ targetRotation.x,
+ 0.1
+ );
+ model.rotation.y = THREE.MathUtils.lerp(
+ model.rotation.y,
+ targetRotation.y,
+ 0.1
+ );
+ model.rotation.z = THREE.MathUtils.lerp(
+ model.rotation.z,
+ targetRotation.z,
+ 0.1
+ );
+ });
+ });
+
+ useEffect(() => {
+ if (!groupRef.current) return;
+ const organization = email!.split("@")[1].split(".")[0];
+
+ getActiveUsersData(organization).then((data) => {
+ const filteredData = data.cameraDatas.filter(
+ (camera: any) => camera.userData.email !== email
+ );
+
+ if (filteredData.length > 0) {
+ loader.load(camModel, (gltf) => {
+ const newCams = filteredData.map((cam: any) => {
+ const newModel = gltf.scene.clone();
+ newModel.uuid = cam.userData._id;
+ newModel.position.set(
+ cam.position.x,
+ cam.position.y,
+ cam.position.z
+ );
+ newModel.rotation.set(
+ cam.rotation.x,
+ cam.rotation.y,
+ cam.rotation.z
+ );
+ newModel.userData = cam.userData;
+ return newModel;
+ });
+
+ const users = filteredData.map((cam: any) => cam.userData);
+ setActiveUsers((prev: any) => dedupeUsers([...prev, ...users]));
+ setCams((prev) => dedupeCams([...prev, ...newCams]));
+ });
+ }
+ });
+ }, []);
+
+ return (
+
+ {cams.map((cam, index) => (
+
+
+
+
+
+ ))}
+
+ );
+};
+
+export default CamModelsGroup;
diff --git a/app/src/modules/collaboration/collabCams.tsx b/app/src/modules/collaboration/collabCams.tsx
deleted file mode 100644
index ca0d1c5..0000000
--- a/app/src/modules/collaboration/collabCams.tsx
+++ /dev/null
@@ -1,231 +0,0 @@
-import * as THREE from "three";
-import { useEffect, useRef, useState } from "react";
-import { useFrame } from "@react-three/fiber";
-import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
-import camModel from "../../assets/gltf-glb/camera face 2.gltf";
-import getActiveUsersData from "../../services/factoryBuilder/collab/getActiveUsers";
-import { useActiveUsers, useSocketStore } from "../../store/store";
-import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
-import { useNavigate } from "react-router-dom";
-import { Html } from "@react-three/drei";
-import CollabUserIcon from "./collabUserIcon";
-import { getAvatarColor } from "./users/functions/getAvatarColor";
-import useModuleStore from "../../store/useModuleStore";
-
-const CamModelsGroup = () => {
- const navigate = useNavigate();
- const groupRef = useRef(null);
- const email = localStorage.getItem("email");
- const { setActiveUsers } = useActiveUsers();
- const { socket } = useSocketStore();
- const { activeModule } = useModuleStore();
-
- const loader = new GLTFLoader();
- const dracoLoader = new DRACOLoader();
- dracoLoader.setDecoderPath("three/examples/jsm/libs/draco/gltf/");
- loader.setDRACOLoader(dracoLoader);
-
- const [cams, setCams] = useState([]);
- const [models, setModels] = useState>({});
-
- const dedupeCams = (cams: any[]) => {
- const seen = new Set();
- return cams.filter((cam) => {
- if (seen.has(cam.uuid)) return false;
- seen.add(cam.uuid);
- return true;
- });
- };
-
- const dedupeUsers = (users: any[]) => {
- const seen = new Set();
- return users.filter((user) => {
- if (seen.has(user._id)) return false;
- seen.add(user._id);
- return true;
- });
- };
-
- useEffect(() => {
- if (!email) navigate("/");
-
- if (!socket) return;
- const organization = email!.split("@")[1].split(".")[0];
-
- socket.on("userConnectResponse", (data: any) => {
- if (!groupRef.current) return;
- if (data.data.userData.email === email) return;
- if (socket.id === data.socketId || organization !== data.organization)
- return;
-
- const model = groupRef.current.getObjectByProperty(
- "uuid",
- data.data.userData._id
- );
- if (model) {
- groupRef.current.remove(model);
- }
-
- loader.load(camModel, (gltf) => {
- const newModel = gltf.scene.clone();
- newModel.uuid = data.data.userData._id;
- newModel.position.set(
- data.data.position.x,
- data.data.position.y,
- data.data.position.z
- );
- newModel.rotation.set(
- data.data.rotation.x,
- data.data.rotation.y,
- data.data.rotation.z
- );
- newModel.userData = data.data.userData;
-
- setCams((prev) => dedupeCams([...prev, newModel]));
- setActiveUsers((prev: any) =>
- dedupeUsers([...prev, data.data.userData])
- );
- });
- });
-
- socket.on("userDisConnectResponse", (data: any) => {
- if (!groupRef.current) return;
- if (socket.id === data.socketId || organization !== data.organization)
- return;
-
- setCams((prev) =>
- prev.filter((cam) => cam.uuid !== data.data.userData._id)
- );
- setActiveUsers((prev: any) =>
- prev.filter((user: any) => user._id !== data.data.userData._id)
- );
- });
-
- socket.on("cameraUpdateResponse", (data: any) => {
- if (
- !groupRef.current ||
- socket.id === data.socketId ||
- organization !== data.organization
- )
- return;
-
- setModels((prev) => ({
- ...prev,
- [data.data.userId]: {
- targetPosition: new THREE.Vector3(
- data.data.position.x,
- data.data.position.y,
- data.data.position.z
- ),
- targetRotation: new THREE.Euler(
- data.data.rotation.x,
- data.data.rotation.y,
- data.data.rotation.z
- ),
- },
- }));
- });
-
- return () => {
- socket.off("userConnectResponse");
- socket.off("userDisConnectResponse");
- socket.off("cameraUpdateResponse");
- };
- }, [socket]);
-
- useFrame(() => {
- if (!groupRef.current) return;
- Object.keys(models).forEach((uuid) => {
- const model = groupRef.current!.getObjectByProperty("uuid", uuid);
- if (!model) return;
-
- const { targetPosition, targetRotation } = models[uuid];
- model.position.lerp(targetPosition, 0.1);
- model.rotation.x = THREE.MathUtils.lerp(
- model.rotation.x,
- targetRotation.x,
- 0.1
- );
- model.rotation.y = THREE.MathUtils.lerp(
- model.rotation.y,
- targetRotation.y,
- 0.1
- );
- model.rotation.z = THREE.MathUtils.lerp(
- model.rotation.z,
- targetRotation.z,
- 0.1
- );
- });
- });
-
- useEffect(() => {
- if (!groupRef.current) return;
- const organization = email!.split("@")[1].split(".")[0];
-
- getActiveUsersData(organization).then((data) => {
- const filteredData = data.cameraDatas.filter(
- (camera: any) => camera.userData.email !== email
- );
-
- if (filteredData.length > 0) {
- loader.load(camModel, (gltf) => {
- const newCams = filteredData.map((cam: any) => {
- const newModel = gltf.scene.clone();
- newModel.uuid = cam.userData._id;
- newModel.position.set(
- cam.position.x,
- cam.position.y,
- cam.position.z
- );
- newModel.rotation.set(
- cam.rotation.x,
- cam.rotation.y,
- cam.rotation.z
- );
- newModel.userData = cam.userData;
- return newModel;
- });
-
- const users = filteredData.map((cam: any) => cam.userData);
- setActiveUsers((prev: any) => dedupeUsers([...prev, ...users]));
- setCams((prev) => dedupeCams([...prev, ...newCams]));
- });
- }
- });
- }, []);
-
- return (
-
- {cams.map((cam, index) => (
-
-
-
-
-
- ))}
-
- );
-};
-
-export default CamModelsGroup;
diff --git a/app/src/modules/collaboration/collaboration.tsx b/app/src/modules/collaboration/collaboration.tsx
new file mode 100644
index 0000000..84d3ab1
--- /dev/null
+++ b/app/src/modules/collaboration/collaboration.tsx
@@ -0,0 +1,14 @@
+import React from 'react'
+import CamModelsGroup from './camera/collabCams'
+
+const Collaboration = () => {
+ return (
+ <>
+
+
+
+ >
+ )
+}
+
+export default Collaboration
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/controls.tsx b/app/src/modules/scene/controls/controls.tsx
index 0e7581f..8bdd3aa 100644
--- a/app/src/modules/scene/controls/controls.tsx
+++ b/app/src/modules/scene/controls/controls.tsx
@@ -9,128 +9,135 @@ import { getCamera } from "../../../services/factoryBuilder/camera/getCameraApi"
import updateCamPosition from "../camera/updateCameraPosition";
import CamMode from "../camera/camMode";
import SwitchView from "../camera/switchView";
+import SelectionControls from "./selectionControls/selectionControls";
export default function Controls() {
- const controlsRef = useRef(null);
+ const controlsRef = useRef(null);
- const { toggleView } = useToggleView();
- const { resetCamera, setResetCamera } = useResetCamera();
- const { socket } = useSocketStore();
- const state = useThree();
+ const { toggleView } = useToggleView();
+ const { resetCamera, setResetCamera } = useResetCamera();
+ const { socket } = useSocketStore();
+ const state = useThree();
- useEffect(() => {
- if (controlsRef.current) {
- (controlsRef.current as any).mouseButtons.left = CONSTANTS.thirdPersonControls.leftMouse;
- (controlsRef.current as any).mouseButtons.right = CONSTANTS.thirdPersonControls.rightMouse;
- }
- const email = localStorage.getItem("email");
- const organization = email!.split("@")[1].split(".")[0];
- getCamera(organization, localStorage.getItem("userId")!).then((data) => {
- if (data && data.position && data.target) {
- controlsRef.current?.setPosition(data.position.x, data.position.y, data.position.z);
- controlsRef.current?.setTarget(data.target.x, data.target.y, data.target.z);
- } else {
- controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition);
- controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget);
- }
- })
- .catch((error) => console.error("Failed to fetch camera data:", error));
- }, []);
+ useEffect(() => {
+ if (controlsRef.current) {
+ (controlsRef.current as any).mouseButtons.left = CONSTANTS.thirdPersonControls.leftMouse;
+ (controlsRef.current as any).mouseButtons.right = CONSTANTS.thirdPersonControls.rightMouse;
+ }
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
+ getCamera(organization, localStorage.getItem("userId")!).then((data) => {
+ if (data && data.position && data.target) {
+ controlsRef.current?.setPosition(data.position.x, data.position.y, data.position.z);
+ controlsRef.current?.setTarget(data.target.x, data.target.y, data.target.z);
+ } else {
+ controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition);
+ controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget);
+ }
+ })
+ .catch((error) => console.error("Failed to fetch camera data:", error));
+ }, []);
- useEffect(() => {
- if (resetCamera) {
- controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition);
- controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget);
- controlsRef.current?.rotateAzimuthTo(CONSTANTS.threeDimension.defaultAzimuth);
+ useEffect(() => {
+ if (resetCamera) {
+ controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition);
+ controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget);
+ controlsRef.current?.rotateAzimuthTo(CONSTANTS.threeDimension.defaultAzimuth);
- localStorage.setItem("cameraPosition", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition)));
- localStorage.setItem("controlTarget", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget)));
+ localStorage.setItem("cameraPosition", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition)));
+ localStorage.setItem("controlTarget", JSON.stringify(new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget)));
- const email = localStorage.getItem('email')
- const organization = (email!.split("@")[1]).split(".")[0];
+ const email = localStorage.getItem('email')
+ const organization = (email!.split("@")[1]).split(".")[0];
- const camData = {
- organization: organization,
- userId: localStorage.getItem('userId')!,
- position: new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition),
- target: new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget),
- rotation: new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation),
- socketId: socket.id
- };
- socket.emit('v1:Camera:set', camData)
+ const camData = {
+ organization: organization,
+ userId: localStorage.getItem('userId')!,
+ position: new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition),
+ target: new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget),
+ rotation: new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation),
+ socketId: socket.id
+ };
+ socket.emit('v1:Camera:set', camData)
- setResetCamera(false);
- }
- }, [resetCamera]);
+ setResetCamera(false);
+ }
+ }, [resetCamera]);
- useEffect(() => {
- controlsRef.current?.setBoundary(new THREE.Box3(new THREE.Vector3(...CONSTANTS.threeDimension.boundaryBottom), new THREE.Vector3(...CONSTANTS.threeDimension.boundaryTop)));
- // state.scene.add(new THREE.Box3Helper(new THREE.Box3(new THREE.Vector3(...CONSTANTS.threeDimension.boundaryBottom), new THREE.Vector3(...CONSTANTS.threeDimension.boundaryTop)), 0xffff00));
- let hasInteracted = false;
- let intervalId: NodeJS.Timeout | null = null;
+ useEffect(() => {
+ controlsRef.current?.setBoundary(new THREE.Box3(new THREE.Vector3(...CONSTANTS.threeDimension.boundaryBottom), new THREE.Vector3(...CONSTANTS.threeDimension.boundaryTop)));
+ // state.scene.add(new THREE.Box3Helper(new THREE.Box3(new THREE.Vector3(...CONSTANTS.threeDimension.boundaryBottom), new THREE.Vector3(...CONSTANTS.threeDimension.boundaryTop)), 0xffff00));
+ let hasInteracted = false;
+ let intervalId: NodeJS.Timeout | null = null;
- const handleRest = () => {
- if (hasInteracted && controlsRef.current && state.camera.position && !toggleView) {
- const position = state.camera.position;
- if (position.x === 0 && position.y === 0 && position.z === 0) return;
- updateCamPosition(controlsRef, socket, position, state.camera.rotation);
- stopInterval();
- }
- };
+ const handleRest = () => {
+ if (hasInteracted && controlsRef.current && state.camera.position && !toggleView) {
+ const position = state.camera.position;
+ if (position.x === 0 && position.y === 0 && position.z === 0) return;
+ updateCamPosition(controlsRef, socket, position, state.camera.rotation);
+ stopInterval();
+ }
+ };
- const startInterval = () => {
- hasInteracted = true;
- if (!intervalId) {
- intervalId = setInterval(() => {
- if (controlsRef.current && !toggleView) {
- handleRest();
- }
- }, CONSTANTS.camPositionUpdateInterval);
- }
- };
+ const startInterval = () => {
+ hasInteracted = true;
+ if (!intervalId) {
+ intervalId = setInterval(() => {
+ if (controlsRef.current && !toggleView) {
+ handleRest();
+ }
+ }, CONSTANTS.camPositionUpdateInterval);
+ }
+ };
- const stopInterval = () => {
- if (intervalId) {
- clearInterval(intervalId);
- intervalId = null;
- }
- };
+ const stopInterval = () => {
+ if (intervalId) {
+ clearInterval(intervalId);
+ intervalId = null;
+ }
+ };
- const controls = controlsRef.current;
- if (controls) {
- controls.addEventListener("sleep", handleRest);
- controls.addEventListener("control", startInterval);
- controls.addEventListener("controlend", stopInterval);
- }
+ const controls = controlsRef.current;
+ if (controls) {
+ controls.addEventListener("sleep", handleRest);
+ controls.addEventListener("control", startInterval);
+ controls.addEventListener("controlend", stopInterval);
+ }
- return () => {
- if (controls) {
- controls.removeEventListener("sleep", handleRest);
- controls.removeEventListener("control", startInterval);
- controls.removeEventListener("controlend", stopInterval);
- }
- stopInterval();
- };
- }, [toggleView, state, socket]);
+ return () => {
+ if (controls) {
+ controls.removeEventListener("sleep", handleRest);
+ controls.removeEventListener("control", startInterval);
+ controls.removeEventListener("controlend", stopInterval);
+ }
+ stopInterval();
+ };
+ }, [toggleView, state, socket]);
- return (
- <>
-
-
-
-
- >
- );
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ >
+ );
}
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selection/copyPasteControls.tsx b/app/src/modules/scene/controls/selection/copyPasteControls.tsx
deleted file mode 100644
index 1f83513..0000000
--- a/app/src/modules/scene/controls/selection/copyPasteControls.tsx
+++ /dev/null
@@ -1,581 +0,0 @@
-import * as THREE from "three";
-import { useEffect, useMemo } from "react";
-import { useFrame, useThree } from "@react-three/fiber";
-import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView } from "../../../../store/store";
-import { toast } from "react-toastify";
-// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
-import * as Types from "../../../../types/world/worldTypes";
-import * as SimulationTypes from "../../../../types/simulationTypes";
-import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
-
-const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, selectionGroup, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => {
- const { camera, controls, gl, scene, pointer, raycaster } = useThree();
- const { toggleView } = useToggleView();
- const { selectedAssets, setSelectedAssets } = useSelectedAssets();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
- const { floorItems, setFloorItems } = useFloorItems();
- const { socket } = useSocketStore()
-
- useEffect(() => {
- if (!camera || !scene || toggleView) return;
- const canvasElement = gl.domElement;
- canvasElement.tabIndex = 0;
-
- let isMoving = false;
-
- const onPointerDown = () => {
- isMoving = false;
- };
-
- const onPointerMove = () => {
- isMoving = true;
- };
-
- const onPointerUp = (event: PointerEvent) => {
- if (!isMoving && pastedObjects.length > 0 && event.button === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
- event.preventDefault();
- addPastedObjects();
- }
- };
-
- const onKeyDown = (event: KeyboardEvent) => {
- const keyCombination = detectModifierKeys(event);
-
- if (keyCombination === "Ctrl+C" && movedObjects.length === 0 && rotatedObjects.length === 0) {
- copySelection();
- }
- if (keyCombination === "Ctrl+V" && copiedObjects.length > 0 && pastedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
- pasteCopiedObjects();
- }
- };
-
- if (!toggleView) {
- canvasElement.addEventListener("pointerdown", onPointerDown);
- canvasElement.addEventListener("pointermove", onPointerMove);
- canvasElement.addEventListener("pointerup", onPointerUp);
- canvasElement.addEventListener("keydown", onKeyDown);
- }
-
- return () => {
- canvasElement.removeEventListener("pointerdown", onPointerDown);
- canvasElement.removeEventListener("pointermove", onPointerMove);
- canvasElement.removeEventListener("pointerup", onPointerUp);
- canvasElement.removeEventListener("keydown", onKeyDown);
- };
-
- }, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, movedObjects, socket, floorItems, rotatedObjects]);
-
- useFrame(() => {
- if (pastedObjects.length > 0) {
- const intersectionPoint = new THREE.Vector3();
- raycaster.setFromCamera(pointer, camera);
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
- if (point) {
- const position = new THREE.Vector3();
- if (boundingBoxRef.current) {
- boundingBoxRef.current?.getWorldPosition(position)
- selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z));
- } else {
- const box = new THREE.Box3();
- pastedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone()));
- const center = new THREE.Vector3();
- box.getCenter(center);
- selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z));
- }
- }
- }
- });
-
- const copySelection = () => {
- if (selectedAssets.length > 0) {
- const newClones = selectedAssets.map((asset: any) => {
- const clone = asset.clone();
- clone.position.copy(asset.position);
- return clone;
- });
- setCopiedObjects(newClones);
- toast.info("Objects copied!");
- }
- };
-
- const pasteCopiedObjects = () => {
- if (copiedObjects.length > 0 && pastedObjects.length === 0) {
- const newClones = copiedObjects.map((obj: THREE.Object3D) => {
- const clone = obj.clone();
- clone.position.copy(obj.position);
- return clone;
- });
- selectionGroup.current.add(...newClones);
- setpastedObjects([...newClones]);
- setSelectedAssets([...newClones]);
-
- const intersectionPoint = new THREE.Vector3();
- raycaster.setFromCamera(pointer, camera);
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
-
- if (point) {
- const position = new THREE.Vector3();
- if (boundingBoxRef.current) {
- boundingBoxRef.current?.getWorldPosition(position)
- selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z));
- } else {
- const box = new THREE.Box3();
- newClones.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone()));
- const center = new THREE.Vector3();
- box.getCenter(center);
- selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z));
- }
- }
- }
- };
-
- const addPastedObjects = () => {
- if (pastedObjects.length === 0) return;
- pastedObjects.forEach(async (obj: THREE.Object3D) => {
- const worldPosition = new THREE.Vector3();
- obj.getWorldPosition(worldPosition);
- obj.position.copy(worldPosition);
-
- if (itemsGroupRef.current) {
-
- const newFloorItem: Types.FloorItemType = {
- modeluuid: obj.uuid,
- modelname: obj.userData.name,
- modelfileID: obj.userData.modelId,
- position: [worldPosition.x, worldPosition.y, worldPosition.z],
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
- isLocked: false,
- isVisible: true
- };
-
- setFloorItems((prevItems: Types.FloorItems) => {
- const updatedItems = [...(prevItems || []), newFloorItem];
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
-
- let eventData: SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema | undefined = simulationStates.find((events) => events.modeluuid === obj.userData.modeluuid);
-
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "default";
- if (eventData) {
- if (eventData.type === 'Conveyor' && eventData) {
- const createConveyorPoint = (index: number) => {
- const pointUUID = THREE.MathUtils.generateUUID();
- const hasActions = (eventData as SimulationTypes.ConveyorEventsSchema)?.points[index].actions.length > 0;
-
- const defaultAction = {
- uuid: THREE.MathUtils.generateUUID(),
- name: 'Action 1',
- type: 'Inherit',
- material: 'Inherit',
- delay: 'Inherit',
- spawnInterval: 'Inherit',
- isUsed: true
- };
-
- return {
- uuid: pointUUID,
- position: (eventData as SimulationTypes.ConveyorEventsSchema)?.points[index].position,
- rotation: (eventData as SimulationTypes.ConveyorEventsSchema)?.points[index].rotation,
- actions: hasActions
- ? (eventData as SimulationTypes.ConveyorEventsSchema)?.points[index].actions.map(action => ({
- ...action,
- uuid: THREE.MathUtils.generateUUID()
- }))
- : [defaultAction],
- triggers: (eventData as SimulationTypes.ConveyorEventsSchema)?.points[index].triggers.map(trigger => ({
- ...trigger,
- uuid: THREE.MathUtils.generateUUID()
- })),
- connections: {
- source: { modelUUID: obj.uuid, pointUUID },
- targets: []
- }
- };
- };
-
- const backendEventData = {
- type: 'Conveyor',
- points: [
- createConveyorPoint(0), // point1
- createConveyorPoint(1), // middlePoint
- createConveyorPoint(2) // point2
- ],
- speed: (eventData as SimulationTypes.ConveyorEventsSchema)?.speed
- };
-
- //REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // obj.userData.modelId,
- // false,
- // true,
- // backendEventData
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- newEventData as SimulationTypes.ConveyorEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'Vehicle' && eventData) {
- const createVehiclePoint = () => {
- const pointUUID = THREE.MathUtils.generateUUID();
- const vehiclePoint = (eventData as SimulationTypes.VehicleEventsSchema)?.points;
- const hasActions = vehiclePoint?.actions !== undefined;
-
- const defaultAction = {
- uuid: THREE.MathUtils.generateUUID(),
- name: 'Action 1',
- type: 'Inherit',
- start: {},
- hitCount: 0,
- end: {},
- buffer: 0
- };
-
- return {
- uuid: pointUUID,
- position: vehiclePoint?.position,
- // rotation: vehiclePoint?.rotation,
- actions: hasActions
- ? {
- ...vehiclePoint.actions,
- uuid: THREE.MathUtils.generateUUID()
- }
- : defaultAction,
- connections: {
- source: { modelUUID: obj.uuid, pointUUID },
- targets: []
- },
- speed: vehiclePoint?.speed || 1
- };
- };
-
- const backendEventData = {
- type: 'Vehicle',
- points: createVehiclePoint(),
- };
-
- // API
-
- // setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- newEventData as SimulationTypes.VehicleEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'StaticMachine' && eventData) {
- const createStaticMachinePoint = () => {
- const pointUUID = THREE.MathUtils.generateUUID();
- const staticMachinePoint = (eventData as SimulationTypes.StaticMachineEventsSchema)?.points;
- const hasActions = staticMachinePoint?.actions !== undefined;
-
- const defaultAction = {
- uuid: THREE.MathUtils.generateUUID(),
- name: 'Action 1',
- buffer: 0,
- material: 'Inherit',
- };
-
- return {
- uuid: pointUUID,
- position: staticMachinePoint?.position,
- rotation: staticMachinePoint?.rotation,
- actions: hasActions
- ? {
- ...staticMachinePoint.actions,
- uuid: THREE.MathUtils.generateUUID()
- }
- : defaultAction,
- triggers: { uuid: THREE.MathUtils.generateUUID(), name: 'Trigger 1', type: 'OnComplete' },
- connections: {
- source: { modelUUID: obj.uuid, pointUUID },
- targets: []
- }
- };
- };
-
- const backendEventData = {
- type: 'StaticMachine',
- points: createStaticMachinePoint()
- };
-
- // API
-
- // setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- newEventData as SimulationTypes.StaticMachineEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'ArmBot' && eventData) {
- const createArmBotPoint = () => {
- const pointUUID = THREE.MathUtils.generateUUID();
- const armBotPoint = (eventData as SimulationTypes.ArmBotEventsSchema)?.points;
- const hasActions = armBotPoint?.actions !== undefined;
-
- const defaultAction = {
- uuid: THREE.MathUtils.generateUUID(),
- name: 'Action 1',
- buffer: 0,
- material: 'Inherit',
- };
-
- return {
- uuid: pointUUID,
- position: armBotPoint?.position,
- rotation: armBotPoint?.rotation,
- actions: hasActions
- ? {
- ...armBotPoint.actions,
- uuid: THREE.MathUtils.generateUUID(),
- processes: []
- }
- : defaultAction,
- triggers: {
- uuid: THREE.MathUtils.generateUUID(),
- name: armBotPoint.triggers.name,
- type: armBotPoint.triggers.type,
- },
- connections: {
- source: { modelUUID: obj.uuid, pointUUID },
- targets: []
- }
- };
- };
-
- const backendEventData = {
- type: 'ArmBot',
- points: createArmBotPoint()
- };
-
- // API
-
- // setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- newEventData as SimulationTypes.ArmBotEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else {
-
- //REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // obj.userData.modelId,
- // false,
- // true,
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- socketId: socket.id,
- };
-
- socket.emit("v2:model-asset:add", data);
-
- }
- } else {
-
- //REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // obj.userData.modelId,
- // false,
- // true,
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- socketId: socket.id,
- };
-
- socket.emit("v2:model-asset:add", data);
-
- }
-
- obj.userData.modeluuid = newFloorItem.modeluuid;
- itemsGroupRef.current.add(obj);
- }
- });
-
- toast.success("Object added!");
- clearSelection();
- };
-
- const clearSelection = () => {
- selectionGroup.current.children = [];
- selectionGroup.current.position.set(0, 0, 0);
- selectionGroup.current.rotation.set(0, 0, 0);
- setMovedObjects([]);
- setpastedObjects([]);
- setDuplicatedObjects([]);
- setRotatedObjects([]);
- setSelectedAssets([]);
- }
-
- return null; // No visible output, but the component handles copy-paste functionality
-};
-
-export default CopyPasteControls;
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selection/duplicationControls.tsx b/app/src/modules/scene/controls/selection/duplicationControls.tsx
deleted file mode 100644
index 915cb61..0000000
--- a/app/src/modules/scene/controls/selection/duplicationControls.tsx
+++ /dev/null
@@ -1,560 +0,0 @@
-import * as THREE from "three";
-import { useEffect, useMemo } from "react";
-import { useFrame, useThree } from "@react-three/fiber";
-import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView } from "../../../../store/store";
-import { toast } from "react-toastify";
-// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
-import * as Types from "../../../../types/world/worldTypes";
-import * as SimulationTypes from "../../../../types/simulationTypes";
-import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
-import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
-
-const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedObjects, setpastedObjects, selectionGroup, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => {
- const { camera, controls, gl, scene, pointer, raycaster } = useThree();
- const { toggleView } = useToggleView();
- const { selectedAssets, setSelectedAssets } = useSelectedAssets();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
- const { floorItems, setFloorItems } = useFloorItems();
- const { socket } = useSocketStore();
-
- useEffect(() => {
- if (!camera || !scene || toggleView) return;
- const canvasElement = gl.domElement;
- canvasElement.tabIndex = 0;
-
- let isMoving = false;
-
- const onPointerDown = () => {
- isMoving = false;
- };
-
- const onPointerMove = () => {
- isMoving = true;
- };
-
- const onPointerUp = (event: PointerEvent) => {
- if (!isMoving && duplicatedObjects.length > 0 && event.button === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
- event.preventDefault();
- addDuplicatedAssets();
- }
- };
-
- const onKeyDown = (event: KeyboardEvent) => {
- const keyCombination = detectModifierKeys(event);
-
- if (keyCombination === "Ctrl+D" && selectedAssets.length > 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
- duplicateSelection();
- }
- };
-
- if (!toggleView) {
- canvasElement.addEventListener("pointerdown", onPointerDown);
- canvasElement.addEventListener("pointermove", onPointerMove);
- canvasElement.addEventListener("pointerup", onPointerUp);
- canvasElement.addEventListener("keydown", onKeyDown);
- }
-
- return () => {
- canvasElement.removeEventListener("pointerdown", onPointerDown);
- canvasElement.removeEventListener("pointermove", onPointerMove);
- canvasElement.removeEventListener("pointerup", onPointerUp);
- canvasElement.removeEventListener("keydown", onKeyDown);
- };
-
- }, [camera, controls, scene, toggleView, selectedAssets, duplicatedObjects, movedObjects, socket, floorItems, rotatedObjects]);
-
- useFrame(() => {
- if (duplicatedObjects.length > 0) {
- const intersectionPoint = new THREE.Vector3();
- raycaster.setFromCamera(pointer, camera);
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
- if (point) {
- const position = new THREE.Vector3();
- if (boundingBoxRef.current) {
- boundingBoxRef.current?.getWorldPosition(position)
- selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z));
- } else {
- const box = new THREE.Box3();
- duplicatedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone()));
- const center = new THREE.Vector3();
- box.getCenter(center);
- selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z));
- }
- }
- }
- });
-
- const duplicateSelection = () => {
- if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
- const newClones = selectedAssets.map((asset: any) => {
- const clone = asset.clone();
- clone.position.copy(asset.position);
- return clone;
- });
-
- selectionGroup.current.add(...newClones);
- setDuplicatedObjects(newClones);
-
- const intersectionPoint = new THREE.Vector3();
- raycaster.setFromCamera(pointer, camera);
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
-
- if (point) {
- const position = new THREE.Vector3();
- boundingBoxRef.current?.getWorldPosition(position)
- selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z));
- }
- }
- };
-
- const addDuplicatedAssets = () => {
- if (duplicatedObjects.length === 0) return;
- duplicatedObjects.forEach(async (obj: THREE.Object3D) => {
- const worldPosition = new THREE.Vector3();
- obj.getWorldPosition(worldPosition);
- obj.position.copy(worldPosition);
-
- if (itemsGroupRef.current) {
-
- const newFloorItem: Types.FloorItemType = {
- modeluuid: obj.uuid,
- modelname: obj.userData.name,
- modelfileID: obj.userData.modelId,
- position: [worldPosition.x, worldPosition.y, worldPosition.z],
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
- isLocked: false,
- isVisible: true
- };
-
- setFloorItems((prevItems: Types.FloorItems) => {
- const updatedItems = [...(prevItems || []), newFloorItem];
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
-
- let eventData: SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema | undefined = simulationStates.find((events) => events.modeluuid === obj.userData.modeluuid);
-
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "default";
-
- if (eventData) {
- if (eventData.type === 'Conveyor' && eventData) {
- const createConveyorPoint = (index: number) => {
- const pointUUID = THREE.MathUtils.generateUUID();
- const hasActions = (eventData as SimulationTypes.ConveyorEventsSchema)?.points[index].actions.length > 0;
-
- const defaultAction = {
- uuid: THREE.MathUtils.generateUUID(),
- name: 'Action 1',
- type: 'Inherit',
- material: 'Inherit',
- delay: 'Inherit',
- spawnInterval: 'Inherit',
- isUsed: true
- };
-
- return {
- uuid: pointUUID,
- position: (eventData as SimulationTypes.ConveyorEventsSchema)?.points[index].position,
- rotation: (eventData as SimulationTypes.ConveyorEventsSchema)?.points[index].rotation,
- actions: hasActions
- ? (eventData as SimulationTypes.ConveyorEventsSchema)?.points[index].actions.map(action => ({
- ...action,
- uuid: THREE.MathUtils.generateUUID()
- }))
- : [defaultAction],
- triggers: (eventData as SimulationTypes.ConveyorEventsSchema)?.points[index].triggers.map(trigger => ({
- ...trigger,
- uuid: THREE.MathUtils.generateUUID()
- })),
- connections: {
- source: { modelUUID: newFloorItem.modeluuid, pointUUID },
- targets: []
- }
- };
- };
-
- const backendEventData = {
- type: 'Conveyor',
- points: [
- createConveyorPoint(0),
- createConveyorPoint(1),
- createConveyorPoint(2)
- ],
- speed: (eventData as SimulationTypes.ConveyorEventsSchema)?.speed
- };
-
- //REST
-
- // setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed }
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- newEventData as SimulationTypes.ConveyorEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'Vehicle' && eventData) {
- const createVehiclePoint = () => {
- const pointUUID = THREE.MathUtils.generateUUID();
- const vehiclePoint = (eventData as SimulationTypes.VehicleEventsSchema)?.points;
- const hasActions = vehiclePoint?.actions !== undefined;
-
- const defaultAction = {
- uuid: THREE.MathUtils.generateUUID(),
- name: 'Action 1',
- type: 'Inherit',
- start: {},
- hitCount: 0,
- end: {},
- buffer: 0
- };
-
- return {
- uuid: pointUUID,
- position: vehiclePoint?.position,
- rotation: vehiclePoint?.rotation,
- actions: hasActions
- ? {
- ...vehiclePoint.actions,
- uuid: THREE.MathUtils.generateUUID()
- }
- : defaultAction,
- connections: {
- source: { modelUUID: obj.uuid, pointUUID },
- targets: []
- },
- speed: vehiclePoint?.speed || 2
- };
- };
-
- const backendEventData = {
- type: 'Vehicle',
- points: createVehiclePoint()
- };
-
- // API
-
- // setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- newEventData as SimulationTypes.VehicleEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'StaticMachine' && eventData) {
- const createStaticMachinePoint = () => {
- const pointUUID = THREE.MathUtils.generateUUID();
- const staticMachinePoint = (eventData as SimulationTypes.StaticMachineEventsSchema)?.points;
- const hasActions = staticMachinePoint?.actions !== undefined;
-
- const defaultAction = {
- uuid: THREE.MathUtils.generateUUID(),
- name: 'Action 1',
- buffer: 0,
- material: 'Inherit',
- };
-
- return {
- uuid: pointUUID,
- position: staticMachinePoint?.position,
- rotation: staticMachinePoint?.rotation,
- actions: hasActions
- ? {
- ...staticMachinePoint.actions,
- uuid: THREE.MathUtils.generateUUID()
- }
- : defaultAction,
- triggers: { uuid: THREE.MathUtils.generateUUID(), name: 'Trigger 1', type: 'OnComplete' },
- connections: {
- source: { modelUUID: obj.uuid, pointUUID },
- targets: []
- }
- };
- };
-
- const backendEventData = {
- type: 'StaticMachine',
- points: createStaticMachinePoint()
- };
-
- // API
-
- // setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- newEventData as SimulationTypes.StaticMachineEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'ArmBot' && eventData) {
- const createArmBotPoint = () => {
- const pointUUID = THREE.MathUtils.generateUUID();
- const armBotPoint = (eventData as SimulationTypes.ArmBotEventsSchema)?.points;
- const hasActions = armBotPoint?.actions !== undefined;
-
- const defaultAction = {
- uuid: THREE.MathUtils.generateUUID(),
- name: 'Action 1',
- buffer: 0,
- material: 'Inherit',
- };
-
- return {
- uuid: pointUUID,
- position: armBotPoint?.position,
- rotation: armBotPoint?.rotation,
- actions: hasActions
- ? {
- ...armBotPoint.actions,
- uuid: THREE.MathUtils.generateUUID(),
- processes: []
- }
- : defaultAction,
- triggers: {
- uuid: THREE.MathUtils.generateUUID(),
- name: armBotPoint.triggers.name,
- type: armBotPoint.triggers.type,
- },
- connections: {
- source: { modelUUID: obj.uuid, pointUUID },
- targets: []
- }
- };
- };
-
- const backendEventData = {
- type: 'ArmBot',
- points: createArmBotPoint()
- };
-
- // API
-
- // setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- // SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => [
- ...(prevEvents || []),
- newEventData as SimulationTypes.ArmBotEventsSchema
- ]);
-
- socket.emit("v2:model-asset:add", data);
-
- } else {
-
- //REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // obj.userData.modelId,
- // false,
- // true,
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- socketId: socket.id,
- };
-
- socket.emit("v2:model-asset:add", data);
-
- }
- } else {
-
- //REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // obj.userData.modelId,
- // false,
- // true,
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- socketId: socket.id,
- };
-
- socket.emit("v2:model-asset:add", data);
-
- }
-
- obj.userData.modeluuid = newFloorItem.modeluuid;
- itemsGroupRef.current.add(obj);
- }
- });
-
- toast.success("Object duplicated!");
- clearSelection();
- }
-
- const clearSelection = () => {
- selectionGroup.current.children = [];
- selectionGroup.current.position.set(0, 0, 0);
- selectionGroup.current.rotation.set(0, 0, 0);
- setMovedObjects([]);
- setpastedObjects([]);
- setDuplicatedObjects([]);
- setRotatedObjects([]);
- setSelectedAssets([]);
- }
-
- return null; // This component does not render any UI
-};
-
-export default DuplicationControls;
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selection/moveControls.tsx b/app/src/modules/scene/controls/selection/moveControls.tsx
deleted file mode 100644
index d717ecb..0000000
--- a/app/src/modules/scene/controls/selection/moveControls.tsx
+++ /dev/null
@@ -1,463 +0,0 @@
-import * as THREE from "three";
-import { useEffect, useMemo, useRef, useState } from "react";
-import { useFrame, useThree } from "@react-three/fiber";
-import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView } from "../../../../store/store";
-// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
-import { toast } from "react-toastify";
-import * as Types from "../../../../types/world/worldTypes";
-import * as SimulationTypes from "../../../../types/simulationTypes";
-import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
-
-function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {
- const { camera, controls, gl, scene, pointer, raycaster } = useThree();
- const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
-
- const { toggleView } = useToggleView();
- const { selectedAssets, setSelectedAssets } = useSelectedAssets();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const { floorItems, setFloorItems } = useFloorItems();
- const { socket } = useSocketStore();
- const itemsData = useRef([]);
-
- useEffect(() => {
- if (!camera || !scene || toggleView || !itemsGroupRef.current) return;
-
- const canvasElement = gl.domElement;
- canvasElement.tabIndex = 0;
-
- let isMoving = false;
-
- const onPointerDown = () => {
- isMoving = false;
- };
-
- const onPointerMove = () => {
- isMoving = true;
- };
-
- const onPointerUp = (event: PointerEvent) => {
- if (!isMoving && movedObjects.length > 0 && event.button === 0) {
- event.preventDefault();
- placeMovedAssets();
- }
- if (!isMoving && movedObjects.length > 0 && event.button === 2) {
- event.preventDefault();
-
- clearSelection();
- movedObjects.forEach((asset: any) => {
- if (itemsGroupRef.current) {
- itemsGroupRef.current.attach(asset);
- }
- });
-
- setFloorItems([...floorItems, ...itemsData.current]);
-
- setMovedObjects([]);
- itemsData.current = [];
- }
- };
-
- const onKeyDown = (event: KeyboardEvent) => {
- const keyCombination = detectModifierKeys(event);
-
- if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0) return;
- if (keyCombination === "G") {
- if (selectedAssets.length > 0) {
- moveAssets();
- itemsData.current = floorItems.filter((item: { modeluuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modeluuid));
- }
- }
- if (keyCombination === "ESCAPE") {
- event.preventDefault();
-
- clearSelection();
- movedObjects.forEach((asset: any) => {
- if (itemsGroupRef.current) {
- itemsGroupRef.current.attach(asset);
- }
- });
-
- setFloorItems([...floorItems, ...itemsData.current]);
-
- setMovedObjects([]);
- itemsData.current = [];
- }
- };
-
- if (!toggleView) {
- canvasElement.addEventListener("pointerdown", onPointerDown);
- canvasElement.addEventListener("pointermove", onPointerMove);
- canvasElement.addEventListener("pointerup", onPointerUp);
- canvasElement.addEventListener("keydown", onKeyDown);
- }
-
- return () => {
- canvasElement.removeEventListener("pointerdown", onPointerDown);
- canvasElement.removeEventListener("pointermove", onPointerMove);
- canvasElement.removeEventListener("pointerup", onPointerUp);
- canvasElement.removeEventListener("keydown", onKeyDown);
- };
- }, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects]);
-
- const gridSize = 0.25;
- const moveSpeed = 0.25;
- const isGridSnap = false;
-
- useFrame(() => {
- if (movedObjects.length > 0) {
- const intersectionPoint = new THREE.Vector3();
- raycaster.setFromCamera(pointer, camera);
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
-
- if (point) {
- let targetX = point.x;
- let targetZ = point.z;
-
- if (isGridSnap) {
- targetX = Math.round(point.x / gridSize) * gridSize;
- targetZ = Math.round(point.z / gridSize) * gridSize;
- }
-
- const position = new THREE.Vector3();
- if (boundingBoxRef.current) {
- boundingBoxRef.current.getWorldPosition(position);
- selectionGroup.current.position.lerp(
- new THREE.Vector3(
- targetX - (position.x - selectionGroup.current.position.x),
- selectionGroup.current.position.y,
- targetZ - (position.z - selectionGroup.current.position.z)
- ),
- moveSpeed
- );
- } else {
- const box = new THREE.Box3();
- movedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj));
- const center = new THREE.Vector3();
- box.getCenter(center);
-
- selectionGroup.current.position.lerp(
- new THREE.Vector3(
- targetX - (center.x - selectionGroup.current.position.x),
- selectionGroup.current.position.y,
- targetZ - (center.z - selectionGroup.current.position.z)
- ),
- moveSpeed
- );
- }
- }
- }
- });
-
-
- const moveAssets = () => {
- const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modeluuid));
- setFloorItems(updatedItems);
- setMovedObjects(selectedAssets);
- selectedAssets.forEach((asset: any) => { selectionGroup.current.attach(asset); });
- }
-
- const placeMovedAssets = () => {
- if (movedObjects.length === 0) return;
-
- movedObjects.forEach(async (obj: THREE.Object3D) => {
- const worldPosition = new THREE.Vector3();
- obj.getWorldPosition(worldPosition);
-
- selectionGroup.current.remove(obj);
- obj.position.copy(worldPosition);
-
- if (itemsGroupRef.current) {
-
- const newFloorItem: Types.FloorItemType = {
- modeluuid: obj.uuid,
- modelname: obj.userData.name,
- modelfileID: obj.userData.modelId,
- position: [worldPosition.x, worldPosition.y, worldPosition.z],
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
- isLocked: false,
- isVisible: true
- };
-
- setFloorItems((prevItems: Types.FloorItems) => {
- const updatedItems = [...(prevItems || []), newFloorItem];
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
-
- let eventData: SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema | undefined = simulationStates.find((events) => events.modeluuid === obj.userData.modeluuid);
-
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "default";
-
- if (eventData) {
- if (eventData.type === 'Conveyor' && eventData) {
-
- const backendEventData = {
- type: 'Conveyor',
- points: eventData.points,
- speed: (eventData as SimulationTypes.ConveyorEventsSchema)?.speed
- };
-
- //REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // obj.userData.modelId,
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed }
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- const updatedEvents = (prevEvents || []).map(event =>
- event.modeluuid === newFloorItem.modeluuid
- ? { ...event, ...newEventData }
- : event
- );
- return updatedEvents;
- });
-
- socket.emit("v2:model-asset:add", data);
- } else if (eventData.type === 'Vehicle' && eventData) {
-
- const backendEventData = {
- type: 'Vehicle',
- points: eventData.points
- };
-
- // REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- const updatedEvents = (prevEvents || []).map(event =>
- event.modeluuid === newFloorItem.modeluuid
- ? { ...event, ...newEventData }
- : event
- );
- return updatedEvents;
- });
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'StaticMachine' && eventData) {
-
- const backendEventData = {
- type: 'StaticMachine',
- points: eventData.points,
- };
-
- // REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- const updatedEvents = (prevEvents || []).map(event =>
- event.modeluuid === newFloorItem.modeluuid
- ? { ...event, ...newEventData }
- : event
- );
- return updatedEvents;
- });
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'ArmBot' && eventData) {
-
- const backendEventData = {
- type: 'ArmBot',
- points: eventData.points,
- };
-
- // REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- const updatedEvents = (prevEvents || []).map(event =>
- event.modeluuid === newFloorItem.modeluuid
- ? { ...event, ...newEventData }
- : event
- );
- return updatedEvents;
- });
-
- socket.emit("v2:model-asset:add", data);
-
- }
- } else {
-
-
- //REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // obj.userData.modelId,
- // false,
- // true,
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- socketId: socket.id,
- };
-
- socket.emit("v2:model-asset:add", data);
-
- }
-
- itemsGroupRef.current.add(obj);
- }
- });
- toast.success("Object moved!");
-
- itemsData.current = [];
- clearSelection();
- }
-
- const clearSelection = () => {
- selectionGroup.current.children = [];
- selectionGroup.current.position.set(0, 0, 0);
- selectionGroup.current.rotation.set(0, 0, 0);
- setpastedObjects([]);
- setDuplicatedObjects([]);
- setMovedObjects([]);
- setRotatedObjects([]);
- setSelectedAssets([]);
- }
-
- return null; // No need to return anything, as this component is used for its side effects
-}
-
-export default MoveControls
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selection/rotateControls.tsx b/app/src/modules/scene/controls/selection/rotateControls.tsx
deleted file mode 100644
index f602bc4..0000000
--- a/app/src/modules/scene/controls/selection/rotateControls.tsx
+++ /dev/null
@@ -1,464 +0,0 @@
-import * as THREE from "three";
-import { useEffect, useMemo, useRef, useState } from "react";
-import { useFrame, useThree } from "@react-three/fiber";
-import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView } from "../../../../store/store";
-// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
-import { toast } from "react-toastify";
-import * as Types from "../../../../types/world/worldTypes";
-import * as SimulationTypes from "../../../../types/simulationTypes";
-import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
-
-function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {
- const { camera, controls, gl, scene, pointer, raycaster } = useThree();
- const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
-
- const { toggleView } = useToggleView();
- const { selectedAssets, setSelectedAssets } = useSelectedAssets();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const { floorItems, setFloorItems } = useFloorItems();
- const { socket } = useSocketStore();
- const itemsData = useRef([]);
-
- const prevPointerPosition = useRef(null);
-
- useEffect(() => {
- if (!camera || !scene || toggleView || !itemsGroupRef.current) return;
-
- const canvasElement = gl.domElement;
- canvasElement.tabIndex = 0;
-
- let isMoving = false;
-
- const onPointerDown = () => {
- isMoving = false;
- };
-
- const onPointerMove = () => {
- isMoving = true;
- };
-
- const onPointerUp = (event: PointerEvent) => {
- if (!isMoving && rotatedObjects.length > 0 && event.button === 0) {
- event.preventDefault();
- placeRotatedAssets();
- }
- if (!isMoving && rotatedObjects.length > 0 && event.button === 2) {
- event.preventDefault();
-
- clearSelection();
- rotatedObjects.forEach((asset: any) => {
- if (itemsGroupRef.current) {
- itemsGroupRef.current.attach(asset);
- }
- });
-
- setFloorItems([...floorItems, ...itemsData.current]);
-
- setRotatedObjects([]);
- itemsData.current = [];
- }
- };
-
- const onKeyDown = (event: KeyboardEvent) => {
- if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || movedObjects.length > 0) return;
- if (event.key.toLowerCase() === "r") {
- if (selectedAssets.length > 0) {
- rotateAssets();
- itemsData.current = floorItems.filter((item: { modeluuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modeluuid));
- }
- }
- if (event.key.toLowerCase() === "escape") {
- event.preventDefault();
-
- clearSelection();
- rotatedObjects.forEach((asset: any) => {
- if (itemsGroupRef.current) {
- itemsGroupRef.current.attach(asset);
- }
- });
-
- setFloorItems([...floorItems, ...itemsData.current]);
-
- setRotatedObjects([]);
- itemsData.current = [];
- }
- };
-
- if (!toggleView) {
- canvasElement.addEventListener("pointerdown", onPointerDown);
- canvasElement.addEventListener("pointermove", onPointerMove);
- canvasElement.addEventListener("pointerup", onPointerUp);
- canvasElement.addEventListener("keydown", onKeyDown);
- }
-
- return () => {
- canvasElement.removeEventListener("pointerdown", onPointerDown);
- canvasElement.removeEventListener("pointermove", onPointerMove);
- canvasElement.removeEventListener("pointerup", onPointerUp);
- canvasElement.removeEventListener("keydown", onKeyDown);
- };
- }, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, rotatedObjects, movedObjects]);
-
- useFrame(() => {
- if (rotatedObjects.length > 0) {
- const intersectionPoint = new THREE.Vector3();
- raycaster.setFromCamera(pointer, camera);
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
-
- if (point && prevPointerPosition.current) {
- const box = new THREE.Box3();
- rotatedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj));
- const center = new THREE.Vector3();
- box.getCenter(center);
-
- const delta = new THREE.Vector3().subVectors(point, center);
- const prevPointerPosition3D = new THREE.Vector3(prevPointerPosition.current.x, 0, prevPointerPosition.current.y);
-
- const angle = Math.atan2(delta.z, delta.x) - Math.atan2(prevPointerPosition3D.z - center.z, prevPointerPosition3D.x - center.x);
-
- selectionGroup.current.rotation.y += -angle;
-
- selectionGroup.current.position.sub(center);
- selectionGroup.current.position.applyAxisAngle(new THREE.Vector3(0, 1, 0), -angle);
- selectionGroup.current.position.add(center);
-
- prevPointerPosition.current = new THREE.Vector2(point.x, point.z);
- }
- }
- });
-
- const rotateAssets = () => {
- const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modeluuid));
- setFloorItems(updatedItems);
-
- const box = new THREE.Box3();
- selectedAssets.forEach((asset: any) => box.expandByObject(asset));
- const center = new THREE.Vector3();
- box.getCenter(center);
-
- const intersectionPoint = new THREE.Vector3();
- raycaster.setFromCamera(pointer, camera);
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
-
- if (point) {
- prevPointerPosition.current = new THREE.Vector2(point.x, point.z);
- }
-
- selectedAssets.forEach((asset: any) => {
- selectionGroup.current.attach(asset);
- });
-
- setRotatedObjects(selectedAssets);
- };
-
- const placeRotatedAssets = () => {
- if (rotatedObjects.length === 0) return;
-
- rotatedObjects.forEach(async (obj: THREE.Object3D) => {
- const worldPosition = new THREE.Vector3();
- const worldQuaternion = new THREE.Quaternion();
-
- obj.getWorldPosition(worldPosition);
- obj.getWorldQuaternion(worldQuaternion);
-
- selectionGroup.current.remove(obj);
-
- obj.position.copy(worldPosition);
- obj.quaternion.copy(worldQuaternion);
-
-
- if (itemsGroupRef.current) {
-
- const newFloorItem: Types.FloorItemType = {
- modeluuid: obj.uuid,
- modelname: obj.userData.name,
- modelfileID: obj.userData.modelId,
- position: [worldPosition.x, worldPosition.y, worldPosition.z],
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
- isLocked: false,
- isVisible: true
- };
-
- setFloorItems((prevItems: Types.FloorItems) => {
- const updatedItems = [...(prevItems || []), newFloorItem];
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
-
- let eventData: SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema | undefined = simulationStates.find((events) => events.modeluuid === obj.userData.modeluuid);
-
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "default";
-
- if (eventData) {
- if (eventData.type === 'Conveyor' && eventData) {
-
- const backendEventData = {
- type: 'Conveyor',
- points: eventData.points,
- speed: (eventData as SimulationTypes.ConveyorEventsSchema)?.speed
- };
-
- // REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed }
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points, speed: backendEventData.speed };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- const updatedEvents = (prevEvents || []).map(event =>
- event.modeluuid === newFloorItem.modeluuid
- ? { ...event, ...newEventData }
- : event
- );
- return updatedEvents;
- });
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'Vehicle' && eventData) {
-
- const backendEventData = {
- type: 'Vehicle',
- points: eventData.points
- };
-
- // REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- const updatedEvents = (prevEvents || []).map(event =>
- event.modeluuid === newFloorItem.modeluuid
- ? { ...event, ...newEventData }
- : event
- );
- return updatedEvents;
- });
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'StaticMachine' && eventData) {
-
- const backendEventData = {
- type: 'StaticMachine',
- points: eventData.points,
- };
-
- // REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- const updatedEvents = (prevEvents || []).map(event =>
- event.modeluuid === newFloorItem.modeluuid
- ? { ...event, ...newEventData }
- : event
- );
- return updatedEvents;
- });
-
- socket.emit("v2:model-asset:add", data);
-
- } else if (eventData.type === 'ArmBot' && eventData) {
-
- const backendEventData = {
- type: 'ArmBot',
- points: eventData.points,
- };
-
- // REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // obj.userData.modelId,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // false,
- // true,
- // { type: backendEventData.type, points: backendEventData.points }
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- eventData: { type: backendEventData.type, points: backendEventData.points },
- socketId: socket.id,
- };
-
- const newEventData: any = { type: backendEventData.type, points: backendEventData.points };
- newEventData.modeluuid = newFloorItem.modeluuid;
- newEventData.modelName = newFloorItem.modelname;
- newEventData.position = newFloorItem.position;
- newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
-
- setSimulationStates((prevEvents: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- const updatedEvents = (prevEvents || []).map(event =>
- event.modeluuid === newFloorItem.modeluuid
- ? { ...event, ...newEventData }
- : event
- );
- return updatedEvents;
- });
-
- socket.emit("v2:model-asset:add", data);
-
- }
- } else {
-
- //REST
-
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // obj.userData.modelId,
- // false,
- // true,
- // );
-
- //SOCKET
-
- const data = {
- organization,
- modeluuid: newFloorItem.modeluuid,
- modelname: newFloorItem.modelname,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- socketId: socket.id,
- };
-
- socket.emit("v2:model-asset:add", data);
-
- }
-
- itemsGroupRef.current.add(obj);
- }
- });
- toast.success("Object rotated!");
-
- itemsData.current = [];
- clearSelection();
- }
-
- const clearSelection = () => {
- selectionGroup.current.children = [];
- selectionGroup.current.position.set(0, 0, 0);
- selectionGroup.current.rotation.set(0, 0, 0);
- setpastedObjects([]);
- setDuplicatedObjects([]);
- setMovedObjects([]);
- setRotatedObjects([]);
- setSelectedAssets([]);
- }
-
- return null; // No need to return anything, as this component is used for its side effects
-}
-
-export default RotateControls
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selection/boundingBoxHelper.tsx b/app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx
similarity index 97%
rename from app/src/modules/scene/controls/selection/boundingBoxHelper.tsx
rename to app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx
index dd9d251..df57bf9 100644
--- a/app/src/modules/scene/controls/selection/boundingBoxHelper.tsx
+++ b/app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx
@@ -1,64 +1,64 @@
-import { Line } from "@react-three/drei";
-import { useMemo } from "react";
-import * as THREE from "three";
-import { useSelectedAssets } from "../../../../store/store";
-
-const BoundingBox = ({ boundingBoxRef }: any) => {
- const { selectedAssets } = useSelectedAssets();
-
- const { points, boxProps } = useMemo(() => {
- if (selectedAssets.length === 0) return { points: [], boxProps: {} };
-
- const box = new THREE.Box3();
- selectedAssets.forEach((obj: any) => box.expandByObject(obj.clone()));
-
- const size = new THREE.Vector3();
- box.getSize(size);
- const center = new THREE.Vector3();
- box.getCenter(center);
-
- const halfSize = size.clone().multiplyScalar(0.5);
- const min = center.clone().sub(halfSize);
- const max = center.clone().add(halfSize);
-
- const points: any = [
- [min.x, min.y, min.z], [max.x, min.y, min.z],
- [max.x, min.y, min.z], [max.x, max.y, min.z],
- [max.x, max.y, min.z], [min.x, max.y, min.z],
- [min.x, max.y, min.z], [min.x, min.y, min.z],
-
- [min.x, min.y, max.z], [max.x, min.y, max.z],
- [max.x, min.y, max.z], [max.x, max.y, max.z],
- [max.x, max.y, max.z], [min.x, max.y, max.z],
- [min.x, max.y, max.z], [min.x, min.y, max.z],
-
- [min.x, min.y, min.z], [min.x, min.y, max.z],
- [max.x, min.y, min.z], [max.x, min.y, max.z],
- [max.x, max.y, min.z], [max.x, max.y, max.z],
- [min.x, max.y, min.z], [min.x, max.y, max.z],
- ];
-
- return {
- points,
- boxProps: { position: center.toArray(), args: size.toArray() }
- };
- }, [selectedAssets]);
-
- const savedTheme: string | null = localStorage.getItem("theme") || "light";
-
- return (
- <>
- {points.length > 0 && (
- <>
-
-
-
-
-
- >
- )}
- >
- );
-};
-
-export default BoundingBox;
+import { Line } from "@react-three/drei";
+import { useMemo } from "react";
+import * as THREE from "three";
+import { useSelectedAssets } from "../../../../store/store";
+
+const BoundingBox = ({ boundingBoxRef }: any) => {
+ const { selectedAssets } = useSelectedAssets();
+
+ const { points, boxProps } = useMemo(() => {
+ if (selectedAssets.length === 0) return { points: [], boxProps: {} };
+
+ const box = new THREE.Box3();
+ selectedAssets.forEach((obj: any) => box.expandByObject(obj.clone()));
+
+ const size = new THREE.Vector3();
+ box.getSize(size);
+ const center = new THREE.Vector3();
+ box.getCenter(center);
+
+ const halfSize = size.clone().multiplyScalar(0.5);
+ const min = center.clone().sub(halfSize);
+ const max = center.clone().add(halfSize);
+
+ const points: any = [
+ [min.x, min.y, min.z], [max.x, min.y, min.z],
+ [max.x, min.y, min.z], [max.x, max.y, min.z],
+ [max.x, max.y, min.z], [min.x, max.y, min.z],
+ [min.x, max.y, min.z], [min.x, min.y, min.z],
+
+ [min.x, min.y, max.z], [max.x, min.y, max.z],
+ [max.x, min.y, max.z], [max.x, max.y, max.z],
+ [max.x, max.y, max.z], [min.x, max.y, max.z],
+ [min.x, max.y, max.z], [min.x, min.y, max.z],
+
+ [min.x, min.y, min.z], [min.x, min.y, max.z],
+ [max.x, min.y, min.z], [max.x, min.y, max.z],
+ [max.x, max.y, min.z], [max.x, max.y, max.z],
+ [min.x, max.y, min.z], [min.x, max.y, max.z],
+ ];
+
+ return {
+ points,
+ boxProps: { position: center.toArray(), args: size.toArray() }
+ };
+ }, [selectedAssets]);
+
+ const savedTheme: string | null = localStorage.getItem("theme") || "light";
+
+ return (
+ <>
+ {points.length > 0 && (
+ <>
+
+
+
+
+
+ >
+ )}
+ >
+ );
+};
+
+export default BoundingBox;
diff --git a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx b/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx
new file mode 100644
index 0000000..9ca4dd0
--- /dev/null
+++ b/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx
@@ -0,0 +1,211 @@
+import * as THREE from "three";
+import { useEffect, useMemo } from "react";
+import { useFrame, useThree } from "@react-three/fiber";
+import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
+import { toast } from "react-toastify";
+// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
+import * as Types from "../../../../types/world/worldTypes";
+import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
+
+const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, selectionGroup, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => {
+ const { camera, controls, gl, scene, pointer, raycaster } = useThree();
+ const { toggleView } = useToggleView();
+ const { selectedAssets, setSelectedAssets } = useSelectedAssets();
+ const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
+ const { floorItems, setFloorItems } = useFloorItems();
+ const { socket } = useSocketStore()
+
+ useEffect(() => {
+ if (!camera || !scene || toggleView) return;
+ const canvasElement = gl.domElement;
+ canvasElement.tabIndex = 0;
+
+ let isMoving = false;
+
+ const onPointerDown = () => {
+ isMoving = false;
+ };
+
+ const onPointerMove = () => {
+ isMoving = true;
+ };
+
+ const onPointerUp = (event: PointerEvent) => {
+ if (!isMoving && pastedObjects.length > 0 && event.button === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
+ event.preventDefault();
+ addPastedObjects();
+ }
+ };
+
+ const onKeyDown = (event: KeyboardEvent) => {
+ const keyCombination = detectModifierKeys(event);
+
+ if (keyCombination === "Ctrl+C" && movedObjects.length === 0 && rotatedObjects.length === 0) {
+ copySelection();
+ }
+ if (keyCombination === "Ctrl+V" && copiedObjects.length > 0 && pastedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
+ pasteCopiedObjects();
+ }
+ };
+
+ if (!toggleView) {
+ canvasElement.addEventListener("pointerdown", onPointerDown);
+ canvasElement.addEventListener("pointermove", onPointerMove);
+ canvasElement.addEventListener("pointerup", onPointerUp);
+ canvasElement.addEventListener("keydown", onKeyDown);
+ }
+
+ return () => {
+ canvasElement.removeEventListener("pointerdown", onPointerDown);
+ canvasElement.removeEventListener("pointermove", onPointerMove);
+ canvasElement.removeEventListener("pointerup", onPointerUp);
+ canvasElement.removeEventListener("keydown", onKeyDown);
+ };
+
+ }, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, movedObjects, socket, floorItems, rotatedObjects]);
+
+ useFrame(() => {
+ if (pastedObjects.length > 0) {
+ const intersectionPoint = new THREE.Vector3();
+ raycaster.setFromCamera(pointer, camera);
+ const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+ if (point) {
+ const position = new THREE.Vector3();
+ if (boundingBoxRef.current) {
+ boundingBoxRef.current?.getWorldPosition(position)
+ selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z));
+ } else {
+ const box = new THREE.Box3();
+ pastedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone()));
+ const center = new THREE.Vector3();
+ box.getCenter(center);
+ selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z));
+ }
+ }
+ }
+ });
+
+ const copySelection = () => {
+ if (selectedAssets.length > 0) {
+ const newClones = selectedAssets.map((asset: any) => {
+ const clone = asset.clone();
+ clone.position.copy(asset.position);
+ return clone;
+ });
+ setCopiedObjects(newClones);
+ toast.info("Objects copied!");
+ }
+ };
+
+ const pasteCopiedObjects = () => {
+ if (copiedObjects.length > 0 && pastedObjects.length === 0) {
+ const newClones = copiedObjects.map((obj: THREE.Object3D) => {
+ const clone = obj.clone();
+ clone.position.copy(obj.position);
+ return clone;
+ });
+ selectionGroup.current.add(...newClones);
+ setpastedObjects([...newClones]);
+ setSelectedAssets([...newClones]);
+
+ const intersectionPoint = new THREE.Vector3();
+ raycaster.setFromCamera(pointer, camera);
+ const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+
+ if (point) {
+ const position = new THREE.Vector3();
+ if (boundingBoxRef.current) {
+ boundingBoxRef.current?.getWorldPosition(position)
+ selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z));
+ } else {
+ const box = new THREE.Box3();
+ newClones.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone()));
+ const center = new THREE.Vector3();
+ box.getCenter(center);
+ selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z));
+ }
+ }
+ }
+ };
+
+ const addPastedObjects = () => {
+ if (pastedObjects.length === 0) return;
+ pastedObjects.forEach(async (obj: THREE.Object3D) => {
+ const worldPosition = new THREE.Vector3();
+ obj.getWorldPosition(worldPosition);
+ obj.position.copy(worldPosition);
+
+ if (itemsGroupRef.current) {
+
+ const newFloorItem: Types.FloorItemType = {
+ modeluuid: obj.uuid,
+ modelname: obj.userData.name,
+ modelfileID: obj.userData.modelId,
+ position: [worldPosition.x, worldPosition.y, worldPosition.z],
+ rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
+ isLocked: false,
+ isVisible: true
+ };
+
+ setFloorItems((prevItems: Types.FloorItems) => {
+ const updatedItems = [...(prevItems || []), newFloorItem];
+ localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
+ return updatedItems;
+ });
+
+ const email = localStorage.getItem("email");
+ const organization = email ? email.split("@")[1].split(".")[0] : "default";
+
+ //REST
+
+ // await setFloorItemApi(
+ // organization,
+ // obj.uuid,
+ // obj.userData.name,
+ // [worldPosition.x, worldPosition.y, worldPosition.z],
+ // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
+ // obj.userData.modelId,
+ // false,
+ // true,
+ // );
+
+ //SOCKET
+
+ const data = {
+ organization,
+ modeluuid: newFloorItem.modeluuid,
+ modelname: newFloorItem.modelname,
+ modelfileID: newFloorItem.modelfileID,
+ position: newFloorItem.position,
+ rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
+ isLocked: false,
+ isVisible: true,
+ socketId: socket.id,
+ };
+
+ socket.emit("v2:model-asset:add", data);
+
+ obj.userData.modeluuid = newFloorItem.modeluuid;
+ itemsGroupRef.current.add(obj);
+ }
+ });
+
+ toast.success("Object added!");
+ clearSelection();
+ };
+
+ const clearSelection = () => {
+ selectionGroup.current.children = [];
+ selectionGroup.current.position.set(0, 0, 0);
+ selectionGroup.current.rotation.set(0, 0, 0);
+ setMovedObjects([]);
+ setpastedObjects([]);
+ setDuplicatedObjects([]);
+ setRotatedObjects([]);
+ setSelectedAssets([]);
+ }
+
+ return null; // No visible output, but the component handles copy-paste functionality
+};
+
+export default CopyPasteControls;
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx
new file mode 100644
index 0000000..39c3e49
--- /dev/null
+++ b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx
@@ -0,0 +1,189 @@
+import * as THREE from "three";
+import { useEffect, useMemo } from "react";
+import { useFrame, useThree } from "@react-three/fiber";
+import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
+import { toast } from "react-toastify";
+// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
+import * as Types from "../../../../types/world/worldTypes";
+import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
+import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
+
+const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedObjects, setpastedObjects, selectionGroup, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => {
+ const { camera, controls, gl, scene, pointer, raycaster } = useThree();
+ const { toggleView } = useToggleView();
+ const { selectedAssets, setSelectedAssets } = useSelectedAssets();
+ const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
+ const { floorItems, setFloorItems } = useFloorItems();
+ const { socket } = useSocketStore();
+
+ useEffect(() => {
+ if (!camera || !scene || toggleView) return;
+ const canvasElement = gl.domElement;
+ canvasElement.tabIndex = 0;
+
+ let isMoving = false;
+
+ const onPointerDown = () => {
+ isMoving = false;
+ };
+
+ const onPointerMove = () => {
+ isMoving = true;
+ };
+
+ const onPointerUp = (event: PointerEvent) => {
+ if (!isMoving && duplicatedObjects.length > 0 && event.button === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
+ event.preventDefault();
+ addDuplicatedAssets();
+ }
+ };
+
+ const onKeyDown = (event: KeyboardEvent) => {
+ const keyCombination = detectModifierKeys(event);
+
+ if (keyCombination === "Ctrl+D" && selectedAssets.length > 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
+ duplicateSelection();
+ }
+ };
+
+ if (!toggleView) {
+ canvasElement.addEventListener("pointerdown", onPointerDown);
+ canvasElement.addEventListener("pointermove", onPointerMove);
+ canvasElement.addEventListener("pointerup", onPointerUp);
+ canvasElement.addEventListener("keydown", onKeyDown);
+ }
+
+ return () => {
+ canvasElement.removeEventListener("pointerdown", onPointerDown);
+ canvasElement.removeEventListener("pointermove", onPointerMove);
+ canvasElement.removeEventListener("pointerup", onPointerUp);
+ canvasElement.removeEventListener("keydown", onKeyDown);
+ };
+
+ }, [camera, controls, scene, toggleView, selectedAssets, duplicatedObjects, movedObjects, socket, floorItems, rotatedObjects]);
+
+ useFrame(() => {
+ if (duplicatedObjects.length > 0) {
+ const intersectionPoint = new THREE.Vector3();
+ raycaster.setFromCamera(pointer, camera);
+ const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+ if (point) {
+ const position = new THREE.Vector3();
+ if (boundingBoxRef.current) {
+ boundingBoxRef.current?.getWorldPosition(position)
+ selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z));
+ } else {
+ const box = new THREE.Box3();
+ duplicatedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj.clone()));
+ const center = new THREE.Vector3();
+ box.getCenter(center);
+ selectionGroup.current.position.set(point.x - (center.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (center.z - selectionGroup.current.position.z));
+ }
+ }
+ }
+ });
+
+ const duplicateSelection = () => {
+ if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
+ const newClones = selectedAssets.map((asset: any) => {
+ const clone = asset.clone();
+ clone.position.copy(asset.position);
+ return clone;
+ });
+
+ selectionGroup.current.add(...newClones);
+ setDuplicatedObjects(newClones);
+
+ const intersectionPoint = new THREE.Vector3();
+ raycaster.setFromCamera(pointer, camera);
+ const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+
+ if (point) {
+ const position = new THREE.Vector3();
+ boundingBoxRef.current?.getWorldPosition(position)
+ selectionGroup.current.position.set(point.x - (position.x - selectionGroup.current.position.x), selectionGroup.current.position.y, point.z - (position.z - selectionGroup.current.position.z));
+ }
+ }
+ };
+
+ const addDuplicatedAssets = () => {
+ if (duplicatedObjects.length === 0) return;
+ duplicatedObjects.forEach(async (obj: THREE.Object3D) => {
+ const worldPosition = new THREE.Vector3();
+ obj.getWorldPosition(worldPosition);
+ obj.position.copy(worldPosition);
+
+ if (itemsGroupRef.current) {
+
+ const newFloorItem: Types.FloorItemType = {
+ modeluuid: obj.uuid,
+ modelname: obj.userData.name,
+ modelfileID: obj.userData.modelId,
+ position: [worldPosition.x, worldPosition.y, worldPosition.z],
+ rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
+ isLocked: false,
+ isVisible: true
+ };
+
+ setFloorItems((prevItems: Types.FloorItems) => {
+ const updatedItems = [...(prevItems || []), newFloorItem];
+ localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
+ return updatedItems;
+ });
+
+ const email = localStorage.getItem("email");
+ const organization = email ? email.split("@")[1].split(".")[0] : "default";
+
+ //REST
+
+ // await setFloorItemApi(
+ // organization,
+ // obj.uuid,
+ // obj.userData.name,
+ // [worldPosition.x, worldPosition.y, worldPosition.z],
+ // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
+ // obj.userData.modelId,
+ // false,
+ // true,
+ // );
+
+ //SOCKET
+
+ const data = {
+ organization,
+ modeluuid: newFloorItem.modeluuid,
+ modelname: newFloorItem.modelname,
+ modelfileID: newFloorItem.modelfileID,
+ position: newFloorItem.position,
+ rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
+ isLocked: false,
+ isVisible: true,
+ socketId: socket.id,
+ };
+
+ socket.emit("v2:model-asset:add", data);
+
+ obj.userData.modeluuid = newFloorItem.modeluuid;
+ itemsGroupRef.current.add(obj);
+ }
+ });
+
+ toast.success("Object duplicated!");
+ clearSelection();
+ }
+
+ const clearSelection = () => {
+ selectionGroup.current.children = [];
+ selectionGroup.current.position.set(0, 0, 0);
+ selectionGroup.current.rotation.set(0, 0, 0);
+ setMovedObjects([]);
+ setpastedObjects([]);
+ setDuplicatedObjects([]);
+ setRotatedObjects([]);
+ setSelectedAssets([]);
+ }
+
+ return null; // This component does not render any UI
+};
+
+export default DuplicationControls;
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selectionControls/moveControls.tsx b/app/src/modules/scene/controls/selectionControls/moveControls.tsx
new file mode 100644
index 0000000..2cde3e4
--- /dev/null
+++ b/app/src/modules/scene/controls/selectionControls/moveControls.tsx
@@ -0,0 +1,240 @@
+import * as THREE from "three";
+import { useEffect, useMemo, useRef, useState } from "react";
+import { useFrame, useThree } from "@react-three/fiber";
+import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
+// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
+import { toast } from "react-toastify";
+import * as Types from "../../../../types/world/worldTypes";
+import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
+
+function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {
+ const { camera, controls, gl, scene, pointer, raycaster } = useThree();
+ const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
+
+ const { toggleView } = useToggleView();
+ const { selectedAssets, setSelectedAssets } = useSelectedAssets();
+ const { floorItems, setFloorItems } = useFloorItems();
+ const { socket } = useSocketStore();
+ const itemsData = useRef([]);
+
+ useEffect(() => {
+ if (!camera || !scene || toggleView || !itemsGroupRef.current) return;
+
+ const canvasElement = gl.domElement;
+ canvasElement.tabIndex = 0;
+
+ let isMoving = false;
+
+ const onPointerDown = () => {
+ isMoving = false;
+ };
+
+ const onPointerMove = () => {
+ isMoving = true;
+ };
+
+ const onPointerUp = (event: PointerEvent) => {
+ if (!isMoving && movedObjects.length > 0 && event.button === 0) {
+ event.preventDefault();
+ placeMovedAssets();
+ }
+ if (!isMoving && movedObjects.length > 0 && event.button === 2) {
+ event.preventDefault();
+
+ clearSelection();
+ movedObjects.forEach((asset: any) => {
+ if (itemsGroupRef.current) {
+ itemsGroupRef.current.attach(asset);
+ }
+ });
+
+ setFloorItems([...floorItems, ...itemsData.current]);
+
+ setMovedObjects([]);
+ itemsData.current = [];
+ }
+ };
+
+ const onKeyDown = (event: KeyboardEvent) => {
+ const keyCombination = detectModifierKeys(event);
+
+ if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0) return;
+ if (keyCombination === "G") {
+ if (selectedAssets.length > 0) {
+ moveAssets();
+ itemsData.current = floorItems.filter((item: { modeluuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modeluuid));
+ }
+ }
+ if (keyCombination === "ESCAPE") {
+ event.preventDefault();
+
+ clearSelection();
+ movedObjects.forEach((asset: any) => {
+ if (itemsGroupRef.current) {
+ itemsGroupRef.current.attach(asset);
+ }
+ });
+
+ setFloorItems([...floorItems, ...itemsData.current]);
+
+ setMovedObjects([]);
+ itemsData.current = [];
+ }
+ };
+
+ if (!toggleView) {
+ canvasElement.addEventListener("pointerdown", onPointerDown);
+ canvasElement.addEventListener("pointermove", onPointerMove);
+ canvasElement.addEventListener("pointerup", onPointerUp);
+ canvasElement.addEventListener("keydown", onKeyDown);
+ }
+
+ return () => {
+ canvasElement.removeEventListener("pointerdown", onPointerDown);
+ canvasElement.removeEventListener("pointermove", onPointerMove);
+ canvasElement.removeEventListener("pointerup", onPointerUp);
+ canvasElement.removeEventListener("keydown", onKeyDown);
+ };
+ }, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects]);
+
+ const gridSize = 0.25;
+ const moveSpeed = 0.25;
+ const isGridSnap = false;
+
+ useFrame(() => {
+ if (movedObjects.length > 0) {
+ const intersectionPoint = new THREE.Vector3();
+ raycaster.setFromCamera(pointer, camera);
+ const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+
+ if (point) {
+ let targetX = point.x;
+ let targetZ = point.z;
+
+ if (isGridSnap) {
+ targetX = Math.round(point.x / gridSize) * gridSize;
+ targetZ = Math.round(point.z / gridSize) * gridSize;
+ }
+
+ const position = new THREE.Vector3();
+ if (boundingBoxRef.current) {
+ boundingBoxRef.current.getWorldPosition(position);
+ selectionGroup.current.position.lerp(
+ new THREE.Vector3(
+ targetX - (position.x - selectionGroup.current.position.x),
+ selectionGroup.current.position.y,
+ targetZ - (position.z - selectionGroup.current.position.z)
+ ),
+ moveSpeed
+ );
+ } else {
+ const box = new THREE.Box3();
+ movedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj));
+ const center = new THREE.Vector3();
+ box.getCenter(center);
+
+ selectionGroup.current.position.lerp(
+ new THREE.Vector3(
+ targetX - (center.x - selectionGroup.current.position.x),
+ selectionGroup.current.position.y,
+ targetZ - (center.z - selectionGroup.current.position.z)
+ ),
+ moveSpeed
+ );
+ }
+ }
+ }
+ });
+
+
+ const moveAssets = () => {
+ const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modeluuid));
+ setFloorItems(updatedItems);
+ setMovedObjects(selectedAssets);
+ selectedAssets.forEach((asset: any) => { selectionGroup.current.attach(asset); });
+ }
+
+ const placeMovedAssets = () => {
+ if (movedObjects.length === 0) return;
+
+ movedObjects.forEach(async (obj: THREE.Object3D) => {
+ const worldPosition = new THREE.Vector3();
+ obj.getWorldPosition(worldPosition);
+
+ selectionGroup.current.remove(obj);
+ obj.position.copy(worldPosition);
+
+ if (itemsGroupRef.current) {
+
+ const newFloorItem: Types.FloorItemType = {
+ modeluuid: obj.uuid,
+ modelname: obj.userData.name,
+ modelfileID: obj.userData.modelId,
+ position: [worldPosition.x, worldPosition.y, worldPosition.z],
+ rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
+ isLocked: false,
+ isVisible: true
+ };
+
+ setFloorItems((prevItems: Types.FloorItems) => {
+ const updatedItems = [...(prevItems || []), newFloorItem];
+ localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
+ return updatedItems;
+ });
+
+ const email = localStorage.getItem("email");
+ const organization = email ? email.split("@")[1].split(".")[0] : "default";
+
+ //REST
+
+ // await setFloorItemApi(
+ // organization,
+ // obj.uuid,
+ // obj.userData.name,
+ // [worldPosition.x, worldPosition.y, worldPosition.z],
+ // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
+ // obj.userData.modelId,
+ // false,
+ // true,
+ // );
+
+ //SOCKET
+
+ const data = {
+ organization,
+ modeluuid: newFloorItem.modeluuid,
+ modelname: newFloorItem.modelname,
+ modelfileID: newFloorItem.modelfileID,
+ position: newFloorItem.position,
+ rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
+ isLocked: false,
+ isVisible: true,
+ socketId: socket.id,
+ };
+
+ socket.emit("v2:model-asset:add", data);
+
+ itemsGroupRef.current.add(obj);
+ }
+ });
+ toast.success("Object moved!");
+
+ itemsData.current = [];
+ clearSelection();
+ }
+
+ const clearSelection = () => {
+ selectionGroup.current.children = [];
+ selectionGroup.current.position.set(0, 0, 0);
+ selectionGroup.current.rotation.set(0, 0, 0);
+ setpastedObjects([]);
+ setDuplicatedObjects([]);
+ setMovedObjects([]);
+ setRotatedObjects([]);
+ setSelectedAssets([]);
+ }
+
+ return null; // No need to return anything, as this component is used for its side effects
+}
+
+export default MoveControls
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
new file mode 100644
index 0000000..5dfaf08
--- /dev/null
+++ b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
@@ -0,0 +1,241 @@
+import * as THREE from "three";
+import { useEffect, useMemo, useRef, useState } from "react";
+import { useFrame, useThree } from "@react-three/fiber";
+import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
+// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
+import { toast } from "react-toastify";
+import * as Types from "../../../../types/world/worldTypes";
+import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
+
+function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {
+ const { camera, controls, gl, scene, pointer, raycaster } = useThree();
+ const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
+
+ const { toggleView } = useToggleView();
+ const { selectedAssets, setSelectedAssets } = useSelectedAssets();
+ const { floorItems, setFloorItems } = useFloorItems();
+ const { socket } = useSocketStore();
+ const itemsData = useRef([]);
+
+ const prevPointerPosition = useRef(null);
+
+ useEffect(() => {
+ if (!camera || !scene || toggleView || !itemsGroupRef.current) return;
+
+ const canvasElement = gl.domElement;
+ canvasElement.tabIndex = 0;
+
+ let isMoving = false;
+
+ const onPointerDown = () => {
+ isMoving = false;
+ };
+
+ const onPointerMove = () => {
+ isMoving = true;
+ };
+
+ const onPointerUp = (event: PointerEvent) => {
+ if (!isMoving && rotatedObjects.length > 0 && event.button === 0) {
+ event.preventDefault();
+ placeRotatedAssets();
+ }
+ if (!isMoving && rotatedObjects.length > 0 && event.button === 2) {
+ event.preventDefault();
+
+ clearSelection();
+ rotatedObjects.forEach((asset: any) => {
+ if (itemsGroupRef.current) {
+ itemsGroupRef.current.attach(asset);
+ }
+ });
+
+ setFloorItems([...floorItems, ...itemsData.current]);
+
+ setRotatedObjects([]);
+ itemsData.current = [];
+ }
+ };
+
+ const onKeyDown = (event: KeyboardEvent) => {
+ if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || movedObjects.length > 0) return;
+ if (event.key.toLowerCase() === "r") {
+ if (selectedAssets.length > 0) {
+ rotateAssets();
+ itemsData.current = floorItems.filter((item: { modeluuid: string }) => selectedAssets.some((asset: any) => asset.uuid === item.modeluuid));
+ }
+ }
+ if (event.key.toLowerCase() === "escape") {
+ event.preventDefault();
+
+ clearSelection();
+ rotatedObjects.forEach((asset: any) => {
+ if (itemsGroupRef.current) {
+ itemsGroupRef.current.attach(asset);
+ }
+ });
+
+ setFloorItems([...floorItems, ...itemsData.current]);
+
+ setRotatedObjects([]);
+ itemsData.current = [];
+ }
+ };
+
+ if (!toggleView) {
+ canvasElement.addEventListener("pointerdown", onPointerDown);
+ canvasElement.addEventListener("pointermove", onPointerMove);
+ canvasElement.addEventListener("pointerup", onPointerUp);
+ canvasElement.addEventListener("keydown", onKeyDown);
+ }
+
+ return () => {
+ canvasElement.removeEventListener("pointerdown", onPointerDown);
+ canvasElement.removeEventListener("pointermove", onPointerMove);
+ canvasElement.removeEventListener("pointerup", onPointerUp);
+ canvasElement.removeEventListener("keydown", onKeyDown);
+ };
+ }, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, rotatedObjects, movedObjects]);
+
+ useFrame(() => {
+ if (rotatedObjects.length > 0) {
+ const intersectionPoint = new THREE.Vector3();
+ raycaster.setFromCamera(pointer, camera);
+ const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+
+ if (point && prevPointerPosition.current) {
+ const box = new THREE.Box3();
+ rotatedObjects.forEach((obj: THREE.Object3D) => box.expandByObject(obj));
+ const center = new THREE.Vector3();
+ box.getCenter(center);
+
+ const delta = new THREE.Vector3().subVectors(point, center);
+ const prevPointerPosition3D = new THREE.Vector3(prevPointerPosition.current.x, 0, prevPointerPosition.current.y);
+
+ const angle = Math.atan2(delta.z, delta.x) - Math.atan2(prevPointerPosition3D.z - center.z, prevPointerPosition3D.x - center.x);
+
+ selectionGroup.current.rotation.y += -angle;
+
+ selectionGroup.current.position.sub(center);
+ selectionGroup.current.position.applyAxisAngle(new THREE.Vector3(0, 1, 0), -angle);
+ selectionGroup.current.position.add(center);
+
+ prevPointerPosition.current = new THREE.Vector2(point.x, point.z);
+ }
+ }
+ });
+
+ const rotateAssets = () => {
+ const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedAssets.some((asset: any) => asset.uuid === item.modeluuid));
+ setFloorItems(updatedItems);
+
+ const box = new THREE.Box3();
+ selectedAssets.forEach((asset: any) => box.expandByObject(asset));
+ const center = new THREE.Vector3();
+ box.getCenter(center);
+
+ const intersectionPoint = new THREE.Vector3();
+ raycaster.setFromCamera(pointer, camera);
+ const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+
+ if (point) {
+ prevPointerPosition.current = new THREE.Vector2(point.x, point.z);
+ }
+
+ selectedAssets.forEach((asset: any) => {
+ selectionGroup.current.attach(asset);
+ });
+
+ setRotatedObjects(selectedAssets);
+ };
+
+ const placeRotatedAssets = () => {
+ if (rotatedObjects.length === 0) return;
+
+ rotatedObjects.forEach(async (obj: THREE.Object3D) => {
+ const worldPosition = new THREE.Vector3();
+ const worldQuaternion = new THREE.Quaternion();
+
+ obj.getWorldPosition(worldPosition);
+ obj.getWorldQuaternion(worldQuaternion);
+
+ selectionGroup.current.remove(obj);
+
+ obj.position.copy(worldPosition);
+ obj.quaternion.copy(worldQuaternion);
+
+
+ if (itemsGroupRef.current) {
+
+ const newFloorItem: Types.FloorItemType = {
+ modeluuid: obj.uuid,
+ modelname: obj.userData.name,
+ modelfileID: obj.userData.modelId,
+ position: [worldPosition.x, worldPosition.y, worldPosition.z],
+ rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
+ isLocked: false,
+ isVisible: true
+ };
+
+ setFloorItems((prevItems: Types.FloorItems) => {
+ const updatedItems = [...(prevItems || []), newFloorItem];
+ localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
+ return updatedItems;
+ });
+
+ const email = localStorage.getItem("email");
+ const organization = email ? email.split("@")[1].split(".")[0] : "default";
+
+ //REST
+
+ // await setFloorItemApi(
+ // organization,
+ // obj.uuid,
+ // obj.userData.name,
+ // [worldPosition.x, worldPosition.y, worldPosition.z],
+ // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
+ // obj.userData.modelId,
+ // false,
+ // true,
+ // );
+
+ //SOCKET
+
+ const data = {
+ organization,
+ modeluuid: newFloorItem.modeluuid,
+ modelname: newFloorItem.modelname,
+ modelfileID: newFloorItem.modelfileID,
+ position: newFloorItem.position,
+ rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
+ isLocked: false,
+ isVisible: true,
+ socketId: socket.id,
+ };
+
+ socket.emit("v2:model-asset:add", data);
+
+ itemsGroupRef.current.add(obj);
+ }
+ });
+ toast.success("Object rotated!");
+
+ itemsData.current = [];
+ clearSelection();
+ }
+
+ const clearSelection = () => {
+ selectionGroup.current.children = [];
+ selectionGroup.current.position.set(0, 0, 0);
+ selectionGroup.current.rotation.set(0, 0, 0);
+ setpastedObjects([]);
+ setDuplicatedObjects([]);
+ setMovedObjects([]);
+ setRotatedObjects([]);
+ setSelectedAssets([]);
+ }
+
+ return null; // No need to return anything, as this component is used for its side effects
+}
+
+export default RotateControls
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selection/selectionControls.tsx b/app/src/modules/scene/controls/selectionControls/selectionControls.tsx
similarity index 54%
rename from app/src/modules/scene/controls/selection/selectionControls.tsx
rename to app/src/modules/scene/controls/selectionControls/selectionControls.tsx
index 8998bc9..49b86d2 100644
--- a/app/src/modules/scene/controls/selection/selectionControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selectionControls.tsx
@@ -1,479 +1,272 @@
-import * as THREE from "three";
-import { useEffect, useMemo, useRef, useState } from "react";
-import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox";
-import { SelectionHelper } from "./selectionHelper";
-import { useFrame, useThree } from "@react-three/fiber";
-import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore, useToggleView, } from "../../../../store/store";
-import BoundingBox from "./boundingBoxHelper";
-import { toast } from "react-toastify";
-// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
-import * as Types from "../../../../types/world/worldTypes";
-import * as SimulationTypes from "../../../../types/simulationTypes";
-
-import DuplicationControls from "./duplicationControls";
-import CopyPasteControls from "./copyPasteControls";
-import MoveControls from "./moveControls";
-import RotateControls from "./rotateControls";
-import useModuleStore from "../../../../store/useModuleStore";
-
-const SelectionControls: React.FC = () => {
- const { camera, controls, gl, scene, pointer } = useThree();
- const itemsGroupRef = useRef(undefined);
- const selectionGroup = useRef() as Types.RefGroup;
- const { toggleView } = useToggleView();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const { selectedAssets, setSelectedAssets } = useSelectedAssets();
- const [movedObjects, setMovedObjects] = useState([]);
- const [rotatedObjects, setRotatedObjects] = useState([]);
- const [copiedObjects, setCopiedObjects] = useState([]);
- const [pastedObjects, setpastedObjects] = useState([]);
- const [duplicatedObjects, setDuplicatedObjects] = useState([]);
- const boundingBoxRef = useRef();
- const { floorItems, setFloorItems } = useFloorItems();
- const { activeModule } = useModuleStore();
- const { socket } = useSocketStore();
- const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]);
-
- useEffect(() => {
- if (!camera || !scene || toggleView) return;
-
- const canvasElement = gl.domElement;
- canvasElement.tabIndex = 0;
-
- const itemsGroup: any = scene.getObjectByName("itemsGroup");
- itemsGroupRef.current = itemsGroup;
-
- let isSelecting = false;
- let isRightClick = false;
- let rightClickMoved = false;
- let isCtrlSelecting = false;
-
- const helper = new SelectionHelper(gl);
-
- if (!itemsGroup) {
- toast.warn("itemsGroup not found in the scene.");
- return;
- }
-
- const onPointerDown = (event: PointerEvent) => {
- if (event.button === 2) {
- isRightClick = true;
- rightClickMoved = false;
- } else if (event.button === 0) {
- isSelecting = false;
- isCtrlSelecting = event.ctrlKey;
- if (event.ctrlKey && duplicatedObjects.length === 0) {
- if (controls) (controls as any).enabled = false;
- selectionBox.startPoint.set(pointer.x, pointer.y, 0);
- }
- }
- };
-
- const onPointerMove = (event: PointerEvent) => {
- if (isRightClick) {
- rightClickMoved = true;
- }
- isSelecting = true;
- if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) {
- selectionBox.endPoint.set(pointer.x, pointer.y, 0);
- }
- };
-
- const onPointerUp = (event: PointerEvent) => {
- if (event.button === 2) {
- isRightClick = false;
- if (!rightClickMoved) {
- clearSelection();
- }
- return;
- }
-
- if (isSelecting && isCtrlSelecting) {
- isCtrlSelecting = false;
- isSelecting = false;
- if (event.ctrlKey && duplicatedObjects.length === 0) {
- selectAssets();
- }
- } else if (!isSelecting && selectedAssets.length > 0 && ((pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) || event.button !== 0)) {
- clearSelection();
- helper.enabled = true;
- isCtrlSelecting = false;
- }
- };
-
- const onKeyDown = (event: KeyboardEvent) => {
- if (movedObjects.length > 0 || rotatedObjects.length > 0) return;
- if (event.key.toLowerCase() === "escape") {
- event.preventDefault();
- clearSelection();
- }
- if (event.key.toLowerCase() === "delete") {
- event.preventDefault();
- deleteSelection();
- }
- };
-
- const onContextMenu = (event: MouseEvent) => {
- event.preventDefault();
- if (!rightClickMoved) {
- clearSelection();
- }
- };
-
- if (!toggleView && activeModule === "builder") {
- helper.enabled = true;
- if (duplicatedObjects.length === 0 && pastedObjects.length === 0) {
- canvasElement.addEventListener("pointerdown", onPointerDown);
- canvasElement.addEventListener("pointermove", onPointerMove);
- canvasElement.addEventListener("pointerup", onPointerUp);
- } else {
- helper.enabled = false;
- helper.dispose();
- }
- canvasElement.addEventListener("contextmenu", onContextMenu);
- canvasElement.addEventListener("keydown", onKeyDown);
- } else {
- helper.enabled = false;
- helper.dispose();
- }
-
- return () => {
- canvasElement.removeEventListener("pointerdown", onPointerDown);
- canvasElement.removeEventListener("pointermove", onPointerMove);
- canvasElement.removeEventListener("contextmenu", onContextMenu);
- canvasElement.removeEventListener("pointerup", onPointerUp);
- canvasElement.removeEventListener("keydown", onKeyDown);
- helper.enabled = false;
- helper.dispose();
- };
- }, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, floorItems, rotatedObjects, activeModule,]);
-
- useEffect(() => {
- if (activeModule !== "builder") {
- clearSelection();
- }
- }, [activeModule]);
-
- useFrame(() => {
- if (pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
- selectionGroup.current.position.set(0, 0, 0);
- }
- });
-
- const selectAssets = () => {
- selectionBox.endPoint.set(pointer.x, pointer.y, 0);
- if (controls) (controls as any).enabled = true;
-
- let selectedObjects = selectionBox.select();
- let Objects = new Set();
-
- selectedObjects.map((object) => {
- let currentObject: THREE.Object3D | null = object;
- while (currentObject) {
- if (currentObject.userData.modelId) {
- Objects.add(currentObject);
- break;
- }
- currentObject = currentObject.parent || null;
- }
- });
-
- if (Objects.size === 0) {
- clearSelection();
- return;
- }
-
- const updatedSelections = new Set(selectedAssets);
- Objects.forEach((obj) => { updatedSelections.has(obj) ? updatedSelections.delete(obj) : updatedSelections.add(obj); });
-
- const selected = Array.from(updatedSelections);
-
- setSelectedAssets(selected);
- };
-
- const clearSelection = () => {
- selectionGroup.current.children = [];
- selectionGroup.current.position.set(0, 0, 0);
- selectionGroup.current.rotation.set(0, 0, 0);
- setpastedObjects([]);
- setDuplicatedObjects([]);
- setSelectedAssets([]);
- };
- const updateBackend = async (updatedPaths: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- if (updatedPaths.length === 0) return;
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "";
-
- updatedPaths.forEach(async (updatedPath) => {
- if (updatedPath.type === "Conveyor") {
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: {
- type: "Conveyor",
- points: updatedPath.points,
- speed: updatedPath.speed,
- },
- };
-
- socket.emit("v2:model-asset:updateEventData", data);
- } else if (updatedPath.type === "Vehicle") {
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "Vehicle", points: updatedPath.points }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: { type: "Vehicle", points: updatedPath.points },
- };
-
- socket.emit("v2:model-asset:updateEventData", data);
- } else if (updatedPath.type === "StaticMachine") {
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "StaticMachine", points: updatedPath.points }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: { type: "StaticMachine", points: updatedPath.points },
- };
-
- socket.emit("v2:model-asset:updateEventData", data);
- } else if (updatedPath.type === "ArmBot") {
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "ArmBot", points: updatedPath.points }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: { type: "ArmBot", points: updatedPath.points },
- };
-
- socket.emit("v2:model-asset:updateEventData", data);
- }
- });
- };
-
- const removeConnections = (deletedModelUUIDs: string[]) => {
-
- const deletedPointUUIDs = new Set();
- simulationStates.forEach(state => {
- if (deletedModelUUIDs.includes(state.modeluuid)) {
- if (state.type === "Conveyor" && state.points) {
- state.points.forEach(point => {
- deletedPointUUIDs.add(point.uuid);
- });
- } else if (state.points && 'uuid' in state.points) {
- deletedPointUUIDs.add(state.points.uuid);
- }
- }
- });
-
- const updatedStates = simulationStates.map((state) => {
- // Handle Conveyor
- if (state.type === "Conveyor") {
- const updatedConveyor: SimulationTypes.ConveyorEventsSchema = {
- ...state,
- points: state.points.map((point) => {
- return {
- ...point,
- connections: {
- ...point.connections,
- targets: point.connections.targets.filter(
- (target) => !deletedModelUUIDs.includes(target.modelUUID)
- ),
- },
- };
- }),
- };
- return updatedConveyor;
- }
-
- // Handle Vehicle
- else if (state.type === "Vehicle") {
- const updatedVehicle: SimulationTypes.VehicleEventsSchema = {
- ...state,
- points: {
- ...state.points,
- connections: {
- ...state.points.connections,
- targets: state.points.connections.targets.filter(
- (target) => !deletedModelUUIDs.includes(target.modelUUID)
- ),
- },
- },
- };
- return updatedVehicle;
- }
-
- // Handle StaticMachine
- else if (state.type === "StaticMachine") {
- const updatedStaticMachine: SimulationTypes.StaticMachineEventsSchema =
- {
- ...state,
- points: {
- ...state.points,
- connections: {
- ...state.points.connections,
- targets: state.points.connections.targets.filter(
- (target) => !deletedModelUUIDs.includes(target.modelUUID)
- ),
- },
- },
- };
- return updatedStaticMachine;
- }
-
- // Handle ArmBot
- else if (state.type === "ArmBot") {
- const updatedArmBot: SimulationTypes.ArmBotEventsSchema = {
- ...state,
- points: {
- ...state.points,
- connections: {
- ...state.points.connections,
- targets: state.points.connections.targets.filter(
- (target: any) => !deletedModelUUIDs.includes(target.modelUUID)
- ),
- },
- actions: {
- ...state.points.actions,
- processes: state.points.actions.processes?.filter((process) => {
- // Check if trigger is from deleted model
- const matchedStates = simulationStates.filter((s) => deletedModelUUIDs.includes(s.modeluuid));
-
- if (matchedStates.length > 0) {
- if (matchedStates[0]?.type === "StaticMachine") {
- const trigPoints = matchedStates[0]?.points;
- if (process.triggerId === trigPoints?.triggers?.uuid) {
- return false;
- }
- } else if (matchedStates[0]?.type === "Conveyor") {
- const trigPoints = matchedStates[0]?.points;
- if (Array.isArray(trigPoints)) {
- const nonEmptyTriggers = trigPoints.filter((point) => point && point.triggers && point.triggers.length > 0);
- const allTriggerUUIDs = nonEmptyTriggers.flatMap((point) => point.triggers).map((trigger) => trigger.uuid);
- if (allTriggerUUIDs.includes(process.triggerId)) {
- return false;
- }
- }
- }
- }
-
- // Check if startPoint or endPoint is from deleted model
- if (deletedPointUUIDs.has(process.startPoint) || deletedPointUUIDs.has(process.endPoint)) {
- return false;
- }
-
- return true;
- }),
- },
- },
- };
- return updatedArmBot;
- }
-
- return state;
- });
-
- const filteredStates = updatedStates.filter((state) => !deletedModelUUIDs.includes(state.modeluuid));
-
- updateBackend(filteredStates);
- setSimulationStates(filteredStates);
- };
-
- const deleteSelection = () => {
- if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
- const email = localStorage.getItem("email");
- const organization = email!.split("@")[1].split(".")[0];
-
- const storedItems = JSON.parse(localStorage.getItem("FloorItems") || "[]");
- const selectedUUIDs = selectedAssets.map((mesh: THREE.Object3D) => mesh.uuid);
-
- const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid));
- localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems));
-
- selectedAssets.forEach((selectedMesh: THREE.Object3D) => {
- //REST
-
- // const response = await deleteFloorItem(organization, selectedMesh.uuid, selectedMesh.userData.name);
-
- //SOCKET
-
- const data = {
- organization: organization,
- modeluuid: selectedMesh.uuid,
- modelname: selectedMesh.userData.name,
- socketId: socket.id,
- };
-
- socket.emit("v2:model-asset:delete", data);
-
- selectedMesh.traverse((child: THREE.Object3D) => {
- if (child instanceof THREE.Mesh) {
- if (child.geometry) child.geometry.dispose();
- if (Array.isArray(child.material)) {
- child.material.forEach((material) => {
- if (material.map) material.map.dispose();
- material.dispose();
- });
- } else if (child.material) {
- if (child.material.map) child.material.map.dispose();
- child.material.dispose();
- }
- }
- });
-
- setSimulationStates((prevEvents: (| SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- const updatedEvents = (prevEvents || []).filter((event) => event.modeluuid !== selectedMesh.uuid);
- return updatedEvents;
- });
-
- itemsGroupRef.current?.remove(selectedMesh);
- });
-
- const allUUIDs = selectedAssets.map((val: any) => val.uuid);
- removeConnections(allUUIDs);
-
- const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid));
- setFloorItems(updatedItems);
- }
- toast.success("Selected models removed!");
- clearSelection();
- };
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-};
-
-export default SelectionControls;
+import * as THREE from "three";
+import { useEffect, useMemo, useRef, useState } from "react";
+import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox";
+import { SelectionHelper } from "./selectionHelper";
+import { useFrame, useThree } from "@react-three/fiber";
+import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView, } from "../../../../store/store";
+import BoundingBox from "./boundingBoxHelper";
+import { toast } from "react-toastify";
+// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
+import * as Types from "../../../../types/world/worldTypes";
+
+import DuplicationControls from "./duplicationControls";
+import CopyPasteControls from "./copyPasteControls";
+import MoveControls from "./moveControls";
+import RotateControls from "./rotateControls";
+import useModuleStore from "../../../../store/useModuleStore";
+
+const SelectionControls: React.FC = () => {
+ const { camera, controls, gl, scene, pointer } = useThree();
+ const itemsGroupRef = useRef(undefined);
+ const selectionGroup = useRef() as Types.RefGroup;
+ const { toggleView } = useToggleView();
+ const { selectedAssets, setSelectedAssets } = useSelectedAssets();
+ const [movedObjects, setMovedObjects] = useState([]);
+ const [rotatedObjects, setRotatedObjects] = useState([]);
+ const [copiedObjects, setCopiedObjects] = useState([]);
+ const [pastedObjects, setpastedObjects] = useState([]);
+ const [duplicatedObjects, setDuplicatedObjects] = useState([]);
+ const boundingBoxRef = useRef();
+ const { floorItems, setFloorItems } = useFloorItems();
+ const { activeModule } = useModuleStore();
+ const { socket } = useSocketStore();
+ const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]);
+
+ useEffect(() => {
+ if (!camera || !scene || toggleView) return;
+
+ const canvasElement = gl.domElement;
+ canvasElement.tabIndex = 0;
+
+ const itemsGroup: any = scene.getObjectByName("itemsGroup");
+ itemsGroupRef.current = itemsGroup;
+
+ let isSelecting = false;
+ let isRightClick = false;
+ let rightClickMoved = false;
+ let isCtrlSelecting = false;
+
+ const helper = new SelectionHelper(gl);
+
+ if (!itemsGroup) {
+ toast.warn("itemsGroup not found in the scene.");
+ return;
+ }
+
+ const onPointerDown = (event: PointerEvent) => {
+ if (event.button === 2) {
+ isRightClick = true;
+ rightClickMoved = false;
+ } else if (event.button === 0) {
+ isSelecting = false;
+ isCtrlSelecting = event.ctrlKey;
+ if (event.ctrlKey && duplicatedObjects.length === 0) {
+ if (controls) (controls as any).enabled = false;
+ selectionBox.startPoint.set(pointer.x, pointer.y, 0);
+ }
+ }
+ };
+
+ const onPointerMove = (event: PointerEvent) => {
+ if (isRightClick) {
+ rightClickMoved = true;
+ }
+ isSelecting = true;
+ if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting) {
+ selectionBox.endPoint.set(pointer.x, pointer.y, 0);
+ }
+ };
+
+ const onPointerUp = (event: PointerEvent) => {
+ if (event.button === 2) {
+ isRightClick = false;
+ if (!rightClickMoved) {
+ clearSelection();
+ }
+ return;
+ }
+
+ if (isSelecting && isCtrlSelecting) {
+ isCtrlSelecting = false;
+ isSelecting = false;
+ if (event.ctrlKey && duplicatedObjects.length === 0) {
+ selectAssets();
+ }
+ } else if (!isSelecting && selectedAssets.length > 0 && ((pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) || event.button !== 0)) {
+ clearSelection();
+ helper.enabled = true;
+ isCtrlSelecting = false;
+ }
+ };
+
+ const onKeyDown = (event: KeyboardEvent) => {
+ if (movedObjects.length > 0 || rotatedObjects.length > 0) return;
+ if (event.key.toLowerCase() === "escape") {
+ event.preventDefault();
+ clearSelection();
+ }
+ if (event.key.toLowerCase() === "delete") {
+ event.preventDefault();
+ deleteSelection();
+ }
+ };
+
+ const onContextMenu = (event: MouseEvent) => {
+ event.preventDefault();
+ if (!rightClickMoved) {
+ clearSelection();
+ }
+ };
+
+ if (!toggleView && activeModule === "builder") {
+ helper.enabled = true;
+ if (duplicatedObjects.length === 0 && pastedObjects.length === 0) {
+ canvasElement.addEventListener("pointerdown", onPointerDown);
+ canvasElement.addEventListener("pointermove", onPointerMove);
+ canvasElement.addEventListener("pointerup", onPointerUp);
+ } else {
+ helper.enabled = false;
+ helper.dispose();
+ }
+ canvasElement.addEventListener("contextmenu", onContextMenu);
+ canvasElement.addEventListener("keydown", onKeyDown);
+ } else {
+ helper.enabled = false;
+ helper.dispose();
+ }
+
+ return () => {
+ canvasElement.removeEventListener("pointerdown", onPointerDown);
+ canvasElement.removeEventListener("pointermove", onPointerMove);
+ canvasElement.removeEventListener("contextmenu", onContextMenu);
+ canvasElement.removeEventListener("pointerup", onPointerUp);
+ canvasElement.removeEventListener("keydown", onKeyDown);
+ helper.enabled = false;
+ helper.dispose();
+ };
+ }, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, floorItems, rotatedObjects, activeModule,]);
+
+ useEffect(() => {
+ if (activeModule !== "builder") {
+ clearSelection();
+ }
+ }, [activeModule]);
+
+ useFrame(() => {
+ if (pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) {
+ selectionGroup.current.position.set(0, 0, 0);
+ }
+ });
+
+ const selectAssets = () => {
+ selectionBox.endPoint.set(pointer.x, pointer.y, 0);
+ if (controls) (controls as any).enabled = true;
+
+ let selectedObjects = selectionBox.select();
+ let Objects = new Set();
+
+ selectedObjects.map((object) => {
+ let currentObject: THREE.Object3D | null = object;
+ while (currentObject) {
+ if (currentObject.userData.modelId) {
+ Objects.add(currentObject);
+ break;
+ }
+ currentObject = currentObject.parent || null;
+ }
+ });
+
+ if (Objects.size === 0) {
+ clearSelection();
+ return;
+ }
+
+ const updatedSelections = new Set(selectedAssets);
+ Objects.forEach((obj) => { updatedSelections.has(obj) ? updatedSelections.delete(obj) : updatedSelections.add(obj); });
+
+ const selected = Array.from(updatedSelections);
+
+ setSelectedAssets(selected);
+ };
+
+ const clearSelection = () => {
+ selectionGroup.current.children = [];
+ selectionGroup.current.position.set(0, 0, 0);
+ selectionGroup.current.rotation.set(0, 0, 0);
+ setpastedObjects([]);
+ setDuplicatedObjects([]);
+ setSelectedAssets([]);
+ };
+
+ const deleteSelection = () => {
+ if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
+
+ const storedItems = JSON.parse(localStorage.getItem("FloorItems") || "[]");
+ const selectedUUIDs = selectedAssets.map((mesh: THREE.Object3D) => mesh.uuid);
+
+ const updatedStoredItems = storedItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid));
+ localStorage.setItem("FloorItems", JSON.stringify(updatedStoredItems));
+
+ selectedAssets.forEach((selectedMesh: THREE.Object3D) => {
+ //REST
+
+ // const response = await deleteFloorItem(organization, selectedMesh.uuid, selectedMesh.userData.name);
+
+ //SOCKET
+
+ const data = {
+ organization: organization,
+ modeluuid: selectedMesh.uuid,
+ modelname: selectedMesh.userData.name,
+ socketId: socket.id,
+ };
+
+ socket.emit("v2:model-asset:delete", data);
+
+ selectedMesh.traverse((child: THREE.Object3D) => {
+ if (child instanceof THREE.Mesh) {
+ if (child.geometry) child.geometry.dispose();
+ if (Array.isArray(child.material)) {
+ child.material.forEach((material) => {
+ if (material.map) material.map.dispose();
+ material.dispose();
+ });
+ } else if (child.material) {
+ if (child.material.map) child.material.map.dispose();
+ child.material.dispose();
+ }
+ }
+ });
+
+ itemsGroupRef.current?.remove(selectedMesh);
+ });
+
+ const updatedItems = floorItems.filter((item: { modeluuid: string }) => !selectedUUIDs.includes(item.modeluuid));
+ setFloorItems(updatedItems);
+ }
+ toast.success("Selected models removed!");
+ clearSelection();
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default SelectionControls;
diff --git a/app/src/modules/scene/controls/selection/selectionHelper.ts b/app/src/modules/scene/controls/selectionControls/selectionHelper.ts
similarity index 96%
rename from app/src/modules/scene/controls/selection/selectionHelper.ts
rename to app/src/modules/scene/controls/selectionControls/selectionHelper.ts
index ae37e67..c1acaf6 100644
--- a/app/src/modules/scene/controls/selection/selectionHelper.ts
+++ b/app/src/modules/scene/controls/selectionControls/selectionHelper.ts
@@ -1,115 +1,115 @@
-import { Vector2, WebGLRenderer } from 'three';
-
-class SelectionHelper {
- element: HTMLDivElement;
- renderer: WebGLRenderer;
- startPoint: Vector2;
- pointTopLeft: Vector2;
- pointBottomRight: Vector2;
- isDown: boolean;
- enabled: boolean;
-
- constructor(renderer: WebGLRenderer) {
- this.element = document.createElement('div');
- this.element.style.position = 'fixed';
- this.element.style.border = '1px solid #55aaff';
- this.element.style.backgroundColor = 'rgba(75, 160, 255, 0.3)';
- this.element.style.pointerEvents = 'none';
- this.element.style.display = 'none';
-
- this.renderer = renderer;
-
- this.startPoint = new Vector2();
- this.pointTopLeft = new Vector2();
- this.pointBottomRight = new Vector2();
-
- this.isDown = false;
- this.enabled = true;
-
- this.onPointerDown = this.onPointerDown.bind(this);
- this.onPointerMove = this.onPointerMove.bind(this);
- this.onPointerUp = this.onPointerUp.bind(this);
-
- this.renderer.domElement.addEventListener('pointerdown', this.onPointerDown);
- this.renderer.domElement.addEventListener('pointermove', this.onPointerMove);
- this.renderer.domElement.addEventListener('pointerup', this.onPointerUp);
- window.addEventListener("blur", this.cleanup.bind(this));
- }
-
- dispose() {
- this.enabled = false;
- this.isDown = false;
- this.cleanup();
-
- this.renderer.domElement.removeEventListener("pointerdown", this.onPointerDown);
- this.renderer.domElement.removeEventListener("pointermove", this.onPointerMove);
- this.renderer.domElement.removeEventListener("pointerup", this.onPointerUp);
- window.removeEventListener("blur", this.cleanup);
- }
-
- private cleanup() {
- this.isDown = false;
- this.element.style.display = 'none';
- if (this.element.parentElement) {
- this.element.parentElement.removeChild(this.element);
- }
- }
-
- onPointerDown(event: PointerEvent) {
- if (!this.enabled || !event.ctrlKey || event.button !== 0) return;
-
- this.isDown = true;
- this.onSelectStart(event);
- }
-
- onPointerMove(event: PointerEvent) {
- if (!this.enabled || !this.isDown || !event.ctrlKey) return;
-
- this.onSelectMove(event);
- }
-
- onPointerUp() {
- if (!this.enabled) return;
-
- this.isDown = false;
- this.onSelectOver();
- }
-
- onSelectStart(event: PointerEvent) {
- this.element.style.display = 'none';
- this.renderer.domElement.parentElement?.appendChild(this.element);
-
- this.element.style.left = `${event.clientX}px`;
- this.element.style.top = `${event.clientY}px`;
- this.element.style.width = '0px';
- this.element.style.height = '0px';
-
- this.startPoint.x = event.clientX;
- this.startPoint.y = event.clientY;
- }
-
- onSelectMove(event: PointerEvent) {
- if (!this.isDown) return;
-
- this.element.style.display = 'block';
-
- this.pointBottomRight.x = Math.max(this.startPoint.x, event.clientX);
- this.pointBottomRight.y = Math.max(this.startPoint.y, event.clientY);
- this.pointTopLeft.x = Math.min(this.startPoint.x, event.clientX);
- this.pointTopLeft.y = Math.min(this.startPoint.y, event.clientY);
-
- this.element.style.left = `${this.pointTopLeft.x}px`;
- this.element.style.top = `${this.pointTopLeft.y}px`;
- this.element.style.width = `${this.pointBottomRight.x - this.pointTopLeft.x}px`;
- this.element.style.height = `${this.pointBottomRight.y - this.pointTopLeft.y}px`;
- }
-
- onSelectOver() {
- this.element.style.display = 'none';
- if (this.element.parentElement) {
- this.element.parentElement.removeChild(this.element);
- }
- }
-}
-
+import { Vector2, WebGLRenderer } from 'three';
+
+class SelectionHelper {
+ element: HTMLDivElement;
+ renderer: WebGLRenderer;
+ startPoint: Vector2;
+ pointTopLeft: Vector2;
+ pointBottomRight: Vector2;
+ isDown: boolean;
+ enabled: boolean;
+
+ constructor(renderer: WebGLRenderer) {
+ this.element = document.createElement('div');
+ this.element.style.position = 'fixed';
+ this.element.style.border = '1px solid #55aaff';
+ this.element.style.backgroundColor = 'rgba(75, 160, 255, 0.3)';
+ this.element.style.pointerEvents = 'none';
+ this.element.style.display = 'none';
+
+ this.renderer = renderer;
+
+ this.startPoint = new Vector2();
+ this.pointTopLeft = new Vector2();
+ this.pointBottomRight = new Vector2();
+
+ this.isDown = false;
+ this.enabled = true;
+
+ this.onPointerDown = this.onPointerDown.bind(this);
+ this.onPointerMove = this.onPointerMove.bind(this);
+ this.onPointerUp = this.onPointerUp.bind(this);
+
+ this.renderer.domElement.addEventListener('pointerdown', this.onPointerDown);
+ this.renderer.domElement.addEventListener('pointermove', this.onPointerMove);
+ this.renderer.domElement.addEventListener('pointerup', this.onPointerUp);
+ window.addEventListener("blur", this.cleanup.bind(this));
+ }
+
+ dispose() {
+ this.enabled = false;
+ this.isDown = false;
+ this.cleanup();
+
+ this.renderer.domElement.removeEventListener("pointerdown", this.onPointerDown);
+ this.renderer.domElement.removeEventListener("pointermove", this.onPointerMove);
+ this.renderer.domElement.removeEventListener("pointerup", this.onPointerUp);
+ window.removeEventListener("blur", this.cleanup);
+ }
+
+ private cleanup() {
+ this.isDown = false;
+ this.element.style.display = 'none';
+ if (this.element.parentElement) {
+ this.element.parentElement.removeChild(this.element);
+ }
+ }
+
+ onPointerDown(event: PointerEvent) {
+ if (!this.enabled || !event.ctrlKey || event.button !== 0) return;
+
+ this.isDown = true;
+ this.onSelectStart(event);
+ }
+
+ onPointerMove(event: PointerEvent) {
+ if (!this.enabled || !this.isDown || !event.ctrlKey) return;
+
+ this.onSelectMove(event);
+ }
+
+ onPointerUp() {
+ if (!this.enabled) return;
+
+ this.isDown = false;
+ this.onSelectOver();
+ }
+
+ onSelectStart(event: PointerEvent) {
+ this.element.style.display = 'none';
+ this.renderer.domElement.parentElement?.appendChild(this.element);
+
+ this.element.style.left = `${event.clientX}px`;
+ this.element.style.top = `${event.clientY}px`;
+ this.element.style.width = '0px';
+ this.element.style.height = '0px';
+
+ this.startPoint.x = event.clientX;
+ this.startPoint.y = event.clientY;
+ }
+
+ onSelectMove(event: PointerEvent) {
+ if (!this.isDown) return;
+
+ this.element.style.display = 'block';
+
+ this.pointBottomRight.x = Math.max(this.startPoint.x, event.clientX);
+ this.pointBottomRight.y = Math.max(this.startPoint.y, event.clientY);
+ this.pointTopLeft.x = Math.min(this.startPoint.x, event.clientX);
+ this.pointTopLeft.y = Math.min(this.startPoint.y, event.clientY);
+
+ this.element.style.left = `${this.pointTopLeft.x}px`;
+ this.element.style.top = `${this.pointTopLeft.y}px`;
+ this.element.style.width = `${this.pointBottomRight.x - this.pointTopLeft.x}px`;
+ this.element.style.height = `${this.pointBottomRight.y - this.pointTopLeft.y}px`;
+ }
+
+ onSelectOver() {
+ this.element.style.display = 'none';
+ if (this.element.parentElement) {
+ this.element.parentElement.removeChild(this.element);
+ }
+ }
+}
+
export { SelectionHelper };
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/transformControls.tsx b/app/src/modules/scene/controls/transformControls.tsx
deleted file mode 100644
index 2e586cc..0000000
--- a/app/src/modules/scene/controls/transformControls.tsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import { TransformControls } from "@react-three/drei";
-import * as THREE from "three";
-import { useSelectedFloorItem, useObjectPosition, useObjectScale, useObjectRotation, useTransformMode, useFloorItems, useSocketStore, useActiveTool } from "../../../store/store";
-import { useThree } from "@react-three/fiber";
-
-import * as Types from '../../../types/world/worldTypes';
-import { useEffect } from "react";
-
-export default function TransformControl() {
- const state = useThree();
- const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
- const { objectPosition, setObjectPosition } = useObjectPosition();
- const { objectScale, setObjectScale } = useObjectScale();
- const { objectRotation, setObjectRotation } = useObjectRotation();
- const { transformMode, setTransformMode } = useTransformMode();
- const { floorItems, setFloorItems } = useFloorItems();
- const { activeTool, setActiveTool } = useActiveTool();
- const { socket } = useSocketStore();
-
- function handleObjectChange() {
- if (selectedFloorItem && transformMode) {
- setObjectPosition(selectedFloorItem.position);
- setObjectScale(selectedFloorItem.scale);
- setObjectRotation({
- x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x),
- y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y),
- z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z),
- });
- }
- }
- function handleMouseUp() {
- if (selectedFloorItem) {
- setObjectPosition(selectedFloorItem.position);
- setObjectScale(selectedFloorItem.scale);
- setObjectRotation({
- x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x),
- y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y),
- z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z),
- });
- }
- setFloorItems((prevItems: Types.FloorItems) => {
- if (!prevItems) {
- return
- }
- let updatedItem: any = null;
- const updatedItems = prevItems.map((item) => {
- if (item.modeluuid === selectedFloorItem?.uuid) {
- updatedItem = {
- ...item,
- position: [selectedFloorItem.position.x, selectedFloorItem.position.y, selectedFloorItem.position.z,] as [number, number, number],
- rotation: { x: selectedFloorItem.rotation.x, y: selectedFloorItem.rotation.y, z: selectedFloorItem.rotation.z, },
- };
- return updatedItem;
- }
- return item;
- });
- if (updatedItem && selectedFloorItem) {
- const email = localStorage.getItem('email')
- const organization = (email!.split("@")[1]).split(".")[0];
-
- //REST
-
- // setFloorItemApi(
- // organization,
- // updatedItem.modeluuid,
- // updatedItem.modelname,
- // [selectedFloorItem.position.x, selectedFloorItem.position.y, selectedFloorItem.position.z,],
- // { "x": selectedFloorItem.rotation.x, "y": selectedFloorItem.rotation.y, "z": selectedFloorItem.rotation.z },
- // false,
- // true,
- // );
-
- //SOCKET
-
- const data = {
- organization: organization,
- modeluuid: updatedItem.modeluuid,
- modelname: updatedItem.modelname,
- position: [selectedFloorItem.position.x, selectedFloorItem.position.y, selectedFloorItem.position.z],
- rotation: { "x": selectedFloorItem.rotation.x, "y": selectedFloorItem.rotation.y, "z": selectedFloorItem.rotation.z },
- isLocked: false,
- isVisible: true,
- socketId: socket.id
- }
-
- socket.emit('v2:model-asset:add', data);
- }
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
- }
-
- useEffect(() => {
- if (activeTool === "Add pillar" || activeTool === "Delete") {
- if (state.controls) {
- const target = (state.controls as any).getTarget(new THREE.Vector3());
- (state.controls as any).setTarget(target.x, 0, target.z, true);
- }
- setSelectedFloorItem(null);
- {
- setObjectPosition({ x: undefined, y: undefined, z: undefined });
- setObjectScale({ x: undefined, y: undefined, z: undefined });
- setObjectRotation({ x: undefined, y: undefined, z: undefined });
- }
- }
- }, [activeTool]);
-
- return (
- <>
- {(selectedFloorItem && transformMode) &&
-
- }
- >
- );
-}
diff --git a/app/src/modules/scene/environment/sky.tsx b/app/src/modules/scene/environment/sky.tsx
index 3be57ce..dbfda22 100644
--- a/app/src/modules/scene/environment/sky.tsx
+++ b/app/src/modules/scene/environment/sky.tsx
@@ -5,6 +5,7 @@ import { useEffect, useRef, useState } from "react";
import * as CONSTANTS from '../../../types/world/worldConstants';
export default function Sun() {
+ const savedTheme: string | null = localStorage.getItem("theme");
const { elevation, setElevation } = useElevation();
const { sunPosition, setSunPosition } = useSunPosition();
const { azimuth, setAzimuth } = useAzimuth();
@@ -28,7 +29,7 @@ export default function Sun() {
return (
<>
- {(azimuth !== undefined && elevation !== undefined) && (
+ {(azimuth !== undefined && elevation !== undefined && savedTheme !== "dark") && (
<>
)}
- {selectedActionSphere && (
-
- )}
- {selectedPath && (
-
- )}
>
);
diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx
index 941616c..41ededb 100644
--- a/app/src/modules/scene/scene.tsx
+++ b/app/src/modules/scene/scene.tsx
@@ -1,63 +1,33 @@
import { useMemo } from "react";
import { Canvas } from "@react-three/fiber";
-import { Environment, KeyboardControls, Stars } from "@react-three/drei";
+import { KeyboardControls } from "@react-three/drei";
-import World from "./world/world";
-import Controls from "./controls/controls";
-import TransformControl from "./controls/transformControls";
-import PostProcessing from "./postProcessing/postProcessing";
-import Sun from "./environment/sky";
-import CamModelsGroup from "../collaboration/collabCams";
-import Shadows from "./environment/shadow";
-import MqttEvents from "../../services/factoryBuilder/mqtt/mqttEvents";
-
-import background from "../../assets/textures/hdr/mudroadpuresky2k.hdr";
-import SelectionControls from "./controls/selection/selectionControls";
-import MeasurementTool from "./tools/measurementTool";
+import Builder from "../builder/builder";
+import Visualization from "../visualization/visualization";
+import Setup from "./setup/setup";
import Simulation from "../simulation/simulation";
-// import Simulation from "./simulationtemp/simulation";
-import ZoneCentreTarget from "../visualization/functions/zoneCameraTarget";
-import Dropped3dWidgets from "../../modules/visualization/widgets/3d/Dropped3dWidget";
-import ZoneAssets from "../visualization/zoneAssets";
-
export default function Scene() {
- const map = useMemo(
- () => [
- { name: "forward", keys: ["ArrowUp", "w", "W"] },
- { name: "backward", keys: ["ArrowDown", "s", "S"] },
- { name: "left", keys: ["ArrowLeft", "a", "A"] },
- { name: "right", keys: ["ArrowRight", "d", "D"] },
- ],
- []
- );
- const savedTheme: string | null = localStorage.getItem("theme");
+ const map = useMemo(() => [
+ { name: "forward", keys: ["ArrowUp", "w", "W"] },
+ { name: "backward", keys: ["ArrowDown", "s", "S"] },
+ { name: "left", keys: ["ArrowLeft", "a", "A"] },
+ { name: "right", keys: ["ArrowRight", "d", "D"] },],
+ []);
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/app/src/modules/scene/setup/setup.tsx b/app/src/modules/scene/setup/setup.tsx
new file mode 100644
index 0000000..34289f9
--- /dev/null
+++ b/app/src/modules/scene/setup/setup.tsx
@@ -0,0 +1,25 @@
+import Sun from '../environment/sky'
+import Shadows from '../environment/shadow'
+import PostProcessing from '../postProcessing/postProcessing'
+import Controls from '../controls/controls';
+import { Environment } from '@react-three/drei'
+
+import background from "../../../assets/hdr/mudroadpuresky2k.hdr";
+
+function Setup() {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
+
+export default Setup
\ No newline at end of file
diff --git a/app/src/modules/simulation/armbot/ArmBot.tsx b/app/src/modules/simulation/armbot/ArmBot.tsx
deleted file mode 100644
index 066779a..0000000
--- a/app/src/modules/simulation/armbot/ArmBot.tsx
+++ /dev/null
@@ -1,87 +0,0 @@
-import React, { useEffect, useState } from "react";
-import { useThree } from "@react-three/fiber";
-import useModuleStore from "../../../store/useModuleStore";
-import { useSimulationStates } from "../../../store/store";
-import * as SimulationTypes from '../../../types/simulationTypes';
-import { ArmbotInstances } from "./ArmBotInstances";
-import { useResetButtonStore } from "../../../store/usePlayButtonStore";
-
-interface ArmBotState {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- status: string;
- material: string;
- triggerId: string;
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
- isActive?: boolean;
-}
-
-interface StaticMachineState {
- uuid: string;
- status: string;
- actions: { uuid: string; name: string; buffer: number; material: string; };
- machineTriggerId: string;
- connectedArmBot: string;
-}
-
-interface ArmBotProps {
- armBots: ArmBotState[];
- setArmBots: React.Dispatch>;
- setStaticMachines: React.Dispatch>;
-}
-
-const ArmBot = ({ armBots, setArmBots, setStaticMachines }: ArmBotProps) => {
- const { activeModule } = useModuleStore();
- const { scene } = useThree();
- const { simulationStates } = useSimulationStates();
- const { isReset } = useResetButtonStore();
-
- useEffect(() => {
- const filtered = simulationStates.filter((s): s is SimulationTypes.ArmBotEventsSchema => s.type === "ArmBot");
- const initialStates: ArmBotState[] = filtered
- .filter(bot => bot.points.connections.targets.length > 0)
- .map(bot => ({
- uuid: bot.modeluuid,
- position: bot.position,
- rotation: bot.rotation,
- status: "idle",
- material: "default",
- triggerId: '',
- actions: bot.points.actions,
- connections: bot.points.connections,
- isActive: false
- }));
- setArmBots(initialStates);
- }, [simulationStates, isReset]);
-
- useEffect(() => {
- armBots.forEach((bot) => {
- const object = scene.getObjectByProperty("uuid", bot.uuid);
- if (object) {
- object.visible = activeModule !== "simulation";
- }
- });
- }, [scene, activeModule, armBots]);
-
- return (
- <>
- {activeModule === "simulation" &&
- armBots.map((bot, i) => (
-
- ))}
- >
- );
-};
-
-export default ArmBot;
diff --git a/app/src/modules/simulation/armbot/ArmBotInstances.tsx b/app/src/modules/simulation/armbot/ArmBotInstances.tsx
deleted file mode 100644
index a0657db..0000000
--- a/app/src/modules/simulation/armbot/ArmBotInstances.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import IkInstances from "./IkInstances";
-import armModel from "../../../assets/gltf-glb/rigged/ik_arm_4.glb";
-import { useEffect, useState } from "react";
-import { useThree } from "@react-three/fiber";
-import { Vector3 } from "three";
-
-interface Process {
- triggerId: string;
- startPoint?: Vector3;
- endPoint?: Vector3;
- speed: number;
-}
-
-interface ArmBotState {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- status: string;
- material: string;
- triggerId: string;
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
- isActive?: boolean;
-}
-
-interface StaticMachineState {
- uuid: string;
- status: string;
- actions: { uuid: string; name: string; buffer: number; material: string; };
- machineTriggerId: string;
- connectedArmBot: string;
-}
-
-interface ArmbotInstancesProps {
- index: number;
- armBot: ArmBotState;
- setArmBots: React.Dispatch>;
- setStaticMachines: React.Dispatch>;
-}
-
-export const ArmbotInstances: React.FC = ({ index, armBot, setArmBots, setStaticMachines }) => {
- const { scene } = useThree();
- const [processes, setProcesses] = useState([]);
-
- useEffect(() => {
- if (armBot.actions.processes.length > 0) {
- const mappedProcesses = armBot.actions.processes.map((process) => {
- return {
- triggerId: process.triggerId,
- startPoint: scene.getObjectByProperty('uuid', process.startPoint)?.getWorldPosition(new Vector3()),
- endPoint: scene.getObjectByProperty('uuid', process.endPoint)?.getWorldPosition(new Vector3()),
- speed: armBot.actions.speed
- };
- });
- setProcesses(mappedProcesses);
- } else {
- setProcesses([]);
- }
- }, [armBot, scene]);
-
- const updateArmBotStatus = (status: string) => {
- setArmBots((prevArmBots) => {
- return prevArmBots.map(bot => {
- if (bot.uuid === armBot.uuid) {
- return { ...bot, status, triggerId: status === 'idle' ? '' : armBot.triggerId };
- }
- return bot;
- });
- });
- };
-
- return (
-
- );
-};
\ No newline at end of file
diff --git a/app/src/modules/simulation/armbot/IKAnimationController.tsx b/app/src/modules/simulation/armbot/IKAnimationController.tsx
deleted file mode 100644
index e2df7f5..0000000
--- a/app/src/modules/simulation/armbot/IKAnimationController.tsx
+++ /dev/null
@@ -1,379 +0,0 @@
-import { useEffect, useMemo, useState, useRef } from "react";
-import { useFrame } from "@react-three/fiber";
-import * as THREE from "three";
-import { usePlayButtonStore, useResetButtonStore } from "../../../store/usePlayButtonStore";
-import { useSimulationStates } from "../../../store/store";
-import MaterialInstances from "./MaterialInstances";
-import { Line } from "react-chartjs-2";
-import { QuadraticBezierLine } from "@react-three/drei";
-
-
-interface StaticMachineState {
- uuid: string;
- status: string;
- actions: { uuid: string; name: string; buffer: number; material: string; };
- machineTriggerId: string;
- connectedArmBot: string;
-}
-
-interface ArmBotState {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- status: string;
- material: string;
- triggerId: string;
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
- isActive?: boolean;
-}
-
-type IKAnimationControllerProps = {
- ikSolver: any;
- processes: {
- triggerId: string;
- startPoint: THREE.Vector3;
- endPoint: THREE.Vector3;
- speed: number;
- }[];
- selectedTrigger: string;
- targetBoneName: string;
- uuid: string;
- logStatus: (status: string) => void;
- groupRef: React.RefObject;
- armBot: ArmBotState;
- setArmBots: React.Dispatch>;
- setStaticMachines: React.Dispatch>;
- updateArmBotStatus: (status: string) => void;
-}
-
-const IKAnimationController = ({
- ikSolver,
- processes,
- selectedTrigger,
- targetBoneName,
- uuid,
- logStatus,
- groupRef,
- armBot,
- setArmBots,
- setStaticMachines,
- updateArmBotStatus
-}: IKAnimationControllerProps) => {
- const [progress, setProgress] = useState(0);
- const [initialProgress, setInitialProgress] = useState(0);
- const [needsInitialMovement, setNeedsInitialMovement] = useState(true);
- const [isInitializing, setIsInitializing] = useState(true);
- const restSpeed = 0.1;
- const restPosition = new THREE.Vector3(0, 2, 1.6);
- const { isPlaying } = usePlayButtonStore();;
- const statusRef = useRef("idle");
- const { simulationStates } = useSimulationStates();
- const { isReset } = useResetButtonStore();
-
- const initialCurveRef = useRef(null);
- const initialStartPositionRef = useRef(null);
-
- useEffect(() => {
- setProgress(0);
- }, [selectedTrigger]);
-
- useEffect(() => {
- setProgress(0);
- setNeedsInitialMovement(true);
- setInitialProgress(0);
- setIsInitializing(true);
- }, [isReset]);
-
- useEffect(() => {
- if (ikSolver) {
- const targetBone = ikSolver.mesh.skeleton.bones.find(
- (b: any) => b.name === targetBoneName
- );
- if (targetBone) {
- initialStartPositionRef.current = targetBone.position.clone();
- calculateInitialCurve(targetBone.position);
- logStatus(`[Arm ${uuid}] Initializing IK system, starting position: ${targetBone.position.toArray()}`);
- }
- }
- }, [ikSolver]);
-
-
- const calculateInitialCurve = (startPosition: THREE.Vector3) => {
- const direction = new THREE.Vector3().subVectors(restPosition, startPosition);
- const distance = direction.length();
- direction.normalize();
-
- const perpendicular = new THREE.Vector3(-direction.z, 0, direction.x).normalize();
-
- const midHeight = 0.5;
- const tiltAmount = 1;
- const mid = new THREE.Vector3()
- .addVectors(startPosition, restPosition)
- .multiplyScalar(0.5)
- .add(perpendicular.clone().multiplyScalar(distance * 0.3 * tiltAmount))
- .add(new THREE.Vector3(0, midHeight, 0));
-
- initialCurveRef.current = new THREE.CatmullRomCurve3([
- startPosition,
- new THREE.Vector3().lerpVectors(startPosition, mid, 0.33),
- mid,
- new THREE.Vector3().lerpVectors(mid, restPosition, 0.66),
- restPosition
- ]);
- };
-
- const processedCurves = useMemo(() => {
- if (!isPlaying) return [];
-
- return processes.map(process => {
- const localStart = groupRef.current?.worldToLocal(process.startPoint.clone());
- const localEnd = groupRef.current?.worldToLocal(process.endPoint.clone());
-
- if (!localStart || !localEnd) return null;
-
- const midPoint = new THREE.Vector3(
- (localStart.x + localEnd.x) / 2,
- Math.max(localStart.y, localEnd.y) + 1,
- (localStart.z + localEnd.z) / 2
- );
- const restToStartCurve = new THREE.CatmullRomCurve3([
- restPosition,
- new THREE.Vector3().lerpVectors(restPosition, localStart, 0.5),
- localStart
- ]);
-
- const processCurve = new THREE.CatmullRomCurve3([
- localStart,
- midPoint,
- localEnd
- ]);
-
- const endToRestCurve = new THREE.CatmullRomCurve3([
- localEnd,
- new THREE.Vector3().lerpVectors(localEnd, restPosition, 0.5),
- restPosition
- ]);
-
- return {
- triggerId: process.triggerId,
- restToStartCurve,
- processCurve,
- endToRestCurve,
- speed: process.speed,
- totalDistance:
- restPosition.distanceTo(localStart) +
- localStart.distanceTo(localEnd) +
- localEnd.distanceTo(restPosition)
- };
- }).filter(Boolean);
- }, [processes, isPlaying]);
-
- const activeProcess = useMemo(() => {
- if (!selectedTrigger) return null;
- return processedCurves.find(p => p?.triggerId === selectedTrigger);
- }, [processedCurves, selectedTrigger]);
-
- // Initial movement to rest position
- useFrame((_, delta) => {
- if (!ikSolver || !needsInitialMovement || !isInitializing || !initialCurveRef.current) return;
-
- const targetBone = ikSolver.mesh.skeleton.bones.find(
- (b: any) => b.name === targetBoneName
- );
- if (!targetBone) return;
-
- setInitialProgress((prev) => {
- const next = prev + delta * 0.5;
- if (next >= 1) {
- targetBone.position.copy(restPosition);
- setNeedsInitialMovement(false);
- setIsInitializing(false);
- return 1;
- }
- targetBone.position.copy(initialCurveRef.current!.getPoint(next));
- return next;
- });
-
- ikSolver.update();
- });
-
- // Main animation loop
- useFrame((_, delta) => {
- if (isInitializing || !isPlaying || !selectedTrigger || !activeProcess || !ikSolver) return;
-
- const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBoneName);
- if (!bone) return;
-
- const {
- restToStartCurve,
- processCurve,
- endToRestCurve,
- speed,
- totalDistance
- } = activeProcess;
-
- // Calculate current segment and progress
- const restToStartDist = restPosition.distanceTo(restToStartCurve.points[2]);
- const processDist = processCurve.getLength();
- const endToRestDist = endToRestCurve.getLength();
-
- const restToStartEnd = restToStartDist / totalDistance;
- const processEnd = (restToStartDist + processDist) / totalDistance;
-
- setProgress(prev => {
- let currentStatus = statusRef.current;
- let currentPosition: THREE.Vector3;
- const newProgress = Math.min(prev + delta * ((currentStatus === 'returning to rest') ? restSpeed : speed), 1);
-
- if (newProgress < restToStartEnd) {
- // Moving from rest to start position
- currentStatus = "moving to start";
- const segmentProgress = newProgress / restToStartEnd;
- currentPosition = restToStartCurve.getPoint(segmentProgress);
- } else if (newProgress < processEnd) {
- // Processing - moving from start to end
- currentStatus = "processing";
- const segmentProgress = (newProgress - restToStartEnd) / (processEnd - restToStartEnd);
- currentPosition = processCurve.getPoint(segmentProgress);
- if (statusRef.current !== "processing") {
- updateConveyorOrStaticMachineStatusOnStart(selectedTrigger);
- }
- } else {
- // Returning to rest position
- currentStatus = "returning to rest";
- const segmentProgress = (newProgress - processEnd) / (1 - processEnd);
- currentPosition = endToRestCurve.getPoint(segmentProgress);
- }
-
- // Update status if changed
- if (currentStatus !== statusRef.current) {
- statusRef.current = currentStatus;
- // updateArmBotStatus(currentStatus);
- logStatus(`[Arm ${uuid}] Status: ${currentStatus}`);
- }
-
- // Only trigger when the entire animation is complete (newProgress === 1)
- if (newProgress === 1 && currentStatus === "returning to rest") {
- updateConveyorOrStaticMachineStatusOnEnd(selectedTrigger);
- }
-
- bone.position.copy(currentPosition);
- ikSolver.update();
- return newProgress;
- });
- });
-
- const updateConveyorOrStaticMachineStatusOnStart = (selectedTrigger: string) => {
- const currentProcess = processes.find(p => p.triggerId === selectedTrigger);
- if (currentProcess) {
- const triggerId = currentProcess.triggerId;
-
- const startPoint = armBot.actions.processes.find((process) => process.triggerId === triggerId)?.startPoint;
-
- const matchedMachine = simulationStates.find((state) => {
- if (state.type === "Conveyor") {
- return (state).points.some(
- (point) => point.uuid === startPoint
- );
- } else if (state.type === "StaticMachine") {
- return state.points.uuid === startPoint;
- }
- return false;
- });
-
- if (matchedMachine) {
- if (matchedMachine.type === "Conveyor") {
- logStatus(`[Arm ${uuid}] start point which is a conveyor (${matchedMachine.modelName})`);
- } else {
- logStatus(`[Arm ${uuid}] started form start point which is a static machine (${matchedMachine.modelName})`);
- }
-
- setTimeout(() => {
- if (matchedMachine.type === "StaticMachine") {
- updateArmBotStatus('dropping');
- }
-
- if (matchedMachine.type === "Conveyor") {
- updateArmBotStatus('picking');
- }
- }, 0);
- }
- }
- }
-
- const updateConveyorOrStaticMachineStatusOnEnd = (selectedTrigger: string) => {
- const currentProcess = processes.find(p => p.triggerId === selectedTrigger);
- if (currentProcess) {
- const triggerId = currentProcess.triggerId;
-
- const endPoint = armBot.actions.processes.find((process) => process.triggerId === triggerId)?.endPoint;
-
- const matchedMachine = simulationStates.find((state) => {
- if (state.type === "Conveyor") {
- return (state).points.some(
- (point) => point.uuid === endPoint
- );
- } else if (state.type === "StaticMachine") {
- return state.points.uuid === endPoint;
- }
- return false;
- });
-
- if (matchedMachine) {
- if (matchedMachine.type === "Conveyor") {
- logStatus(`[Arm ${uuid}] Reached end point which is a conveyor (${matchedMachine.modelName})`);
- } else {
- logStatus(`[Arm ${uuid}] Reached end point which is a static machine (${matchedMachine.modelName})`);
- }
-
- setTimeout(() => {
- if (matchedMachine.type === "StaticMachine") {
- setStaticMachines((machines) => {
- return machines.map((machine) => {
- if (machine.uuid === matchedMachine.modeluuid) {
- return { ...machine, status: "running" };
- } else {
- return machine;
- }
- });
- });
- updateArmBotStatus('idle');
- }
-
- if (matchedMachine.type === "Conveyor") {
- setArmBots((prev) =>
- prev.map((arm) => {
- if (arm.uuid === uuid && arm.isActive === true) {
- return {
- ...arm,
- isActive: false,
- status: "idle",
- };
- }
- else {
- return arm;
- }
- })
- );
- }
- }, 0);
- }
- }
- }
-
- return (
- <>
-
- >
- );
-};
-
-export default IKAnimationController;
\ No newline at end of file
diff --git a/app/src/modules/simulation/armbot/IkInstances.tsx b/app/src/modules/simulation/armbot/IkInstances.tsx
deleted file mode 100644
index 6e7dc13..0000000
--- a/app/src/modules/simulation/armbot/IkInstances.tsx
+++ /dev/null
@@ -1,150 +0,0 @@
-import * as THREE from "three";
-import { useEffect, useMemo, useRef, useState } from "react";
-import { useFrame, useLoader } from "@react-three/fiber";
-import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
-import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
-import { clone } from "three/examples/jsm/utils/SkeletonUtils";
-import { CCDIKSolver, CCDIKHelper, } from "three/examples/jsm/animation/CCDIKSolver";
-import IKAnimationController from "./IKAnimationController";
-import { TransformControls } from "@react-three/drei";
-
-interface StaticMachineState {
- uuid: string;
- status: string;
- actions: { uuid: string; name: string; buffer: number; material: string; };
- machineTriggerId: string;
- connectedArmBot: string;
-}
-
-interface ArmBotState {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- status: string;
- material: string;
- triggerId: string;
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
- isActive?: boolean;
-}
-
-const IkInstances = ({
- uuid,
- selectedTrigger,
- modelUrl,
- processes,
- position,
- rotation,
- armBot,
- setArmBots,
- setStaticMachines,
- updateArmBotStatus
-}: {
- uuid: string;
- selectedTrigger: string;
- modelUrl: string;
- processes: any;
- position: [number, number, number];
- rotation: [number, number, number];
- armBot: ArmBotState;
- setArmBots: React.Dispatch>;
- setStaticMachines: React.Dispatch>;
- updateArmBotStatus: (status: string) => void;
-}) => {
- const [ikSolver, setIkSolver] = useState(null);
- const gltf = useLoader(GLTFLoader, modelUrl, (loader) => {
- const draco = new DRACOLoader();
- draco.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/");
- loader.setDRACOLoader(draco);
- });
- const cloned = useMemo(() => clone(gltf.scene), [gltf]);
- const groupRef = useRef(null);
- const targetBoneName = "Target";
- const skinnedMeshName = "link_0";
-
- useEffect(() => {
- if (!gltf) return;
- const OOI: any = {};
- cloned.traverse((n: any) => {
- if (n.name === targetBoneName) OOI.Target_Bone = n;
- if (n.name === skinnedMeshName) OOI.Skinned_Mesh = n;
- });
-
- if (!OOI.Target_Bone || !OOI.Skinned_Mesh) return;
-
- const iks = [
- {
- target: 7,
- effector: 6,
- links: [
- {
- index: 5,
- enabled: true,
- rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0),
- rotationMax: new THREE.Vector3(Math.PI / 2, 0, 0),
- },
- {
- index: 4,
- enabled: true,
- rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0),
- rotationMax: new THREE.Vector3(0, 0, 0),
- },
- {
- index: 3,
- enabled: true,
- rotationMin: new THREE.Vector3(0, 0, 0),
- rotationMax: new THREE.Vector3(2, 0, 0),
- },
- { index: 1, enabled: true, limitation: new THREE.Vector3(0, 1, 0) },
- { index: 0, enabled: false, limitation: new THREE.Vector3(0, 0, 0) },
- ],
- },
- ];
-
- const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks);
- setIkSolver(solver);
-
- const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05);
- // groupRef.current.add(helper);
-
- }, [gltf]);
-
-
- const logStatus = (status: string) => {
- // console.log(status);
- }
-
- return (
- <>
-
-
-
-
- >
- );
-};
-
-export default IkInstances;
\ No newline at end of file
diff --git a/app/src/modules/simulation/armbot/MaterialInstances.tsx b/app/src/modules/simulation/armbot/MaterialInstances.tsx
deleted file mode 100644
index c83cd51..0000000
--- a/app/src/modules/simulation/armbot/MaterialInstances.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react';
-import * as THREE from 'three';
-import { Box } from '@react-three/drei';
-
-type MaterialInstancesProps = {
- statusRef: React.RefObject;
- ikSolver: any;
- targetBoneName: string;
-};
-
-function MaterialInstances({
- statusRef,
- ikSolver,
- targetBoneName
-}: MaterialInstancesProps) {
- if (!ikSolver) return null;
-
- const targetBone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBoneName);
- if (!targetBone) return null;
-
- const worldPos = new THREE.Vector3();
- targetBone.getWorldPosition(worldPos);
-
- return (
-
-
-
- );
-}
-
-export default MaterialInstances;
\ No newline at end of file
diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx
deleted file mode 100644
index 3db399e..0000000
--- a/app/src/modules/simulation/path/pathConnector.tsx
+++ /dev/null
@@ -1,1428 +0,0 @@
-import { useFrame, useThree } from "@react-three/fiber";
-import React, { useEffect, useRef, useState } from "react";
-import * as THREE from "three";
-import * as Types from "../../../types/world/worldTypes";
-import * as SimulationTypes from "../../../types/simulationTypes";
-import { QuadraticBezierLine } from "@react-three/drei";
-import { useDeleteTool, useIsConnecting, useRenderDistance, useSimulationStates, useSocketStore, } from "../../../store/store";
-import useModuleStore from "../../../store/useModuleStore";
-import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
-import { setEventApi } from "../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
-
-function PathConnector({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObject; }) {
- const { activeModule } = useModuleStore();
- const { gl, raycaster, scene, pointer, camera } = useThree();
- const { deleteTool } = useDeleteTool();
- const { renderDistance } = useRenderDistance();
- const { setIsConnecting } = useIsConnecting();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const { isPlaying } = usePlayButtonStore();
- const { socket } = useSocketStore();
- const groupRefs = useRef<{ [key: string]: any }>({});
-
- const [firstSelected, setFirstSelected] = useState<{ modelUUID: string; sphereUUID: string; position: THREE.Vector3; isCorner: boolean; } | null>(null);
- const [currentLine, setCurrentLine] = useState<{ start: THREE.Vector3; end: THREE.Vector3; mid: THREE.Vector3; } | null>(null);
- const [helperlineColor, setHelperLineColor] = useState("red");
- const [hoveredLineKey, setHoveredLineKey] = useState(null);
-
- const updatePathConnections = (fromModelUUID: string, fromPointUUID: string, toModelUUID: string, toPointUUID: string) => {
- const updatedPaths = simulationStates.map((path) => {
- if (path.type === "Conveyor") {
- // Handle outgoing connections from Conveyor
- if (path.modeluuid === fromModelUUID) {
- return {
- ...path,
- points: path.points.map((point) => {
- if (point.uuid === fromPointUUID) {
- const newTarget = {
- modelUUID: toModelUUID,
- pointUUID: toPointUUID,
- };
- const existingTargets = point.connections.targets || [];
-
- // Check connection limits
- const toPath = simulationStates.find(p => p.modeluuid === toModelUUID);
- if (toPath) {
- // Check if we already have this type of connection
- const hasConveyor = existingTargets.some(t => {
- const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
- return targetPath?.type === "Conveyor";
- });
- const hasArmBot = existingTargets.some(t => {
- const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
- return targetPath?.type === "ArmBot";
- });
- const hasVehicle = existingTargets.some(t => {
- const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
- return targetPath?.type === "Vehicle";
- });
-
- if (toPath.type === "Conveyor" && hasConveyor) {
- console.log("Conveyor can only connect to one other conveyor");
- return point;
- }
- if (toPath.type === "ArmBot" && hasArmBot) {
- console.log("Conveyor can only connect to one ArmBot");
- return point;
- }
- if (toPath.type === "Vehicle" && hasVehicle) {
- console.log("Conveyor can only connect to one Vehicle");
- return point;
- }
- }
-
- if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) {
- return {
- ...point,
- connections: {
- ...point.connections,
- targets: [...existingTargets, newTarget],
- },
- };
- }
- }
- return point;
- }),
- };
- }
- // Handle incoming connections to Conveyor
- else if (path.modeluuid === toModelUUID) {
- return {
- ...path,
- points: path.points.map((point) => {
- if (point.uuid === toPointUUID) {
- const reverseTarget = {
- modelUUID: fromModelUUID,
- pointUUID: fromPointUUID,
- };
- const existingTargets = point.connections.targets || [];
-
- // Check connection limits
- const fromPath = simulationStates.find(p => p.modeluuid === fromModelUUID);
- if (fromPath) {
- const hasConveyor = existingTargets.some(t => {
- const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
- return targetPath?.type === "Conveyor";
- });
- const hasArmBot = existingTargets.some(t => {
- const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
- return targetPath?.type === "ArmBot";
- });
- const hasVehicle = existingTargets.some(t => {
- const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
- return targetPath?.type === "Vehicle";
- });
-
- if (fromPath.type === "Conveyor" && hasConveyor) {
- console.log("Conveyor can only connect to one other conveyor");
- return point;
- }
- if (fromPath.type === "ArmBot" && hasArmBot) {
- console.log("Conveyor can only connect to one ArmBot");
- return point;
- }
- if (fromPath.type === "Vehicle" && hasVehicle) {
- console.log("Conveyor can only connect to one Vehicle");
- return point;
- }
- }
-
- if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) {
- return {
- ...point,
- connections: {
- ...point.connections,
- targets: [...existingTargets, reverseTarget],
- },
- };
- }
- }
- return point;
- }),
- };
- }
- } else if (path.type === "Vehicle") {
- // Handle outgoing connections from Vehicle
- if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
- const newTarget = {
- modelUUID: toModelUUID,
- pointUUID: toPointUUID,
- };
- const existingTargets = path.points.connections.targets || [];
-
- // Check if target is a Conveyor
- const toPath = simulationStates.find((p) => p.modeluuid === toModelUUID);
- if (toPath?.type !== "Conveyor") {
- console.log("Vehicle can only connect to Conveyors");
- return path;
- }
-
- // Check if already has a connection
- if (existingTargets.length >= 1) {
- console.log("Vehicle can have only one connection");
- return path;
- }
-
- if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) {
- return {
- ...path,
- points: {
- ...path.points,
- connections: {
- ...path.points.connections,
- targets: [...existingTargets, newTarget],
- },
- },
- };
- }
- }
- // Handle incoming connections to Vehicle
- else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
- const reverseTarget = {
- modelUUID: fromModelUUID,
- pointUUID: fromPointUUID,
- };
- const existingTargets = path.points.connections.targets || [];
-
- // Check if source is a Conveyor
- const fromPath = simulationStates.find((p) => p.modeluuid === fromModelUUID);
- if (fromPath?.type !== "Conveyor") {
- console.log("Vehicle can only connect to Conveyors");
- return path;
- }
-
- // Check if already has a connection
- if (existingTargets.length >= 1) {
- console.log("Vehicle can have only one connection");
- return path;
- }
-
- if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) {
- return {
- ...path,
- points: {
- ...path.points,
- connections: {
- ...path.points.connections,
- targets: [...existingTargets, reverseTarget],
- },
- },
- };
- }
- }
- return path;
- } else if (path.type === "StaticMachine") {
- // Handle outgoing connections from StaticMachine
- if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
- const newTarget = {
- modelUUID: toModelUUID,
- pointUUID: toPointUUID,
- };
-
- // Ensure target is an ArmBot
- const toPath = simulationStates.find((p) => p.modeluuid === toModelUUID);
- if (toPath?.type !== "ArmBot") {
- console.log("StaticMachine can only connect to ArmBot");
- return path;
- }
-
- const existingTargets = path.points.connections.targets || [];
-
- // Allow only one connection
- if (existingTargets.length >= 1) {
- console.log("StaticMachine can only have one connection");
- return path;
- }
-
- if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) {
- return {
- ...path,
- points: {
- ...path.points,
- connections: {
- ...path.points.connections,
- targets: [...existingTargets, newTarget],
- },
- },
- };
- }
- }
-
- // Handle incoming connections to StaticMachine
- else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
- const reverseTarget = {
- modelUUID: fromModelUUID,
- pointUUID: fromPointUUID,
- };
-
- const fromPath = simulationStates.find((p) => p.modeluuid === fromModelUUID);
- if (fromPath?.type !== "ArmBot") {
- console.log("StaticMachine can only be connected from ArmBot");
- return path;
- }
-
- const existingTargets = path.points.connections.targets || [];
-
- if (existingTargets.length >= 1) {
- console.log("StaticMachine can only have one connection");
- return path;
- }
-
- if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) {
- return {
- ...path,
- points: {
- ...path.points,
- connections: {
- ...path.points.connections,
- targets: [...existingTargets, reverseTarget],
- },
- },
- };
- }
- }
- return path;
- } else if (path.type === "ArmBot") {
- // Handle outgoing connections from ArmBot
- if (path.modeluuid === fromModelUUID && path.points.uuid === fromPointUUID) {
- const newTarget = {
- modelUUID: toModelUUID,
- pointUUID: toPointUUID,
- };
-
- const toPath = simulationStates.find((p) => p.modeluuid === toModelUUID);
- if (!toPath) return path;
-
- const existingTargets = path.points.connections.targets || [];
-
- // Check if connecting to a StaticMachine and already connected to one
- const alreadyConnectedToStatic = existingTargets.some((target) => {
- const targetPath = simulationStates.find((p) => p.modeluuid === target.modelUUID);
- return targetPath?.type === "StaticMachine";
- });
-
- if (toPath.type === "StaticMachine") {
- if (alreadyConnectedToStatic) {
- console.log("ArmBot can only connect to one StaticMachine");
- return path;
- }
- }
-
- if (!existingTargets.some((target) => target.modelUUID === newTarget.modelUUID && target.pointUUID === newTarget.pointUUID)) {
- return {
- ...path,
- points: {
- ...path.points,
- connections: {
- ...path.points.connections,
- targets: [...existingTargets, newTarget],
- },
- },
- };
- }
- }
-
- // Handle incoming connections to ArmBot
- else if (path.modeluuid === toModelUUID && path.points.uuid === toPointUUID) {
- const reverseTarget = {
- modelUUID: fromModelUUID,
- pointUUID: fromPointUUID,
- };
-
- const fromPath = simulationStates.find((p) => p.modeluuid === fromModelUUID);
- if (!fromPath) return path;
-
- const existingTargets = path.points.connections.targets || [];
-
- const alreadyConnectedFromStatic = existingTargets.some((target) => {
- const targetPath = simulationStates.find((p) => p.modeluuid === target.modelUUID);
- return targetPath?.type === "StaticMachine";
- });
-
- if (fromPath.type === "StaticMachine") {
- if (alreadyConnectedFromStatic) {
- console.log(
- "ArmBot can only be connected from one StaticMachine"
- );
- return path;
- }
- }
-
- if (!existingTargets.some((target) => target.modelUUID === reverseTarget.modelUUID && target.pointUUID === reverseTarget.pointUUID)) {
- return {
- ...path,
- points: {
- ...path.points,
- connections: {
- ...path.points.connections,
- targets: [...existingTargets, reverseTarget],
- },
- },
- };
- }
- }
- return path;
- }
-
- return path;
- });
-
- setSimulationStates(updatedPaths);
-
- const updatedPathDetails = updatedPaths.filter((path) => path.modeluuid === fromModelUUID || path.modeluuid === toModelUUID);
-
- updateBackend(updatedPathDetails);
- };
-
- const updateBackend = async (updatedPaths: (| SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
- if (updatedPaths.length === 0) return;
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "";
-
- updatedPaths.forEach(async (updatedPath) => {
- if (updatedPath.type === "Conveyor") {
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "Conveyor", points: updatedPath.points, speed: updatedPath.speed }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: {
- type: "Conveyor",
- points: updatedPath.points,
- speed: updatedPath.speed,
- },
- };
-
- socket.emit("v2:model-asset:updateEventData", data);
- } else if (updatedPath.type === "Vehicle") {
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "Vehicle", points: updatedPath.points }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: { type: "Vehicle", points: updatedPath.points },
- };
-
- socket.emit("v2:model-asset:updateEventData", data);
- } else if (updatedPath.type === "StaticMachine") {
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "StaticMachine", points: updatedPath.points }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: { type: "StaticMachine", points: updatedPath.points },
- };
-
- socket.emit("v2:model-asset:updateEventData", data);
- } else if (updatedPath.type === "ArmBot") {
- // await setEventApi(
- // organization,
- // updatedPath.modeluuid,
- // { type: "ArmBot", points: updatedPath.points }
- // );
-
- const data = {
- organization: organization,
- modeluuid: updatedPath.modeluuid,
- eventData: { type: "ArmBot", points: updatedPath.points },
- };
-
- socket.emit("v2:model-asset:updateEventData", data);
- }
- });
- };
-
- const handleAddConnection = (fromModelUUID: string, fromUUID: string, toModelUUID: string, toUUID: string) => {
- updatePathConnections(fromModelUUID, fromUUID, toModelUUID, toUUID);
- setFirstSelected(null);
- setCurrentLine(null);
- setIsConnecting(false);
- };
-
- useEffect(() => {
- const canvasElement = gl.domElement;
- let drag = false;
- let MouseDown = false;
-
- const onMouseDown = () => {
- MouseDown = true;
- drag = false;
- };
-
- const onMouseUp = () => {
- MouseDown = false;
- };
-
- const onMouseMove = () => {
- if (MouseDown) {
- drag = true;
- }
- };
-
- const onContextMenu = (evt: MouseEvent) => {
- evt.preventDefault();
- if (drag || evt.button === 0) return;
-
- raycaster.setFromCamera(pointer, camera);
- const intersects = raycaster.intersectObjects(
- pathsGroupRef.current.children,
- true
- );
-
- if (intersects.length > 0) {
- const intersected = intersects[0].object;
-
- if (intersected.name.includes("events-sphere")) {
- const modelUUID = intersected.userData.path.modeluuid;
- const sphereUUID = intersected.uuid;
- const worldPosition = new THREE.Vector3();
- intersected.getWorldPosition(worldPosition);
-
- let isStartOrEnd = false;
-
- if (intersected.userData.path.points && intersected.userData.path.points.length > 1) {
- 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.points) {
- isStartOrEnd = sphereUUID === intersected.userData.path.points.uuid;
- }
-
- if (modelUUID) {
- const firstPath = simulationStates.find((p) => p.modeluuid === firstSelected?.modelUUID);
- const secondPath = simulationStates.find((p) => p.modeluuid === modelUUID);
-
- // Prevent vehicle-to-vehicle connections
- if (firstPath && secondPath && firstPath.type === "Vehicle" && secondPath.type === "Vehicle") {
- console.log("Cannot connect two vehicle paths together");
- return;
- }
-
- // Prevent conveyor middle point to conveyor connections
- if (firstPath && secondPath && firstPath.type === "Conveyor" && secondPath.type === "Conveyor" && (!firstSelected?.isCorner || !isStartOrEnd)) {
- console.log("Conveyor connections must be between start/end points");
- return;
- }
-
- // Check if this specific connection already exists
- const isDuplicateConnection = firstSelected
- ? simulationStates.some((path) => {
- if (path.modeluuid === firstSelected.modelUUID) {
- if (path.type === "Conveyor") {
- const point = path.points.find(
- (p) => p.uuid === firstSelected.sphereUUID
- );
- return point?.connections.targets.some(
- (t) =>
- t.modelUUID === modelUUID &&
- t.pointUUID === sphereUUID
- );
- } else if (path.type === "Vehicle") {
- return path.points.connections.targets.some(
- (t) =>
- t.modelUUID === modelUUID &&
- t.pointUUID === sphereUUID
- );
- }
- }
- return false;
- })
- : false;
-
- if (isDuplicateConnection) {
- console.log("These points are already connected. Ignoring.");
- return;
- }
-
- // For Vehicles, check if they're already connected to anything
- if (intersected.userData.path.type === "Vehicle") {
- const vehicleConnections =
- intersected.userData.path.points.connections.targets.length;
- if (vehicleConnections >= 1) {
- console.log("Vehicle can only have one connection");
- return;
- }
- }
-
- // For Conveyors, check connection limits in BOTH DIRECTIONS
- if (firstSelected && (firstPath?.type === "Conveyor" || secondPath?.type === "Conveyor")) {
- const checkConveyorLimits = (path: any, pointUUID: string) => {
- if (path?.type === "Conveyor") {
- const point = path.points.find((p: { uuid: string }) => p.uuid === pointUUID);
- if (point) {
- return {
- hasConveyor: point.connections.targets.some((t: { modelUUID: string }) => {
- const targetPath = simulationStates.find((p: { modeluuid: string }) => p.modeluuid === t.modelUUID);
- return targetPath?.type === "Conveyor";
- }),
- hasArmBot: point.connections.targets.some((t: { modelUUID: string }) => {
- const targetPath = simulationStates.find((p: { modeluuid: string }) => p.modeluuid === t.modelUUID);
- return targetPath?.type === "ArmBot";
- }),
- hasVehicle: point.connections.targets.some((t: { modelUUID: string }) => {
- const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
- return targetPath?.type === "Vehicle";
- })
- };
- }
- }
- return { hasConveyor: false, hasArmBot: false, hasVehicle: false };
- };
-
- const firstConveyorLimits = checkConveyorLimits(firstPath, firstSelected?.sphereUUID);
- const secondConveyorLimits = checkConveyorLimits(secondPath, sphereUUID);
-
- // Check if trying to connect two conveyors
- if (firstPath?.type === "Conveyor" && secondPath?.type === "Conveyor") {
- if (firstConveyorLimits.hasConveyor || secondConveyorLimits.hasConveyor) {
- console.log("Conveyor can only connect to one other conveyor");
- return;
- }
- }
-
- // Check if trying to connect to an ArmBot when already connected to one
- if (secondPath?.type === "ArmBot" && firstConveyorLimits.hasArmBot) {
- console.log("Conveyor can only connect to one ArmBot");
- return;
- }
- if (firstPath?.type === "ArmBot" && secondConveyorLimits.hasArmBot) {
- console.log("Conveyor can only connect to one ArmBot");
- return;
- }
-
- // Check if trying to connect to a Vehicle when already connected to one
- if (secondPath?.type === "Vehicle" && firstConveyorLimits.hasVehicle) {
- console.log("Conveyor can only connect to one Vehicle");
- return;
- }
- if (firstPath?.type === "Vehicle" && secondConveyorLimits.hasVehicle) {
- console.log("Conveyor can only connect to one Vehicle");
- return;
- }
- }
-
- if (firstSelected) {
- // Check if trying to connect Vehicle to non-Conveyor
- if ((firstPath?.type === "Vehicle" && secondPath?.type !== "Conveyor") || (secondPath?.type === "Vehicle" && firstPath?.type !== "Conveyor")) {
- console.log("Vehicle can only connect to Conveyors");
- return;
- }
-
- // Prevent same-path connections
- if (firstSelected.modelUUID === modelUUID) {
- console.log("Cannot connect spheres on the same path.");
- return;
- }
-
- // Check if StaticMachine is involved in the connection
- if ((firstPath?.type === "StaticMachine" && secondPath?.type !== "ArmBot") || (secondPath?.type === "StaticMachine" && firstPath?.type !== "ArmBot")) {
- console.log("StaticMachine can only connect to ArmBot");
- return;
- }
-
- // Check if StaticMachine already has a connection
- if (firstPath?.type === "StaticMachine") {
- const staticConnections = firstPath.points.connections.targets.length;
- if (staticConnections >= 1) {
- console.log("StaticMachine can only have one connection");
- return;
- }
- }
- if (secondPath?.type === "StaticMachine") {
- const staticConnections = secondPath.points.connections.targets.length;
- if (staticConnections >= 1) {
- console.log("StaticMachine can only have one connection");
- return;
- }
- }
-
- // Check if ArmBot is involved
- if ((firstPath?.type === "ArmBot" && secondPath?.type === "StaticMachine") || (secondPath?.type === "ArmBot" && firstPath?.type === "StaticMachine")) {
- const armBotPath = firstPath?.type === "ArmBot" ? firstPath : secondPath;
- const staticPath = firstPath?.type === "StaticMachine" ? firstPath : secondPath;
-
- const armBotConnections = armBotPath.points.connections.targets || [];
- const alreadyConnectedToStatic = armBotConnections.some(
- (target) => {
- const targetPath = simulationStates.find((p) => p.modeluuid === target.modelUUID);
- return targetPath?.type === "StaticMachine";
- }
- );
-
- if (alreadyConnectedToStatic) {
- console.log("ArmBot can only connect to one StaticMachine");
- return;
- }
-
- const staticConnections = staticPath.points.connections.targets.length;
- if (staticConnections >= 1) {
- console.log("StaticMachine can only have one connection");
- return;
- }
- }
-
- // Prevent ArmBot ↔ ArmBot
- if (firstPath?.type === "ArmBot" && secondPath?.type === "ArmBot") {
- console.log("Cannot connect two ArmBots together");
- return;
- }
-
- // If one is ArmBot, ensure the other is StaticMachine or Conveyor
- if (firstPath?.type === "ArmBot" || secondPath?.type === "ArmBot") {
- const otherType = firstPath?.type === "ArmBot" ? secondPath?.type : firstPath?.type;
- if (otherType !== "StaticMachine" && otherType !== "Conveyor") {
- console.log("ArmBot can only connect to Conveyors or one StaticMachine");
- return;
- }
- }
-
- // At least one must be start/end point
- if (!firstSelected.isCorner && !isStartOrEnd) {
- console.log("At least one of the selected spheres must be a start or end point.");
- return;
- }
-
- // All checks passed - make the connection
- handleAddConnection(firstSelected.modelUUID, firstSelected.sphereUUID, modelUUID, sphereUUID);
- } else {
- // First selection - just store it
- setFirstSelected({ modelUUID, sphereUUID, position: worldPosition, isCorner: isStartOrEnd });
- setIsConnecting(true);
- }
- }
- }
- } else {
- // Clicked outside - cancel connection
- setFirstSelected(null);
- setCurrentLine(null);
- setIsConnecting(false);
- }
- };
-
- if (activeModule === "simulation" && !deleteTool) {
- canvasElement.addEventListener("mousedown", onMouseDown);
- canvasElement.addEventListener("mouseup", onMouseUp);
- canvasElement.addEventListener("mousemove", onMouseMove);
- canvasElement.addEventListener("contextmenu", onContextMenu);
- } else {
- setFirstSelected(null);
- setCurrentLine(null);
- setIsConnecting(false);
- }
-
- return () => {
- canvasElement.removeEventListener("mousedown", onMouseDown);
- canvasElement.removeEventListener("mouseup", onMouseUp);
- canvasElement.removeEventListener("mousemove", onMouseMove);
- canvasElement.removeEventListener("contextmenu", onContextMenu);
- };
- }, [camera, scene, raycaster, firstSelected, simulationStates, deleteTool]);
-
- useFrame(() => {
- Object.values(groupRefs.current).forEach((group) => {
- if (group) {
- const distance = new THREE.Vector3(...group.position.toArray()).distanceTo(camera.position);
- group.visible = distance <= renderDistance && !isPlaying;
- }
- });
- });
-
- useFrame(() => {
- if (firstSelected) {
- 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")
- );
-
- let point: THREE.Vector3 | null = null;
- let snappedSphere: { sphereUUID: string; position: THREE.Vector3; modelUUID: string; isCorner: boolean; } | null = null;
- let isInvalidConnection = false;
-
- if (intersects.length > 0) {
- point = intersects[0].point;
- if (point.y < 0.05) {
- point = new THREE.Vector3(point.x, 0.05, point.z);
- }
- }
-
- const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) => obj.object.name.includes("events-sphere"));
-
- if (sphereIntersects.length > 0) {
- const sphere = sphereIntersects[0].object;
- const sphereUUID = sphere.uuid;
- const spherePosition = new THREE.Vector3();
- sphere.getWorldPosition(spherePosition);
- const pathData = sphere.userData.path;
- const modelUUID = pathData.modeluuid;
-
- const firstPath = simulationStates.find((p) => p.modeluuid === firstSelected.modelUUID);
- const secondPath = simulationStates.find((p) => p.modeluuid === modelUUID);
- const isVehicleToVehicle = firstPath?.type === "Vehicle" && secondPath?.type === "Vehicle";
-
- // Inside the useFrame hook, where we check for snapped spheres:
- const isConnectable = (
- pathData.type === 'Vehicle' ||
- pathData.type === 'ArmBot' ||
- (pathData.points.length > 0 && (
- sphereUUID === pathData.points[0].uuid ||
- sphereUUID === pathData.points[pathData.points.length - 1].uuid ||
- (pathData.type === 'Conveyor' && firstPath?.type === 'ArmBot') // Allow ArmBot to connect to middle points
- ))
- ) &&
- !isVehicleToVehicle &&
- !(
- firstPath?.type === 'Conveyor' &&
- pathData.type === 'Conveyor' &&
- !firstSelected.isCorner
- );
-
- // Check for duplicate connection (regardless of path type)
- const isDuplicateConnection = simulationStates.some(path => {
- if (path.modeluuid === firstSelected.modelUUID) {
- if (path.type === 'Conveyor') {
- const point = path.points.find(p => p.uuid === firstSelected.sphereUUID);
- return point?.connections.targets.some(t =>
- t.modelUUID === modelUUID && t.pointUUID === sphereUUID
- );
- } else if (path.type === 'Vehicle') {
- return path.points.connections.targets.some(t =>
- t.modelUUID === modelUUID && t.pointUUID === sphereUUID
- );
- }
- }
- return false;
- });
-
- // For non-Vehicle paths, check if already connected
- const isNonVehicleAlreadyConnected = pathData.type !== 'Vehicle' &&
- simulationStates.some(path => {
- if (path.type === 'Conveyor') {
- return path.points.some(point =>
- point.uuid === sphereUUID &&
- point.connections.targets.length > 0
- );
- }
- return false;
- });
-
- // Check vehicle connection rules
- const isVehicleAtMaxConnections = pathData.type === 'Vehicle' &&
- pathData.points.connections.targets.length >= 1;
- const isVehicleConnectingToNonConveyor =
- (firstPath?.type === 'Vehicle' && secondPath?.type !== 'Conveyor') ||
- (secondPath?.type === 'Vehicle' && firstPath?.type !== 'Conveyor');
-
- // Check if StaticMachine is connecting to non-ArmBot
- const isStaticMachineToNonArmBot =
- (firstPath?.type === 'StaticMachine' && secondPath?.type !== 'ArmBot') ||
- (secondPath?.type === 'StaticMachine' && firstPath?.type !== 'ArmBot');
-
- // Check if StaticMachine already has a connection
- const isStaticMachineAtMaxConnections =
- (firstPath?.type === 'StaticMachine' && firstPath.points.connections.targets.length >= 1) ||
- (secondPath?.type === 'StaticMachine' && secondPath.points.connections.targets.length >= 1);
-
- // Check if ArmBot is connecting to StaticMachine
- const isArmBotToStaticMachine =
- (firstPath?.type === 'ArmBot' && secondPath?.type === 'StaticMachine') ||
- (secondPath?.type === 'ArmBot' && firstPath?.type === 'StaticMachine');
-
- // Prevent multiple StaticMachine connections to ArmBot
- let isArmBotAlreadyConnectedToStatic = false;
- if (isArmBotToStaticMachine) {
- const armBotPath = firstPath?.type === 'ArmBot' ? firstPath : secondPath;
- isArmBotAlreadyConnectedToStatic = armBotPath.points.connections.targets.some(target => {
- const targetPath = simulationStates.find(p => p.modeluuid === target.modelUUID);
- return targetPath?.type === 'StaticMachine';
- });
- }
-
- // Prevent ArmBot to ArmBot
- const isArmBotToArmBot = firstPath?.type === 'ArmBot' && secondPath?.type === 'ArmBot';
-
- // If ArmBot is involved, other must be Conveyor or StaticMachine
- const isArmBotToInvalidType = (firstPath?.type === 'ArmBot' || secondPath?.type === 'ArmBot') &&
- !(firstPath?.type === 'Conveyor' || firstPath?.type === 'StaticMachine' ||
- secondPath?.type === 'Conveyor' || secondPath?.type === 'StaticMachine');
-
- // NEW: Check conveyor connection limits
- let isConveyorAtMaxConnections = false;
- if (firstPath?.type === 'Conveyor' || secondPath?.type === 'Conveyor') {
- const conveyorPath = firstPath?.type === 'Conveyor' ? firstPath : secondPath;
- const otherPath = firstPath?.type === 'Conveyor' ? secondPath : firstPath;
-
- if (conveyorPath) {
- const conveyorPoint = Array.isArray(conveyorPath.points)
- ? conveyorPath.points.find((p: { uuid: string }) => p.uuid ===
- (firstPath?.type === 'Conveyor' ? firstSelected.sphereUUID : sphereUUID))
- : undefined;
-
- if (conveyorPoint) {
- const hasConveyor = conveyorPoint.connections.targets.some((t: { modelUUID: string }) => {
- const targetPath = simulationStates.find((p: { modeluuid: string }) => p.modeluuid === t.modelUUID);
- return targetPath?.type === 'Conveyor';
- });
- const hasArmBot = conveyorPoint.connections.targets.some((t: { modelUUID: string }) => {
- const targetPath = simulationStates.find((p: { modeluuid: string }) => p.modeluuid === t.modelUUID);
- return targetPath?.type === 'ArmBot';
- });
- const hasVehicle = conveyorPoint.connections.targets.some((t: { modelUUID: string }) => {
- const targetPath = simulationStates.find(p => p.modeluuid === t.modelUUID);
- return targetPath?.type === 'Vehicle';
- });
-
- if (otherPath?.type === 'Conveyor' && hasConveyor) {
- isConveyorAtMaxConnections = true;
- }
- if (otherPath?.type === 'ArmBot' && hasArmBot) {
- isConveyorAtMaxConnections = true;
- }
- if (otherPath?.type === 'Vehicle' && hasVehicle) {
- isConveyorAtMaxConnections = true;
- }
- }
- }
- }
-
- if (
- !isDuplicateConnection &&
- !isVehicleToVehicle &&
- !isNonVehicleAlreadyConnected &&
- !isVehicleAtMaxConnections &&
- !isVehicleConnectingToNonConveyor &&
- !isStaticMachineToNonArmBot &&
- !isStaticMachineAtMaxConnections &&
- !isArmBotToArmBot &&
- !isArmBotToInvalidType &&
- !isArmBotAlreadyConnectedToStatic &&
- !isConveyorAtMaxConnections && // NEW: Check conveyor limits
- firstSelected.sphereUUID !== sphereUUID &&
- firstSelected.modelUUID !== modelUUID &&
- (firstSelected.isCorner || isConnectable) &&
- !(firstPath?.type === 'Conveyor' &&
- pathData.type === 'Conveyor' &&
- !(firstSelected.isCorner && isConnectable))
- ) {
- snappedSphere = {
- sphereUUID,
- position: spherePosition,
- modelUUID,
- isCorner: isConnectable
- };
- } else {
- isInvalidConnection = true;
- }
- }
-
- if (snappedSphere) {
- point = snappedSphere.position;
- }
-
- if (point) {
- const distance = firstSelected.position.distanceTo(point);
- const heightFactor = Math.max(0.5, distance * 0.2);
- const midPoint = new THREE.Vector3(
- (firstSelected.position.x + point.x) / 2,
- Math.max(firstSelected.position.y, point.y) + heightFactor,
- (firstSelected.position.z + point.z) / 2
- );
-
- setCurrentLine({
- start: firstSelected.position,
- end: point,
- mid: midPoint,
- });
-
- if (sphereIntersects.length > 0) {
- setHelperLineColor(isInvalidConnection ? "red" : "#6cf542");
- } else {
- setHelperLineColor("yellow");
- }
- } else {
- setCurrentLine(null);
- setIsConnecting(false);
- }
- } else {
- setCurrentLine(null);
- setIsConnecting(false);
- }
- });
-
- const removeConnection = (connection1: { model: string; point: string }, connection2: { model: string; point: string }) => {
- const updatedStates = simulationStates.map((state) => {
-
- // Handle Conveyor (which has multiple points)
- if (state.type === "Conveyor") {
- const updatedConveyor: SimulationTypes.ConveyorEventsSchema = {
- ...state,
- points: state.points.map((point) => {
- // Check if this point is either connection1 or connection2
- if ((state.modeluuid === connection1.model && point.uuid === connection1.point) || (state.modeluuid === connection2.model && point.uuid === connection2.point)) {
- return {
- ...point,
- connections: {
- ...point.connections,
- targets: point.connections.targets.filter((target) => {
- // Remove the target that matches the other connection
- return !(
- (target.modelUUID === connection1.model &&
- target.pointUUID === connection1.point) ||
- (target.modelUUID === connection2.model &&
- target.pointUUID === connection2.point)
- );
- }),
- },
- };
- }
- return point;
- }),
- };
- return updatedConveyor;
- }
-
- // Handle Vehicle
- else if (state.type === "Vehicle") {
- if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) || (state.modeluuid === connection2.model && state.points.uuid === connection2.point)) {
- const updatedVehicle: SimulationTypes.VehicleEventsSchema = {
- ...state,
- points: {
- ...state.points,
- connections: {
- ...state.points.connections,
- targets: state.points.connections.targets.filter((target) => {
- return !(
- (target.modelUUID === connection1.model &&
- target.pointUUID === connection1.point) ||
- (target.modelUUID === connection2.model &&
- target.pointUUID === connection2.point)
- );
- }),
- },
- // Ensure all required Vehicle point properties are included
- speed: state.points.speed,
- actions: state.points.actions,
- },
- };
- return updatedVehicle;
- }
- }
-
- // Handle StaticMachine
- else if (state.type === "StaticMachine") {
- if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) || (state.modeluuid === connection2.model && state.points.uuid === connection2.point)) {
- const updatedStaticMachine: SimulationTypes.StaticMachineEventsSchema =
- {
- ...state,
- points: {
- ...state.points,
- connections: {
- ...state.points.connections,
- targets: state.points.connections.targets.filter((target) => {
- return !(
- (target.modelUUID === connection1.model &&
- target.pointUUID === connection1.point) ||
- (target.modelUUID === connection2.model &&
- target.pointUUID === connection2.point)
- );
- }),
- },
- // Ensure all required StaticMachine point properties are included
- actions: state.points.actions,
- triggers: state.points.triggers,
- },
- };
- return updatedStaticMachine;
- }
- }
-
- // Handle ArmBot
- else if (state.type === "ArmBot") {
- if ((state.modeluuid === connection1.model && state.points.uuid === connection1.point) || (state.modeluuid === connection2.model && state.points.uuid === connection2.point)) {
- const updatedArmBot: SimulationTypes.ArmBotEventsSchema = {
- ...state,
- points: {
- ...state.points,
- connections: {
- ...state.points.connections,
- targets: state.points.connections.targets.filter((target) => {
- return !(
- (target.modelUUID === connection1.model &&
- target.pointUUID === connection1.point) ||
- (target.modelUUID === connection2.model &&
- target.pointUUID === connection2.point)
- );
- }),
- },
- actions: {
- ...state.points.actions,
- processes:
- state.points.actions.processes?.filter((process) => {
- return !(
- process.startPoint === connection1.point ||
- process.endPoint === connection1.point ||
- process.startPoint === connection2.point ||
- process.endPoint === connection2.point
- );
- }) || [],
- },
- triggers: state.points.triggers,
- },
- };
- return updatedArmBot;
- }
- }
- return state;
- });
-
- const updatedPaths = updatedStates.filter(
- (state) =>
- state.modeluuid === connection1.model ||
- state.modeluuid === connection2.model
- );
-
- updateBackend(updatedPaths);
-
- setSimulationStates(updatedStates);
- };
-
- const removeConnections = (deletedModelUUIDs: string[]) => {
-
- const deletedPointUUIDs = new Set();
- simulationStates.forEach(state => {
- if (deletedModelUUIDs.includes(state.modeluuid)) {
- if (state.type === "Conveyor" && state.points) {
- state.points.forEach(point => {
- deletedPointUUIDs.add(point.uuid);
- });
- } else if (state.points && 'uuid' in state.points) {
- deletedPointUUIDs.add(state.points.uuid);
- }
- }
- });
-
- const updatedStates = simulationStates.map((state) => {
- // Handle Conveyor
- if (state.type === "Conveyor") {
- const updatedConveyor: SimulationTypes.ConveyorEventsSchema = {
- ...state,
- points: state.points.map((point) => {
- return {
- ...point,
- connections: {
- ...point.connections,
- targets: point.connections.targets.filter(
- (target) => !deletedModelUUIDs.includes(target.modelUUID)
- ),
- },
- };
- }),
- };
- return updatedConveyor;
- }
-
- // Handle Vehicle
- else if (state.type === "Vehicle") {
- const updatedVehicle: SimulationTypes.VehicleEventsSchema = {
- ...state,
- points: {
- ...state.points,
- connections: {
- ...state.points.connections,
- targets: state.points.connections.targets.filter(
- (target) => !deletedModelUUIDs.includes(target.modelUUID)
- ),
- },
- },
- };
- return updatedVehicle;
- }
-
- // Handle StaticMachine
- else if (state.type === "StaticMachine") {
- const updatedStaticMachine: SimulationTypes.StaticMachineEventsSchema =
- {
- ...state,
- points: {
- ...state.points,
- connections: {
- ...state.points.connections,
- targets: state.points.connections.targets.filter(
- (target) => !deletedModelUUIDs.includes(target.modelUUID)
- ),
- },
- },
- };
- return updatedStaticMachine;
- }
-
- // Handle ArmBot
- else if (state.type === "ArmBot") {
- const updatedArmBot: SimulationTypes.ArmBotEventsSchema = {
- ...state,
- points: {
- ...state.points,
- connections: {
- ...state.points.connections,
- targets: state.points.connections.targets.filter(
- (target: any) => !deletedModelUUIDs.includes(target.modelUUID)
- ),
- },
- actions: {
- ...state.points.actions,
- processes: state.points.actions.processes?.filter((process) => {
- // Check if trigger is from deleted model
- const matchedStates = simulationStates.filter((s) => deletedModelUUIDs.includes(s.modeluuid));
-
- if (matchedStates.length > 0) {
- if (matchedStates[0]?.type === "StaticMachine") {
- const trigPoints = matchedStates[0]?.points;
- if (process.triggerId === trigPoints?.triggers?.uuid) {
- return false;
- }
- } else if (matchedStates[0]?.type === "Conveyor") {
- const trigPoints = matchedStates[0]?.points;
- if (Array.isArray(trigPoints)) {
- const nonEmptyTriggers = trigPoints.filter((point) => point && point.triggers && point.triggers.length > 0);
- const allTriggerUUIDs = nonEmptyTriggers.flatMap((point) => point.triggers).map((trigger) => trigger.uuid);
- if (allTriggerUUIDs.includes(process.triggerId)) {
- return false;
- }
- }
- }
- }
-
- // Check if startPoint or endPoint is from deleted model
- if (deletedPointUUIDs.has(process.startPoint) || deletedPointUUIDs.has(process.endPoint)) {
- return false;
- }
-
- return true;
- }),
- },
- },
- };
- return updatedArmBot;
- }
-
- return state;
- });
-
- const filteredStates = updatedStates.filter((state) => !deletedModelUUIDs.includes(state.modeluuid));
-
- updateBackend(filteredStates);
- setSimulationStates(filteredStates);
- };
-
- return (
-
- {simulationStates.flatMap((path) => {
- if (path.type === "Conveyor") {
- return path.points.flatMap((point) =>
- point.connections.targets.map((target, index) => {
- const targetPath = simulationStates.find((p) => p.modeluuid === target.modelUUID);
- if (targetPath?.type !== "Conveyor" && targetPath?.type !== "ArmBot") 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 (
- (groupRefs.current[`${point.uuid}-${target.pointUUID}-${index}`] = el!)}
- start={fromWorldPosition.toArray()}
- end={toWorldPosition.toArray()}
- mid={midPoint.toArray()}
- color={deleteTool && hoveredLineKey === `${point.uuid}-${target.pointUUID}-${index}` ? "red" : targetPath?.type === "ArmBot" ? "#42a5f5" : "white"}
- lineWidth={4}
- dashed={deleteTool && hoveredLineKey === `${point.uuid}-${target.pointUUID}-${index}` ? false : true}
- dashSize={0.75}
- dashScale={20}
- onPointerOver={() => setHoveredLineKey(`${point.uuid}-${target.pointUUID}-${index}`)}
- onPointerOut={() => setHoveredLineKey(null)}
- onClick={() => {
- if (deleteTool) {
- const connection1 = {
- model: path.modeluuid,
- point: point.uuid,
- };
- const connection2 = {
- model: target.modelUUID,
- point: target.pointUUID,
- };
-
- removeConnection(connection1, connection2);
- }
- }}
- userData={target}
- />
- );
- }
- return null;
- })
- );
- }
-
- if (path.type === "Vehicle") {
- return path.points.connections.targets.map((target, index) => {
- const fromSphere = pathsGroupRef.current?.getObjectByProperty("uuid", path.points.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 (
- (groupRefs.current[`${path.points.uuid}-${target.pointUUID}-${index}`] = el!)}
- start={fromWorldPosition.toArray()}
- end={toWorldPosition.toArray()}
- mid={midPoint.toArray()}
- color={deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}` ? "red" : "orange"}
- lineWidth={4}
- dashed={deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}` ? false : true}
- dashSize={0.75}
- dashScale={20}
- onPointerOver={() => setHoveredLineKey(`${path.points.uuid}-${target.pointUUID}-${index}`)}
- onPointerOut={() => setHoveredLineKey(null)}
- onClick={() => {
- if (deleteTool) {
- const connection1 = {
- model: path.modeluuid,
- point: path.points.uuid,
- };
- const connection2 = {
- model: target.modelUUID,
- point: target.pointUUID,
- };
-
- removeConnection(connection1, connection2);
- }
- }}
- userData={target}
- />
- );
- }
- return null;
- });
- }
-
- if (path.type === "StaticMachine") {
- return path.points.connections.targets.map((target, index) => {
- const targetPath = simulationStates.find((p) => p.modeluuid === target.modelUUID);
- if (targetPath?.type !== "ArmBot") return null;
-
- const fromSphere = pathsGroupRef.current?.getObjectByProperty("uuid", path.points.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 (
- (groupRefs.current[`${path.points.uuid}-${target.pointUUID}-${index}`] = el!)}
- start={fromWorldPosition.toArray()}
- end={toWorldPosition.toArray()}
- mid={midPoint.toArray()}
- color={deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}` ? "red" : "#42a5f5"}
- lineWidth={4}
- dashed={deleteTool && hoveredLineKey === `${path.points.uuid}-${target.pointUUID}-${index}` ? false : true}
- dashSize={0.75}
- dashScale={20}
- onPointerOver={() => setHoveredLineKey(`${path.points.uuid}-${target.pointUUID}-${index}`)}
- onPointerOut={() => setHoveredLineKey(null)}
- onClick={() => {
- if (deleteTool) {
- const connection1 = {
- model: path.modeluuid,
- point: path.points.uuid,
- };
- const connection2 = {
- model: target.modelUUID,
- point: target.pointUUID,
- };
-
- removeConnection(connection1, connection2);
- }
- }}
- userData={target}
- />
- );
- }
- return null;
- });
- }
-
- return [];
- })}
-
- {currentLine && (
-
- )}
-
- );
-}
-
-export default PathConnector;
diff --git a/app/src/modules/simulation/path/pathCreation.tsx b/app/src/modules/simulation/path/pathCreation.tsx
deleted file mode 100644
index 1e9601d..0000000
--- a/app/src/modules/simulation/path/pathCreation.tsx
+++ /dev/null
@@ -1,415 +0,0 @@
-import * as THREE from "three";
-import * as SimulationTypes from "../../../types/simulationTypes";
-import { useRef, useState, useEffect, useMemo } from "react";
-import { Sphere, TransformControls } from "@react-three/drei";
-import {
- useEditingPoint,
- useEyeDropMode,
- useIsConnecting,
- usePreviewPosition,
- useRenderDistance,
- useSelectedActionSphere,
- useSelectedPath,
- useSimulationStates,
-} from "../../../store/store";
-import { useFrame, useThree } from "@react-three/fiber";
-import { useSubModuleStore } from "../../../store/useModuleStore";
-import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
-import { setEventApi } from "../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
-import { detectModifierKeys } from "../../../utils/shortcutkeys/detectModifierKeys";
-
-function PathCreation({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObject; }) {
- const { isPlaying } = usePlayButtonStore();
- const { renderDistance } = useRenderDistance();
- const { setSubModule } = useSubModuleStore();
- const { setSelectedActionSphere, selectedActionSphere } = useSelectedActionSphere();
- const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
- const { editingPoint, setEditingPoint } = useEditingPoint();
- const { previewPosition, setPreviewPosition } = usePreviewPosition();
- const { raycaster, camera, pointer, gl } = useThree();
- const { setSelectedPath } = useSelectedPath();
- const { simulationStates, setSimulationStates } = useSimulationStates();
- const { isConnecting } = useIsConnecting();
- const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
-
- const groupRefs = useRef<{ [key: string]: THREE.Group }>({});
- const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
- const isMovingRef = useRef(false);
- const transformRef = useRef(null);
- const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
-
- useEffect(() => {
- setTransformMode(null);
- const handleKeyDown = (e: KeyboardEvent) => {
- const keyCombination = detectModifierKeys(e);
- if (!selectedActionSphere) return;
- if (keyCombination === "G") {
- setTransformMode((prev) => (prev === "translate" ? null : "translate"));
- }
- if (keyCombination === "R") {
- setTransformMode((prev) => (prev === "rotate" ? null : "rotate"));
- }
- };
-
- window.addEventListener("keydown", handleKeyDown);
- return () => window.removeEventListener("keydown", handleKeyDown);
- }, [selectedActionSphere]);
-
- useFrame(() => {
- Object.values(groupRefs.current).forEach((group) => {
- if (group) {
- const distance = new THREE.Vector3(
- ...group.position.toArray()
- ).distanceTo(camera.position);
- group.visible = ((distance <= renderDistance) && !isPlaying);
- }
- });
- });
-
- useFrame(() => {
- if (eyeDropMode) {
- raycaster.setFromCamera(pointer, camera);
- const intersectionPoint = new THREE.Vector3();
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
-
- if (point) {
- setPreviewPosition({ x: point.x, y: point.z });
- }
- } else {
- setPreviewPosition(null);
- }
- });
-
- useEffect(() => {
- if (!camera) return;
- const canvasElement = gl.domElement;
- canvasElement.tabIndex = 0;
-
- const onPointerDown = () => {
- isMovingRef.current = false;
- };
-
- const onPointerMove = () => {
- isMovingRef.current = true;
- };
-
- const onPointerUp = (event: PointerEvent) => {
- if (
- !isMovingRef.current &&
- eyeDropMode &&
- event.button === 0 &&
- previewPosition
- ) {
- event.preventDefault();
- if (editingPoint) {
- handlePointUpdate(editingPoint, previewPosition.x, previewPosition.y);
- setEditingPoint(null);
- setEyeDropMode(false);
- }
- }
- };
-
- if (eyeDropMode) {
- canvasElement.addEventListener("pointerdown", onPointerDown);
- canvasElement.addEventListener("pointermove", onPointerMove);
- canvasElement.addEventListener("pointerup", onPointerUp);
- }
-
- return () => {
- canvasElement.removeEventListener("pointerdown", onPointerDown);
- canvasElement.removeEventListener("pointermove", onPointerMove);
- canvasElement.removeEventListener("pointerup", onPointerUp);
- };
- }, [eyeDropMode, editingPoint, previewPosition]);
-
- const updateBackend = async (updatedPath: SimulationTypes.VehicleEventsSchema | undefined) => {
- if (!updatedPath) return;
- const email = localStorage.getItem("email");
- const organization = email ? email.split("@")[1].split(".")[0] : "";
- await setEventApi(
- organization,
- updatedPath.modeluuid,
- { type: "Vehicle", points: updatedPath.points }
- );
- }
-
- const handlePointUpdate = (pointType: "start" | "end", x: number, z: number) => {
- if (!selectedActionSphere?.points?.uuid) return;
- const updatedPaths = simulationStates.map((path) => {
-
- if (path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid) {
- return {
- ...path,
- points: {
- ...path.points,
- actions: {
- ...path.points.actions,
- [pointType]: { ...path.points.actions[pointType], x: x, y: z, },
- },
- },
- };
- }
- return path;
- });
-
- const updatedPath = updatedPaths.find((path): path is SimulationTypes.VehicleEventsSchema => path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid);
- updateBackend(updatedPath);
-
- setSimulationStates(updatedPaths);
- };
-
- return (
-
- {simulationStates.map((path) => {
- if (path.type === "Conveyor") {
- const points = path.points.map(
- (point) => new THREE.Vector3(...point.position)
- );
-
- return (
- (groupRefs.current[path.modeluuid] = el!)}
- position={path.position}
- rotation={path.rotation}
- onClick={(e) => {
- if (isConnecting || eyeDropMode) return;
- e.stopPropagation();
- setSelectedPath({
- path,
- group: groupRefs.current[path.modeluuid],
- });
- setSelectedActionSphere(null);
- setTransformMode(null);
- setSubModule("mechanics");
- }}
- onPointerMissed={() => {
- if (eyeDropMode) return;
- setSelectedPath(null);
- setSubModule("properties");
- }}
- >
- {path.points.map((point, index) => (
- (sphereRefs.current[point.uuid] = el!)}
- onClick={(e) => {
- if (isConnecting || eyeDropMode) return;
- e.stopPropagation();
- setSelectedActionSphere({
- path,
- points: sphereRefs.current[point.uuid],
- });
- setSubModule("mechanics");
- setSelectedPath(null);
- }}
- userData={{ points, path }}
- onPointerMissed={() => {
- if (eyeDropMode) return;
- 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.position}
- rotation={path.rotation}
- onClick={(e) => {
- if (isConnecting || eyeDropMode) return;
- e.stopPropagation();
- setSelectedPath({
- path,
- group: groupRefs.current[path.modeluuid],
- });
- setSelectedActionSphere(null);
- setTransformMode(null);
- setSubModule("mechanics");
- }}
- onPointerMissed={() => {
- if (eyeDropMode) return;
- setSelectedPath(null);
- setSubModule("properties");
- }}
- >
- (sphereRefs.current[path.points.uuid] = el!)}
- onClick={(e) => {
- if (isConnecting || eyeDropMode) return;
- e.stopPropagation();
- setSelectedActionSphere({
- path,
- points: sphereRefs.current[path.points.uuid],
- });
- setSubModule("mechanics");
- setSelectedPath(null);
- }}
- userData={{ points: path.points, path }}
- onPointerMissed={() => {
- if (eyeDropMode) return;
- setSubModule("properties");
- setSelectedActionSphere(null);
- }}
- >
-
-
-
- );
- } else if (path.type === "StaticMachine") {
- return (
- (groupRefs.current[path.modeluuid] = el!)}
- position={path.position}
- rotation={path.rotation}
- onClick={(e) => {
- if (isConnecting || eyeDropMode) return;
- e.stopPropagation();
- setSelectedPath({
- path,
- group: groupRefs.current[path.modeluuid],
- });
- setSelectedActionSphere(null);
- setTransformMode(null);
- setSubModule("mechanics");
- }}
- onPointerMissed={() => {
- if (eyeDropMode) return;
- setSelectedPath(null);
- setSubModule("properties");
- }}
- >
- (sphereRefs.current[path.points.uuid] = el!)}
- onClick={(e) => {
- if (isConnecting || eyeDropMode) return;
- e.stopPropagation();
- setSelectedActionSphere({
- path,
- points: sphereRefs.current[path.points.uuid],
- });
- setSubModule("mechanics");
- setSelectedPath(null);
- }}
- userData={{ points: path.points, path }}
- onPointerMissed={() => {
- if (eyeDropMode) return;
- setSubModule("properties");
- setSelectedActionSphere(null);
- }}
- >
-
-
-
- );
- } else if (path.type === "ArmBot") {
- return (
- (groupRefs.current[path.modeluuid] = el!)}
- position={path.position}
- rotation={path.rotation}
- onClick={(e) => {
- if (isConnecting || eyeDropMode) return;
- e.stopPropagation();
- setSelectedPath({
- path,
- group: groupRefs.current[path.modeluuid],
- });
- setSelectedActionSphere(null);
- setTransformMode(null);
- setSubModule("mechanics");
- }}
- onPointerMissed={() => {
- if (eyeDropMode) return;
- setSelectedPath(null);
- setSubModule("properties");
- }}
- >
- (sphereRefs.current[path.points.uuid] = el!)}
- onClick={(e) => {
- if (isConnecting || eyeDropMode) return;
- e.stopPropagation();
- setSelectedActionSphere({
- path,
- points: sphereRefs.current[path.points.uuid],
- });
- setSubModule("mechanics");
- setSelectedPath(null);
- }}
- userData={{ points: path.points, path }}
- onPointerMissed={() => {
- if (eyeDropMode) return;
- setSubModule("properties");
- setSelectedActionSphere(null);
- }}
- >
-
-
-
- );
- }
- return null;
- })}
-
- {selectedActionSphere && transformMode && (
-
- )}
-
- );
-}
-
-export default PathCreation;
diff --git a/app/src/modules/simulation/process/processAnimator.tsx b/app/src/modules/simulation/process/processAnimator.tsx
deleted file mode 100644
index 2cd574f..0000000
--- a/app/src/modules/simulation/process/processAnimator.tsx
+++ /dev/null
@@ -1,611 +0,0 @@
-import React, { useRef, useEffect, useMemo, useCallback } from "react";
-import { useLoader, useFrame } from "@react-three/fiber";
-import { GLTFLoader } from "three-stdlib";
-import * as THREE from "three";
-import { GLTF } from "three-stdlib";
-import crate from "../../../assets/gltf-glb/crate_box.glb";
-
-import { useProcessAnimation } from "./useProcessAnimations";
-import ProcessObject from "./processObject";
-import { ProcessData } from "./types";
-
-interface ArmBotState {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- status: string;
- material: string;
- triggerId: string;
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- actions: {
- uuid: string;
- name: string;
- speed: number;
- processes: { triggerId: string; startPoint: string; endPoint: string }[];
- };
- isActive?: boolean;
-}
-interface ProcessContainerProps {
- processes: ProcessData[];
- setProcesses: React.Dispatch>;
- agvRef: any;
- MaterialRef: any;
- armBots: ArmBotState[];
- setArmBots: React.Dispatch>;
-}
-
-const ProcessAnimator: React.FC = ({
- processes,
- setProcesses,
- agvRef,
- MaterialRef,
- armBots,
- setArmBots,
-}) => {
- const gltf = useLoader(GLTFLoader, crate) as GLTF;
- const groupRef = useRef(null);
- const tempStackedObjectsRef = useRef>({});
-
- const {
- animationStates,
- setAnimationStates,
- clockRef,
- elapsedBeforePauseRef,
- speedRef,
- debugRef,
- findSpawnPoint,
- createSpawnedObject,
- handlePointActions,
- hasNonInheritActions,
- getPointDataForAnimationIndex,
- processes: processedProcesses,
- checkAndCountTriggers,
- } = useProcessAnimation(processes, setProcesses, agvRef, armBots, setArmBots);
-
- const baseMaterials = useMemo(
- () => ({
- Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
- Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
- Default: new THREE.MeshStandardMaterial(),
- }),
- []
- );
-
- useEffect(() => {
- // Update material references for all spawned objects
- Object.entries(animationStates).forEach(([processId, processState]) => {
- Object.keys(processState.spawnedObjects).forEach((objectId) => {
- const entry = { processId, objectId };
-
- const materialType =
- processState.spawnedObjects[objectId]?.currentMaterialType;
-
- if (!materialType) {
- return;
- }
-
- const matRefArray = MaterialRef.current;
-
- // Find existing material group
- const existing = matRefArray.find(
- (entryGroup: { material: string; objects: any[] }) =>
- entryGroup.material === materialType
- );
-
- if (existing) {
- // Check if this processId + objectId already exists
- const alreadyExists = existing.objects.some(
- (o: any) =>
- o.processId === entry.processId && o.objectId === entry.objectId
- );
-
- if (!alreadyExists) {
- existing.objects.push(entry);
- }
- } else {
- // Create new group for this material type
- matRefArray.push({
- material: materialType,
- objects: [entry],
- });
- }
- });
- });
- }, [animationStates, MaterialRef, agvRef]);
-
- // In processAnimator.tsx - only the relevant spawn logic part that needs fixes
-
- // Add this function to ProcessAnimator component
- const isConnectedToActiveArmBot = useCallback(
- (processId: any) => {
- // Check if any active armbot is connected to this process
- return armBots.some((armbot) => {
- if (!armbot.isActive) return false;
-
- // Check if this armbot is connected to the process
- return armbot.connections?.targets?.some((connection) => {
- // Find the process that owns this modelUUID
- const connectedProcess = processes.find((p) =>
- p.paths?.some((path) => path.modeluuid === connection.modelUUID)
- );
- return connectedProcess?.id === processId;
- });
- });
- },
- [armBots, processes]
- );
-
- // First useFrame for spawn logic
- useFrame(() => {
- // Spawn logic frame
- const currentTime =
- clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
-
- setAnimationStates((prev) => {
- const newStates = { ...prev };
-
- processedProcesses.forEach((process) => {
- const processState = newStates[process.id];
- if (!processState) return;
-
- // Check connection status
- const isConnected = isConnectedToActiveArmBot(process.id);
-
- if (processState.isProcessDelaying) {
- // Existing delay handling logic...
- return;
- }
-
- if (isConnected) {
- newStates[process.id] = {
- ...processState,
- nextSpawnTime: Infinity, // Prevent future spawns
- };
- return;
- }
-
- const spawnPoint = findSpawnPoint(process);
- if (!spawnPoint || !spawnPoint.actions) {
- // console.log(
- // `Process ${process.id} has no valid spawn point or actions`
- // );
- return;
- }
-
- const spawnAction = spawnPoint.actions.find(
- (a) => a.isUsed && a.type === "Spawn"
- );
- if (!spawnAction) {
- return;
- }
-
- const spawnInterval =
- typeof spawnAction.spawnInterval === "number"
- ? spawnAction.spawnInterval
- : parseFloat(spawnAction.spawnInterval || "0") || 0;
-
- // Check if this is a zero interval spawn and we already spawned an object
- if (
- spawnInterval === 0 &&
- processState.hasSpawnedZeroIntervalObject === true
- ) {
- return; // Don't spawn more objects for zero interval
- }
-
- const effectiveSpawnInterval = spawnInterval / speedRef.current;
-
- if (currentTime >= processState.nextSpawnTime) {
- const objectId = `obj-${process.id}-${processState.objectIdCounter}`;
- const newObject = createSpawnedObject(
- process,
- currentTime,
- spawnAction.material || "Default",
- spawnPoint,
- baseMaterials
- );
-
- // Initialize state properly to ensure animation
- newObject.state = {
- ...newObject.state,
- isAnimating: true,
- isDelaying: false,
- delayComplete: false,
- progress: 0.005, // Start with tiny progress to ensure animation begins
- };
-
- // Update state with the new object and flag for zero interval
- newStates[process.id] = {
- ...processState,
- spawnedObjects: {
- ...processState.spawnedObjects,
- [objectId]: newObject,
- },
- objectIdCounter: processState.objectIdCounter + 1,
- nextSpawnTime: currentTime + effectiveSpawnInterval,
- // Mark that we've spawned an object for zero interval case
- hasSpawnedZeroIntervalObject:
- spawnInterval === 0
- ? true
- : processState.hasSpawnedZeroIntervalObject,
- };
- }
- });
-
- return newStates;
- });
- });
-
- // Second useFrame for animation logic
- useFrame((_, delta) => {
- // Animation logic frame
- const currentTime =
- clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
-
- setAnimationStates((prev) => {
- const newStates = { ...prev };
-
- processedProcesses.forEach((process) => {
- const processState = newStates[process.id];
- if (!processState) {
- return;
- }
-
- // Check connection status with debugging
- const isConnected = isConnectedToActiveArmBot(process.id);
- // console.log(
- // `Process ${process.id} animation - connected:`,
- // isConnected
- // );
-
- if (isConnected) {
- // Stop all animations when connected to active arm bot
- newStates[process.id] = {
- ...processState,
- spawnedObjects: Object.entries(processState.spawnedObjects).reduce(
- (acc, [id, obj]) => ({
- ...acc,
- [id]: {
- ...obj,
- state: {
- ...obj.state,
- isAnimating: false, // Stop animation
- isDelaying: false, // Clear delays
- delayComplete: false, // Reset delays
- progress: 0, // Reset progress
- },
- },
- }),
- {}
- ),
- };
- return;
- }
-
- // Process delay handling
- if (processState.isProcessDelaying) {
- const effectiveDelayTime =
- processState.processDelayDuration / speedRef.current;
-
- if (
- currentTime - processState.processDelayStartTime >=
- effectiveDelayTime
- ) {
- // console.log(
- // `Process ${process.id} delay completed, resuming animation`
- // );
- newStates[process.id] = {
- ...processState,
- isProcessDelaying: false,
- spawnedObjects: Object.entries(
- processState.spawnedObjects
- ).reduce(
- (acc, [id, obj]) => ({
- ...acc,
- [id]: {
- ...obj,
- state: {
- ...obj.state,
- isDelaying: false,
- delayComplete: true,
- isAnimating: true,
- progress:
- obj.state.progress === 0 ? 0.005 : obj.state.progress,
- },
- },
- }),
- {}
- ),
- };
- return;
- } else {
- return;
- }
- }
-
- // Ensure we have a valid path to follow
- const path =
- process.animationPath?.map((p) => new THREE.Vector3(p.x, p.y, p.z)) ||
- [];
-
- if (path.length < 2) {
- // console.log(
- // `Process ${process.id} has insufficient path points: ${path.length}`
- // );
- return;
- }
-
- const updatedObjects = { ...processState.spawnedObjects };
- let animationOccurring = false; // Track if any animation is happening
-
- Object.entries(processState.spawnedObjects).forEach(
- ([objectId, obj]) => {
- if (!obj.visible) {
- return;
- }
-
- const currentRef = gltf?.scene ? obj.ref.current : obj.ref.current;
- if (!currentRef) {
- // console.log(
- // `No reference for object ${objectId}, skipping animation`
- // );
- return;
- }
-
- // Initialize position for new objects
- if (
- obj.position &&
- obj.state.currentIndex === 0 &&
- obj.state.progress === 0
- ) {
- currentRef.position.copy(obj.position);
- }
-
- const stateRef = obj.state;
-
- // Ensure animation state is properly set for objects
- if (!stateRef.isAnimating && !stateRef.isDelaying && !isConnected) {
- stateRef.isAnimating = true;
- stateRef.progress =
- stateRef.progress > 0 ? stateRef.progress : 0.005;
- }
-
- // Handle delay logic
- if (stateRef.isDelaying) {
- const effectiveDelayTime =
- stateRef.currentDelayDuration / speedRef.current;
-
- if (currentTime - stateRef.delayStartTime >= effectiveDelayTime) {
- // console.log(
- // `Delay complete for object ${objectId}, resuming animation`
- // );
- stateRef.isDelaying = false;
- stateRef.delayComplete = true;
- stateRef.isAnimating = true;
-
- if (stateRef.progress === 0) {
- stateRef.progress = 0.005;
- }
-
- const nextPointIdx = stateRef.currentIndex + 1;
- if (nextPointIdx < path.length) {
- const slightProgress = Math.max(stateRef.progress, 0.005);
- currentRef.position.lerpVectors(
- path[stateRef.currentIndex],
- nextPointIdx < path.length
- ? path[nextPointIdx]
- : path[stateRef.currentIndex],
- slightProgress
- );
- }
- } else {
- updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
- return;
- }
- }
-
- // Skip non-animating objects
- if (!stateRef.isAnimating) {
- // console.log(
- // `Object ${objectId} not animating, skipping animation updates`
- // );
- return;
- }
-
- animationOccurring = true; // Mark that animation is happening
-
- // Handle point actions
- const currentPointData = getPointDataForAnimationIndex(
- process,
- stateRef.currentIndex
- );
-
- // Handle point actions when first arriving at point
- if (stateRef.progress === 0 && currentPointData?.actions) {
- const shouldStop = handlePointActions(
- process.id,
- objectId,
- currentPointData.actions,
- currentTime,
- processedProcesses,
- baseMaterials
- );
- if (shouldStop) {
- updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
- return;
- }
- }
-
- const nextPointIdx = stateRef.currentIndex + 1;
- const isLastPoint = nextPointIdx >= path.length;
-
- // Handle objects at the last point
- if (isLastPoint) {
- const isAgvPicking = agvRef.current.some(
- (agv: any) =>
- agv.processId === process.id && agv.status === "picking"
- );
-
- const shouldHide =
- !currentPointData?.actions ||
- !hasNonInheritActions(currentPointData.actions);
-
- if (shouldHide) {
- if (isAgvPicking) {
- // console.log(
- // `AGV picking at last point for object ${objectId}, hiding object`
- // );
- updatedObjects[objectId] = {
- ...obj,
- visible: false,
- state: {
- ...stateRef,
- isAnimating: false,
- },
- };
- } else {
- tempStackedObjectsRef.current[objectId] = true;
-
- updatedObjects[objectId] = {
- ...obj,
- visible: true,
- state: {
- ...stateRef,
- isAnimating: true,
- },
- };
- }
-
- return;
- }
- }
-
- // Handle stacked objects when AGV picks
- if (tempStackedObjectsRef.current[objectId]) {
- const isAgvPicking = agvRef.current.some(
- (agv: any) =>
- agv.processId === process.id && agv.status === "picking"
- );
-
- if (isAgvPicking) {
- delete tempStackedObjectsRef.current[objectId];
-
- updatedObjects[objectId] = {
- ...obj,
- visible: false,
- state: {
- ...stateRef,
- isAnimating: false,
- },
- };
-
- return;
- }
- }
-
- // Handle normal animation progress for objects not at last point
- if (!isLastPoint) {
- const nextPoint = path[nextPointIdx];
- const distance =
- path[stateRef.currentIndex].distanceTo(nextPoint);
- const effectiveSpeed = stateRef.speed * speedRef.current;
- const movement = effectiveSpeed * delta;
-
- // Ensure progress is always moving forward
- if (stateRef.delayComplete && stateRef.progress < 0.01) {
- stateRef.progress = 0.05;
- stateRef.delayComplete = false;
- // console.log(
- // `Boosting progress for object ${objectId} after delay`
- // );
- } else {
- stateRef.progress += movement / distance;
- // console.log(
- // `Object ${objectId} progress: ${stateRef.progress.toFixed(3)}`
- // );
- }
-
- // Handle point transition
- if (stateRef.progress >= 1) {
- stateRef.currentIndex = nextPointIdx;
- stateRef.progress = 0;
- currentRef.position.copy(nextPoint);
-
- // TRIGGER CHECK - When object arrives at new point
- checkAndCountTriggers(
- process.id,
- objectId,
- stateRef.currentIndex, // The new point index
- processedProcesses,
- currentTime
- );
-
- const newPointData = getPointDataForAnimationIndex(
- process,
- stateRef.currentIndex
- );
-
- // No action needed with newPointData here - will be handled in next frame
- } else {
- // Update position with lerp
- currentRef.position.lerpVectors(
- path[stateRef.currentIndex],
- nextPoint,
- stateRef.progress
- );
- }
- }
-
- updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
- }
- );
-
- // Log if no animation is occurring when it should
- if (!animationOccurring && !isConnected) {
- // console.log(
- // `Warning: No animation occurring for process ${process.id} despite not being connected`
- // );
- }
-
- newStates[process.id] = {
- ...processState,
- spawnedObjects: updatedObjects,
- };
- });
-
- return newStates;
- });
- });
-
- if (!processedProcesses || processedProcesses.length === 0) {
- return null;
- }
-
- return (
-
- {Object.entries(animationStates).flatMap(([processId, processState]) =>
- Object.entries(processState.spawnedObjects)
- .filter(([_, obj]) => obj.visible)
- .map(([objectId, obj]) => {
- const process = processedProcesses.find((p) => p.id === processId);
-
- const renderAs = process?.renderAs || "custom";
-
- return (
-
- );
- })
- )}
-
- );
-};
-
-export default ProcessAnimator;
diff --git a/app/src/modules/simulation/process/processContainer.tsx b/app/src/modules/simulation/process/processContainer.tsx
deleted file mode 100644
index 0bcdb13..0000000
--- a/app/src/modules/simulation/process/processContainer.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import React, { useState } from "react";
-import ProcessCreator from "./processCreator";
-import ProcessAnimator from "./processAnimator";
-
-interface ArmBotState {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- status: string;
- material: string;
- triggerId: string;
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
- isActive?: boolean;
-}
-
-interface ProcessContainerProps {
- processes: any[];
- setProcesses: React.Dispatch>;
- agvRef: any;
- MaterialRef: any;
- armBots: ArmBotState[];
- setArmBots: React.Dispatch>;
-}
-
-const ProcessContainer: React.FC = ({
- processes,
- setProcesses,
- agvRef,
- MaterialRef,
- armBots,
- setArmBots
-}) => {
- return (
- <>
-
-
- >
- );
-};
-
-export default ProcessContainer;
diff --git a/app/src/modules/simulation/process/processCreator.tsx b/app/src/modules/simulation/process/processCreator.tsx
deleted file mode 100644
index 0a486c9..0000000
--- a/app/src/modules/simulation/process/processCreator.tsx
+++ /dev/null
@@ -1,492 +0,0 @@
-import React, {
- useEffect,
- useMemo,
- useState,
- useCallback,
- useRef,
-} from "react";
-import { useSimulationStates } from "../../../store/store";
-import * as THREE from "three";
-import { useThree } from "@react-three/fiber";
-import {
- ArmBotEventsSchema,
- ConveyorEventsSchema,
- VehicleEventsSchema,
-} from "../../../types/simulationTypes";
-import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
-
-// Type definitions
-export interface PointAction {
- uuid: string;
- name: string;
- type: string;
- material: string;
- delay: number | string;
- spawnInterval: string | number;
- isUsed: boolean;
-}
-
-export interface PointTrigger {
- uuid: string;
- bufferTime: number;
- name: string;
- type: string;
- isUsed: boolean;
-}
-
-// Update the connections type in your interfaces
-export interface PathPoint {
- uuid: string;
- position: [number, number, number];
- actions: PointAction[];
- triggers: PointTrigger[];
- connections: {
- targets: Array<{ modelUUID: string; pointUUID?: string }>;
- };
-}
-
-export interface SimulationPath {
- type: string;
- modeluuid: string;
- points: PathPoint[];
- pathPosition: [number, number, number];
- speed?: number;
- isActive: boolean;
-}
-export interface ArmBot {
- type: string;
- modeluuid: string;
- points: PathPoint[];
- pathPosition: [number, number, number];
- speed?: number;
- isActive: boolean;
-}
-
-export interface Process {
- id: string;
- paths: SimulationPath[];
- animationPath: THREE.Vector3[];
- pointActions: PointAction[][];
- pointTriggers: PointTrigger[][];
- speed: number;
- isActive: boolean;
-}
-
-interface ProcessCreatorProps {
- onProcessesCreated: (processes: Process[]) => void;
-}
-
-// Convert event schemas to SimulationPath
-function convertToSimulationPath(
- path: ConveyorEventsSchema | VehicleEventsSchema | ArmBotEventsSchema
-): SimulationPath {
- const { modeluuid } = path;
-
- // Normalized action handler
- const normalizeAction = (action: any): PointAction => {
- return { ...action }; // Return exact copy with no modifications
- };
-
- // Normalized trigger handler
- const normalizeTrigger = (trigger: any): PointTrigger => {
- return { ...trigger }; // Return exact copy with no modifications
- };
-
- if (path.type === "Conveyor") {
- return {
- type: path.type,
- modeluuid,
- points: path.points.map((point) => ({
- uuid: point.uuid,
- position: point.position,
- actions: Array.isArray(point.actions)
- ? point.actions.map(normalizeAction)
- : point.actions
- ? [normalizeAction(point.actions)]
- : [],
- triggers: Array.isArray(point.triggers)
- ? point.triggers.map(normalizeTrigger)
- : point.triggers
- ? [normalizeTrigger(point.triggers)]
- : [],
- connections: {
- targets: point.connections.targets.map((target) => ({
- modelUUID: target.modelUUID,
- })),
- },
- })),
- pathPosition: path.position,
- speed:
- typeof path.speed === "string"
- ? parseFloat(path.speed) || 1
- : path.speed || 1,
- isActive: false, // Added missing property
- };
- } else if (path.type === "ArmBot") {
- return {
- type: path.type,
- modeluuid,
- points: [
- {
- uuid: path.points.uuid,
- position: path.points.position,
- actions: Array.isArray(path.points.actions)
- ? path.points.actions.map(normalizeAction)
- : path.points.actions
- ? [normalizeAction(path.points.actions)]
- : [],
- triggers: Array.isArray(path.points.triggers)
- ? path.points.triggers.map(normalizeTrigger)
- : path.points.triggers
- ? [normalizeTrigger(path.points.triggers)]
- : [],
- connections: {
- targets: path.points.connections.targets.map((target) => ({
- modelUUID: target.modelUUID,
- pointUUID: target.pointUUID, // Include if available
- })),
- },
- },
- ],
- pathPosition: path.position,
- speed: path.points.actions?.speed || 1,
- isActive: false,
- };
- } else {
- // For vehicle paths, handle the case where triggers might not exist
- return {
- type: path.type,
- modeluuid,
- points: [
- {
- uuid: path.points.uuid,
- position: path.points.position,
- actions: Array.isArray(path.points.actions)
- ? path.points.actions.map(normalizeAction)
- : path.points.actions
- ? [normalizeAction(path.points.actions)]
- : [],
- triggers: [],
- connections: {
- targets: path.points.connections.targets.map((target) => ({
- modelUUID: target.modelUUID,
- })),
- },
- },
- ],
- pathPosition: path.position,
- speed: path.points.speed || 1,
- isActive: false,
- };
- }
-}
-
-// Helper function to create an empty process
-const createEmptyProcess = (): Process => ({
- id: `process-${Math.random().toString(36).substring(2, 11)}`,
- paths: [],
- animationPath: [],
- pointActions: [],
- pointTriggers: [], // Added point triggers array
- speed: 1,
- isActive: false,
-});
-
-// Enhanced connection checking function
-function shouldReverseNextPath(
- currentPath: SimulationPath,
- nextPath: SimulationPath
-): boolean {
- if (nextPath.points.length !== 3) return false;
-
- const currentLastPoint = currentPath.points[currentPath.points.length - 1];
- const nextFirstPoint = nextPath.points[0];
- const nextLastPoint = nextPath.points[nextPath.points.length - 1];
-
- // Check if current last connects to next last (requires reversal)
- const connectsToLast = currentLastPoint.connections.targets.some(
- (target) =>
- target.modelUUID === nextPath.modeluuid &&
- nextLastPoint.connections.targets.some(
- (t) => t.modelUUID === currentPath.modeluuid
- )
- );
-
- // Check if current last connects to next first (no reversal needed)
- const connectsToFirst = currentLastPoint.connections.targets.some(
- (target) =>
- target.modelUUID === nextPath.modeluuid &&
- nextFirstPoint.connections.targets.some(
- (t) => t.modelUUID === currentPath.modeluuid
- )
- );
-
- // Only reverse if connected to last point and not to first point
- return connectsToLast && !connectsToFirst;
-}
-
-// Check if a point has a spawn action
-function hasSpawnAction(point: PathPoint): boolean {
- return point.actions.some((action) => action.type.toLowerCase() === "spawn");
-}
-
-// Ensure spawn point is always at the beginning of the path
-function ensureSpawnPointIsFirst(path: SimulationPath): SimulationPath {
- if (path.points.length !== 3) return path;
-
- // If the third point has spawn action and first doesn't, reverse the array
- if (hasSpawnAction(path.points[2]) && !hasSpawnAction(path.points[0])) {
- return {
- ...path,
- points: [...path.points].reverse(),
- };
- }
-
- return path;
-}
-
-// Updated path adjustment function
-function adjustPathPointsOrder(paths: SimulationPath[]): SimulationPath[] {
- if (paths.length < 1) return paths;
-
- const adjustedPaths = [...paths];
-
- // First ensure all paths have spawn points at the beginning
- for (let i = 0; i < adjustedPaths.length; i++) {
- adjustedPaths[i] = ensureSpawnPointIsFirst(adjustedPaths[i]);
- }
-
- // Then handle connections between paths
- for (let i = 0; i < adjustedPaths.length - 1; i++) {
- const currentPath = adjustedPaths[i];
- const nextPath = adjustedPaths[i + 1];
-
- if (shouldReverseNextPath(currentPath, nextPath)) {
- const reversedPoints = [
- nextPath.points[2],
- nextPath.points[1],
- nextPath.points[0],
- ];
-
- adjustedPaths[i + 1] = {
- ...nextPath,
- points: reversedPoints,
- };
- }
- }
-
- return adjustedPaths;
-}
-
-// Main hook for process creation
-export function useProcessCreation() {
- const { scene } = useThree();
- const [processes, setProcesses] = useState([]);
-
- const hasSpawnAction = useCallback((path: SimulationPath): boolean => {
- if (path.type !== "Conveyor") return false;
- return path.points.some((point) =>
- point.actions.some((action) => action.type.toLowerCase() === "spawn")
- );
- }, []);
-
- const createProcess = useCallback(
- (paths: SimulationPath[]): Process => {
- if (!paths || paths.length === 0) {
- return createEmptyProcess();
- }
-
- const animationPath: THREE.Vector3[] = [];
- const pointActions: PointAction[][] = [];
- const pointTriggers: PointTrigger[][] = []; // Added point triggers collection
- const processSpeed = paths[0]?.speed || 1;
-
- for (const path of paths) {
- for (const point of path.points) {
- if (path.type === "Conveyor") {
- const obj = scene.getObjectByProperty("uuid", point.uuid);
- if (!obj) {
- console.warn(`Object with UUID ${point.uuid} not found in scene`);
- continue;
- }
-
- const position = obj.getWorldPosition(new THREE.Vector3());
- animationPath.push(position.clone());
- pointActions.push(point.actions);
- pointTriggers.push(point.triggers); // Collect triggers for each point
- }
- }
- }
-
- return {
- id: `process-${Math.random().toString(36).substring(2, 11)}`,
- paths,
- animationPath,
- pointActions,
- pointTriggers,
- speed: processSpeed,
- isActive: false,
- };
- },
- [scene]
- );
-
- const getAllConnectedPaths = useCallback(
- (
- initialPath: SimulationPath,
- allPaths: SimulationPath[],
- visited: Set = new Set()
- ): SimulationPath[] => {
- const connectedPaths: SimulationPath[] = [];
- const queue: SimulationPath[] = [initialPath];
- visited.add(initialPath.modeluuid);
-
- const pathMap = new Map();
- allPaths.forEach((path) => pathMap.set(path.modeluuid, path));
-
- while (queue.length > 0) {
- const currentPath = queue.shift()!;
- connectedPaths.push(currentPath);
-
- // Process outgoing connections
- for (const point of currentPath.points) {
- for (const target of point.connections.targets) {
- if (!visited.has(target.modelUUID)) {
- const targetPath = pathMap.get(target.modelUUID);
- if (targetPath) {
- visited.add(target.modelUUID);
- queue.push(targetPath);
- }
- }
- }
- }
-
- // Process incoming connections
- for (const [uuid, path] of pathMap) {
- if (!visited.has(uuid)) {
- const hasConnectionToCurrent = path.points.some((point) =>
- point.connections.targets.some(
- (t) => t.modelUUID === currentPath.modeluuid
- )
- );
- if (hasConnectionToCurrent) {
- visited.add(uuid);
- queue.push(path);
- }
- }
- }
- }
-
- return connectedPaths;
- },
- []
- );
-
- const createProcessesFromPaths = useCallback(
- (paths: SimulationPath[]): Process[] => {
- if (!paths || paths.length === 0) return [];
-
- const visited = new Set();
- const processes: Process[] = [];
- const pathMap = new Map();
- paths.forEach((path) => pathMap.set(path.modeluuid, path));
-
- for (const path of paths) {
- if (!visited.has(path.modeluuid) && hasSpawnAction(path)) {
- const connectedPaths = getAllConnectedPaths(path, paths, visited);
- const adjustedPaths = adjustPathPointsOrder(connectedPaths);
- const process = createProcess(adjustedPaths);
- processes.push(process);
- }
- }
-
- return processes;
- },
- [createProcess, getAllConnectedPaths, hasSpawnAction]
- );
-
- return {
- processes,
- createProcessesFromPaths,
- setProcesses,
- };
-}
-
-const ProcessCreator: React.FC = React.memo(
- ({ onProcessesCreated }) => {
- const { simulationStates } = useSimulationStates();
- const { createProcessesFromPaths } = useProcessCreation();
- const prevPathsRef = useRef([]);
- const prevProcessesRef = useRef([]);
- const { isPlaying } = usePlayButtonStore();
-
- const convertedPaths = useMemo((): SimulationPath[] => {
- if (!simulationStates) return [];
- return simulationStates.map((path) =>
- convertToSimulationPath(
- path as
- | ConveyorEventsSchema
- | VehicleEventsSchema
- | ArmBotEventsSchema
- )
- );
- }, [simulationStates]);
-
- // Enhanced dependency tracking that includes action and trigger types
- const pathsDependency = useMemo(() => {
- if (!convertedPaths) return null;
- return convertedPaths.map((path) => ({
- id: path.modeluuid,
- // Track all action types for each point
- actionSignature: path.points
- .map((point, index) =>
- point.actions.map((action) => `${index}-${action.type}`).join("|")
- )
- .join(","),
- // Track all trigger types for each point
- triggerSignature: path.points
- .map((point, index) =>
- point.triggers
- .map((trigger) => `${index}-${trigger.type}`)
- .join("|")
- )
- .join(","),
- connections: path.points
- .flatMap((p: PathPoint) =>
- p.connections.targets.map((t: { modelUUID: string }) => t.modelUUID)
- )
- .join(","),
- isActive: false,
- }));
- }, [convertedPaths]);
-
- // Force process recreation when paths change
- useEffect(() => {
- if (!convertedPaths || convertedPaths.length === 0) {
- if (prevProcessesRef.current.length > 0) {
- onProcessesCreated([]);
- prevProcessesRef.current = [];
- }
- return;
- }
-
- // Always regenerate processes if the pathsDependency has changed
- // This ensures action and trigger type changes will be detected
- const newProcesses = createProcessesFromPaths(convertedPaths);
- prevPathsRef.current = convertedPaths;
-
- // Always update processes when action or trigger types change
- onProcessesCreated(newProcesses);
- prevProcessesRef.current = newProcesses;
- }, [
- pathsDependency, // This now includes action and trigger types
- onProcessesCreated,
- convertedPaths,
- createProcessesFromPaths,
- ]);
-
- return null;
- }
-);
-
-export default ProcessCreator;
diff --git a/app/src/modules/simulation/process/processObject.tsx b/app/src/modules/simulation/process/processObject.tsx
deleted file mode 100644
index 01ef41d..0000000
--- a/app/src/modules/simulation/process/processObject.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import React, { useMemo } from "react";
-import * as THREE from "three";
-import { GLTF } from "three-stdlib";
-import { SpawnedObject } from "./types";
-
-interface ProcessObjectProps {
- objectId: string;
- obj: SpawnedObject;
- renderAs?: "box" | "custom";
- gltf?: GLTF;
-}
-
-const ProcessObject: React.FC = ({
- objectId,
- obj,
- renderAs = "custom",
- gltf,
-}) => {
- const renderedObject = useMemo(() => {
- if (renderAs === "box") {
- return (
- }
- material={obj.material}
- position={obj.position}
- >
-
-
- );
- }
-
- if (gltf?.scene) {
- const clonedScene = gltf.scene.clone();
- clonedScene.traverse((child) => {
- if (child instanceof THREE.Mesh) {
- child.material = obj.material;
- }
- });
-
- return (
- }
- position={obj.position}
- >
-
-
- );
- }
-
- return null;
- }, [objectId, obj, renderAs, gltf]);
-
- return renderedObject;
-};
-
-export default ProcessObject;
diff --git a/app/src/modules/simulation/process/types.ts b/app/src/modules/simulation/process/types.ts
deleted file mode 100644
index 9c9a1bc..0000000
--- a/app/src/modules/simulation/process/types.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import * as THREE from "three";
-
-export interface Trigger {
- uuid: string;
- name: string;
- type: string;
- bufferTime: number;
- isUsed: boolean;
-}
-
-export interface PointAction {
- uuid: string;
- name: string;
- type: "Inherit" | "Spawn" | "Despawn" | "Delay" | "Swap";
- objectType: string;
- material: string;
- delay: string | number;
- spawnInterval: string | number;
- isUsed: boolean;
- hitCount?: number;
-}
-
-export interface ProcessPoint {
- uuid: string;
- position: number[];
- rotation: number[];
- actions: PointAction[];
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- triggers?: Trigger[];
-}
-export interface ProcessPath {
- modeluuid: string;
- modelName: string;
- points: ProcessPoint[];
- pathPosition: number[];
- pathRotation: number[];
- speed: number;
- type: "Conveyor" | "Vehicle" | "ArmBot";
- isActive: boolean
-}
-
-export interface ProcessData {
- id: string;
- paths: ProcessPath[];
- animationPath: { x: number; y: number; z: number }[];
- pointActions: PointAction[][];
- speed: number;
- customMaterials?: Record;
- renderAs?: "box" | "custom";
- pointTriggers: [];
-}
-
-export interface AnimationState {
- currentIndex: number;
- progress: number;
- isAnimating: boolean;
- speed: number;
- isDelaying: boolean;
- delayStartTime: number;
- currentDelayDuration: number;
- delayComplete: boolean;
- currentPathIndex: number;
-}
-
-export interface SpawnedObject {
- ref: React.RefObject;
- state: AnimationState;
- visible: boolean;
- material: THREE.Material;
- spawnTime: number;
- currentMaterialType: string;
- position: THREE.Vector3;
-}
-
-export interface ProcessAnimationState {
- spawnedObjects: { [objectId: string]: SpawnedObject };
- nextSpawnTime: number;
- objectIdCounter: number;
- isProcessDelaying: boolean;
- processDelayStartTime: number;
- processDelayDuration: number;
- hasSpawnedZeroIntervalObject?: boolean;
-}
diff --git a/app/src/modules/simulation/process/useProcessAnimations.tsx b/app/src/modules/simulation/process/useProcessAnimations.tsx
deleted file mode 100644
index 2c701e9..0000000
--- a/app/src/modules/simulation/process/useProcessAnimations.tsx
+++ /dev/null
@@ -1,671 +0,0 @@
-import { useCallback, useEffect, useRef, useState } from "react";
-import * as THREE from "three";
-import {
- ProcessData,
- ProcessAnimationState,
- SpawnedObject,
- AnimationState,
- ProcessPoint,
- PointAction,
- Trigger,
-} from "./types";
-import {
- useAnimationPlaySpeed,
- usePauseButtonStore,
- usePlayButtonStore,
- useResetButtonStore,
-} from "../../../store/usePlayButtonStore";
-import { usePlayAgv, useSimulationStates } from "../../../store/store";
-
-interface ArmBotProcess {
- triggerId: string;
- startPoint: string;
- endPoint: string;
-}
-
-// Enhanced ProcessAnimationState with trigger tracking
-interface EnhancedProcessAnimationState extends ProcessAnimationState {
- triggerCounts: Record;
- triggerLogs: Array<{
- timestamp: number;
- pointId: string;
- objectId: string;
- triggerId: string;
- }>;
-}
-
-interface ProcessContainerProps {
- processes: ProcessData[];
- setProcesses: React.Dispatch>;
- agvRef: any;
-}
-
-interface PlayAgvState {
- playAgv: Record;
- setPlayAgv: (data: any) => void;
-}
-
-interface ArmBotState {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- status: string;
- material: string;
- triggerId: string;
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
- isActive?: boolean;
-}
-
-export const useProcessAnimation = (
- processes: ProcessData[],
- setProcesses: React.Dispatch>,
- agvRef: any,
- armBots: ArmBotState[],
- setArmBots: React.Dispatch>
-) => {
- // State and refs initialization
- const { isPlaying, setIsPlaying } = usePlayButtonStore();
- const { isPaused, setIsPaused } = usePauseButtonStore();
- const { isReset, setReset } = useResetButtonStore();
- const debugRef = useRef(false);
- const clockRef = useRef(new THREE.Clock());
- const pauseTimeRef = useRef(0);
- const elapsedBeforePauseRef = useRef(0);
- const animationStatesRef = useRef>({});
- const { speed } = useAnimationPlaySpeed();
- const prevIsPlaying = useRef(null);
- const [internalResetFlag, setInternalResetFlag] = useState(false);
- const [animationStates, setAnimationStates] = useState>({});
- const speedRef = useRef(speed);
- const { PlayAgv, setPlayAgv } = usePlayAgv();
- const { simulationStates } = useSimulationStates();
-
- // Effect hooks
- useEffect(() => {
- speedRef.current = speed;
- }, [speed]);
-
- useEffect(() => {
- if (prevIsPlaying.current !== null || !isPlaying) {
- setAnimationStates({});
- }
- prevIsPlaying.current = isPlaying;
- }, [isPlaying]);
-
- useEffect(() => {
- animationStatesRef.current = animationStates;
- }, [animationStates]);
-
- // Reset handler
- useEffect(() => {
- if (isReset) {
- setInternalResetFlag(true);
- setIsPlaying(false);
- setIsPaused(false);
- setAnimationStates({});
- animationStatesRef.current = {};
- clockRef.current = new THREE.Clock();
- elapsedBeforePauseRef.current = 0;
- pauseTimeRef.current = 0;
- setReset(false);
- setTimeout(() => {
- setInternalResetFlag(false);
- setIsPlaying(true);
- }, 0);
- }
- }, [isReset, setReset, setIsPlaying, setIsPaused]);
-
- // Pause handler
- useEffect(() => {
- if (isPaused) {
- pauseTimeRef.current = clockRef.current.getElapsedTime();
- } else if (pauseTimeRef.current > 0) {
- const pausedDuration = clockRef.current.getElapsedTime() - pauseTimeRef.current;
- elapsedBeforePauseRef.current += pausedDuration;
- }
- }, [isPaused]);
-
- // Initialize animation states with trigger tracking
- useEffect(() => {
- if (isPlaying && !internalResetFlag) {
- const newStates: Record = {};
-
- processes.forEach((process) => {
- const triggerCounts: Record = {};
-
- // Initialize trigger counts for all On-Hit triggers
- process.paths?.forEach((path) => {
- path.points?.forEach((point) => {
- point.triggers?.forEach((trigger: Trigger) => {
- if (trigger.type === "On-Hit" && trigger.isUsed) {
- triggerCounts[`${point.uuid}-${trigger.uuid}`] = 0;
- }
- });
- });
- });
-
- newStates[process.id] = {
- spawnedObjects: {},
- nextSpawnTime: 0,
- objectIdCounter: 0,
- isProcessDelaying: false,
- processDelayStartTime: 0,
- processDelayDuration: 0,
- triggerCounts,
- triggerLogs: [],
- };
- });
-
- setAnimationStates(newStates);
- animationStatesRef.current = newStates;
- clockRef.current.start();
- }
- }, [isPlaying, processes, internalResetFlag]);
-
- useEffect(() => {
- if (isPlaying && !internalResetFlag) {
- const newStates: Record = {};
-
- // Initialize AGVs for each process first
- processes.forEach((process) => {
- // Find all vehicle paths for this process
- const vehiclePaths = process.paths?.filter(
- (path) => path.type === "Vehicle"
- ) || [];
-
- // Initialize AGVs for each vehicle path
- vehiclePaths.forEach((vehiclePath) => {
- if (vehiclePath.points?.length > 0) {
- const vehiclePoint = vehiclePath.points[0];
- const action = vehiclePoint.actions?.[0];
- const maxHitCount = action?.hitCount;
-
- const vehicleId = vehiclePath.modeluuid;
- const processId = process.id;
-
- // Check if this AGV already exists
- const existingAgv = agvRef.current.find(
- (v: any) => v.vehicleId === vehicleId && v.processId === processId
- );
-
- if (!existingAgv) {
- // Initialize the AGV in a stationed state
- agvRef.current.push({
- processId,
- vehicleId,
- maxHitCount: maxHitCount || 0,
- isActive: false,
- hitCount: 0,
- status: 'stationed',
- lastUpdated: 0
- });
- }
- }
- });
-
- // Then initialize trigger counts as before
- const triggerCounts: Record = {};
- process.paths?.forEach((path) => {
- path.points?.forEach((point) => {
- point.triggers?.forEach((trigger: Trigger) => {
- if (trigger.type === "On-Hit" && trigger.isUsed) {
- triggerCounts[`${point.uuid}-${trigger.uuid}`] = 0;
- }
- });
- });
- });
-
- newStates[process.id] = {
- spawnedObjects: {},
- nextSpawnTime: 0,
- objectIdCounter: 0,
- isProcessDelaying: false,
- processDelayStartTime: 0,
- processDelayDuration: 0,
- triggerCounts,
- triggerLogs: [],
- };
- });
-
- setAnimationStates(newStates);
- animationStatesRef.current = newStates;
- clockRef.current.start();
- }
- }, [isPlaying, processes, internalResetFlag]);
-
- // Helper functions
- const findSpawnPoint = (process: ProcessData): ProcessPoint | null => {
- for (const path of process.paths || []) {
- for (const point of path.points || []) {
- const spawnAction = point.actions?.find(
- (a) => a.isUsed && a.type === "Spawn"
- );
- if (spawnAction) {
- return point;
- }
- }
- }
- return null;
- };
-
- const findAnimationPathPoint = (
- process: ProcessData,
- spawnPoint: ProcessPoint
- ): THREE.Vector3 => {
- if (process.animationPath && process.animationPath.length > 0) {
- let pointIndex = 0;
- for (const path of process.paths || []) {
- for (let i = 0; i < (path.points?.length || 0); i++) {
- const point = path.points?.[i];
- if (point && point.uuid === spawnPoint.uuid) {
- if (process.animationPath[pointIndex]) {
- const p = process.animationPath[pointIndex];
- return new THREE.Vector3(p.x, p.y, p.z);
- }
- }
- pointIndex++;
- }
- }
- }
- return new THREE.Vector3(
- spawnPoint.position[0],
- spawnPoint.position[1],
- spawnPoint.position[2]
- );
- };
-
- // Optimized object creation
- const createSpawnedObject = useCallback(
- (
- process: ProcessData,
- currentTime: number,
- materialType: string,
- spawnPoint: ProcessPoint,
- baseMaterials: Record
- ): SpawnedObject => {
- const processMaterials = {
- ...baseMaterials,
- ...(process.customMaterials || {}),
- };
-
- const spawnPosition = findAnimationPathPoint(process, spawnPoint);
- const material =
- processMaterials[materialType as keyof typeof processMaterials] ||
- baseMaterials.Default;
-
- return {
- ref: { current: null },
- state: {
- currentIndex: 0,
- progress: 0,
- isAnimating: true,
- speed: process.speed || 1,
- isDelaying: false,
- delayStartTime: 0,
- currentDelayDuration: 0,
- delayComplete: false,
- currentPathIndex: 0,
- },
- visible: true,
- material: material,
- currentMaterialType: materialType,
- spawnTime: currentTime,
- position: spawnPosition,
- };
- },
- []
- );
-
- // Material handling
- const handleMaterialSwap = useCallback(
- (
- processId: string,
- objectId: string,
- materialType: string,
- processes: ProcessData[],
- baseMaterials: Record
- ) => {
- setAnimationStates((prev) => {
- const processState = prev[processId];
- if (!processState || !processState.spawnedObjects[objectId])
- return prev;
-
- const process = processes.find((p) => p.id === processId);
- if (!process) return prev;
-
- const processMaterials = {
- ...baseMaterials,
- ...(process.customMaterials || {}),
- };
-
- const newMaterial =
- processMaterials[materialType as keyof typeof processMaterials];
- if (!newMaterial) return prev;
-
- return {
- ...prev,
- [processId]: {
- ...processState,
- spawnedObjects: {
- ...processState.spawnedObjects,
- [objectId]: {
- ...processState.spawnedObjects[objectId],
- material: newMaterial,
- currentMaterialType: materialType,
- },
- },
- },
- };
- });
- },
- []
- );
-
- // Point action handler with trigger counting
- const handlePointActions = useCallback(
- (
- processId: string,
- objectId: string,
- actions: PointAction[] = [],
- currentTime: number,
- processes: ProcessData[],
- baseMaterials: Record
- ): boolean => {
- let shouldStopAnimation = false;
-
- actions.forEach((action) => {
- if (!action.isUsed) return;
-
- switch (action.type) {
- case "Delay":
- setAnimationStates((prev) => {
- const processState = prev[processId];
- if (!processState || processState.isProcessDelaying) return prev;
-
- const delayDuration =
- typeof action.delay === "number"
- ? action.delay
- : parseFloat(action.delay as string) || 0;
-
- if (delayDuration > 0) {
- return {
- ...prev,
- [processId]: {
- ...processState,
- isProcessDelaying: true,
- processDelayStartTime: currentTime,
- processDelayDuration: delayDuration,
- spawnedObjects: {
- ...processState.spawnedObjects,
- [objectId]: {
- ...processState.spawnedObjects[objectId],
- state: {
- ...processState.spawnedObjects[objectId].state,
- isAnimating: false,
- isDelaying: true,
- delayStartTime: currentTime,
- currentDelayDuration: delayDuration,
- delayComplete: false,
- },
- },
- },
- },
- };
- }
- return prev;
- });
- shouldStopAnimation = true;
- break;
-
- case "Despawn":
- setAnimationStates((prev) => {
- const processState = prev[processId];
- if (!processState) return prev;
-
- const newSpawnedObjects = { ...processState.spawnedObjects };
- delete newSpawnedObjects[objectId];
-
- return {
- ...prev,
- [processId]: {
- ...processState,
- spawnedObjects: newSpawnedObjects,
- },
- };
- });
- shouldStopAnimation = true;
- break;
-
- case "Swap":
- if (action.material) {
- handleMaterialSwap(
- processId,
- objectId,
- action.material,
- processes,
- baseMaterials
- );
- }
- break;
-
- default:
- break;
- }
- });
-
- return shouldStopAnimation;
- },
- [handleMaterialSwap]
- );
-
- const deferredArmBotUpdates = useRef<{ uuid: string; triggerId: string }[]>([]);
-
- // Trigger counting system
- const checkAndCountTriggers = useCallback(
- (
- processId: string,
- objectId: string,
- currentPointIndex: number,
- processes: ProcessData[],
- currentTime: number
- ) => {
- setAnimationStates((prev) => {
- const processState = prev[processId];
- if (!processState) return prev;
-
- const process = processes.find((p) => p.id === processId);
- if (!process) return prev;
-
- const point = getPointDataForAnimationIndex(process, currentPointIndex);
- if (!point?.triggers) return prev;
-
- const onHitTriggers = point.triggers.filter((t: Trigger) => t.type === "On-Hit" && t.isUsed);
-
- if (onHitTriggers.length === 0) return prev;
-
- let newTriggerCounts = { ...processState.triggerCounts };
- const newTriggerLogs = [...processState.triggerLogs];
- let shouldLog = false;
-
- const vehiclePaths = process.paths.filter((path) => path.type === "Vehicle");
- const armBotPaths = process.paths.filter((path) => path.type === "ArmBot");
-
- const activeVehicles = vehiclePaths.filter((path) => {
- const vehicleId = path.modeluuid;
- const vehicleEntry = agvRef.current.find((v: any) => v.vehicleId === vehicleId && v.processId === processId);
- return vehicleEntry?.isActive;
- });
-
- // Check if any ArmBot is active for this process
- // const activeArmBots = armBotPaths.filter((path) => {
- // const armBotId = path.modeluuid;
- // const armBotEntry = armBots.find((a: any) => a.uuid === armBotId);
- // return armBotEntry;
- // });
-
- // Only count triggers if no vehicles and no ArmBots are active for this process
-
- if (activeVehicles.length === 0) {
- onHitTriggers.forEach((trigger: Trigger) => {
- const triggerKey = `${point.uuid}-${trigger.uuid}`;
-
- newTriggerCounts[triggerKey] = (newTriggerCounts[triggerKey] || 0) + 1;
-
- newTriggerLogs.push({ timestamp: currentTime, pointId: point.uuid, objectId, triggerId: trigger.uuid, });
-
- const connections = point.connections?.targets || [];
-
- connections.forEach((connection) => {
- const connectedModelUUID = connection.modelUUID;
-
- const isConveyor = simulationStates.find((state) => state.modeluuid === connectedModelUUID && state.type === "Conveyor");
-
- if (!isConveyor) {
- const matchingArmPath = armBotPaths.find((path) => path.modeluuid === connectedModelUUID);
-
- if (matchingArmPath) {
- deferredArmBotUpdates.current.push({
- uuid: connectedModelUUID,
- triggerId: trigger.uuid,
- });
- } else {
- shouldLog = true;
- }
- }
- });
- });
- }
-
- let processTotalHits = Object.values(newTriggerCounts).reduce((a, b) => a + b, 0);
-
- // Handle logic for vehicles when a trigger is hit
- if (shouldLog) {
- vehiclePaths.forEach((vehiclePath) => {
- if (vehiclePath.points?.length > 0) {
- const vehiclePoint = vehiclePath.points[0];
- const action = vehiclePoint.actions?.[0];
- const maxHitCount = action?.hitCount;
-
- if (maxHitCount !== undefined) {
- const vehicleId = vehiclePath.modeluuid;
- let vehicleEntry = agvRef.current.find(
- (v: any) =>
- v.vehicleId === vehicleId && v.processId === processId
- );
-
- if (!vehicleEntry) {
- vehicleEntry = {
- processId,
- vehicleId,
- maxHitCount: maxHitCount,
- isActive: false,
- hitCount: 0,
- status: "stationed",
- };
- agvRef.current.push(vehicleEntry);
- }
-
- if (!vehicleEntry.isActive) {
- vehicleEntry.hitCount++;
- vehicleEntry.lastUpdated = currentTime;
-
- if (vehicleEntry.hitCount >= vehicleEntry.maxHitCount) {
- vehicleEntry.isActive = true;
- newTriggerCounts = {};
- processTotalHits = 0;
- }
- }
- }
- }
- });
- }
-
- return {
- ...prev,
- [processId]: {
- ...processState,
- triggerCounts: newTriggerCounts,
- triggerLogs: newTriggerLogs,
- totalHits: processTotalHits,
- },
- };
- });
- }, []);
-
- useEffect(() => {
- // console.log('deferredArmBotUpdates: ', deferredArmBotUpdates);
- if (deferredArmBotUpdates.current.length > 0) {
- const updates = [...deferredArmBotUpdates.current];
- deferredArmBotUpdates.current = [];
-
- setArmBots((prev) =>
- prev.map((bot) => {
- const update = updates.find((u) => u.uuid === bot.uuid);
-
- return update
- ? { ...bot, triggerId: update.triggerId, isActive: true }
- : bot;
- })
- );
- }
- }, [animationStates]);
-
- // Utility functions
- const hasNonInheritActions = useCallback(
- (actions: PointAction[] = []): boolean => {
- return actions.some(
- (action) => action.isUsed && action.type !== "Inherit"
- );
- }, []);
-
- const getPointDataForAnimationIndex = useCallback(
- (process: ProcessData, index: number): ProcessPoint | null => {
- if (!process.paths) return null;
-
- let cumulativePoints = 0;
- for (const path of process.paths) {
- const pointCount = path.points?.length || 0;
-
- if (index < cumulativePoints + pointCount) {
- const pointIndex = index - cumulativePoints;
- return path.points?.[pointIndex] || null;
- }
-
- cumulativePoints += pointCount;
- }
-
- return null;
- },
- []
- );
-
- const getTriggerCounts = useCallback((processId: string) => {
- return animationStatesRef.current[processId]?.triggerCounts || {};
- }, []);
-
- const getTriggerLogs = useCallback((processId: string) => {
- return animationStatesRef.current[processId]?.triggerLogs || [];
- }, []);
-
- return {
- animationStates,
- setAnimationStates,
- clockRef,
- elapsedBeforePauseRef,
- speedRef,
- debugRef,
- findSpawnPoint,
- createSpawnedObject,
- handlePointActions,
- hasNonInheritActions,
- getPointDataForAnimationIndex,
- checkAndCountTriggers,
- getTriggerCounts,
- getTriggerLogs,
- processes,
- };
-};
diff --git a/app/src/modules/simulation/simulation.tsx b/app/src/modules/simulation/simulation.tsx
index 84d3651..bde8106 100644
--- a/app/src/modules/simulation/simulation.tsx
+++ b/app/src/modules/simulation/simulation.tsx
@@ -1,74 +1,10 @@
-import { useState, useRef } from "react";
-import * as THREE from "three";
-import PathCreation from "./path/pathCreation";
-import PathConnector from "./path/pathConnector";
-import useModuleStore from "../../store/useModuleStore";
-import ProcessContainer from "./process/processContainer";
-import Agv from "../builder/agv/agv";
-import ArmBot from "./armbot/ArmBot";
-import StaticMachine from "./staticMachine/staticMachine";
-
-interface ArmBotState {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- status: string;
- material: string;
- triggerId: string;
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
- isActive?: boolean;
-}
-
-interface StaticMachineState {
- uuid: string;
- status: string;
- actions: { uuid: string; name: string; buffer: number; material: string; };
- machineTriggerId: string;
- connectedArmBot: string;
-}
+import React from 'react'
function Simulation() {
- const { activeModule } = useModuleStore();
- const pathsGroupRef = useRef() as React.MutableRefObject;
- const [armBots, setArmBots] = useState([]);
- const [staticMachines, setStaticMachines] = useState([]);
- const [processes, setProcesses] = useState([]);
- const agvRef = useRef([]);
- const MaterialRef = useRef([]);
-
- return (
- <>
- {activeModule === "simulation" && (
- <>
-
-
-
-
-
-
-
-
- >
- )}
-
-
- >
- );
+ return (
+ <>
+ >
+ )
}
-export default Simulation;
+export default Simulation
\ No newline at end of file
diff --git a/app/src/modules/simulation/simulationUI.tsx b/app/src/modules/simulation/simulationUI.tsx
deleted file mode 100644
index 055fb36..0000000
--- a/app/src/modules/simulation/simulationUI.tsx
+++ /dev/null
@@ -1,409 +0,0 @@
-// import { useMemo, useState } from 'react';
-// import { useSelectedActionSphere, useToggleView, useSimulationStates, 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 { simulationStates, setSimulationStates } = useSimulationStates();
-// const { drawMaterialPath, setDrawMaterialPath } = useDrawMaterialPath();
-// const [activeButton, setActiveButton] = useState(null);
-
-// const handleAddAction = () => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) => {
-// if (point.uuid === selectedActionSphere.points.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;
-// }),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const handleDeleteAction = (uuid: string) => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) =>
-// point.uuid === selectedActionSphere.points.uuid
-// ? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) }
-// : point
-// ),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const handleActionSelect = (uuid: string, actionType: string) => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) =>
-// point.uuid === selectedActionSphere.points.uuid
-// ? {
-// ...point,
-// actions: point.actions.map((action) =>
-// action.uuid === uuid ? { ...action, type: actionType } : action
-// ),
-// }
-// : point
-// ),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const handleMaterialSelect = (uuid: string, material: string) => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) =>
-// point.uuid === selectedActionSphere.points.uuid
-// ? {
-// ...point,
-// actions: point.actions.map((action) =>
-// action.uuid === uuid ? { ...action, material } : action
-// ),
-// }
-// : point
-// ),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const handleDelayChange = (uuid: string, delay: number | string) => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) =>
-// point.uuid === selectedActionSphere.points.uuid
-// ? {
-// ...point,
-// actions: point.actions.map((action) =>
-// action.uuid === uuid ? { ...action, delay } : action
-// ),
-// }
-// : point
-// ),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) =>
-// point.uuid === selectedActionSphere.points.uuid
-// ? {
-// ...point,
-// actions: point.actions.map((action) =>
-// action.uuid === uuid ? { ...action, spawnInterval } : action
-// ),
-// }
-// : point
-// ),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const handleSpeedChange = (speed: number) => {
-// if (!selectedPath) return;
-
-// const updatedPaths = simulationStates.map((path) =>
-// path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
-// );
-
-// setSimulationStates(updatedPaths);
-// setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
-// };
-
-// const handleAddTrigger = () => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) => {
-// if (point.uuid === selectedActionSphere.points.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;
-// }),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const handleDeleteTrigger = (uuid: string) => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) =>
-// point.uuid === selectedActionSphere.points.uuid
-// ? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) }
-// : point
-// ),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const handleTriggerSelect = (uuid: string, triggerType: string) => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) =>
-// point.uuid === selectedActionSphere.points.uuid
-// ? {
-// ...point,
-// triggers: point.triggers.map((trigger) =>
-// trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger
-// ),
-// }
-// : point
-// ),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const handleResetPath = () => {
-// if (!selectedPath) return;
-
-// };
-
-
-// const handleActionToggle = (uuid: string) => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) =>
-// point.uuid === selectedActionSphere.points.uuid
-// ? {
-// ...point,
-// actions: point.actions.map((action) => ({
-// ...action,
-// isUsed: action.uuid === uuid ? !action.isUsed : false,
-// })),
-// }
-// : point
-// ),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const handleTriggerToggle = (uuid: string) => {
-// if (!selectedActionSphere) return;
-
-// const updatedPaths = simulationStates.map((path) => ({
-// ...path,
-// points: path.points.map((point) =>
-// point.uuid === selectedActionSphere.points.uuid
-// ? {
-// ...point,
-// triggers: point.triggers.map((trigger) => ({
-// ...trigger,
-// isUsed: trigger.uuid === uuid ? !trigger.isUsed : false,
-// })),
-// }
-// : point
-// ),
-// }));
-
-// setSimulationStates(updatedPaths);
-// };
-
-// const selectedPoint = useMemo(() => {
-// if (!selectedActionSphere) return null;
-// return simulationStates.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.points.uuid);
-// }, [selectedActionSphere, simulationStates]);
-
-// const createPath = () => {
-// setActiveButton(activeButton !== 'addMaterialPath' ? 'addMaterialPath' : null);
-// setDrawMaterialPath(!drawMaterialPath);
-// }
-
-// return (
-// <>
-// {activeModule === "simulation" && (
-//
-// {!ToggleView && (
-// <>
-//
-
-//
-// {!ToggleView && }
-//
-
-// {selectedPath && (
-//
-//
-// handleSpeedChange(parseFloat(e.target.value))}
-// />
-//
-// )}
-
-// {selectedActionSphere && (
-//
-//
-//
-
-// {selectedPoint?.actions.map((action) => (
-//
-//
-//
-//
-
-// {(action.type === 'Spawn' || action.type === 'Swap') && (
-//
-//
-//
-// )}
-
-// {action.type === 'Delay' && (
-//
-//
-// handleDelayChange(action.uuid, parseInt(e.target.value) || 'Inherit')}
-// />
-
-//
-// )}
-
-// {action.type === 'Spawn' && (
-//
-//
-// handleSpawnIntervalChange(action.uuid, parseInt(e.target.value) || 'Inherit')}
-// />
-
-//
-// )}
-//
-//
-// ))}
-
-//
-
-// {selectedPoint?.triggers.map((trigger) => (
-//
-//
-//
-//
-//
-//
-// ))}
-
-
-//
-// )}
-
-// {selectedPath && (
-//
-//
-//
-// )}
-// >
-// )}
-//
-// )}
-// >
-// );
-// }
-
-// export default SimulationUI;
\ No newline at end of file
diff --git a/app/src/modules/simulation/simulationtemp/collider/colliderCreator.tsx b/app/src/modules/simulation/simulationtemp/collider/colliderCreator.tsx
deleted file mode 100644
index ec5e14b..0000000
--- a/app/src/modules/simulation/simulationtemp/collider/colliderCreator.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from 'react'
-
-function ColliderCreator() {
- return (
- <>>
- )
-}
-
-export default ColliderCreator
\ No newline at end of file
diff --git a/app/src/modules/simulation/simulationtemp/path/pathCreator.tsx b/app/src/modules/simulation/simulationtemp/path/pathCreator.tsx
deleted file mode 100644
index c9dd36b..0000000
--- a/app/src/modules/simulation/simulationtemp/path/pathCreator.tsx
+++ /dev/null
@@ -1,407 +0,0 @@
-import { useEffect, useState } from 'react';
-import * as THREE from 'three';
-import { useThree, useFrame } from '@react-three/fiber';
-import { Line, TransformControls } from '@react-three/drei';
-import { useDrawMaterialPath } from '../../../../store/store';
-
-type PathPoint = {
- position: THREE.Vector3;
- rotation: THREE.Quaternion;
- uuid: string;
-};
-
-type PathCreatorProps = {
- simulationStates: PathPoint[][];
- setSimulationStates: React.Dispatch>;
- connections: { start: PathPoint; end: PathPoint }[];
- setConnections: React.Dispatch>
-};
-
-const PathCreator = ({ simulationStates, setSimulationStates, connections, setConnections }: PathCreatorProps) => {
- const { camera, scene, raycaster, pointer, gl } = useThree();
- const { drawMaterialPath } = useDrawMaterialPath();
-
- const [currentPath, setCurrentPath] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }[]>([]);
- const [temporaryPoint, setTemporaryPoint] = useState(null);
- const [selectedPoint, setSelectedPoint] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string } | null>(null);
- const [selectedConnectionPoint, setSelectedConnectionPoint] = useState<{ point: PathPoint; pathIndex: number } | null>(null);
- const [previewConnection, setPreviewConnection] = useState<{ start: PathPoint; end?: THREE.Vector3 } | null>(null);
- const [transformMode, setTransformMode] = useState<'translate' | 'rotate'>('translate');
-
- useEffect(() => {
- const handleKeyDown = (event: KeyboardEvent) => {
- if (selectedPoint) {
- if (event.key === 'g') {
- setTransformMode('translate');
- } else if (event.key === 'r') {
- setTransformMode('rotate');
- }
- }
- };
-
- document.addEventListener('keydown', handleKeyDown);
-
- return () => {
- document.removeEventListener('keydown', handleKeyDown);
- };
- }, [selectedPoint]);
-
- useEffect(() => {
- const canvasElement = gl.domElement;
-
- let drag = false;
- let MouseDown = false;
-
- const onMouseDown = () => {
- MouseDown = true;
- drag = false;
- };
-
- const onMouseUp = () => {
- MouseDown = false;
- };
-
- const onMouseMove = () => {
- if (MouseDown) {
- drag = true;
- }
- };
-
- const onContextMenu = (e: any) => {
- e.preventDefault();
- if (drag || e.button === 0) return;
- if (currentPath.length > 1) {
- setSimulationStates((prevPaths) => [...prevPaths, currentPath]);
- }
- setCurrentPath([]);
- setTemporaryPoint(null);
- setPreviewConnection(null);
- setSelectedConnectionPoint(null);
- };
-
- const onMouseClick = (evt: any) => {
- if (drag || evt.button !== 0) return;
-
- evt.preventDefault();
- raycaster.setFromCamera(pointer, camera);
-
- let intersects = raycaster.intersectObjects(scene.children, true);
-
- if (intersects.some((intersect) => intersect.object.name.includes("path-point"))) {
- intersects = [];
- } else {
- intersects = intersects.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")
- );
- }
-
- if (intersects.length > 0 && selectedPoint === null) {
- let point = intersects[0].point;
- if (point.y < 0.05) {
- point = new THREE.Vector3(point.x, 0.05, point.z);
- }
- const newPoint = {
- position: point,
- rotation: new THREE.Quaternion(),
- uuid: THREE.MathUtils.generateUUID(),
- };
- setCurrentPath((prevPath) => [...prevPath, newPoint]);
- setTemporaryPoint(null);
- } else {
- setSelectedPoint(null);
- }
- };
-
- if (drawMaterialPath) {
- canvasElement.addEventListener("mousedown", onMouseDown);
- canvasElement.addEventListener("mouseup", onMouseUp);
- canvasElement.addEventListener("mousemove", onMouseMove);
- canvasElement.addEventListener("click", onMouseClick);
- canvasElement.addEventListener("contextmenu", onContextMenu);
- } else {
- if (currentPath.length > 1) {
- setSimulationStates((prevPaths) => [...prevPaths, currentPath]);
- }
- setCurrentPath([]);
- setTemporaryPoint(null);
- }
-
- return () => {
- canvasElement.removeEventListener("mousedown", onMouseDown);
- canvasElement.removeEventListener("mouseup", onMouseUp);
- canvasElement.removeEventListener("mousemove", onMouseMove);
- canvasElement.removeEventListener("click", onMouseClick);
- canvasElement.removeEventListener("contextmenu", onContextMenu);
- };
- }, [camera, scene, raycaster, currentPath, drawMaterialPath, selectedPoint]);
-
- useFrame(() => {
- if (drawMaterialPath && currentPath.length > 0) {
- 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")
- );
-
- if (intersects.length > 0) {
- let point = intersects[0].point;
- if (point.y < 0.05) {
- point = new THREE.Vector3(point.x, 0.05, point.z);
- }
- setTemporaryPoint(point);
- } else {
- setTemporaryPoint(null);
- }
- } else {
- setTemporaryPoint(null);
- }
- });
-
- const handlePointClick = (point: { position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }) => {
- if (currentPath.length === 0 && drawMaterialPath) {
- setSelectedPoint(point);
- } else {
- setSelectedPoint(null);
- }
- };
-
- const handleTransform = (e: any) => {
- if (selectedPoint) {
- const updatedPosition = e.target.object.position.clone();
- const updatedRotation = e.target.object.quaternion.clone();
- const updatedPaths = simulationStates.map((path) =>
- path.map((p) =>
- p.uuid === selectedPoint.uuid ? { ...p, position: updatedPosition, rotation: updatedRotation } : p
- )
- );
- setSimulationStates(updatedPaths);
- }
- };
-
-
- const meshContext = (uuid: string) => {
- const pathIndex = simulationStates.findIndex(path => path.some(point => point.uuid === uuid));
- if (pathIndex === -1) return;
-
- const clickedPoint = simulationStates[pathIndex].find(point => point.uuid === uuid);
- if (!clickedPoint) return;
-
- const isStart = simulationStates[pathIndex][0].uuid === uuid;
- const isEnd = simulationStates[pathIndex][simulationStates[pathIndex].length - 1].uuid === uuid;
-
- if (pathIndex === 0 && isStart) {
- console.log("The first-ever point is not connectable.");
- setSelectedConnectionPoint(null);
- setPreviewConnection(null);
- return;
- }
-
- if (!isStart && !isEnd) {
- console.log("Selected point is not a valid connection point (not start or end)");
- setSelectedConnectionPoint(null);
- setPreviewConnection(null);
- return;
- }
-
- if (connections.some(conn => conn.start.uuid === uuid || conn.end.uuid === uuid)) {
- console.log("The selected point is already connected.");
- setSelectedConnectionPoint(null);
- setPreviewConnection(null);
- return;
- }
-
- if (!selectedConnectionPoint) {
- setSelectedConnectionPoint({ point: clickedPoint, pathIndex });
- setPreviewConnection({ start: clickedPoint });
- console.log("First point selected for connection:", clickedPoint);
- return;
- }
-
- if (selectedConnectionPoint.pathIndex === pathIndex) {
- console.log("Cannot connect points within the same path.");
- setSelectedConnectionPoint(null);
- setPreviewConnection(null);
- return;
- }
-
- if (connections.some(conn => conn.start.uuid === clickedPoint.uuid || conn.end.uuid === clickedPoint.uuid)) {
- console.log("The target point is already connected.");
- setSelectedConnectionPoint(null);
- setPreviewConnection(null);
- return;
- }
-
- setConnections(prevConnections => [
- ...prevConnections,
- { start: selectedConnectionPoint.point, end: clickedPoint },
- ]);
-
-
- setSelectedConnectionPoint(null);
- setPreviewConnection(null);
- };
-
- useEffect(() => {
- if (!selectedConnectionPoint) {
- setPreviewConnection(null);
- }
- }, [selectedConnectionPoint, connections]);
-
- useFrame(() => {
- if (selectedConnectionPoint) {
- 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")
- );
-
- if (intersects.length > 0) {
- let point = intersects[0].point;
- if (point.y < 0.05) {
- point = new THREE.Vector3(point.x, 0.05, point.z);
- }
- setPreviewConnection({ start: selectedConnectionPoint.point, end: point });
- } else {
- setPreviewConnection(null);
- }
- }
- });
-
- return (
- <>
-
- {/* Render finalized simulationStates */}
- {simulationStates.map((path, pathIndex) => (
-
- point.position)}
- color="yellow"
- lineWidth={5}
- userData={{ isPathObject: true }}
- />
-
- ))}
-
- {/* Render finalized points */}
- {simulationStates.map((path) =>
- path.map((point) => (
- handlePointClick(point)}
- onPointerMissed={() => { setSelectedPoint(null) }}
- onContextMenu={() => { meshContext(point.uuid); }}
- >
-
-
-
- ))
- )}
-
- {connections.map((conn, index) => (
-
- ))}
-
-
-
- {/* Render current path */}
- {currentPath.length > 1 && (
-
- point.position)}
- color="red"
- lineWidth={5}
- userData={{ isPathObject: true }}
- />
-
- )}
-
- {/* Render current path points */}
- {currentPath.map((point) => (
-
-
-
-
- ))}
-
- {/* Render temporary indicator line */}
- {temporaryPoint && currentPath.length > 0 && (
-
-
-
- )}
-
- {/* Render dashed preview connection */}
- {previewConnection && previewConnection.end && (
-
- )}
-
- {/* Render temporary point */}
- {temporaryPoint && (
-
-
-
-
- )}
-
- {/* Attach TransformControls to the selected point */}
- {selectedPoint && (
-
- )}
- >
- );
-};
-
-export default PathCreator;
\ No newline at end of file
diff --git a/app/src/modules/simulation/simulationtemp/path/pathFlow.tsx b/app/src/modules/simulation/simulationtemp/path/pathFlow.tsx
deleted file mode 100644
index 586fd3a..0000000
--- a/app/src/modules/simulation/simulationtemp/path/pathFlow.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-import * as THREE from 'three';
-import { useState, useEffect, useRef, useMemo } from "react";
-import { useLoader, useFrame } from "@react-three/fiber";
-import { GLTFLoader } from "three-stdlib";
-import crate from "../../../../assets/gltf-glb/crate_box.glb";
-import { useOrganization } from '../../../../store/store';
-import { useControls } from 'leva';
-
-type PathPoint = {
- position: THREE.Vector3;
- rotation: THREE.Quaternion;
- uuid: string;
-};
-
-type PathFlowProps = {
- path: PathPoint[];
- connections: { start: PathPoint; end: PathPoint }[];
-};
-
-export default function PathFlow({ path, connections }: PathFlowProps) {
- const { organization } = useOrganization();
- const [isPaused, setIsPaused] = useState(false);
- const [isStopped, setIsStopped] = useState(false);
-
- const { spawnInterval, speed, pauseResume, startStop } = useControls({
- spawnInterval: { value: 1000, min: 500, max: 5000, step: 100 },
- speed: { value: 2, min: 1, max: 20, step: 0.5 },
- pauseResume: { value: false, label: "Pause/Resume" },
- startStop: { value: false, label: "Start/Stop" },
- });
-
- const [meshes, setMeshes] = useState<{ id: number }[]>([]);
- const gltf = useLoader(GLTFLoader, crate);
-
- const meshIdRef = useRef(0);
- const lastSpawnTime = useRef(performance.now());
- const totalPausedTime = useRef(0);
- const pauseStartTime = useRef(null);
-
- useEffect(() => {
- setIsPaused(pauseResume);
- setIsStopped(startStop);
- }, [pauseResume, startStop]);
-
- const removeMesh = (id: number) => {
- setMeshes((prev) => prev.filter((m) => m.id !== id));
- };
-
- useFrame(() => {
- if (isStopped || !path) return;
-
- const now = performance.now();
-
- if (isPaused) {
- if (pauseStartTime.current === null) {
- pauseStartTime.current = now;
- }
- return;
- }
-
- if (pauseStartTime.current !== null) {
- totalPausedTime.current += now - pauseStartTime.current;
- pauseStartTime.current = null;
- }
-
- const adjustedTime = now - totalPausedTime.current;
-
- if (adjustedTime - lastSpawnTime.current >= spawnInterval) {
- setMeshes((prev) => [...prev, { id: meshIdRef.current++ }]);
- lastSpawnTime.current = adjustedTime;
- }
- });
-
- return (
- <>
- {meshes.map((mesh) => (
-
- ))}
- >
- );
-}
-
-function MovingMesh({ meshId, points, speed, gltf, removeMesh, isPaused }: any) {
- const meshRef = useRef();
- const startTime = useRef(null); // Initialize as null
- const pausedTime = useRef(0);
- const pauseStartTime = useRef(null);
-
- const distances = useMemo(() => {
- if (!points || points.length < 2) return [];
- return points.slice(1).map((point: any, i: number) => points[i].position.distanceTo(point.position));
- }, [points]);
-
- useFrame(() => {
- if (!points || points.length < 2) return;
-
- if (startTime.current === null && points.length > 0) {
- startTime.current = performance.now();
- }
-
- if (!meshRef.current) return;
-
- if (isPaused) {
- if (pauseStartTime.current === null) {
- pauseStartTime.current = performance.now();
- }
- return;
- }
-
- if (pauseStartTime.current !== null) {
- pausedTime.current += performance.now() - pauseStartTime.current;
- pauseStartTime.current = null;
- }
-
- if (startTime.current === null) return;
-
- const elapsed = performance.now() - startTime.current - pausedTime.current;
-
- const distanceTraveled = elapsed / 1000 * speed;
-
- let remainingDistance = distanceTraveled;
- let currentSegmentIndex = 0;
-
- while (currentSegmentIndex < distances.length && remainingDistance > distances[currentSegmentIndex]) {
- remainingDistance -= distances[currentSegmentIndex];
- currentSegmentIndex++;
- }
-
- if (currentSegmentIndex >= distances.length) {
- removeMesh(meshId);
- return;
- }
-
- const progress = remainingDistance / distances[currentSegmentIndex];
- const start = points[currentSegmentIndex].position;
- const end = points[currentSegmentIndex + 1].position;
-
- meshRef.current.position.lerpVectors(start, end, Math.min(progress, 1));
-
- const startRotation = points[currentSegmentIndex].rotation;
- const endRotation = points[currentSegmentIndex + 1].rotation;
- const interpolatedRotation = new THREE.Quaternion().slerpQuaternions(startRotation, endRotation, Math.min(progress, 1));
-
- meshRef.current.quaternion.copy(interpolatedRotation);
- });
-
- return (
- <>
- {points && points.length > 0 &&
-
-
-
- }
- >
- );
-}
\ No newline at end of file
diff --git a/app/src/modules/simulation/simulationtemp/process/processCreator.tsx b/app/src/modules/simulation/simulationtemp/process/processCreator.tsx
deleted file mode 100644
index 1c5241d..0000000
--- a/app/src/modules/simulation/simulationtemp/process/processCreator.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from 'react'
-
-function ProcessCreator() {
- return (
- <>>
- )
-}
-
-export default ProcessCreator
\ No newline at end of file
diff --git a/app/src/modules/simulation/simulationtemp/simulation.tsx b/app/src/modules/simulation/simulationtemp/simulation.tsx
deleted file mode 100644
index 1c7847b..0000000
--- a/app/src/modules/simulation/simulationtemp/simulation.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import React, { useState } from 'react';
-import * as THREE from 'three';
-import PathCreator from './path/pathCreator';
-import PathFlow from './path/pathFlow';
-
-type PathPoint = {
- position: THREE.Vector3;
- rotation: THREE.Quaternion;
- uuid: string;
-};
-
-function Simulation() {
- const [simulationStates, setSimulationStates] = useState<{ position: THREE.Vector3; rotation: THREE.Quaternion; uuid: string }[][]>([]);
- const [connections, setConnections] = useState<{ start: PathPoint; end: PathPoint }[]>([]);
-
- return (
- <>
-
- {simulationStates.map((path, index) => (
-
- ))}
- >
- );
-}
-
-export default Simulation;
\ No newline at end of file
diff --git a/app/src/modules/simulation/staticMachine/staticMachine.tsx b/app/src/modules/simulation/staticMachine/staticMachine.tsx
deleted file mode 100644
index 3f61993..0000000
--- a/app/src/modules/simulation/staticMachine/staticMachine.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import React, { useEffect } from 'react'
-import * as SimulationTypes from '../../../types/simulationTypes';
-import { useSimulationStates } from '../../../store/store';
-import StaticMachineInstances from './staticMachineInstances';
-import { useResetButtonStore } from '../../../store/usePlayButtonStore';
-
-interface ArmBotState {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- status: string;
- material: string;
- triggerId: string;
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
- isActive?: boolean;
-}
-interface StaticMachineState {
- uuid: string;
- status: string;
- actions: { uuid: string; name: string; buffer: number; material: string; };
- machineTriggerId: string;
- connectedArmBot: string;
-}
-
-type StaticMachineProps = {
- setArmBots: React.Dispatch>;
- staticMachines: StaticMachineState[];
- setStaticMachines: React.Dispatch>;
-}
-
-function StaticMachine({ setArmBots, staticMachines, setStaticMachines }: StaticMachineProps) {
-
- const { simulationStates } = useSimulationStates();
- const { isReset } = useResetButtonStore();
-
- useEffect(() => {
- const filtered = simulationStates.filter((s): s is SimulationTypes.StaticMachineEventsSchema => s.type === "StaticMachine");
- const initialStates: StaticMachineState[] = filtered
- .filter(machine => machine.points.connections.targets.length > 0)
- .map(machine => ({
- uuid: machine.modeluuid,
- status: "idle",
- actions: machine.points.actions,
- machineTriggerId: machine.points.triggers.uuid,
- connectedArmBot: machine.points.connections.targets[0].modelUUID
- }));
- setStaticMachines(initialStates);
- }, [simulationStates, isReset]);
-
- const updateArmBotTriggerAndMachineStatus = (armBotUuid: string, triggerId: string, machineId: string) => {
- setArmBots((prevArmBots) => {
- return prevArmBots.map(bot => {
- if (bot.uuid === armBotUuid) {
- return { ...bot, triggerId: triggerId };
- }
- return bot;
- });
- });
- setStaticMachines((prevStaticMachines) => {
- return prevStaticMachines.map(machine => {
- if (machine.uuid === machineId) {
- return { ...machine, status: "idle" };
- } else {
- return machine;
- }
- });
- });
- }
-
- return (
- <>
- {staticMachines.map((machine, index) => (
-
- ))}
- >
- )
-}
-
-export default StaticMachine;
\ No newline at end of file
diff --git a/app/src/modules/simulation/staticMachine/staticMachineInstances.tsx b/app/src/modules/simulation/staticMachine/staticMachineInstances.tsx
deleted file mode 100644
index 94a2faa..0000000
--- a/app/src/modules/simulation/staticMachine/staticMachineInstances.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import React, { useEffect } from 'react'
-import { useAnimationPlaySpeed } from '../../../store/usePlayButtonStore';
-
-interface StaticMachineState {
- uuid: string;
- status: string;
- actions: { uuid: string; name: string; buffer: number; material: string; };
- machineTriggerId: string;
- connectedArmBot: string;
-}
-
-type StaticMachineInstancesProps = {
- machine: StaticMachineState,
- updateArmBotTriggerAndMachineStatus: (armBotUuid: string, triggerId: string, machineId: string) => void;
-}
-
-function StaticMachineInstances({ machine, updateArmBotTriggerAndMachineStatus }: StaticMachineInstancesProps) {
- const { speed } = useAnimationPlaySpeed();
-
- useEffect(() => {
- if (machine.status === 'running') {
- setTimeout(() => {
- updateArmBotTriggerAndMachineStatus(machine.connectedArmBot, machine.machineTriggerId, machine.uuid);
- }, machine.actions.buffer * 1000 * speed);
- }
- }, [machine])
-
- return (
- <>>
- )
-}
-
-export default StaticMachineInstances
\ No newline at end of file
diff --git a/app/src/modules/visualization/RealTimeVisulization.tsx b/app/src/modules/visualization/RealTimeVisulization.tsx
index e039592..e341fcd 100644
--- a/app/src/modules/visualization/RealTimeVisulization.tsx
+++ b/app/src/modules/visualization/RealTimeVisulization.tsx
@@ -3,7 +3,7 @@ import { usePlayButtonStore } from "../../store/usePlayButtonStore";
import Panel from "./widgets/panel/Panel";
import AddButtons from "./widgets/panel/AddButtons";
import { useSelectedZoneStore } from "../../store/useZoneStore";
-import DisplayZone from "./DisplayZone";
+import DisplayZone from "./zone/DisplayZone";
import Scene from "../scene/scene";
import useModuleStore from "../../store/useModuleStore";
@@ -17,10 +17,10 @@ import {
useWidgetSubOption,
useZones,
} from "../../store/store";
-import { getZone2dData } from "../../services/realTimeVisulization/zoneData/getZoneData";
+import { getZone2dData } from "../../services/visulization/zone/getZoneData";
import { generateUniqueId } from "../../functions/generateUniqueId";
import { determinePosition } from "./functions/determinePosition";
-import { addingFloatingWidgets } from "../../services/realTimeVisulization/zoneData/addFloatingWidgets";
+import { addingFloatingWidgets } from "../../services/visulization/zone/addFloatingWidgets";
import SocketRealTimeViz from "./socket/realTimeVizSocket.dev";
import RenderOverlay from "../../components/templates/Overlay";
import ConfirmationPopup from "../../components/layout/confirmationPopup/ConfirmationPopup";
@@ -31,7 +31,6 @@ import {
useRightClickSelected,
useRightSelected,
} from "../../store/useZone3DWidgetStore";
-import Dropped3dWidgets from "./widgets/3d/Dropped3dWidget";
import OuterClick from "../../utils/outerClick";
import { useWidgetStore } from "../../store/useWidgetStore";
import { getActiveProperties } from "./functions/getActiveProperties";
diff --git a/app/src/modules/scene/mqttTemp/drieHtmlTemp.tsx b/app/src/modules/visualization/mqttTemp/drieHtmlTemp.tsx
similarity index 96%
rename from app/src/modules/scene/mqttTemp/drieHtmlTemp.tsx
rename to app/src/modules/visualization/mqttTemp/drieHtmlTemp.tsx
index 68c8c37..8604bcc 100644
--- a/app/src/modules/scene/mqttTemp/drieHtmlTemp.tsx
+++ b/app/src/modules/visualization/mqttTemp/drieHtmlTemp.tsx
@@ -1,109 +1,109 @@
-import { Html } from "@react-three/drei";
-import * as THREE from "three";
-import * as Types from "../../../types/world/worldTypes";
-import { useDrieTemp, useDrieUIValue } from "../../../store/store"
-import UI from "./ui";
-import { useEffect } from "react";
-import { useThree } from "@react-three/fiber";
-
-export default function DrieHtmlTemp({ itemsGroup }: { itemsGroup: Types.RefGroup }) {
- const { drieTemp, setDrieTemp } = useDrieTemp();
- const { drieUIValue, setDrieUIValue } = useDrieUIValue();
- const state = useThree();
- const { camera, raycaster } = state;
-
- useEffect(() => {
- const canvasElement = state.gl.domElement;
- let drag = false;
- let isLeftMouseDown = false;
-
- const onMouseDown = (evt: any) => {
- if (evt.button === 0) {
- isLeftMouseDown = true;
- drag = false;
- }
- };
-
- const onMouseMove = () => {
- if (isLeftMouseDown) {
- drag = true;
- }
- };
-
- const onMouseUp = (evt: any) => {
- if (evt.button === 0) {
- isLeftMouseDown = false;
- if (drag) return;
- if (!itemsGroup.current) return
- let intersects = raycaster.intersectObjects(itemsGroup.current.children, true);
- if (intersects.length > 0) {
- let currentObject = intersects[0].object;
-
- while (currentObject) {
- if (currentObject.name === "Scene") {
- break;
- }
- currentObject = currentObject.parent as THREE.Object3D;
- }
- if (currentObject && (currentObject.userData.name === "SV2 Controll pannel" || currentObject.userData.name === "forklift")) {
- const worldPos = new THREE.Vector3();
- currentObject.getWorldPosition(worldPos);
-
- const rightOffset = new THREE.Vector3(1, 0, 0);
- const upOffset = new THREE.Vector3(0, 1, 0);
-
- currentObject.localToWorld(rightOffset);
- currentObject.localToWorld(upOffset);
-
- const finalPosition = worldPos.clone().addScaledVector(rightOffset.sub(currentObject.position).normalize(), 2.5).addScaledVector(upOffset.sub(currentObject.position).normalize(), 2.3);
-
- setDrieTemp(finalPosition);
- } else {
- setDrieTemp(undefined);
- }
- }
- else {
- setDrieTemp(undefined);
- }
- }
- };
-
-
- canvasElement.addEventListener("mousedown", onMouseDown);
- canvasElement.addEventListener("mouseup", onMouseUp);
- canvasElement.addEventListener("mousemove", onMouseMove);
-
- return () => {
- canvasElement.removeEventListener("mousedown", onMouseDown);
- canvasElement.removeEventListener("mouseup", onMouseUp);
- canvasElement.removeEventListener("mousemove", onMouseMove);
- };
- }, [])
-
- return (
- <>
- {drieTemp &&
-
-
-
-
-
- }
- >
- )
+import { Html } from "@react-three/drei";
+import * as THREE from "three";
+import * as Types from "../../../types/world/worldTypes";
+import { useDrieTemp, useDrieUIValue } from "../../../store/store"
+import UI from "./ui";
+import { useEffect } from "react";
+import { useThree } from "@react-three/fiber";
+
+export default function DrieHtmlTemp({ itemsGroup }: { itemsGroup: Types.RefGroup }) {
+ const { drieTemp, setDrieTemp } = useDrieTemp();
+ const { drieUIValue, setDrieUIValue } = useDrieUIValue();
+ const state = useThree();
+ const { camera, raycaster } = state;
+
+ useEffect(() => {
+ const canvasElement = state.gl.domElement;
+ let drag = false;
+ let isLeftMouseDown = false;
+
+ const onMouseDown = (evt: any) => {
+ if (evt.button === 0) {
+ isLeftMouseDown = true;
+ drag = false;
+ }
+ };
+
+ const onMouseMove = () => {
+ if (isLeftMouseDown) {
+ drag = true;
+ }
+ };
+
+ const onMouseUp = (evt: any) => {
+ if (evt.button === 0) {
+ isLeftMouseDown = false;
+ if (drag) return;
+ if (!itemsGroup.current) return
+ let intersects = raycaster.intersectObjects(itemsGroup.current.children, true);
+ if (intersects.length > 0) {
+ let currentObject = intersects[0].object;
+
+ while (currentObject) {
+ if (currentObject.name === "Scene") {
+ break;
+ }
+ currentObject = currentObject.parent as THREE.Object3D;
+ }
+ if (currentObject && (currentObject.userData.name === "SV2 Controll pannel" || currentObject.userData.name === "forklift")) {
+ const worldPos = new THREE.Vector3();
+ currentObject.getWorldPosition(worldPos);
+
+ const rightOffset = new THREE.Vector3(1, 0, 0);
+ const upOffset = new THREE.Vector3(0, 1, 0);
+
+ currentObject.localToWorld(rightOffset);
+ currentObject.localToWorld(upOffset);
+
+ const finalPosition = worldPos.clone().addScaledVector(rightOffset.sub(currentObject.position).normalize(), 2.5).addScaledVector(upOffset.sub(currentObject.position).normalize(), 2.3);
+
+ setDrieTemp(finalPosition);
+ } else {
+ setDrieTemp(undefined);
+ }
+ }
+ else {
+ setDrieTemp(undefined);
+ }
+ }
+ };
+
+
+ canvasElement.addEventListener("mousedown", onMouseDown);
+ canvasElement.addEventListener("mouseup", onMouseUp);
+ canvasElement.addEventListener("mousemove", onMouseMove);
+
+ return () => {
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ };
+ }, [])
+
+ return (
+ <>
+ {drieTemp &&
+
+
+
+
+
+ }
+ >
+ )
}
\ No newline at end of file
diff --git a/app/src/modules/scene/mqttTemp/ui.jsx b/app/src/modules/visualization/mqttTemp/ui.jsx
similarity index 97%
rename from app/src/modules/scene/mqttTemp/ui.jsx
rename to app/src/modules/visualization/mqttTemp/ui.jsx
index 4d4c5fb..cafff38 100644
--- a/app/src/modules/scene/mqttTemp/ui.jsx
+++ b/app/src/modules/visualization/mqttTemp/ui.jsx
@@ -1,141 +1,141 @@
-export default function UI({ temperature, humidity, touch, header }) {
- return (
-
-
- {header ? header : "Sensor Details"}
-
-
-
-
-
- Temperature
-
-
- {temperature}
-
-
-
-
-
- Humidity
-
-
- {humidity}
-
-
-
-
-
-
- Touch Sensor
-
-
- {touch === "True" ? "Active" : "In active"}
-
-
-
-
- );
-}
+export default function UI({ temperature, humidity, touch, header }) {
+ return (
+
+
+ {header ? header : "Sensor Details"}
+
+
+
+
+
+ Temperature
+
+
+ {temperature}
+
+
+
+
+
+ Humidity
+
+
+ {humidity}
+
+
+
+
+
+
+ Touch Sensor
+
+
+ {touch === "True" ? "Active" : "In active"}
+
+
+
+
+ );
+}
diff --git a/app/src/modules/visualization/template/Templates.tsx b/app/src/modules/visualization/template/Templates.tsx
index 8370112..59a38ce 100644
--- a/app/src/modules/visualization/template/Templates.tsx
+++ b/app/src/modules/visualization/template/Templates.tsx
@@ -2,7 +2,7 @@ import { useEffect } from "react";
import useTemplateStore from "../../../store/useTemplateStore";
import { useSelectedZoneStore } from "../../../store/useZoneStore";
import { useSocketStore } from "../../../store/store";
-import { getTemplateData } from "../../../services/realTimeVisulization/zoneData/getTemplate";
+import { getTemplateData } from "../../../services/visulization/zone/getTemplate";
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
import RenameInput from "../../../components/ui/inputs/RenameInput";
diff --git a/app/src/modules/visualization/visualization.tsx b/app/src/modules/visualization/visualization.tsx
new file mode 100644
index 0000000..36c5537
--- /dev/null
+++ b/app/src/modules/visualization/visualization.tsx
@@ -0,0 +1,22 @@
+import React from 'react'
+import Dropped3dWidgets from './widgets/3d/Dropped3dWidget'
+import ZoneCentreTarget from './zone/zoneCameraTarget'
+import ZoneAssets from './zone/zoneAssets'
+// import MqttEvents from '../../services/factoryBuilder/mqtt/mqttEvents'
+
+const Visualization = () => {
+ return (
+ <>
+
+
+
+ {/*
+
+
+
+ */}
+ >
+ )
+}
+
+export default Visualization;
\ No newline at end of file
diff --git a/app/src/modules/visualization/widgets/2d/DraggableWidget.tsx b/app/src/modules/visualization/widgets/2d/DraggableWidget.tsx
index f865719..ca70d45 100644
--- a/app/src/modules/visualization/widgets/2d/DraggableWidget.tsx
+++ b/app/src/modules/visualization/widgets/2d/DraggableWidget.tsx
@@ -13,8 +13,6 @@ import {
KebabIcon,
} from "../../../../components/icons/ExportCommonIcons";
import { useEffect, useRef, useState } from "react";
-import { duplicateWidgetApi } from "../../../../services/realTimeVisulization/zoneData/duplicateWidget";
-import { deleteWidgetApi } from "../../../../services/realTimeVisulization/zoneData/deleteWidgetApi";
import { useClickOutside } from "../../functions/handleWidgetsOuterClick";
import { useSocketStore } from "../../../../store/store";
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
diff --git a/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx b/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx
index 6acc994..c094109 100644
--- a/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx
+++ b/app/src/modules/visualization/widgets/3d/Dropped3dWidget.tsx
@@ -7,7 +7,7 @@ import { ThreeState } from "../../../../types/world/worldTypes";
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
import { useEditWidgetOptionsStore, useLeftData, useRightClickSelected, useRightSelected, useTopData, useZoneWidgetStore } from "../../../../store/useZone3DWidgetStore";
import { use3DWidget } from "../../../../store/useDroppedObjectsStore";
-import { get3dWidgetZoneData } from "../../../../services/realTimeVisulization/zoneData/get3dWidgetData";
+import { get3dWidgetZoneData } from "../../../../services/visulization/zone/get3dWidgetData";
import { generateUniqueId } from "../../../../functions/generateUniqueId";
import ProductionCapacity from "./cards/ProductionCapacity";
import ReturnOfInvestment from "./cards/ReturnOfInvestment";
@@ -16,10 +16,6 @@ import Throughput from "./cards/Throughput";
import { useWidgetStore } from "../../../../store/useWidgetStore";
import useChartStore from "../../../../store/useChartStore";
-
-
-
-
type WidgetData = {
id: string;
type: string;
diff --git a/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx b/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx
index cfe29aa..1121e27 100644
--- a/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx
+++ b/app/src/modules/visualization/widgets/floating/DroppedFloatingWidgets.tsx
@@ -7,14 +7,14 @@ import {
import useModuleStore from "../../../../store/useModuleStore";
import { determinePosition } from "../../functions/determinePosition";
import { getActiveProperties } from "../../functions/getActiveProperties";
-import { addingFloatingWidgets } from "../../../../services/realTimeVisulization/zoneData/addFloatingWidgets";
+import { addingFloatingWidgets } from "../../../../services/visulization/zone/addFloatingWidgets";
import {
DublicateIcon,
KebabIcon,
DeleteIcon,
} from "../../../../components/icons/ExportCommonIcons";
import DistanceLines from "./DistanceLines"; // Import the DistanceLines component
-import { deleteFloatingWidgetApi } from "../../../../services/realTimeVisulization/zoneData/deleteFloatingWidget";
+import { deleteFloatingWidgetApi } from "../../../../services/visulization/zone/deleteFloatingWidget";
import TotalCardComponent from "./cards/TotalCardComponent";
import WarehouseThroughputComponent from "./cards/WarehouseThroughputComponent";
diff --git a/app/src/modules/visualization/widgets/panel/AddButtons.tsx b/app/src/modules/visualization/widgets/panel/AddButtons.tsx
index 5d45d3f..d066cd4 100644
--- a/app/src/modules/visualization/widgets/panel/AddButtons.tsx
+++ b/app/src/modules/visualization/widgets/panel/AddButtons.tsx
@@ -6,8 +6,8 @@ import {
} from "../../../../components/icons/RealTimeVisulationIcons";
import { AddIcon } from "../../../../components/icons/ExportCommonIcons";
import { useSocketStore } from "../../../../store/store";
-import { clearPanel } from "../../../../services/realTimeVisulization/zoneData/clearPanel";
-import { lockPanel } from "../../../../services/realTimeVisulization/zoneData/lockPanel";
+import { clearPanel } from "../../../../services/visulization/zone/clearPanel";
+import { lockPanel } from "../../../../services/visulization/zone/lockPanel";
// Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right";
diff --git a/app/src/modules/visualization/DisplayZone.tsx b/app/src/modules/visualization/zone/DisplayZone.tsx
similarity index 92%
rename from app/src/modules/visualization/DisplayZone.tsx
rename to app/src/modules/visualization/zone/DisplayZone.tsx
index e2f3b2f..66fdba2 100644
--- a/app/src/modules/visualization/DisplayZone.tsx
+++ b/app/src/modules/visualization/zone/DisplayZone.tsx
@@ -1,18 +1,18 @@
import React, { useEffect, useRef, useState, useCallback } from "react";
-import { useWidgetStore, Widget } from "../../store/useWidgetStore";
+import { useWidgetStore, Widget } from "../../../store/useWidgetStore";
import {
useDroppedObjectsStore,
useFloatingWidget,
-} from "../../store/useDroppedObjectsStore";
-import { getSelect2dZoneData } from "../../services/realTimeVisulization/zoneData/getSelect2dZoneData";
-import { getFloatingZoneData } from "../../services/realTimeVisulization/zoneData/getFloatingData";
-import { get3dWidgetZoneData } from "../../services/realTimeVisulization/zoneData/get3dWidgetData";
+} from "../../../store/useDroppedObjectsStore";
+import { getSelect2dZoneData } from "../../../services/visulization/zone/getSelect2dZoneData";
+import { getFloatingZoneData } from "../../../services/visulization/zone/getFloatingData";
+import { get3dWidgetZoneData } from "../../../services/visulization/zone/get3dWidgetData";
import {
MoveArrowLeft,
MoveArrowRight,
-} from "../../components/icons/SimulationIcons";
-import { InfoIcon } from "../../components/icons/ExportCommonIcons";
+} from "../../../components/icons/SimulationIcons";
+import { InfoIcon } from "../../../components/icons/ExportCommonIcons";
// Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right";
diff --git a/app/src/modules/visualization/zoneAssets.tsx b/app/src/modules/visualization/zone/zoneAssets.tsx
similarity index 89%
rename from app/src/modules/visualization/zoneAssets.tsx
rename to app/src/modules/visualization/zone/zoneAssets.tsx
index 7a48196..af8b849 100644
--- a/app/src/modules/visualization/zoneAssets.tsx
+++ b/app/src/modules/visualization/zone/zoneAssets.tsx
@@ -1,8 +1,8 @@
import React, { useEffect, useRef } from 'react'
-import { useSelectedFloorItem, useZoneAssetId } from '../../store/store';
+import { useSelectedFloorItem, useZoneAssetId } from '../../../store/store';
import * as THREE from "three";
import { useThree } from '@react-three/fiber';
-import * as Types from "../../types/world/worldTypes";
+import * as Types from "../../../types/world/worldTypes";
export default function ZoneAssets() {
const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
const { setSelectedFloorItem } = useSelectedFloorItem();
@@ -10,7 +10,6 @@ export default function ZoneAssets() {
useEffect(() => {
// console.log('zoneAssetId: ', zoneAssetId);
if (!zoneAssetId) return
- console.log('zoneAssetId: ', zoneAssetId);
let AssetMesh = scene.getObjectByProperty("uuid", zoneAssetId.id);
if (AssetMesh) {
const bbox = new THREE.Box3().setFromObject(AssetMesh);
@@ -30,20 +29,17 @@ export default function ZoneAssets() {
setSelectedFloorItem(AssetMesh);
} else {
- console.log('zoneAssetId: ', zoneAssetId)
if (Array.isArray(zoneAssetId.position) && zoneAssetId.position.length >= 3) {
let selectedAssetPosition = [
zoneAssetId.position[0],
10,
zoneAssetId.position[2]
];
- console.log('selectedAssetPosition: ', selectedAssetPosition);
let selectedAssetTarget = [
zoneAssetId.position[0],
zoneAssetId.position[1],
zoneAssetId.position[2]
];
- console.log('selectedAssetTarget: ', selectedAssetTarget);
const setCam = async () => {
await controls?.setLookAt(...selectedAssetPosition, ...selectedAssetTarget, true);
setTimeout(() => {
diff --git a/app/src/modules/visualization/functions/zoneCameraTarget.tsx b/app/src/modules/visualization/zone/zoneCameraTarget.tsx
similarity index 100%
rename from app/src/modules/visualization/functions/zoneCameraTarget.tsx
rename to app/src/modules/visualization/zone/zoneCameraTarget.tsx
diff --git a/app/src/services/factoryBuilder/assest/floorAsset/setEventsApt.ts b/app/src/services/factoryBuilder/assest/floorAsset/setEventsApt.ts
deleted file mode 100644
index b419963..0000000
--- a/app/src/services/factoryBuilder/assest/floorAsset/setEventsApt.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const setEventApi = async (
- organization: string,
- modeluuid: string,
- eventData: any
-) => {
- try {
- const body: any = { organization, modeluuid, eventData };
-
- const response = await fetch(`${url_Backend_dwinzo}/api/v2/eventDataUpdate`, {
- method: "PATCH",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify(body),
- });
-
- if (!response.ok) {
- throw new Error("Failed to set or Update Event Data");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- if (error instanceof Error) {
- throw new Error(error.message);
- } else {
- throw new Error("An unknown error occurred");
- }
- }
-};
\ No newline at end of file
diff --git a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts
index 3e156cb..d587f06 100644
--- a/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts
+++ b/app/src/services/factoryBuilder/assest/floorAsset/setFloorItemApi.ts
@@ -8,13 +8,9 @@ export const setFloorItemApi = async (
rotation?: Object,
isLocked?: boolean,
isVisible?: boolean,
- eventData?: any
) => {
try {
const body: any = { organization, modeluuid, modelname, position, rotation, modelfileID, isLocked, isVisible };
- if (eventData) {
- body.eventData = eventData;
- }
const response = await fetch(`${url_Backend_dwinzo}/api/v2/setasset`, {
method: "POST",
diff --git a/app/src/services/simulation/getAssetEventType.ts b/app/src/services/simulation/getAssetEventType.ts
deleted file mode 100644
index 84433ec..0000000
--- a/app/src/services/simulation/getAssetEventType.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const getAssetEventType = async (modelId: string, organization: string) => {
- try {
- const response = await fetch(`${url_Backend_dwinzo}/api/v2/pointData/${modelId}/${organization}`, {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- },
- });
-
- if (!response.ok) {
- throw new Error("Failed to fetch model event type");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- if (error instanceof Error) {
- throw new Error(error.message);
- } else {
- throw new Error("An unknown error occurred");
- }
- }
-};
\ No newline at end of file
diff --git a/app/src/modules/builder/temp.md b/app/src/services/simulation/temp.md
similarity index 100%
rename from app/src/modules/builder/temp.md
rename to app/src/services/simulation/temp.md
diff --git a/app/src/services/temp.md b/app/src/services/temp.md
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/modules/simulation/temp.md b/app/src/services/visulization/temp.md
similarity index 100%
rename from app/src/modules/simulation/temp.md
rename to app/src/services/visulization/temp.md
diff --git a/app/src/services/realTimeVisulization/zoneData/add3dWidget.ts b/app/src/services/visulization/zone/add3dWidget.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/add3dWidget.ts
rename to app/src/services/visulization/zone/add3dWidget.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/addFloatingWidgets.ts b/app/src/services/visulization/zone/addFloatingWidgets.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/addFloatingWidgets.ts
rename to app/src/services/visulization/zone/addFloatingWidgets.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/addWidgets.ts b/app/src/services/visulization/zone/addWidgets.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/addWidgets.ts
rename to app/src/services/visulization/zone/addWidgets.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/clearPanel.ts b/app/src/services/visulization/zone/clearPanel.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/clearPanel.ts
rename to app/src/services/visulization/zone/clearPanel.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/delete3dWidget.ts b/app/src/services/visulization/zone/delete3dWidget.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/delete3dWidget.ts
rename to app/src/services/visulization/zone/delete3dWidget.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/deleteFloatingWidget.ts b/app/src/services/visulization/zone/deleteFloatingWidget.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/deleteFloatingWidget.ts
rename to app/src/services/visulization/zone/deleteFloatingWidget.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/deletePanel.ts b/app/src/services/visulization/zone/deletePanel.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/deletePanel.ts
rename to app/src/services/visulization/zone/deletePanel.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/deleteTemplate.ts b/app/src/services/visulization/zone/deleteTemplate.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/deleteTemplate.ts
rename to app/src/services/visulization/zone/deleteTemplate.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/deleteWidgetApi.ts b/app/src/services/visulization/zone/deleteWidgetApi.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/deleteWidgetApi.ts
rename to app/src/services/visulization/zone/deleteWidgetApi.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/duplicateWidget.ts b/app/src/services/visulization/zone/duplicateWidget.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/duplicateWidget.ts
rename to app/src/services/visulization/zone/duplicateWidget.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/get3dWidgetData.ts b/app/src/services/visulization/zone/get3dWidgetData.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/get3dWidgetData.ts
rename to app/src/services/visulization/zone/get3dWidgetData.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/getFloatingData.ts b/app/src/services/visulization/zone/getFloatingData.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/getFloatingData.ts
rename to app/src/services/visulization/zone/getFloatingData.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/getSelect2dZoneData.ts b/app/src/services/visulization/zone/getSelect2dZoneData.ts
similarity index 85%
rename from app/src/services/realTimeVisulization/zoneData/getSelect2dZoneData.ts
rename to app/src/services/visulization/zone/getSelect2dZoneData.ts
index 00d4dfe..b2c39e9 100644
--- a/app/src/services/realTimeVisulization/zoneData/getSelect2dZoneData.ts
+++ b/app/src/services/visulization/zone/getSelect2dZoneData.ts
@@ -7,7 +7,7 @@ export const getSelect2dZoneData = async (
) => {
try {
const response = await fetch(
- `${url_Backend_dwinzo}/api/v2/ZoneVisualization/${ZoneId}?organization=${organization}`,
+ `${url_Backend_dwinzo}/api/v2/Zone/visualization/${ZoneId}?organization=${organization}`,
{
method: "GET",
headers: {
diff --git a/app/src/services/realTimeVisulization/zoneData/getTemplate.ts b/app/src/services/visulization/zone/getTemplate.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/getTemplate.ts
rename to app/src/services/visulization/zone/getTemplate.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/getZoneData.ts b/app/src/services/visulization/zone/getZoneData.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/getZoneData.ts
rename to app/src/services/visulization/zone/getZoneData.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/getZones.ts b/app/src/services/visulization/zone/getZones.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/getZones.ts
rename to app/src/services/visulization/zone/getZones.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/loadTemplate.ts b/app/src/services/visulization/zone/loadTemplate.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/loadTemplate.ts
rename to app/src/services/visulization/zone/loadTemplate.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/lockPanel.ts b/app/src/services/visulization/zone/lockPanel.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/lockPanel.ts
rename to app/src/services/visulization/zone/lockPanel.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/panel.ts b/app/src/services/visulization/zone/panel.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/panel.ts
rename to app/src/services/visulization/zone/panel.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/saveTempleteApi.ts b/app/src/services/visulization/zone/saveTempleteApi.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/saveTempleteApi.ts
rename to app/src/services/visulization/zone/saveTempleteApi.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/update3dWidget.ts b/app/src/services/visulization/zone/update3dWidget.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/update3dWidget.ts
rename to app/src/services/visulization/zone/update3dWidget.ts
diff --git a/app/src/services/realTimeVisulization/zoneData/zoneCameraUpdation.ts b/app/src/services/visulization/zone/zoneCameraUpdation.ts
similarity index 100%
rename from app/src/services/realTimeVisulization/zoneData/zoneCameraUpdation.ts
rename to app/src/services/visulization/zone/zoneCameraUpdation.ts
diff --git a/app/src/store/store.ts b/app/src/store/store.ts
index 765712b..2165b82 100644
--- a/app/src/store/store.ts
+++ b/app/src/store/store.ts
@@ -1,6 +1,5 @@
import * as THREE from "three";
import * as Types from "../types/world/worldTypes";
-import * as SimulationTypes from "../types/simulationTypes";
import { create } from "zustand";
import { io } from "socket.io-client";
@@ -338,49 +337,6 @@ export const useDrieUIValue = create((set: any) => ({
})),
}));
-export const useDrawMaterialPath = create((set: any) => ({
- drawMaterialPath: false,
- setDrawMaterialPath: (x: any) => set({ drawMaterialPath: x }),
-}));
-
-export const useSelectedActionSphere = create((set: any) => ({
- selectedActionSphere: undefined,
- setSelectedActionSphere: (x: any) => set({ selectedActionSphere: x }),
-}));
-
-export const useSelectedPath = create((set: any) => ({
- selectedPath: undefined,
- setSelectedPath: (x: any) => set({ selectedPath: x }),
-}));
-
-interface SimulationPathsStore {
- simulationStates: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[];
- setSimulationStates: (
- paths: (| SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]
- | ((prev: (| SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[])
- => (| SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[])
- ) => void;
-}
-
-export const useSimulationStates = create((set) => ({
- simulationStates: [],
- setSimulationStates: (paths) =>
- set((state) => ({
- simulationStates:
- typeof paths === "function" ? paths(state.simulationStates) : paths,
- })),
-}));
-
-export const useNavMesh = create((set: any) => ({
- navMesh: null,
- setNavMesh: (x: any) => set({ navMesh: x }),
-}));
-
-export const useIsConnecting = create((set: any) => ({
- isConnecting: false,
- setIsConnecting: (x: any) => set({ isConnecting: x }),
-}));
-
export const useStartSimulation = create((set: any) => ({
startSimulation: false,
setStartSimulation: (x: any) => set({ startSimulation: x }),
@@ -396,14 +352,6 @@ export const useEditingPoint = create((set: any) => ({
setEditingPoint: (x: any) => set({ editingPoint: x }),
}));
-export const usePreviewPosition = create<{
- previewPosition: { x: number; y: number } | null;
- setPreviewPosition: (position: { x: number; y: number } | null) => void;
-}>((set) => ({
- previewPosition: null,
- setPreviewPosition: (position) => set({ previewPosition: position }),
-}));
-
export const usezoneTarget = create((set: any) => ({
zoneTarget: [],
setZoneTarget: (x: any) => set({ zoneTarget: x }),
@@ -421,7 +369,7 @@ interface EditPositionState {
export const useEditPosition = create((set) => ({
Edit: false,
- setEdit: (value) => set({ Edit: value }), // Properly updating the state
+ setEdit: (value) => set({ Edit: value }),
}));
export const useAsset3dWidget = create((set: any) => ({
diff --git a/app/src/store/useDroppedObjectsStore.ts b/app/src/store/useDroppedObjectsStore.ts
index 0c03eec..ded9f0a 100644
--- a/app/src/store/useDroppedObjectsStore.ts
+++ b/app/src/store/useDroppedObjectsStore.ts
@@ -1,5 +1,5 @@
import { create } from "zustand";
-import { addingFloatingWidgets } from "../services/realTimeVisulization/zoneData/addFloatingWidgets";
+import { addingFloatingWidgets } from "../services/visulization/zone/addFloatingWidgets";
import { useSocketStore } from "./store";
import useChartStore from "./useChartStore";
@@ -114,7 +114,7 @@ export const useDroppedObjectsStore = create((set) => ({
// Create a shallow copy of the object with a unique ID and slightly adjusted position
const duplicatedObject: DroppedObject = {
...originalObject,
- Data:{
+ Data: {
measurements: iotMeasurements,
duration: iotDuration,
},
@@ -132,8 +132,8 @@ export const useDroppedObjectsStore = create((set) => ({
: originalObject.position.left,
},
};
- console.log("duplicated object",duplicatedObject);
-
+ console.log("duplicated object", duplicatedObject);
+
let duplicateFloatingWidget = {
organization: organization,
widget: duplicatedObject,
diff --git a/app/src/store/useSimulationStore.ts b/app/src/store/useSimulationStore.ts
index aaa1697..c1d76cd 100644
--- a/app/src/store/useSimulationStore.ts
+++ b/app/src/store/useSimulationStore.ts
@@ -142,7 +142,7 @@ type Store = {
removeEventFromProduct: (productId: string, modelUuid: string) => void;
updateEventInProduct: (productId: string, modelUuid: string, updates: Partial) => void;
- // Point-level actions (for transfer, vehicle, etc.)
+ // Point-level actions
addPointToEvent: (productId: string, modelUuid: string, point: TransferPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema) => void;
removePointFromEvent: (productId: string, modelUuid: string, pointUuid: string) => void;
updatePointInEvent: (
@@ -153,35 +153,25 @@ type Store = {
) => void;
// Action-level actions
- addActionToPoint: (
+ addAction: (
productId: string,
modelUuid: string,
pointUuid: string,
action: TransferPointSchema['actions'][0] | VehiclePointSchema['actions'][0] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['actions'][0] | StoragePointSchema['actions'][0]
) => void;
- removeActionFromPoint: (productId: string, modelUuid: string, pointUuid: string, actionUuid: string) => void;
- updateActionInPoint: (
- productId: string,
- modelUuid: string,
- pointUuid: string,
+ removeAction: (actionUuid: string) => void;
+ updateAction: (
actionUuid: string,
updates: Partial
) => void;
// Trigger-level actions
- addTriggerToAction: (
- productId: string,
- modelUuid: string,
- pointUuid: string,
+ addTrigger: (
actionUuid: string,
trigger: TriggerSchema
) => void;
- removeTriggerFromAction: (productId: string, modelUuid: string, pointUuid: string, actionUuid: string, triggerUuid: string) => void;
- updateTriggerInAction: (
- productId: string,
- modelUuid: string,
- pointUuid: string,
- actionUuid: string,
+ removeTrigger: (triggerUuid: string) => void;
+ updateTrigger: (
triggerUuid: string,
updates: Partial
) => void;
@@ -190,6 +180,8 @@ type Store = {
getProductById: (productId: string) => { productName: string; productId: string; eventsData: EventsSchema[] } | undefined;
getEventByModelUuid: (productId: string, modelUuid: string) => EventsSchema | undefined;
getPointByUuid: (productId: string, modelUuid: string, pointUuid: string) => TransferPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
+ getActionByUuid: (actionUuid: string) => (TransferPointSchema['actions'][0] | VehiclePointSchema['actions'][0] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['actions'][0] | StoragePointSchema['actions'][0]) | undefined;
+ getTriggerByUuid: (triggerUuid: string) => TriggerSchema | undefined;
};
export const useProductStore = create()(
@@ -303,7 +295,7 @@ export const useProductStore = create()(
},
// Action-level actions
- addActionToPoint: (productId, modelUuid, pointUuid, action) => {
+ addAction: (productId, modelUuid, pointUuid, action) => {
set((state) => {
const product = state.products.find(p => p.productId === productId);
if (product) {
@@ -320,115 +312,120 @@ export const useProductStore = create()(
});
},
- removeActionFromPoint: (productId, modelUuid, pointUuid, actionUuid) => {
+ removeAction: (actionUuid) => {
set((state) => {
- const product = state.products.find(p => p.productId === productId);
- if (product) {
- const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
- if (event && 'points' in event) {
- const point = (event as TransferEventSchema).points.find(p => p.uuid === pointUuid);
- if (point) {
- point.actions = point.actions.filter(a => a.actionUuid !== actionUuid);
+ for (const product of state.products) {
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as TransferEventSchema).points) {
+ point.actions = point.actions.filter(a => a.actionUuid !== actionUuid);
+ }
+ } else if ('point' in event) {
+ (event as any).point.actions = (event as any).point.actions.filter((a: any) => a.actionUuid !== actionUuid);
}
- } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
- (event as any).point.actions = (event as any).point.actions.filter((a: any) => a.actionUuid !== actionUuid);
}
}
});
},
- updateActionInPoint: (productId, modelUuid, pointUuid, actionUuid, updates) => {
+ updateAction: (actionUuid, updates) => {
set((state) => {
- const product = state.products.find(p => p.productId === productId);
- if (product) {
- const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
- if (event && 'points' in event) {
- const point = (event as TransferEventSchema).points.find(p => p.uuid === pointUuid);
- if (point) {
- const action = point.actions.find(a => a.actionUuid === actionUuid);
+ for (const product of state.products) {
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as TransferEventSchema).points) {
+ const action = point.actions.find(a => a.actionUuid === actionUuid);
+ if (action) {
+ Object.assign(action, updates);
+ return;
+ }
+ }
+ } else if ('point' in event) {
+ const action = (event as any).point.actions.find((a: any) => a.actionUuid === actionUuid);
if (action) {
Object.assign(action, updates);
+ return;
}
}
- } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
- const action = (event as any).point.actions.find((a: any) => a.actionUuid === actionUuid);
- if (action) {
- Object.assign(action, updates);
- }
}
}
});
},
// Trigger-level actions
- addTriggerToAction: (productId, modelUuid, pointUuid, actionUuid, trigger) => {
+ addTrigger: (actionUuid, trigger) => {
set((state) => {
- const product = state.products.find(p => p.productId === productId);
- if (product) {
- const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
- if (event && 'points' in event) {
- const point = (event as TransferEventSchema).points.find(p => p.uuid === pointUuid);
- if (point) {
- const action = point.actions.find(a => a.actionUuid === actionUuid);
+ for (const product of state.products) {
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as TransferEventSchema).points) {
+ const action = point.actions.find(a => a.actionUuid === actionUuid);
+ if (action && 'triggers' in action) {
+ action.triggers.push(trigger);
+ return;
+ }
+ }
+ } else if ('point' in event) {
+ const action = (event as any).point.actions.find((a: any) => a.actionUuid === actionUuid);
if (action && 'triggers' in action) {
action.triggers.push(trigger);
+ return;
}
}
- } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
- const action = (event as any).point.actions.find((a: any) => a.actionUuid === actionUuid);
- if (action && 'triggers' in action) {
- action.triggers.push(trigger);
- }
}
}
});
},
- removeTriggerFromAction: (productId, modelUuid, pointUuid, actionUuid, triggerUuid) => {
+ removeTrigger: (triggerUuid) => {
set((state) => {
- const product = state.products.find(p => p.productId === productId);
- if (product) {
- const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
- if (event && 'points' in event) {
- const point = (event as TransferEventSchema).points.find(p => p.uuid === pointUuid);
- if (point) {
- const action = point.actions.find(a => a.actionUuid === actionUuid);
- if (action && 'triggers' in action) {
- action.triggers = action.triggers.filter(t => t.triggerUuid !== triggerUuid);
+ for (const product of state.products) {
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as TransferEventSchema).points) {
+ for (const action of point.actions) {
+ if ('triggers' in action) {
+ action.triggers = action.triggers.filter(t => t.triggerUuid !== triggerUuid);
+ }
+ }
}
- }
- } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
- const action = (event as any).point.actions.find((a: any) => a.actionUuid === actionUuid);
- if (action && 'triggers' in action) {
- action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
- }
- }
- }
- });
- },
-
- updateTriggerInAction: (productId, modelUuid, pointUuid, actionUuid, triggerUuid, updates) => {
- set((state) => {
- const product = state.products.find(p => p.productId === productId);
- if (product) {
- const event = product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
- if (event && 'points' in event) {
- const point = (event as TransferEventSchema).points.find(p => p.uuid === pointUuid);
- if (point) {
- const action = point.actions.find(a => a.actionUuid === actionUuid);
- if (action && 'triggers' in action) {
- const trigger = action.triggers.find(t => t.triggerUuid === triggerUuid);
- if (trigger) {
- Object.assign(trigger, updates);
+ } else if ('point' in event) {
+ for (const action of (event as any).point.actions) {
+ if ('triggers' in action) {
+ action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
}
}
}
- } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
- const action = (event as any).point.actions.find((a: any) => a.actionUuid === actionUuid);
- if (action && 'triggers' in action) {
- const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
- if (trigger) {
- Object.assign(trigger, updates);
+ }
+ }
+ });
+ },
+
+ updateTrigger: (triggerUuid, updates) => {
+ set((state) => {
+ for (const product of state.products) {
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as TransferEventSchema).points) {
+ for (const action of point.actions) {
+ if ('triggers' in action) {
+ const trigger = action.triggers.find(t => t.triggerUuid === triggerUuid);
+ if (trigger) {
+ Object.assign(trigger, updates);
+ return;
+ }
+ }
+ }
+ }
+ } else if ('point' in event) {
+ for (const action of (event as any).point.actions) {
+ if ('triggers' in action) {
+ const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
+ if (trigger) {
+ Object.assign(trigger, updates);
+ return;
+ }
+ }
}
}
}
@@ -460,6 +457,50 @@ export const useProductStore = create()(
}
}
return undefined;
+ },
+
+ getActionByUuid: (actionUuid) => {
+ const state = get();
+ for (const product of state.products) {
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as TransferEventSchema).points) {
+ const action = point.actions.find(a => a.actionUuid === actionUuid);
+ if (action) return action;
+ }
+ } else if ('point' in event) {
+ const action = (event as any).point.actions.find((a: any) => a.actionUuid === actionUuid);
+ if (action) return action;
+ }
+ }
+ }
+ return undefined;
+ },
+
+ getTriggerByUuid: (triggerUuid) => {
+ const state = get();
+ for (const product of state.products) {
+ for (const event of product.eventsData) {
+ if ('points' in event) {
+ for (const point of (event as TransferEventSchema).points) {
+ for (const action of point.actions) {
+ if ('triggers' in action) {
+ const trigger = action.triggers.find(t => t.triggerUuid === triggerUuid);
+ if (trigger) return trigger;
+ }
+ }
+ }
+ } else if ('point' in event) {
+ for (const action of (event as any).point.actions) {
+ if ('triggers' in action) {
+ const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
+ if (trigger) return trigger;
+ }
+ }
+ }
+ }
+ }
+ return undefined;
}
}))
);
\ No newline at end of file
diff --git a/app/src/types/simulationTypes.d.ts b/app/src/types/simulationTypes.d.ts
index e21d52f..0e30be4 100644
--- a/app/src/types/simulationTypes.d.ts
+++ b/app/src/types/simulationTypes.d.ts
@@ -94,75 +94,6 @@ interface ArmBotEventsSchema {
rotation: [number, number, number];
}
-export type EventData = {
- modeluuid: string;
- modelname: string;
- position: [number, number, number];
- rotation: { x: number; y: number; z: number };
- modelfileID: string;
- isLocked: boolean;
- isVisible: boolean;
- eventData?:
- {
- type: "Conveyor";
- points: {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean; }[] | [];
- triggers: { uuid: string; name: string; type: string; isUsed: boolean; bufferTime: number; }[] | [];
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- }[];
- speed: number | string;
- }
- | {
- type: "Vehicle";
- points: {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- actions: { uuid: string; name: string; type: string; start: { x: number; y: number } | {}; hitCount: number; end: { x: number; y: number } | {}; buffer: number; };
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- speed: number;
- };
- }
- | {
- type: "StaticMachine";
- points: {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- actions: { uuid: string; name: string; buffer: number; material: string; };
- triggers: { uuid: string; name: string; type: string };
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- };
- }
- | {
- type: "ArmBot";
- points: {
- uuid: string;
- position: [number, number, number];
- rotation: [number, number, number];
- actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string; }[]; };
- triggers: { uuid: string; name: string; type: string };
- connections: {
- source: { modelUUID: string; pointUUID: string };
- targets: { modelUUID: string; pointUUID: string }[];
- };
- };
- };
-};
-
-
interface AssetEventSchema {
modelUuid: string;
modelName: string;