@@ -258,14 +253,14 @@ function VehicleMechanics() {
{activeOption === "travel" && (
+
+
+
+
>
)}
@@ -289,4 +321,4 @@ function VehicleMechanics() {
);
}
-export default VehicleMechanics;
+export default VehicleMechanics;
\ No newline at end of file
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx
index eb4b0ac..0697c7b 100644
--- a/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx
+++ b/app/src/components/layout/sidebarRight/properties/eventProperties/trigger/Trigger.tsx
@@ -65,8 +65,11 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
const action = getActionByUuid(selectedProduct.productUuid, currentAction);
const actionTriggers = action?.triggers || [];
setTriggers(actionTriggers);
+ if (actionTriggers.length === 0) {
+ setSelectedTrigger(undefined);
+ }
setSelectedTrigger(actionTriggers[0]);
- }, [currentAction, selectedProduct]);
+ }, [currentAction, selectedProduct, selectedTrigger, selectedPointData]);
const triggeredModel = useMemo(() => {
if (!selectedProduct || !selectedTrigger?.triggeredAsset?.triggeredModel?.modelUuid)
diff --git a/app/src/components/ui/Tools.tsx b/app/src/components/ui/Tools.tsx
index 1aeb646..e834f28 100644
--- a/app/src/components/ui/Tools.tsx
+++ b/app/src/components/ui/Tools.tsx
@@ -22,7 +22,6 @@ import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
import {
useActiveTool,
useAddAction,
- useRefTextUpdate,
useSelectedWallItem,
useSocketStore,
useToggleView,
@@ -75,7 +74,6 @@ const Tools: React.FC = () => {
const { setActiveSubTool, activeSubTool } = useActiveSubTool();
const { setSelectedWallItem } = useSelectedWallItem();
- const { setRefTextUpdate } = useRefTextUpdate();
const { setToggleUI } = useToggleStore();
const { setToggleView, toggleView } = useToggleView();
@@ -131,7 +129,6 @@ const Tools: React.FC = () => {
const resetTools = () => {
setToolMode(null);
setAddAction(null);
- setRefTextUpdate((prev) => prev - 1);
};
const updateToolBehavior = (tool: string, is2D: boolean) => {
@@ -406,7 +403,6 @@ const useStoreHooks = () => {
...useActiveTool(),
...useToolMode(),
...useAddAction(),
- ...useRefTextUpdate(),
};
};
diff --git a/app/src/components/ui/inputs/InputWithDropDown.tsx b/app/src/components/ui/inputs/InputWithDropDown.tsx
index 61fbaf4..486faea 100644
--- a/app/src/components/ui/inputs/InputWithDropDown.tsx
+++ b/app/src/components/ui/inputs/InputWithDropDown.tsx
@@ -2,93 +2,89 @@ import React, { useState } from "react";
import RenameInput from "./RenameInput";
type InputWithDropDownProps = {
- label: string;
- value: string;
- min?: number;
- max?: number;
- step?: number;
- defaultValue?: string;
- disabled?: boolean;
- options?: string[]; // Array of dropdown options
- activeOption?: string; // The currently active dropdown option
- onClick?: () => void;
- onChange: (newValue: string) => void;
- editableLabel?: boolean;
- placeholder?: string; // New placeholder prop
+ label: string;
+ value: string;
+ min?: number;
+ max?: number;
+ step?: number;
+ defaultValue?: string;
+ disabled?: boolean;
+ options?: string[];
+ activeOption?: string;
+ onClick?: () => void;
+ onChange: (newValue: string) => void;
+ editableLabel?: boolean;
+ placeholder?: string;
};
const InputWithDropDown: React.FC
= ({
- label,
- value,
- min,
- max,
- step,
- defaultValue,
- disabled = false,
- options,
- activeOption,
- onClick,
- onChange,
- editableLabel = false,
- placeholder = "Inherit", // Default empty placeholder
+ label,
+ value,
+ min,
+ max,
+ step,
+ defaultValue,
+ disabled = false,
+ options,
+ activeOption,
+ onClick,
+ onChange,
+ editableLabel = false,
+ placeholder = "Inherit",
}) => {
- const separatedWords = label
- .split(/(?=[A-Z])/)
- .map((word) => word.trim())
- .toString();
+ const [openDropdown, setOpenDropdown] = useState(false);
- const [openDropdown, setOpenDropdown] = useState(false);
+ const separatedWords = label
+ .split(/(?=[A-Z])/)
+ .map((word) => word.trim())
+ .join(" ");
- return (
-
- {editableLabel ? (
-
- ) : (
-
- )}
-
-
{
- onChange(e.target.value);
- }}
- placeholder={placeholder} // Added placeholder prop
- />
-
- {activeOption && (
-
{
- setOpenDropdown(true);
- }}
- >
-
{activeOption}
- {options && openDropdown && (
-
- {options.map((option, index) => (
-
- {option}
-
- ))}
-
+ return (
+
+ {editableLabel ? (
+
+ ) : (
+
)}
-
- )}
-
-
- );
+
+
+
onChange(e.target.value)}
+ placeholder={placeholder}
+ />
+
+ {activeOption && (
+
setOpenDropdown((prev) => !prev)}
+ >
+
{activeOption}
+ {options && openDropdown && (
+
+ {options.map((option, index) => (
+
+ {option}
+
+ ))}
+
+ )}
+
+ )}
+
+
+ );
};
-export default InputWithDropDown;
\ No newline at end of file
+export default InputWithDropDown;
diff --git a/app/src/components/ui/list/DropDownList.tsx b/app/src/components/ui/list/DropDownList.tsx
index d75387d..b158c80 100644
--- a/app/src/components/ui/list/DropDownList.tsx
+++ b/app/src/components/ui/list/DropDownList.tsx
@@ -2,7 +2,6 @@ import React, { useEffect, useState } from "react";
import List from "./List";
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
-import { useZones } from "../../../store/builder/store";
import { useSceneContext } from "../../../modules/scene/sceneContext";
interface DropDownListProps {
@@ -44,14 +43,12 @@ const DropDownList: React.FC = ({
remove,
}) => {
const [isOpen, setIsOpen] = useState(defaultOpen);
- // const { zones } = useZones();
const handleToggle = () => {
setIsOpen((prev) => !prev); // Toggle the state
};
const [zoneDataList, setZoneDataList] = useState([]);
- // const { assetStore } = useSceneContext();
const { assetStore, zoneStore } = useSceneContext();
const { assets } = assetStore();
const { zones } = zoneStore()
diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx
index dac4b40..fc0f5ec 100644
--- a/app/src/components/ui/list/List.tsx
+++ b/app/src/components/ui/list/List.tsx
@@ -14,7 +14,6 @@ import {
} from "../../icons/ExportCommonIcons";
import {
useZoneAssetId,
- useZones,
} from "../../../store/builder/store";
import { zoneCameraUpdate } from "../../../services/visulization/zone/zoneCameraUpdation";
import { setAssetsApi } from "../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
diff --git a/app/src/components/ui/simulation/simulationPlayer.tsx b/app/src/components/ui/simulation/simulationPlayer.tsx
index 5fc8790..e2ec99f 100644
--- a/app/src/components/ui/simulation/simulationPlayer.tsx
+++ b/app/src/components/ui/simulation/simulationPlayer.tsx
@@ -34,7 +34,7 @@ import { useComparisonProduct } from "../../../store/simulation/useSimulationSto
import InputToggle from "../inputs/InputToggle";
const SimulationPlayer: React.FC = () => {
- const MAX_SPEED = 4; // Maximum speed
+ const MAX_SPEED = 8; // Maximum speed
const isDragging = useRef(false);
const sliderRef = useRef(null);
@@ -109,12 +109,24 @@ const SimulationPlayer: React.FC = () => {
isDragging.current = false;
};
+ const handleVisibility = () => {
+ if (document.visibilityState !== 'visible' && isPlaying) {
+ setIsPaused(!isPaused);
+ if (isPaused) {
+ setIsPlaying(true);
+ }
+ echo.warn(`Simulation is ${isPaused ? "Resumed" : "Paused"}`);
+ }
+ }
+
useEffect(() => {
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
+ document.addEventListener('visibilitychange', handleVisibility);
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
+ document.removeEventListener('visibilitychange', handleVisibility);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx
index f51edf1..a05e423 100644
--- a/app/src/modules/builder/asset/assetsGroup.tsx
+++ b/app/src/modules/builder/asset/assetsGroup.tsx
@@ -139,6 +139,11 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
steeringAngle: 0,
pickUpPoint: null,
unLoadPoint: null,
+ paths: {
+ initPickup: [],
+ pickupDrop: [],
+ dropPickup: [],
+ },
triggers: []
}
}
@@ -256,14 +261,17 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0],
- action: {
- actionUuid: THREE.MathUtils.generateUUID(),
- actionName: "Action 1",
- actionType: "worker",
- loadCapacity: 1,
- triggers: []
- }
-
+ actions: [
+ {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: "Action 1",
+ actionType: "worker",
+ loadCount: 1,
+ loadCapacity: 1,
+ processTime: 10,
+ triggers: []
+ }
+ ]
}
}
addEvent(humanEvent);
diff --git a/app/src/modules/builder/asset/functions/addAssetModel.ts b/app/src/modules/builder/asset/functions/addAssetModel.ts
index 8a09bb7..4b72cd3 100644
--- a/app/src/modules/builder/asset/functions/addAssetModel.ts
+++ b/app/src/modules/builder/asset/functions/addAssetModel.ts
@@ -262,6 +262,11 @@ async function handleModelLoad(
steeringAngle: 0,
pickUpPoint: null,
unLoadPoint: null,
+ paths: {
+ initPickup: [],
+ pickupDrop: [],
+ dropPickup: [],
+ },
triggers: [],
},
},
@@ -373,14 +378,17 @@ async function handleModelLoad(
uuid: THREE.MathUtils.generateUUID(),
position: [data.points[0].x, data.points[0].y, data.points[0].z],
rotation: [0, 0, 0],
- action: {
- actionUuid: THREE.MathUtils.generateUUID(),
- actionName: "Action 1",
- actionType: "worker",
- loadCapacity: 1,
- triggers: []
- }
-
+ actions: [
+ {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: "Action 1",
+ actionType: "worker",
+ loadCount: 1,
+ loadCapacity: 1,
+ processTime: 10,
+ triggers: []
+ }
+ ]
}
}
addEvent(humanEvent);
diff --git a/app/src/modules/builder/asset/models/model/model.tsx b/app/src/modules/builder/asset/models/model/model.tsx
index 4cc4ad5..7c3f580 100644
--- a/app/src/modules/builder/asset/models/model/model.tsx
+++ b/app/src/modules/builder/asset/models/model/model.tsx
@@ -17,7 +17,7 @@ import { useParams } from 'react-router-dom';
import { getUserData } from '../../../../../functions/getUserData';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useVersionContext } from '../../../version/versionContext';
-import { useAnimationPlaySpeed } from '../../../../../store/usePlayButtonStore';
+import { useAnimationPlaySpeed, usePauseButtonStore } from '../../../../../store/usePlayButtonStore';
import { upsertProductOrEventApi } from '../../../../../services/simulation/products/UpsertProductOrEventApi';
import { getAssetIksApi } from '../../../../../services/simulation/ik/getAssetIKs';
import ConveyorCollider from './conveyorCollider';
@@ -31,6 +31,7 @@ function Model({ asset }: { readonly asset: Asset }) {
const { subModule } = useSubModuleStore();
const { activeModule } = useModuleStore();
const { speed } = useAnimationPlaySpeed();
+ const { isPaused } = usePauseButtonStore();
const { assetStore, eventStore, productStore } = useSceneContext();
const { removeAsset, setAnimations, resetAnimation, setAnimationComplete } = assetStore();
const { setTop } = useTopData();
@@ -395,7 +396,7 @@ function Model({ asset }: { readonly asset: Asset }) {
const currentAction = actions.current[current];
const previousAction = previousAnimation ? actions.current[previousAnimation] : null;
- if (isPlaying && currentAction) {
+ if (isPlaying && currentAction && activeModule === 'simulation' && !isPaused) {
blendFactor.current = 0;
currentAction.reset();
@@ -418,7 +419,7 @@ function Model({ asset }: { readonly asset: Asset }) {
mixerRef.current.removeEventListener('finished', handleAnimationComplete);
}
};
- }, [asset.animationState?.current, asset.animationState?.isPlaying]);
+ }, [asset.animationState?.current, asset.animationState?.isCompleted, asset.animationState?.isPlaying, isPaused, activeModule]);
useEffect(() => {
const canvasElement = gl.domElement;
@@ -526,15 +527,7 @@ function Model({ asset }: { readonly asset: Asset }) {
{
- // Option A: Reset the same object
- rigidBody.setTranslation({ x: 0, y: 10, z: 0 }, true);
- rigidBody.setLinvel({ x: 0, y: 0, z: 0 }, true);
- rigidBody.setAngvel({ x: 0, y: 0, z: 0 }, true);
- rigidBody.wakeUp();
-
- // Option B: You can also call a function that sets a state to "add a new rigid body"
- }} />
+ />
>
)}
diff --git a/app/src/modules/builder/dfx/LoadBlueprint.tsx b/app/src/modules/builder/dfx/LoadBlueprint.tsx
index 5763d26..216f2fe 100644
--- a/app/src/modules/builder/dfx/LoadBlueprint.tsx
+++ b/app/src/modules/builder/dfx/LoadBlueprint.tsx
@@ -1,9 +1,8 @@
import { useEffect, useRef } from 'react';
-import { useActiveLayer, useDfxUpload, useSocketStore, useToggleView, useUpdateScene } from '../../../store/builder/store';
+import { useActiveLayer, useDfxUpload, useSocketStore, useToggleView } from '../../../store/builder/store';
import { LineBasicMaterial, Line } from 'three';
import { TransformControls } from '@react-three/drei';
import { getWallPointsFromBlueprint } from './functions/getWallPointsFromBlueprint';
-import * as Types from '../../../types/world/worldTypes';
import { useParams } from 'react-router-dom';
import { getUserData } from '../../../functions/getUserData';
import { useVersionContext } from '../version/versionContext';
diff --git a/app/src/modules/builder/line/line.tsx b/app/src/modules/builder/line/line.tsx
index cc53b9d..a0470aa 100644
--- a/app/src/modules/builder/line/line.tsx
+++ b/app/src/modules/builder/line/line.tsx
@@ -9,6 +9,8 @@ import * as Constants from '../../../types/world/worldConstants';
import { useVersionContext } from '../version/versionContext';
import { useParams } from 'react-router-dom';
import { getUserData } from '../../../functions/getUserData';
+import { handleCanvasCursors } from '../../../utils/mouseUtils/handleCanvasCursors';
+import { useSelectedPoints } from '../../../store/simulation/useSimulationStore';
// import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
// import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
@@ -23,7 +25,7 @@ interface LineProps {
function Line({ points }: Readonly) {
const [isHovered, setIsHovered] = useState(false);
- const { raycaster, camera, pointer, gl } = useThree();
+ const { raycaster, camera, pointer } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const [isDeletable, setIsDeletable] = useState(false);
const { socket } = useSocketStore();
@@ -38,6 +40,7 @@ function Line({ points }: Readonly) {
const { projectId } = useParams();
const [dragOffset, setDragOffset] = useState(null);
const { hoveredLine, setHoveredLine, hoveredPoint } = useBuilderStore();
+ const { selectedPoints } = useSelectedPoints();
const path = useMemo(() => {
const [start, end] = points.map(p => new THREE.Vector3(...p.position));
@@ -213,7 +216,7 @@ function Line({ points }: Readonly) {
});
}
}
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
}
}
@@ -224,7 +227,7 @@ function Line({ points }: Readonly) {
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
- gl.domElement.style.cursor = 'move';
+ handleCanvasCursors('grabbing');
const positionWithOffset = new THREE.Vector3().addVectors(hit, dragOffset);
const start = new THREE.Vector3(...points[0].position);
@@ -269,7 +272,7 @@ function Line({ points }: Readonly) {
const handleDragEnd = (points: [Point, Point]) => {
if (toolMode !== 'move' || !dragOffset) return;
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
setDragOffset(null);
if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
const updatedWalls1 = getWallsByPointId(points[0].pointUuid);
@@ -372,19 +375,21 @@ function Line({ points }: Readonly) {
onClick={() => {
handlePointClick(points);
}}
- onPointerOver={() => {
- if (!hoveredLine) {
+ onPointerOver={(e) => {
+ if (selectedPoints.length === 0 && e.buttons === 0 && !e.ctrlKey) {
setHoveredLine(points);
setIsHovered(true)
if (toolMode === 'move' && !hoveredPoint) {
- gl.domElement.style.cursor = 'pointer';
+ handleCanvasCursors('grab');
}
}
}}
onPointerOut={() => {
- if (hoveredLine) {
+ if (hoveredLine && isHovered) {
setHoveredLine(null);
- gl.domElement.style.cursor = 'default';
+ if (!hoveredPoint) {
+ handleCanvasCursors('default');
+ }
}
setIsHovered(false)
}}
diff --git a/app/src/modules/builder/point/point.tsx b/app/src/modules/builder/point/point.tsx
index 73dec77..5c62dd5 100644
--- a/app/src/modules/builder/point/point.tsx
+++ b/app/src/modules/builder/point/point.tsx
@@ -5,6 +5,7 @@ import { useSocketStore, useToolMode } from '../../../store/builder/store';
import { DragControls } from '@react-three/drei';
import { useThree } from '@react-three/fiber';
import { useBuilderStore } from '../../../store/builder/useBuilderStore';
+import { useSelectedPoints } from '../../../store/simulation/useSimulationStore';
import { usePointSnapping } from './helpers/usePointSnapping';
import { useParams } from 'react-router-dom';
import { useVersionContext } from '../version/versionContext';
@@ -20,12 +21,14 @@ import { useSceneContext } from '../../scene/sceneContext';
// import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
import { getUserData } from '../../../functions/getUserData';
+import { handleCanvasCursors } from '../../../utils/mouseUtils/handleCanvasCursors';
function Point({ point }: { readonly point: Point }) {
const materialRef = useRef(null);
- const { raycaster, camera, pointer, gl } = useThree();
+ const { raycaster, camera, pointer } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const [isHovered, setIsHovered] = useState(false);
+ const [isSelected, setIsSelected] = useState(false);
const [dragOffset, setDragOffset] = useState(null);
const { socket } = useSocketStore();
const { toolMode } = useToolMode();
@@ -35,7 +38,8 @@ function Point({ point }: { readonly point: Point }) {
const { setPosition: setFloorPosition, removePoint: removeFloorPoint, getFloorsByPointId } = floorStore();
const { setPosition: setZonePosition, removePoint: removeZonePoint, getZonesByPointId } = zoneStore();
const { snapAislePoint, snapAisleAngle, snapWallPoint, snapWallAngle, snapFloorPoint, snapFloorAngle, snapZonePoint, snapZoneAngle } = usePointSnapping({ uuid: point.pointUuid, pointType: point.pointType, position: point.position });
- const { hoveredPoint, setHoveredPoint } = useBuilderStore();
+ const { hoveredPoint,hoveredLine, setHoveredPoint } = useBuilderStore();
+ const { selectedPoints } = useSelectedPoints();
const { userId, organization } = getUserData();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
@@ -44,7 +48,7 @@ function Point({ point }: { readonly point: Point }) {
const colors = getColor(point);
useEffect(() => {
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
}, [toolMode])
function getColor(point: Point) {
@@ -114,7 +118,7 @@ function Point({ point }: { readonly point: Point }) {
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
- gl.domElement.style.cursor = 'move';
+ handleCanvasCursors('grabbing');
const positionWithOffset = new THREE.Vector3().addVectors(hit, dragOffset);
const newPosition: [number, number, number] = [positionWithOffset.x, positionWithOffset.y, positionWithOffset.z];
@@ -152,7 +156,7 @@ function Point({ point }: { readonly point: Point }) {
};
const handleDragEnd = (point: Point) => {
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
setDragOffset(null);
if (toolMode !== 'move') return;
if (point.pointType === 'Aisle') {
@@ -396,7 +400,7 @@ function Point({ point }: { readonly point: Point }) {
});
}
}
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
}
}
@@ -406,50 +410,63 @@ function Point({ point }: { readonly point: Point }) {
}
}, [hoveredPoint])
+ useEffect(() => {
+ if (selectedPoints.length > 0 && selectedPoints.some((selectedPoint) => (selectedPoint.userData.pointUuid && selectedPoint.userData.pointUuid === point.pointUuid))) {
+ setIsSelected(true);
+ } else {
+ setIsSelected(false);
+ }
+ }, [selectedPoints])
+
if (!point) {
return null;
}
+
return (
- handleDragStart(point)}
- onDrag={() => handleDrag(point)}
- onDragEnd={() => handleDragEnd(point)}
- >
- {
- handlePointClick(point);
- }}
- onPointerOver={() => {
- if (!hoveredPoint) {
- setHoveredPoint(point);
- setIsHovered(true);
- if (toolMode === 'move') {
- gl.domElement.style.cursor = 'pointer';
- }
- }
- }}
- onPointerOut={() => {
- if (hoveredPoint) {
- setHoveredPoint(null);
- gl.domElement.style.cursor = 'default';
- }
- setIsHovered(false)
- }}
- userData={point}
- >
-
-
+ {!isSelected ?
+ handleDragStart(point)}
+ onDrag={() => handleDrag(point)}
+ onDragEnd={() => handleDragEnd(point)}
+ >
+ {
+ handlePointClick(point);
+ }}
+ onPointerOver={(e) => {
+ if (!hoveredPoint && selectedPoints.length === 0 && e.buttons === 0 && !e.ctrlKey) {
+ setHoveredPoint(point);
+ setIsHovered(true);
+ if (toolMode === 'move') {
+ handleCanvasCursors('grab');
+ }
+ }
+ }}
+ onPointerOut={() => {
+ if (hoveredPoint) {
+ setHoveredPoint(null);
+ if(!hoveredLine){
+ handleCanvasCursors('default');
+ }
+ }
+ setIsHovered(false)
+ }}
+ userData={point}
+ >
+
+
-
-
+ }
+ />
+
+
+ :
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ >
);
}
diff --git a/app/src/modules/builder/wall/Instances/instance/helpers/useWallClassification.ts b/app/src/modules/builder/wall/Instances/instance/helpers/useWallClassification.ts
index bc910b5..8ba211a 100644
--- a/app/src/modules/builder/wall/Instances/instance/helpers/useWallClassification.ts
+++ b/app/src/modules/builder/wall/Instances/instance/helpers/useWallClassification.ts
@@ -85,13 +85,45 @@ export function useWallClassification(walls: Walls) {
}));
}
- const allCoords = mergedLineStrings.flatMap(ls => ls.geometry.coordinates);
- const uniqueCoords = Array.from(new Set(allCoords.map(coord => coord.join(','))));
- if (uniqueCoords.length < 4) return [];
+ const validLineStrings = mergedLineStrings.map(ls => {
+ const coords = ls.geometry.coordinates.map(coord => coord.join(','));
- const lineStrings = turf.featureCollection(mergedLineStrings);
+ if (coords.length < 2) return null;
- const polygons = turf.polygonize(lineStrings);
+ const start = coords[0];
+ const end = coords[coords.length - 1];
+ const middle = coords.slice(1, -1);
+
+ const seen = new Set([start, end]);
+ const filteredMiddle: string[] = [];
+
+ for (const point of middle) {
+ if (!seen.has(point)) {
+ seen.add(point);
+ filteredMiddle.push(point);
+ }
+ }
+
+ const newCoords = [start, ...filteredMiddle, end];
+
+ if (newCoords.length >= 4) {
+ const resultCoords = newCoords.map(str => str.split(',').map(Number));
+ return {
+ ...ls,
+ geometry: {
+ ...ls.geometry,
+ coordinates: resultCoords,
+ },
+ };
+ }
+
+ return null;
+ }).filter(Boolean);
+
+ if (validLineStrings.length === 0) return [];
+
+ const lineStrings = turf.featureCollection(validLineStrings as any);
+ const polygons = turf.polygonize(lineStrings as any);
const rooms: Point[][] = [];
diff --git a/app/src/modules/builder/wall/Instances/instance/wall.tsx b/app/src/modules/builder/wall/Instances/instance/wall.tsx
index 452b69a..a441ea8 100644
--- a/app/src/modules/builder/wall/Instances/instance/wall.tsx
+++ b/app/src/modules/builder/wall/Instances/instance/wall.tsx
@@ -152,9 +152,9 @@ function Wall({ wall }: { readonly wall: Wall }) {
>
- {wall.decals.map((decal) => (
+ {/* {wall.decals.map((decal) => (
- ))}
+ ))} */}
);
diff --git a/app/src/modules/collaboration/camera/collabCams.tsx b/app/src/modules/collaboration/camera/collabCams.tsx
index 0fd3569..2cf09b1 100644
--- a/app/src/modules/collaboration/camera/collabCams.tsx
+++ b/app/src/modules/collaboration/camera/collabCams.tsx
@@ -255,6 +255,8 @@ const CamModelsGroup = () => {
setCams((prev) => dedupeCams([...prev, ...newCams]));
});
}
+ }).catch(() => {
+ console.log('Error fetching active users data')
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
diff --git a/app/src/modules/scene/controls/controls.tsx b/app/src/modules/scene/controls/controls.tsx
index f0bbc29..975ab54 100644
--- a/app/src/modules/scene/controls/controls.tsx
+++ b/app/src/modules/scene/controls/controls.tsx
@@ -9,10 +9,11 @@ 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";
+import SelectionControls3D from "./selectionControls/selection3D/selectionControls3D";
import TransformControl from "./transformControls/transformControls";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../functions/getUserData";
+import SelectionControls2D from "./selectionControls/selection2D/selectionControls2D";
export default function Controls() {
const controlsRef = useRef(null);
@@ -137,7 +138,9 @@ export default function Controls() {
-
+
+
+
diff --git a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx
new file mode 100644
index 0000000..790a330
--- /dev/null
+++ b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx
@@ -0,0 +1,341 @@
+import * as THREE from "three";
+import { useCallback, useEffect, useMemo, useState } from "react";
+import { useFrame, useThree } from "@react-three/fiber";
+import { useSocketStore, useToggleView, useToolMode, } from "../../../../../store/builder/store";
+import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
+import { useParams } from "react-router-dom";
+import { getUserData } from "../../../../../functions/getUserData";
+import { useSceneContext } from "../../../sceneContext";
+import { useVersionContext } from "../../../../builder/version/versionContext";
+import { useSelectedPoints } from "../../../../../store/simulation/useSimulationStore";
+import useModuleStore from "../../../../../store/useModuleStore";
+
+// import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
+// import { upsertWallApi } from "../../../../../services/factoryBuilder/wall/upsertWallApi";
+// import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
+// import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
+
+function MoveControls2D({
+ movedObjects,
+ setMovedObjects,
+ pastedObjects,
+ setpastedObjects,
+ duplicatedObjects,
+ setDuplicatedObjects,
+ rotatedObjects,
+ setRotatedObjects,
+}: any) {
+ const { camera, controls, gl, scene, pointer, raycaster } = useThree();
+ const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
+ const { toolMode } = useToolMode();
+ const { toggleView } = useToggleView();
+ const { activeModule } = useModuleStore();
+ const { selectedPoints, clearSelectedPoints } = useSelectedPoints();
+ const { socket } = useSocketStore();
+ const { userId, organization } = getUserData();
+ const { projectId } = useParams();
+ const { selectedVersionStore } = useVersionContext();
+ const { selectedVersion } = selectedVersionStore();
+ const { aisleStore, wallStore, floorStore, zoneStore } = useSceneContext();
+ const { setPosition: setAislePosition, getAislesByPointId } = aisleStore();
+ const { setPosition: setWallPosition, getWallsByPointId } = wallStore();
+ const { setPosition: setFloorPosition, getFloorsByPointId } = floorStore();
+ const { setPosition: setZonePosition, getZonesByPointId } = zoneStore();
+ const [dragOffset, setDragOffset] = useState(null);
+ const [initialPositions, setInitialPositions] = useState>({});
+ const [initialStates, setInitialStates] = useState>({});
+ const [isMoving, setIsMoving] = useState(false);
+
+ 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 && movedObjects.length > 0 && event.button === 0) {
+ event.preventDefault();
+ placeMovedAssets();
+ }
+ if (!isMoving && movedObjects.length > 0 && event.button === 2) {
+ event.preventDefault();
+
+ clearSelection();
+ setMovedObjects([]);
+ resetToInitialPositions();
+ }
+ };
+
+ const onKeyDown = (event: KeyboardEvent) => {
+ const keyCombination = detectModifierKeys(event);
+
+ if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0) return;
+
+ if (keyCombination === "G") {
+ if (selectedPoints.length > 0) {
+ moveAssets();
+ }
+ }
+
+ if (keyCombination === "ESCAPE") {
+ event.preventDefault();
+
+ clearSelection();
+ setMovedObjects([]);
+ resetToInitialPositions();
+ }
+ };
+
+ if (toggleView && selectedPoints.length > 0) {
+ 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, selectedPoints, socket, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects]);
+
+ useEffect(() => {
+ if (toolMode !== 'move' || !toggleView) {
+ if (movedObjects.length > 0) {
+ resetToInitialPositions();
+ }
+ clearSelection();
+ }
+ }, [activeModule, toolMode, toggleView, movedObjects]);
+
+ useFrame(() => {
+ if (!isMoving || movedObjects.length === 0 || !dragOffset) return;
+
+ raycaster.setFromCamera(pointer, camera);
+ const intersectionPoint = new THREE.Vector3();
+ const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
+
+ if (hit) {
+ const baseNewPosition = new THREE.Vector3().addVectors(hit, dragOffset);
+
+ movedObjects.forEach((movedPoint: THREE.Object3D) => {
+ if (movedPoint.userData.pointUuid) {
+ const point: Point = movedPoint.userData as Point;
+ const initialPosition = initialPositions[movedPoint.uuid];
+
+ if (initialPosition) {
+ const relativeOffset = new THREE.Vector3().subVectors(
+ initialPosition,
+ initialPositions[movedObjects[0].uuid]
+ );
+
+ const newPosition = new THREE.Vector3().addVectors(baseNewPosition, relativeOffset);
+ const positionArray: [number, number, number] = [newPosition.x, newPosition.y, newPosition.z];
+
+ if (point.pointType === 'Aisle') {
+ setAislePosition(point.pointUuid, positionArray);
+ } else if (point.pointType === 'Wall') {
+ setWallPosition(point.pointUuid, positionArray);
+ } else if (point.pointType === 'Floor') {
+ setFloorPosition(point.pointUuid, positionArray);
+ } else if (point.pointType === 'Zone') {
+ setZonePosition(point.pointUuid, positionArray);
+ }
+ }
+ }
+ });
+ }
+ });
+
+ const calculateDragOffset = useCallback((point: THREE.Object3D, hitPoint: THREE.Vector3) => {
+ const pointPosition = new THREE.Vector3().copy(point.position);
+ return new THREE.Vector3().subVectors(pointPosition, hitPoint);
+ }, []);
+
+ const moveAssets = useCallback(() => {
+ if (selectedPoints.length === 0) return;
+
+ const states: Record = {};
+
+ selectedPoints.forEach((point: THREE.Object3D) => {
+ states[point.uuid] = {
+ position: new THREE.Vector3().copy(point.position),
+ rotation: point.rotation ? new THREE.Euler().copy(point.rotation) : undefined
+ };
+ });
+ setInitialStates(states);
+
+ const positions: Record = {};
+ selectedPoints.forEach((point: THREE.Object3D) => { positions[point.uuid] = new THREE.Vector3().copy(point.position); });
+ setInitialPositions(positions);
+
+ raycaster.setFromCamera(pointer, camera);
+ const intersectionPoint = new THREE.Vector3();
+ const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
+
+ if (hit && selectedPoints[0]) {
+ const offset = calculateDragOffset(selectedPoints[0], hit);
+ setDragOffset(offset);
+ }
+
+ setMovedObjects(selectedPoints);
+ setIsMoving(true);
+ }, [selectedPoints, camera, pointer, plane, raycaster, calculateDragOffset]);
+
+ const resetToInitialPositions = useCallback(() => {
+ setTimeout(() => {
+ movedObjects.forEach((movedPoint: THREE.Object3D) => {
+ if (movedPoint.userData.pointUuid && initialStates[movedPoint.uuid]) {
+ const point: Point = movedPoint.userData as Point;
+ const initialState = initialStates[movedPoint.uuid];
+ const positionArray: [number, number, number] = [
+ initialState.position.x,
+ initialState.position.y,
+ initialState.position.z
+ ];
+
+ if (point.pointType === 'Aisle') {
+ setAislePosition(point.pointUuid, positionArray);
+ } else if (point.pointType === 'Wall') {
+ setWallPosition(point.pointUuid, positionArray);
+ } else if (point.pointType === 'Floor') {
+ setFloorPosition(point.pointUuid, positionArray);
+ } else if (point.pointType === 'Zone') {
+ setZonePosition(point.pointUuid, positionArray);
+ }
+ }
+ });
+ }, 0)
+ }, [movedObjects, initialStates, setAislePosition, setWallPosition, setFloorPosition, setZonePosition]);
+
+ const placeMovedAssets = () => {
+ if (movedObjects.length === 0) return;
+
+ movedObjects.forEach((movedObject: THREE.Object3D) => {
+ if (movedObject.userData.pointUuid) {
+ const point: Point = movedObject.userData as Point;
+
+ if (point.pointType === 'Aisle') {
+ const updatedAisles = getAislesByPointId(point.pointUuid);
+ if (updatedAisles.length > 0 && projectId) {
+ updatedAisles.forEach((updatedAisle) => {
+
+ // API
+
+ // upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');
+
+ // SOCKET
+
+ socket.emit('v1:model-aisle:add', {
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization,
+ aisleUuid: updatedAisle.aisleUuid,
+ points: updatedAisle.points,
+ type: updatedAisle.type
+ })
+ })
+ }
+ } else if (point.pointType === 'Wall') {
+ const updatedWalls = getWallsByPointId(point.pointUuid);
+ if (updatedWalls && updatedWalls.length > 0 && projectId) {
+ updatedWalls.forEach((updatedWall) => {
+
+ // API
+
+ // upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
+
+ // SOCKET
+
+ const data = {
+ wallData: updatedWall,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Wall:add', data);
+ });
+ }
+ } else if (point.pointType === 'Floor') {
+ const updatedFloors = getFloorsByPointId(point.pointUuid);
+ if (updatedFloors && updatedFloors.length > 0 && projectId) {
+ updatedFloors.forEach((updatedFloor) => {
+
+ // API
+
+ // upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
+
+ // SOCKET
+
+ const data = {
+ floorData: updatedFloor,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Floor:add', data);
+ });
+ }
+ } else if (point.pointType === 'Zone') {
+ const updatedZones = getZonesByPointId(point.pointUuid);
+ if (updatedZones && updatedZones.length > 0 && projectId) {
+ updatedZones.forEach((updatedZone) => {
+
+ // API
+
+ // upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);
+
+ // SOCKET
+
+ const data = {
+ zoneData: updatedZone,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:zone:add', data);
+ });
+ }
+ }
+ }
+ })
+
+ echo.success("Object moved!");
+
+ clearSelection();
+ };
+
+ const clearSelection = () => {
+ setpastedObjects([]);
+ setDuplicatedObjects([]);
+ setMovedObjects([]);
+ setRotatedObjects([]);
+ clearSelectedPoints();
+ };
+
+ return (
+ <>
+ >
+ );
+}
+
+export default MoveControls2D;
diff --git a/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx b/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx
new file mode 100644
index 0000000..9d90d3c
--- /dev/null
+++ b/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx
@@ -0,0 +1,389 @@
+import { useCallback, useEffect, useMemo, useRef, useState } from "react";
+import * as THREE from "three";
+import { useThree } from "@react-three/fiber";
+import { SelectionHelper } from "../selectionHelper";
+import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox";
+
+import useModuleStore from "../../../../../store/useModuleStore";
+import { useParams } from "react-router-dom";
+import { getUserData } from "../../../../../functions/getUserData";
+import { useSceneContext } from "../../../sceneContext";
+import { useVersionContext } from "../../../../builder/version/versionContext";
+import { useSocketStore, useToggleView, useToolMode, } from "../../../../../store/builder/store";
+import { useSelectedPoints } from "../../../../../store/simulation/useSimulationStore";
+import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
+import MoveControls2D from "./moveControls2D";
+
+// import { deleteAisleApi } from "../../../../../services/factoryBuilder/aisle/deleteAisleApi";
+// import { deleteWallApi } from "../../../../../services/factoryBuilder/wall/deleteWallApi";
+// import { deleteFloorApi } from "../../../../../services/factoryBuilder/floor/deleteFloorApi";
+// import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/upsertFloorApi";
+// import { deleteZoneApi } from "../../../../../services/factoryBuilder/zone/deleteZoneApi";
+// import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
+
+const SelectionControls2D: React.FC = () => {
+ const { camera, controls, gl, scene, raycaster, pointer } = useThree();
+ const { toggleView } = useToggleView();
+ const { selectedPoints, setSelectedPoints, clearSelectedPoints } = useSelectedPoints();
+ const [movedObjects, setMovedObjects] = useState([]);
+ const [rotatedObjects, setRotatedObjects] = useState([]);
+ const [copiedObjects, setCopiedObjects] = useState([]);
+ const [pastedObjects, setpastedObjects] = useState([]);
+ const [duplicatedObjects, setDuplicatedObjects] = useState([]);
+ const { activeModule } = useModuleStore();
+ const { socket } = useSocketStore();
+ const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]);
+ const { toolMode } = useToolMode();
+ const { selectedVersionStore } = useVersionContext();
+ const { selectedVersion } = selectedVersionStore();
+ const { projectId } = useParams();
+ const { hoveredLine, hoveredPoint } = useBuilderStore();
+ const { aisleStore, wallStore, floorStore, zoneStore } = useSceneContext();
+ const { removePoint: removeAislePoint } = aisleStore();
+ const { removePoint: removeWallPoint } = wallStore();
+ const { removePoint: removeFloorPoint } = floorStore();
+ const { removePoint: removeZonePoint } = zoneStore();
+
+ const isDragging = useRef(false);
+ const isLeftMouseDown = useRef(false);
+ const isSelecting = useRef(false);
+ const isRightClick = useRef(false);
+ const rightClickMoved = useRef(false);
+ const isCtrlSelecting = useRef(false);
+ const isShiftSelecting = useRef(false);
+ const { userId, organization } = getUserData();
+
+ useEffect(() => {
+ if (!camera || !scene || !toggleView) return;
+
+ const canvasElement = gl.domElement;
+ canvasElement.tabIndex = 0;
+
+ const helper = new SelectionHelper(gl);
+
+ const onPointerDown = (event: PointerEvent) => {
+ if (event.button === 2) {
+ isRightClick.current = true;
+ rightClickMoved.current = false;
+ } else if (event.button === 0) {
+ isSelecting.current = false;
+ isCtrlSelecting.current = event.ctrlKey;
+ isShiftSelecting.current = event.shiftKey;
+ isLeftMouseDown.current = true;
+ isDragging.current = false;
+ 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.current) {
+ rightClickMoved.current = true;
+ }
+ if (isLeftMouseDown.current) {
+ isDragging.current = true;
+ }
+ isSelecting.current = true;
+ if (helper.isDown && event.ctrlKey && duplicatedObjects.length === 0 && isCtrlSelecting.current) {
+ selectionBox.endPoint.set(pointer.x, pointer.y, 0);
+ }
+ };
+
+ const onPointerUp = (event: PointerEvent) => {
+ if (event.button === 2 && !event.ctrlKey && !event.shiftKey) {
+ isRightClick.current = false;
+ if (!rightClickMoved.current) {
+ clearSelection();
+ }
+ return;
+ }
+
+ if (isSelecting.current && isCtrlSelecting.current) {
+ isCtrlSelecting.current = false;
+ isSelecting.current = false;
+ if (event.ctrlKey && duplicatedObjects.length === 0) {
+ selectAssets();
+ }
+ } else if (!isSelecting.current && selectedPoints.length > 0 && ((!event.ctrlKey && !event.shiftKey && pastedObjects.length === 0 && duplicatedObjects.length === 0 && movedObjects.length === 0 && rotatedObjects.length === 0) || event.button !== 0)) {
+ clearSelection();
+ helper.enabled = true;
+ isCtrlSelecting.current = false;
+ } else if (controls) {
+ (controls as any).enabled = true;
+ }
+
+ if (!isDragging.current && isLeftMouseDown.current && isShiftSelecting.current && event.shiftKey) {
+ isShiftSelecting.current = false;
+ isLeftMouseDown.current = false;
+ isDragging.current = false;
+
+ } else if (controls) {
+ (controls as any).enabled = true;
+ }
+ };
+
+ 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.current) {
+ clearSelection();
+ }
+ rightClickMoved.current = false;
+ };
+
+ if (toggleView && toolMode === 'move') {
+ helper.enabled = true;
+ canvasElement.addEventListener("pointermove", onPointerMove);
+ canvasElement.addEventListener("pointerup", onPointerUp);
+ canvasElement.addEventListener("pointerdown", onPointerDown);
+ 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, selectedPoints, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, rotatedObjects, toolMode, hoveredLine, hoveredPoint]);
+
+ useEffect(() => {
+ if (toolMode !== 'move' || !toggleView) {
+ clearSelection();
+ }
+ }, [activeModule, toolMode, toggleView]);
+
+ const selectAssets = useCallback(() => {
+ selectionBox.endPoint.set(pointer.x, pointer.y, 0);
+ if (controls) (controls as any).enabled = true;
+
+ let selectedObjects = selectionBox.select();
+ let Objects = new Set();
+
+ selectedObjects.forEach((object) => {
+ let currentObject: THREE.Object3D | null = object;
+ while (currentObject) {
+ if (currentObject.userData.pointUuid) {
+ Objects.add(currentObject);
+ break;
+ }
+ currentObject = currentObject.parent || null;
+ }
+ });
+
+ if (Objects.size === 0) {
+ clearSelection();
+ return;
+ }
+
+ const updatedSelections = new Set(selectedPoints);
+
+ Objects.forEach((obj) => {
+ const existing = Array.from(updatedSelections).find((o) => o.userData?.pointUuid === obj.userData?.pointUuid);
+
+ if (existing) {
+ updatedSelections.delete(existing);
+ } else {
+ updatedSelections.add(obj);
+ }
+ });
+
+ const selected = Array.from(updatedSelections);
+
+ setSelectedPoints(selected);
+
+ }, [selectionBox, pointer, controls, selectedPoints, setSelectedPoints]);
+
+ const clearSelection = () => {
+ setpastedObjects([]);
+ setDuplicatedObjects([]);
+ clearSelectedPoints();
+ };
+
+ const deleteSelection = () => {
+ if (selectedPoints.length > 0 && duplicatedObjects.length === 0) {
+
+ selectedPoints.forEach((selectedPoint) => {
+ if (selectedPoint.userData.pointUuid) {
+ const point: Point = selectedPoint.userData as Point;
+ if (point.pointType === 'Aisle') {
+ const removedAisles = removeAislePoint(point.pointUuid);
+ if (removedAisles.length > 0) {
+ removedAisles.forEach(aisle => {
+ if (projectId) {
+
+ // API
+
+ // deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '');
+
+ // SOCKET
+
+ const data = {
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization,
+ aisleUuid: aisle.aisleUuid
+ }
+
+ socket.emit('v1:model-aisle:delete', data);
+ }
+ });
+ }
+ }
+ if (point.pointType === 'Wall') {
+ const removedWalls = removeWallPoint(point.pointUuid);
+ if (removedWalls.length > 0) {
+ removedWalls.forEach(wall => {
+ if (projectId) {
+
+ // API
+
+ // deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);
+
+ // SOCKET
+
+ const data = {
+ wallUuid: wall.wallUuid,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Wall:delete', data);
+ }
+ });
+ }
+ }
+ if (point.pointType === 'Floor') {
+ const { removedFloors, updatedFloors } = removeFloorPoint(point.pointUuid);
+ if (removedFloors.length > 0) {
+ removedFloors.forEach(floor => {
+ if (projectId) {
+
+ // API
+
+ // deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);
+
+ // SOCKET
+
+ const data = {
+ floorUuid: floor.floorUuid,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Floor:delete', data);
+ }
+ });
+ }
+ if (updatedFloors.length > 0) {
+ updatedFloors.forEach(floor => {
+ if (projectId) {
+
+ // API
+
+ // upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
+
+ // SOCKET
+
+ const data = {
+ floorData: floor,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Floor:add', data);
+ }
+ });
+ }
+ }
+ if (point.pointType === 'Zone') {
+ const { removedZones, updatedZones } = removeZonePoint(point.pointUuid);
+ if (removedZones.length > 0) {
+ removedZones.forEach(zone => {
+ if (projectId) {
+
+ // API
+
+ // deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);
+
+ // SOCKET
+
+ const data = {
+ zoneUuid: zone.zoneUuid,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:zone:delete', data);
+ }
+ });
+ }
+ if (updatedZones.length > 0) {
+ updatedZones.forEach(zone => {
+ if (projectId) {
+
+ // API
+
+ // upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
+
+ // SOCKET
+
+ const data = {
+ zoneData: zone,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:zone:add', data);
+ }
+ });
+ }
+ }
+ }
+ })
+
+ }
+ echo.success("Selected points removed!");
+ clearSelection();
+ };
+
+ return (
+ <>
+
+
+ >
+ );
+};
+
+export default SelectionControls2D;
diff --git a/app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/boundingBoxHelper3D.tsx
similarity index 98%
rename from app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx
rename to app/src/modules/scene/controls/selectionControls/selection3D/boundingBoxHelper3D.tsx
index 43e044c..dde668e 100644
--- a/app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selection3D/boundingBoxHelper3D.tsx
@@ -1,7 +1,7 @@
import { Line } from "@react-three/drei";
import { useMemo } from "react";
import * as THREE from "three";
-import { useSelectedAssets } from "../../../../store/builder/store";
+import { useSelectedAssets } from "../../../../../store/builder/store";
interface BoundingBoxProps {
boundingBoxRef?: any;
diff --git a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx
similarity index 94%
rename from app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx
rename to app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx
index 6a48465..9c81a82 100644
--- a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx
@@ -2,17 +2,17 @@ import * as THREE from "three";
import { useEffect, useMemo } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { SkeletonUtils } from "three-stdlib";
-import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/builder/store";
-import * as Types from "../../../../types/world/worldTypes";
-import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
+import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../../store/builder/store";
+import * as Types from "../../../../../types/world/worldTypes";
+import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
import { useParams } from "react-router-dom";
-import { getUserData } from "../../../../functions/getUserData";
-import { useSceneContext } from "../../sceneContext";
-import { useVersionContext } from "../../../builder/version/versionContext";
+import { getUserData } from "../../../../../functions/getUserData";
+import { useSceneContext } from "../../../sceneContext";
+import { useVersionContext } from "../../../../builder/version/versionContext";
-// import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
+// import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
-const CopyPasteControls = ({
+const CopyPasteControls3D = ({
copiedObjects,
setCopiedObjects,
pastedObjects,
@@ -239,6 +239,11 @@ const CopyPasteControls = ({
steeringAngle: 0,
pickUpPoint: null,
unLoadPoint: null,
+ paths: {
+ initPickup: [],
+ pickupDrop: [],
+ dropPickup: [],
+ },
triggers: []
}
}
@@ -352,13 +357,17 @@ const CopyPasteControls = ({
uuid: THREE.MathUtils.generateUUID(),
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
- action: {
- actionUuid: THREE.MathUtils.generateUUID(),
- actionName: "Action 1",
- actionType: "worker",
- loadCapacity: 1,
- triggers: []
- }
+ actions: [
+ {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: "Action 1",
+ actionType: "worker",
+ loadCapacity: 1,
+ loadCount: 1,
+ processTime: 10,
+ triggers: []
+ }
+ ]
}
}
addEvent(humanEvent);
@@ -495,4 +504,4 @@ const CopyPasteControls = ({
return null;
};
-export default CopyPasteControls;
\ No newline at end of file
+export default CopyPasteControls3D;
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selectionControls/distanceFindingControls.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/distanceFindingControls.tsx
similarity index 100%
rename from app/src/modules/scene/controls/selectionControls/distanceFindingControls.tsx
rename to app/src/modules/scene/controls/selectionControls/selection3D/distanceFindingControls.tsx
diff --git a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx
similarity index 93%
rename from app/src/modules/scene/controls/selectionControls/duplicationControls.tsx
rename to app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx
index 38c62d1..38816f4 100644
--- a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx
@@ -2,17 +2,17 @@ import * as THREE from "three";
import { useEffect, useMemo } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { SkeletonUtils } from "three-stdlib";
-import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/builder/store";
-import * as Types from "../../../../types/world/worldTypes";
-import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
+import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../../store/builder/store";
+import * as Types from "../../../../../types/world/worldTypes";
+import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
import { useParams } from "react-router-dom";
-import { getUserData } from "../../../../functions/getUserData";
-import { useSceneContext } from "../../sceneContext";
-import { useVersionContext } from "../../../builder/version/versionContext";
+import { getUserData } from "../../../../../functions/getUserData";
+import { useSceneContext } from "../../../sceneContext";
+import { useVersionContext } from "../../../../builder/version/versionContext";
-// import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
+// import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
-const DuplicationControls = ({
+const DuplicationControls3D = ({
duplicatedObjects,
setDuplicatedObjects,
setpastedObjects,
@@ -213,6 +213,11 @@ const DuplicationControls = ({
steeringAngle: 0,
pickUpPoint: null,
unLoadPoint: null,
+ paths: {
+ initPickup: [],
+ pickupDrop: [],
+ dropPickup: [],
+ },
triggers: []
}
}
@@ -326,13 +331,17 @@ const DuplicationControls = ({
uuid: THREE.MathUtils.generateUUID(),
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
- action: {
- actionUuid: THREE.MathUtils.generateUUID(),
- actionName: "Action 1",
- actionType: "worker",
- loadCapacity: 1,
- triggers: []
- }
+ actions: [
+ {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: "Action 1",
+ actionType: "worker",
+ loadCapacity: 1,
+ loadCount: 1,
+ processTime: 10,
+ triggers: []
+ }
+ ]
}
}
addEvent(humanEvent);
@@ -464,4 +473,4 @@ const DuplicationControls = ({
return null;
};
-export default DuplicationControls;
\ No newline at end of file
+export default DuplicationControls3D;
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selectionControls/moveControls.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx
similarity index 94%
rename from app/src/modules/scene/controls/selectionControls/moveControls.tsx
rename to app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx
index 79cf195..6658f62 100644
--- a/app/src/modules/scene/controls/selectionControls/moveControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selection3D/moveControls3D.tsx
@@ -1,20 +1,21 @@
import * as THREE from "three";
import { useEffect, useMemo, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
-import { useSelectedAssets, useSocketStore, useToggleView, } from "../../../../store/builder/store";
-// import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
-import * as Types from "../../../../types/world/worldTypes";
-import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
-import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
-import { snapControls } from "../../../../utils/handleSnap";
+import { useSelectedAssets, useSocketStore, useToggleView, } from "../../../../../store/builder/store";
+import * as Types from "../../../../../types/world/worldTypes";
+import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
+import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
+import { snapControls } from "../../../../../utils/handleSnap";
import DistanceFindingControls from "./distanceFindingControls";
import { useParams } from "react-router-dom";
-import { useProductContext } from "../../../simulation/products/productContext";
-import { getUserData } from "../../../../functions/getUserData";
-import { useSceneContext } from "../../sceneContext";
-import { useVersionContext } from "../../../builder/version/versionContext";
+import { useProductContext } from "../../../../simulation/products/productContext";
+import { getUserData } from "../../../../../functions/getUserData";
+import { useSceneContext } from "../../../sceneContext";
+import { useVersionContext } from "../../../../builder/version/versionContext";
-function MoveControls({
+// import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
+
+function MoveControls3D({
movedObjects,
setMovedObjects,
pastedObjects,
@@ -364,4 +365,4 @@ function MoveControls({
);
}
-export default MoveControls;
+export default MoveControls3D;
diff --git a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx
similarity index 94%
rename from app/src/modules/scene/controls/selectionControls/rotateControls.tsx
rename to app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx
index 216d4f7..fdde56a 100644
--- a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selection3D/rotateControls3D.tsx
@@ -1,17 +1,18 @@
import * as THREE from "three";
import { useEffect, useMemo, useRef } from "react";
import { useFrame, useThree } from "@react-three/fiber";
-import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/builder/store";
-// import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
-import * as Types from "../../../../types/world/worldTypes";
-import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
+import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../../store/builder/store";
+import * as Types from "../../../../../types/world/worldTypes";
+import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useParams } from "react-router-dom";
-import { useProductContext } from "../../../simulation/products/productContext";
-import { getUserData } from "../../../../functions/getUserData";
-import { useSceneContext } from "../../sceneContext";
-import { useVersionContext } from "../../../builder/version/versionContext";
+import { useProductContext } from "../../../../simulation/products/productContext";
+import { getUserData } from "../../../../../functions/getUserData";
+import { useSceneContext } from "../../../sceneContext";
+import { useVersionContext } from "../../../../builder/version/versionContext";
-function RotateControls({
+// import { setAssetsApi } from '../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
+
+function RotateControls3D({
rotatedObjects,
setRotatedObjects,
movedObjects,
@@ -300,4 +301,4 @@ function RotateControls({
return null;
}
-export default RotateControls
\ No newline at end of file
+export default RotateControls3D
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selectionControls/selectionControls.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx
similarity index 84%
rename from app/src/modules/scene/controls/selectionControls/selectionControls.tsx
rename to app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx
index 9a5ab33..080a5d8 100644
--- a/app/src/modules/scene/controls/selectionControls/selectionControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selection3D/selectionControls3D.tsx
@@ -1,26 +1,27 @@
-import * as THREE from "three";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
-import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox";
-import { SelectionHelper } from "./selectionHelper";
+import * as THREE from "three";
import { useFrame, useThree } from "@react-three/fiber";
-import { useSelectedAssets, useSocketStore, useToggleView, useToolMode, } from "../../../../store/builder/store";
-import BoundingBox from "./boundingBoxHelper";
-// import { deleteFloorItem } from '../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi';
-import * as Types from "../../../../types/world/worldTypes";
+import { SelectionHelper } from "../selectionHelper";
+import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox";
+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";
+import useModuleStore from "../../../../../store/useModuleStore";
import { useParams } from "react-router-dom";
-import { getUserData } from "../../../../functions/getUserData";
-import { useSceneContext } from "../../sceneContext";
-import { useVersionContext } from "../../../builder/version/versionContext";
-import { useProductContext } from "../../../simulation/products/productContext";
-import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
+import { getUserData } from "../../../../../functions/getUserData";
+import { useSceneContext } from "../../../sceneContext";
+import { useVersionContext } from "../../../../builder/version/versionContext";
+import { useProductContext } from "../../../../simulation/products/productContext";
+import { useSelectedAssets, useSocketStore, useToggleView, useToolMode, } from "../../../../../store/builder/store";
+import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
+import BoundingBox from "./boundingBoxHelper3D";
+import DuplicationControls3D from "./duplicationControls3D";
+import CopyPasteControls3D from "./copyPasteControls3D";
+import MoveControls3D from "./moveControls3D";
+import RotateControls3D from "./rotateControls3D";
-const SelectionControls: React.FC = () => {
+// import { deleteFloorItem } from '../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi';
+
+const SelectionControls3D: React.FC = () => {
const { camera, controls, gl, scene, raycaster, pointer } = useThree();
const selectionGroup = useRef() as Types.RefGroup;
const { toggleView } = useToggleView();
@@ -253,7 +254,7 @@ const SelectionControls: React.FC = () => {
});
if (Objects.size === 0) {
- clearSelection();
+ // clearSelection();
return;
}
@@ -350,15 +351,15 @@ const SelectionControls: React.FC = () => {
-
+
-
+
-
+
-
+
>
);
};
-export default SelectionControls;
+export default SelectionControls3D;
diff --git a/app/src/modules/scene/environment/shadow.tsx b/app/src/modules/scene/environment/shadow.tsx
index d8c8002..3321673 100644
--- a/app/src/modules/scene/environment/shadow.tsx
+++ b/app/src/modules/scene/environment/shadow.tsx
@@ -6,7 +6,6 @@ import {
useElevation,
useShadows,
useSunPosition,
- useWallItems,
useTileDistance,
} from "../../../store/builder/store";
import * as CONSTANTS from "../../../types/world/worldConstants";
@@ -25,13 +24,12 @@ export default function Shadows() {
const { controls, gl } = useThree();
const { elevation, setElevation } = useElevation();
const { azimuth, setAzimuth } = useAzimuth();
- const { wallItems } = useWallItems();
const { planeValue } = useTileDistance();
useEffect(() => {
gl.shadowMap.enabled = true;
gl.shadowMap.type = THREE.PCFShadowMap;
- }, [gl, wallItems]);
+ }, [gl]);
useEffect(() => {
if (lightRef.current && targetRef.current) {
diff --git a/app/src/modules/scene/postProcessing/postProcessing.tsx b/app/src/modules/scene/postProcessing/postProcessing.tsx
index 7c6c719..c70f733 100644
--- a/app/src/modules/scene/postProcessing/postProcessing.tsx
+++ b/app/src/modules/scene/postProcessing/postProcessing.tsx
@@ -6,11 +6,12 @@ import {
useSelectedFloorItem,
} from "../../../store/builder/store";
import * as CONSTANTS from "../../../types/world/worldConstants";
-import { useDeletableEventSphere, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
+import { useDeletableEventSphere, useSelectedEventSphere, useSelectedPoints } from "../../../store/simulation/useSimulationStore";
import { useEffect } from "react";
import { useBuilderStore } from "../../../store/builder/useBuilderStore";
export default function PostProcessing() {
+ const { selectedPoints } = useSelectedPoints();
const { deletableFloorItem } = useDeletableFloorItem();
const { selectedWallItem } = useSelectedWallItem();
const { selectedFloorItem } = useSelectedFloorItem();
@@ -61,6 +62,10 @@ export default function PostProcessing() {
// console.log('deletableEventSphere: ', deletableEventSphere);
}, [deletableEventSphere])
+ useEffect(() => {
+ // console.log('selectedPoints: ', selectedPoints);
+ }, [selectedPoints])
+
return (
{
echo.info(`${materialUuid}, ${status}`);
@@ -17,6 +17,7 @@ export function useDespawnHandler() {
setEndTime(material.materialId, performance.now());
removeMaterial(material.materialId);
+ clearLocations(material.materialId);
deSpawnLogStatus(material.materialName, `Despawned`);
diff --git a/app/src/modules/simulation/actions/human/actionHandler/useAssemblyHandler.ts b/app/src/modules/simulation/actions/human/actionHandler/useAssemblyHandler.ts
index a654b35..602de27 100644
--- a/app/src/modules/simulation/actions/human/actionHandler/useAssemblyHandler.ts
+++ b/app/src/modules/simulation/actions/human/actionHandler/useAssemblyHandler.ts
@@ -8,7 +8,7 @@ export function useAssemblyHandler() {
const { getModelUuidByActionUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
- const { incrementHumanLoad, addCurrentMaterial } = humanStore();
+ const { incrementHumanLoad, addCurrentMaterial, addCurrentAction } = humanStore();
const assemblyLogStatus = (materialUuid: string, status: string) => {
echo.info(`${materialUuid}, ${status}`);
@@ -24,6 +24,7 @@ export function useAssemblyHandler() {
if (!modelUuid) return;
incrementHumanLoad(modelUuid, 1);
+ addCurrentAction(modelUuid, action.actionUuid);
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
assemblyLogStatus(material.materialName, `performing assembly action`);
diff --git a/app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts b/app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts
index 9a1cf99..efefc39 100644
--- a/app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts
+++ b/app/src/modules/simulation/actions/human/actionHandler/useWorkerHandler.ts
@@ -8,7 +8,7 @@ export function useWorkerHandler() {
const { getModelUuidByActionUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
- const { incrementHumanLoad, addCurrentMaterial } = humanStore();
+ const { incrementHumanLoad, incrementLoadCount, addCurrentMaterial, addCurrentAction } = humanStore();
const workerLogStatus = (materialUuid: string, status: string) => {
echo.info(`${materialUuid}, ${status}`);
@@ -24,6 +24,8 @@ export function useWorkerHandler() {
if (!modelUuid) return;
incrementHumanLoad(modelUuid, 1);
+ incrementLoadCount(modelUuid, 1);
+ addCurrentAction(modelUuid, action.actionUuid);
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
workerLogStatus(material.materialName, `performing worker action`);
diff --git a/app/src/modules/simulation/actions/storageUnit/actionHandler/useRetrieveHandler.ts b/app/src/modules/simulation/actions/storageUnit/actionHandler/useRetrieveHandler.ts
index c4b4245..79d6401 100644
--- a/app/src/modules/simulation/actions/storageUnit/actionHandler/useRetrieveHandler.ts
+++ b/app/src/modules/simulation/actions/storageUnit/actionHandler/useRetrieveHandler.ts
@@ -5,12 +5,14 @@ import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function useRetrieveHandler() {
- const { materialStore, armBotStore, vehicleStore, storageUnitStore, productStore } = useSceneContext();
+ const { materialStore, armBotStore, vehicleStore, storageUnitStore, productStore, humanStore, assetStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { addMaterial } = materialStore();
const { getModelUuidByActionUuid, getPointUuidByActionUuid, getEventByModelUuid, getActionByUuid } = productStore();
const { getStorageUnitById, getLastMaterial, updateCurrentLoad, removeLastMaterial } = storageUnitStore();
const { getVehicleById, incrementVehicleLoad, addCurrentMaterial } = vehicleStore();
+ const { getHumanById, incrementHumanLoad, incrementLoadCount, addCurrentMaterial: addCurrentMaterialToHuman } = humanStore();
+ const { getAssetById, setCurrentAnimation } = assetStore();
const { selectedProduct } = selectedProductStore();
const { getArmBotById, addCurrentAction } = armBotStore();
const { isPlaying } = usePlayButtonStore();
@@ -269,7 +271,7 @@ export function useRetrieveHandler() {
if (material) {
removeLastMaterial(storageUnit.modelUuid);
- updateCurrentLoad(storageUnit.modelUuid, -1)
+ updateCurrentLoad(storageUnit.modelUuid, -1);
incrementVehicleLoad(vehicle.modelUuid, 1);
addCurrentMaterial(vehicle.modelUuid, material.materialType, material.materialId);
retrieveLogStatus(material.materialName, `is picked by ${vehicle.modelName}`);
@@ -293,6 +295,37 @@ export function useRetrieveHandler() {
retrievalTimeRef.current.delete(actionUuid);
retrievalTimeRef.current.delete(`${actionUuid}_last`);
}
+ } else if (triggeredModel.type === 'human') {
+ const human = getHumanById(triggeredModel.modelUuid);
+ const humanAsset = getAssetById(triggeredModel.modelUuid);
+ const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
+
+ if (human && !human.isScheduled && human.state === 'idle' && human.currentLoad < (action as HumanAction).loadCapacity) {
+ if (humanAsset && humanAsset.animationState?.current === 'idle') {
+ setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
+ } else if (humanAsset && humanAsset.animationState?.current === 'pickup' && humanAsset.animationState.isCompleted) {
+ const lastMaterial = getLastMaterial(storageUnit.modelUuid);
+ if (lastMaterial) {
+ if (action && human.currentLoad < (action as HumanAction).loadCapacity) {
+ const material = createNewMaterial(
+ lastMaterial.materialId,
+ lastMaterial.materialType,
+ storageUnit.point.action
+ );
+ if (material) {
+ removeLastMaterial(storageUnit.modelUuid);
+ updateCurrentLoad(storageUnit.modelUuid, -1);
+ incrementHumanLoad(human.modelUuid, 1);
+ incrementLoadCount(human.modelUuid, 1);
+ addCurrentMaterialToHuman(human.modelUuid, material.materialType, material.materialId);
+ retrieveLogStatus(material.materialName, `is picked by ${human.modelName}`);
+ }
+ if (human.currentLoad + 1 < (action as HumanAction).loadCapacity) {
+ }
+ }
+ }
+ }
+ }
}
});
diff --git a/app/src/modules/simulation/conveyor/eventManager/useConveyorEventManager.ts b/app/src/modules/simulation/conveyor/eventManager/useConveyorEventManager.ts
index 34407c9..76a1047 100644
--- a/app/src/modules/simulation/conveyor/eventManager/useConveyorEventManager.ts
+++ b/app/src/modules/simulation/conveyor/eventManager/useConveyorEventManager.ts
@@ -6,65 +6,92 @@ import { useSceneContext } from '../../../scene/sceneContext';
type ConveyorCallback = {
conveyorId: string;
callback: () => void;
+ except: string[];
};
export function useConveyorEventManager() {
- const { conveyorStore } = useSceneContext();
- const { getConveyorById } = conveyorStore();
- const callbacksRef = useRef([]);
+ const { materialStore } = useSceneContext();
+ const { getMaterialsByCurrentModelUuid } = materialStore();
+ const callbacksRef = useRef