From c73bdf455615a74303bb129f48850d5f0ed2909b Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Fri, 27 Jun 2025 15:44:31 +0530 Subject: [PATCH] completed floor --- .../layout/sidebarRight/SideBarRight.tsx | 425 +++++---- .../properties/FloorProperties.tsx | 171 ++++ .../properties/SelectedFloorProperties.tsx | 250 +++++ .../properties/SelectedWallProperties.tsx | 32 +- .../properties/WallProperties.tsx | 271 +++--- .../instance/aisleTypes/arcAisle.tsx | 2 +- .../instance/aisleTypes/arrowAisle.tsx | 2 +- .../instance/aisleTypes/arrowsAisle.tsx | 2 +- .../instance/aisleTypes/circleAisle.tsx | 2 +- .../instance/aisleTypes/dashedAisle.tsx | 2 +- .../instance/aisleTypes/dottedAisle.tsx | 2 +- .../instance/aisleTypes/junctionAisle.tsx | 2 +- .../instance/aisleTypes/solidAisle.tsx | 2 +- app/src/modules/builder/asset/assetsGroup.tsx | 4 +- .../builder/asset/functions/addAssetModel.ts | 875 +++++++++--------- .../Instances/Instance/floorInstance.tsx | 12 +- .../builder/wall/Instances/instance/wall.tsx | 2 +- .../builder/wall/Instances/wallInstances.tsx | 7 +- .../builder/wall/wallCreator/wallCreator.tsx | 4 +- .../distanceFindingControls.tsx | 487 ++++------ app/src/store/builder/useBuilderStore.ts | 6 +- app/src/store/builder/useFloorStore.ts | 19 +- 22 files changed, 1422 insertions(+), 1159 deletions(-) create mode 100644 app/src/components/layout/sidebarRight/properties/FloorProperties.tsx create mode 100644 app/src/components/layout/sidebarRight/properties/SelectedFloorProperties.tsx diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index d6413bc..1fa90d3 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -1,27 +1,28 @@ import React, { useEffect } from "react"; import Header from "./Header"; import useModuleStore, { - useSubModuleStore, + useSubModuleStore, } from "../../../store/useModuleStore"; import { - AnalysisIcon, - MechanicsIcon, - PropertiesIcon, - SimulationIcon, + AnalysisIcon, + MechanicsIcon, + PropertiesIcon, + SimulationIcon, } from "../../icons/SimulationIcons"; import { useToggleStore } from "../../../store/useUIToggleStore"; import Visualization from "./visualization/Visualization"; import Analysis from "./analysis/Analysis"; import Simulations from "./simulation/Simulations"; import useVersionHistoryVisibleStore, { - useSaveVersion, - useSelectedFloorItem, - useToolMode, + useSaveVersion, + useSelectedFloorItem, + useToolMode, } from "../../../store/builder/store"; import { - useSelectedEventData, - useSelectedEventSphere, + useSelectedEventData, + useSelectedEventSphere, } from "../../../store/simulation/useSimulationStore"; +import { useBuilderStore } from "../../../store/builder/useBuilderStore"; import GlobalProperties from "./properties/GlobalProperties"; import AssetProperties from "./properties/AssetProperties"; import ZoneProperties from "./properties/ZoneProperties"; @@ -29,207 +30,227 @@ import EventProperties from "./properties/eventProperties/EventProperties"; import VersionHistory from "./versionHisory/VersionHistory"; import AisleProperties from "./properties/AisleProperties"; import WallProperties from "./properties/WallProperties"; -import { useBuilderStore } from "../../../store/builder/useBuilderStore"; +import FloorProperties from "./properties/FloorProperties"; import SelectedWallProperties from "./properties/SelectedWallProperties"; +import SelectedFloorProperties from "./properties/SelectedFloorProperties"; const SideBarRight: React.FC = () => { - const { activeModule } = useModuleStore(); - const { toggleUIRight } = useToggleStore(); - const { toolMode } = useToolMode(); - const { subModule, setSubModule } = useSubModuleStore(); - const { selectedFloorItem } = useSelectedFloorItem(); - const { selectedWall } = useBuilderStore(); - const { selectedEventData } = useSelectedEventData(); - const { selectedEventSphere } = useSelectedEventSphere(); - const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore(); - const { isVersionSaved } = useSaveVersion(); + const { activeModule } = useModuleStore(); + const { toggleUIRight } = useToggleStore(); + const { toolMode } = useToolMode(); + const { subModule, setSubModule } = useSubModuleStore(); + const { selectedFloorItem } = useSelectedFloorItem(); + const { selectedWall, selectedFloor, selectedAisle } = useBuilderStore(); + const { selectedEventData } = useSelectedEventData(); + const { selectedEventSphere } = useSelectedEventSphere(); + const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore(); + const { isVersionSaved } = useSaveVersion(); - // Reset activeList whenever activeModule changes - useEffect(() => { - if (activeModule !== "simulation") setSubModule("properties"); - if (activeModule === "simulation") setSubModule("simulations"); - }, [activeModule, setSubModule]); + // Reset activeList whenever activeModule changes + useEffect(() => { + if (activeModule !== "simulation") setSubModule("properties"); + if (activeModule === "simulation") setSubModule("simulations"); + }, [activeModule, setSubModule]); - useEffect(() => { - if ( - activeModule !== "mechanics" && - selectedEventData && - selectedEventSphere - ) { - setSubModule("mechanics"); - } else if (!selectedEventData && !selectedEventSphere) { - if (activeModule === "simulation") { - setSubModule("simulations"); - } - } - if (activeModule !== "simulation") { - setSubModule("properties"); - } - }, [activeModule, selectedEventData, selectedEventSphere, setSubModule]); + useEffect(() => { + if ( + activeModule !== "mechanics" && + selectedEventData && + selectedEventSphere + ) { + setSubModule("mechanics"); + } else if (!selectedEventData && !selectedEventSphere) { + if (activeModule === "simulation") { + setSubModule("simulations"); + } + } + if (activeModule !== "simulation") { + setSubModule("properties"); + } + }, [activeModule, selectedEventData, selectedEventSphere, setSubModule]); - return ( -
-
- {toggleUIRight && ( - <> - {!isVersionSaved && ( -
- {activeModule !== "simulation" && ( - - )} - {activeModule === "simulation" && ( + return ( +
+
+ {toggleUIRight && ( <> - - - + {!isVersionSaved && ( +
+ {activeModule !== "simulation" && ( + + )} + {activeModule === "simulation" && ( + <> + + + + + )} +
+ )} + + {viewVersionHistory && ( +
+
+ +
+
+ )} + + {/* process builder */} + {!viewVersionHistory && + subModule === "properties" && + activeModule !== "visualization" && + !selectedFloorItem && + !selectedFloor && + !selectedWall && ( +
+
+ {(() => { + if (toolMode === "Aisle") { + return ; + } else if (toolMode === "Wall") { + return ; + } else if (toolMode === "Floor") { + return ; + } else { + return ; + } + })()} +
+
+ )} + + {!viewVersionHistory && + subModule === "properties" && + activeModule !== "visualization" && + selectedFloorItem && ( +
+
+ +
+
+ )} + + {!viewVersionHistory && + subModule === "properties" && + activeModule !== "visualization" && + !selectedFloorItem && + !selectedFloor && + !selectedAisle && + selectedWall && ( +
+
+ +
+
+ )} + + {!viewVersionHistory && + subModule === "properties" && + activeModule !== "visualization" && + !selectedFloorItem && + !selectedWall && + !selectedAisle && + selectedFloor && ( +
+
+ +
+
+ )} + + {!viewVersionHistory && + subModule === "zoneProperties" && + (activeModule === "builder" || activeModule === "simulation") && ( +
+
+ +
+
+ )} + + {/* simulation */} + {!isVersionSaved && + !viewVersionHistory && + activeModule === "simulation" && ( + <> + {subModule === "simulations" && ( +
+
+ +
+
+ )} + {subModule === "mechanics" && ( +
+
+ +
+
+ )} + {subModule === "analysis" && ( +
+
+ +
+
+ )} + + )} + {/* realtime visualization */} + {activeModule === "visualization" && } - )} -
- )} - - {viewVersionHistory && ( -
-
- -
-
- )} - - {/* process builder */} - {!viewVersionHistory && - subModule === "properties" && - activeModule !== "visualization" && - !selectedFloorItem && - !selectedWall && ( -
-
- {(() => { - if (toolMode === "Aisle") { - return ; - } else if (toolMode === "Wall") { - return ; - } else { - return ; - } - })()} -
-
)} - - {!viewVersionHistory && - subModule === "properties" && - activeModule !== "visualization" && - selectedFloorItem && ( -
-
- -
-
- )} - - {!viewVersionHistory && - subModule === "properties" && - activeModule !== "visualization" && - !selectedFloorItem && - selectedWall && ( -
-
- -
-
- )} - - {!viewVersionHistory && - subModule === "zoneProperties" && - (activeModule === "builder" || activeModule === "simulation") && ( -
-
- -
-
- )} - - {/* simulation */} - {!isVersionSaved && - !viewVersionHistory && - activeModule === "simulation" && ( - <> - {subModule === "simulations" && ( -
-
- -
-
- )} - {subModule === "mechanics" && ( -
-
- -
-
- )} - {subModule === "analysis" && ( -
-
- -
-
- )} - - )} - {/* realtime visualization */} - {activeModule === "visualization" && } - - )} -
- ); +
+ ); }; export default SideBarRight; diff --git a/app/src/components/layout/sidebarRight/properties/FloorProperties.tsx b/app/src/components/layout/sidebarRight/properties/FloorProperties.tsx new file mode 100644 index 0000000..41e8d41 --- /dev/null +++ b/app/src/components/layout/sidebarRight/properties/FloorProperties.tsx @@ -0,0 +1,171 @@ +import { useEffect, useState } from "react"; +import InputToggle from "../../../ui/inputs/InputToggle"; +import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; + +import defaultTexture from '../../../../assets/textures/floor/white.png'; +import flootTexture1 from '../../../../assets/textures/floor/factory wall texture.jpg'; + +import { useBuilderStore } from "../../../../store/builder/useBuilderStore"; + +type Material = { + texture: string; + textureId: string; + textureName: string; +}; + +const materials = [ + { texture: defaultTexture, textureId: "Default Material", textureName: "Default Material" }, + { texture: flootTexture1, textureId: "Material 1", textureName: "Grunge Concrete Wall" } +]; + +const FloorProperties = () => { + const { floorDepth, isBeveled, topMaterial, sideMaterial, bevelStrength, setFloorDepth, setIsBeveled, setBevelStrength, setFloorMaterial } = useBuilderStore(); + + const [activeSurface, setActiveSurface] = useState<"top" | "side">("top"); + + const [selectedMaterials, setSelectedMaterials] = useState<{ top: Material | null; side: Material | null; }>({ top: null, side: null, }); + + useEffect(() => { + setSelectedMaterials({ + top: materials.find((mat) => mat.textureId === topMaterial) || null, + side: materials.find((mat) => mat.textureId === sideMaterial) || null, + }); + }, []); + + const handleDepthChange = (val: string) => { + setFloorDepth(parseFloat(val)); + }; + + const handleIsBevelChange = (val: boolean) => { + setIsBeveled(val); + }; + + const handleBevelChange = (val: string) => { + setBevelStrength(parseFloat(val)); + }; + + const handleSelectMaterial = (material: Material) => { + setSelectedMaterials((prev) => ({ + ...prev, + [activeSurface]: material, + })); + setFloorMaterial(material.textureId, activeSurface); + }; + + return ( +
+
+
Floor
+
+ + handleIsBevelChange(!isBeveled)} + /> + +
+
+ +
+
+
Materials
+
+ +
+
+ + + +
+ +
+ {selectedMaterials[activeSurface] && ( + {selectedMaterials[activeSurface]!.textureName} + )} +
+
+ +
+ {materials.length === 0 ? ( +
No materials added yet.
+ ) : ( +
+ {materials.map((material, index) => { + const isSelected = selectedMaterials[activeSurface]?.texture === material.texture; + + return ( + + ); + })} +
+ )} +
+
+
+ ); +}; + +export default FloorProperties; diff --git a/app/src/components/layout/sidebarRight/properties/SelectedFloorProperties.tsx b/app/src/components/layout/sidebarRight/properties/SelectedFloorProperties.tsx new file mode 100644 index 0000000..8df2a88 --- /dev/null +++ b/app/src/components/layout/sidebarRight/properties/SelectedFloorProperties.tsx @@ -0,0 +1,250 @@ +import { useEffect, useState } from "react"; +import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; +import InputToggle from "../../../ui/inputs/InputToggle"; + +import defaultTexture from '../../../../assets/textures/floor/white.png'; +import floorTexture1 from '../../../../assets/textures/floor/factory wall texture.jpg'; + +import { useBuilderStore } from "../../../../store/builder/useBuilderStore"; +import { useSceneContext } from "../../../../modules/scene/sceneContext"; +import { useVersionContext } from "../../../../modules/builder/version/versionContext"; +import { useParams } from "react-router-dom"; +import { getUserData } from "../../../../functions/getUserData"; +import { useSocketStore } from "../../../../store/builder/store"; + +// import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsertFloorApi"; + +const SelectedFloorProperties = () => { + const [depth, setDepth] = useState(""); + const [isBeveled, setIsBeveled] = useState(false); + const [bevelStrength, setBevelStrength] = useState(""); + const { selectedFloor } = useBuilderStore(); + const { floorStore } = useSceneContext(); + const { selectedVersionStore } = useVersionContext(); + const { selectedVersion } = selectedVersionStore(); + const { socket } = useSocketStore(); + const { userId, organization } = getUserData(); + const { projectId } = useParams(); + const { getFloorById, updateFloor } = floorStore(); + + const [activeSurface, setActiveSurface] = useState<"top" | "side">("top"); + + const materials = [ + { texture: defaultTexture, textureId: "Default Material", textureName: "Default Material" }, + { texture: floorTexture1, textureId: "Material 1", textureName: "Grunge Concrete" } + ]; + + const floor = selectedFloor ? getFloorById(selectedFloor.userData.floorUuid) : null; + + useEffect(() => { + if (floor) { + setDepth(floor.floorDepth.toString()); + setIsBeveled(floor.isBeveled); + setBevelStrength(floor.bevelStrength.toString()); + } + }, [floor]); + + const handleDepthChange = (val: string) => { + setDepth(val); + const parsed = parseFloat(val); + if (!isNaN(parsed) && floor) { + const updatedFloor = updateFloor(floor.floorUuid, { floorDepth: parsed }); + if (projectId) { + + // API + + // upsertFloorApi(projectId, selectedVersion?.versionId || '', floor); + + // SOCKET + + const data = { + floorData: updatedFloor, + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization + } + + socket.emit('v1:model-Floor:add', data); + } + } + }; + + const handleBevelChange = (val: string) => { + setBevelStrength(val); + const parsed = parseFloat(val); + if (!isNaN(parsed) && floor) { + const updatedFloor = updateFloor(floor.floorUuid, { bevelStrength: parsed }); + if (projectId) { + + // API + + // upsertFloorApi(projectId, selectedVersion?.versionId || '', floor); + + // SOCKET + + const data = { + floorData: updatedFloor, + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization + } + + socket.emit('v1:model-Floor:add', data); + } + } + }; + + const handleIsBeveledToggle = () => { + setIsBeveled(!isBeveled); + if (!floor) return; + const updatedFloor = updateFloor(floor.floorUuid, { isBeveled: !floor.isBeveled }); + if (projectId) { + + // API + + // upsertFloorApi(projectId, selectedVersion?.versionId || '', floor); + + // SOCKET + + const data = { + floorData: updatedFloor, + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization + } + + socket.emit('v1:model-Floor:add', data); + } + + }; + + const handleSelectMaterial = (material: { textureId: string; textureName: string }) => { + if (!floor) return; + const key = activeSurface === "top" ? "topMaterial" : "sideMaterial"; + const updatedFloor = updateFloor(floor.floorUuid, { [key]: material.textureId }); + if (projectId) { + + // API + + // upsertFloorApi(projectId, selectedVersion?.versionId || '', floor); + + // SOCKET + + const data = { + floorData: updatedFloor, + projectId: projectId, + versionId: selectedVersion?.versionId || '', + userId: userId, + organization: organization + } + + socket.emit('v1:model-Floor:add', data); + } + + }; + + if (!floor) return null; + + const selectedMaterials = { + top: materials.find((m) => m.textureId === floor.topMaterial) ?? materials[0], + side: materials.find((m) => m.textureId === floor.sideMaterial) ?? materials[0], + }; + + return ( +
+
+
Floor
+
+ + + +
+
+ +
+
+
Materials
+
+ +
+
+ {(["top", "side"] as const).map((surface) => ( + + ))} +
+ +
+ {selectedMaterials[activeSurface].textureName} +
+
+ +
+
+ {materials.map((material, index) => { + const isSelected = selectedMaterials[activeSurface].textureId === material.textureId; + return ( + + ); + })} +
+
+
+
+ ); +}; + +export default SelectedFloorProperties; diff --git a/app/src/components/layout/sidebarRight/properties/SelectedWallProperties.tsx b/app/src/components/layout/sidebarRight/properties/SelectedWallProperties.tsx index b5099d5..517927c 100644 --- a/app/src/components/layout/sidebarRight/properties/SelectedWallProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/SelectedWallProperties.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; import defaultTexture from '../../../../assets/textures/floor/wall-tex.png'; @@ -8,11 +8,14 @@ import { useBuilderStore } from "../../../../store/builder/useBuilderStore"; import { useSceneContext } from "../../../../modules/scene/sceneContext"; import { useVersionContext } from "../../../../modules/builder/version/versionContext"; import { useParams } from "react-router-dom"; -import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi"; import { getUserData } from "../../../../functions/getUserData"; import { useSocketStore } from "../../../../store/builder/store"; +// import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi"; + const SelectedWallProperties = () => { + const [height, setHeight] = useState(""); + const [thickness, setThickness] = useState(""); const { selectedWall } = useBuilderStore(); const { wallStore } = useSceneContext(); const { selectedVersionStore } = useVersionContext(); @@ -31,7 +34,15 @@ const SelectedWallProperties = () => { const wall = selectedWall ? getWallById(selectedWall.userData.wallUuid) : null; + useEffect(() => { + if (wall) { + setHeight(wall.wallHeight.toString()); + setThickness(wall.wallThickness.toString()); + } + }, [wall, selectedWall]); + const handleHeightChange = (val: string) => { + setHeight(val); const height = parseFloat(val); if (!isNaN(height) && wall) { const updatedWall = updateWall(wall.wallUuid, { wallHeight: height }); @@ -57,6 +68,7 @@ const SelectedWallProperties = () => { }; const handleThicknessChange = (val: string) => { + setThickness(val); const thickness = parseFloat(val); if (!isNaN(thickness) && wall) { const updatedWall = updateWall(wall.wallUuid, { wallThickness: thickness }); @@ -109,16 +121,8 @@ const SelectedWallProperties = () => { if (!wall) return null; const selectedMaterials = { - side1: { - texture: materials.find((material) => material.textureId === wall.insideMaterial)?.texture || 'Unknown', - textureId: materials.find((material) => material.textureId === wall.insideMaterial)?.textureId || 'Unknown', - textureName: materials.find((material) => material.textureId === wall.insideMaterial)?.textureName || 'Unknown' - }, - side2: { - texture: materials.find((material) => material.textureId === wall.outsideMaterial)?.texture || 'Unknown', - textureId: materials.find((material) => material.textureId === wall.outsideMaterial)?.textureId || 'Unknown', - textureName: materials.find((material) => material.textureId === wall.outsideMaterial)?.textureName || 'Unknown' - } + side1: materials.find((m) => m.textureId === wall.insideMaterial) ?? materials[0], + side2: materials.find((m) => m.textureId === wall.outsideMaterial) ?? materials[0] }; return ( @@ -128,12 +132,12 @@ const SelectedWallProperties = () => {
diff --git a/app/src/components/layout/sidebarRight/properties/WallProperties.tsx b/app/src/components/layout/sidebarRight/properties/WallProperties.tsx index eb835f1..ae17c1f 100644 --- a/app/src/components/layout/sidebarRight/properties/WallProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/WallProperties.tsx @@ -10,163 +10,152 @@ import { useBuilderStore } from "../../../../store/builder/useBuilderStore"; // Define Material type type Material = { - texture: string; - textureName: string; + texture: string; + textureId: string; + textureName: string; }; -// Default and initial materials -const defaultMaterial: Material = { - texture: defaultTexture, - textureName: "Default Material", -}; - -const initialMaterial: Material = { - texture: wallTexture1, - textureName: "Grunge Concrete Wall", -}; +const materials = [ + { texture: defaultTexture, textureId: "Default Material", textureName: "Default Material" }, + { texture: wallTexture1, textureId: "Material 1", textureName: "Grunge Concrete Wall" } +]; const WallProperties = () => { - const { wallHeight, wallThickness, setWallHeight, setWallThickness } = useBuilderStore(); + const { wallHeight, wallThickness, insideMaterial, outsideMaterial, setWallHeight, setWallThickness } = useBuilderStore(); - const [activeSide, setActiveSide] = useState<"side1" | "side2">("side1"); + const [activeSide, setActiveSide] = useState<"side1" | "side2">("side1"); - const [materials, setMaterials] = useState([ - defaultMaterial, - initialMaterial, - ]); - - const [selectedMaterials, setSelectedMaterials] = useState<{ - side1: Material | null; - side2: Material | null; - }>({ - side1: null, - side2: null, - }); - - // Set default material initially for both sides - useEffect(() => { - setSelectedMaterials({ - side1: defaultMaterial, - side2: defaultMaterial, + const [selectedMaterials, setSelectedMaterials] = useState<{ + side1: Material | null; + side2: Material | null; + }>({ + side1: null, + side2: null, }); - }, []); - const handleHeightChange = (newValue: string) => { - setWallHeight(parseFloat(newValue)); - }; + useEffect(() => { + setSelectedMaterials({ + side1: materials.find((mat) => mat.textureId === outsideMaterial) || null, + side2: materials.find((mat) => mat.textureId === insideMaterial) || null, + }); + }, []); - const handleThicknessChange = (newValue: string) => { - setWallThickness(parseFloat(newValue)); - }; + const handleHeightChange = (newValue: string) => { + setWallHeight(parseFloat(newValue)); + }; - const handleSelectMaterial = (material: Material) => { - setSelectedMaterials((prev) => ({ - ...prev, - [activeSide]: material, - })); - }; + const handleThicknessChange = (newValue: string) => { + setWallThickness(parseFloat(newValue)); + }; - return ( -
-
-
Wall
-
- handleHeightChange(val)} - /> - handleThicknessChange(val)} - /> -
-
-
-
-
Materials
-
+ const handleSelectMaterial = (material: Material) => { + setSelectedMaterials((prev) => ({ + ...prev, + [activeSide]: material, + })); + }; -
-
- + return ( +
+
+
Wall
+
+ handleHeightChange(val)} + /> + handleThicknessChange(val)} + /> +
+
+
+
+
Materials
+
- -
+
+
+ -
- {selectedMaterials[activeSide] && ( - {selectedMaterials[activeSide]!.textureName} - )} -
-
- -
- {materials.length === 0 ? ( -
No materials added yet.
- ) : ( -
- {materials.map((material, index) => { - const isSelected = selectedMaterials[activeSide]?.texture === material.texture; - - return ( -
- - ); - })} -
- )} + +
+ {selectedMaterials[activeSide] && ( + {selectedMaterials[activeSide]!.textureName} + )} +
+
+ +
+ {materials.length === 0 ? ( +
No materials added yet.
+ ) : ( +
+ {materials.map((material, index) => { + const isSelected = selectedMaterials[activeSide]?.texture === material.texture; + + return ( + + ); + })} +
+ )} +
+
- - - ); + ); }; export default WallProperties; diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arcAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arcAisle.tsx index d4c27b6..bc09b68 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arcAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arcAisle.tsx @@ -78,7 +78,7 @@ function ArcAisle({ aisle }: { readonly aisle: Aisle }) { position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} rotation={[Math.PI / 2, 0, 0]} userData={aisle} - onClick={handleClick} + onDoubleClick={handleClick} onPointerMissed={() => { setSelectedAisle(null); }} diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowAisle.tsx index 941fb7f..49bf666 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowAisle.tsx @@ -65,7 +65,7 @@ function ArrowAisle({ aisle }: { readonly aisle: Aisle }) { position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} rotation={[Math.PI / 2, 0, 0]} userData={aisle} - onClick={handleClick} + onDoubleClick={handleClick} onPointerMissed={() => { setSelectedAisle(null); }} diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowsAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowsAisle.tsx index 5dc6ee7..8bc6fd5 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowsAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/arrowsAisle.tsx @@ -68,7 +68,7 @@ function ArrowsAisle({ aisle }: { readonly aisle: Aisle }) { position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} rotation={[Math.PI / 2, 0, 0]} userData={aisle} - onClick={handleClick} + onDoubleClick={handleClick} onPointerMissed={() => { setSelectedAisle(null); }} diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/circleAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/circleAisle.tsx index 6d838de..af852e8 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/circleAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/circleAisle.tsx @@ -53,7 +53,7 @@ function CircleAisle({ aisle }: { readonly aisle: Aisle }) { position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} rotation={[Math.PI / 2, 0, 0]} userData={aisle} - onClick={handleClick} + onDoubleClick={handleClick} onPointerMissed={() => { setSelectedAisle(null); }} diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dashedAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dashedAisle.tsx index 0c3eb7f..bbdad90 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dashedAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dashedAisle.tsx @@ -66,7 +66,7 @@ function DashedAisle({ aisle }: { readonly aisle: Aisle }) { position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} rotation={[Math.PI / 2, 0, 0]} userData={aisle} - onClick={handleClick} + onDoubleClick={handleClick} onPointerMissed={() => { setSelectedAisle(null); }} diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dottedAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dottedAisle.tsx index f701fba..bf17d08 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dottedAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/dottedAisle.tsx @@ -53,7 +53,7 @@ function DottedAisle({ aisle }: { readonly aisle: Aisle }) { position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} rotation={[Math.PI / 2, 0, 0]} userData={aisle} - onClick={handleClick} + onDoubleClick={handleClick} onPointerMissed={() => { setSelectedAisle(null); }} diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/junctionAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/junctionAisle.tsx index 23ea6e6..a3f8bdf 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/junctionAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/junctionAisle.tsx @@ -100,7 +100,7 @@ function JunctionAisle({ aisle }: { readonly aisle: Aisle }) { position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} rotation={[Math.PI / 2, 0, 0]} userData={aisle} - onClick={handleClick} + onDoubleClick={handleClick} onPointerMissed={() => { setSelectedAisle(null); }} diff --git a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/solidAisle.tsx b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/solidAisle.tsx index ed78112..e9321b0 100644 --- a/app/src/modules/builder/aisle/Instances/instance/aisleTypes/solidAisle.tsx +++ b/app/src/modules/builder/aisle/Instances/instance/aisleTypes/solidAisle.tsx @@ -50,7 +50,7 @@ function SolidAisle({ aisle }: { readonly aisle: Aisle }) { position={[0, (aisle.points[0].layer - 1) * Constants.wallConfig.height + 0.01, 0]} rotation={[Math.PI / 2, 0, 0]} userData={aisle} - onClick={handleClick} + onDoubleClick={handleClick} onPointerMissed={() => { setSelectedAisle(null); }} diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx index b597ab3..2b923f8 100644 --- a/app/src/modules/builder/asset/assetsGroup.tsx +++ b/app/src/modules/builder/asset/assetsGroup.tsx @@ -26,7 +26,7 @@ const gltfLoaderWorker = new Worker( function AssetsGroup({ floorGroup, plane }: { readonly floorGroup: RefGroup, readonly plane: RefMesh }) { const { activeModule } = useModuleStore(); const { socket } = useSocketStore(); - const { controls, gl, pointer, camera, raycaster } = useThree(); + const { controls, gl, pointer, camera, raycaster, scene } = useThree(); const { setLoadingProgress } = useLoadingProgress(); const { assetStore, eventStore } = useSceneContext(); const { selectedVersionStore } = useVersionContext(); @@ -277,7 +277,7 @@ function AssetsGroup({ floorGroup, plane }: { readonly floorGroup: RefGroup, rea pointer.x = (event.clientX / window.innerWidth) * 2 - 1; pointer.y = -(event.clientY / window.innerHeight) * 2 + 1; - addAssetModel(raycaster, camera, pointer, floorGroup, socket, selectedItem, setSelectedItem, addEvent, addAsset, plane, selectedVersion, projectId, userId); + addAssetModel(scene, raycaster, camera, pointer, socket, selectedItem, setSelectedItem, addEvent, addAsset, plane, selectedVersion, projectId, userId); } }; diff --git a/app/src/modules/builder/asset/functions/addAssetModel.ts b/app/src/modules/builder/asset/functions/addAssetModel.ts index 2eaa744..3977fa7 100644 --- a/app/src/modules/builder/asset/functions/addAssetModel.ts +++ b/app/src/modules/builder/asset/functions/addAssetModel.ts @@ -10,489 +10,438 @@ import PointsCalculator from "../../../simulation/events/points/functions/points import { getUserData } from "../../../../functions/getUserData"; async function addAssetModel( - raycaster: THREE.Raycaster, - camera: THREE.Camera, - pointer: THREE.Vector2, - floorGroup: Types.RefGroup, - socket: Socket, - selectedItem: any, - setSelectedItem: any, - addEvent: (event: EventsSchema) => void, - addAsset: (asset: Asset) => void, - plane: Types.RefMesh, - selectedVersion?: Version | null, - projectId?: string, - userId?: string + scene: THREE.Scene, + raycaster: THREE.Raycaster, + camera: THREE.Camera, + pointer: THREE.Vector2, + socket: Socket, + selectedItem: any, + setSelectedItem: any, + addEvent: (event: EventsSchema) => void, + addAsset: (asset: Asset) => void, + plane: Types.RefMesh, + selectedVersion?: Version | null, + projectId?: string, + userId?: string ): Promise { - ////////// Load Floor GLtf's and set the positions, rotation, type etc. in state and store in localstorage ////////// + ////////// Load Floor GLtf's and set the positions, rotation, type etc. in state and store in localstorage ////////// - let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; + let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; - try { - const loader = new GLTFLoader(); - const dracoLoader = new DRACOLoader(); + try { + 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); + dracoLoader.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/"); + loader.setDRACOLoader(dracoLoader); - raycaster.setFromCamera(pointer, camera); - const floorIntersections = raycaster.intersectObjects( - floorGroup.current.children, - true - ); - const intersectedFloor = floorIntersections.find((intersect) => - intersect.object.name.includes("Floor") - ); + raycaster.setFromCamera(pointer, camera); + const wallFloorsGroup = scene.getObjectByName("Walls-Floors-Group") as Types.Group | null; + const floorsGroup = scene.getObjectByName("Floors-Group") as Types.Group | null; + const floorChildren = floorsGroup?.children ?? []; + const wallFloorChildren = wallFloorsGroup?.children ?? []; + const floorIntersections = raycaster.intersectObjects([...floorChildren, ...wallFloorChildren], true); + const intersectedFloor = floorIntersections.find((intersect) => intersect.object.name.includes("Floor")); - const planeIntersections = raycaster.intersectObject(plane.current!, true); - const intersectedPlane = planeIntersections[0]; + const planeIntersections = raycaster.intersectObject(plane.current!, true); + const intersectedPlane = planeIntersections[0]; - let intersectPoint: THREE.Vector3 | null = null; + let intersectPoint: THREE.Vector3 | null = null; - if (intersectedFloor && intersectedPlane) { - intersectPoint = - intersectedFloor.distance < intersectedPlane.distance - ? new THREE.Vector3( - intersectedFloor.point.x, - Math.round(intersectedFloor.point.y), - intersectedFloor.point.z - ) - : new THREE.Vector3( - intersectedPlane.point.x, - 0, - intersectedPlane.point.z - ); - } else if (intersectedFloor) { - intersectPoint = new THREE.Vector3( - intersectedFloor.point.x, - Math.round(intersectedFloor.point.y), - intersectedFloor.point.z - ); - } else if (intersectedPlane) { - intersectPoint = new THREE.Vector3( - intersectedPlane.point.x, - 0, - intersectedPlane.point.z - ); - } - - if (intersectPoint) { - if (intersectPoint.y < 0) { - intersectPoint = new THREE.Vector3( - intersectPoint.x, - 0, - intersectPoint.z - ); - } - const cachedModel = THREE.Cache.get(selectedItem.id); - if (cachedModel) { - handleModelLoad( - cachedModel, - intersectPoint!, - selectedItem, - addEvent, - addAsset, - socket, - selectedVersion?.versionId || '', - projectId, - userId - ); - return; - } else { - const cachedModelBlob = await retrieveGLTF(selectedItem.id); - if (cachedModelBlob) { - const blobUrl = URL.createObjectURL(cachedModelBlob); - loader.load(blobUrl, (gltf) => { - URL.revokeObjectURL(blobUrl); - THREE.Cache.remove(blobUrl); - THREE.Cache.add(selectedItem.id, gltf); - handleModelLoad( - gltf, - intersectPoint!, - selectedItem, - addEvent, - addAsset, - socket, - selectedVersion?.versionId || '', - projectId, - userId - ); - }); - } else { - loader.load( - `${url_Backend_dwinzo}/api/v2/AssetFile/${selectedItem.id}`, - async (gltf) => { - 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, - addEvent, - addAsset, - socket, - selectedVersion?.versionId || '', - projectId, - userId - ); + if (intersectedFloor && intersectedPlane) { + // intersectPoint = intersectedFloor.distance < intersectedPlane.distance ? + // new THREE.Vector3(intersectedFloor.point.x, Math.round(intersectedFloor.point.y), intersectedFloor.point.z) + // : new THREE.Vector3(intersectedPlane.point.x, 0, intersectedPlane.point.z); + if (intersectedFloor.distance < intersectedPlane.distance) { + if (intersectedFloor.object.userData.floorUuid) { + intersectPoint = new THREE.Vector3(intersectedFloor.point.x, intersectedFloor.object.userData.floorDepth, intersectedFloor.point.z); + } else { + intersectPoint = new THREE.Vector3(intersectedFloor.point.x, 0, intersectedFloor.point.z); + } + } else { + intersectPoint = new THREE.Vector3(intersectedPlane.point.x, 0, intersectedPlane.point.z); } - ); + } else if (intersectedFloor) { + intersectPoint = new THREE.Vector3(intersectedFloor.point.x, Math.round(intersectedFloor.point.y), intersectedFloor.point.z); + } else if (intersectedPlane) { + intersectPoint = new THREE.Vector3(intersectedPlane.point.x, 0, intersectedPlane.point.z); } - } + + if (intersectPoint) { + + if (intersectPoint.y < 0) { + intersectPoint = new THREE.Vector3(intersectPoint.x, 0, intersectPoint.z); + } + const cachedModel = THREE.Cache.get(selectedItem.id); + if (cachedModel) { + handleModelLoad(cachedModel, intersectPoint!, selectedItem, addEvent, addAsset, socket, selectedVersion?.versionId || '', projectId, userId); + return; + } else { + const cachedModelBlob = await retrieveGLTF(selectedItem.id); + if (cachedModelBlob) { + const blobUrl = URL.createObjectURL(cachedModelBlob); + loader.load(blobUrl, (gltf) => { + URL.revokeObjectURL(blobUrl); + THREE.Cache.remove(blobUrl); + THREE.Cache.add(selectedItem.id, gltf); + handleModelLoad(gltf, intersectPoint!, selectedItem, addEvent, addAsset, socket, selectedVersion?.versionId || '', projectId, userId); + }); + } else { + loader.load(`${url_Backend_dwinzo}/api/v2/AssetFile/${selectedItem.id}`, + async (gltf) => { + 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, addEvent, addAsset, socket, selectedVersion?.versionId || '', projectId, userId); + } + ); + } + } + } + } catch (error) { + echo.error("Failed to add asset"); + } finally { + setSelectedItem({}); } - } catch (error) { - echo.error("Failed to add asset"); - } finally { - setSelectedItem({}); - } } async function handleModelLoad( - gltf: any, - intersectPoint: THREE.Vector3, - selectedItem: any, - addEvent: (event: EventsSchema) => void, - addAsset: (asset: Asset) => void, - socket: Socket, - versionId: string, - projectId?: string, - userId?: string + gltf: any, + intersectPoint: THREE.Vector3, + selectedItem: any, + addEvent: (event: EventsSchema) => void, + addAsset: (asset: Asset) => void, + socket: Socket, + versionId: string, + projectId?: string, + userId?: string ) { - const { organization } = getUserData(); - const model = gltf.scene.clone(); - model.userData = { - name: selectedItem.name, - modelId: selectedItem.id, - modelUuid: model.uuid, - }; - model.position.set(intersectPoint!.x, intersectPoint!.y, intersectPoint!.z); - model.scale.set(...CONSTANTS.assetConfig.defaultScaleAfterGsap); - - model.traverse((child: any) => { - if (child) { - child.castShadow = true; - child.receiveShadow = true; - } - }); - - const newFloorItem: Asset = { - modelUuid: model.uuid, - modelName: selectedItem.name, - assetId: selectedItem.id, - position: [intersectPoint!.x, intersectPoint!.y, intersectPoint!.z], - rotation: [0, 0, 0], - isLocked: false, - isVisible: true, - isCollidable: false, - opacity: 1, - }; - - - // API - - // await setAssetsApi( - // organization, - // newFloorItem.modelUuid, - // newFloorItem.modelName, - // newFloorItem.assetId, - // newFloorItem.position, - // { x: 0, y: 0, z: 0 }, - // false, - // true, - // ); - - // SOCKET - - if (selectedItem.type) { - const data = PointsCalculator( - selectedItem.type, - gltf.scene.clone(), - new THREE.Vector3(...model.rotation) - ); - - if (!data || !data.points) return; - - const eventData: any = { - type: selectedItem.type, + const { organization } = getUserData(); + const model = gltf.scene.clone(); + model.userData = { + name: selectedItem.name, + modelId: selectedItem.id, + modelUuid: model.uuid, }; + model.position.set(intersectPoint!.x, intersectPoint!.y, intersectPoint!.z); + model.scale.set(...CONSTANTS.assetConfig.defaultScaleAfterGsap); - if (selectedItem.type === "Conveyor") { - const ConveyorEvent: ConveyorEventSchema = { - modelUuid: newFloorItem.modelUuid, - modelName: newFloorItem.modelName, - position: newFloorItem.position, - rotation: newFloorItem.rotation, - state: "idle", - type: "transfer", - speed: 1, - points: data.points.map((point: THREE.Vector3, index: number) => { - const triggers: TriggerSchema[] = []; - - if (data.points && index < data.points.length - 1) { - triggers.push({ - triggerUuid: THREE.MathUtils.generateUUID(), - triggerName: `Trigger 1`, - triggerType: "onComplete", - delay: 0, - triggeredAsset: { - triggeredModel: { - modelName: newFloorItem.modelName, - modelUuid: newFloorItem.modelUuid, - }, - triggeredPoint: { - pointName: `Point`, - pointUuid: "", - }, - triggeredAction: { - actionName: `Action 1`, - actionUuid: "", - }, - }, - }); - } - - return { - uuid: THREE.MathUtils.generateUUID(), - position: [point.x, point.y, point.z], - rotation: [0, 0, 0], - action: { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: `Action 1`, - actionType: "default", - material: "Default Material", - delay: 0, - spawnInterval: 5, - spawnCount: 1, - triggers: triggers, - }, - }; - }), - }; - - for (let i = 0; i < ConveyorEvent.points.length - 1; i++) { - const currentPoint = ConveyorEvent.points[i]; - const nextPoint = ConveyorEvent.points[i + 1]; - - if (currentPoint.action.triggers.length > 0) { - currentPoint.action.triggers[0].triggeredAsset!.triggeredPoint!.pointUuid = - nextPoint.uuid; - currentPoint.action.triggers[0].triggeredAsset!.triggeredAction!.actionUuid = - nextPoint.action.actionUuid; + model.traverse((child: any) => { + if (child) { + child.castShadow = true; + child.receiveShadow = true; } - } - addEvent(ConveyorEvent); - eventData.points = ConveyorEvent.points.map((point) => ({ - uuid: point.uuid, - position: point.position, - rotation: point.rotation, - })); - } else if (selectedItem.type === "Vehicle") { - const vehicleEvent: VehicleEventSchema = { - modelUuid: newFloorItem.modelUuid, - modelName: newFloorItem.modelName, - position: newFloorItem.position, - rotation: newFloorItem.rotation, - state: "idle", - type: "vehicle", - speed: 1, - point: { - uuid: THREE.MathUtils.generateUUID(), - position: [data.points[0].x, data.points[0].y, data.points[0].z], - rotation: [0, 0, 0], - action: { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Action 1", - actionType: "travel", - unLoadDuration: 5, - loadCapacity: 1, - steeringAngle: 0, - pickUpPoint: null, - unLoadPoint: null, - triggers: [], - }, - }, - }; - addEvent(vehicleEvent); - eventData.point = { - uuid: vehicleEvent.point.uuid, - position: vehicleEvent.point.position, - rotation: vehicleEvent.point.rotation, - }; - } else if (selectedItem.type === "ArmBot") { - const roboticArmEvent: RoboticArmEventSchema = { - modelUuid: newFloorItem.modelUuid, - modelName: newFloorItem.modelName, - position: newFloorItem.position, - rotation: newFloorItem.rotation, - state: "idle", - type: "roboticArm", - speed: 1, - point: { - uuid: THREE.MathUtils.generateUUID(), - position: [data.points[0].x, data.points[0].y, data.points[0].z], - rotation: [0, 0, 0], - actions: [ - { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Action 1", - actionType: "pickAndPlace", - process: { - startPoint: null, - endPoint: null, - }, - triggers: [], + }); + + const newFloorItem: Asset = { + modelUuid: model.uuid, + modelName: selectedItem.name, + assetId: selectedItem.id, + position: [intersectPoint!.x, intersectPoint!.y, intersectPoint!.z], + rotation: [0, 0, 0], + isLocked: false, + isVisible: true, + isCollidable: false, + opacity: 1, + }; + + + // API + + // await setAssetsApi( + // organization, + // newFloorItem.modelUuid, + // newFloorItem.modelName, + // newFloorItem.assetId, + // newFloorItem.position, + // { x: 0, y: 0, z: 0 }, + // false, + // true, + // ); + + // SOCKET + + if (selectedItem.type) { + const data = PointsCalculator( + selectedItem.type, + gltf.scene.clone(), + new THREE.Vector3(...model.rotation) + ); + + if (!data || !data.points) return; + + const eventData: any = { type: selectedItem.type, }; + + if (selectedItem.type === "Conveyor") { + const ConveyorEvent: ConveyorEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: newFloorItem.rotation, + state: "idle", + type: "transfer", + speed: 1, + points: data.points.map((point: THREE.Vector3, index: number) => { + const triggers: TriggerSchema[] = []; + + if (data.points && index < data.points.length - 1) { + triggers.push({ + triggerUuid: THREE.MathUtils.generateUUID(), + triggerName: `Trigger 1`, + triggerType: "onComplete", + delay: 0, + triggeredAsset: { + triggeredModel: { + modelName: newFloorItem.modelName, + modelUuid: newFloorItem.modelUuid, + }, + triggeredPoint: { + pointName: `Point`, + pointUuid: "", + }, + triggeredAction: { + actionName: `Action 1`, + actionUuid: "", + }, + }, + }); + } + + return { + uuid: THREE.MathUtils.generateUUID(), + position: [point.x, point.y, point.z], + rotation: [0, 0, 0], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: `Action 1`, + actionType: "default", + material: "Default Material", + delay: 0, + spawnInterval: 5, + spawnCount: 1, + triggers: triggers, + }, + }; + }), + }; + + for (let i = 0; i < ConveyorEvent.points.length - 1; i++) { + const currentPoint = ConveyorEvent.points[i]; + const nextPoint = ConveyorEvent.points[i + 1]; + + if (currentPoint.action.triggers.length > 0) { + currentPoint.action.triggers[0].triggeredAsset!.triggeredPoint!.pointUuid = nextPoint.uuid; + currentPoint.action.triggers[0].triggeredAsset!.triggeredAction!.actionUuid = nextPoint.action.actionUuid; + } + } + addEvent(ConveyorEvent); + eventData.points = ConveyorEvent.points.map((point) => ({ + uuid: point.uuid, + position: point.position, + rotation: point.rotation, + })); + } else if (selectedItem.type === "Vehicle") { + const vehicleEvent: VehicleEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: newFloorItem.rotation, + state: "idle", + type: "vehicle", + speed: 1, + point: { + uuid: THREE.MathUtils.generateUUID(), + position: [data.points[0].x, data.points[0].y, data.points[0].z], + rotation: [0, 0, 0], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "travel", + unLoadDuration: 5, + loadCapacity: 1, + steeringAngle: 0, + pickUpPoint: null, + unLoadPoint: null, + triggers: [], + }, + }, + }; + addEvent(vehicleEvent); + eventData.point = { + uuid: vehicleEvent.point.uuid, + position: vehicleEvent.point.position, + rotation: vehicleEvent.point.rotation, + }; + } else if (selectedItem.type === "ArmBot") { + const roboticArmEvent: RoboticArmEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: newFloorItem.rotation, + state: "idle", + type: "roboticArm", + speed: 1, + point: { + uuid: THREE.MathUtils.generateUUID(), + position: [data.points[0].x, data.points[0].y, data.points[0].z], + rotation: [0, 0, 0], + actions: [ + { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "pickAndPlace", + process: { + startPoint: null, + endPoint: null, + }, + triggers: [], + }, + ], + }, + }; + addEvent(roboticArmEvent); + eventData.point = { + uuid: roboticArmEvent.point.uuid, + position: roboticArmEvent.point.position, + rotation: roboticArmEvent.point.rotation, + }; + } else if (selectedItem.type === "StaticMachine") { + const machineEvent: MachineEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: newFloorItem.rotation, + state: "idle", + type: "machine", + point: { + uuid: THREE.MathUtils.generateUUID(), + position: [data.points[0].x, data.points[0].y, data.points[0].z], + rotation: [0, 0, 0], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "process", + processTime: 10, + swapMaterial: "Default Material", + triggers: [], + }, + }, + }; + addEvent(machineEvent); + eventData.point = { + uuid: machineEvent.point.uuid, + position: machineEvent.point.position, + rotation: machineEvent.point.rotation, + }; + } else if (selectedItem.type === "Storage") { + const storageEvent: StorageEventSchema = { + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + position: newFloorItem.position, + rotation: newFloorItem.rotation, + state: "idle", + type: "storageUnit", + point: { + uuid: THREE.MathUtils.generateUUID(), + position: [data.points[0].x, data.points[0].y, data.points[0].z], + rotation: [0, 0, 0], + action: { + actionUuid: THREE.MathUtils.generateUUID(), + actionName: "Action 1", + actionType: "store", + storageCapacity: 10, + triggers: [], + }, + }, + }; + addEvent(storageEvent); + eventData.point = { + uuid: storageEvent.point.uuid, + position: storageEvent.point.position, + rotation: storageEvent.point.rotation, + }; + } + + const completeData = { + organization, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + assetId: newFloorItem.assetId, + position: newFloorItem.position, + rotation: { + x: model.rotation.x, + y: model.rotation.y, + z: model.rotation.z, }, - ], - }, - }; - addEvent(roboticArmEvent); - eventData.point = { - uuid: roboticArmEvent.point.uuid, - position: roboticArmEvent.point.position, - rotation: roboticArmEvent.point.rotation, - }; - } else if (selectedItem.type === "StaticMachine") { - const machineEvent: MachineEventSchema = { - modelUuid: newFloorItem.modelUuid, - modelName: newFloorItem.modelName, - position: newFloorItem.position, - rotation: newFloorItem.rotation, - state: "idle", - type: "machine", - point: { - uuid: THREE.MathUtils.generateUUID(), - position: [data.points[0].x, data.points[0].y, data.points[0].z], - rotation: [0, 0, 0], - action: { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Action 1", - actionType: "process", - processTime: 10, - swapMaterial: "Default Material", - triggers: [], - }, - }, - }; - addEvent(machineEvent); - eventData.point = { - uuid: machineEvent.point.uuid, - position: machineEvent.point.position, - rotation: machineEvent.point.rotation, - }; - } else if (selectedItem.type === "Storage") { - const storageEvent: StorageEventSchema = { - modelUuid: newFloorItem.modelUuid, - modelName: newFloorItem.modelName, - position: newFloorItem.position, - rotation: newFloorItem.rotation, - state: "idle", - type: "storageUnit", - point: { - uuid: THREE.MathUtils.generateUUID(), - position: [data.points[0].x, data.points[0].y, data.points[0].z], - rotation: [0, 0, 0], - action: { - actionUuid: THREE.MathUtils.generateUUID(), - actionName: "Action 1", - actionType: "store", - storageCapacity: 10, - triggers: [], - }, - }, - }; - addEvent(storageEvent); - eventData.point = { - uuid: storageEvent.point.uuid, - position: storageEvent.point.position, - rotation: storageEvent.point.rotation, - }; + isLocked: false, + isVisible: true, + socketId: socket.id, + eventData: eventData, + versionId: versionId, + projectId: projectId, + userId: userId, + }; + + socket.emit("v1:model-asset:add", completeData); + + const asset: Asset = { + modelUuid: completeData.modelUuid, + modelName: completeData.modelName, + assetId: completeData.assetId, + position: completeData.position, + rotation: [ + completeData.rotation.x, + completeData.rotation.y, + completeData.rotation.z, + ] as [number, number, number], + isLocked: completeData.isLocked, + isCollidable: false, + isVisible: completeData.isVisible, + opacity: 1, + eventData: completeData.eventData, + }; + + addAsset(asset); + } else { + const data = { + organization, + modelUuid: newFloorItem.modelUuid, + modelName: newFloorItem.modelName, + assetId: newFloorItem.assetId, + position: newFloorItem.position, + rotation: { + x: model.rotation.x, + y: model.rotation.y, + z: model.rotation.z, + }, + isLocked: false, + isVisible: true, + socketId: socket.id, + versionId: versionId, + projectId: projectId, + userId: userId, + }; + + socket.emit("v1:model-asset:add", data); + + const asset = { + modelUuid: data.modelUuid, + modelName: data.modelName, + assetId: data.assetId, + position: data.position, + rotation: [data.rotation.x, data.rotation.y, data.rotation.z] as [ + number, + number, + number + ], + isLocked: data.isLocked, + isCollidable: false, + isVisible: data.isVisible, + opacity: 1, + }; + + addAsset(asset); } - - const completeData = { - organization, - modelUuid: newFloorItem.modelUuid, - modelName: newFloorItem.modelName, - assetId: newFloorItem.assetId, - position: newFloorItem.position, - rotation: { - x: model.rotation.x, - y: model.rotation.y, - z: model.rotation.z, - }, - isLocked: false, - isVisible: true, - socketId: socket.id, - eventData: eventData, - versionId: versionId, - projectId: projectId, - userId: userId, - }; - - socket.emit("v1:model-asset:add", completeData); - - const asset: Asset = { - modelUuid: completeData.modelUuid, - modelName: completeData.modelName, - assetId: completeData.assetId, - position: completeData.position, - rotation: [ - completeData.rotation.x, - completeData.rotation.y, - completeData.rotation.z, - ] as [number, number, number], - isLocked: completeData.isLocked, - isCollidable: false, - isVisible: completeData.isVisible, - opacity: 1, - eventData: completeData.eventData, - }; - - addAsset(asset); - } else { - const data = { - organization, - modelUuid: newFloorItem.modelUuid, - modelName: newFloorItem.modelName, - assetId: newFloorItem.assetId, - position: newFloorItem.position, - rotation: { - x: model.rotation.x, - y: model.rotation.y, - z: model.rotation.z, - }, - isLocked: false, - isVisible: true, - socketId: socket.id, - versionId: versionId, - projectId: projectId, - userId: userId, - }; - - socket.emit("v1:model-asset:add", data); - - const asset = { - modelUuid: data.modelUuid, - modelName: data.modelName, - assetId: data.assetId, - position: data.position, - rotation: [data.rotation.x, data.rotation.y, data.rotation.z] as [ - number, - number, - number - ], - isLocked: data.isLocked, - isCollidable: false, - isVisible: data.isVisible, - opacity: 1, - }; - - addAsset(asset); - } } export default addAssetModel; diff --git a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx index ce82298..e5ed733 100644 --- a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx +++ b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx @@ -59,9 +59,9 @@ function FloorInstance({ floor }: { floor: Floor }) { receiveShadow name={`Floor-${floor.floorUuid}`} rotation={[Math.PI / 2, 0, 0]} - position={[0, floor.floorDepth, 0]} + position={[0, !floor.isBeveled ? floor.floorDepth : (floor.floorDepth - 0.1), 0]} userData={floor} - onClick={(e) => { + onDoubleClick={(e) => { if (!togglView && activeModule === 'builder') { if (e.object.userData.floorUuid) { setSelectedFloor(e.object); @@ -76,10 +76,14 @@ function FloorInstance({ floor }: { floor: Floor }) { }} > diff --git a/app/src/modules/builder/wall/Instances/instance/wall.tsx b/app/src/modules/builder/wall/Instances/instance/wall.tsx index a07e8f9..ff0e5ce 100644 --- a/app/src/modules/builder/wall/Instances/instance/wall.tsx +++ b/app/src/modules/builder/wall/Instances/instance/wall.tsx @@ -123,7 +123,7 @@ function Wall({ wall }: { readonly wall: Wall }) { rotation={[0, -angle, 0]} userData={wall} name={`WallReference_${wall.wallUuid}`} - onClick={(e) => { + onDoubleClick={(e) => { if (visible && !togglView && activeModule === 'builder') { if (e.object.userData.wallUuid) { setSelectedWall(e.object); diff --git a/app/src/modules/builder/wall/Instances/wallInstances.tsx b/app/src/modules/builder/wall/Instances/wallInstances.tsx index 40c60cd..267c91f 100644 --- a/app/src/modules/builder/wall/Instances/wallInstances.tsx +++ b/app/src/modules/builder/wall/Instances/wallInstances.tsx @@ -134,14 +134,15 @@ function Floor({ room }: { room: Point[] }) { if (!shape) return null; return ( - + - + ); } diff --git a/app/src/modules/builder/wall/wallCreator/wallCreator.tsx b/app/src/modules/builder/wall/wallCreator/wallCreator.tsx index c3a6c66..b31ad82 100644 --- a/app/src/modules/builder/wall/wallCreator/wallCreator.tsx +++ b/app/src/modules/builder/wall/wallCreator/wallCreator.tsx @@ -12,8 +12,8 @@ import getClosestIntersection from '../../geomentries/lines/getClosestIntersecti import ReferencePoint from '../../point/reference/referencePoint'; import ReferenceWall from './referenceWall'; -import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi'; -import { deleteWallApi } from '../../../../services/factoryBuilder/wall/deleteWallApi'; +// import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi'; +// import { deleteWallApi } from '../../../../services/factoryBuilder/wall/deleteWallApi'; function WallCreator() { const { scene, camera, raycaster, gl, pointer } = useThree(); diff --git a/app/src/modules/scene/controls/selectionControls/distanceFindingControls.tsx b/app/src/modules/scene/controls/selectionControls/distanceFindingControls.tsx index 4f2eb02..af654d6 100644 --- a/app/src/modules/scene/controls/selectionControls/distanceFindingControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/distanceFindingControls.tsx @@ -1,339 +1,208 @@ import React, { useRef, useState } from "react"; import { - Vector3, - Raycaster, - BufferGeometry, - LineBasicMaterial, - Line, - Mesh, - Group, + Vector3, + Raycaster, + BufferGeometry, + LineBasicMaterial, + Line, + Mesh, + Group, } from "three"; import { useThree, useFrame } from "@react-three/fiber"; import { Html } from "@react-three/drei"; interface DistanceFindingControlsProps { - boundingBoxRef: React.RefObject; - object: number; + boundingBoxRef: React.RefObject; + object: number; } +const material = new LineBasicMaterial({ color: "#d2baff" }); + +const DIRECTION_LABEL_MAP = { + textPosX: "textPosX", + textNegX: "textNegX", + textPosZ: "textPosZ", + textNegZ: "textNegZ", +} as const; + const DistanceFindingControls = ({ - boundingBoxRef, - object, + boundingBoxRef, + object, }: DistanceFindingControlsProps) => { - const { camera, scene } = useThree(); - const [labelValues, setLabelValues] = useState<{ - textPosX: any; - textNegX: any; - textPosZ: any; - textNegZ: any; - }>({ - textPosX: "", - textNegX: "", - textPosZ: "", - textNegZ: "", - }); + const { camera, scene } = useThree(); + const [labelValues, setLabelValues] = useState>({ + textPosX: "", + textNegX: "", + textPosZ: "", + textNegZ: "", + }); - // Refs for measurement lines - const line1 = useRef(null); - const line2 = useRef(null); - const line3 = useRef(null); - const line4 = useRef(null); - const line5 = useRef(null); - - // Refs for measurement text labels - const textPosX = useRef(null); - const textNegX = useRef(null); - const textPosZ = useRef(null); - const textNegZ = useRef(null); - const textPosY = useRef(null); - - // Store line geometries to avoid recreation - const lineGeometries = useRef({ - posX: new BufferGeometry(), - negX: new BufferGeometry(), - posZ: new BufferGeometry(), - negZ: new BufferGeometry(), - posY: new BufferGeometry(), - }); - - useFrame(() => { - if (!boundingBoxRef?.current) return; - - boundingBoxRef.current.geometry.computeBoundingBox(); - const bbox = boundingBoxRef.current.geometry.boundingBox; - - if (!bbox) return; - - const size = { - x: bbox.max.x - bbox.min.x, - y: bbox.max.y - bbox.min.y, - z: bbox.max.z - bbox.min.z, + const lineRefs = { + posX: useRef(null), + negX: useRef(null), + posZ: useRef(null), + negZ: useRef(null), + posY: useRef(null), }; - const vec = boundingBoxRef.current?.getWorldPosition(new Vector3()).clone(); + const textRefs = { + textPosX: useRef(null), + textNegX: useRef(null), + textPosZ: useRef(null), + textNegZ: useRef(null), + textPosY: useRef(null), + }; - if (!vec) return; - updateLine({ - line: line1.current, - geometry: lineGeometries.current.posX, - direction: new Vector3(1, 0, 0), // Positive X - angle: "pos", - mesh: textPosX, - vec, - size, + const lineGeometries = useRef({ + posX: new BufferGeometry(), + negX: new BufferGeometry(), + posZ: new BufferGeometry(), + negZ: new BufferGeometry(), + posY: new BufferGeometry(), }); - updateLine({ - line: line2.current, - geometry: lineGeometries.current.negX, - direction: new Vector3(-1, 0, 0), // Negative X - angle: "neg", - mesh: textNegX, - vec, - size, + + useFrame(() => { + const bboxMesh = boundingBoxRef?.current; + if (!bboxMesh) return; + + bboxMesh.geometry.computeBoundingBox(); + const bbox = bboxMesh.geometry.boundingBox; + if (!bbox) return; + + const size = { + x: bbox.max.x - bbox.min.x, + y: bbox.max.y - bbox.min.y, + z: bbox.max.z - bbox.min.z, + }; + + const center = bboxMesh.getWorldPosition(new Vector3()).clone(); + if (!center) return; + + updateLine("posX", new Vector3(1, 0, 0), "pos", size, center); + updateLine("negX", new Vector3(-1, 0, 0), "neg", size, center); + updateLine("posZ", new Vector3(0, 0, 1), "pos", size, center); + updateLine("negZ", new Vector3(0, 0, -1), "neg", size, center); + updateLine("posY", new Vector3(0, -1, 0), "posY", size, center); }); - updateLine({ - line: line3.current, - geometry: lineGeometries.current.posZ, - direction: new Vector3(0, 0, 1), // Positive Z - angle: "pos", - mesh: textPosZ, - vec, - size, - }); - updateLine({ - line: line4.current, - geometry: lineGeometries.current.negZ, - direction: new Vector3(0, 0, -1), // Negative Z - angle: "neg", - mesh: textNegZ, - vec, - size, - }); - updateLine({ - line: line5.current, - geometry: lineGeometries.current.posY, - direction: new Vector3(0, -1, 0), // Down (Y) - angle: "posY", - mesh: textPosY, - vec, - size, - }); - }); - const updateLine = ({ - line, - geometry, - direction, - angle, - mesh, - vec, - size, - }: { - line: Line | null; - geometry: BufferGeometry; - direction: Vector3; - angle: string; - mesh: React.RefObject; - vec: Vector3; - size: { x: number; y: number; z: number }; - }) => { - if (!line) return; + const updateLine = ( + key: keyof typeof lineRefs, + direction: Vector3, + angle: string, + size: { x: number; y: number; z: number }, + origin: Vector3 + ) => { + const line = lineRefs[key].current; + const geometry = lineGeometries.current[key]; + const mesh = textRefs[`text${key[0].toUpperCase() + key.slice(1)}` as keyof typeof textRefs]; - const points = []; + if (!line) return; - if (angle === "pos") { - points[0] = new Vector3(vec.x, vec.y, vec.z).add( - new Vector3((direction.x * size.x) / 2, 0, (direction.z * size.z) / 2) - ); - } else if (angle === "neg") { - points[0] = new Vector3(vec.x, vec.y, vec.z).sub( - new Vector3((-direction.x * size.x) / 2, 0, (-direction.z * size.z) / 2) - ); - } else if (angle === "posY") { - points[0] = new Vector3(vec.x, vec.y, vec.z).sub( - new Vector3(0, size.y / 2, 0) - ); - } + const points: Vector3[] = []; + const halfSize = new Vector3(size.x / 2, size.y / 2, size.z / 2); - const ray = new Raycaster(); - if (camera) ray.camera = camera; - ray.set(new Vector3(vec.x, vec.y, vec.z), direction); - ray.params.Line.threshold = 0.1; + if (angle === "pos") { + points[0] = origin.clone().add(direction.clone().multiply(halfSize)); + } else if (angle === "neg") { + points[0] = origin.clone().sub(direction.clone().multiply(halfSize)); + } else if (angle === "posY") { + points[0] = origin.clone().sub(new Vector3(0, size.y / 2, 0)); + } - // Find intersection points - const wallsGroup = scene.children.find((val) => - val?.name.includes("Walls") + const ray = new Raycaster(); + ray.camera = camera; + ray.set(origin, direction); + ray.params.Line.threshold = 0.1; + + const wallsGroup = scene.children.find((val) => + val?.name.includes("Walls") + ); + const intersects = wallsGroup + ? ray.intersectObjects([wallsGroup], true) + : []; + + const intersect = intersects.find((i) => + i.object.name.includes("Wall") + ); + + if (intersect) { + points[1] = angle !== "posY" ? intersect.point : new Vector3(origin.x, 0, origin.z); + } + + if (points[1]) { + geometry.dispose(); + geometry.setFromPoints(points); + line.geometry = geometry; + + const distance = points[0].distanceTo(points[1]).toFixed(2); + + if (mesh?.current) { + geometry.computeBoundingSphere(); + mesh.current.position.copy(geometry.boundingSphere!.center); + + const labelEl = document.getElementById(mesh.current.name); + if (labelEl) { + labelEl.innerText = `${distance}m`; + + if (DIRECTION_LABEL_MAP[labelEl.id as keyof typeof DIRECTION_LABEL_MAP]) { + setLabelValues((prev) => ({ + ...prev, + [labelEl.id]: distance, + })); + } + } + } + } else { + geometry.dispose(); + geometry.setFromPoints([new Vector3(), new Vector3()]); + line.geometry = geometry; + + const labelEl = document.getElementById(mesh?.current?.name ?? ""); + if (labelEl && DIRECTION_LABEL_MAP[labelEl.id as keyof typeof DIRECTION_LABEL_MAP]) { + labelEl.innerText = ""; + setLabelValues((prev) => ({ + ...prev, + [labelEl.id]: "", + })); + } + } + }; + + const renderLabel = (id: keyof typeof textRefs) => ( + + +
{labelValues[id]}
+ +
); - const intersects = wallsGroup - ? ray.intersectObjects([wallsGroup], true) - : []; - // Find intersection point - if (intersects[0]) { - for (const intersect of intersects) { - if (intersect.object.name.includes("Wall")) { - points[1] = - angle !== "posY" ? intersect.point : new Vector3(vec.x, 0, vec.z); // Floor - break; - } - } - } - if (points[1]) { - geometry.dispose(); - geometry.setFromPoints([points[0], points[1]]); - line.geometry = geometry; - - // Calculate the distance only once - const distance = points[0].distanceTo(points[1]).toFixed(2); - - // Update measurement text - if (mesh?.current) { - geometry.computeBoundingSphere(); - const center = geometry.boundingSphere?.center; - if (center) { - mesh.current.position.copy(center); - } - - const label = document.getElementById(mesh.current.name); - if (label) { - label.innerText = `${distance}m`; - - // Update specific label state based on the label ID - switch (label.id) { - case "textPosX": - setLabelValues((prevState) => ({ ...prevState, textPosX: distance })); - break; - case "textNegX": - setLabelValues((prevState) => ({ ...prevState, textNegX: distance })); - break; - case "textPosZ": - setLabelValues((prevState) => ({ ...prevState, textPosZ: distance })); - break; - case "textNegZ": - setLabelValues((prevState) => ({ ...prevState, textNegZ: distance })); - break; - default: - break; - } - } - } - } else { - // No intersection found - clear the line - geometry.dispose(); - geometry.setFromPoints([new Vector3(), new Vector3()]); - line.geometry = geometry; - - const label = document.getElementById(mesh?.current?.name ?? ""); - if (label) { - label.innerText = ""; - - // Clear the corresponding label value in the state - switch (label.id) { - case "textPosX": - setLabelValues((prevState) => ({ ...prevState, textPosX: "" })); - break; - case "textNegX": - setLabelValues((prevState) => ({ ...prevState, textNegX: "" })); - break; - case "textPosZ": - setLabelValues((prevState) => ({ ...prevState, textPosZ: "" })); - break; - case "textNegZ": - setLabelValues((prevState) => ({ ...prevState, textNegZ: "" })); - break; - default: - break; - } - } - } - - }; - - const Material = new LineBasicMaterial({ color: "#d2baff" }); - - return ( - <> - {/* Measurement text labels */} - {boundingBoxRef.current && object > 0 && ( + return ( <> - - -
{labelValues.textPosX}
- -
+ {boundingBoxRef.current && object > 0 && ( + + {renderLabel("textPosX")} + {renderLabel("textNegX")} + {renderLabel("textPosZ")} + {renderLabel("textNegZ")} - - -
{labelValues.textNegX}
- -
- - - -
{labelValues.textPosZ}
- -
- - - -
{labelValues.textNegZ}
- -
- - {/* Measurement lines */} - - - - + + + + +
+ )} - ) - } - - ); + ); }; export default DistanceFindingControls; diff --git a/app/src/store/builder/useBuilderStore.ts b/app/src/store/builder/useBuilderStore.ts index 8e240c1..e7a60ca 100644 --- a/app/src/store/builder/useBuilderStore.ts +++ b/app/src/store/builder/useBuilderStore.ts @@ -55,7 +55,7 @@ interface BuilderState { // Setters - Floor setSelectedFloor: (floor: Object3D | null) => void; setFloorDepth: (depth: number) => void; - setBeveled: (isBeveled: boolean) => void; + setIsBeveled: (isBeveled: boolean) => void; setBevelStrength: (strength: number) => void; setFloorMaterial: (material: string, side: 'side' | 'top') => void; @@ -99,7 +99,7 @@ export const useBuilderStore = create()( selectedFloor: null, floorDepth: 0.1, isBeveled: false, - bevelStrength: 0.05, + bevelStrength: 5, sideMaterial: 'Material 1', topMaterial: 'Default Material', @@ -182,7 +182,7 @@ export const useBuilderStore = create()( }); }, - setBeveled: (isBeveled: boolean) => { + setIsBeveled: (isBeveled: boolean) => { set((state) => { state.isBeveled = isBeveled; }); diff --git a/app/src/store/builder/useFloorStore.ts b/app/src/store/builder/useFloorStore.ts index 7d425eb..77dc152 100644 --- a/app/src/store/builder/useFloorStore.ts +++ b/app/src/store/builder/useFloorStore.ts @@ -5,7 +5,7 @@ interface FloorStore { floors: Floor[]; setFloors: (floors: Floor[]) => void; addFloor: (floor: Floor) => void; - updateFloor: (uuid: string, updated: Partial) => void; + updateFloor: (uuid: string, updated: Partial) => Floor | undefined; removeFloor: (uuid: string) => void; removePoint: (pointUuid: string) => { removedFloors: Floor[], updatedFloors: Floor[] }; removeFloorByPoints: (Points: [Point, Point]) => { removedFloors: Floor[], updatedFloors: Floor[] }; @@ -45,12 +45,17 @@ export const createFloorStore = () => { state.floors.push(floor); }), - updateFloor: (uuid, updated) => set(state => { - const floor = state.floors.find(f => f.floorUuid === uuid); - if (floor) { - Object.assign(floor, updated); - } - }), + updateFloor: (uuid, updated) => { + let updatedFloor: Floor | undefined; + set(state => { + const floor = state.floors.find(f => f.floorUuid === uuid); + if (floor) { + Object.assign(floor, updated); + updatedFloor = JSON.parse(JSON.stringify(floor)); + } + }); + return updatedFloor; + }, removeFloor: (uuid) => set(state => { state.floors = state.floors.filter(f => f.floorUuid !== uuid);