diff --git a/app/src/components/layout/scenes/MainScene.tsx b/app/src/components/layout/scenes/MainScene.tsx
index 6e49fe4..117d7d6 100644
--- a/app/src/components/layout/scenes/MainScene.tsx
+++ b/app/src/components/layout/scenes/MainScene.tsx
@@ -33,7 +33,7 @@ import {
import { useProductContext } from "../../../modules/simulation/products/productContext";
import RegularDropDown from "../../ui/inputs/RegularDropDown";
import RenameTooltip from "../../ui/features/RenameTooltip";
-import { setAssetsApi } from "../../../services/factoryBuilder/assest/floorAsset/setAssetsApi";
+import { setAssetsApi } from "../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../modules/scene/sceneContext";
import { useVersionHistoryStore } from "../../../store/builder/useVersionHistoryStore";
diff --git a/app/src/components/layout/sidebarLeft/Assets.tsx b/app/src/components/layout/sidebarLeft/Assets.tsx
index 391675b..0420d2a 100644
--- a/app/src/components/layout/sidebarLeft/Assets.tsx
+++ b/app/src/components/layout/sidebarLeft/Assets.tsx
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react";
import Search from "../../ui/inputs/Search";
-import { getCategoryAsset } from "../../../services/factoryBuilder/assest/assets/getCategoryAsset";
+import { getCategoryAsset } from "../../../services/factoryBuilder/asset/assets/getCategoryAsset";
import { fetchAssets } from "../../../services/marketplace/fetchAssets";
import { useSelectedItem } from "../../../store/builder/store";
diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx
index 5fbf079..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,215 +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 { useSceneContext } from "../../../modules/scene/sceneContext";
+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 { 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();
- const { selectedWall } = 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]);
+ 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]);
-
- // 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]);
-
- 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)}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {selectedMaterials[activeSurface] && (
+
![{selectedMaterials[activeSurface]!.textureName}]({selectedMaterials[activeSurface]!.texture})
+ )}
+
+
+
+
+ {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 (
+
+
+
+
+
+
+
+
+ {(["top", "side"] as const).map((surface) => (
+
+ ))}
+
+
+
+
![{selectedMaterials[activeSurface].textureName}]({selectedMaterials[activeSurface].texture})
+
+
+
+
+
+ {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 b647145..794ede0 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';
@@ -6,10 +6,23 @@ import wallTexture1 from '../../../../assets/textures/floor/factory wall texture
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 { 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();
+ const { selectedVersion } = selectedVersionStore();
+ const { socket } = useSocketStore();
+ const { userId, organization } = getUserData();
+ const { projectId } = useParams();
const { getWallById, updateWall } = wallStore();
const [activeSide, setActiveSide] = useState<"side1" | "side2">("side1");
@@ -21,17 +34,62 @@ 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) {
- updateWall(wall.wallUuid, { wallHeight: height });
+ const updatedWall = updateWall(wall.wallUuid, { wallHeight: height });
+ if (updatedWall && projectId) {
+
+ // 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);
+ }
}
};
const handleThicknessChange = (val: string) => {
+ setThickness(val);
const thickness = parseFloat(val);
if (!isNaN(thickness) && wall) {
- updateWall(wall.wallUuid, { wallThickness: thickness });
+ const updatedWall = updateWall(wall.wallUuid, { wallThickness: thickness });
+ if (updatedWall && projectId) {
+
+ // 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);
+ }
}
};
@@ -39,23 +97,32 @@ const SelectedWallProperties = () => {
if (!wall) return;
const updated = (activeSide === "side1" ? { insideMaterial: material.textureId } : { outsideMaterial: material.textureId })
+ const updatedWall = updateWall(wall.wallUuid, updated);
+ if (updatedWall && projectId) {
- updateWall(wall.wallUuid, updated);
+ // 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);
+ }
};
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 (
@@ -65,12 +132,18 @@ const SelectedWallProperties = () => {
diff --git a/app/src/components/layout/sidebarRight/properties/WallProperties.tsx b/app/src/components/layout/sidebarRight/properties/WallProperties.tsx
index eb835f1..e158b44 100644
--- a/app/src/components/layout/sidebarRight/properties/WallProperties.tsx
+++ b/app/src/components/layout/sidebarRight/properties/WallProperties.tsx
@@ -10,163 +10,158 @@ 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)}
- />
-
-
-
-
+ const handleSelectMaterial = (material: Material) => {
+ setSelectedMaterials((prev) => ({
+ ...prev,
+ [activeSide]: material,
+ }));
+ };
-
-
-
+ return (
+
+
+ Wall
+
+ handleHeightChange(val)}
+ />
+ handleThicknessChange(val)}
+ />
+
+
+
+
-
-
+
+
+
-
- {selectedMaterials[activeSide] && (
-
![{selectedMaterials[activeSide]!.textureName}]({selectedMaterials[activeSide]!.texture})
- )}
-
-
-
-
- {materials.length === 0 ? (
-
No materials added yet.
- ) : (
-
- {materials.map((material, index) => {
- const isSelected = selectedMaterials[activeSide]?.texture === material.texture;
-
- return (
-
- );
- })}
-
- )}
+
+
+ {selectedMaterials[activeSide] && (
+
![{selectedMaterials[activeSide]!.textureName}]({selectedMaterials[activeSide]!.texture})
+ )}
+
+
+
+
+ {materials.length === 0 ? (
+
No materials added yet.
+ ) : (
+
+ {materials.map((material, index) => {
+ const isSelected = selectedMaterials[activeSide]?.texture === material.texture;
+
+ return (
+
handleSelectMaterial(material)}
+ >
+
+
+

+
+
{material.textureName}
+
+
+ );
+ })}
+
+ )}
+
+
-
-
- );
+ );
};
export default WallProperties;
diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx
index 0d81bda..cf13a4f 100644
--- a/app/src/components/ui/list/List.tsx
+++ b/app/src/components/ui/list/List.tsx
@@ -17,7 +17,7 @@ import {
useZones,
} from "../../../store/builder/store";
import { zoneCameraUpdate } from "../../../services/visulization/zone/zoneCameraUpdation";
-import { setAssetsApi } from "../../../services/factoryBuilder/assest/floorAsset/setAssetsApi";
+import { setAssetsApi } from "../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../functions/getUserData";
import { useSceneContext } from "../../../modules/scene/sceneContext";
diff --git a/app/src/modules/builder/Decal/decalInstance.tsx b/app/src/modules/builder/Decal/decalInstance.tsx
index 6ed0490..1b68f3d 100644
--- a/app/src/modules/builder/Decal/decalInstance.tsx
+++ b/app/src/modules/builder/Decal/decalInstance.tsx
@@ -7,8 +7,8 @@ import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import defaultMaterial from '../../../assets/textures/floor/wall-tex.png';
import useModuleStore from '../../../store/useModuleStore';
-function DecalInstance({ visible = true, decal }: { visible?: boolean, decal: Decal }) {
- const { setSelectedWall, selectedDecal, setSelectedDecal } = useBuilderStore();
+function DecalInstance({ visible = true, decal, zPosition = decal.decalPosition[2] }: { visible?: boolean, decal: Decal, zPosition?: number }) {
+ const { setSelectedWall, setSelectedFloor, selectedDecal, setSelectedDecal } = useBuilderStore();
const { togglView } = useToggleView();
const { activeModule } = useModuleStore();
const material = useLoader(THREE.TextureLoader, defaultMaterial);
@@ -17,15 +17,17 @@ function DecalInstance({ visible = true, decal }: { visible?: boolean, decal: De
{
if (visible && !togglView && activeModule === 'builder') {
if (e.object.userData.decalUuid) {
+ e.stopPropagation();
setSelectedDecal(e.object);
setSelectedWall(null);
+ setSelectedFloor(null);
}
}
}}
diff --git a/app/src/modules/builder/IntialLoad/loadInitialLine.ts b/app/src/modules/builder/IntialLoad/loadInitialLine.ts
deleted file mode 100644
index f8c3132..0000000
--- a/app/src/modules/builder/IntialLoad/loadInitialLine.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import addLineToScene from '../../builder/geomentries/lines/addLineToScene';
-import * as CONSTANTS from '../../../types/world/worldConstants';
-import * as Types from "../../../types/world/worldTypes";
-
-function loadInitialLine(
- floorPlanGroupLine: Types.RefGroup,
- lines: Types.RefLines
-): void {
-
- if (!floorPlanGroupLine.current) return
-
- ////////// Load the Lines initially if there are any //////////
-
- floorPlanGroupLine.current.children = [];
- lines.current.forEach((line) => {
- let colour;
- if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.wallName) {
- colour = CONSTANTS.lineConfig.wallColor;
- } else if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.floorName) {
- colour = CONSTANTS.lineConfig.floorColor;
- } else if (line[0][3] && line[1][3] === CONSTANTS.lineConfig.aisleName) {
- colour = CONSTANTS.lineConfig.aisleColor;
- }
- if (colour) {
- addLineToScene(line[0][0], line[1][0], colour, line, floorPlanGroupLine);
- }
- });
-}
-
-export default loadInitialLine;
diff --git a/app/src/modules/builder/IntialLoad/loadInitialPoint.ts b/app/src/modules/builder/IntialLoad/loadInitialPoint.ts
deleted file mode 100644
index 91db577..0000000
--- a/app/src/modules/builder/IntialLoad/loadInitialPoint.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import * as THREE from 'three';
-
-import * as CONSTANTS from '../../../types/world/worldConstants';
-import * as Types from "../../../types/world/worldTypes";
-
-////////// Load the Boxes initially if there are any //////////
-
-function loadInitialPoint(
- lines: Types.RefLines,
- floorPlanGroupPoint: Types.RefGroup,
- currentLayerPoint: Types.RefMeshArray,
- dragPointControls: Types.RefDragControl
-): void {
-
- if (!floorPlanGroupPoint.current) return
-
- floorPlanGroupPoint.current.children = [];
- currentLayerPoint.current = [];
- lines.current.forEach((line) => {
- const colour = getPointColor(line[0][3]);
- line.forEach((pointData) => {
- const [point, id] = pointData;
-
- /////////// Check if a box with this id already exists //////////
-
- const existingBox = floorPlanGroupPoint.current?.getObjectByProperty('uuid', id);
- if (existingBox) {
- return;
- }
-
- const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale);
- const material = new THREE.ShaderMaterial({
- uniforms: {
- uOuterColor: { value: new THREE.Color(colour) }, // Blue color for the border
- uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square
- },
- vertexShader: `
- varying vec2 vUv;
-
- void main() {
- vUv = uv;
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
- }
- `,
- fragmentShader: `
- varying vec2 vUv;
- uniform vec3 uOuterColor;
- uniform vec3 uInnerColor;
-
- void main() {
- // Define the size of the white square as a proportion of the face
- float borderThickness = 0.2; // Adjust this value for border thickness
- if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness &&
- vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
- gl_FragColor = vec4(uInnerColor, 1.0); // White inner square
- } else {
- gl_FragColor = vec4(uOuterColor, 1.0); // Blue border
- }
- }
- `,
- });
- const box = new THREE.Mesh(geometry, material);
- box.name = "point";
- box.uuid = id;
- box.userData = { type: line[0][3], color: colour };
- box.position.set(point.x, point.y, point.z);
- currentLayerPoint.current.push(box);
-
- floorPlanGroupPoint.current?.add(box);
- });
- });
-
- function getPointColor(lineType: string | undefined): string {
- switch (lineType) {
- case CONSTANTS.lineConfig.wallName: return CONSTANTS.pointConfig.wallOuterColor;
- case CONSTANTS.lineConfig.floorName: return CONSTANTS.pointConfig.floorOuterColor;
- case CONSTANTS.lineConfig.aisleName: return CONSTANTS.pointConfig.aisleOuterColor;
- default: return CONSTANTS.pointConfig.defaultOuterColor;
- }
- }
-
- if (dragPointControls.current) {
- dragPointControls.current!.objects = currentLayerPoint.current;
- }
-}
-
-export default loadInitialPoint;
diff --git a/app/src/modules/builder/IntialLoad/loadInitialWallItems.ts b/app/src/modules/builder/IntialLoad/loadInitialWallItems.ts
index ba82510..80fdcb9 100644
--- a/app/src/modules/builder/IntialLoad/loadInitialWallItems.ts
+++ b/app/src/modules/builder/IntialLoad/loadInitialWallItems.ts
@@ -1,110 +1,110 @@
-import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
-import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
-import * as THREE from "three";
-import * as Types from "../../../types/world/worldTypes";
-import { getWallItems } from "../../../services/factoryBuilder/assest/wallAsset/getWallItemsApi";
-import { retrieveGLTF, storeGLTF } from "../../../utils/indexDB/idbUtils";
-import { getUserData } from "../../../functions/getUserData";
+// import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
+// import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
+// import * as THREE from "three";
+// import * as Types from "../../../types/world/worldTypes";
+// import { getWallItems } from "../../../services/factoryBuilder/asset/wallAsset/getWallItemsApi";
+// import { retrieveGLTF, storeGLTF } from "../../../utils/indexDB/idbUtils";
+// import { getUserData } from "../../../functions/getUserData";
-async function loadInitialWallItems(
- setWallItems: Types.setWallItemSetState,
- projectId?: string,
- versionId?: string
-): Promise {
- if (!projectId || !versionId) return;
- try {
- const { organization, email } = getUserData();
+// async function loadInitialWallItems(
+// setWallItems: Types.setWallItemSetState,
+// projectId?: string,
+// versionId?: string
+// ): Promise {
+// if (!projectId || !versionId) return;
+// try {
+// const { organization, email } = getUserData();
- if (!email) {
- console.error("No email found in localStorage");
- }
+// if (!email) {
+// console.error("No email found in localStorage");
+// }
- const items = await getWallItems(organization, projectId, versionId);
+// const items = await getWallItems(organization, projectId, versionId);
- let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
+// let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
- if (!items || items.length === 0) {
- localStorage.removeItem("WallItems");
- return;
- }
+// if (!items || items.length === 0) {
+// localStorage.removeItem("WallItems");
+// return;
+// }
- localStorage.setItem("WallItems", JSON.stringify(items));
+// localStorage.setItem("WallItems", JSON.stringify(items));
- const loader = new GLTFLoader();
- const dracoLoader = new DRACOLoader();
- dracoLoader.setDecoderPath(
- "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/"
- );
- loader.setDRACOLoader(dracoLoader);
+// 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);
- const loadedWallItems = await Promise.all(
- items.map(async (item: Types.WallItem) => {
- // Check THREE.js cache first
- const cachedModel = THREE.Cache.get(item.assetId!);
- if (cachedModel) {
- return processModel(cachedModel, item);
- }
+// const loadedWallItems = await Promise.all(
+// items.map(async (item: Types.WallItem) => {
+// // Check THREE.js cache first
+// const cachedModel = THREE.Cache.get(item.assetId!);
+// if (cachedModel) {
+// return processModel(cachedModel, item);
+// }
- // Check IndexedDB cache
- const cachedModelBlob = await retrieveGLTF(item.assetId!);
- if (cachedModelBlob) {
- const blobUrl = URL.createObjectURL(cachedModelBlob);
- return new Promise((resolve) => {
- loader.load(blobUrl, (gltf) => {
- URL.revokeObjectURL(blobUrl);
- THREE.Cache.add(item.assetId!, gltf);
- resolve(processModel(gltf, item));
- });
- });
- }
+// // Check IndexedDB cache
+// const cachedModelBlob = await retrieveGLTF(item.assetId!);
+// if (cachedModelBlob) {
+// const blobUrl = URL.createObjectURL(cachedModelBlob);
+// return new Promise((resolve) => {
+// loader.load(blobUrl, (gltf) => {
+// URL.revokeObjectURL(blobUrl);
+// THREE.Cache.add(item.assetId!, gltf);
+// resolve(processModel(gltf, item));
+// });
+// });
+// }
- // Load from original URL if not cached
- const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${item.assetId!}`;
- return new Promise((resolve) => {
- loader.load(modelUrl, async (gltf) => {
- try {
- // Cache the model
- const modelBlob = await fetch(modelUrl).then((res) => res.blob());
- await storeGLTF(item.assetId!, modelBlob);
- THREE.Cache.add(item.assetId!, gltf);
- resolve(processModel(gltf, item));
- } catch (error) {
- console.error("Failed to cache model:", error);
- resolve(processModel(gltf, item));
- }
- });
- });
- })
- );
+// // Load from original URL if not cached
+// const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${item.assetId!}`;
+// return new Promise((resolve) => {
+// loader.load(modelUrl, async (gltf) => {
+// try {
+// // Cache the model
+// const modelBlob = await fetch(modelUrl).then((res) => res.blob());
+// await storeGLTF(item.assetId!, modelBlob);
+// THREE.Cache.add(item.assetId!, gltf);
+// resolve(processModel(gltf, item));
+// } catch (error) {
+// console.error("Failed to cache model:", error);
+// resolve(processModel(gltf, item));
+// }
+// });
+// });
+// })
+// );
- setWallItems(loadedWallItems);
- } catch (error) {
- console.error("Failed to load wall items:", error);
- }
-}
+// setWallItems(loadedWallItems);
+// } catch (error) {
+// console.error("Failed to load wall items:", error);
+// }
+// }
-function processModel(gltf: GLTF, item: Types.WallItem): Types.WallItem {
- const model = gltf.scene.clone();
- model.uuid = item.modelUuid!;
+// function processModel(gltf: GLTF, item: Types.WallItem): Types.WallItem {
+// const model = gltf.scene.clone();
+// model.uuid = item.modelUuid!;
- model.children[0]?.children?.forEach((child: THREE.Object3D) => {
- if (child.name !== "CSG_REF") {
- child.castShadow = true;
- child.receiveShadow = true;
- }
- });
+// model.children[0]?.children?.forEach((child: THREE.Object3D) => {
+// if (child.name !== "CSG_REF") {
+// child.castShadow = true;
+// child.receiveShadow = true;
+// }
+// });
- return {
- type: item.type,
- model: model,
- modelName: item.modelName,
- assetId: item.assetId,
- scale: item.scale,
- csgscale: item.csgscale,
- csgposition: item.csgposition,
- position: item.position,
- quaternion: item.quaternion,
- };
-}
+// return {
+// type: item.type,
+// model: model,
+// modelName: item.modelName,
+// assetId: item.assetId,
+// scale: item.scale,
+// csgscale: item.csgscale,
+// csgposition: item.csgposition,
+// position: item.position,
+// quaternion: item.quaternion,
+// };
+// }
-export default loadInitialWallItems;
+// export default loadInitialWallItems;
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/aisle/aisleCreator/aisleCreator.tsx b/app/src/modules/builder/aisle/aisleCreator/aisleCreator.tsx
index e0805e9..31ed1f6 100644
--- a/app/src/modules/builder/aisle/aisleCreator/aisleCreator.tsx
+++ b/app/src/modules/builder/aisle/aisleCreator/aisleCreator.tsx
@@ -2,13 +2,13 @@ import * as THREE from 'three'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useThree } from '@react-three/fiber';
import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
-import ReferenceAisle from './referenceAisle';
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
-import ReferencePoint from '../../point/reference/referencePoint';
-import { createAisleApi } from '../../../../services/factoryBuilder/aisle/createAisleApi';
+import { upsertAisleApi } from '../../../../services/factoryBuilder/aisle/upsertAisleApi';
import { useParams } from 'react-router-dom';
import { useVersionContext } from '../../version/versionContext';
import { useSceneContext } from '../../../scene/sceneContext';
+import ReferenceAisle from './referenceAisle';
+import ReferencePoint from '../../point/reference/referencePoint';
function AisleCreator() {
const { scene, camera, raycaster, gl, pointer } = useThree();
@@ -74,6 +74,8 @@ function AisleCreator() {
newPoint.layer = snappedPoint.layer;
}
+ if (snappedPoint && snappedPoint.pointUuid === tempPoints[0]?.pointUuid) { return }
+
if (snappedPosition && !snappedPoint) {
newPoint.position = snappedPosition;
}
@@ -104,7 +106,7 @@ function AisleCreator() {
};
addAisle(aisle);
if (projectId) {
- createAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
+ upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
}
setTempPoints([newPoint]);
}
@@ -127,7 +129,7 @@ function AisleCreator() {
};
addAisle(aisle);
if (projectId) {
- createAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
+ upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
}
setTempPoints([newPoint]);
}
@@ -149,7 +151,7 @@ function AisleCreator() {
};
addAisle(aisle);
if (projectId) {
- createAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
+ upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
}
setTempPoints([newPoint]);
}
@@ -170,7 +172,7 @@ function AisleCreator() {
};
addAisle(aisle);
if (projectId) {
- createAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
+ upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
}
setTempPoints([newPoint]);
}
@@ -193,7 +195,7 @@ function AisleCreator() {
};
addAisle(aisle);
if (projectId) {
- createAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
+ upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
}
setTempPoints([newPoint]);
}
@@ -215,7 +217,7 @@ function AisleCreator() {
};
addAisle(aisle);
if (projectId) {
- createAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
+ upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
}
setTempPoints([newPoint]);
}
@@ -236,7 +238,7 @@ function AisleCreator() {
};
addAisle(aisle);
if (projectId) {
- createAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
+ upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
}
setTempPoints([newPoint]);
}
@@ -258,7 +260,7 @@ function AisleCreator() {
};
addAisle(aisle);
if (projectId) {
- createAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
+ upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
}
setTempPoints([newPoint]);
}
diff --git a/app/src/modules/builder/aisle/aisleCreator/referenceAisle.tsx b/app/src/modules/builder/aisle/aisleCreator/referenceAisle.tsx
index 10bf6fa..6ce66fe 100644
--- a/app/src/modules/builder/aisle/aisleCreator/referenceAisle.tsx
+++ b/app/src/modules/builder/aisle/aisleCreator/referenceAisle.tsx
@@ -177,7 +177,7 @@ function ReferenceAisle({ tempPoints }: Readonly) {
useEffect(() => {
setTempAisle(null);
- }, [toolMode, toggleView, tempPoints.length, aisleType, aisleWidth, aisleColor]);
+ }, [toolMode, toggleView, tempPoints.length, aisleType, aisleWidth, aisleColor, activeLayer]);
if (!tempAisle) return null;
diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx
index b597ab3..13fb414 100644
--- a/app/src/modules/builder/asset/assetsGroup.tsx
+++ b/app/src/modules/builder/asset/assetsGroup.tsx
@@ -1,6 +1,6 @@
import * as THREE from "three"
import { useEffect } from 'react'
-import { getFloorAssets } from '../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
+import { getFloorAssets } from '../../../services/factoryBuilder/asset/floorAsset/getFloorItemsApi';
import { useLoadingProgress, useRenameModeStore, useSelectedFloorItem, useSelectedItem, useSocketStore } from '../../../store/builder/store';
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
@@ -23,10 +23,10 @@ const gltfLoaderWorker = new Worker(
)
);
-function AssetsGroup({ floorGroup, plane }: { readonly floorGroup: RefGroup, readonly plane: RefMesh }) {
+function AssetsGroup({ plane }: { 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();
@@ -269,7 +269,7 @@ function AssetsGroup({ floorGroup, plane }: { readonly floorGroup: RefGroup, rea
useEffect(() => {
const canvasElement = gl.domElement;
- const onDrop = (event: any) => {
+ const onDrop = (event: DragEvent) => {
if (!event.dataTransfer?.files[0]) return;
if (selectedItem.id !== "" && event.dataTransfer?.files[0] && selectedItem.category !== 'Fenestration') {
@@ -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..7c85a49 100644
--- a/app/src/modules/builder/asset/functions/addAssetModel.ts
+++ b/app/src/modules/builder/asset/functions/addAssetModel.ts
@@ -3,496 +3,445 @@ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import * as Types from "../../../../types/world/worldTypes";
import { retrieveGLTF, storeGLTF } from "../../../../utils/indexDB/idbUtils";
-// import { setAssetsApi } from '../../../../services/factoryBuilder/assest/floorAsset/setAssetsApi';
+// import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
import { Socket } from "socket.io-client";
import * as CONSTANTS from "../../../../types/world/worldConstants";
import PointsCalculator from "../../../simulation/events/points/functions/pointsCalculator";
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/asset/models/model/model.tsx b/app/src/modules/builder/asset/models/model/model.tsx
index 4d10c28..75a8477 100644
--- a/app/src/modules/builder/asset/models/model/model.tsx
+++ b/app/src/modules/builder/asset/models/model/model.tsx
@@ -4,7 +4,7 @@ import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils';
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import { ThreeEvent, useFrame, useThree } from '@react-three/fiber';
-import { useActiveTool, useDeletableFloorItem, useRenderDistance, useSelectedFloorItem, useSocketStore, useToggleView, useToolMode } from '../../../../../store/builder/store';
+import { useActiveTool, useDeletableFloorItem, useLimitDistance, useRenderDistance, useSelectedFloorItem, useSocketStore, useToggleView, useToolMode } from '../../../../../store/builder/store';
import { AssetBoundingBox } from '../../functions/assetBoundingBox';
import { CameraControls, Html } from '@react-three/drei';
import useModuleStore, { useSubModuleStore } from '../../../../../store/useModuleStore';
@@ -34,6 +34,7 @@ function Model({ asset }: { readonly asset: Asset }) {
const { socket } = useSocketStore();
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
const { setSelectedFloorItem } = useSelectedFloorItem();
+ const { limitDistance } = useLimitDistance();
const { renderDistance } = useRenderDistance();
const [isRendered, setIsRendered] = useState(false);
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
@@ -162,10 +163,16 @@ function Model({ asset }: { readonly asset: Asset }) {
useFrame(() => {
const assetPosition = new THREE.Vector3(...asset.position);
- if (!isRendered && assetPosition.distanceTo(camera.position) <= renderDistance) {
- setIsRendered(true);
- } else if (isRendered && assetPosition.distanceTo(camera.position) > renderDistance) {
- setIsRendered(false);
+ if (limitDistance) {
+ if (!isRendered && assetPosition.distanceTo(camera.position) <= renderDistance) {
+ setIsRendered(true);
+ } else if (isRendered && assetPosition.distanceTo(camera.position) > renderDistance) {
+ setIsRendered(false);
+ }
+ } else {
+ if (!isRendered) {
+ setIsRendered(true);
+ }
}
})
diff --git a/app/src/modules/builder/builder.tsx b/app/src/modules/builder/builder.tsx
index b977781..ab9434b 100644
--- a/app/src/modules/builder/builder.tsx
+++ b/app/src/modules/builder/builder.tsx
@@ -1,139 +1,68 @@
////////// Three and React Three Fiber Imports //////////
import * as THREE from "three";
-import { useEffect, useRef, useState } from "react";
-import { useThree, useFrame } from "@react-three/fiber";
-
-////////// Component Imports //////////
-
-import DistanceText from "./geomentries/lines/distanceText/distanceText";
-import ReferenceDistanceText from "./geomentries/lines/distanceText/referenceDistanceText";
+import { useEffect, useRef } from "react";
+import { useFrame, useThree } from "@react-three/fiber";
+import { Geometry } from "@react-three/csg";
////////// Zustand State Imports //////////
import {
useToggleView,
- useActiveLayer,
useWallVisibility,
useRoofVisibility,
useShadows,
- useUpdateScene,
- useWalls,
useToolMode,
- useRefTextUpdate,
useRenderDistance,
useLimitDistance,
} from "../../store/builder/store";
////////// 3D Function Imports //////////
-import loadWalls from "./geomentries/walls/loadWalls";
-
import * as Types from "../../types/world/worldTypes";
import SocketResponses from "../collaboration/socket/socketResponses.dev";
-import FloorPlanGroup from "./groups/floorPlanGroup";
-import FloorGroup from "./groups/floorGroup";
-import Draw from "./functions/draw";
-import WallsAndWallItems from "./groups/wallsAndWallItems";
import Ground from "../scene/environment/ground";
import { findEnvironment } from "../../services/factoryBuilder/environment/findEnvironment";
-import Layer2DVisibility from "./geomentries/layers/layer2DVisibility";
-import ZoneGroup from "./groups/zoneGroup";
+
import MeasurementTool from "../scene/tools/measurementTool";
import NavMesh from "../simulation/vehicle/navMesh/navMesh";
import CalculateAreaGroup from "./groups/calculateAreaGroup";
import LayoutImage from "./layout/layoutImage";
import AssetsGroup from "./asset/assetsGroup";
-import { Bvh } from "@react-three/drei";
import DxfFile from "./dfx/LoadBlueprint";
-import { useParams } from "react-router-dom";
import AislesGroup from "./aisle/aislesGroup";
import WallGroup from "./wall/wallGroup";
+import FloorGroup from "./floor/floorGroup";
+import ZoneGroup from "./zone/zoneGroup";
+
+import { useParams } from "react-router-dom";
import { useBuilderStore } from "../../store/builder/useBuilderStore";
import { getUserData } from "../../functions/getUserData";
+import WallAssetGroup from "./wallAsset/wallAssetGroup";
export default function Builder() {
- const state = useThree(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
- const csg = useRef(); // Reference for CSG object, used for 3D modeling.
- const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects.
- const scene = useRef() as Types.RefScene; // Reference to the scene.
- const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control.
+ const state = useThree();
+ const plane = useRef(null);
+ const csgRef = useRef(null);
- // Assigning the scene and camera from the Three.js state to the references.
-
- const plane = useRef(null); // Reference for a plane object for raycaster reference.
- const grid = useRef() as any; // Reference for a grid object for raycaster reference.
- const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line.
- const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end).
- const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc...
- const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active.
- const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point.
- const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start).
- const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation.
- const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn.
- const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn.
- const onlyFloorline = useRef([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn.
- const onlyFloorlines = useRef([]); // Reference for all the floor lines that are ever drawn.
- const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw.
- const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not.
- const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed.
- const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors.
- const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group.
- const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn.
- const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created.
- const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls.
- const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted.
- const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted.
- const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted.
- const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted.
- const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc...
-
- const cursorPosition = new THREE.Vector3(); // 3D vector for storing the cursor position.
-
- const [selectedItemsIndex, setSelectedItemsIndex] = useState(null); // State for tracking the index of the selected item.
- const { activeLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx.
- const { toggleView } = useToggleView(); // State for toggling between 2D and 3D.
- const { toolMode, setToolMode } = useToolMode();
+ const { toggleView } = useToggleView();
+ const { setToolMode } = useToolMode();
const { setRoofVisibility } = useRoofVisibility();
const { setWallVisibility } = useWallVisibility();
const { setShadows } = useShadows();
const { setRenderDistance } = useRenderDistance();
const { setLimitDistance } = useLimitDistance();
- const { setUpdateScene } = useUpdateScene();
- const { setWalls } = useWalls();
- const { refTextupdate, setRefTextUpdate } = useRefTextUpdate();
const { projectId } = useParams();
const { setHoveredPoint, setHoveredLine } = useBuilderStore();
const { userId, organization } = getUserData();
- // 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);
-
- ////////// All Toggle's //////////
-
useEffect(() => {
- setRefTextUpdate((prevUpdate: number) => prevUpdate - 1);
- if (toggleView) {
- Layer2DVisibility(
- activeLayer,
- floorPlanGroup,
- floorPlanGroupLine,
- floorPlanGroupPoint,
- currentLayerPoint,
- dragPointControls
- );
- } else {
+ if (!toggleView) {
setHoveredLine(null);
setHoveredPoint(null);
state.gl.domElement.style.cursor = 'default';
setToolMode('cursor');
- loadWalls(lines, setWalls);
- setUpdateScene(true);
- line.current = [];
}
}, [toggleView]);
@@ -152,131 +81,45 @@ export default function Builder() {
fetchVisibility();
}, []);
- ////////// UseFrame is Here //////////
-
useFrame(() => {
- if (toolMode) {
- Draw(
- state,
- plane,
- cursorPosition,
- floorPlanGroupPoint,
- snappedPoint,
- isSnapped,
- isSnappedUUID,
- line,
- ispreSnapped,
- floorPlanGroup,
- ReferenceLineMesh,
- LineCreated,
- setRefTextUpdate,
- Tube,
- anglesnappedPoint,
- isAngleSnapped,
- toolMode
- );
+ if (csgRef.current) {
+ csgRef.current.update();
}
- });
-
- ////////// Return //////////
+ })
return (
<>
-
+
-
-
-
+
-
+
-
-
-
+
+
-
+
-
+
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
- {/* */}
+
>
);
}
diff --git a/app/src/modules/builder/dfx/LoadBlueprint.tsx b/app/src/modules/builder/dfx/LoadBlueprint.tsx
index 4e2425d..1a95268 100644
--- a/app/src/modules/builder/dfx/LoadBlueprint.tsx
+++ b/app/src/modules/builder/dfx/LoadBlueprint.tsx
@@ -1,40 +1,21 @@
import { useEffect, useRef } from 'react';
import { useDfxUpload, useSocketStore, useToggleView, useUpdateScene } from '../../../store/builder/store';
import { LineBasicMaterial, Line } from 'three';
-import loadInitialPoint from '../IntialLoad/loadInitialPoint';
-import loadInitialLine from '../IntialLoad/loadInitialLine';
import { TransformControls } from '@react-three/drei';
import { getWallPointsFromBlueprint } from './functions/getWallPointsFromBlueprint';
import * as Types from '../../../types/world/worldTypes';
-import arrayLineToObject from '../geomentries/lines/lineConvertions/arrayLineToObject';
import { useParams } from 'react-router-dom';
import { getUserData } from '../../../functions/getUserData';
import { useVersionContext } from '../version/versionContext';
-// Interface defining the props for the DxfFile component
-interface DxfFileProps {
- lines: Types.RefLines; // Reference to lines in the DXF file
- floorPlanGroupPoint: Types.RefGroup; // Reference to floor plan points group
- dragPointControls: Types.RefDragControl; // Reference to drag controls
- floorPlanGroupLine: Types.RefGroup; // Reference to floor plan lines group
- currentLayerPoint: Types.RefMeshArray; // Reference to current layer points
-}
-
/**
* DxfFile component handles the rendering and manipulation of DXf file data in a 3D scene.
* It processes the DXF data to create points and lines representing walls and allows
* transformation controls for interactive editing.
*/
-const DxfFile = ({
- floorPlanGroupPoint,
- currentLayerPoint,
- dragPointControls,
- floorPlanGroupLine,
- lines,
-}: DxfFileProps) => {
+const DxfFile = () => {
// State management hooks
const { dfxuploaded, dfxWallGenerate, setObjValue, objValue } = useDfxUpload();
- const { setUpdateScene } = useUpdateScene();
const { toggleView } = useToggleView();
const { socket } = useSocketStore();
const { selectedVersionStore } = useVersionContext();
@@ -50,55 +31,34 @@ const DxfFile = ({
* Loads initial points and lines from the DXF data and updates the scene.
*/
useEffect(() => {
- if (
- dfxWallGenerate &&
- dragPointControls &&
- floorPlanGroupPoint &&
- currentLayerPoint &&
- floorPlanGroupLine
- ) {
+ if (dfxWallGenerate) {
// Store generated lines in ref
- lines.current.push(...dfxWallGenerate);
- dfxWallGenerate.map((line: any) => {
- const lineData = arrayLineToObject(line as Types.Line);
+ // lines.current.push(...dfxWallGenerate);
+ // dfxWallGenerate.map((line: any) => {
+ // const lineData = arrayLineToObject(line as Types.Line);
- //REST
+ // //REST
- // setLine(organization, lineData.layer!, lineData.line!, lineData.type!);
+ // // setLine(organization, lineData.layer!, lineData.line!, lineData.type!);
- //SOCKET
+ // //SOCKET
- const input = {
- organization,
- layer: lineData.layer,
- line: lineData.line,
- type: lineData.type,
- socketId: socket.id,
- versionId: selectedVersion?.versionId || '',
- projectId,
- userId
- }
+ // const input = {
+ // organization,
+ // layer: lineData.layer,
+ // line: lineData.line,
+ // type: lineData.type,
+ // socketId: socket.id,
+ // versionId: selectedVersion?.versionId || '',
+ // projectId,
+ // userId
+ // }
- console.log('input: ', input);
- socket.emit('v1:Line:create', input);
+ // socket.emit('v1:Line:create', input);
- })
-
- // Load initial points and lines from DXF data
- loadInitialPoint(lines, floorPlanGroupPoint, currentLayerPoint, dragPointControls);
- loadInitialLine(floorPlanGroupLine, lines);
-
- // Trigger scene update
- setUpdateScene(true);
+ // })
}
- }, [
- lines,
- floorPlanGroupLine,
- floorPlanGroupPoint,
- currentLayerPoint,
- dragPointControls,
- dfxWallGenerate,
- ]);
+ }, [dfxWallGenerate]);
/**
* Handles transformation changes for individual lines.
diff --git a/app/src/modules/builder/eventDeclaration/dragControlDeclaration.ts b/app/src/modules/builder/eventDeclaration/dragControlDeclaration.ts
deleted file mode 100644
index 52a4e16..0000000
--- a/app/src/modules/builder/eventDeclaration/dragControlDeclaration.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-import * as THREE from "three";
-import { DragControls } from "three/examples/jsm/controls/DragControls";
-import * as CONSTANTS from "../../../types/world/worldConstants";
-import DragPoint from "../geomentries/points/dragPoint";
-
-import * as Types from "../../../types/world/worldTypes";
-// import { updatePoint } from '../../../services/factoryBuilder/lines/updatePointApi';
-import { Socket } from "socket.io-client";
-import { getUserData } from "../../../functions/getUserData";
-
-export default async function addDragControl(
- dragPointControls: Types.RefDragControl,
- currentLayerPoint: Types.RefMeshArray,
- state: Types.ThreeState,
- floorPlanGroupPoint: Types.RefGroup,
- floorPlanGroupLine: Types.RefGroup,
- lines: Types.RefLines,
- onlyFloorlines: Types.RefOnlyFloorLines,
- socket: Socket,
- projectId?: string,
- versionId?: string
-) {
- ////////// Dragging Point and also change the size to indicate during hover //////////
-
- dragPointControls.current = new DragControls(
- currentLayerPoint.current,
- state.camera,
- state.gl.domElement
- );
- dragPointControls.current.enabled = false;
- const { userId, organization, email } = getUserData();
- dragPointControls.current.addEventListener("drag", function (event) {
- const object = event.object;
- if (object.visible) {
- (state.controls as any).enabled = false;
- DragPoint(
- event as any,
- floorPlanGroupPoint,
- floorPlanGroupLine,
- state.scene,
- lines,
- onlyFloorlines
- );
- } else {
- (state.controls as any).enabled = true;
- }
- });
-
- dragPointControls.current.addEventListener("dragstart", function (event) { });
-
- dragPointControls.current.addEventListener("dragend", async function (event) {
- if (!dragPointControls.current) return;
-
- //REST
-
- // await updatePoint(
- // organization,
- // { "x": event.object.position.x, "y": 0.01, "z": event.object.position.z },
- // event.object.uuid,
- // )
-
- //SOCKET
-
- const data = {
- organization,
- position: {
- x: event.object.position.x,
- y: 0.01,
- z: event.object.position.z,
- },
- uuid: event.object.uuid,
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- socket.emit("v1:Line:update", data);
-
- if (state.controls) {
- (state.controls as any).enabled = true;
- }
- });
-
- dragPointControls.current.addEventListener("hoveron", function (event: any) {
- if ((event.object as Types.Mesh).name === "point") {
- event.object.material.uniforms.uInnerColor.value.set(
- event.object.userData.color
- );
- }
- });
-
- dragPointControls.current.addEventListener("hoveroff", function (event: any) {
- if ((event.object as Types.Mesh).name === "point") {
- event.object.material.uniforms.uInnerColor.value.set(
- new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor)
- );
- }
- });
-}
diff --git a/app/src/modules/builder/eventFunctions/handleContextMenu.ts b/app/src/modules/builder/eventFunctions/handleContextMenu.ts
deleted file mode 100644
index 454f847..0000000
--- a/app/src/modules/builder/eventFunctions/handleContextMenu.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import * as Types from "../../../types/world/worldTypes";
-
-export default function handleContextMenu(
- menuVisible: Types.Boolean,
- setMenuVisible: Types.BooleanState
-): void {
- // setMenuVisible(true)
-}
\ No newline at end of file
diff --git a/app/src/modules/builder/eventFunctions/handleMeshDown.ts b/app/src/modules/builder/eventFunctions/handleMeshDown.ts
deleted file mode 100644
index 9fb7839..0000000
--- a/app/src/modules/builder/eventFunctions/handleMeshDown.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import * as THREE from 'three';
-
-import * as Types from "../../../types/world/worldTypes";
-
-function handleMeshDown(
- event: Types.MeshEvent,
- currentWallItem: Types.RefMesh,
- setSelectedWallItem: Types.setSelectedWallItemSetState,
- setSelectedItemsIndex: Types.setSelectedItemsIndexSetState,
- wallItems: Types.wallItems,
- toggleView: Types.Boolean
-): void {
-
- ////////// To select which of the Wall item and CSG is selected to be dragged //////////
-
- if (!toggleView) {
- if (currentWallItem.current) {
- currentWallItem.current.children.forEach((child) => {
- if ((child as THREE.Mesh).isMesh && child.name !== "CSG_REF") {
- const material = (child as THREE.Mesh).material;
- if (Array.isArray(material)) {
- material.forEach(mat => {
- if (mat instanceof THREE.MeshStandardMaterial) {
- mat.emissive = new THREE.Color("black");
- }
- });
- } else if (material instanceof THREE.MeshStandardMaterial) {
- material.emissive = new THREE.Color("black");
- }
- }
- });
- currentWallItem.current = null;
- setSelectedWallItem(null);
- setSelectedItemsIndex(null);
- }
-
- if (event.intersections.length > 0) {
- if (event.object) {
- const wallItemModel = event.object;
- let currentObject = wallItemModel as THREE.Object3D;
- while (currentObject) {
- if (currentObject.name === "Scene") {
- break;
- }
- currentObject = currentObject.parent as THREE.Object3D;
- }
- if (!currentObject) return;
- const clickedIndex = wallItems.findIndex((item) => item.model?.uuid === currentObject.uuid);
- if (clickedIndex !== -1) {
- setSelectedItemsIndex(clickedIndex);
- const wallItemModel = wallItems[clickedIndex]?.model;
- if (wallItemModel) {
- setSelectedWallItem(wallItemModel);
- }
- }
- }
-
- }
- }
-}
-export default handleMeshDown;
diff --git a/app/src/modules/builder/eventFunctions/handleMeshMissed.ts b/app/src/modules/builder/eventFunctions/handleMeshMissed.ts
deleted file mode 100644
index f374831..0000000
--- a/app/src/modules/builder/eventFunctions/handleMeshMissed.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import * as THREE from 'three';
-import * as Types from "../../../types/world/worldTypes";
-
-function handleMeshMissed(
- currentWallItem: Types.RefMesh,
- setSelectedWallItem: Types.setSelectedWallItemSetState,
- setSelectedItemsIndex: Types.setSelectedItemsIndexSetState
-): void {
-
- ////////// If an item is selected and then clicked outside other than the selected object, this runs and removes the color of the selected object and sets setSelectedWallItem and setSelectedItemsIndex as null //////////
-
- if (currentWallItem.current) {
- currentWallItem.current.children.forEach((child) => {
- if ((child as THREE.Mesh).isMesh && child.name !== "CSG_REF") {
- const material = (child as THREE.Mesh).material;
-
- if (Array.isArray(material)) {
- material.forEach(mat => {
- if (mat instanceof THREE.MeshStandardMaterial) {
- mat.emissive = new THREE.Color("black");
- }
- });
- } else if (material instanceof THREE.MeshStandardMaterial) {
- material.emissive = new THREE.Color("black");
- }
- }
- });
- currentWallItem.current = null;
- setSelectedWallItem(null);
- setSelectedItemsIndex(null);
- }
-}
-
-export default handleMeshMissed;
diff --git a/app/src/modules/builder/floor/Instances/Instance/floor2DInstance.tsx b/app/src/modules/builder/floor/Instances/Instance/floor2DInstance.tsx
new file mode 100644
index 0000000..1ba15f0
--- /dev/null
+++ b/app/src/modules/builder/floor/Instances/Instance/floor2DInstance.tsx
@@ -0,0 +1,50 @@
+import { useMemo } from 'react';
+import { DoubleSide, Shape, Vector2 } from 'three';
+import { Extrude } from '@react-three/drei';
+import * as Constants from '../../../../../types/world/worldConstants';
+
+function Floor2DInstance({ floor }: { floor: Floor }) {
+ const savedTheme: string | null = localStorage.getItem("theme");
+
+ const shape = useMemo(() => {
+ const shape = new Shape();
+ const points = floor.points.map(p => new Vector2(p.position[0], p.position[2]));
+ if (points.length < 3) return null;
+ shape.moveTo(points[0].x, points[0].y);
+ for (let i = 1; i < points.length; i++) {
+ shape.lineTo(points[i].x, points[i].y);
+ }
+ return shape;
+ }, [floor]);
+
+ if (!shape) return null;
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default Floor2DInstance;
\ No newline at end of file
diff --git a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx
new file mode 100644
index 0000000..c6c8139
--- /dev/null
+++ b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx
@@ -0,0 +1,108 @@
+import { useMemo } from 'react';
+import { Shape, Vector2, DoubleSide, TextureLoader, RepeatWrapping, SRGBColorSpace } from 'three';
+import { useLoader } from '@react-three/fiber';
+import { Extrude } from '@react-three/drei';
+import useModuleStore from '../../../../../store/useModuleStore';
+import { useBuilderStore } from '../../../../../store/builder/useBuilderStore';
+import { useToggleView } from '../../../../../store/builder/store';
+import * as Constants from '../../../../../types/world/worldConstants';
+
+import texturePath from "../../../../../assets/textures/floor/white.png";
+import texturePathDark from "../../../../../assets/textures/floor/black.png";
+import material1 from '../../../../../assets/textures/floor/factory wall texture.jpg';
+
+function FloorInstance({ floor }: { floor: Floor }) {
+ const { togglView } = useToggleView();
+ const { activeModule } = useModuleStore();
+ const { selectedFloor, setSelectedFloor, setSelectedDecal } = useBuilderStore();
+ const savedTheme = localStorage.getItem('theme');
+
+ const materials: Record = {
+ "Default Material": savedTheme === "dark" ? texturePathDark : texturePath,
+ "Material 1": savedTheme === "dark" ? material1 : material1,
+ };
+
+ const shape = useMemo(() => {
+ const shape = new Shape();
+ const points = floor.points.map(p => new Vector2(p.position[0], p.position[2]));
+ if (points.length < 3) return null;
+ shape.moveTo(points[0].x, points[0].y);
+ for (let i = 1; i < points.length; i++) {
+ shape.lineTo(points[i].x, points[i].y);
+ }
+ return shape;
+ }, [floor]);
+
+ const textureScale = Constants.floorConfig.textureScale;
+
+ const [topTexture, sideTexture] = useLoader(
+ TextureLoader,
+ [
+ materials[floor.topMaterial] || materials['Default Material'],
+ materials[floor.sideMaterial] || materials['Default Material']
+ ]
+ );
+
+ if (!materials[floor.topMaterial] || !materials[floor.sideMaterial]) return null;
+
+ [topTexture, sideTexture].forEach(tex => {
+ tex.wrapS = tex.wrapT = RepeatWrapping;
+ tex.repeat.set(textureScale, textureScale);
+ tex.colorSpace = SRGBColorSpace;
+ });
+
+ if (!shape) return null;
+
+ return (
+ {
+ if (!togglView && activeModule === 'builder') {
+ if (e.object.userData.floorUuid) {
+ e.stopPropagation();
+ setSelectedFloor(e.object);
+ setSelectedDecal(null);
+ }
+ }
+ }}
+ onPointerMissed={() => {
+ if (selectedFloor && selectedFloor.userData.floorUuid === floor.floorUuid) {
+ setSelectedFloor(null);
+ }
+ }}
+ >
+
+
+
+
+
+ );
+}
+
+export default FloorInstance;
\ No newline at end of file
diff --git a/app/src/modules/builder/floor/Instances/floorInstances.tsx b/app/src/modules/builder/floor/Instances/floorInstances.tsx
new file mode 100644
index 0000000..a578800
--- /dev/null
+++ b/app/src/modules/builder/floor/Instances/floorInstances.tsx
@@ -0,0 +1,133 @@
+import React, { useEffect, useMemo } from 'react';
+import { Vector3 } from 'three';
+import { Html } from '@react-three/drei';
+import { useSceneContext } from '../../../scene/sceneContext';
+import { useToggleView } from '../../../../store/builder/store';
+import Line from '../../line/line';
+import Point from '../../point/point';
+import FloorInstance from './Instance/floorInstance';
+import Floor2DInstance from './Instance/floor2DInstance';
+
+function FloorInstances() {
+ const { floorStore } = useSceneContext();
+ const { floors } = floorStore();
+ const { toggleView } = useToggleView();
+
+ useEffect(() => {
+ // console.log('floors: ', floors);
+ }, [floors])
+
+ const allPoints = useMemo(() => {
+ const points: Point[] = [];
+ const seenUuids = new Set();
+
+ floors.forEach(floor => {
+ floor.points.forEach(point => {
+ if (!seenUuids.has(point.pointUuid)) {
+ seenUuids.add(point.pointUuid);
+ points.push(point);
+ }
+ });
+ });
+
+ return points;
+ }, [floors]);
+
+ const allLines = useMemo(() => {
+ const lines: { start: Point; end: Point; key: string }[] = [];
+ const seenUuids = new Set();
+
+ floors.forEach((floor) => {
+ const points = floor.points;
+ if (points.length < 2) return;
+
+ for (let i = 0; i < points.length; i++) {
+ const current = points[i];
+ const next = points[(i + 1) % points.length];
+ const lineKey = `${current.pointUuid}-${next.pointUuid}`;
+ if (current.pointUuid !== next.pointUuid && !seenUuids.has(lineKey)) {
+ seenUuids.add(lineKey);
+ lines.push({
+ start: current,
+ end: next,
+ key: lineKey
+ });
+ }
+ }
+ });
+
+ return lines;
+ }, [floors]);
+
+ return (
+ <>
+
+ {!toggleView && floors.length > 0 && (
+
+ {floors.map((floor) => (
+
+ ))}
+
+ )}
+
+ {toggleView && floors.length > 0 && (
+
+ {floors.map((floor) => (
+
+ ))}
+
+ )}
+
+ {toggleView && (
+ <>
+
+ {allPoints.map((point) => (
+
+ ))}
+
+
+
+
+ {allLines.map(({ start, end, key }) => (
+
+ ))}
+
+ {allLines.map((line) => {
+ const { start, end, key } = line;
+ const textPosition = new Vector3().addVectors(new Vector3(...start.position), new Vector3(...end.position)).divideScalar(2);
+ const distance = new Vector3(...start.position).distanceTo(new Vector3(...end.position));
+
+ return (
+
+ {toggleView &&
+
+
+ {distance.toFixed(2)} m
+
+
+ }
+
+ )
+ })}
+
+
+
+ >
+ )}
+ >
+ )
+}
+
+export default FloorInstances;
\ No newline at end of file
diff --git a/app/src/modules/builder/floor/floorCreator/floorCreator.tsx b/app/src/modules/builder/floor/floorCreator/floorCreator.tsx
new file mode 100644
index 0000000..acab425
--- /dev/null
+++ b/app/src/modules/builder/floor/floorCreator/floorCreator.tsx
@@ -0,0 +1,267 @@
+import * as THREE from 'three'
+import { useEffect, useMemo, useRef, useState } from 'react'
+import { useThree } from '@react-three/fiber';
+import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
+import { useSceneContext } from '../../../scene/sceneContext';
+import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
+import { useParams } from 'react-router-dom';
+import { useVersionContext } from '../../version/versionContext';
+import { getUserData } from '../../../../functions/getUserData';
+import ReferencePoint from '../../point/reference/referencePoint';
+import ReferenceFloor from './referenceFloor';
+
+// import { upsertFloorApi } from '../../../../services/factoryBuilder/floor/upsertFloorApi';
+
+function FloorCreator() {
+ const { scene, camera, raycaster, gl, pointer } = useThree();
+ const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
+ const { toggleView } = useToggleView();
+ const { toolMode } = useToolMode();
+ const { activeLayer } = useActiveLayer();
+ const { socket } = useSocketStore();
+ const { floorStore } = useSceneContext();
+ const { addFloor, getFloorPointById, getFloorByPoints } = floorStore();
+ const drag = useRef(false);
+ const isLeftMouseDown = useRef(false);
+ const { selectedVersionStore } = useVersionContext();
+ const { selectedVersion } = selectedVersionStore();
+ const { userId, organization } = getUserData();
+ const { projectId } = useParams();
+
+ const [tempPoints, setTempPoints] = useState([]);
+ const [isCreating, setIsCreating] = useState(false);
+ const { floorDepth, isBeveled, bevelStrength, sideMaterial, topMaterial, snappedPosition, snappedPoint, setSnappedPoint, setSnappedPosition } = useBuilderStore();
+
+ useEffect(() => {
+ const canvasElement = gl.domElement;
+
+ const onMouseDown = (evt: any) => {
+ if (evt.button === 0) {
+ isLeftMouseDown.current = true;
+ drag.current = false;
+ }
+ };
+
+ const onMouseUp = (evt: any) => {
+ if (evt.button === 0) {
+ isLeftMouseDown.current = false;
+ }
+ };
+
+ const onMouseMove = () => {
+ if (isLeftMouseDown) {
+ drag.current = true;
+ }
+ };
+
+ const onMouseClick = () => {
+ if (drag.current || !toggleView) return;
+
+ raycaster.setFromCamera(pointer, camera);
+ const intersectionPoint = new THREE.Vector3();
+ let position = raycaster.ray.intersectPlane(plane, intersectionPoint);
+ if (!position) return;
+
+ const pointIntersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Floor-Point');
+
+ // const floorIntersect = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Floor-Line');
+
+ // if (floorIntersect && !pointIntersects) {
+
+ // }
+
+ const newPoint: Point = {
+ pointUuid: THREE.MathUtils.generateUUID(),
+ pointType: 'Floor',
+ position: [position.x, position.y, position.z],
+ layer: activeLayer
+ };
+
+ if (snappedPosition && snappedPoint) {
+ newPoint.pointUuid = snappedPoint.pointUuid;
+ newPoint.position = snappedPosition;
+ newPoint.layer = snappedPoint.layer;
+ }
+
+ if (snappedPoint && snappedPoint.pointUuid === tempPoints[tempPoints.length - 1]?.pointUuid) { return }
+
+ if (snappedPosition && !snappedPoint) {
+ newPoint.position = snappedPosition;
+ }
+
+ if (tempPoints.length > 2 && isCreating && snappedPoint && snappedPoint.pointUuid === tempPoints[0].pointUuid) {
+ const floor: Floor = {
+ floorUuid: THREE.MathUtils.generateUUID(),
+ floorName: "Floor",
+ points: tempPoints,
+ topMaterial,
+ sideMaterial,
+ floorDepth,
+ isBeveled,
+ bevelStrength,
+ decals: [],
+ };
+
+ addFloor(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);
+
+ }
+ setTempPoints([]);
+ setIsCreating(false);
+ } else if (isCreating && snappedPoint && !tempPoints.some(p => p.pointUuid === snappedPoint.pointUuid)) {
+ setTempPoints(prev => [...prev, newPoint]);
+ setIsCreating(true);
+ } else if (pointIntersects) {
+ if (tempPoints.length > 2 && isCreating && pointIntersects.object.uuid === tempPoints[0].pointUuid) {
+ const floor: Floor = {
+ floorUuid: THREE.MathUtils.generateUUID(),
+ floorName: "Floor",
+ points: tempPoints,
+ topMaterial,
+ sideMaterial,
+ floorDepth,
+ isBeveled,
+ bevelStrength,
+ decals: [],
+ };
+
+ addFloor(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);
+
+ }
+ setTempPoints([]);
+ setIsCreating(false);
+ } else if (tempPoints.length === 0 || (tempPoints.length > 1 && !tempPoints.slice(1).some(p => p.pointUuid === pointIntersects.object.uuid))) {
+ tempPoints.push(pointIntersects.object.userData as Point);
+ setIsCreating(true);
+ }
+ } else {
+ setTempPoints(prev => [...prev, newPoint]);
+ setIsCreating(true);
+ }
+
+ };
+
+ const onContext = (event: any) => {
+ event.preventDefault();
+ if (isCreating) {
+ if (tempPoints.length >= 3) {
+ const floor: Floor = {
+ floorUuid: THREE.MathUtils.generateUUID(),
+ floorName: "Floor",
+ points: tempPoints,
+ topMaterial,
+ sideMaterial,
+ floorDepth,
+ isBeveled,
+ bevelStrength,
+ decals: [],
+ };
+
+ addFloor(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);
+
+ }
+ }
+ setTempPoints([]);
+ setIsCreating(false);
+ }
+ };
+
+ if (toolMode === "Floor" && toggleView) {
+ if (tempPoints.length === 0) {
+ setSnappedPosition(null);
+ setSnappedPoint(null);
+ }
+ canvasElement.addEventListener("mousedown", onMouseDown);
+ canvasElement.addEventListener("mouseup", onMouseUp);
+ canvasElement.addEventListener("mousemove", onMouseMove);
+ canvasElement.addEventListener("click", onMouseClick);
+ canvasElement.addEventListener("contextmenu", onContext);
+ } else {
+ setTempPoints([]);
+ setIsCreating(false);
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ canvasElement.removeEventListener("click", onMouseClick);
+ canvasElement.removeEventListener("contextmenu", onContext);
+ }
+
+ return () => {
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ canvasElement.removeEventListener("click", onMouseClick);
+ canvasElement.removeEventListener("contextmenu", onContext);
+ };
+ }, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addFloor, getFloorPointById, getFloorByPoints, floorDepth, isBeveled, bevelStrength, sideMaterial, topMaterial, snappedPosition, snappedPoint]);
+
+ return (
+ <>
+ {toggleView &&
+ <>
+
+ {tempPoints.map((point) => (
+
+ ))}
+
+
+ {tempPoints.length > 0 &&
+
+ }
+ >
+ }
+ >
+ )
+}
+
+export default FloorCreator
\ No newline at end of file
diff --git a/app/src/modules/builder/floor/floorCreator/referenceFloor.tsx b/app/src/modules/builder/floor/floorCreator/referenceFloor.tsx
new file mode 100644
index 0000000..71d376c
--- /dev/null
+++ b/app/src/modules/builder/floor/floorCreator/referenceFloor.tsx
@@ -0,0 +1,165 @@
+import { useEffect, useRef, useState, useMemo } from 'react';
+import * as THREE from 'three';
+import { useFrame, useThree } from '@react-three/fiber';
+import { Extrude, Html } from '@react-three/drei';
+import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
+import { useActiveLayer, useToolMode, useToggleView } from '../../../../store/builder/store';
+import { useDirectionalSnapping } from '../../point/helpers/useDirectionalSnapping';
+import { usePointSnapping } from '../../point/helpers/usePointSnapping';
+import ReferenceLine from '../../line/reference/referenceLine';
+
+interface ReferenceFloorProps {
+ tempPoints: Point[];
+}
+
+function ReferenceFloor({ tempPoints }: Readonly) {
+ const { floorDepth, isBeveled, bevelStrength, setSnappedPosition, setSnappedPoint } = useBuilderStore();
+ const { pointer, raycaster, camera } = useThree();
+ const { toolMode } = useToolMode();
+ const { toggleView } = useToggleView();
+ const { activeLayer } = useActiveLayer();
+ const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
+ const finalPosition = useRef<[number, number, number] | null>(null);
+
+ const [tempFloor, setTempFloor] = useState(null);
+ const [currentPosition, setCurrentPosition] = useState<[number, number, number]>(tempPoints[0]?.position);
+
+ const directionalSnap = useDirectionalSnapping(currentPosition, tempPoints[tempPoints.length - 1]?.position || null);
+ const { snapFloorPoint } = usePointSnapping({ uuid: 'temp-Floor', pointType: 'Floor', position: directionalSnap.position || [0, 0, 0], });
+
+ useFrame(() => {
+ if (toolMode === 'Floor' && toggleView && tempPoints.length > 0) {
+ raycaster.setFromCamera(pointer, camera);
+ const intersectionPoint = new THREE.Vector3();
+ raycaster.ray.intersectPlane(plane, intersectionPoint);
+
+ setCurrentPosition([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z]);
+
+ if (!intersectionPoint) return;
+ const snapped = snapFloorPoint([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z], tempPoints.length > 2 ? [tempPoints[0]] : []);
+
+ if (snapped.isSnapped && snapped.snappedPoint) {
+ finalPosition.current = snapped.position;
+ setSnappedPosition(snapped.position);
+ setSnappedPoint(snapped.snappedPoint);
+ } else if (directionalSnap.isSnapped) {
+ finalPosition.current = directionalSnap.position;
+ setSnappedPosition(directionalSnap.position);
+ setSnappedPoint(null);
+ } else {
+ finalPosition.current = [intersectionPoint.x, intersectionPoint.y, intersectionPoint.z];
+ setSnappedPosition(null);
+ setSnappedPoint(null);
+ }
+
+ if (!finalPosition.current) return;
+
+ const floorPoints: Point[] = [
+ ...tempPoints,
+ {
+ pointUuid: 'temp-point',
+ pointType: 'Floor',
+ position: finalPosition.current,
+ layer: activeLayer,
+ },
+ ];
+
+ setTempFloor({
+ floorUuid: 'temp-floor',
+ floorName: 'temp-floor',
+ points: floorPoints,
+ topMaterial: 'default',
+ sideMaterial: 'default',
+ floorDepth,
+ bevelStrength,
+ isBeveled,
+ decals: [],
+ });
+
+ } else if (tempFloor !== null) {
+ setTempFloor(null);
+ }
+ });
+
+ useEffect(() => {
+ setTempFloor(null);
+ }, [toolMode, toggleView, tempPoints.length, floorDepth, bevelStrength, isBeveled, activeLayer]);
+
+ const allLines = useMemo(() => {
+ if (!tempFloor || tempFloor.points.length < 2) return [];
+
+ const lines: [Point, Point][] = [];
+ const pts = tempFloor.points;
+
+ for (let i = 0; i < pts.length - 1; i++) {
+ lines.push([pts[i], pts[i + 1]]);
+ }
+
+ return lines;
+ }, [tempFloor]);
+
+ if (!tempFloor) return null;
+
+ return (
+
+ {allLines.map(([p1, p2], idx) => {
+ const v1 = new THREE.Vector3(...p1.position);
+ const v2 = new THREE.Vector3(...p2.position);
+ const mid = new THREE.Vector3().addVectors(v1, v2).multiplyScalar(0.5);
+ const dist = v1.distanceTo(v2);
+
+ return (
+
+
+ {toggleView && (
+
+ {dist.toFixed(2)} m
+
+ )}
+
+ );
+ })}
+
+ {tempPoints.length >= 3 && (
+
+ )}
+
+ );
+}
+
+export default ReferenceFloor;
+
+
+function Floor({ floor }: { floor: Point[] }) {
+ const savedTheme: string | null = localStorage.getItem('theme');
+
+ const shape = useMemo(() => {
+ const shape = new THREE.Shape();
+ const points = floor.map(p => new THREE.Vector2(p.position[0], p.position[2]));
+ if (points.length < 3) return null;
+ shape.moveTo(points[0].x, points[0].y);
+ points.forEach((pt) => { shape.lineTo(pt.x, pt.y); });
+ return shape;
+ }, [floor]);
+
+ if (!shape) return null;
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/app/src/modules/builder/floor/floorGroup.tsx b/app/src/modules/builder/floor/floorGroup.tsx
new file mode 100644
index 0000000..47ea3b5
--- /dev/null
+++ b/app/src/modules/builder/floor/floorGroup.tsx
@@ -0,0 +1,55 @@
+import { useEffect } from 'react';
+import { useActiveTool, useToggleView } from '../../../store/builder/store'
+import { useBuilderStore } from '../../../store/builder/useBuilderStore';
+import { useVersionContext } from '../version/versionContext';
+import { useSceneContext } from '../../scene/sceneContext';
+import { useParams } from 'react-router-dom';
+import useModuleStore from '../../../store/useModuleStore';
+import FloorCreator from './floorCreator/floorCreator';
+import FloorInstances from './Instances/floorInstances';
+import { getFloorsApi } from '../../../services/factoryBuilder/floor/getFloorsApi';
+
+function FloorGroup() {
+ const { togglView } = useToggleView();
+ const { setSelectedFloor, setSelectedDecal } = useBuilderStore();
+ const { activeModule } = useModuleStore();
+ const { activeTool } = useActiveTool();
+ const { selectedVersionStore } = useVersionContext();
+ const { selectedVersion } = selectedVersionStore();
+ const { floorStore } = useSceneContext();
+ const { setFloors } = floorStore();
+ const { projectId } = useParams();
+
+ useEffect(() => {
+ if (togglView || activeModule !== 'builder') {
+ setSelectedFloor(null);
+ setSelectedDecal(null);
+ }
+ }, [togglView, activeModule, activeTool])
+
+ useEffect(() => {
+ if (projectId && selectedVersion) {
+ getFloorsApi(projectId, selectedVersion?.versionId || '').then((floors) => {
+ if (floors && floors.length > 0) {
+ setFloors(floors);
+ } else {
+ setFloors([]);
+ }
+ }).catch((err) => {
+ console.log(err);
+ })
+ }
+ }, [projectId, selectedVersion?.versionId])
+
+ return (
+ <>
+
+
+
+
+
+ >
+ )
+}
+
+export default FloorGroup
\ No newline at end of file
diff --git a/app/src/modules/builder/functions/deletableLineOrPoint.ts b/app/src/modules/builder/functions/deletableLineOrPoint.ts
deleted file mode 100644
index cbca682..0000000
--- a/app/src/modules/builder/functions/deletableLineOrPoint.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import * as THREE from 'three';
-import * as CONSTANTS from '../../../types/world/worldConstants';
-import * as Types from "../../../types/world/worldTypes";
-
-function DeletableLineorPoint(
- state: Types.ThreeState,
- plane: Types.RefMesh,
- floorPlanGroupLine: Types.RefGroup,
- floorPlanGroupPoint: Types.RefGroup,
- hoveredDeletableLine: Types.RefMesh,
- hoveredDeletablePoint: Types.RefMesh
-): void {
-
- ////////// Altering the color of the hovered line or point during the deletion time //////////
-
- if (!plane.current) return;
- let intersects = state.raycaster.intersectObject(plane.current, true);
-
- let visibleIntersectLines;
- if (floorPlanGroupLine.current) { visibleIntersectLines = state.raycaster?.intersectObjects(floorPlanGroupLine.current.children, true); }
- const visibleIntersectLine = visibleIntersectLines?.find(intersect => intersect.object.visible) as THREE.Line | undefined || null;
-
- let visibleIntersectPoints;
- if (floorPlanGroupPoint.current) {
- visibleIntersectPoints = state.raycaster?.intersectObjects(floorPlanGroupPoint.current.children, true);
- }
- const visibleIntersectPoint = visibleIntersectPoints?.find(intersect => intersect.object.visible) as THREE.Mesh | undefined;
-
- function getLineColor(lineType: string | undefined): string {
- switch (lineType) {
- case CONSTANTS.lineConfig.wallName: return CONSTANTS.lineConfig.wallColor;
- case CONSTANTS.lineConfig.floorName: return CONSTANTS.lineConfig.floorColor;
- case CONSTANTS.lineConfig.aisleName: return CONSTANTS.lineConfig.aisleColor;
- default: return CONSTANTS.lineConfig.defaultColor;
- }
- }
-
- if (intersects.length > 0) {
- if (visibleIntersectPoint) {
- if (hoveredDeletableLine.current) {
- const lineType = hoveredDeletableLine.current.userData.linePoints[1]?.[3];
- const color = getLineColor(lineType);
- (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color(color);
- hoveredDeletableLine.current = null;
- }
-
- hoveredDeletablePoint.current = (visibleIntersectPoint as any).object;
- (hoveredDeletablePoint.current as any).material.uniforms.uInnerColor.value.set(new THREE.Color("red"));
- (hoveredDeletablePoint.current as any).material.uniforms.uOuterColor.value.set(new THREE.Color("red"));
- // (hoveredDeletablePoint.current as THREE.Mesh).scale.set(1.5, 1.5, 1.5);
- } else if (hoveredDeletablePoint.current) {
- (hoveredDeletablePoint.current as any).material.uniforms.uInnerColor.value.set(CONSTANTS.pointConfig.defaultInnerColor);
- (hoveredDeletablePoint.current as any).material.uniforms.uOuterColor.value.set((hoveredDeletablePoint.current as any).userData.color);
- // hoveredDeletablePoint.current.scale.set(1, 1, 1);
- hoveredDeletablePoint.current = null;
- }
-
- if (visibleIntersectLine && !visibleIntersectPoint) {
- if (hoveredDeletableLine.current) {
- const lineType = hoveredDeletableLine.current.userData.linePoints[1]?.[3];
- const color = getLineColor(lineType);
- (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color(color);
- hoveredDeletableLine.current = null;
- }
-
- if (hoveredDeletablePoint.current) {
- (hoveredDeletablePoint.current as any).material.uniforms.uInnerColor.value.set(CONSTANTS.pointConfig.defaultInnerColor);
- (hoveredDeletablePoint.current as any).material.uniforms.uOuterColor.value.set((hoveredDeletablePoint.current as any).userData.color);
- // hoveredDeletablePoint.current.scale.set(1, 1, 1);
- hoveredDeletablePoint.current = null;
- }
-
- hoveredDeletableLine.current = (visibleIntersectLine as any).object;
- if (hoveredDeletableLine.current) {
- (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color("red");
- }
- } else if (hoveredDeletableLine.current) {
- const lineType = hoveredDeletableLine.current.userData.linePoints[1]?.[3];
- const color = getLineColor(lineType);
- (hoveredDeletableLine.current.material as THREE.MeshBasicMaterial).color = new THREE.Color(color);
- hoveredDeletableLine.current = null;
- }
- }
-
-}
-
-export default DeletableLineorPoint;
diff --git a/app/src/modules/builder/functions/draw.ts b/app/src/modules/builder/functions/draw.ts
deleted file mode 100644
index 425fbbb..0000000
--- a/app/src/modules/builder/functions/draw.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import * as Types from "../../../types/world/worldTypes";
-import * as CONSTANTS from '../../../types/world/worldConstants';
-import createAndMoveReferenceLine from "../geomentries/lines/createAndMoveReferenceLine";
-
-async function Draw(
- state: Types.ThreeState,
- plane: Types.RefMesh,
- cursorPosition: Types.Vector3,
- floorPlanGroupPoint: Types.RefGroup,
- snappedPoint: Types.RefVector3,
- isSnapped: Types.RefBoolean,
- isSnappedUUID: Types.RefString,
- line: Types.RefLine,
- ispreSnapped: Types.RefBoolean,
- floorPlanGroup: Types.RefGroup,
- ReferenceLineMesh: Types.RefMesh,
- LineCreated: Types.RefBoolean,
- setRefTextUpdate: any,
- Tube: Types.RefTubeGeometry,
- anglesnappedPoint: Types.RefVector3,
- isAngleSnapped: Types.RefBoolean,
- toolMode: Types.String,
-): Promise {
-
- ////////// Snapping the cursor during the drawing time and also changing the color of the intersected lines //////////
-
- if (!plane.current) return;
- const intersects = state.raycaster.intersectObject(plane.current, true);
-
- if (intersects.length > 0 && (toolMode === "Wall" || toolMode === "Floor")) {
- const intersectionPoint = intersects[0].point;
- cursorPosition.copy(intersectionPoint);
- const snapThreshold = 1;
-
- if (line.current.length === 0) {
- for (const point of floorPlanGroupPoint.current.children) {
- const pointType = point.userData.type;
-
- const canSnap =
- ((toolMode === "Wall") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName)) ||
- ((toolMode === "Floor") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName))
-
- if (canSnap && cursorPosition.distanceTo(point.position) < snapThreshold + 0.5 && point.visible) {
- cursorPosition.copy(point.position);
- snappedPoint.current = point.position;
- ispreSnapped.current = true;
- isSnapped.current = false;
- isSnappedUUID.current = point.uuid;
- break;
- } else {
- ispreSnapped.current = false;
- }
- }
- } else if (line.current.length > 0 && line.current[0]) {
- for (const point of floorPlanGroupPoint.current.children) {
- const pointType = point.userData.type;
-
- let canSnap =
- ((toolMode === "Wall") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName)) ||
- ((toolMode === "Floor") && (pointType === CONSTANTS.lineConfig.wallName || pointType === CONSTANTS.lineConfig.floorName))
-
- if (canSnap && cursorPosition.distanceTo(point.position) < snapThreshold && point.visible) {
- cursorPosition.copy(point.position);
- snappedPoint.current = point.position;
- isSnapped.current = true;
- ispreSnapped.current = false;
- isSnappedUUID.current = point.uuid;
- break;
- } else {
- isSnapped.current = false;
- }
- }
-
- createAndMoveReferenceLine(
- line.current[0][0],
- cursorPosition,
- isSnapped,
- ispreSnapped,
- line,
- setRefTextUpdate,
- floorPlanGroup,
- ReferenceLineMesh,
- LineCreated,
- Tube,
- anglesnappedPoint,
- isAngleSnapped
- );
- }
- }
-
-}
-
-export default Draw;
\ No newline at end of file
diff --git a/app/src/modules/builder/geomentries/floors/addFloorToScene.ts b/app/src/modules/builder/geomentries/floors/addFloorToScene.ts
deleted file mode 100644
index 71f2d24..0000000
--- a/app/src/modules/builder/geomentries/floors/addFloorToScene.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import * as THREE from 'three';
-import * as Types from "../../../../types/world/worldTypes";
-import * as CONSTANTS from "../../../../types/world/worldConstants";
-
-import texturePath from "../../../../assets/textures/floor/white.png";
-import texturePathDark from "../../../../assets/textures/floor/black.png";
-
-// Cache for materials
-const materialCache = new Map();
-
-export default function addFloorToScene(
- shape: THREE.Shape,
- layer: number,
- floorGroup: Types.RefGroup,
- userData: any,
-) {
- const savedTheme: string | null = localStorage.getItem('theme');
-
- const textureLoader = new THREE.TextureLoader();
-
- const textureScale = CONSTANTS.floorConfig.textureScale;
-
- const materialKey = `floorMaterial_${textureScale}`;
-
- let material: THREE.Material;
-
- if (materialCache.has(materialKey)) {
- material = materialCache.get(materialKey) as THREE.Material;
- } else {
- const floorTexture = textureLoader.load(savedTheme === "dark" ? texturePathDark : texturePath);
- // const floorTexture = textureLoader.load(texturePath);
-
- floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
- floorTexture.repeat.set(textureScale, textureScale);
- floorTexture.colorSpace = THREE.SRGBColorSpace;
-
- material = new THREE.MeshStandardMaterial({
- map: floorTexture,
- side: THREE.DoubleSide,
- });
-
- materialCache.set(materialKey, material);
- }
-
- const extrudeSettings = {
- depth: CONSTANTS.floorConfig.height,
- bevelEnabled: false,
- };
-
- const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
- const mesh = new THREE.Mesh(geometry, material);
-
- mesh.receiveShadow = true;
- mesh.position.y = (layer) * CONSTANTS.wallConfig.height;
- mesh.rotateX(Math.PI / 2);
- mesh.name = `Floor_Layer_${layer}`;
-
- // Store UUIDs for debugging or future processing
- mesh.userData.uuids = userData;
-
- floorGroup.current.add(mesh);
-}
diff --git a/app/src/modules/builder/geomentries/floors/drawOnlyFloor.ts b/app/src/modules/builder/geomentries/floors/drawOnlyFloor.ts
deleted file mode 100644
index 74b06ef..0000000
--- a/app/src/modules/builder/geomentries/floors/drawOnlyFloor.ts
+++ /dev/null
@@ -1,275 +0,0 @@
-import * as THREE from "three";
-
-import * as Types from "../../../../types/world/worldTypes";
-import * as CONSTANTS from "../../../../types/world/worldConstants";
-
-import addPointToScene from "../points/addPointToScene";
-import addLineToScene from "../lines/addLineToScene";
-import splitLine from "../lines/splitLine";
-import removeReferenceLine from "../lines/removeReferenceLine";
-import getClosestIntersection from "../lines/getClosestIntersection";
-import arrayLineToObject from "../lines/lineConvertions/arrayLineToObject";
-// import { setLine } from '../../../../services/factoryBuilder/lines/setLineApi';
-import { Socket } from "socket.io-client";
-import { getUserData } from "../../../../functions/getUserData";
-
-async function drawOnlyFloor(
- raycaster: THREE.Raycaster,
- state: Types.ThreeState,
- camera: THREE.Camera,
- plane: Types.RefMesh,
- floorPlanGroupPoint: Types.RefGroup,
- snappedPoint: Types.RefVector3,
- isSnapped: Types.RefBoolean,
- isSnappedUUID: Types.RefString,
- line: Types.RefLine,
- ispreSnapped: Types.RefBoolean,
- anglesnappedPoint: Types.RefVector3,
- isAngleSnapped: Types.RefBoolean,
- onlyFloorline: Types.RefOnlyFloorLine,
- onlyFloorlines: Types.RefOnlyFloorLines,
- lines: Types.RefLines,
- floorPlanGroupLine: Types.RefGroup,
- floorPlanGroup: Types.RefGroup,
- ReferenceLineMesh: Types.RefMesh,
- LineCreated: Types.RefBoolean,
- currentLayerPoint: Types.RefMeshArray,
- dragPointControls: Types.RefDragControl,
- setNewLines: any,
- setDeletedLines: any,
- activeLayer: Types.Number,
- socket: Socket,
- projectId?: string,
- versionId?: string,
-): Promise {
- ////////// Creating lines Based on the positions clicked //////////
-
- if (!plane.current) return;
- const { userId, organization, email } = getUserData();
- const intersects = raycaster.intersectObject(plane.current, true);
- const intersectsLines = raycaster.intersectObjects(
- floorPlanGroupLine.current.children,
- true
- );
- const intersectsPoint = raycaster.intersectObjects(
- floorPlanGroupPoint.current.children,
- true
- );
- const VisibleintersectsPoint = intersectsPoint.find(
- (intersect) => intersect.object.visible
- );
- const visibleIntersect = intersectsLines.find(
- (intersect) =>
- intersect.object.visible &&
- intersect.object.name !== CONSTANTS.lineConfig.referenceName
- );
- if (
- (intersectsPoint.length === 0 || VisibleintersectsPoint === undefined) &&
- intersectsLines.length > 0 &&
- !isSnapped.current &&
- !ispreSnapped.current
- ) {
- ////////// Clicked on a preexisting Line //////////
-
- if (
- visibleIntersect &&
- (intersectsLines[0].object.userData.linePoints[0][3] ===
- CONSTANTS.lineConfig.floorName ||
- intersectsLines[0].object.userData.linePoints[0][3] ===
- CONSTANTS.lineConfig.wallName)
- ) {
- let pointColor, lineColor;
- if (
- intersectsLines[0].object.userData.linePoints[0][3] ===
- CONSTANTS.lineConfig.wallName
- ) {
- pointColor = CONSTANTS.pointConfig.wallOuterColor;
- lineColor = CONSTANTS.lineConfig.wallColor;
- } else {
- pointColor = CONSTANTS.pointConfig.floorOuterColor;
- lineColor = CONSTANTS.lineConfig.floorColor;
- }
- let IntersectsPoint = new THREE.Vector3(
- intersects[0].point.x,
- 0.01,
- intersects[0].point.z
- );
- if (
- isAngleSnapped.current &&
- line.current.length > 0 &&
- anglesnappedPoint.current
- ) {
- IntersectsPoint = anglesnappedPoint.current;
- }
- if (visibleIntersect.object instanceof THREE.Mesh) {
- const ThroughPoint =
- visibleIntersect.object.geometry.parameters.path.getPoints(
- CONSTANTS.lineConfig.lineIntersectionPoints
- );
- let intersectionPoint = getClosestIntersection(
- ThroughPoint,
- IntersectsPoint
- );
-
- if (intersectionPoint) {
- const newLines = splitLine(
- visibleIntersect,
- intersectionPoint,
- currentLayerPoint,
- floorPlanGroupPoint,
- dragPointControls,
- isSnappedUUID,
- lines,
- setDeletedLines,
- floorPlanGroupLine,
- socket,
- pointColor,
- lineColor,
- intersectsLines[0].object.userData.linePoints[0][3],
- projectId
- );
- setNewLines([newLines[0], newLines[1]]);
-
- (line.current as Types.Line).push([
- new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z),
- isSnappedUUID.current!,
- activeLayer,
- CONSTANTS.lineConfig.floorName,
- ]);
-
- if (line.current.length >= 2 && line.current[0] && line.current[1]) {
- lines.current.push(line.current as Types.Line);
- const data = arrayLineToObject(line.current as Types.Line);
-
- //REST
-
- // setLine(organization, data.layer!, data.line!, data.type!);
-
- //SOCKET
-
- const input = {
- organization,
- layer: data.layer,
- line: data.line,
- type: data.type,
- socketId: socket.id,
- projectId,
- versionId,
- userId,
- };
-
- console.log('input: ', input);
- socket.emit("v1:Line:create", input);
-
- setNewLines([newLines[0], newLines[1], line.current]);
- onlyFloorline.current.push(line.current as Types.Line);
- onlyFloorlines.current.push(onlyFloorline.current);
- onlyFloorline.current = [];
-
- addLineToScene(
- line.current[0][0],
- line.current[1][0],
- CONSTANTS.lineConfig.floorColor,
- line.current,
- floorPlanGroupLine
- );
-
- removeReferenceLine(
- floorPlanGroup,
- ReferenceLineMesh,
- LineCreated,
- line
- );
- }
- return;
- }
- }
- }
- }
- if (intersects.length > 0 && intersectsLines.length === 0) {
- ////////// Clicked on an empty place or a point //////////
-
- let intersectionPoint = intersects[0].point;
-
- if (
- isAngleSnapped.current &&
- line.current.length > 0 &&
- anglesnappedPoint.current
- ) {
- intersectionPoint = anglesnappedPoint.current;
- }
- if (isSnapped.current && line.current.length > 0 && snappedPoint.current) {
- intersectionPoint = snappedPoint.current;
- }
- if (ispreSnapped.current && snappedPoint.current) {
- intersectionPoint = snappedPoint.current;
- }
-
- if (!isSnapped.current && !ispreSnapped.current) {
- addPointToScene(
- intersectionPoint,
- CONSTANTS.pointConfig.floorOuterColor,
- currentLayerPoint,
- floorPlanGroupPoint,
- dragPointControls,
- isSnappedUUID,
- CONSTANTS.lineConfig.floorName
- );
- } else {
- ispreSnapped.current = false;
- isSnapped.current = false;
- }
-
- (line.current as Types.Line).push([
- new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z),
- isSnappedUUID.current!,
- activeLayer,
- CONSTANTS.lineConfig.floorName,
- ]);
-
- if (line.current.length >= 2 && line.current[0] && line.current[1]) {
- onlyFloorline.current.push(line.current as Types.Line);
- lines.current.push(line.current as Types.Line);
- const data = arrayLineToObject(line.current as Types.Line);
-
- //REST
-
- // setLine(organization, data.layer!, data.line!, data.type!);
-
- //SOCKET
-
- const input = {
- organization,
- layer: data.layer,
- line: data.line,
- type: data.type,
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- console.log('input: ', input);
- socket.emit("v1:Line:create", input);
-
- setNewLines([line.current]);
- addLineToScene(
- line.current[0][0],
- line.current[1][0],
- CONSTANTS.lineConfig.floorColor,
- line.current,
- floorPlanGroupLine
- );
- const lastPoint = line.current[line.current.length - 1];
- line.current = [lastPoint];
- }
- if (isSnapped.current) {
- ////////// Add this to stop the drawing mode after snapping //////////
- removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
- onlyFloorlines.current.push(onlyFloorline.current);
- onlyFloorline.current = [];
- }
- }
-}
-
-export default drawOnlyFloor;
diff --git a/app/src/modules/builder/geomentries/floors/loadFloor.ts b/app/src/modules/builder/geomentries/floors/loadFloor.ts
deleted file mode 100644
index d4f2fc1..0000000
--- a/app/src/modules/builder/geomentries/floors/loadFloor.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import * as THREE from 'three';
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-import addRoofToScene from '../roofs/addRoofToScene';
-
-import * as Types from "../../../../types/world/worldTypes";
-import loadOnlyFloors from './loadOnlyFloors';
-import addFloorToScene from './addFloorToScene';
-import getRoomsFromLines from '../lines/getRoomsFromLines';
-
-async function loadFloor(
- lines: Types.RefLines,
- floorGroup: Types.RefGroup,
-): Promise {
-
- if (!floorGroup.current) return;
-
- floorGroup.current.children = [];
-
- if (lines.current.length > 2) {
- const linesByLayer = lines.current.reduce((acc: { [key: number]: any[] }, pair) => {
- const layer = pair[0][2];
- if (!acc[layer]) acc[layer] = [];
- acc[layer].push(pair);
- return acc;
- }, {});
-
- for (const layer in linesByLayer) {
- // Only Floor Polygons
- loadOnlyFloors(floorGroup, linesByLayer, layer);
-
- const rooms: Types.Rooms = await getRoomsFromLines({ current: linesByLayer[layer] });
-
- rooms.forEach(({ coordinates: room, layer }) => {
- const userData = room.map(point => point.uuid);
- const shape = new THREE.Shape();
- shape.moveTo(room[0].position.x, room[0].position.z);
- room.forEach(point => shape.lineTo(point.position.x, point.position.z));
- shape.closePath();
-
- // Floor Polygons
- addFloorToScene(shape, (layer - 1) * CONSTANTS.wallConfig.height, floorGroup, userData);
-
- // Roof Polygons
- addRoofToScene(shape, (layer - 1) * CONSTANTS.wallConfig.height, userData, floorGroup);
- });
- }
- }
-}
-
-export default loadFloor;
diff --git a/app/src/modules/builder/geomentries/floors/loadOnlyFloors.ts b/app/src/modules/builder/geomentries/floors/loadOnlyFloors.ts
deleted file mode 100644
index 3da7b46..0000000
--- a/app/src/modules/builder/geomentries/floors/loadOnlyFloors.ts
+++ /dev/null
@@ -1,183 +0,0 @@
-import * as THREE from 'three';
-import * as turf from '@turf/turf';
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-import * as Types from "../../../../types/world/worldTypes";
-
-function loadOnlyFloors(
- floorGroup: Types.RefGroup,
- linesByLayer: any,
- layer: any,
-): void {
-
- ////////// Creating polygon floor based on the onlyFloorlines.current which does not add roof to it, The lines are still stored in Lines.current as well //////////
-
- let floorsInLayer = linesByLayer[layer];
- floorsInLayer = floorsInLayer.filter((line: any) => line[0][3] && line[1][3] === CONSTANTS.lineConfig.floorName);
- const floorResult = floorsInLayer.map((pair: [THREE.Vector3, string, number, string][]) =>
- pair.map((point) => ({
- position: [point[0].x, point[0].z],
- uuid: point[1]
- }))
- );
- const FloorLineFeatures = floorResult.map((line: any) => turf.lineString(line.map((p: any) => p.position)));
-
- function identifyPolygonsAndConnectedLines(FloorLineFeatures: any) {
- const floorpolygons = [];
- const connectedLines = [];
- const unprocessedLines = [...FloorLineFeatures]; // Copy the features
-
- while (unprocessedLines.length > 0) {
- const currentLine = unprocessedLines.pop();
- const coordinates = currentLine.geometry.coordinates;
-
- // Check if the line is closed (forms a polygon)
- if (
- coordinates[0][0] === coordinates[coordinates.length - 1][0] &&
- coordinates[0][1] === coordinates[coordinates.length - 1][1]
- ) {
- floorpolygons.push(turf.polygon([coordinates])); // Add as a polygon
- continue;
- }
-
- // Check if the line connects to another line
- let connected = false;
- for (let i = unprocessedLines.length - 1; i >= 0; i--) {
- const otherCoordinates = unprocessedLines[i].geometry.coordinates;
-
- // Check if lines share a start or end point
- if (
- coordinates[0][0] === otherCoordinates[otherCoordinates.length - 1][0] &&
- coordinates[0][1] === otherCoordinates[otherCoordinates.length - 1][1]
- ) {
- // Merge lines
- const mergedCoordinates = [...otherCoordinates, ...coordinates.slice(1)];
- unprocessedLines[i] = turf.lineString(mergedCoordinates);
- connected = true;
- break;
- } else if (
- coordinates[coordinates.length - 1][0] === otherCoordinates[0][0] &&
- coordinates[coordinates.length - 1][1] === otherCoordinates[0][1]
- ) {
- // Merge lines
- const mergedCoordinates = [...coordinates, ...otherCoordinates.slice(1)];
- unprocessedLines[i] = turf.lineString(mergedCoordinates);
- connected = true;
- break;
- }
- }
-
- if (!connected) {
- connectedLines.push(currentLine); // Add unconnected line as-is
- }
- }
-
- return { floorpolygons, connectedLines };
- }
-
- const { floorpolygons, connectedLines } = identifyPolygonsAndConnectedLines(FloorLineFeatures);
-
- function convertConnectedLinesToPolygons(connectedLines: any) {
- return connectedLines.map((line: any) => {
- const coordinates = line.geometry.coordinates;
-
- // If the line has more than two points, close the polygon
- if (coordinates.length > 2) {
- const firstPoint = coordinates[0];
- const lastPoint = coordinates[coordinates.length - 1];
-
- // Check if already closed; if not, close it
- if (firstPoint[0] !== lastPoint[0] || firstPoint[1] !== lastPoint[1]) {
- coordinates.push(firstPoint);
- }
-
- // Convert the closed line into a polygon
- return turf.polygon([coordinates]);
- }
-
- // If not enough points for a polygon, return the line unchanged
- return line;
- });
- }
-
- const convertedConnectedPolygons = convertConnectedLinesToPolygons(connectedLines);
-
- if (convertedConnectedPolygons.length > 0) {
- const validPolygons = convertedConnectedPolygons.filter(
- (polygon: any) => polygon.geometry?.type === "Polygon"
- );
-
- if (validPolygons.length > 0) {
- floorpolygons.push(...validPolygons);
- }
- }
-
- function convertPolygonsToOriginalFormat(floorpolygons: any, originalLines: [THREE.Vector3, string, number, string][][]) {
- return floorpolygons.map((polygon: any) => {
- const coordinates = polygon.geometry.coordinates[0]; // Extract the coordinates array (assume it's a single polygon)
-
- // Map each coordinate back to its original structure
- const mappedPoints = coordinates.map((coord: [number, number]) => {
- const [x, z] = coord;
-
- // Find the original point matching this coordinate
- const originalPoint = originalLines.flat().find(([point]) => point.x === x && point.z === z);
-
- if (!originalPoint) {
- console.error(`Original point for coordinate [${x}, ${z}] not found.`);
- }
-
- return originalPoint;
- });
-
- // Create pairs of consecutive points
- const pairs: typeof originalLines = [];
- for (let i = 0; i < mappedPoints.length - 1; i++) {
- pairs.push([mappedPoints[i], mappedPoints[i + 1]]);
- }
-
- return pairs;
- });
- }
-
- const convertedFloorPolygons: Types.OnlyFloorLines = convertPolygonsToOriginalFormat(floorpolygons, floorsInLayer);
-
- convertedFloorPolygons.forEach((floor) => {
- const points: THREE.Vector3[] = [];
-
- floor.forEach((lineSegment) => {
- const startPoint = lineSegment[0][0];
- points.push(new THREE.Vector3(startPoint.x, startPoint.y, startPoint.z));
- });
-
- const lastLine = floor[floor.length - 1];
- const endPoint = lastLine[1][0];
- points.push(new THREE.Vector3(endPoint.x, endPoint.y, endPoint.z));
-
- const shape = new THREE.Shape();
- shape.moveTo(points[0].x, points[0].z);
-
- points.forEach(point => shape.lineTo(point.x, point.z));
- shape.closePath();
-
- const extrudeSettings = {
- depth: CONSTANTS.floorConfig.height,
- bevelEnabled: false
- };
-
- const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
- const material = new THREE.MeshStandardMaterial({ color: CONSTANTS.floorConfig.defaultColor, side: THREE.DoubleSide });
- const mesh = new THREE.Mesh(geometry, material);
-
- mesh.castShadow = true;
- mesh.receiveShadow = true;
-
- mesh.position.y = (floor[0][0][2] - 1) * CONSTANTS.wallConfig.height;
- mesh.rotateX(Math.PI / 2);
- mesh.name = `Only_Floor_Line_${floor[0][0][2]}`;
-
- mesh.userData = floor;
- floorGroup?.current?.add(mesh);
- });
-}
-
-export default loadOnlyFloors;
diff --git a/app/src/modules/builder/geomentries/floors/updateFloorLines.ts b/app/src/modules/builder/geomentries/floors/updateFloorLines.ts
deleted file mode 100644
index 4198a00..0000000
--- a/app/src/modules/builder/geomentries/floors/updateFloorLines.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as Types from "../../../../types/world/worldTypes";
-
-function updateFloorLines(
- onlyFloorlines: Types.RefOnlyFloorLines,
- DragedPoint: Types.Mesh | { uuid: string, position: Types.Vector3 }
-): void {
-
- ////////// Update onlyFloorlines.current if it contains the dragged point //////////
-
- onlyFloorlines.current.forEach((floorline) => {
- floorline.forEach((line) => {
- line.forEach((point) => {
- const [position, uuid] = point;
- if (uuid === DragedPoint.uuid) {
- position.x = DragedPoint.position.x;
- position.y = 0.01;
- position.z = DragedPoint.position.z;
- }
- });
- });
- });
-}
-
-export default updateFloorLines;
diff --git a/app/src/modules/builder/geomentries/layers/deleteLayer.ts b/app/src/modules/builder/geomentries/layers/deleteLayer.ts
deleted file mode 100644
index 318cc61..0000000
--- a/app/src/modules/builder/geomentries/layers/deleteLayer.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-import { toast } from "react-toastify";
-import RemoveConnectedLines from "../lines/removeConnectedLines";
-
-import * as Types from "../../../../types/world/worldTypes";
-import { Socket } from "socket.io-client";
-import { getUserData } from "../../../../functions/getUserData";
-// import { deleteLayer } from '../../../../services/factoryBuilder/lines/deleteLayerApi';
-
-async function DeleteLayer(
- removedLayer: Types.Number,
- lines: Types.RefLines,
- floorPlanGroupLine: Types.RefGroup,
- floorPlanGroupPoint: Types.RefGroup,
- onlyFloorlines: Types.RefOnlyFloorLines,
- floorGroup: Types.RefGroup,
- setDeletedLines: any,
- setRemovedLayer: Types.setRemoveLayerSetState,
- socket: Socket,
- projectId?: string,
- versionId?: string,
-): Promise {
- ////////// Remove the Lines from the lines.current based on the removed layer and rearrange the layer number that are higher than the removed layer //////////
-
- const removedLines: Types.Lines = lines.current.filter(
- (line) => line[0][2] === removedLayer
- );
- const { userId, organization } = getUserData();
-
- //REST
-
- // await deleteLayer(organization, removedLayer);
-
- //SOCKET
-
- const data = {
- organization,
- layer: removedLayer,
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- socket.emit("v1:Line:delete:layer", data);
-
- ////////// Remove Points and lines from the removed layer //////////
-
- removedLines.forEach((line) => {
- line.forEach((removedPoint) => {
- RemoveConnectedLines(
- removedPoint[1],
- floorPlanGroupLine,
- floorPlanGroupPoint,
- setDeletedLines,
- lines
- );
- });
- });
-
- ////////// Update the remaining lines layer values in the userData and in lines.current //////////
-
- let remaining = lines.current.filter((line) => line[0][2] !== removedLayer);
- let updatedLines: Types.Lines = [];
- remaining.forEach((line) => {
- let newLines: Types.Line = [...line];
- if (newLines[0][2] > removedLayer) {
- newLines[0][2] -= 1;
- newLines[1][2] -= 1;
- }
-
- const matchingLine = floorPlanGroupLine.current.children.find(
- (l) =>
- l.userData.linePoints[0][1] === line[0][1] &&
- l.userData.linePoints[1][1] === line[1][1]
- );
- if (matchingLine) {
- const updatedUserData = matchingLine.userData;
- updatedUserData.linePoints[0][2] = newLines[0][2];
- updatedUserData.linePoints[1][2] = newLines[1][2];
- }
- updatedLines.push(newLines);
- });
-
- lines.current = updatedLines;
- localStorage.setItem("Lines", JSON.stringify(lines.current));
-
- ////////// Also remove OnlyFloorLines and update it in localstorage //////////
-
- onlyFloorlines.current = onlyFloorlines.current.filter((floor) => {
- return floor[0][0][2] !== removedLayer;
- });
- const meshToRemove: any = floorGroup.current?.children.find(
- (mesh) => mesh.name === `Only_Floor_Line_${removedLayer}`
- );
- if (meshToRemove) {
- (meshToRemove.material).dispose();
- (meshToRemove.geometry).dispose();
- floorGroup.current?.remove(meshToRemove);
- }
-
- echo.success("Layer Removed!");
- setRemovedLayer(null);
-}
-export default DeleteLayer;
diff --git a/app/src/modules/builder/geomentries/layers/layer2DVisibility.ts b/app/src/modules/builder/geomentries/layers/layer2DVisibility.ts
deleted file mode 100644
index f1828de..0000000
--- a/app/src/modules/builder/geomentries/layers/layer2DVisibility.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import * as Types from "../../../../types/world/worldTypes";
-
-function Layer2DVisibility(
- activeLayer: Types.Number,
- floorPlanGroup: Types.RefGroup,
- floorPlanGroupLine: Types.RefGroup,
- floorPlanGroupPoint: Types.RefGroup,
- currentLayerPoint: Types.RefMeshArray,
- dragPointControls: Types.RefDragControl
-): void {
-
- if (floorPlanGroup.current && dragPointControls.current) {
- currentLayerPoint.current = [];
- floorPlanGroupLine.current.children.forEach((line) => {
- const linePoints = line.userData.linePoints;
-
- const point1 = floorPlanGroupPoint.current.getObjectByProperty('uuid', linePoints[0][1]) as Types.Mesh;
- const point2 = floorPlanGroupPoint.current.getObjectByProperty('uuid', linePoints[1][1]) as Types.Mesh;
-
- if (linePoints[0][2] !== activeLayer && linePoints[1][2] !== activeLayer) {
- point1.visible = false;
- point2.visible = false;
- line.visible = false;
- } else {
- point1.visible = true;
- point2.visible = true;
- line.visible = true;
- currentLayerPoint.current.push(point1, point2);
- }
- });
- dragPointControls.current!.objects = currentLayerPoint.current;
- }
-}
-
-export default Layer2DVisibility;
diff --git a/app/src/modules/builder/geomentries/lines/addLineToScene.ts b/app/src/modules/builder/geomentries/lines/addLineToScene.ts
deleted file mode 100644
index 9e30e1d..0000000
--- a/app/src/modules/builder/geomentries/lines/addLineToScene.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as THREE from "three";
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-import * as Types from "../../../../types/world/worldTypes";
-
-function addLineToScene(
- start: Types.Vector3,
- end: Types.Vector3,
- colour: Types.Color,
- userData: Types.UserData,
- floorPlanGroupLine: Types.RefGroup
-): void {
-
- ////////// A function that creates and adds lines based on the start, end, and colour from the params, Also adds the userData in the mesh userData //////////
-
- const path = new THREE.CatmullRomCurve3([start, end]);
- const geometry = new THREE.TubeGeometry(path, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false);
- const material = new THREE.MeshBasicMaterial({ color: colour });
- const mesh = new THREE.Mesh(geometry, material);
- floorPlanGroupLine.current.add(mesh);
-
- mesh.userData.linePoints = userData;
-}
-
-export default addLineToScene;
diff --git a/app/src/modules/builder/geomentries/lines/createAndMoveReferenceLine.ts b/app/src/modules/builder/geomentries/lines/createAndMoveReferenceLine.ts
deleted file mode 100644
index e5b6fbe..0000000
--- a/app/src/modules/builder/geomentries/lines/createAndMoveReferenceLine.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-import * as THREE from "three";
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-import * as Types from "../../../../types/world/worldTypes";
-
-function createAndMoveReferenceLine(
- point: Types.Vector3,
- cursorPosition: Types.Vector3,
- isSnapped: Types.RefBoolean,
- ispreSnapped: Types.RefBoolean,
- line: Types.RefLine,
- setRefTextUpdate: Types.NumberIncrementState,
- floorPlanGroup: Types.RefGroup,
- ReferenceLineMesh: Types.RefMesh,
- LineCreated: Types.RefBoolean,
- Tube: Types.RefTubeGeometry,
- anglesnappedPoint: Types.RefVector3,
- isAngleSnapped: Types.RefBoolean
-): void {
-
- ////////// Creating new and maintaining the old reference line and also snap the reference line based on its angle //////////
-
- const startPoint = point;
-
- const dx = cursorPosition.x - startPoint.x;
- const dz = cursorPosition.z - startPoint.z;
- let angle = Math.atan2(dz, dx);
-
- angle = (angle * 180) / Math.PI;
- angle = (angle + 360) % 360;
-
- const snapAngles = [0, 90, 180, 270, 360];
- const snapThreshold = 2.5;
-
- const closestSnapAngle = snapAngles.reduce((prev, curr) =>
- Math.abs(curr - angle) < Math.abs(prev - angle) ? curr : prev
- );
-
- if (!isSnapped.current && !ispreSnapped.current && line.current.length > 0) {
- if (Math.abs(closestSnapAngle - angle) <= snapThreshold) {
- const snappedAngleRad = (closestSnapAngle * Math.PI) / 180;
- const distance = Math.sqrt(dx * dx + dz * dz);
- const snappedX = startPoint.x + distance * Math.cos(snappedAngleRad);
- const snappedZ = startPoint.z + distance * Math.sin(snappedAngleRad);
-
- if (
- cursorPosition.distanceTo(
- new THREE.Vector3(snappedX, 0.01, snappedZ)
- ) < 2
- ) {
- cursorPosition.set(snappedX, 0.01, snappedZ);
- isAngleSnapped.current = true;
- anglesnappedPoint.current = new THREE.Vector3(
- snappedX,
- 0.01,
- snappedZ
- );
- } else {
- isAngleSnapped.current = false;
- anglesnappedPoint.current = null;
- }
- } else {
- isAngleSnapped.current = false;
- anglesnappedPoint.current = null;
- }
- } else {
- isAngleSnapped.current = false;
- anglesnappedPoint.current = null;
- }
-
- if (!LineCreated.current) {
- setRefTextUpdate((prevUpdate) => prevUpdate - 1);
- const path = new THREE.LineCurve3(startPoint, cursorPosition);
- Tube.current = new THREE.TubeGeometry(path, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false);
- const material = new THREE.MeshBasicMaterial({ color: CONSTANTS.lineConfig.helperColor });
- ReferenceLineMesh.current = new THREE.Mesh(Tube.current, material);
- ReferenceLineMesh.current.name = CONSTANTS.lineConfig.referenceName;
- ReferenceLineMesh.current.userData = {
- linePoints: { startPoint, cursorPosition },
- };
- floorPlanGroup.current?.add(ReferenceLineMesh.current);
- LineCreated.current = true;
- } else {
- if (ReferenceLineMesh.current) {
- const path = new THREE.LineCurve3(startPoint, new THREE.Vector3(cursorPosition.x, 0.01, cursorPosition.z));
- Tube.current = new THREE.TubeGeometry(path, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false);
-
- if (ReferenceLineMesh.current) {
- ReferenceLineMesh.current.userData = {
- linePoints: { startPoint, cursorPosition },
- };
- ReferenceLineMesh.current.geometry.dispose();
- ReferenceLineMesh.current.geometry = Tube.current;
- }
- }
- }
-}
-
-export default createAndMoveReferenceLine;
diff --git a/app/src/modules/builder/geomentries/lines/deleteLine.ts b/app/src/modules/builder/geomentries/lines/deleteLine.ts
deleted file mode 100644
index 4b5158f..0000000
--- a/app/src/modules/builder/geomentries/lines/deleteLine.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-import { Socket } from "socket.io-client";
-// import { deleteLineApi } from "../../../../services/factoryBuilder/lines/deleteLineApi";
-import * as Types from "../../../../types/world/worldTypes";
-
-import { toast } from "react-toastify";
-import { getUserData } from "../../../../functions/getUserData";
-
-function deleteLine(
- hoveredDeletableLine: Types.RefMesh,
- onlyFloorlines: Types.RefOnlyFloorLines,
- lines: Types.RefLines,
- floorPlanGroupLine: Types.RefGroup,
- floorPlanGroupPoint: Types.RefGroup,
- setDeletedLines: any,
- socket: Socket,
- projectId?: string,
- versionId?: string,
-): void {
- const { userId, organization, email } = getUserData();
- ////////// Deleting a line and the points if they are not connected to any other line //////////
-
- if (!hoveredDeletableLine.current) {
- return;
- }
-
- const linePoints = hoveredDeletableLine.current.userData.linePoints;
- const connectedpoints = [linePoints[0][1], linePoints[1][1]];
-
- //REST
-
- // deleteLineApi(
- // organization,
- // [
- // { "uuid": linePoints[0][1] },
- // { "uuid": linePoints[1][1] }
- // ]
- // )
-
- //SOCKET
-
- const data = {
- organization,
- line: [{ uuid: linePoints[0][1] }, { uuid: linePoints[1][1] }],
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- socket.emit("v1:Line:delete", data);
-
- onlyFloorlines.current = onlyFloorlines.current
- .map((floorline) =>
- floorline.filter(
- (line) =>
- line[0][1] !== connectedpoints[0] && line[1][1] !== connectedpoints[1]
- )
- )
- .filter((floorline) => floorline.length > 0);
-
- lines.current = lines.current.filter((item) => item !== linePoints);
- (hoveredDeletableLine.current.material).dispose();
- (hoveredDeletableLine.current.geometry).dispose();
- floorPlanGroupLine.current.remove(hoveredDeletableLine.current);
- setDeletedLines([linePoints]);
-
- connectedpoints.forEach((pointUUID) => {
- let isConnected = false;
- floorPlanGroupLine.current.children.forEach((line) => {
- const linePoints = line.userData.linePoints;
- const uuid1 = linePoints[0][1];
- const uuid2 = linePoints[1][1];
- if (uuid1 === pointUUID || uuid2 === pointUUID) {
- isConnected = true;
- }
- });
-
- if (!isConnected) {
- floorPlanGroupPoint.current.children.forEach((point: any) => {
- if (point.uuid === pointUUID) {
- (point.material).dispose();
- (point.geometry).dispose();
- floorPlanGroupPoint.current.remove(point);
- }
- });
- }
- });
-
- echo.success("Line Removed!");
-}
-
-export default deleteLine;
diff --git a/app/src/modules/builder/geomentries/lines/distanceText/distanceText.tsx b/app/src/modules/builder/geomentries/lines/distanceText/distanceText.tsx
deleted file mode 100644
index cdb586e..0000000
--- a/app/src/modules/builder/geomentries/lines/distanceText/distanceText.tsx
+++ /dev/null
@@ -1,226 +0,0 @@
-import { useEffect, useState } from "react";
-import { getLines } from "../../../../../services/factoryBuilder/lines/getLinesApi";
-import * as THREE from "three";
-import {
- useActiveLayer,
- useDeletedLines,
- useNewLines,
- useRoomsState,
- useToggleView,
-} from "../../../../../store/builder/store";
-import objectLinesToArray from "../lineConvertions/objectLinesToArray";
-import { Html } from "@react-three/drei";
-import { Vector2 } from "three";
-import * as Types from "../../../../../types/world/worldTypes";
-import getRoomsFromLines from "../getRoomsFromLines";
-import * as turf from '@turf/turf';
-import { useParams } from "react-router-dom";
-import { getUserData } from "../../../../../functions/getUserData";
-import { useVersionContext } from "../../../version/versionContext";
-
-const DistanceText = () => {
- const [lines, setLines] = useState<
- {
- distance: string;
- position: THREE.Vector3;
- userData: Types.Line;
- layer: string;
- }[]
- >([]);
- const { activeLayer } = useActiveLayer();
- const { toggleView } = useToggleView();
- const { newLines, setNewLines } = useNewLines();
- const { deletedLines, setDeletedLines } = useDeletedLines();
- const [linesState, setLinesState] = useState([]);
- const { roomsState, setRoomsState } = useRoomsState();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { projectId } = useParams();
- const { organization, email } = getUserData();
-
- useEffect(() => {
-
- if (linesState.length === 0) return;
- const getLines = async () => {
- const points3D = linesState.map(line => {
- const startPoint = line[0][0]; // First point of each wall line
- return [startPoint.x, 0, startPoint.z];
- });
-
- // Ensure the polygon is closed
- if (
- points3D[0][0] !== points3D[points3D.length - 1][0] ||
- points3D[0][1] !== points3D[points3D.length - 1][1]
- ) {
- points3D.push(points3D[0]);
- }
-
- // Convert to 2D for turf (x, z)
- const coords2D = points3D.map(p => [p[0], p[1]]);
-
- const projected = points3D.map((p: any) => new Vector2(p[0], p[1]));
-
- // Shoelace formula for 2D polygon
- let area = 0;
- const n = projected.length;
- for (let i = 0; i < n - 1; i++) {
- const curr = projected[i];
- const next = projected[i + 1];
- area += curr.x * next.y - next.x * curr.y;
-
- }
-
- // return Math.abs(area) / 2;
-
- // Build polygon and compute area
- // const polygon = turf.polygon([coords2D]);
- // const area = turf.area(polygon);
- // const area = computeAreaFrom3DPoints(coords2D)
-
- //
- if (lines.length > 2) {
- const linesByLayer = linesState.reduce((acc: { [key: number]: any[] }, pair) => {
- const layer = pair[0][2];
- if (!acc[layer]) acc[layer] = [];
- acc[layer].push(pair);
- return acc;
- }, {});
-
-
- for (const layer in linesByLayer) {
- const rooms: Types.Rooms = await getRoomsFromLines({ current: linesByLayer[layer] });
- setRoomsState(rooms)
- }
- }
- }
- getLines();
- }, [linesState, roomsState])
-
-
- useEffect(() => {
- if (!email || !selectedVersion) return;
-
- getLines(organization, projectId, selectedVersion?.versionId || '').then((data) => {
- data = objectLinesToArray(data);
- setLinesState(data);
-
- const lines = data
- .filter((line: Types.Line) => line[0][2] === activeLayer)
- .map((line: Types.Line) => {
- const point1 = new THREE.Vector3(
- line[0][0].x,
- line[0][0].y,
- line[0][0].z
- );
- const point2 = new THREE.Vector3(
- line[1][0].x,
- line[1][0].y,
- line[1][0].z
- );
- const distance = point1.distanceTo(point2);
- const midpoint = new THREE.Vector3()
- .addVectors(point1, point2)
- .divideScalar(2);
- return {
- distance: distance.toFixed(1),
- position: midpoint,
- userData: line,
- layer: activeLayer,
- };
- });
- setLines(lines);
- });
- }, [activeLayer, selectedVersion?.versionId]);
-
- useEffect(() => {
- if (newLines.length > 0) {
- if (newLines[0][0][2] !== activeLayer) return;
- const newLinesData = newLines.map((line: Types.Line) => {
- const point1 = new THREE.Vector3(
- line[0][0].x,
- line[0][0].y,
- line[0][0].z
- );
- const point2 = new THREE.Vector3(
- line[1][0].x,
- line[1][0].y,
- line[1][0].z
- );
- const distance = point1.distanceTo(point2);
- const midpoint = new THREE.Vector3()
- .addVectors(point1, point2)
- .divideScalar(2);
-
- return {
- distance: distance.toFixed(1),
- position: midpoint,
- userData: line,
- layer: activeLayer,
- };
- });
- setLines((prevLines) => [...prevLines, ...newLinesData]);
- setLinesState((prevLines) => [...prevLines, ...newLines]);
- setNewLines([]);
- }
- }, [newLines, activeLayer]);
-
- useEffect(() => {
- if ((deletedLines as Types.Lines).length > 0) {
- setLines((prevLines) =>
- prevLines.filter(
- (line) =>
- !deletedLines.some(
- (deletedLine: any) =>
- deletedLine[0][1] === line.userData[0][1] &&
- deletedLine[1][1] === line.userData[1][1]
- )
- )
- );
-
- setLinesState(prev =>
- prev.filter(line =>
- !(deletedLines as Types.Lines).some(
- deleted =>
- line[0][1] === deleted[0][1] && line[1][1] === deleted[1][1]
- )
- )
- );
-
- setDeletedLines([]);
- setRoomsState([])
- }
- }, [deletedLines]);
-
- return (
- <>
- {toggleView && (
-
- {lines.map((text) => (
-
-
- {text.distance} m
-
-
- ))}
-
- )}
- >
- );
-};
-
-export default DistanceText;
diff --git a/app/src/modules/builder/geomentries/lines/distanceText/referenceDistanceText.tsx b/app/src/modules/builder/geomentries/lines/distanceText/referenceDistanceText.tsx
deleted file mode 100644
index ce9864d..0000000
--- a/app/src/modules/builder/geomentries/lines/distanceText/referenceDistanceText.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import * as THREE from "three";
-import { Html } from "@react-three/drei";
-import { useState, useEffect } from "react";
-import { useActiveLayer } from "../../../../../store/builder/store";
-
-const ReferenceDistanceText = ({ line }: { line: any }) => {
- interface TextState {
- distance: string;
- position: THREE.Vector3;
- userData: any;
- layer: any;
- }
-
- const [text, setTexts] = useState(null);
- const { activeLayer } = useActiveLayer();
-
- useEffect(() => {
- if (line) {
- if (line.parent === null) {
- setTexts(null);
- return;
- }
- const distance = line.userData.linePoints.cursorPosition.distanceTo(
- line.userData.linePoints.startPoint
- );
- const midpoint = new THREE.Vector3()
- .addVectors(
- line.userData.linePoints.cursorPosition,
- line.userData.linePoints.startPoint
- )
- .divideScalar(2);
- const newTexts = {
- distance: distance.toFixed(1),
- position: midpoint,
- userData: line,
- layer: activeLayer,
- };
- setTexts(newTexts);
- }
- });
-
- return (
-
-
- {text !== null && (
-
-
- {text.distance} m
-
-
- )}
-
-
- );
-};
-
-export default ReferenceDistanceText;
diff --git a/app/src/modules/builder/geomentries/lines/drawWall.ts b/app/src/modules/builder/geomentries/lines/drawWall.ts
deleted file mode 100644
index 7807610..0000000
--- a/app/src/modules/builder/geomentries/lines/drawWall.ts
+++ /dev/null
@@ -1,331 +0,0 @@
-import * as THREE from "three";
-import * as CONSTANTS from "../../../../types/world/worldConstants";
-
-import addPointToScene from "../points/addPointToScene";
-import addLineToScene from "./addLineToScene";
-import splitLine from "./splitLine";
-import removeReferenceLine from "./removeReferenceLine";
-import getClosestIntersection from "./getClosestIntersection";
-
-import * as Types from "../../../../types/world/worldTypes";
-import arrayLineToObject from "./lineConvertions/arrayLineToObject";
-// import { setLine } from '../../../../services/factoryBuilder/lines/setLineApi';
-import { Socket } from "socket.io-client";
-import { getUserData } from "../../../../functions/getUserData";
-import * as Y from 'yjs';
-import { generateUniqueId } from "../../../../functions/generateUniqueId";
-
-async function drawWall(
- raycaster: THREE.Raycaster,
- plane: Types.RefMesh,
- floorPlanGroupPoint: Types.RefGroup,
- snappedPoint: Types.RefVector3,
- isSnapped: Types.RefBoolean,
- isSnappedUUID: Types.RefString,
- line: Types.RefLine,
- ispreSnapped: Types.RefBoolean,
- anglesnappedPoint: Types.RefVector3,
- isAngleSnapped: Types.RefBoolean,
- lines: Types.RefLines,
- floorPlanGroupLine: Types.RefGroup,
- floorPlanGroup: Types.RefGroup,
- ReferenceLineMesh: Types.RefMesh,
- LineCreated: Types.RefBoolean,
- currentLayerPoint: Types.RefMeshArray,
- dragPointControls: Types.RefDragControl,
- setNewLines: any,
- setDeletedLines: any,
- activeLayer: Types.Number,
- socket: Socket,
- projectId?: string,
- versionId?: string,
- ydoc?: any
-): Promise {
- const { userId, organization } = getUserData();
- ////////// Creating lines Based on the positions clicked //////////
-
- ////////// Allows the user lines that represents walls and roof, floor if forms a polygon //////////
-
- if (!plane.current) return;
- let intersects = raycaster.intersectObject(plane.current, true);
-
- let intersectsLines = raycaster.intersectObjects(floorPlanGroupLine.current.children, true);
- let intersectsPoint = raycaster.intersectObjects(floorPlanGroupPoint.current.children, true);
-
- const VisibleintersectsPoint = intersectsPoint.find((intersect) => intersect.object.visible);
- const visibleIntersect = intersectsLines.find(
- (intersect) =>
- intersect.object.visible &&
- intersect.object.name !== CONSTANTS.lineConfig.referenceName &&
- intersect.object.userData.linePoints[0][3] ===
- CONSTANTS.lineConfig.wallName
- );
-
- if ((intersectsPoint.length === 0 || VisibleintersectsPoint === undefined) && intersectsLines.length > 0 && !isSnapped.current && !ispreSnapped.current) {
- ////////// Clicked on a preexisting Line //////////
-
- if (visibleIntersect && intersects) {
- let IntersectsPoint = new THREE.Vector3(intersects[0].point.x, 0.01, intersects[0].point.z);
-
- if (isAngleSnapped.current && anglesnappedPoint.current) {
- IntersectsPoint = anglesnappedPoint.current;
- }
- if (visibleIntersect.object instanceof THREE.Mesh) {
- const ThroughPoint = visibleIntersect.object.geometry.parameters.path.getPoints(CONSTANTS.lineConfig.lineIntersectionPoints);
- let intersectionPoint = getClosestIntersection(ThroughPoint, IntersectsPoint);
-
- if (intersectionPoint) {
- const newLines = splitLine(
- visibleIntersect,
- intersectionPoint,
- currentLayerPoint,
- floorPlanGroupPoint,
- dragPointControls,
- isSnappedUUID,
- lines,
- setDeletedLines,
- floorPlanGroupLine,
- socket,
- CONSTANTS.pointConfig.wallOuterColor,
- CONSTANTS.lineConfig.wallColor,
- CONSTANTS.lineConfig.wallName,
- projectId,
- versionId
- );
- setNewLines([newLines[0], newLines[1]]);
-
- (line.current as Types.Line).push([
- new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z),
- isSnappedUUID.current!,
- activeLayer,
- CONSTANTS.lineConfig.wallName,
- ]);
-
- if (line.current.length >= 2 && line.current[0] && line.current[1]) {
- const data = arrayLineToObject(line.current as Types.Line);
-
- //REST
-
- // setLine(organization, data.layer!, data.line!, data.type!);
-
- //SOCKET
-
- const input = {
- organization,
- layer: data.layer,
- line: data.line,
- type: data.type,
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- console.log('input: ', input);
- socket.emit("v1:Line-collab:create", input);
-
- // ✅ Add to Yjs map (will auto-sync to other clients)
- const yLine = new Y.Map();
- yLine.set("organization", organization);
- yLine.set("layer", data.layer);
- yLine.set("type", data.type);
- yLine.set("line", data.line)
- yLine.set("socketId", socket.id)
- yLine.set("projectId", projectId);
- yLine.set("versionId", versionId);
- yLine.set("userId", userId);
-
- const yLineArray = new Y.Array();
- if (!data.line) return
- for (const point of data.line) {
- const yPoint = new Y.Map();
- yPoint.set("uuid", point.uuid);
- if (point.position) {
- yPoint.set("position", new Y.Map([
- ["x", point.position.x],
- ["y", point.position.y],
- ["z", point.position.z],
- ]));
- }
- yLineArray.push([yPoint]);
- }
- yLine.set("line", yLineArray);
-
- const lineMap = ydoc.getMap("lines");
- lineMap.observe((event: any) => {
- console.log('event: ', event);
- console.log("Map changed!", event.changes.keys);
- });
-
- const lineId = crypto.randomUUID(); // Or use backend _id if available
- lineMap.set(lineId, yLine); // 👈 triggers Yjs update event
-
-
-
- setNewLines([newLines[0], newLines[1], line.current]);
- lines.current.push(line.current as Types.Line);
- addLineToScene(
- line.current[0][0],
- line.current[1][0],
- CONSTANTS.lineConfig.wallColor,
- line.current,
- floorPlanGroupLine
- );
- let lastPoint = line.current[line.current.length - 1];
- line.current = [lastPoint];
- }
-
-
- return;
- }
- }
- }
- }
-
- if (intersects && intersects.length > 0) {
- ////////// Clicked on a emply place or a point //////////
-
- let intersectionPoint = intersects[0].point;
-
- if (isAngleSnapped.current && line.current.length > 0 && anglesnappedPoint.current) {
- intersectionPoint = anglesnappedPoint.current;
- }
- if (isSnapped.current && line.current.length > 0 && snappedPoint.current) {
- intersectionPoint = snappedPoint.current;
- }
- if (ispreSnapped.current && snappedPoint.current) {
- intersectionPoint = snappedPoint.current;
- }
-
- if (!isSnapped.current && !ispreSnapped.current) {
- addPointToScene(
- intersectionPoint,
- CONSTANTS.pointConfig.wallOuterColor,
- currentLayerPoint,
- floorPlanGroupPoint,
- dragPointControls,
- isSnappedUUID,
- CONSTANTS.lineConfig.wallName
- );
- } else {
- ispreSnapped.current = false;
- isSnapped.current = false;
- }
-
- (line.current as Types.Line).push([
- new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z),
- isSnappedUUID.current!,
- activeLayer,
- CONSTANTS.lineConfig.wallName,
- ]);
-
- // if (line.current.length >= 2 && line.current[0] && line.current[1]) {
- // const data = arrayLineToObject(line.current as Types.Line);
-
- // //REST
-
- // // setLine(organization, data.layer!, data.line!, data.type!);
-
- // //SOCKET
-
- // const input = {
- // organization,
- // layer: data.layer,
- // line: data.line,
- // type: data.type,
- // socketId: socket.id,
- // versionId,
- // projectId,
- // userId,
- // };
-
- // console.log('input: ', input);
- // socket.emit("v1:Line-collab:create", input);
-
- // setNewLines([line.current]);
- // lines.current.push(line.current as Types.Line);
- // addLineToScene(
- // line.current[0][0],
- // line.current[1][0],
- // CONSTANTS.lineConfig.wallColor,
- // line.current,
- // floorPlanGroupLine
- // );
- // let lastPoint = line.current[line.current.length - 1];
- // line.current = [lastPoint];
- // }
- if (line.current.length >= 2 && line.current[0] && line.current[1]) {
- const data = arrayLineToObject(line.current as Types.Line);
-
- // ✅ Prepare input for socket.emit (your backend)
- const input = {
- organization,
- layer: data.layer,
- line: data.line,
- type: data.type,
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- // ✅ Emit to backend
- socket.emit("v1:Line-collab:create", input);
-
- // ✅ Add to Yjs map (will auto-sync to other clients)
- const yLine = new Y.Map();
- yLine.set("organization", organization);
- yLine.set("layer", data.layer);
- yLine.set("type", data.type);
- yLine.set("line", data.line)
- yLine.set("socketId", socket.id)
- yLine.set("projectId", projectId);
- yLine.set("versionId", versionId);
- yLine.set("userId", userId);
-
- const yLineArray = new Y.Array();
- if (!data.line) return
- for (const point of data.line) {
- const yPoint = new Y.Map();
- yPoint.set("uuid", point.uuid);
- if (point.position) {
- yPoint.set("position", new Y.Map([
- ["x", point.position.x],
- ["y", point.position.y],
- ["z", point.position.z],
- ]));
- }
- yLineArray.push([yPoint]);
- }
- yLine.set("line", yLineArray);
-
- const lineMap = ydoc.getMap("lines");
- lineMap.observe((event: any) => {
- console.log('event: ', event);
- console.log("Map changed!", event.changes.keys);
- });
-
- const lineId = generateUniqueId(); // Or use backend _id if available
- lineMap.set(lineId, yLine); // 👈 triggers Yjs update event
-
- // ✅ Scene + local updates
- setNewLines([line.current]);
- lines.current.push(line.current as Types.Line);
- addLineToScene(
- line.current[0][0],
- line.current[1][0],
- CONSTANTS.lineConfig.wallColor,
- line.current,
- floorPlanGroupLine
- );
-
- const lastPoint = line.current[line.current.length - 1];
- line.current = [lastPoint];
- }
- if (isSnapped.current) {
- removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
- }
- }
-}
-
-export default drawWall;
diff --git a/app/src/modules/builder/geomentries/lines/getRoomsFromLines.ts b/app/src/modules/builder/geomentries/lines/getRoomsFromLines.ts
deleted file mode 100644
index 08304ea..0000000
--- a/app/src/modules/builder/geomentries/lines/getRoomsFromLines.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-import * as THREE from 'three';
-import * as turf from '@turf/turf';
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-import * as Types from "../../../../types/world/worldTypes";
-
-async function getRoomsFromLines(lines: Types.RefLines) {
- const rooms: Types.Rooms = [];
-
- if (lines.current.length > 2) {
- const linesByLayer = lines.current.reduce((acc: { [key: number]: any[] }, pair) => {
- const layer = pair[0][2];
- if (!acc[layer]) acc[layer] = [];
- acc[layer].push(pair);
- return acc;
- }, {});
-
- ////////// Use turf.polygonize to create polygons from the line points //////////
-
- for (const layer in linesByLayer) {
-
- let linesInLayer = linesByLayer[layer];
- linesInLayer = linesInLayer.filter(line => line[0][3] && line[1][3] === CONSTANTS.lineConfig.wallName);
- const result = linesInLayer.map((pair: [THREE.Vector3, string, number, string][]) =>
- pair.map((point) => ({
- position: [point[0].x, point[0].z],
- uuid: point[1]
- }))
- );
- const lineFeatures = result.map(line => turf.lineString(line.map(p => p.position)));
- const polygons = turf.polygonize(turf.featureCollection(lineFeatures));
-
- let union: any[] = [];
-
- polygons.features.forEach((feature) => {
- union.push(feature);
- });
-
- if (union.length > 1) {
- const unionResult = turf.union(turf.featureCollection(union));
- if (unionResult?.geometry.type === "MultiPolygon") {
- unionResult?.geometry.coordinates.forEach((poly) => {
- const Coordinates = poly[0].map(([x, z]) => {
- const matchingPoint = result.flat().find(r =>
- r.position[0].toFixed(10) === x.toFixed(10) &&
- r.position[1].toFixed(10) === z.toFixed(10)
- );
- return {
- position: new THREE.Vector3(x, 0, z),
- uuid: matchingPoint ? matchingPoint.uuid : ''
- };
- });
- rooms.push({ coordinates: Coordinates.reverse(), layer: parseInt(layer) });
- });
- } else if (unionResult?.geometry.type === "Polygon") {
- const Coordinates = unionResult?.geometry.coordinates[0].map(([x, z]) => {
- const matchingPoint = result.flat().find(r =>
- r.position[0].toFixed(10) === x.toFixed(10) &&
- r.position[1].toFixed(10) === z.toFixed(10)
- );
- return {
- position: new THREE.Vector3(x, 0, z),
- uuid: matchingPoint ? matchingPoint.uuid : ''
- };
- });
- rooms.push({ coordinates: Coordinates.reverse(), layer: parseInt(layer) });
- }
- } else if (union.length === 1) {
- const Coordinates = union[0].geometry.coordinates[0].map(([x, z]: [number, number]) => {
- const matchingPoint = result.flat().find(r =>
- r.position[0].toFixed(10) === x.toFixed(10) &&
- r.position[1].toFixed(10) === z.toFixed(10)
- );
- return {
- position: new THREE.Vector3(x, 0, z),
- uuid: matchingPoint ? matchingPoint.uuid : ''
- };
- });
- rooms.push({ coordinates: Coordinates, layer: parseInt(layer) });
- }
- }
- }
-
- return rooms;
-}
-
-export default getRoomsFromLines;
diff --git a/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLineToObject.ts b/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLineToObject.ts
deleted file mode 100644
index dffac05..0000000
--- a/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLineToObject.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as Types from "../../../../../types/world/worldTypes";
-
-export default function arrayLineToObject(array: Types.Line) {
- if (!Array.isArray(array)) {
- return {};
- }
-
- // Extract common properties from the first point
- const commonLayer = array[0][2];
- const commonType = array[0][3];
-
- // Map points into a structured format
- const line = array.map(([position, uuid]) => ({
- position,
- uuid,
- }));
-
- // Create the final structured object
- return {
- layer: commonLayer,
- type: commonType,
- line,
- };
-}
\ No newline at end of file
diff --git a/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLinesToObject.ts b/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLinesToObject.ts
deleted file mode 100644
index 041b17c..0000000
--- a/app/src/modules/builder/geomentries/lines/lineConvertions/arrayLinesToObject.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import * as Types from "../../../../../types/world/worldTypes";
-
-export default function arrayLinesToObject(array: Array) {
- if (!Array.isArray(array)) {
- return [];
- }
-
- return array.map((lineArray) => {
- if (!Array.isArray(lineArray)) {
- return null;
- }
-
- // Extract common properties from the first point
- const commonLayer = lineArray[0][2];
- const commonType = lineArray[0][3];
-
- // Map points into a structured format
- const line = lineArray.map(([position, uuid]) => ({
- position,
- uuid,
- }));
-
- // Create the final structured object
- return {
- layer: commonLayer,
- type: commonType,
- line,
- };
- }).filter((item) => item !== null); // Filter out invalid entries
-}
diff --git a/app/src/modules/builder/geomentries/lines/lineConvertions/objectLineToArray.ts b/app/src/modules/builder/geomentries/lines/lineConvertions/objectLineToArray.ts
deleted file mode 100644
index ac0162c..0000000
--- a/app/src/modules/builder/geomentries/lines/lineConvertions/objectLineToArray.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import * as THREE from 'three';
-
-export default function objectLineToArray(structuredObject: any) {
- if (!structuredObject || !structuredObject.line) {
- return [];
- }
-
- // Destructure common properties
- const { layer, type, line } = structuredObject;
-
- // Map points back to the original array format
- return line.map(({ position, uuid }: any) => [new THREE.Vector3(position.x, position.y, position.z), uuid, layer, type]);
-}
\ No newline at end of file
diff --git a/app/src/modules/builder/geomentries/lines/lineConvertions/objectLinesToArray.ts b/app/src/modules/builder/geomentries/lines/lineConvertions/objectLinesToArray.ts
deleted file mode 100644
index 856b935..0000000
--- a/app/src/modules/builder/geomentries/lines/lineConvertions/objectLinesToArray.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import * as THREE from 'three';
-
-export default function objectLinesToArray(structuredObjects: any): any {
- if (!Array.isArray(structuredObjects)) {
- return [];
- }
-
- return structuredObjects.map((structuredObject) => {
- if (!structuredObject || !structuredObject.line) {
- return [];
- }
-
- const { layer, type, line } = structuredObject;
-
- return line.map(({ position, uuid }: any) => {
- const vector = new THREE.Vector3(position.x, position.y, position.z);
- return [vector, uuid, layer, type];
- });
- });
-}
diff --git a/app/src/modules/builder/geomentries/lines/removeConnectedLines.ts b/app/src/modules/builder/geomentries/lines/removeConnectedLines.ts
deleted file mode 100644
index ddf6452..0000000
--- a/app/src/modules/builder/geomentries/lines/removeConnectedLines.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import * as THREE from 'three';
-
-import * as Types from "../../../../types/world/worldTypes";
-
-function RemoveConnectedLines(
- DeletedPointUUID: Types.String,
- floorPlanGroupLine: Types.RefGroup,
- floorPlanGroupPoint: Types.RefGroup,
- setDeletedLines: any,
- lines: Types.RefLines,
-): void {
-
- ////////// Check if any and how many lines are connected to the deleted point //////////
-
- const removableLines: THREE.Mesh[] = [];
- const connectedpoints: string[] = [];
-
- const removedLinePoints: [number, string, number][][] = []; // Array to hold linePoints of removed lines
-
- floorPlanGroupLine.current.children.forEach((line) => {
- const linePoints = line.userData.linePoints as [number, string, number][];
- const uuid1 = linePoints[0][1];
- const uuid2 = linePoints[1][1];
-
- if (uuid1 === DeletedPointUUID || uuid2 === DeletedPointUUID) {
- connectedpoints.push(uuid1 === DeletedPointUUID ? uuid2 : uuid1);
- removableLines.push(line as THREE.Mesh);
- removedLinePoints.push(linePoints);
- }
- });
-
- if (removableLines.length > 0) {
- removableLines.forEach((line) => {
- lines.current = lines.current.filter(item => item !== line.userData.linePoints);
- (line.material).dispose();
- (line.geometry).dispose();
- floorPlanGroupLine.current.remove(line);
- });
- }
- setDeletedLines(removedLinePoints)
-
- ////////// Check and Remove point that are no longer connected to any lines //////////
-
- connectedpoints.forEach((pointUUID) => {
- let isConnected = false;
- floorPlanGroupLine.current.children.forEach((line) => {
- const linePoints = line.userData.linePoints as [number, string, number][];
- const uuid1 = linePoints[0][1];
- const uuid2 = linePoints[1][1];
- if (uuid1 === pointUUID || uuid2 === pointUUID) {
- isConnected = true;
- }
- });
- if (!isConnected) {
- floorPlanGroupPoint.current.children.forEach((point: any) => {
- if (point.uuid === pointUUID) {
- (point.material).dispose();
- (point.geometry).dispose();
- floorPlanGroupPoint.current.remove(point);
- }
- });
- }
- });
-}
-
-export default RemoveConnectedLines;
diff --git a/app/src/modules/builder/geomentries/lines/removeReferenceLine.ts b/app/src/modules/builder/geomentries/lines/removeReferenceLine.ts
deleted file mode 100644
index 787389a..0000000
--- a/app/src/modules/builder/geomentries/lines/removeReferenceLine.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import * as Types from "../../../../types/world/worldTypes";
-
-function removeReferenceLine(
- floorPlanGroup: Types.RefGroup,
- ReferenceLineMesh: Types.RefMesh,
- LineCreated: Types.RefBoolean,
- line: Types.RefLine
-): void {
-
- ////////// Removes Dangling reference line if the draw mode is ended or any other case //////////
-
- line.current = [];
- if (ReferenceLineMesh.current) {
- (ReferenceLineMesh.current.material).dispose();
- (ReferenceLineMesh.current.geometry).dispose();
- floorPlanGroup.current.remove(ReferenceLineMesh.current);
- LineCreated.current = false;
- ReferenceLineMesh.current = undefined;
- }
-}
-
-export default removeReferenceLine;
\ No newline at end of file
diff --git a/app/src/modules/builder/geomentries/lines/splitLine.ts b/app/src/modules/builder/geomentries/lines/splitLine.ts
deleted file mode 100644
index 31c2646..0000000
--- a/app/src/modules/builder/geomentries/lines/splitLine.ts
+++ /dev/null
@@ -1,153 +0,0 @@
-import * as THREE from "three";
-
-import addLineToScene from "./addLineToScene";
-import addPointToScene from "../points/addPointToScene";
-
-import * as Types from "../../../../types/world/worldTypes";
-import arrayLineToObject from "../lines/lineConvertions/arrayLineToObject";
-import { Socket } from "socket.io-client";
-import { getUserData } from "../../../../functions/getUserData";
-// import { deleteLineApi } from '../../../../services/factoryBuilder/lines/deleteLineApi';
-// import { setLine } from '../../../../services/factoryBuilder/lines/setLineApi';
-
-function splitLine(
- visibleIntersect: Types.IntersectionEvent,
- intersectionPoint: Types.Vector3,
- currentLayerPoint: Types.RefMeshArray,
- floorPlanGroupPoint: Types.RefGroup,
- dragPointControls: Types.RefDragControl,
- isSnappedUUID: Types.RefString,
- lines: Types.RefLines,
- setDeletedLines: any,
- floorPlanGroupLine: { current: THREE.Group },
- socket: Socket,
- pointColor: Types.String,
- lineColor: Types.String,
- lineType: Types.String,
- projectId?: string,
- versionId?: string,
-): [Types.Line, Types.Line] {
- ////////// Removing the clicked line and splitting it with the clicked position adding a new point and two new lines //////////
-
- const { userId, organization, email } = getUserData();
- (visibleIntersect.object as any).material.dispose();
- (visibleIntersect.object as any).geometry.dispose();
- floorPlanGroupLine.current.remove(visibleIntersect.object);
- setDeletedLines([visibleIntersect.object.userData.linePoints]);
-
- //REST
-
- // deleteLineApi(
- // organization,
- // [
- // { "uuid": visibleIntersect.object.userData.linePoints[0][1] },
- // { "uuid": visibleIntersect.object.userData.linePoints[1][1] }
- // ]
- // )
-
- //SOCKET
-
- const data = {
- organization,
- line: [
- { uuid: visibleIntersect.object.userData.linePoints[0][1] },
- { uuid: visibleIntersect.object.userData.linePoints[1][1] },
- ],
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- socket.emit("v1:Line:delete", data);
-
- const point = addPointToScene(
- intersectionPoint,
- pointColor,
- currentLayerPoint,
- floorPlanGroupPoint,
- dragPointControls,
- isSnappedUUID,
- lineType
- );
-
- const oldLinePoints = visibleIntersect.object.userData.linePoints;
- lines.current = lines.current.filter((item) => item !== oldLinePoints);
-
- const clickedPoint: Types.Point = [
- new THREE.Vector3(intersectionPoint.x, 0.01, intersectionPoint.z),
- point.uuid,
- oldLinePoints[0][2],
- lineType,
- ];
-
- const start = oldLinePoints[0];
- const end = oldLinePoints[1];
-
- const newLine1: Types.Line = [start, clickedPoint];
- const newLine2: Types.Line = [clickedPoint, end];
-
- const line1 = arrayLineToObject(newLine1);
- const line2 = arrayLineToObject(newLine2);
-
- //REST
-
- // setLine(organization, line1.layer!, line1.line!, line1.type!);
-
- //SOCKET
-
- const input1 = {
- organization,
- layer: line1.layer,
- line: line1.line,
- type: line1.type,
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- console.log('input1: ', input1);
- socket.emit("v1:Line:create", input1);
-
- //REST
-
- // setLine(organization, line2.layer!, line2.line!, line2.type!);
-
- //SOCKET
-
- const input2 = {
- organization,
- layer: line2.layer,
- line: line2.line,
- type: line2.type,
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- console.log('input2: ', input2);
- socket.emit("v1:Line:create", input2);
-
- lines.current.push(newLine1, newLine2);
-
- addLineToScene(
- newLine1[0][0],
- newLine1[1][0],
- lineColor,
- newLine1,
- floorPlanGroupLine
- );
- addLineToScene(
- newLine2[0][0],
- newLine2[1][0],
- lineColor,
- newLine2,
- floorPlanGroupLine
- );
-
- return [newLine1, newLine2];
-}
-
-export default splitLine;
diff --git a/app/src/modules/builder/geomentries/lines/updateDistanceText.ts b/app/src/modules/builder/geomentries/lines/updateDistanceText.ts
deleted file mode 100644
index 8d7fbe2..0000000
--- a/app/src/modules/builder/geomentries/lines/updateDistanceText.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import * as THREE from 'three';
-
-import * as Types from "../../../../types/world/worldTypes";
-
-function updateDistanceText(
- scene: THREE.Scene,
- floorPlanGroupLine: Types.RefGroup,
- affectedLines: Types.NumberArray
-): void {
-
- ////////// Updating the Distance Texts of the lines that are affected during drag //////////
-
- const DistanceGroup = scene.getObjectByName('Distance_Text') as THREE.Group;
-
- affectedLines.forEach((lineIndex) => {
- const mesh = floorPlanGroupLine.current.children[lineIndex] as THREE.Mesh;
- const linePoints = mesh.userData.linePoints;
-
- if (linePoints) {
- const distance = linePoints[0][0].distanceTo(linePoints[1][0]).toFixed(1);
- const position = new THREE.Vector3().addVectors(linePoints[0][0], linePoints[1][0]).divideScalar(2);
-
- if (!DistanceGroup || !linePoints) {
- return
- }
-
- DistanceGroup.children.forEach((text) => {
- const textMesh = text as THREE.Mesh;
- if (textMesh.userData[0][1] === linePoints[0][1] && textMesh.userData[1][1] === linePoints[1][1]) {
- textMesh.position.set(position.x, 1, position.z);
- const className = `distance line-${textMesh.userData[0][1]}_${textMesh.userData[1][1]}_${linePoints[0][2]}`;
- const element = document.getElementsByClassName(className)[0] as HTMLElement;
- if (element) {
- element.innerHTML = `${distance} m`;
- }
- }
- });
- }
- });
-}
-
-export default updateDistanceText;
diff --git a/app/src/modules/builder/geomentries/lines/updateLines.ts b/app/src/modules/builder/geomentries/lines/updateLines.ts
deleted file mode 100644
index 0c4f22f..0000000
--- a/app/src/modules/builder/geomentries/lines/updateLines.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as THREE from 'three';
-import * as Types from "../../../../types/world/worldTypes";
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-
-function updateLines(
- floorPlanGroupLine: Types.RefGroup,
- affectedLines: Types.NumberArray
-): void {
-
- ////////// Updating the positions for the affected lines only based on the updated positions //////////
-
- affectedLines.forEach((lineIndex) => {
- const mesh = floorPlanGroupLine.current.children[lineIndex] as Types.Mesh;
- const linePoints = mesh.userData.linePoints as Types.Line;
- if (linePoints) {
- const newPositions = linePoints.map(([pos]) => pos);
- const newPath = new THREE.CatmullRomCurve3(newPositions);
- mesh.geometry.dispose();
- mesh.geometry = new THREE.TubeGeometry(newPath, CONSTANTS.lineConfig.tubularSegments, CONSTANTS.lineConfig.radius, CONSTANTS.lineConfig.radialSegments, false);
- }
- });
-}
-
-export default updateLines;
\ No newline at end of file
diff --git a/app/src/modules/builder/geomentries/lines/updateLinesPositions.ts b/app/src/modules/builder/geomentries/lines/updateLinesPositions.ts
deleted file mode 100644
index 6411a09..0000000
--- a/app/src/modules/builder/geomentries/lines/updateLinesPositions.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import * as Types from "../../../../types/world/worldTypes";
-
-function updateLinesPositions(
- DragedPoint: Types.Mesh | { uuid: string, position: Types.Vector3 },
- lines: Types.RefLines
-): Types.NumberArray {
-
- ////////// Updating the lines position based on the dragged point's position //////////
-
- const objectUUID = DragedPoint.uuid;
- const affectedLines: Types.NumberArray = [];
-
- lines.current.forEach((line, index) => {
- let lineUpdated = false;
- line.forEach((point) => {
- const [position, uuid] = point;
- if (uuid === objectUUID) {
- position.x = DragedPoint.position.x;
- position.y = 0.01;
- position.z = DragedPoint.position.z;
- lineUpdated = true;
- }
- });
- if (lineUpdated) {
- affectedLines.push(index);
- }
- });
-
- return affectedLines;
-}
-
-export default updateLinesPositions;
diff --git a/app/src/modules/builder/geomentries/lines/vectorizeLinesCurrent.ts b/app/src/modules/builder/geomentries/lines/vectorizeLinesCurrent.ts
deleted file mode 100644
index a404a07..0000000
--- a/app/src/modules/builder/geomentries/lines/vectorizeLinesCurrent.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import * as THREE from 'three';
-
-import * as Types from "../../../../types/world/worldTypes";
-
-function vectorizeLinesCurrent(
- lines: Types.Lines
-): Types.Lines {
-
- ////////// Storing a vector3 array in localstorage makes the prototype functions go puff. This function brings back the prototype functions by creating it again //////////
-
- return lines.map((line) => {
- const p1: Types.Point = [new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z), line[0][1], line[0][2], line[0][3],];
- const p2: Types.Point = [new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z), line[1][1], line[0][2], line[1][3],];
- return [p1, p2];
- });
-}
-
-export default vectorizeLinesCurrent;
diff --git a/app/src/modules/builder/geomentries/pillars/addAndUpdateReferencePillar.ts b/app/src/modules/builder/geomentries/pillars/addAndUpdateReferencePillar.ts
deleted file mode 100644
index 04cad47..0000000
--- a/app/src/modules/builder/geomentries/pillars/addAndUpdateReferencePillar.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import * as THREE from 'three';
-import updateReferencePolesheight from './updateReferencePolesheight';
-
-import * as Types from "../../../../types/world/worldTypes";
-
-function addAndUpdateReferencePillar(
- raycaster: THREE.Raycaster,
- floorGroup: Types.RefGroup,
- referencePole: Types.RefMesh
-): void {
-
- ////////// Find Pillars position and scale based on the pointer interaction //////////
-
- let Roofs = raycaster.intersectObjects(floorGroup.current.children, true);
- const intersected = Roofs.find(intersect => intersect.object.name.includes("Roof") || intersect.object.name.includes("Floor"));
-
- if (intersected) {
- const intersectionPoint = intersected.point;
- raycaster.ray.origin.copy(intersectionPoint);
- raycaster.ray.direction.set(0, -1, 0);
- const belowIntersections = raycaster.intersectObjects(floorGroup.current.children, true);
- const validIntersections = belowIntersections.filter(intersect => intersect.object.name.includes("Floor"));
-
- let distance: Types.Number;
-
- if (validIntersections.length > 1) {
- let valid = validIntersections.find(intersectedBelow => intersected.point.distanceTo(intersectedBelow.point) > 3);
- if (valid) {
- updateReferencePolesheight(intersectionPoint, valid.distance, referencePole, floorGroup);
- } else {
- const belowPoint = new THREE.Vector3(intersectionPoint.x, 0, intersectionPoint.z);
- distance = intersected.point.distanceTo(belowPoint);
- if (distance > 3) {
- updateReferencePolesheight(intersectionPoint, distance, referencePole, floorGroup);
- }
- }
- } else {
- const belowPoint = new THREE.Vector3(intersectionPoint.x, 0, intersectionPoint.z);
- distance = intersected.point.distanceTo(belowPoint);
- if (distance > 3) {
- updateReferencePolesheight(intersectionPoint, distance, referencePole, floorGroup);
- }
- }
- } else {
- if (referencePole.current) {
- (referencePole.current.material).dispose();
- (referencePole.current.geometry).dispose();
- floorGroup.current.remove(referencePole.current);
- referencePole.current = null;
- }
- }
-}
-
-export default addAndUpdateReferencePillar;
diff --git a/app/src/modules/builder/geomentries/pillars/addPillar.ts b/app/src/modules/builder/geomentries/pillars/addPillar.ts
deleted file mode 100644
index e6e4b86..0000000
--- a/app/src/modules/builder/geomentries/pillars/addPillar.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as THREE from 'three';
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-import * as Types from "../../../../types/world/worldTypes";
-
-function addPillar(
- referencePole: Types.RefMesh,
- floorGroup: Types.RefGroup
-): void {
-
- ////////// Add Pillars to the scene based on the reference. current poles position and scale //////////
-
- if (referencePole.current) {
- let pole: THREE.Mesh;
- const geometry = referencePole.current.userData.geometry.clone();
- const material = new THREE.MeshStandardMaterial({ color: CONSTANTS.columnConfig.defaultColor });
- pole = new THREE.Mesh(geometry, material);
- pole.rotateX(Math.PI / 2);
- pole.name = "Pole";
- pole.position.set(referencePole.current.userData.position.x, referencePole.current.userData.position.y, referencePole.current.userData.position.z);
- floorGroup.current.add(pole);
- }
-}
-
-export default addPillar;
\ No newline at end of file
diff --git a/app/src/modules/builder/geomentries/pillars/deletableHoveredPillar.ts b/app/src/modules/builder/geomentries/pillars/deletableHoveredPillar.ts
deleted file mode 100644
index 4fb65c0..0000000
--- a/app/src/modules/builder/geomentries/pillars/deletableHoveredPillar.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import * as THREE from 'three';
-
-import * as Types from "../../../../types/world/worldTypes";
-
-function DeletableHoveredPillar(
- state: Types.ThreeState,
- floorGroup: Types.RefGroup,
- hoveredDeletablePillar: Types.RefMesh
-): void {
-
- ////////// Altering the color of the hovered Pillar during the Deletion time //////////
-
- const intersects = state.raycaster.intersectObjects(floorGroup.current.children, true);
- const poleIntersect = intersects.find(intersect => intersect.object.name === "Pole");
-
- if (poleIntersect) {
- if (poleIntersect.object.name !== "Pole") {
- return;
- }
- if (hoveredDeletablePillar.current) {
- (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("black");
- hoveredDeletablePillar.current = undefined;
- }
- hoveredDeletablePillar.current = poleIntersect.object as THREE.Mesh; // Type assertion
- (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("red");
- } else {
- if (hoveredDeletablePillar.current) {
- (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("black");
- hoveredDeletablePillar.current = undefined;
- }
- }
-}
-
-export default DeletableHoveredPillar;
\ No newline at end of file
diff --git a/app/src/modules/builder/geomentries/pillars/deletePillar.ts b/app/src/modules/builder/geomentries/pillars/deletePillar.ts
deleted file mode 100644
index 39e0b28..0000000
--- a/app/src/modules/builder/geomentries/pillars/deletePillar.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { toast } from 'react-toastify';
-
-import * as Types from "../../../../types/world/worldTypes";
-
-function DeletePillar(
- hoveredDeletablePillar: Types.RefMesh,
- floorGroup: Types.RefGroup
-): void {
-
- ////////// Deleting the hovered Pillar from the itemsGroup //////////
-
- if (hoveredDeletablePillar.current) {
- (hoveredDeletablePillar.current.material).dispose();
- (hoveredDeletablePillar.current.geometry).dispose();
- floorGroup.current.remove(hoveredDeletablePillar.current);
- echo.success("Pillar Removed!");
- hoveredDeletablePillar.current = undefined;
- }
-}
-
-export default DeletePillar;
diff --git a/app/src/modules/builder/geomentries/pillars/updateReferencePolesheight.ts b/app/src/modules/builder/geomentries/pillars/updateReferencePolesheight.ts
deleted file mode 100644
index f538546..0000000
--- a/app/src/modules/builder/geomentries/pillars/updateReferencePolesheight.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import * as THREE from 'three';
-
-import * as Types from "../../../../types/world/worldTypes";
-
-function updateReferencePolesheight(
- intersectionPoint: Types.Vector3,
- distance: Types.Number,
- referencePole: Types.RefMesh,
- floorGroup: Types.RefGroup
-): void {
-
- ////////// Add a Reference Pillar and update its position and scale based on the pointer interaction //////////
-
- if (referencePole.current) {
- (referencePole.current.material).dispose();
- (referencePole.current.geometry).dispose();
- floorGroup.current.remove(referencePole.current);
- referencePole.current.geometry.dispose();
- }
-
- const shape = new THREE.Shape();
- shape.moveTo(0.5, 0);
- shape.absarc(0, 0, 0.5, 0, 2 * Math.PI, false);
-
- const extrudeSettings = {
- depth: distance,
- bevelEnabled: false,
- };
-
- const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
- const material = new THREE.MeshBasicMaterial({ color: "green", transparent: true, opacity: 0.5 });
- referencePole.current = new THREE.Mesh(geometry, material);
- referencePole.current.rotateX(Math.PI / 2);
- referencePole.current.position.set(intersectionPoint.x, intersectionPoint.y - 0.01, intersectionPoint.z);
- referencePole.current.userData = { geometry: geometry, distance: distance, position: { x: intersectionPoint.x, y: intersectionPoint.y - 0.01, z: intersectionPoint.z } };
-
- floorGroup.current.add(referencePole.current);
-}
-
-export default updateReferencePolesheight;
diff --git a/app/src/modules/builder/geomentries/points/addPointToScene.ts b/app/src/modules/builder/geomentries/points/addPointToScene.ts
deleted file mode 100644
index b182128..0000000
--- a/app/src/modules/builder/geomentries/points/addPointToScene.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import * as THREE from 'three';
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-import * as Types from "../../../../types/world/worldTypes";
-
-function addPointToScene(
- position: Types.Vector3,
- colour: Types.Color,
- currentLayerPoint: Types.RefMeshArray,
- floorPlanGroupPoint: Types.RefGroup,
- dragPointControls: Types.RefDragControl | undefined,
- uuid: Types.RefString | undefined,
- Type: Types.String
-): Types.Mesh {
-
- ////////// A function that creates and adds a cube (point) with an outline based on the position and colour given as params, It also updates the drag controls objects and sets the box uuid in uuid.current //////////
-
- const geometry = new THREE.BoxGeometry(...CONSTANTS.pointConfig.boxScale);
- const material = new THREE.ShaderMaterial({
- uniforms: {
- uOuterColor: { value: new THREE.Color(colour) }, // Blue color for the border
- uInnerColor: { value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor) }, // White color for the inner square
- },
- vertexShader: `
- varying vec2 vUv;
-
- void main() {
- vUv = uv;
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
- }
- `,
- fragmentShader: `
- varying vec2 vUv;
- uniform vec3 uOuterColor;
- uniform vec3 uInnerColor;
-
- void main() {
- // Define the size of the white square as a proportion of the face
- float borderThickness = 0.2; // Adjust this value for border thickness
- if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness &&
- vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
- gl_FragColor = vec4(uInnerColor, 1.0); // White inner square
- } else {
- gl_FragColor = vec4(uOuterColor, 1.0); // Blue border
- }
- }
- `,
- });
- const point = new THREE.Mesh(geometry, material);
- point.name = "point";
- point.userData = { type: Type, color: colour };
- point.position.set(position.x, 0.01, position.z);
-
- currentLayerPoint.current.push(point);
- floorPlanGroupPoint.current.add(point);
- if (uuid) {
- uuid.current = point.uuid;
- }
- if (dragPointControls) {
- dragPointControls.current!.objects = currentLayerPoint.current;
- }
-
- return point;
-}
-
-export default addPointToScene;
diff --git a/app/src/modules/builder/geomentries/points/deletePoint.ts b/app/src/modules/builder/geomentries/points/deletePoint.ts
deleted file mode 100644
index 9a58eb5..0000000
--- a/app/src/modules/builder/geomentries/points/deletePoint.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import * as Types from "../../../../types/world/worldTypes";
-
-import { toast } from "react-toastify";
-
-import RemoveConnectedLines from "../lines/removeConnectedLines";
-// import { deletePointApi } from "../../../../services/factoryBuilder/lines/deletePointApi";
-import { Socket } from "socket.io-client";
-import { getUserData } from "../../../../functions/getUserData";
-
-function deletePoint(
- hoveredDeletablePoint: Types.RefMesh,
- onlyFloorlines: Types.RefOnlyFloorLines,
- floorPlanGroupPoint: Types.RefGroup,
- floorPlanGroupLine: Types.RefGroup,
- lines: Types.RefLines,
- setDeletedLines: any,
- socket: Socket,
- projectId?: string,
- versionId?: string,
-): void {
- ////////// Deleting a Point and the lines that are connected to it //////////
-
- if (!hoveredDeletablePoint.current) {
- return;
- }
- const { userId, organization, email } = getUserData();
- (hoveredDeletablePoint.current.material).dispose();
- (hoveredDeletablePoint.current.geometry).dispose();
- floorPlanGroupPoint.current.remove(hoveredDeletablePoint.current);
- const DeletedPointUUID = hoveredDeletablePoint.current.uuid;
-
- //REST
-
- // deletePointApi(organization, DeletedPointUUID);
-
- //SOCKET
-
- const data = {
- organization,
- uuid: DeletedPointUUID,
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- // console.log('data: ', data);
- socket.emit("v1:Line:delete:point", data);
-
- ////////// Update onlyFloorlines.current to remove references to the deleted point //////////
-
- onlyFloorlines.current = onlyFloorlines.current
- .map((floorline) =>
- floorline.filter(
- (line) =>
- line[0][1] !== DeletedPointUUID && line[1][1] !== DeletedPointUUID
- )
- )
- .filter((floorline) => floorline.length > 0);
-
- RemoveConnectedLines(
- DeletedPointUUID,
- floorPlanGroupLine,
- floorPlanGroupPoint,
- setDeletedLines,
- lines
- );
-
- echo.success("Point Removed!");
-}
-
-export default deletePoint;
diff --git a/app/src/modules/builder/geomentries/points/dragPoint.ts b/app/src/modules/builder/geomentries/points/dragPoint.ts
deleted file mode 100644
index 6494721..0000000
--- a/app/src/modules/builder/geomentries/points/dragPoint.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import * as THREE from "three";
-import * as Types from "../../../../types/world/worldTypes"
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-
-import updateLinesPositions from "../lines/updateLinesPositions";
-import updateLines from "../lines/updateLines";
-import updateDistanceText from "../lines/updateDistanceText";
-import updateFloorLines from "../floors/updateFloorLines";
-
-function DragPoint(
- event: Types.IntersectionEvent,
- floorPlanGroupPoint: Types.RefGroup,
- floorPlanGroupLine: Types.RefGroup,
- scene: THREE.Scene,
- lines: Types.RefLines,
- onlyFloorlines: Types.RefOnlyFloorLines
-): void {
-
- ////////// Calling the line updation of the affected lines and Snapping of the point during the drag //////////
-
- const snapThreshold = CONSTANTS.pointConfig.snappingThreshold;
- const DragedPoint = event.object as Types.Mesh;
-
- floorPlanGroupPoint.current.children.forEach((point) => {
- let canSnap =
- ((DragedPoint.userData.type === CONSTANTS.lineConfig.wallName) && (point.userData.type === CONSTANTS.lineConfig.wallName || point.userData.type === CONSTANTS.lineConfig.floorName)) ||
- ((DragedPoint.userData.type === CONSTANTS.lineConfig.floorName) && (point.userData.type === CONSTANTS.lineConfig.wallName || point.userData.type === CONSTANTS.lineConfig.floorName)) ||
- ((DragedPoint.userData.type === CONSTANTS.lineConfig.aisleName) && point.userData.type === CONSTANTS.lineConfig.aisleName);
- if (canSnap && point.uuid !== DragedPoint.uuid && point.visible) {
- const distance = DragedPoint.position.distanceTo(point.position);
- if (distance < snapThreshold) {
- DragedPoint.position.copy(point.position);
- }
- }
- });
-
- const affectedLines = updateLinesPositions(DragedPoint, lines);
-
- updateLines(floorPlanGroupLine, affectedLines);
- updateDistanceText(scene, floorPlanGroupLine, affectedLines);
- updateFloorLines(onlyFloorlines, DragedPoint);
-}
-
-export default DragPoint;
\ No newline at end of file
diff --git a/app/src/modules/builder/geomentries/points/removeSoloPoint.ts b/app/src/modules/builder/geomentries/points/removeSoloPoint.ts
deleted file mode 100644
index 56d3ee7..0000000
--- a/app/src/modules/builder/geomentries/points/removeSoloPoint.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import * as Types from "../../../../types/world/worldTypes";
-
-function removeSoloPoint(
- line: Types.RefLine,
- floorPlanGroupLine: Types.RefGroup,
- floorPlanGroupPoint: Types.RefGroup
-): void {
-
- ////////// Remove the point if there is only one point and if it is not connected to any other line and also the reference line //////////
-
- if (line.current[0]) {
- const pointUUID = line.current[0][1];
- let isConnected = false;
-
- floorPlanGroupLine.current.children.forEach((line) => {
- const linePoints = line.userData.linePoints;
- const uuid1 = linePoints[0][1];
- const uuid2 = linePoints[1][1];
- if (uuid1 === pointUUID || uuid2 === pointUUID) {
- isConnected = true;
- }
- });
-
- if (!isConnected) {
- floorPlanGroupPoint.current.children.forEach((point: any) => {
- if (point.uuid === pointUUID) {
- (point.material).dispose();
- (point.geometry).dispose();
- floorPlanGroupPoint.current.remove(point);
- }
- });
- }
- line.current = [];
- }
-}
-
-export default removeSoloPoint;
diff --git a/app/src/modules/builder/geomentries/roofs/addRoofToScene.ts b/app/src/modules/builder/geomentries/roofs/addRoofToScene.ts
deleted file mode 100644
index 4630efc..0000000
--- a/app/src/modules/builder/geomentries/roofs/addRoofToScene.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import * as THREE from 'three';
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-import * as Types from "../../../../types/world/worldTypes";
-
-function addRoofToScene(
- shape: Types.Shape,
- floor: Types.Number,
- userData: Types.UserData,
- floorGroup: Types.RefGroup
-): void {
-
- ////////// Creating a Polygon roof from the shape of the Polygon floor //////////
-
- const extrudeSettings: THREE.ExtrudeGeometryOptions = {
- depth: CONSTANTS.roofConfig.height,
- bevelEnabled: false
- };
-
- const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
- const material = new THREE.MeshStandardMaterial({ color: CONSTANTS.roofConfig.defaultColor, side: THREE.DoubleSide });
- const mesh = new THREE.Mesh(geometry, material);
- mesh.position.y = CONSTANTS.wallConfig.height + floor;
- mesh.castShadow = true;
- mesh.receiveShadow = true;
- mesh.rotateX(Math.PI / 2);
- mesh.userData.uuids = userData;
- mesh.name = `Roof_Layer_${(floor / CONSTANTS.wallConfig.height) + 1}`;
-
- floorGroup.current.add(mesh);
-}
-
-export default addRoofToScene;
diff --git a/app/src/modules/builder/geomentries/roofs/hideRoof.ts b/app/src/modules/builder/geomentries/roofs/hideRoof.ts
deleted file mode 100644
index 8eb80f8..0000000
--- a/app/src/modules/builder/geomentries/roofs/hideRoof.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import * as THREE from 'three';
-
-import * as Types from "../../../../types/world/worldTypes";
-
-function hideRoof(
- visibility: Types.Boolean,
- floorGroup: Types.RefGroup,
- camera: THREE.Camera
-): void {
-
- ////////// Toggles the visibility of the roof based on the camera position and the Roof visibility button on UI //////////
-
- const v = new THREE.Vector3();
- const u = new THREE.Vector3();
-
- if (visibility === true && floorGroup.current) {
- for (const child of floorGroup.current.children) {
- if (child.name.includes("Roof")) {
- const roofChild = child as Types.Mesh;
- roofChild.getWorldDirection(v);
- camera?.getWorldDirection(u);
- if (roofChild.material) {
- const materials = Array.isArray(roofChild.material) ? roofChild.material : [roofChild.material];
- materials.forEach(material => {
- material.visible = v.dot(u) < 0.25;
- });
- }
- }
- }
- } else {
- if (floorGroup.current) {
- for (const child of floorGroup.current.children) {
- if (child.name.includes("Roof")) {
- const roofChild = child as Types.Mesh;
- if (roofChild.material) {
- const materials = Array.isArray(roofChild.material) ? roofChild.material : [roofChild.material];
- materials.forEach(material => {
- material.visible = false;
- });
- }
- }
- }
- }
- }
-}
-
-export default hideRoof;
diff --git a/app/src/modules/builder/geomentries/walls/addWallItems.ts b/app/src/modules/builder/geomentries/walls/addWallItems.ts
deleted file mode 100644
index 809b093..0000000
--- a/app/src/modules/builder/geomentries/walls/addWallItems.ts
+++ /dev/null
@@ -1,164 +0,0 @@
-import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
-import { toast } from "react-toastify";
-import * as THREE from "three";
-import * as Types from "../../../../types/world/worldTypes";
-import * as CONSTANTS from "../../../../types/world/worldConstants";
-import { Socket } from "socket.io-client";
-import { retrieveGLTF, storeGLTF } from "../../../../utils/indexDB/idbUtils";
-import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
-import { getUserData } from "../../../../functions/getUserData";
-
-async function AddWallItems(
- selected: any,
- raycaster: THREE.Raycaster,
- CSGGroup: Types.RefMesh,
- setWallItems: Types.setWallItemSetState,
- socket: Socket,
- projectId?: string,
- versionId?: string
-): Promise {
-
- const { userId, organization } = getUserData();
- let intersects = raycaster?.intersectObject(CSGGroup.current!, true);
- const wallRaycastIntersection = intersects?.find((child) =>
- child.object.name.includes("WallRaycastReference")
- );
- let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
-
- if (!wallRaycastIntersection) return;
-
- const intersectionPoint = wallRaycastIntersection;
- 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);
-
- // Check THREE.js cache first
- const cachedModel = THREE.Cache.get(selected.id);
- if (cachedModel) {
- handleModelLoad(cachedModel);
- return;
- }
-
- // Check IndexedDB cache
- const cachedModelBlob = await retrieveGLTF(selected.id);
- if (cachedModelBlob) {
- const blobUrl = URL.createObjectURL(cachedModelBlob);
- loader.load(blobUrl, (gltf) => {
- URL.revokeObjectURL(blobUrl);
- THREE.Cache.remove(blobUrl);
- THREE.Cache.add(selected.id, gltf);
- handleModelLoad(gltf);
- });
- return;
- }
-
- // Load from backend if not in any cache
- loader.load(
- `${url_Backend_dwinzo}/api/v2/AssetFile/${selected.id}`,
- async (gltf) => {
- try {
- const modelBlob = await fetch(
- `${url_Backend_dwinzo}/api/v2/AssetFile/${selected.id}`
- ).then((res) => res.blob());
- await storeGLTF(selected.id, modelBlob);
- THREE.Cache.add(selected.id, gltf);
- await handleModelLoad(gltf);
- } catch (error) {
- console.error("Failed to cache model:", error);
- handleModelLoad(gltf);
- }
- }
- );
-
- async function handleModelLoad(gltf: GLTF) {
- const model = gltf.scene.clone();
- model.userData = { wall: intersectionPoint.object.parent };
-
- model.children[0].children.forEach((child) => {
- if (child.name !== "CSG_REF") {
- child.castShadow = true;
- child.receiveShadow = true;
- }
- });
-
- const boundingBox = new THREE.Box3().setFromObject(model);
- const size = new THREE.Vector3();
- boundingBox.getSize(size);
-
- const csgscale = [size.x, size.y, size.z] as [number, number, number];
-
- const center = new THREE.Vector3();
- boundingBox.getCenter(center);
- const csgposition = [center.x, center.y, center.z] as [
- number,
- number,
- number
- ];
-
- let positionY =
- selected.subCategory === "fixed-move" ? 0 : intersectionPoint.point.y;
- if (positionY === 0) {
- positionY =
- Math.floor(intersectionPoint.point.y / CONSTANTS.wallConfig.height) *
- CONSTANTS.wallConfig.height;
- }
-
- const newWallItem = {
- type: selected.subCategory,
- model: model,
- modelName: selected.name,
- assetId: selected.id,
- scale: [1, 1, 1] as [number, number, number],
- csgscale: csgscale,
- csgposition: csgposition,
- position: [
- intersectionPoint.point.x,
- positionY,
- intersectionPoint.point.z,
- ] as [number, number, number],
- quaternion:
- intersectionPoint.object.quaternion.clone() as Types.QuaternionType,
- };
-
- const data = {
- organization,
- modelUuid: model.uuid,
- modelName: newWallItem.modelName,
- assetId: selected.id,
- type: selected.subCategory,
- csgposition: newWallItem.csgposition,
- csgscale: newWallItem.csgscale,
- position: newWallItem.position,
- quaternion: newWallItem.quaternion,
- scale: newWallItem.scale,
- socketId: socket.id,
- versionId,
- projectId,
- userId,
- };
-
- socket.emit("v1:wallItems:set", data);
-
- setWallItems((prevItems) => {
- const updatedItems = [...prevItems, newWallItem];
-
- const WallItemsForStorage = updatedItems.map((item) => {
- const { model, ...rest } = item;
- return {
- ...rest,
- modelUuid: model?.uuid,
- };
- });
-
- localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
- echo.success("Model Added!");
- return updatedItems;
- });
- }
-}
-
-export default AddWallItems;
diff --git a/app/src/modules/builder/geomentries/walls/deleteWallItems.ts b/app/src/modules/builder/geomentries/walls/deleteWallItems.ts
deleted file mode 100644
index 5d16e91..0000000
--- a/app/src/modules/builder/geomentries/walls/deleteWallItems.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { getUserData } from "../../../../functions/getUserData";
-import * as Types from "../../../../types/world/worldTypes";
-// import { deleteWallItem } from '../../../../services/factoryBuilder/assest/wallAsset/deleteWallItemApi';
-import { Socket } from "socket.io-client";
-
-function DeleteWallItems(
- hoveredDeletableWallItem: Types.RefMesh,
- setWallItems: Types.setWallItemSetState,
- wallItems: Types.wallItems,
- socket: Socket,
- projectId?: string,
- versionId? : string,
-): void {
- ////////// Deleting the hovered Wall GLTF from thewallItems and also update it in the localstorage //////////
- const { userId, organization, email } = getUserData();
- if (hoveredDeletableWallItem.current && hoveredDeletableWallItem.current) {
- setWallItems([]);
- let WallItemsRef = wallItems;
- const removedItem = WallItemsRef.find(
- (item) => item.model?.uuid === hoveredDeletableWallItem.current?.uuid
- );
- const Items = WallItemsRef.filter(
- (item) => item.model?.uuid !== hoveredDeletableWallItem.current?.uuid
- );
-
- setTimeout(async () => {
- WallItemsRef = Items;
- setWallItems(WallItemsRef);
-
- //REST
-
- // await deleteWallItem(organization, removedItem?.model?.uuid!, removedItem?.modelName!)
-
- //SOCKET
-
- const data = {
- organization,
- modelUuid: removedItem?.model?.uuid!,
- modelName: removedItem?.modelName!,
- socketId: socket.id,
- projectId,
- versionId,
- userId,
- };
-
- socket.emit("v1:wallItems:delete", data);
-
- const WallItemsForStorage = WallItemsRef.map((item) => {
- const { model, ...rest } = item;
- return {
- ...rest,
- modelUuid: model?.uuid,
- };
- });
-
- localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
- hoveredDeletableWallItem.current = null;
- }, 50);
- }
-}
-
-export default DeleteWallItems;
diff --git a/app/src/modules/builder/geomentries/walls/hideWalls.ts b/app/src/modules/builder/geomentries/walls/hideWalls.ts
deleted file mode 100644
index 02233b0..0000000
--- a/app/src/modules/builder/geomentries/walls/hideWalls.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import * as THREE from 'three';
-import * as Types from "../../../../types/world/worldTypes";
-
-function hideWalls(
- visibility: Types.Boolean,
- scene: THREE.Scene,
- camera: THREE.Camera
-): void {
- const wallNormal = new THREE.Vector3();
- const cameraToWall = new THREE.Vector3();
- const cameraDirection = new THREE.Vector3();
-
- if (visibility === true) {
- for (const children of scene.children) {
- if (children.name === "Walls" && children.children[0]?.children.length > 0) {
- children.children[0].children.forEach((child: any) => {
- if (child.children[0]?.userData.WallType === "RoomWall") {
- const wallMesh = child.children[0];
- wallMesh.getWorldDirection(wallNormal);
- cameraToWall.copy(wallMesh.position).sub(camera.position).normalize();
- camera.getWorldDirection(cameraDirection);
- const isFacingCamera = wallNormal.dot(cameraToWall) > 0;
- const isInFrontOfCamera = cameraDirection.dot(cameraToWall) > -0.3;
-
- if (wallMesh.material) {
- wallMesh.material.visible = isFacingCamera && isInFrontOfCamera;
- }
- }
- });
- }
- }
- } else {
- for (const children of scene.children) {
- if (children.name === "Walls" && children.children[0]?.children.length > 0) {
- children.children[0].children.forEach((child: any) => {
- if (child.children[0]?.userData.WallType === "RoomWall" && child.children[0].material) {
- child.children[0].material.visible = true;
- }
- });
- }
- }
- }
-}
-
-export default hideWalls;
\ No newline at end of file
diff --git a/app/src/modules/builder/geomentries/walls/loadWalls.ts b/app/src/modules/builder/geomentries/walls/loadWalls.ts
deleted file mode 100644
index 14d72c4..0000000
--- a/app/src/modules/builder/geomentries/walls/loadWalls.ts
+++ /dev/null
@@ -1,140 +0,0 @@
-import * as THREE from 'three';
-import * as turf from '@turf/turf';
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-
-import * as Types from "../../../../types/world/worldTypes";
-import getRoomsFromLines from '../lines/getRoomsFromLines';
-
-async function loadWalls(
- lines: Types.RefLines,
- setWalls: any,
-): Promise {
- ////////// Removes the old walls if any, Checks if there is any overlapping in lines if any updates it , starts function that creates floor and roof //////////
-
- const Walls: Types.Walls = [];
- const Rooms: Types.Rooms = [];
-
- localStorage.setItem("Lines", JSON.stringify(lines.current));
-
- if (lines.current.length > 1) {
-
- ////////// Add Walls that are forming a room //////////
-
- const wallSet = new Set();
-
- const rooms: Types.Rooms = await getRoomsFromLines(lines);
- Rooms.push(...rooms);
-
- Rooms.forEach(({ coordinates: room, layer }) => {
- for (let i = 0; i < room.length - 1; i++) {
- const uuid1 = room[i].uuid;
- const uuid2 = room[(i + 1) % room.length].uuid;
- const wallId = `${uuid1}_${uuid2}`;
-
- if (!wallSet.has(wallId)) {
- const p1 = room[i].position;
- const p2 = room[(i + 1) % room.length].position;
-
- const shape = new THREE.Shape();
- shape.moveTo(0, 0);
- shape.lineTo(0, CONSTANTS.wallConfig.height);
- shape.lineTo(p2.distanceTo(p1), CONSTANTS.wallConfig.height);
- shape.lineTo(p2.distanceTo(p1), 0);
- shape.lineTo(0, 0);
-
- const extrudeSettings = {
- depth: CONSTANTS.wallConfig.width,
- bevelEnabled: false
- };
- const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
- const angle = Math.atan2(p2.z - p1.z, p2.x - p1.x);
- Walls.push([geometry, [0, -angle, 0], [p1.x, (layer - 1) * CONSTANTS.wallConfig.height, p1.z], "RoomWall", layer]);
-
- wallSet.add(wallId);
- }
- }
- });
-
- ////////// Add Walls that are not forming any room //////////
-
- lines.current.forEach(line => {
- if (line[0][3] && line[1][3] !== CONSTANTS.lineConfig.wallName) {
- return;
- }
- const [uuid1, uuid2] = line.map(point => point[1]);
- let isInRoom = false;
- const lineLayer = line[0][2];
-
- for (let room of Rooms) {
- const roomLayer = room.layer;
- if (roomLayer !== lineLayer) continue;
- for (let i = 0; i < room.coordinates.length - 1; i++) {
- const roomUuid1 = room.coordinates[i].uuid;
- const roomUuid2 = room.coordinates[(i + 1) % room.coordinates.length].uuid;
- if (
- (uuid1 === roomUuid1 && uuid2 === roomUuid2) ||
- (uuid1 === roomUuid2 && uuid2 === roomUuid1)
- ) {
- isInRoom = true;
- break;
- }
- }
- if (isInRoom) break;
- }
-
- if (!isInRoom) {
- const p1 = new THREE.Vector3(line[0][0].x, 0, line[0][0].z);
- const p2 = new THREE.Vector3(line[1][0].x, 0, line[1][0].z);
-
- let isCollinear = false;
- for (let room of Rooms) {
- if (room.layer !== lineLayer) continue;
- for (let i = 0; i < room.coordinates.length - 1; i++) {
- const roomP1 = room.coordinates[i].position;
- const roomP2 = room.coordinates[(i + 1) % room.coordinates.length].position;
- const lineFeature = turf.lineString([[p1.x, p1.z], [p2.x, p2.z]]);
- const roomFeature = turf.lineString([[roomP1.x, roomP1.z], [roomP2.x, roomP2.z]]);
- if (turf.booleanOverlap(lineFeature, roomFeature)) {
- isCollinear = true;
- break;
- }
- }
- if (isCollinear) break;
- }
-
- if (!isCollinear) {
- const shape = new THREE.Shape();
- shape.moveTo(0, 0);
- shape.lineTo(0, CONSTANTS.wallConfig.height);
- shape.lineTo(p2.distanceTo(p1), CONSTANTS.wallConfig.height);
- shape.lineTo(p2.distanceTo(p1), 0);
- shape.lineTo(0, 0);
-
- const extrudeSettings = {
- depth: CONSTANTS.wallConfig.width,
- bevelEnabled: false
- };
- const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
- const angle = Math.atan2(p2.z - p1.z, p2.x - p1.x);
- Walls.push([geometry, [0, -angle, 0], [p1.x, (lineLayer - 1) * CONSTANTS.wallConfig.height, p1.z], "SegmentWall", lineLayer]);
- }
- }
- });
- setWalls(Walls);
- } else {
- setWalls([]);
- }
-}
-
-export default loadWalls;
-
-
-// A----- B----- C
-// | | |
-// | | |
-// | | |
-// F----- E----- D
-
-// 1. A -> B, B -> C, C -> D, D -> E, E -> F, F -> A, B -> E
-
-// 2. E -> F, F -> A, A -> B, B -> E, E -> D, D -> C, C -> B
\ No newline at end of file
diff --git a/app/src/modules/builder/geomentries/zones/addZonesToScene.ts b/app/src/modules/builder/geomentries/zones/addZonesToScene.ts
deleted file mode 100644
index 2832c7a..0000000
--- a/app/src/modules/builder/geomentries/zones/addZonesToScene.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import * as THREE from 'three';
-import * as Types from '../../../../types/world/worldTypes';
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-
-const baseMaterial = new THREE.ShaderMaterial({
- side: THREE.DoubleSide,
- vertexShader: `
- varying vec2 vUv;
- void main(){
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
- vUv = uv;
- }
- `,
- fragmentShader: `
- varying vec2 vUv;
- uniform vec3 uOuterColor;
- void main(){
- float alpha = 1.0 - vUv.y;
- gl_FragColor = vec4(uOuterColor, alpha);
- }
- `,
- uniforms: {
- uOuterColor: { value: new THREE.Color(CONSTANTS.zoneConfig.defaultColor) },
- },
- transparent: true,
-});
-
-export default function addZonesToScene(
- line: Types.Line,
- floorGroupZone: Types.RefGroup,
- color: THREE.Color
-) {
- const point1 = line[0][0];
- const point2 = line[1][0];
-
- const length = (new THREE.Vector3(point2.x, point2.y, point2.z)).distanceTo(new THREE.Vector3(point1.x, point1.y, point1.z));
- const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x);
-
- const geometry = new THREE.PlaneGeometry(length, 10);
-
- const material = baseMaterial.clone();
- material.uniforms.uOuterColor.value.set(color.r, color.g, color.b);
-
- const mesh = new THREE.Mesh(geometry, material);
-
- mesh.position.set((point1.x + point2.x) / 2, ((line[0][2] - 1) * CONSTANTS.wallConfig.height) + 5, (point1.z + point2.z) / 2);
- mesh.rotation.y = -angle;
-
- floorGroupZone.current.add(mesh);
-}
diff --git a/app/src/modules/builder/geomentries/zones/loadZones.ts b/app/src/modules/builder/geomentries/zones/loadZones.ts
deleted file mode 100644
index aa78199..0000000
--- a/app/src/modules/builder/geomentries/zones/loadZones.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import * as Types from '../../../../types/world/worldTypes';
-import * as THREE from 'three';
-import * as CONSTANTS from '../../../../types/world/worldConstants';
-import addZonesToScene from './addZonesToScene';
-
-export default function loadZones(
- lines: Types.RefLines,
- floorGroupZone: Types.RefGroup
-) {
- if (!floorGroupZone.current) return
- floorGroupZone.current.children = [];
- const zones = lines.current.filter((line) => line[0][3] && line[1][3] === CONSTANTS.lineConfig.zoneName);
-
- if (zones.length > 0) {
- zones.forEach((zone: Types.Line) => {
- addZonesToScene(zone, floorGroupZone, new THREE.Color(CONSTANTS.zoneConfig.color))
- })
- }
-}
\ No newline at end of file
diff --git a/app/src/modules/builder/groups/floorGroup.tsx b/app/src/modules/builder/groups/floorGroup.tsx
deleted file mode 100644
index 4af21b9..0000000
--- a/app/src/modules/builder/groups/floorGroup.tsx
+++ /dev/null
@@ -1,127 +0,0 @@
-import { useFrame, useThree } from "@react-three/fiber";
-import {
- useAddAction,
- useRoofVisibility,
- useToggleView,
- useWallVisibility,
- useUpdateScene,
- useRenameModeStore,
- useToolMode,
-} from "../../../store/builder/store";
-import hideRoof from "../geomentries/roofs/hideRoof";
-import hideWalls from "../geomentries/walls/hideWalls";
-import addAndUpdateReferencePillar from "../geomentries/pillars/addAndUpdateReferencePillar";
-import { useEffect } from "react";
-import addPillar from "../geomentries/pillars/addPillar";
-import DeletePillar from "../geomentries/pillars/deletePillar";
-import DeletableHoveredPillar from "../geomentries/pillars/deletableHoveredPillar";
-import loadFloor from "../geomentries/floors/loadFloor";
-import { useLeftData, useTopData } from "../../../store/visualization/useZone3DWidgetStore";
-
-const FloorGroup = ({
- floorGroup,
- lines,
- referencePole,
- hoveredDeletablePillar,
-}: any) => {
- const state = useThree();
- const { roofVisibility } = useRoofVisibility();
- const { wallVisibility } = useWallVisibility();
- const { toggleView } = useToggleView();
- const { scene, camera, raycaster, gl } = useThree();
- const { addAction } = useAddAction();
- const { toolMode } = useToolMode();
- const { updateScene, setUpdateScene } = useUpdateScene();
- const { setTop } = useTopData();
- const { setLeft } = useLeftData();
- const { isRenameMode, setIsRenameMode } = useRenameModeStore();
-
- useEffect(() => {
- if (updateScene) {
- loadFloor(lines, floorGroup);
- setUpdateScene(false);
- }
- }, [updateScene]);
-
- useEffect(() => {
- if (!addAction) {
- if (referencePole.current) {
- (referencePole.current as any).material.dispose();
- (referencePole.current.geometry as any).dispose();
- floorGroup.current.remove(referencePole.current);
- referencePole.current = undefined;
- }
- }
- }, [addAction]);
-
- useEffect(() => {
- const canvasElement = gl.domElement;
- let drag = false;
- let isLeftMouseDown = false;
-
- const onMouseDown = (evt: any) => {
-
- if (evt.button === 0) {
- isLeftMouseDown = true;
- drag = false;
- }
- };
-
- const onMouseUp = (evt: any) => {
- setIsRenameMode(false);
- if (evt.button === 0) {
- isLeftMouseDown = false;
- if (!drag) {
- if (addAction === "pillar") {
- addPillar(referencePole, floorGroup);
- }
- if (toolMode === '3D-Delete') {
- DeletePillar(hoveredDeletablePillar, floorGroup);
- }
- }
- }
- };
-
- const onMouseMove = (evt: any) => {
- if (!canvasElement) return;
- const canvasRect = canvasElement.getBoundingClientRect();
- const relativeX = evt.clientX - canvasRect.left;
- const relativeY = evt.clientY - canvasRect.top;
- // if (!isRenameMode) {
- // setTop(relativeY);
- // setLeft(relativeX);
- // }
- if (isLeftMouseDown) {
- drag = true;
- }
- };
-
- canvasElement.addEventListener("mousedown", onMouseDown);
- canvasElement.addEventListener("mouseup", onMouseUp);
- canvasElement.addEventListener("mousemove", onMouseMove);
-
- return () => {
- canvasElement.removeEventListener("mousedown", onMouseDown);
- canvasElement.removeEventListener("mouseup", onMouseUp);
- canvasElement.removeEventListener("mousemove", onMouseMove);
- };
- }, [toolMode, addAction, isRenameMode]);
-
- useFrame(() => {
- hideRoof(roofVisibility, floorGroup, camera);
- hideWalls(wallVisibility, scene, camera);
-
- if (addAction === "pillar") {
- addAndUpdateReferencePillar(raycaster, floorGroup, referencePole);
- }
- if (toolMode === '3D-Delete') {
- DeletableHoveredPillar(state, floorGroup, hoveredDeletablePillar);
- }
- });
-
- return (
-
- );
-};
-
-export default FloorGroup;
diff --git a/app/src/modules/builder/groups/floorPlanGroup.tsx b/app/src/modules/builder/groups/floorPlanGroup.tsx
deleted file mode 100644
index e35cec9..0000000
--- a/app/src/modules/builder/groups/floorPlanGroup.tsx
+++ /dev/null
@@ -1,193 +0,0 @@
-import { useEffect } from "react";
-import * as Types from '../../../types/world/worldTypes';
-import { useActiveLayer, useDeletedLines, useToolMode, useNewLines, useRemovedLayer, useSocketStore, useToggleView, useUpdateScene } from "../../../store/builder/store";
-import Layer2DVisibility from "../geomentries/layers/layer2DVisibility";
-import { useFrame, useThree } from "@react-three/fiber";
-import DeletableLineorPoint from "../functions/deletableLineOrPoint";
-import removeSoloPoint from "../geomentries/points/removeSoloPoint";
-import removeReferenceLine from "../geomentries/lines/removeReferenceLine";
-import DeleteLayer from "../geomentries/layers/deleteLayer";
-import { getLines } from "../../../services/factoryBuilder/lines/getLinesApi";
-import objectLinesToArray from "../geomentries/lines/lineConvertions/objectLinesToArray";
-import loadInitialPoint from "../IntialLoad/loadInitialPoint";
-import loadInitialLine from "../IntialLoad/loadInitialLine";
-import deletePoint from "../geomentries/points/deletePoint";
-import deleteLine from "../geomentries/lines/deleteLine";
-import drawWall from "../geomentries/lines/drawWall";
-import drawOnlyFloor from "../geomentries/floors/drawOnlyFloor";
-import addDragControl from "../eventDeclaration/dragControlDeclaration";
-import { useParams } from "react-router-dom";
-import { getUserData } from "../../../functions/getUserData";
-import { useVersionContext } from "../version/versionContext";
-
-const FloorPlanGroup = ({ floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, floorGroup, currentLayerPoint, dragPointControls, hoveredDeletablePoint, hoveredDeletableLine, plane, line, lines, onlyFloorline, onlyFloorlines, ReferenceLineMesh, LineCreated, isSnapped, ispreSnapped, snappedPoint, isSnappedUUID, isAngleSnapped, anglesnappedPoint }: any) => {
- const state = useThree();
- const { camera, gl, raycaster, controls } = state;
- const { activeLayer } = useActiveLayer();
- const { toggleView } = useToggleView();
- const { toolMode } = useToolMode();
- const { removedLayer, setRemovedLayer } = useRemovedLayer();
- const { setUpdateScene } = useUpdateScene();
- const { setNewLines } = useNewLines();
- const { setDeletedLines } = useDeletedLines();
- const { socket } = useSocketStore();
- const { ydoc } = useSocketStore();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { projectId } = useParams();
- const { organization } = getUserData();
-
-
- useEffect(() => {
- if (toolMode === 'move') {
- addDragControl(dragPointControls, currentLayerPoint, state, floorPlanGroupPoint, floorPlanGroupLine, lines, onlyFloorlines, socket, projectId, selectedVersion?.versionId || '',);
- }
-
- return () => {
- if (dragPointControls.current) {
- dragPointControls.current.enabled = false;
- }
- };
- }, [toolMode, state]);
-
- useEffect(() => {
- if (!selectedVersion) return;
-
- getLines(organization, projectId, selectedVersion?.versionId || '').then((data) => {
-
- const Lines: Types.Lines = objectLinesToArray(data);
-
- if (Lines) {
- lines.current = Lines;
- loadInitialPoint(lines, floorPlanGroupPoint, currentLayerPoint, dragPointControls);
- loadInitialLine(floorPlanGroupLine, lines);
- setUpdateScene(true);
- }
- })
- }, [selectedVersion?.versionId]);
-
- useEffect(() => {
- if (!toggleView) {
- removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint);
- removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
- }
- }, [toggleView]);
-
- useEffect(() => {
- removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint);
- removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
- }, [toolMode]);
-
- useEffect(() => {
- if (toolMode === 'move' && toggleView) {
- if (dragPointControls.current) {
- dragPointControls.current.enabled = true;
- }
- } else {
- if (dragPointControls.current) {
- dragPointControls.current.enabled = false;
- }
- }
- }, [toolMode, toggleView, state]);
-
- useEffect(() => {
- Layer2DVisibility(activeLayer, floorPlanGroup, floorPlanGroupLine, floorPlanGroupPoint, currentLayerPoint, dragPointControls);
- }, [activeLayer]);
-
- useEffect(() => {
- if (removedLayer !== null) {
- DeleteLayer(removedLayer, lines, floorPlanGroupLine, floorPlanGroupPoint, onlyFloorlines, floorGroup, setDeletedLines, setRemovedLayer, socket, projectId, selectedVersion?.versionId || '',);
- }
- }, [removedLayer]);
-
- useEffect(() => {
-
- const canvasElement = gl.domElement;
-
- let drag = false;
- let isLeftMouseDown = false;
-
- const onMouseDown = (evt: any) => {
- if (evt.button === 0) {
- isLeftMouseDown = true;
- drag = false;
- }
- };
-
- const onMouseUp = (evt: any) => {
- if (evt.button === 0) {
- isLeftMouseDown = false;
- }
- if (controls) {
- (controls as any).enabled = true;
- }
- }
-
- const onMouseMove = () => {
- if (isLeftMouseDown) {
- drag = true;
- }
- };
-
- const onContextMenu = (e: any) => {
- e.preventDefault();
- if (toolMode === "Wall" || toolMode === "Floor") {
- removeSoloPoint(line, floorPlanGroupLine, floorPlanGroupPoint);
- removeReferenceLine(floorPlanGroup, ReferenceLineMesh, LineCreated, line);
- }
- };
-
- const onMouseClick = (evt: any) => {
- if (!plane.current || drag) return;
-
- if (toolMode === "2D-Delete") {
- if (hoveredDeletablePoint.current !== null) {
- deletePoint(hoveredDeletablePoint, onlyFloorlines, floorPlanGroupPoint, floorPlanGroupLine, lines, setDeletedLines, socket, projectId, selectedVersion?.versionId || '',);
- }
- if (hoveredDeletableLine.current !== null) {
- deleteLine(hoveredDeletableLine, onlyFloorlines, lines, floorPlanGroupLine, floorPlanGroupPoint, setDeletedLines, socket, projectId, selectedVersion?.versionId || '',);
- }
- }
-
- if (toolMode === "Wall") {
- drawWall(raycaster, plane, floorPlanGroupPoint, snappedPoint, isSnapped, isSnappedUUID, line, ispreSnapped, anglesnappedPoint, isAngleSnapped, lines, floorPlanGroupLine, floorPlanGroup, ReferenceLineMesh, LineCreated, currentLayerPoint, dragPointControls, setNewLines, setDeletedLines, activeLayer, socket, projectId, selectedVersion?.versionId || '', ydoc);
- }
-
- if (toolMode === "Floor") {
- drawOnlyFloor(raycaster, state, camera, plane, floorPlanGroupPoint, snappedPoint, isSnapped, isSnappedUUID, line, ispreSnapped, anglesnappedPoint, isAngleSnapped, onlyFloorline, onlyFloorlines, lines, floorPlanGroupLine, floorPlanGroup, ReferenceLineMesh, LineCreated, currentLayerPoint, dragPointControls, setNewLines, setDeletedLines, activeLayer, socket, projectId, selectedVersion?.versionId || '',);
- }
- }
-
- if (toolMode === "2D-Delete" || toolMode === "Wall" || toolMode === "Floor") {
- canvasElement.addEventListener("mousedown", onMouseDown);
- canvasElement.addEventListener("mouseup", onMouseUp);
- canvasElement.addEventListener("mousemove", onMouseMove);
- canvasElement.addEventListener("click", onMouseClick);
- canvasElement.addEventListener("contextmenu", onContextMenu);
- }
-
- return () => {
- canvasElement.removeEventListener("mousedown", onMouseDown);
- canvasElement.removeEventListener("mouseup", onMouseUp);
- canvasElement.removeEventListener("mousemove", onMouseMove);
- canvasElement.removeEventListener("click", onMouseClick);
- canvasElement.removeEventListener("contextmenu", onContextMenu);
- };
- }, [toolMode, activeLayer])
-
-
- useFrame(() => {
- if (toolMode === '2D-Delete') {
- DeletableLineorPoint(state, plane, floorPlanGroupLine, floorPlanGroupPoint, hoveredDeletableLine, hoveredDeletablePoint);
- }
- })
-
- return (
-
-
-
-
- )
-}
-
-export default FloorPlanGroup;
\ No newline at end of file
diff --git a/app/src/modules/builder/groups/wallItemsGroup.tsx b/app/src/modules/builder/groups/wallItemsGroup.tsx
index 210377b..28f4f4b 100644
--- a/app/src/modules/builder/groups/wallItemsGroup.tsx
+++ b/app/src/modules/builder/groups/wallItemsGroup.tsx
@@ -1,291 +1,291 @@
-import { useEffect } from "react";
-import {
- useObjectPosition,
- useObjectRotation,
- useSelectedWallItem,
- useSocketStore,
- useWallItems,
- useSelectedItem,
- useToolMode,
-} from "../../../store/builder/store";
-import { Csg } from "../csg/csg";
-import * as Types from "../../../types/world/worldTypes";
-import * as CONSTANTS from "../../../types/world/worldConstants";
-import * as THREE from "three";
-import { useThree } from "@react-three/fiber";
-import handleMeshMissed from "../eventFunctions/handleMeshMissed";
-import DeleteWallItems from "../geomentries/walls/deleteWallItems";
-import loadInitialWallItems from "../IntialLoad/loadInitialWallItems";
-import AddWallItems from "../geomentries/walls/addWallItems";
-import useModuleStore from "../../../store/useModuleStore";
-import { useParams } from "react-router-dom";
-import { getUserData } from "../../../functions/getUserData";
-import { useVersionContext } from "../version/versionContext";
+// import { useEffect } from "react";
+// import {
+// useObjectPosition,
+// useObjectRotation,
+// useSelectedWallItem,
+// useSocketStore,
+// useWallItems,
+// useSelectedItem,
+// useToolMode,
+// } from "../../../store/builder/store";
+// import { Csg } from "../csg/csg";
+// import * as Types from "../../../types/world/worldTypes";
+// import * as CONSTANTS from "../../../types/world/worldConstants";
+// import * as THREE from "three";
+// import { useThree } from "@react-three/fiber";
+// import handleMeshMissed from "../eventFunctions/handleMeshMissed";
+// import DeleteWallItems from "../geomentries/walls/deleteWallItems";
+// import loadInitialWallItems from "../IntialLoad/loadInitialWallItems";
+// import AddWallItems from "../geomentries/walls/addWallItems";
+// import useModuleStore from "../../../store/useModuleStore";
+// import { useParams } from "react-router-dom";
+// import { getUserData } from "../../../functions/getUserData";
+// import { useVersionContext } from "../version/versionContext";
-const WallItemsGroup = ({
- currentWallItem,
- hoveredDeletableWallItem,
- selectedItemsIndex,
- setSelectedItemsIndex,
- CSGGroup,
-}: any) => {
- const state = useThree();
- const { socket } = useSocketStore();
- const { pointer, camera, raycaster } = state;
- const { toolMode } = useToolMode();
- const { wallItems, setWallItems } = useWallItems();
- const { setObjectPosition } = useObjectPosition();
- const { setObjectRotation } = useObjectRotation();
- const { setSelectedWallItem } = useSelectedWallItem();
- const { activeModule } = useModuleStore();
- const { selectedItem } = useSelectedItem();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { projectId } = useParams();
- const { userId, organization } = getUserData();
+// const WallItemsGroup = ({
+// currentWallItem,
+// hoveredDeletableWallItem,
+// selectedItemsIndex,
+// setSelectedItemsIndex,
+// CSGGroup,
+// }: any) => {
+// const state = useThree();
+// const { socket } = useSocketStore();
+// const { pointer, camera, raycaster } = state;
+// const { toolMode } = useToolMode();
+// const { wallItems, setWallItems } = useWallItems();
+// const { setObjectPosition } = useObjectPosition();
+// const { setObjectRotation } = useObjectRotation();
+// const { setSelectedWallItem } = useSelectedWallItem();
+// const { activeModule } = useModuleStore();
+// const { selectedItem } = useSelectedItem();
+// const { selectedVersionStore } = useVersionContext();
+// const { selectedVersion } = selectedVersionStore();
+// const { projectId } = useParams();
+// const { userId, organization } = getUserData();
- useEffect(() => {
- // Load Wall Items from the backend
- if (!projectId || !selectedVersion) return;
- loadInitialWallItems(setWallItems, projectId, selectedVersion?.versionId);
- }, [selectedVersion?.versionId]);
+// useEffect(() => {
+// // Load Wall Items from the backend
+// if (!projectId || !selectedVersion) return;
+// loadInitialWallItems(setWallItems, projectId, selectedVersion?.versionId);
+// }, [selectedVersion?.versionId]);
- ////////// Update the Position value changes in the selected item //////////
+// ////////// Update the Position value changes in the selected item //////////
- useEffect(() => {
- const canvasElement = state.gl.domElement;
- function handlePointerMove(e: any) {
- if (selectedItemsIndex !== null && toolMode === 'cursor' && e.buttons === 1) {
- const Raycaster = state.raycaster;
- const intersects = Raycaster.intersectObjects(CSGGroup.current?.children[0].children!, true);
- const Object = intersects.find((child) => child.object.name.includes("WallRaycastReference"));
+// useEffect(() => {
+// const canvasElement = state.gl.domElement;
+// function handlePointerMove(e: any) {
+// if (selectedItemsIndex !== null && toolMode === 'cursor' && e.buttons === 1) {
+// const Raycaster = state.raycaster;
+// const intersects = Raycaster.intersectObjects(CSGGroup.current?.children[0].children!, true);
+// const Object = intersects.find((child) => child.object.name.includes("WallRaycastReference"));
- if (Object) {
- (state.controls as any)!.enabled = false;
- setWallItems((prevItems: any) => {
- const updatedItems = [...prevItems];
- let position: [number, number, number] = [0, 0, 0];
+// if (Object) {
+// (state.controls as any)!.enabled = false;
+// setWallItems((prevItems: any) => {
+// const updatedItems = [...prevItems];
+// let position: [number, number, number] = [0, 0, 0];
- if (updatedItems[selectedItemsIndex].type === "fixed-move") {
- position = [
- Object!.point.x,
- Math.floor(Object!.point.y / CONSTANTS.wallConfig.height) *
- CONSTANTS.wallConfig.height,
- Object!.point.z,
- ];
- } else if (updatedItems[selectedItemsIndex].type === "free-move") {
- position = [Object!.point.x, Object!.point.y, Object!.point.z];
- }
+// if (updatedItems[selectedItemsIndex].type === "fixed-move") {
+// position = [
+// Object!.point.x,
+// Math.floor(Object!.point.y / CONSTANTS.wallConfig.height) *
+// CONSTANTS.wallConfig.height,
+// Object!.point.z,
+// ];
+// } else if (updatedItems[selectedItemsIndex].type === "free-move") {
+// position = [Object!.point.x, Object!.point.y, Object!.point.z];
+// }
- requestAnimationFrame(() => {
- setObjectPosition(new THREE.Vector3(...position));
- setObjectRotation({
- x: THREE.MathUtils.radToDeg(Object!.object.rotation.x),
- y: THREE.MathUtils.radToDeg(Object!.object.rotation.y),
- z: THREE.MathUtils.radToDeg(Object!.object.rotation.z),
- });
- });
+// requestAnimationFrame(() => {
+// setObjectPosition(new THREE.Vector3(...position));
+// setObjectRotation({
+// x: THREE.MathUtils.radToDeg(Object!.object.rotation.x),
+// y: THREE.MathUtils.radToDeg(Object!.object.rotation.y),
+// z: THREE.MathUtils.radToDeg(Object!.object.rotation.z),
+// });
+// });
- updatedItems[selectedItemsIndex] = {
- ...updatedItems[selectedItemsIndex],
- position: position,
- quaternion: Object!.object.quaternion.clone() as Types.QuaternionType,
- };
+// updatedItems[selectedItemsIndex] = {
+// ...updatedItems[selectedItemsIndex],
+// position: position,
+// quaternion: Object!.object.quaternion.clone() as Types.QuaternionType,
+// };
- return updatedItems;
- });
- }
- }
- }
+// return updatedItems;
+// });
+// }
+// }
+// }
- async function handlePointerUp() {
- const Raycaster = state.raycaster;
- const intersects = Raycaster.intersectObjects(
- CSGGroup.current?.children[0].children!,
- true
- );
- const Object = intersects.find((child) =>
- child.object.name.includes("WallRaycastReference")
- );
- if (Object) {
- if (selectedItemsIndex !== null) {
- let currentItem: any = null;
- setWallItems((prevItems: any) => {
- const updatedItems = [...prevItems];
- const WallItemsForStorage = updatedItems.map((item) => {
- const { model, ...rest } = item;
- return {
- ...rest,
- modelUuid: model?.uuid,
- };
- });
+// async function handlePointerUp() {
+// const Raycaster = state.raycaster;
+// const intersects = Raycaster.intersectObjects(
+// CSGGroup.current?.children[0].children!,
+// true
+// );
+// const Object = intersects.find((child) =>
+// child.object.name.includes("WallRaycastReference")
+// );
+// if (Object) {
+// if (selectedItemsIndex !== null) {
+// let currentItem: any = null;
+// setWallItems((prevItems: any) => {
+// const updatedItems = [...prevItems];
+// const WallItemsForStorage = updatedItems.map((item) => {
+// const { model, ...rest } = item;
+// return {
+// ...rest,
+// modelUuid: model?.uuid,
+// };
+// });
- currentItem = updatedItems[selectedItemsIndex];
- localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
- return updatedItems;
- });
+// currentItem = updatedItems[selectedItemsIndex];
+// localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
+// return updatedItems;
+// });
- setTimeout(async () => {
+// setTimeout(async () => {
- //REST
+// //REST
- // await setWallItem(
- // organization,
- // currentItem?.model?.uuid,
- // currentItem.modelName,
- // currentItem.assetId,
- // currentItem.type!,
- // currentItem.csgposition!,
- // currentItem.csgscale!,
- // currentItem.position,
- // currentItem.quaternion,
- // currentItem.scale!,
- // )
+// // await setWallItem(
+// // organization,
+// // currentItem?.model?.uuid,
+// // currentItem.modelName,
+// // currentItem.assetId,
+// // currentItem.type!,
+// // currentItem.csgposition!,
+// // currentItem.csgscale!,
+// // currentItem.position,
+// // currentItem.quaternion,
+// // currentItem.scale!,
+// // )
- //SOCKET
+// //SOCKET
- const data = {
- organization,
- modelUuid: currentItem.model?.uuid!,
- assetId: currentItem.assetId,
- modelName: currentItem.modelName!,
- type: currentItem.type!,
- csgposition: currentItem.csgposition!,
- csgscale: currentItem.csgscale!,
- position: currentItem.position!,
- quaternion: currentItem.quaternion,
- scale: currentItem.scale!,
- socketId: socket.id,
- versionId: selectedVersion?.versionId || '',
- projectId,
- userId
- };
+// const data = {
+// organization,
+// modelUuid: currentItem.model?.uuid!,
+// assetId: currentItem.assetId,
+// modelName: currentItem.modelName!,
+// type: currentItem.type!,
+// csgposition: currentItem.csgposition!,
+// csgscale: currentItem.csgscale!,
+// position: currentItem.position!,
+// quaternion: currentItem.quaternion,
+// scale: currentItem.scale!,
+// socketId: socket.id,
+// versionId: selectedVersion?.versionId || '',
+// projectId,
+// userId
+// };
- // console.log('data: ', data);
- socket.emit("v1:wallItems:set", data);
- }, 0);
- (state.controls as any)!.enabled = true;
- }
- }
- }
+// // console.log('data: ', data);
+// socket.emit("v1:wallItems:set", data);
+// }, 0);
+// (state.controls as any)!.enabled = true;
+// }
+// }
+// }
- canvasElement.addEventListener("pointermove", handlePointerMove);
- canvasElement.addEventListener("pointerup", handlePointerUp);
+// canvasElement.addEventListener("pointermove", handlePointerMove);
+// canvasElement.addEventListener("pointerup", handlePointerUp);
- return () => {
- canvasElement.removeEventListener("pointermove", handlePointerMove);
- canvasElement.removeEventListener("pointerup", handlePointerUp);
- };
- }, [selectedItemsIndex, selectedVersion?.versionId]);
+// return () => {
+// canvasElement.removeEventListener("pointermove", handlePointerMove);
+// canvasElement.removeEventListener("pointerup", handlePointerUp);
+// };
+// }, [selectedItemsIndex, selectedVersion?.versionId]);
- useEffect(() => {
- const canvasElement = state.gl.domElement;
- let drag = false;
- let isLeftMouseDown = false;
+// useEffect(() => {
+// const canvasElement = state.gl.domElement;
+// let drag = false;
+// let isLeftMouseDown = false;
- const onMouseDown = (evt: any) => {
- if (evt.button === 0) {
- isLeftMouseDown = true;
- drag = false;
- }
- };
+// const onMouseDown = (evt: any) => {
+// if (evt.button === 0) {
+// isLeftMouseDown = true;
+// drag = false;
+// }
+// };
- const onMouseUp = (evt: any) => {
- if (evt.button === 0) {
- isLeftMouseDown = false;
- if (!drag && toolMode === '3D-Delete' && activeModule === "builder") {
- DeleteWallItems(
- hoveredDeletableWallItem,
- setWallItems,
- wallItems,
- socket,
- projectId,
- selectedVersion?.versionId || '',
- );
- }
- }
- };
+// const onMouseUp = (evt: any) => {
+// if (evt.button === 0) {
+// isLeftMouseDown = false;
+// if (!drag && toolMode === '3D-Delete' && activeModule === "builder") {
+// DeleteWallItems(
+// hoveredDeletableWallItem,
+// setWallItems,
+// wallItems,
+// socket,
+// projectId,
+// selectedVersion?.versionId || '',
+// );
+// }
+// }
+// };
- const onMouseMove = () => {
- if (isLeftMouseDown) {
- drag = true;
- }
- };
+// const onMouseMove = () => {
+// if (isLeftMouseDown) {
+// drag = true;
+// }
+// };
- const onDrop = (event: any) => {
- if (selectedItem.category !== 'Fenestration') return;
+// const onDrop = (event: any) => {
+// if (selectedItem.category !== 'Fenestration') return;
- pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
- pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
+// pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
+// pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
- raycaster.setFromCamera(pointer, camera);
+// raycaster.setFromCamera(pointer, camera);
- if (selectedItem.id && selectedVersion && projectId) {
- if (selectedItem.subCategory) {
- AddWallItems(
- selectedItem,
- raycaster,
- CSGGroup,
- setWallItems,
- socket,
- projectId,
- selectedVersion?.versionId || '',
- );
- }
- event.preventDefault();
- }
- };
+// if (selectedItem.id && selectedVersion && projectId) {
+// if (selectedItem.subCategory) {
+// AddWallItems(
+// selectedItem,
+// raycaster,
+// CSGGroup,
+// setWallItems,
+// socket,
+// projectId,
+// selectedVersion?.versionId || '',
+// );
+// }
+// event.preventDefault();
+// }
+// };
- const onDragOver = (event: any) => {
- event.preventDefault();
- };
+// const onDragOver = (event: any) => {
+// event.preventDefault();
+// };
- canvasElement.addEventListener("mousedown", onMouseDown);
- canvasElement.addEventListener("mouseup", onMouseUp);
- canvasElement.addEventListener("mousemove", onMouseMove);
- canvasElement.addEventListener("drop", onDrop);
- canvasElement.addEventListener("dragover", onDragOver);
+// canvasElement.addEventListener("mousedown", onMouseDown);
+// canvasElement.addEventListener("mouseup", onMouseUp);
+// canvasElement.addEventListener("mousemove", onMouseMove);
+// canvasElement.addEventListener("drop", onDrop);
+// canvasElement.addEventListener("dragover", onDragOver);
- return () => {
- canvasElement.removeEventListener("mousedown", onMouseDown);
- canvasElement.removeEventListener("mouseup", onMouseUp);
- canvasElement.removeEventListener("mousemove", onMouseMove);
- canvasElement.removeEventListener("drop", onDrop);
- canvasElement.removeEventListener("dragover", onDragOver);
- };
- }, [toolMode, wallItems, selectedItem, camera, selectedVersion?.versionId]);
+// return () => {
+// canvasElement.removeEventListener("mousedown", onMouseDown);
+// canvasElement.removeEventListener("mouseup", onMouseUp);
+// canvasElement.removeEventListener("mousemove", onMouseMove);
+// canvasElement.removeEventListener("drop", onDrop);
+// canvasElement.removeEventListener("dragover", onDragOver);
+// };
+// }, [toolMode, wallItems, selectedItem, camera, selectedVersion?.versionId]);
- useEffect(() => {
- if (toolMode && activeModule === "builder") {
- handleMeshMissed(
- currentWallItem,
- setSelectedWallItem,
- setSelectedItemsIndex
- );
- setSelectedWallItem(null);
- setSelectedItemsIndex(null);
- }
- }, [toolMode]);
+// useEffect(() => {
+// if (toolMode && activeModule === "builder") {
+// handleMeshMissed(
+// currentWallItem,
+// setSelectedWallItem,
+// setSelectedItemsIndex
+// );
+// setSelectedWallItem(null);
+// setSelectedItemsIndex(null);
+// }
+// }, [toolMode]);
- return (
- <>
- {wallItems.map((item: Types.WallItem, index: number) => (
-
-
-
- ))}
- >
- );
-};
+// return (
+// <>
+// {wallItems.map((item: Types.WallItem, index: number) => (
+//
+//
+//
+// ))}
+// >
+// );
+// };
-export default WallItemsGroup;
+// export default WallItemsGroup;
diff --git a/app/src/modules/builder/groups/wallsAndWallItems.tsx b/app/src/modules/builder/groups/wallsAndWallItems.tsx
index d4d52ec..6961cf6 100644
--- a/app/src/modules/builder/groups/wallsAndWallItems.tsx
+++ b/app/src/modules/builder/groups/wallsAndWallItems.tsx
@@ -1,74 +1,74 @@
-import { Geometry } from "@react-three/csg";
-import {
- useSelectedWallItem,
- useToggleView,
- useToolMode,
- useWallItems,
- useWalls,
-} from "../../../store/builder/store";
-import handleMeshDown from "../eventFunctions/handleMeshDown";
-import handleMeshMissed from "../eventFunctions/handleMeshMissed";
-import WallsMesh from "./wallsMesh";
-import WallItemsGroup from "./wallItemsGroup";
+// import { Geometry } from "@react-three/csg";
+// import {
+// useSelectedWallItem,
+// useToggleView,
+// useToolMode,
+// useWallItems,
+// useWalls,
+// } from "../../../store/builder/store";
+// import handleMeshDown from "../eventFunctions/handleMeshDown";
+// import handleMeshMissed from "../eventFunctions/handleMeshMissed";
+// import WallsMesh from "./wallsMesh";
+// import WallItemsGroup from "./wallItemsGroup";
-const WallsAndWallItems = ({
- CSGGroup,
- setSelectedItemsIndex,
- selectedItemsIndex,
- currentWallItem,
- csg,
- lines,
- hoveredDeletableWallItem,
-}: any) => {
- const { walls } = useWalls();
- const { wallItems } = useWallItems();
- const { toggleView } = useToggleView();
- const { toolMode } = useToolMode();
- const { setSelectedWallItem } = useSelectedWallItem();
+// const WallsAndWallItems = ({
+// CSGGroup,
+// setSelectedItemsIndex,
+// selectedItemsIndex,
+// currentWallItem,
+// csg,
+// lines,
+// hoveredDeletableWallItem,
+// }: any) => {
+// const { walls } = useWalls();
+// const { wallItems } = useWallItems();
+// const { toggleView } = useToggleView();
+// const { toolMode } = useToolMode();
+// const { setSelectedWallItem } = useSelectedWallItem();
- return (
- {
- if (toolMode === "cursor") {
- handleMeshDown(
- event,
- currentWallItem,
- setSelectedWallItem,
- setSelectedItemsIndex,
- wallItems,
- toggleView
- );
- }
- }}
- onPointerMissed={() => {
- if (toolMode === "cursor") {
- handleMeshMissed(
- currentWallItem,
- setSelectedWallItem,
- setSelectedItemsIndex
- );
- setSelectedWallItem(null);
- setSelectedItemsIndex(null);
- }
- }}
- >
-
-
-
-
-
- );
-};
+// return (
+// {
+// if (toolMode === "cursor") {
+// handleMeshDown(
+// event,
+// currentWallItem,
+// setSelectedWallItem,
+// setSelectedItemsIndex,
+// wallItems,
+// toggleView
+// );
+// }
+// }}
+// onPointerMissed={() => {
+// if (toolMode === "cursor") {
+// handleMeshMissed(
+// currentWallItem,
+// setSelectedWallItem,
+// setSelectedItemsIndex
+// );
+// setSelectedWallItem(null);
+// setSelectedItemsIndex(null);
+// }
+// }}
+// >
+//
+//
+//
+//
+//
+// );
+// };
-export default WallsAndWallItems;
+// export default WallsAndWallItems;
diff --git a/app/src/modules/builder/groups/wallsMesh.tsx b/app/src/modules/builder/groups/wallsMesh.tsx
index 6b22a8d..80468e5 100644
--- a/app/src/modules/builder/groups/wallsMesh.tsx
+++ b/app/src/modules/builder/groups/wallsMesh.tsx
@@ -1,82 +1,82 @@
-import * as THREE from "three";
-import * as Types from "../../../types/world/worldTypes";
-import * as CONSTANTS from "../../../types/world/worldConstants";
-import { Base } from "@react-three/csg";
-import { MeshDiscardMaterial } from "@react-three/drei";
-import { useUpdateScene, useWalls } from "../../../store/builder/store";
-import React, { useEffect } from "react";
-import { getLines } from "../../../services/factoryBuilder/lines/getLinesApi";
-import objectLinesToArray from "../geomentries/lines/lineConvertions/objectLinesToArray";
-import loadWalls from "../geomentries/walls/loadWalls";
-import texturePath from "../../../assets/textures/floor/wall-tex.png";
-import { useParams } from "react-router-dom";
-import { getUserData } from "../../../functions/getUserData";
-import { useVersionContext } from "../version/versionContext";
+// import * as THREE from "three";
+// import * as Types from "../../../types/world/worldTypes";
+// import * as CONSTANTS from "../../../types/world/worldConstants";
+// import { Base } from "@react-three/csg";
+// import { MeshDiscardMaterial } from "@react-three/drei";
+// import { useUpdateScene, useWalls } from "../../../store/builder/store";
+// import React, { useEffect } from "react";
+// import { getLines } from "../../../services/factoryBuilder/lines/getLinesApi";
+// import objectLinesToArray from "../geomentries/lines/lineConvertions/objectLinesToArray";
+// import loadWalls from "../geomentries/walls/loadWalls";
+// import texturePath from "../../../assets/textures/floor/wall-tex.png";
+// import { useParams } from "react-router-dom";
+// import { getUserData } from "../../../functions/getUserData";
+// import { useVersionContext } from "../version/versionContext";
-const WallsMeshComponent = ({ lines }: any) => {
- const { walls, setWalls } = useWalls();
- const { updateScene, setUpdateScene } = useUpdateScene();
- const { projectId } = useParams();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { organization } = getUserData();
+// const WallsMeshComponent = ({ lines }: any) => {
+// const { walls, setWalls } = useWalls();
+// const { updateScene, setUpdateScene } = useUpdateScene();
+// const { projectId } = useParams();
+// const { selectedVersionStore } = useVersionContext();
+// const { selectedVersion } = selectedVersionStore();
+// const { organization } = getUserData();
- useEffect(() => {
- if (updateScene) {
- if (!selectedVersion) {
- setUpdateScene(false);
- return;
- };
- getLines(organization, projectId, selectedVersion?.versionId || '').then((data) => {
- const Lines: Types.Lines = objectLinesToArray(data);
- localStorage.setItem("Lines", JSON.stringify(Lines));
+// useEffect(() => {
+// if (updateScene) {
+// if (!selectedVersion) {
+// setUpdateScene(false);
+// return;
+// };
+// getLines(organization, projectId, selectedVersion?.versionId || '').then((data) => {
+// const Lines: Types.Lines = objectLinesToArray(data);
+// localStorage.setItem("Lines", JSON.stringify(Lines));
- if (Lines) {
- loadWalls(lines, setWalls);
- }
- });
- setUpdateScene(false);
- }
- }, [updateScene, selectedVersion?.versionId]);
+// if (Lines) {
+// loadWalls(lines, setWalls);
+// }
+// });
+// setUpdateScene(false);
+// }
+// }, [updateScene, selectedVersion?.versionId]);
- const textureLoader = new THREE.TextureLoader();
- const wallTexture = textureLoader.load(texturePath);
+// const textureLoader = new THREE.TextureLoader();
+// const wallTexture = textureLoader.load(texturePath);
- wallTexture.wrapS = wallTexture.wrapT = THREE.RepeatWrapping;
- wallTexture.repeat.set(0.1, 0.1);
- wallTexture.colorSpace = THREE.SRGBColorSpace;
+// wallTexture.wrapS = wallTexture.wrapT = THREE.RepeatWrapping;
+// wallTexture.repeat.set(0.1, 0.1);
+// wallTexture.colorSpace = THREE.SRGBColorSpace;
- return (
- <>
- {walls.map((wall: Types.Wall, index: number) => (
-
-
-
-
-
-
-
-
- ))}
- >
- );
-};
+// return (
+// <>
+// {walls.map((wall: Types.Wall, index: number) => (
+//
+//
+//
+//
+//
+//
+//
+//
+// ))}
+// >
+// );
+// };
-const WallsMesh = React.memo(WallsMeshComponent);
-export default WallsMesh;
+// const WallsMesh = React.memo(WallsMeshComponent);
+// export default WallsMesh;
diff --git a/app/src/modules/builder/groups/zoneGroup.tsx b/app/src/modules/builder/groups/zoneGroup.tsx
deleted file mode 100644
index 24f6ee4..0000000
--- a/app/src/modules/builder/groups/zoneGroup.tsx
+++ /dev/null
@@ -1,651 +0,0 @@
-import React, { useState, useEffect, useMemo, useRef } from "react";
-import { Html, Line, Sphere } from "@react-three/drei";
-import { useThree, useFrame } from "@react-three/fiber";
-import * as THREE from "three";
-import {
- useActiveLayer,
- useSocketStore,
- useToggleView,
- useToolMode,
- useRemovedLayer,
- useZones,
- useZonePoints,
-} from "../../../store/builder/store";
-import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi";
-
-import * as CONSTANTS from "../../../types/world/worldConstants";
-import * as turf from "@turf/turf";
-import { computeArea } from "../functions/computeArea";
-import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore";
-import { useParams } from "react-router-dom";
-import { getUserData } from "../../../functions/getUserData";
-import { useVersionContext } from "../version/versionContext";
-
-const ZoneGroup: React.FC = () => {
- const { camera, pointer, gl, raycaster, scene, controls } = useThree();
- const [startPoint, setStartPoint] = useState(null);
- const [endPoint, setEndPoint] = useState(null);
- const { zones, setZones } = useZones();
- const { zonePoints, setZonePoints } = useZonePoints();
- const [isDragging, setIsDragging] = useState(false);
- const { selectedZone } = useSelectedZoneStore();
- const [draggedSphere, setDraggedSphere] = useState(null);
- const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
- const { toggleView } = useToggleView();
- const { removedLayer, setRemovedLayer } = useRemovedLayer();
- const { toolMode } = useToolMode();
- const { activeLayer } = useActiveLayer();
- const { socket } = useSocketStore();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { projectId } = useParams();
- const { userId, organization } = getUserData();
-
- const groupsRef = useRef();
-
- const zoneMaterial = useMemo(
- () =>
- new THREE.ShaderMaterial({
- side: THREE.DoubleSide,
- vertexShader: `
- varying vec2 vUv;
- void main(){
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
- vUv = uv;
- }
- `,
- fragmentShader: `
- varying vec2 vUv;
- uniform vec3 uOuterColor;
- void main(){
- float alpha = 1.0 - vUv.y;
- gl_FragColor = vec4(uOuterColor, alpha);
- }
- `,
- uniforms: {
- uOuterColor: { value: new THREE.Color(CONSTANTS.zoneConfig.color) },
- },
- transparent: true,
- depthWrite: false,
- }),
- []
- );
-
- useEffect(() => {
- if (!selectedVersion) return;
- getZonesApi(organization, projectId, selectedVersion?.versionId || '').then((data) => {
- if (data && data.length > 0) {
- const fetchedZones = data.map((zone: any) => ({
- zoneUuid: zone.zoneUuid,
- zoneName: zone.zoneName,
- points: zone.points,
- viewPortCenter: zone.viewPortCenter,
- viewPortposition: zone.viewPortposition,
- layer: zone.layer,
- }));
-
- setZones(fetchedZones);
-
- const fetchedPoints = data.flatMap((zone: any) =>
- zone.points.slice(0, 4).map((point: [number, number, number]) => new THREE.Vector3(...point))
- );
-
- setZonePoints(fetchedPoints);
- } else {
- setZones([]);
- }
- }).catch((err) => {
- console.error(err);
- })
- }, [selectedVersion?.versionId]);
-
- useEffect(() => {
- localStorage.setItem("zones", JSON.stringify(zones));
- }, [zones]);
-
- useEffect(() => {
- if (removedLayer) {
- const updatedZones = zones.filter((zone: any) => zone.layer !== removedLayer);
- setZones(updatedZones);
-
- const updatedzonePoints = zonePoints.filter((_: any, index: any) => {
- const zoneIndex = Math.floor(index / 4);
- return zones[zoneIndex]?.layer !== removedLayer;
- });
- setZonePoints(updatedzonePoints);
-
- zones.filter((zone: any) => zone.layer === removedLayer).forEach((zone: any) => { deleteZoneFromBackend(zone.zoneUuid); });
-
- setRemovedLayer(null);
- }
- }, [removedLayer]);
-
- useEffect(() => {
- if (toolMode !== "Zone") {
- setStartPoint(null);
- setEndPoint(null);
- }
- if (!toggleView) {
- setStartPoint(null);
- setEndPoint(null);
- }
- }, [toolMode, toggleView]);
-
- // eslint-disable-next-line react-hooks/exhaustive-deps
- const addZoneToBackend = async (zone: {
- zoneUuid: string;
- zoneName: string;
- points: [number, number, number][];
- layer: string;
- }) => {
-
- const calculateCenter = (points: number[][]) => {
- if (!points || points.length === 0) return null;
-
- let sumX = 0, sumY = 0, sumZ = 0;
- const numPoints = points.length;
-
- points.forEach(([x, y, z]) => {
- sumX += x;
- sumY += y;
- sumZ += z;
- });
-
- return [sumX / numPoints, sumY / numPoints, sumZ / numPoints] as [
- number,
- number,
- number
- ];
- };
-
- const target: [number, number, number] | null = calculateCenter(zone.points);
- if (!target || zone.points.length < 4) return;
- const position = [target[0], 10, target[2]];
-
- const input = {
- userId: userId,
- versionId: selectedVersion?.versionId || '',
- projectId,
- organization,
- zoneData: {
- zoneName: zone.zoneName,
- zoneUuid: zone.zoneUuid,
- points: zone.points,
- viewPortCenter: target,
- viewPortposition: position,
- layer: zone.layer,
- },
- };
-
- socket.emit("v1:zone:set", input);
- };
-
- // eslint-disable-next-line react-hooks/exhaustive-deps
- const updateZoneToBackend = async (zone: {
- zoneUuid: string;
- zoneName: string;
- points: [number, number, number][];
- layer: string;
- }) => {
-
- const calculateCenter = (points: number[][]) => {
- if (!points || points.length === 0) return null;
-
- let sumX = 0, sumY = 0, sumZ = 0;
- const numPoints = points.length;
-
- points.forEach(([x, y, z]) => {
- sumX += x;
- sumY += y;
- sumZ += z;
- });
-
- return [sumX / numPoints, sumY / numPoints, sumZ / numPoints] as [
- number,
- number,
- number
- ];
- };
-
- const target: [number, number, number] | null = calculateCenter(zone.points);
- if (!target || zone.points.length < 4) return;
- const position = [target[0], 10, target[2]];
-
- const input = {
- userId: userId,
- versionId: selectedVersion?.versionId || '',
- projectId,
- organization,
- zoneData: {
- zoneName: zone.zoneName,
- zoneUuid: zone.zoneUuid,
- points: zone.points,
- viewPortCenter: target,
- viewPortposition: position,
- layer: zone.layer,
- },
- };
-
- socket.emit("v1:zone:set", input);
- };
-
- const deleteZoneFromBackend = async (zoneUuid: string) => {
-
- const input = {
- userId: userId,
- versionId: selectedVersion?.versionId || '',
- projectId,
- organization,
- zoneUuid: zoneUuid,
- };
-
- socket.emit("v1:zone:delete", input);
- };
-
- // eslint-disable-next-line react-hooks/exhaustive-deps
- const handleDeleteZone = (zoneUuid: string) => {
- const updatedZones = zones.filter((zone: any) => zone.zoneUuid !== zoneUuid);
- setZones(updatedZones);
-
- const zoneIndex = zones.findIndex((zone: any) => zone.zoneUuid === zoneUuid);
- if (zoneIndex !== -1) {
- const zonePointsToRemove = zonePoints.slice(zoneIndex * 4, zoneIndex * 4 + 4);
- zonePointsToRemove.forEach((point: any) => groupsRef.current.remove(point));
- const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4);
- setZonePoints(updatedzonePoints);
- }
- deleteZoneFromBackend(zoneUuid);
- };
-
- useEffect(() => {
- if (!camera || !toggleView) return;
- const canvasElement = gl.domElement;
-
- let drag = false;
- let isLeftMouseDown = false;
-
- const onMouseDown = (evt: any) => {
- if (evt.button === 0) {
- isLeftMouseDown = true;
- drag = false;
-
- raycaster.setFromCamera(pointer, camera);
- const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
-
- if (intersects.length > 0 && toolMode === "move") {
- const clickedObject = intersects[0].object;
- const sphereIndex = zonePoints.findIndex((point: any) =>
- point.equals(clickedObject.position)
- );
- if (sphereIndex !== -1) {
- (controls as any).enabled = false;
- setDraggedSphere(zonePoints[sphereIndex]);
- setIsDragging(true);
- }
- }
- }
- };
-
- const onMouseUp = (evt: any) => {
- if (evt.button === 0 && !drag && !isDragging && toolMode === 'Zone') {
- isLeftMouseDown = false;
-
- if (!startPoint) {
- raycaster.setFromCamera(pointer, camera);
- const intersectionPoint = new THREE.Vector3();
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
- if (point) {
- setStartPoint(point);
- setEndPoint(null);
- }
- } else if (startPoint) {
- raycaster.setFromCamera(pointer, camera);
- const intersectionPoint = new THREE.Vector3();
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
- if (!point) return;
-
- const points = [
- [startPoint.x, 0.15, startPoint.z],
- [point.x, 0.15, startPoint.z],
- [point.x, 0.15, point.z],
- [startPoint.x, 0.15, point.z],
- [startPoint.x, 0.15, startPoint.z],
- ] as [number, number, number][];
-
- const zoneName = `Zone ${zones.length + 1}`;
- const zoneUuid = THREE.MathUtils.generateUUID();
- const newZone = {
- zoneUuid,
- zoneName,
- points: points,
- layer: activeLayer,
- };
-
- const newZones = [...zones, newZone];
-
- setZones(newZones);
-
- const newzonePoints = [
- new THREE.Vector3(startPoint.x, 0.15, startPoint.z),
- new THREE.Vector3(point.x, 0.15, startPoint.z),
- new THREE.Vector3(point.x, 0.15, point.z),
- new THREE.Vector3(startPoint.x, 0.15, point.z),
- ];
-
- const updatedZonePoints = [...zonePoints, ...newzonePoints];
- setZonePoints(updatedZonePoints);
-
- addZoneToBackend(newZone);
- setStartPoint(null);
- setEndPoint(null);
- }
- } else if (evt.button === 0 && !drag && !isDragging && toolMode === '2D-Delete') {
- raycaster.setFromCamera(pointer, camera);
- const intersects = raycaster.intersectObjects(
- groupsRef.current.children,
- true
- );
-
- if (intersects.length > 0) {
- const clickedObject = intersects[0].object;
-
- const sphereIndex = zonePoints.findIndex((point: any) =>
- point.equals(clickedObject.position)
- );
- if (sphereIndex !== -1) {
- const zoneIndex = Math.floor(sphereIndex / 4);
- const zoneUuid = zones[zoneIndex].zoneUuid;
- handleDeleteZone(zoneUuid);
- return;
- }
- }
- }
-
- if (evt.button === 0) {
- if (isDragging && draggedSphere) {
- setIsDragging(false);
- setDraggedSphere(null);
-
- const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere);
- if (sphereIndex !== -1) {
- const zoneIndex = Math.floor(sphereIndex / 4);
-
- if (zoneIndex !== -1 && zones[zoneIndex]) {
- updateZoneToBackend(zones[zoneIndex]);
- }
- }
- }
- }
- };
-
- const onMouseMove = () => {
- if (!groupsRef.current) return;
- if (isLeftMouseDown) {
- drag = true;
- }
- raycaster.setFromCamera(pointer, camera);
-
- if (isDragging && draggedSphere) {
- raycaster.setFromCamera(pointer, camera);
- const intersectionPoint = new THREE.Vector3();
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
- if (point) {
- draggedSphere.set(point.x, 0.15, point.z);
-
- const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere);
- if (sphereIndex !== -1) {
- const zoneIndex = Math.floor(sphereIndex / 4);
- const cornerIndex = sphereIndex % 4;
-
- const updatedZones = zones.map((zone: any, index: number) => {
- if (index === zoneIndex) {
- const updatedPoints = [...zone.points];
- updatedPoints[cornerIndex] = [point.x, 0.15, point.z];
- updatedPoints[4] = updatedPoints[0];
- return { ...zone, points: updatedPoints };
- }
- return zone;
- });
-
- setZones(updatedZones);
- }
- }
- }
- };
-
- const onContext = (event: any) => {
- event.preventDefault();
- setStartPoint(null);
- setEndPoint(null);
- };
-
- if (toolMode === "Zone" || toolMode === '2D-Delete' || toolMode === "move") {
- canvasElement.addEventListener("mousedown", onMouseDown);
- canvasElement.addEventListener("mouseup", onMouseUp);
- canvasElement.addEventListener("mousemove", onMouseMove);
- canvasElement.addEventListener("contextmenu", onContext);
- }
- return () => {
- canvasElement.removeEventListener("mousedown", onMouseDown);
- canvasElement.removeEventListener("mouseup", onMouseUp);
- canvasElement.removeEventListener("mousemove", onMouseMove);
- canvasElement.removeEventListener("contextmenu", onContext);
- };
- }, [gl, camera, startPoint, toggleView, scene, toolMode, zones, isDragging, zonePoints, draggedSphere, activeLayer, raycaster, pointer, controls, plane, setZones, setZonePoints, addZoneToBackend, handleDeleteZone, updateZoneToBackend, selectedVersion?.versionId]);
-
- useFrame(() => {
- if (!startPoint) return;
- raycaster.setFromCamera(pointer, camera);
- const intersectionPoint = new THREE.Vector3();
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
- if (point) {
- setEndPoint(point);
- }
- });
-
- return (
-
-
- {zones.map((zone: any) => (
-
- {zone.points
- .slice(0, -1)
- .map((point: [number, number, number], index: number) => {
- const nextPoint = zone.points[index + 1];
-
- const point1 = new THREE.Vector3(point[0], point[1], point[2]);
- const point2 = new THREE.Vector3(
- nextPoint[0],
- nextPoint[1],
- nextPoint[2]
- );
-
- const planeWidth = point1.distanceTo(point2);
- const planeHeight = CONSTANTS.zoneConfig.height;
-
- const midpoint = new THREE.Vector3(
- (point1.x + point2.x) / 2,
- CONSTANTS.zoneConfig.height / 2 +
- (zone.layer - 1) * CONSTANTS.zoneConfig.height,
- (point1.z + point2.z) / 2
- );
-
- const angle = Math.atan2(
- point2.z - point1.z,
- point2.x - point1.x
- );
-
- return (
-
-
-
-
- );
- })}
- {!toggleView &&
- (() => {
- const points3D = zone.points || [];
- const coords2D = points3D.map((p: any) => [p[0], p[2]]);
-
- // Ensure the polygon is closed
- if (
- coords2D.length >= 4 &&
- (coords2D[0][0] !== coords2D[coords2D.length - 1][0] ||
- coords2D[0][1] !== coords2D[coords2D.length - 1][1])
- ) {
- coords2D.push(coords2D[0]);
- }
- if (coords2D.length < 4) return null;
-
- const polygon = turf.polygon([coords2D]);
- const center2D = turf.center(polygon).geometry.coordinates;
-
- // Calculate the average Y value
- const sumY = points3D.reduce(
- (sum: number, p: any) => sum + p[1],
- 0
- );
- const avgY = points3D.length > 0 ? sumY / points3D.length : 0;
-
- const htmlPosition: [number, number, number] = [
- center2D[0],
- avgY + (CONSTANTS.zoneConfig.height || 0) + 1.5,
- center2D[1],
- ];
-
- return (
-
- {zone.zoneName}
-
- );
- })()}
-
- ))}
-
-
- {zones
- .filter((zone: any) => zone.layer === activeLayer)
- .map((zone: any) => (
- {
- e.stopPropagation();
- if (toolMode === '2D-Delete') {
- handleDeleteZone(zone.zoneUuid);
- }
- }}
- />
- ))}
-
-
- {zones.map((zone: any, index: any) => {
- if (!toggleView) return null;
- const points3D = zone.points;
- const coords2D = points3D.map((p: any) => [p[0], p[2]]);
-
- if (
- coords2D.length < 4 ||
- coords2D[0][0] !== coords2D[coords2D.length - 1][0] ||
- coords2D[0][1] !== coords2D[coords2D.length - 1][1]
- ) {
- coords2D.push(coords2D[0]);
- }
- if (coords2D.length < 4) return null;
-
- const polygon = turf.polygon([coords2D]);
- const center2D = turf.center(polygon).geometry.coordinates;
-
- const sumY = points3D.reduce((sum: number, p: any) => sum + p[1], 0);
- const avgY = sumY / points3D.length;
-
- const area = computeArea(points3D, "zone");
- const formattedArea = `${area.toFixed(2)} m²`;
-
- const htmlPosition: [number, number, number] = [
- center2D[0],
- avgY + CONSTANTS.zoneConfig.height,
- center2D[1],
- ];
- return (
-
-
- {zone.zoneName} ({formattedArea})
-
-
- );
- })}
-
-
-
- {zones
- .filter((zone: any) => zone.layer === activeLayer)
- .flatMap((zone: any) =>
- zone.points.slice(0, 4).map((point: any, pointIndex: number) => (
-
-
-
- ))
- )}
-
-
- {startPoint && endPoint && (
-
- )}
-
-
- );
-};
-
-export default ZoneGroup;
diff --git a/app/src/modules/builder/geomentries/lines/getClosestIntersection.ts b/app/src/modules/builder/line/helpers/getClosestIntersection.ts
similarity index 96%
rename from app/src/modules/builder/geomentries/lines/getClosestIntersection.ts
rename to app/src/modules/builder/line/helpers/getClosestIntersection.ts
index afae9d5..e5a803d 100644
--- a/app/src/modules/builder/geomentries/lines/getClosestIntersection.ts
+++ b/app/src/modules/builder/line/helpers/getClosestIntersection.ts
@@ -1,26 +1,26 @@
-import * as THREE from 'three';
-
-import * as Types from "../../../../types/world/worldTypes";
-
-function getClosestIntersection(
- intersects: Types.Vector3Array,
- point: Types.Vector3
-): Types.Vector3 {
-
- ////////// A function that finds which point is closest from the intersects points that is given, Used in finding which point in a line is closest when clicked on a line during drawing //////////
-
- let closestNewPoint: THREE.Vector3 = point;
- let minDistance = Infinity;
-
- for (const intersect of intersects) {
- const distance = point.distanceTo(intersect);
- if (distance < minDistance) {
- minDistance = distance;
- closestNewPoint = intersect;
- }
- }
-
- return closestNewPoint;
-}
-
-export default getClosestIntersection;
+import * as THREE from 'three';
+
+import * as Types from "../../../../types/world/worldTypes";
+
+function getClosestIntersection(
+ intersects: Types.Vector3Array,
+ point: Types.Vector3
+): Types.Vector3 {
+
+ ////////// A function that finds which point is closest from the intersects points that is given, Used in finding which point in a line is closest when clicked on a line during drawing //////////
+
+ let closestNewPoint: THREE.Vector3 = point;
+ let minDistance = Infinity;
+
+ for (const intersect of intersects) {
+ const distance = point.distanceTo(intersect);
+ if (distance < minDistance) {
+ minDistance = distance;
+ closestNewPoint = intersect;
+ }
+ }
+
+ return closestNewPoint;
+}
+
+export default getClosestIntersection;
diff --git a/app/src/modules/builder/line/helpers/getClosestPointOnLineSegment.ts b/app/src/modules/builder/line/helpers/getClosestPointOnLineSegment.ts
new file mode 100644
index 0000000..8b65282
--- /dev/null
+++ b/app/src/modules/builder/line/helpers/getClosestPointOnLineSegment.ts
@@ -0,0 +1,12 @@
+import { Vector3 } from "three";
+
+export default function closestPointOnLineSegment(p: Vector3, a: Vector3, b: Vector3) {
+ const ab = new Vector3().subVectors(b, a);
+ const ap = new Vector3().subVectors(p, a);
+
+ const abLengthSq = ab.lengthSq();
+ const dot = ap.dot(ab);
+ const t = Math.max(0, Math.min(1, dot / abLengthSq));
+
+ return new Vector3().copy(a).add(ab.multiplyScalar(t));
+}
\ No newline at end of file
diff --git a/app/src/modules/builder/line/line.tsx b/app/src/modules/builder/line/line.tsx
index 19f0810..cc53b9d 100644
--- a/app/src/modules/builder/line/line.tsx
+++ b/app/src/modules/builder/line/line.tsx
@@ -2,10 +2,20 @@ import * as THREE from 'three';
import { useThree } from '@react-three/fiber';
import { useEffect, useMemo, useState } from "react";
import { DragControls, Tube } from '@react-three/drei';
-import { useToolMode } from '../../../store/builder/store';
+import { useSocketStore, useToolMode } from '../../../store/builder/store';
import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import { useSceneContext } from '../../scene/sceneContext';
import * as Constants from '../../../types/world/worldConstants';
+import { useVersionContext } from '../version/versionContext';
+import { useParams } from 'react-router-dom';
+import { getUserData } from '../../../functions/getUserData';
+
+// import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
+// import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
+// import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
+// import { deleteFloorApi } from '../../../services/factoryBuilder/floor/deleteFloorApi';
+// import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
+// import { upsertZoneApi } from '../../../services/factoryBuilder/zone/upsertZoneApi';
interface LineProps {
points: [Point, Point];
@@ -16,9 +26,16 @@ function Line({ points }: Readonly) {
const { raycaster, camera, pointer, gl } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const [isDeletable, setIsDeletable] = useState(false);
+ const { socket } = useSocketStore();
const { toolMode } = useToolMode();
- const { wallStore } = useSceneContext();
- const { removeWallByPoints, setPosition } = wallStore();
+ const { wallStore, floorStore, zoneStore } = useSceneContext();
+ const { removeWallByPoints, setPosition: setWallPosition, getWallsByPointId } = wallStore();
+ const { removeFloorByPoints, setPosition: setFloorPosition, getFloorsByPointId } = floorStore();
+ const { removeZoneByPoints, setPosition: setZonePosition, getZonesByPointId } = zoneStore();
+ const { userId, organization } = getUserData();
+ const { selectedVersionStore } = useVersionContext();
+ const { selectedVersion } = selectedVersionStore();
+ const { projectId } = useParams();
const [dragOffset, setDragOffset] = useState(null);
const { hoveredLine, setHoveredLine, hoveredPoint } = useBuilderStore();
@@ -79,9 +96,123 @@ function Line({ points }: Readonly) {
const handlePointClick = (points: [Point, Point]) => {
if (toolMode === '2D-Delete') {
if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
- removeWallByPoints(points);
+ const removedWall = removeWallByPoints(points);
+ if (removedWall && projectId) {
+
+ // API
+
+ // deleteWallApi(projectId, selectedVersion?.versionId || '', removedWall.wallUuid);
+
+ // SOCKET
+
+ const data = {
+ wallUuid: removedWall.wallUuid,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Wall:delete', data);
+ }
setHoveredLine(null);
}
+ if (points[0].pointType === 'Floor' && points[1].pointType === 'Floor') {
+ const { removedFloors, updatedFloors } = removeFloorByPoints(points);
+ 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);
+ }
+ });
+ }
+
+ setHoveredLine(null);
+ }
+ if (points[0].pointType === 'Zone' && points[1].pointType === 'Zone') {
+ const { removedZones, updatedZones } = removeZoneByPoints(points);
+ 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);
+ }
+ });
+ }
+ }
gl.domElement.style.cursor = 'default';
}
}
@@ -105,8 +236,18 @@ function Line({ points }: Readonly) {
const newStart = new THREE.Vector3().addVectors(start, delta);
const newEnd = new THREE.Vector3().addVectors(end, delta);
- setPosition(points[0].pointUuid, [newStart.x, newStart.y, newStart.z]);
- setPosition(points[1].pointUuid, [newEnd.x, newEnd.y, newEnd.z]);
+ if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
+ setWallPosition(points[0].pointUuid, [newStart.x, newStart.y, newStart.z]);
+ setWallPosition(points[1].pointUuid, [newEnd.x, newEnd.y, newEnd.z]);
+ }
+ if (points[0].pointType === 'Floor' && points[1].pointType === 'Floor') {
+ setFloorPosition(points[0].pointUuid, [newStart.x, newStart.y, newStart.z]);
+ setFloorPosition(points[1].pointUuid, [newEnd.x, newEnd.y, newEnd.z]);
+ }
+ if (points[0].pointType === 'Zone' && points[1].pointType === 'Zone') {
+ setZonePosition(points[0].pointUuid, [newStart.x, newStart.y, newStart.z]);
+ setZonePosition(points[1].pointUuid, [newEnd.x, newEnd.y, newEnd.z]);
+ }
}
}
};
@@ -127,11 +268,90 @@ function Line({ points }: Readonly) {
};
const handleDragEnd = (points: [Point, Point]) => {
+ if (toolMode !== 'move' || !dragOffset) return;
gl.domElement.style.cursor = 'default';
setDragOffset(null);
- if (toolMode !== 'move') return;
if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
- // console.log('Wall after drag: ', points);
+ const updatedWalls1 = getWallsByPointId(points[0].pointUuid);
+ const updatedWalls2 = getWallsByPointId(points[1].pointUuid);
+ const updatedWalls = [...updatedWalls1, ...updatedWalls2].filter((wall, index, self) => index === self.findIndex((w) => w.wallUuid === wall.wallUuid));
+
+ if (updatedWalls.length > 0 && projectId) {
+ updatedWalls.forEach(updatedWall => {
+
+ // API
+
+ // upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall).catch((error) => {
+ // console.error('Error updating wall:', error);
+ // });
+
+ // SOCKET
+
+ const data = {
+ wallData: updatedWall,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Wall:add', data);
+ })
+ }
+ } else if (points[0].pointType === 'Floor' && points[1].pointType === 'Floor') {
+ const updatedFloors1 = getFloorsByPointId(points[0].pointUuid);
+ const updatedFloors2 = getFloorsByPointId(points[1].pointUuid);
+ const updatedFloors = [...updatedFloors1, ...updatedFloors2].filter((floor, index, self) => index === self.findIndex((f) => f.floorUuid === floor.floorUuid));
+
+ if (updatedFloors.length > 0 && projectId) {
+ updatedFloors.forEach(updatedFloor => {
+
+ // API
+
+ // upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor).catch((error) => {
+ // console.error('Error updating floor:', error);
+ // });
+
+ // SOCKET
+
+ const data = {
+ floorData: updatedFloor,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Floor:add', data);
+ })
+ }
+ } else if (points[0].pointType === 'Zone' && points[1].pointType === 'Zone') {
+ const updatedZones1 = getZonesByPointId(points[0].pointUuid);
+ const updatedZones2 = getZonesByPointId(points[1].pointUuid);
+ const updatedZones = [...updatedZones1, ...updatedZones2].filter((zone, index, self) => index === self.findIndex((z) => z.zoneUuid === zone.zoneUuid));
+
+ if (updatedZones.length > 0 && projectId) {
+ updatedZones.forEach(updatedZone => {
+
+ // API
+
+ // upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone).catch((error) => {
+ // console.error('Error updating zone:', error);
+ // });
+
+ // SOCKET
+
+ const data = {
+ zoneData: updatedZone,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:zone:add', data);
+ })
+ }
}
}
diff --git a/app/src/modules/builder/pillars/addAndUpdateReferencePillar.ts b/app/src/modules/builder/pillars/addAndUpdateReferencePillar.ts
new file mode 100644
index 0000000..31407ee
--- /dev/null
+++ b/app/src/modules/builder/pillars/addAndUpdateReferencePillar.ts
@@ -0,0 +1,54 @@
+// import * as THREE from 'three';
+// import updateReferencePolesheight from './updateReferencePolesheight';
+
+// import * as Types from "../../../../types/world/worldTypes";
+
+// function addAndUpdateReferencePillar(
+// raycaster: THREE.Raycaster,
+// floorGroup: Types.RefGroup,
+// referencePole: Types.RefMesh
+// ): void {
+
+// ////////// Find Pillars position and scale based on the pointer interaction //////////
+
+// let Roofs = raycaster.intersectObjects(floorGroup.current.children, true);
+// const intersected = Roofs.find(intersect => intersect.object.name.includes("Roof") || intersect.object.name.includes("Floor"));
+
+// if (intersected) {
+// const intersectionPoint = intersected.point;
+// raycaster.ray.origin.copy(intersectionPoint);
+// raycaster.ray.direction.set(0, -1, 0);
+// const belowIntersections = raycaster.intersectObjects(floorGroup.current.children, true);
+// const validIntersections = belowIntersections.filter(intersect => intersect.object.name.includes("Floor"));
+
+// let distance: Types.Number;
+
+// if (validIntersections.length > 1) {
+// let valid = validIntersections.find(intersectedBelow => intersected.point.distanceTo(intersectedBelow.point) > 3);
+// if (valid) {
+// updateReferencePolesheight(intersectionPoint, valid.distance, referencePole, floorGroup);
+// } else {
+// const belowPoint = new THREE.Vector3(intersectionPoint.x, 0, intersectionPoint.z);
+// distance = intersected.point.distanceTo(belowPoint);
+// if (distance > 3) {
+// updateReferencePolesheight(intersectionPoint, distance, referencePole, floorGroup);
+// }
+// }
+// } else {
+// const belowPoint = new THREE.Vector3(intersectionPoint.x, 0, intersectionPoint.z);
+// distance = intersected.point.distanceTo(belowPoint);
+// if (distance > 3) {
+// updateReferencePolesheight(intersectionPoint, distance, referencePole, floorGroup);
+// }
+// }
+// } else {
+// if (referencePole.current) {
+// (referencePole.current.material).dispose();
+// (referencePole.current.geometry).dispose();
+// floorGroup.current.remove(referencePole.current);
+// referencePole.current = null;
+// }
+// }
+// }
+
+// export default addAndUpdateReferencePillar;
diff --git a/app/src/modules/builder/pillars/addPillar.ts b/app/src/modules/builder/pillars/addPillar.ts
new file mode 100644
index 0000000..9839f16
--- /dev/null
+++ b/app/src/modules/builder/pillars/addPillar.ts
@@ -0,0 +1,24 @@
+// import * as THREE from 'three';
+// import * as CONSTANTS from '../../../../types/world/worldConstants';
+// import * as Types from "../../../../types/world/worldTypes";
+
+// function addPillar(
+// referencePole: Types.RefMesh,
+// floorGroup: Types.RefGroup
+// ): void {
+
+// ////////// Add Pillars to the scene based on the reference. current poles position and scale //////////
+
+// if (referencePole.current) {
+// let pole: THREE.Mesh;
+// const geometry = referencePole.current.userData.geometry.clone();
+// const material = new THREE.MeshStandardMaterial({ color: CONSTANTS.columnConfig.defaultColor });
+// pole = new THREE.Mesh(geometry, material);
+// pole.rotateX(Math.PI / 2);
+// pole.name = "Pole";
+// pole.position.set(referencePole.current.userData.position.x, referencePole.current.userData.position.y, referencePole.current.userData.position.z);
+// floorGroup.current.add(pole);
+// }
+// }
+
+// export default addPillar;
\ No newline at end of file
diff --git a/app/src/modules/builder/pillars/deletableHoveredPillar.ts b/app/src/modules/builder/pillars/deletableHoveredPillar.ts
new file mode 100644
index 0000000..1751fdb
--- /dev/null
+++ b/app/src/modules/builder/pillars/deletableHoveredPillar.ts
@@ -0,0 +1,34 @@
+// import * as THREE from 'three';
+
+// import * as Types from "../../../../types/world/worldTypes";
+
+// function DeletableHoveredPillar(
+// state: Types.ThreeState,
+// floorGroup: Types.RefGroup,
+// hoveredDeletablePillar: Types.RefMesh
+// ): void {
+
+// ////////// Altering the color of the hovered Pillar during the Deletion time //////////
+
+// const intersects = state.raycaster.intersectObjects(floorGroup.current.children, true);
+// const poleIntersect = intersects.find(intersect => intersect.object.name === "Pole");
+
+// if (poleIntersect) {
+// if (poleIntersect.object.name !== "Pole") {
+// return;
+// }
+// if (hoveredDeletablePillar.current) {
+// (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("black");
+// hoveredDeletablePillar.current = undefined;
+// }
+// hoveredDeletablePillar.current = poleIntersect.object as THREE.Mesh; // Type assertion
+// (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("red");
+// } else {
+// if (hoveredDeletablePillar.current) {
+// (hoveredDeletablePillar.current.material as THREE.MeshStandardMaterial).emissive = new THREE.Color("black");
+// hoveredDeletablePillar.current = undefined;
+// }
+// }
+// }
+
+// export default DeletableHoveredPillar;
\ No newline at end of file
diff --git a/app/src/modules/builder/pillars/deletePillar.ts b/app/src/modules/builder/pillars/deletePillar.ts
new file mode 100644
index 0000000..22fc9bf
--- /dev/null
+++ b/app/src/modules/builder/pillars/deletePillar.ts
@@ -0,0 +1,21 @@
+// import { toast } from 'react-toastify';
+
+// import * as Types from "../../../../types/world/worldTypes";
+
+// function DeletePillar(
+// hoveredDeletablePillar: Types.RefMesh,
+// floorGroup: Types.RefGroup
+// ): void {
+
+// ////////// Deleting the hovered Pillar from the itemsGroup //////////
+
+// if (hoveredDeletablePillar.current) {
+// (hoveredDeletablePillar.current.material).dispose();
+// (hoveredDeletablePillar.current.geometry).dispose();
+// floorGroup.current.remove(hoveredDeletablePillar.current);
+// echo.success("Pillar Removed!");
+// hoveredDeletablePillar.current = undefined;
+// }
+// }
+
+// export default DeletePillar;
diff --git a/app/src/modules/builder/pillars/updateReferencePolesheight.ts b/app/src/modules/builder/pillars/updateReferencePolesheight.ts
new file mode 100644
index 0000000..eaffd76
--- /dev/null
+++ b/app/src/modules/builder/pillars/updateReferencePolesheight.ts
@@ -0,0 +1,40 @@
+// import * as THREE from 'three';
+
+// import * as Types from "../../../../types/world/worldTypes";
+
+// function updateReferencePolesheight(
+// intersectionPoint: Types.Vector3,
+// distance: Types.Number,
+// referencePole: Types.RefMesh,
+// floorGroup: Types.RefGroup
+// ): void {
+
+// ////////// Add a Reference Pillar and update its position and scale based on the pointer interaction //////////
+
+// if (referencePole.current) {
+// (referencePole.current.material).dispose();
+// (referencePole.current.geometry).dispose();
+// floorGroup.current.remove(referencePole.current);
+// referencePole.current.geometry.dispose();
+// }
+
+// const shape = new THREE.Shape();
+// shape.moveTo(0.5, 0);
+// shape.absarc(0, 0, 0.5, 0, 2 * Math.PI, false);
+
+// const extrudeSettings = {
+// depth: distance,
+// bevelEnabled: false,
+// };
+
+// const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
+// const material = new THREE.MeshBasicMaterial({ color: "green", transparent: true, opacity: 0.5 });
+// referencePole.current = new THREE.Mesh(geometry, material);
+// referencePole.current.rotateX(Math.PI / 2);
+// referencePole.current.position.set(intersectionPoint.x, intersectionPoint.y - 0.01, intersectionPoint.z);
+// referencePole.current.userData = { geometry: geometry, distance: distance, position: { x: intersectionPoint.x, y: intersectionPoint.y - 0.01, z: intersectionPoint.z } };
+
+// floorGroup.current.add(referencePole.current);
+// }
+
+// export default updateReferencePolesheight;
diff --git a/app/src/modules/builder/point/helpers/usePointSnapping.tsx b/app/src/modules/builder/point/helpers/usePointSnapping.tsx
index c7d31cc..648e4c5 100644
--- a/app/src/modules/builder/point/helpers/usePointSnapping.tsx
+++ b/app/src/modules/builder/point/helpers/usePointSnapping.tsx
@@ -11,9 +11,11 @@ const ANGLE_SNAP_DISTANCE_THRESHOLD = 0.5; // Distance threshold for snapping i
const CAN_ANGLE_SNAP = true; // Whether snapping is enabled or not
export const usePointSnapping = (currentPoint: { uuid: string, pointType: string, position: [number, number, number] } | null) => {
- const { aisleStore, wallStore } = useSceneContext();
+ const { aisleStore, wallStore, floorStore, zoneStore } = useSceneContext();
const { aisles, getConnectedPoints: getConnectedAislePoints } = aisleStore();
const { walls, getConnectedPoints: getConnectedWallPoints } = wallStore();
+ const { floors, getConnectedPoints: getConnectedFloorPoints } = floorStore();
+ const { zones, getConnectedPoints: getConnectedZonePoints } = zoneStore();
// Wall Snapping
@@ -24,10 +26,13 @@ export const usePointSnapping = (currentPoint: { uuid: string, pointType: string
);
}, [walls, currentPoint]);
- const snapWallPoint = useCallback((position: [number, number, number]) => {
+ const snapWallPoint = useCallback((position: [number, number, number], tempPoints?: Point) => {
if (!currentPoint || !CAN_POINT_SNAP) return { position: position, isSnapped: false, snappedPoint: null };
const otherPoints = getAllOtherWallPoints();
+ if (tempPoints) {
+ otherPoints.push(tempPoints);
+ }
const currentVec = new THREE.Vector3(...position);
for (const point of otherPoints) {
const pointVec = new THREE.Vector3(...point.position);
@@ -187,10 +192,188 @@ export const usePointSnapping = (currentPoint: { uuid: string, pointType: string
};
}, [currentPoint, getConnectedAislePoints]);
+ // Floor Snapping
+
+ const getAllOtherFloorPoints = useCallback(() => {
+ if (!currentPoint) return [];
+
+ return floors.flatMap(floor =>
+ floor.points.filter(point => point.pointUuid !== currentPoint.uuid)
+ );
+ }, [floors, currentPoint]);
+
+ const snapFloorPoint = useCallback((position: [number, number, number], tempPoints?: Point[] | []) => {
+ if (!currentPoint || !CAN_POINT_SNAP) return { position: position, isSnapped: false, snappedPoint: null };
+
+ let otherPoints = getAllOtherFloorPoints();
+ if (tempPoints) {
+ otherPoints = [...otherPoints, ...tempPoints];
+ }
+ const currentVec = new THREE.Vector3(...position);
+
+ for (const point of otherPoints) {
+ const pointVec = new THREE.Vector3(...point.position);
+ const distance = currentVec.distanceTo(pointVec);
+
+ if (distance <= POINT_SNAP_THRESHOLD && currentPoint.pointType === 'Floor') {
+ return { position: point.position, isSnapped: true, snappedPoint: point };
+ }
+ }
+
+ return { position: position, isSnapped: false, snappedPoint: null };
+ }, [currentPoint, getAllOtherFloorPoints]);
+
+ const snapFloorAngle = useCallback((newPosition: [number, number, number]): {
+ position: [number, number, number],
+ isSnapped: boolean,
+ snapSources: THREE.Vector3[]
+ } => {
+ if (!currentPoint || !CAN_ANGLE_SNAP) return { position: newPosition, isSnapped: false, snapSources: [] };
+
+ const connectedPoints = getConnectedFloorPoints(currentPoint.uuid);
+ if (connectedPoints.length === 0) {
+ return { position: newPosition, isSnapped: false, snapSources: [] };
+ }
+
+ const newPos = new THREE.Vector3(...newPosition);
+ let closestX: { pos: THREE.Vector3, dist: number } | null = null;
+ let closestZ: { pos: THREE.Vector3, dist: number } | null = null;
+
+ for (const connectedPoint of connectedPoints) {
+ const cPos = new THREE.Vector3(...connectedPoint.position);
+ const xDist = Math.abs(newPos.x - cPos.x);
+ const zDist = Math.abs(newPos.z - cPos.z);
+
+ if (xDist < ANGLE_SNAP_DISTANCE_THRESHOLD) {
+ if (!closestX || xDist < closestX.dist) {
+ closestX = { pos: cPos, dist: xDist };
+ }
+ }
+
+ if (zDist < ANGLE_SNAP_DISTANCE_THRESHOLD) {
+ if (!closestZ || zDist < closestZ.dist) {
+ closestZ = { pos: cPos, dist: zDist };
+ }
+ }
+ }
+
+ const snappedPos = newPos.clone();
+ const snapSources: THREE.Vector3[] = [];
+
+ if (closestX) {
+ snappedPos.x = closestX.pos.x;
+ snapSources.push(closestX.pos.clone());
+ }
+
+ if (closestZ) {
+ snappedPos.z = closestZ.pos.z;
+ snapSources.push(closestZ.pos.clone());
+ }
+
+ const isSnapped = snapSources.length > 0;
+
+ return {
+ position: [snappedPos.x, snappedPos.y, snappedPos.z],
+ isSnapped,
+ snapSources
+ };
+ }, [currentPoint, getConnectedFloorPoints]);
+
+ // Zone Snapping
+
+ const getAllOtherZonePoints = useCallback(() => {
+ if (!currentPoint) return [];
+
+ return zones.flatMap(zone =>
+ zone.points.filter(point => point.pointUuid !== currentPoint.uuid)
+ );
+ }, [zones, currentPoint]);
+
+ const snapZonePoint = useCallback((position: [number, number, number], tempPoints?: Point[] | []) => {
+ if (!currentPoint || !CAN_POINT_SNAP) return { position: position, isSnapped: false, snappedPoint: null };
+
+ let otherPoints = getAllOtherZonePoints();
+ if (tempPoints) {
+ otherPoints = [...otherPoints, ...tempPoints];
+ }
+ const currentVec = new THREE.Vector3(...position);
+
+ for (const point of otherPoints) {
+ const pointVec = new THREE.Vector3(...point.position);
+ const distance = currentVec.distanceTo(pointVec);
+
+ if (distance <= POINT_SNAP_THRESHOLD && currentPoint.pointType === 'Zone') {
+ return { position: point.position, isSnapped: true, snappedPoint: point };
+ }
+ }
+
+ return { position: position, isSnapped: false, snappedPoint: null };
+ }, [currentPoint, getAllOtherZonePoints]);
+
+ const snapZoneAngle = useCallback((newPosition: [number, number, number]): {
+ position: [number, number, number],
+ isSnapped: boolean,
+ snapSources: THREE.Vector3[]
+ } => {
+ if (!currentPoint || !CAN_ANGLE_SNAP) return { position: newPosition, isSnapped: false, snapSources: [] };
+
+ const connectedPoints = getConnectedZonePoints(currentPoint.uuid);
+ if (connectedPoints.length === 0) {
+ return { position: newPosition, isSnapped: false, snapSources: [] };
+ }
+
+ const newPos = new THREE.Vector3(...newPosition);
+ let closestX: { pos: THREE.Vector3, dist: number } | null = null;
+ let closestZ: { pos: THREE.Vector3, dist: number } | null = null;
+
+ for (const connectedPoint of connectedPoints) {
+ const cPos = new THREE.Vector3(...connectedPoint.position);
+ const xDist = Math.abs(newPos.x - cPos.x);
+ const zDist = Math.abs(newPos.z - cPos.z);
+
+ if (xDist < ANGLE_SNAP_DISTANCE_THRESHOLD) {
+ if (!closestX || xDist < closestX.dist) {
+ closestX = { pos: cPos, dist: xDist };
+ }
+ }
+
+ if (zDist < ANGLE_SNAP_DISTANCE_THRESHOLD) {
+ if (!closestZ || zDist < closestZ.dist) {
+ closestZ = { pos: cPos, dist: zDist };
+ }
+ }
+ }
+
+ const snappedPos = newPos.clone();
+ const snapSources: THREE.Vector3[] = [];
+
+ if (closestX) {
+ snappedPos.x = closestX.pos.x;
+ snapSources.push(closestX.pos.clone());
+ }
+
+ if (closestZ) {
+ snappedPos.z = closestZ.pos.z;
+ snapSources.push(closestZ.pos.clone());
+ }
+
+ const isSnapped = snapSources.length > 0;
+
+ return {
+ position: [snappedPos.x, snappedPos.y, snappedPos.z],
+ isSnapped,
+ snapSources
+ };
+ }, [currentPoint, getConnectedZonePoints]);
+
return {
snapAislePoint,
snapAisleAngle,
snapWallPoint,
snapWallAngle,
+ snapFloorPoint,
+ snapFloorAngle,
+ snapZonePoint,
+ snapZoneAngle,
};
};
\ No newline at end of file
diff --git a/app/src/modules/builder/point/point.tsx b/app/src/modules/builder/point/point.tsx
index a671806..15777aa 100644
--- a/app/src/modules/builder/point/point.tsx
+++ b/app/src/modules/builder/point/point.tsx
@@ -1,29 +1,42 @@
import * as THREE from 'three';
import * as Constants from '../../../types/world/worldConstants';
import { useRef, useState, useEffect, useMemo } from 'react';
-import { useToolMode } from '../../../store/builder/store';
+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 { usePointSnapping } from './helpers/usePointSnapping';
-import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi';
import { useParams } from 'react-router-dom';
-import { createAisleApi } from '../../../services/factoryBuilder/aisle/createAisleApi';
import { useVersionContext } from '../version/versionContext';
import { useSceneContext } from '../../scene/sceneContext';
+import { upsertAisleApi } from '../../../services/factoryBuilder/aisle/upsertAisleApi';
+import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi';
+// import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
+// import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
+// import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
+// import { deleteFloorApi } from '../../../services/factoryBuilder/floor/deleteFloorApi';
+// import { upsertZoneApi } from '../../../services/factoryBuilder/zone/upsertZoneApi';
+// import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
+
+import { getUserData } from '../../../functions/getUserData';
+
function Point({ point }: { readonly point: Point }) {
const materialRef = useRef(null);
const { raycaster, camera, pointer, gl } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const [isHovered, setIsHovered] = useState(false);
const [dragOffset, setDragOffset] = useState(null);
+ const { socket } = useSocketStore();
const { toolMode } = useToolMode();
- const { aisleStore, wallStore } = useSceneContext();
+ const { aisleStore, wallStore, floorStore, zoneStore } = useSceneContext();
const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore();
- const { setPosition: setWallPosition, removePoint: removeWallPoint } = wallStore();
- const { snapAislePoint, snapAisleAngle, snapWallPoint, snapWallAngle } = usePointSnapping({ uuid: point.pointUuid, pointType: point.pointType, position: point.position });
+ const { setPosition: setWallPosition, removePoint: removeWallPoint, getWallsByPointId } = wallStore();
+ 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 { userId, organization } = getUserData();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams();
@@ -113,6 +126,14 @@ function Point({ point }: { readonly point: Point }) {
const wallSnapped = snapWallAngle(newPosition);
const finalSnapped = snapWallPoint(wallSnapped.position);
setWallPosition(point.pointUuid, finalSnapped.position);
+ } else if (point.pointType === 'Floor') {
+ const floorSnapped = snapFloorAngle(newPosition);
+ const finalSnapped = snapFloorPoint(floorSnapped.position);
+ setFloorPosition(point.pointUuid, finalSnapped.position);
+ } else if (point.pointType === 'Zone') {
+ const zoneSnapped = snapZoneAngle(newPosition);
+ const finalSnapped = snapZonePoint(zoneSnapped.position);
+ setZonePosition(point.pointUuid, finalSnapped.position);
}
}
}
@@ -138,11 +159,75 @@ function Point({ point }: { readonly point: Point }) {
const updatedAisles = getAislesByPointId(point.pointUuid);
if (updatedAisles.length > 0 && projectId) {
updatedAisles.forEach((updatedAisle) => {
- createAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '')
+ upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '')
})
}
} else if (point.pointType === 'Wall') {
- // console.log('Wall after drag: ', point);
+ 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);
+ });
+ }
}
}
@@ -152,16 +237,133 @@ function Point({ point }: { readonly point: Point }) {
const removedAisles = removeAislePoint(point.pointUuid);
if (removedAisles.length > 0) {
removedAisles.forEach(aisle => {
- if (projectId)
+ if (projectId) {
deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '')
+ }
});
setHoveredPoint(null);
}
}
if (point.pointType === 'Wall') {
- const removedAisles = removeWallPoint(point.pointUuid);
- if (removedAisles.length > 0) {
+ const removedWalls = removeWallPoint(point.pointUuid);
+ if (removedWalls.length > 0) {
setHoveredPoint(null);
+ 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);
+ setHoveredPoint(null);
+ 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);
+ setHoveredPoint(null);
+ 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);
+ }
+ });
}
}
gl.domElement.style.cursor = 'default';
diff --git a/app/src/modules/builder/point/reference/referencePoint.tsx b/app/src/modules/builder/point/reference/referencePoint.tsx
index 44d399f..2f2cccd 100644
--- a/app/src/modules/builder/point/reference/referencePoint.tsx
+++ b/app/src/modules/builder/point/reference/referencePoint.tsx
@@ -21,9 +21,17 @@ function ReferencePoint({ point }: { readonly point: Point }) {
return null;
}
+ const pointName = point.pointType === 'Wall' ? 'Wall-Point' :
+ point.pointType === 'Floor' ? 'Floor-Point' :
+ point.pointType === 'Aisle' ? 'Aisle-Point' :
+ point.pointType === 'Zone' ? 'Zone-Point' : 'Point';
+
return (
ls.geometry.coordinates);
+ const uniqueCoords = Array.from(new Set(allCoords.map(coord => coord.join(','))));
+ if (uniqueCoords.length < 4) return [];
+
const lineStrings = turf.featureCollection(mergedLineStrings);
- // Now polygonize merged line strings
const polygons = turf.polygonize(lineStrings);
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 037816b..280167d 100644
--- a/app/src/modules/builder/wall/Instances/instance/wall.tsx
+++ b/app/src/modules/builder/wall/Instances/instance/wall.tsx
@@ -1,20 +1,21 @@
import * as THREE from 'three';
import { Base } from '@react-three/csg';
import { useMemo, useRef, useState } from 'react';
-import { Decal, MeshDiscardMaterial } from '@react-three/drei';
+import { MeshDiscardMaterial } from '@react-three/drei';
import { useFrame, useThree } from '@react-three/fiber';
-
-import defaultMaterial from '../../../../../assets/textures/floor/wall-tex.png';
-import material1 from '../../../../../assets/textures/floor/factory wall texture.jpg';
-
import useModuleStore from '../../../../../store/useModuleStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useWallClassification } from './helpers/useWallClassification';
import { useToggleView, useWallVisibility } from '../../../../../store/builder/store';
import { useBuilderStore } from '../../../../../store/builder/useBuilderStore';
import * as Constants from '../../../../../types/world/worldConstants';
+
import DecalInstance from '../../../Decal/decalInstance';
+import defaultMaterial from '../../../../../assets/textures/floor/wall-tex.png';
+import material1 from '../../../../../assets/textures/floor/factory wall texture.jpg';
+
+
function Wall({ wall }: { readonly wall: Wall }) {
const { wallStore } = useSceneContext();
const { walls, addDecal } = wallStore();
@@ -116,14 +117,16 @@ function Wall({ wall }: { readonly wall: Wall }) {
{
+ onDoubleClick={(e) => {
if (visible && !togglView && activeModule === 'builder') {
if (e.object.userData.wallUuid) {
+ e.stopPropagation();
setSelectedWall(e.object);
setSelectedDecal(null);
@@ -151,7 +154,7 @@ function Wall({ wall }: { readonly wall: Wall }) {
{wall.decals.map((decal) => (
-
+
))}
diff --git a/app/src/modules/builder/wall/Instances/wallInstances.tsx b/app/src/modules/builder/wall/Instances/wallInstances.tsx
index 4d5da1e..c5e22bf 100644
--- a/app/src/modules/builder/wall/Instances/wallInstances.tsx
+++ b/app/src/modules/builder/wall/Instances/wallInstances.tsx
@@ -1,6 +1,5 @@
import React, { useEffect, useMemo } from 'react';
import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from 'three';
-import { Geometry } from '@react-three/csg';
import { Html, Extrude } from '@react-three/drei';
import { useLoader } from '@react-three/fiber';
import { useSceneContext } from '../../../scene/sceneContext';
@@ -17,7 +16,7 @@ import texturePathDark from "../../../../assets/textures/floor/black.png";
function WallInstances() {
const { wallStore } = useSceneContext();
const { walls } = wallStore();
- const { rooms } = useWallClassification(walls)
+ const { rooms } = useWallClassification(walls);
const { toggleView } = useToggleView();
useEffect(() => {
@@ -28,8 +27,8 @@ function WallInstances() {
const points: Point[] = [];
const seenUuids = new Set();
- walls.forEach(aisle => {
- aisle.points.forEach(point => {
+ walls.forEach(wall => {
+ wall.points.forEach(point => {
if (!seenUuids.has(point.pointUuid)) {
seenUuids.add(point.pointUuid);
points.push(point);
@@ -44,13 +43,9 @@ function WallInstances() {
<>
{!toggleView && walls.length > 1 && (
<>
-
-
- {walls.map((wall) => (
-
- ))}
-
-
+ {walls.map((wall) => (
+
+ ))}
{rooms.map((room, index) => (
@@ -134,14 +129,15 @@ function Floor({ room }: { room: Point[] }) {
if (!shape) return null;
return (
-
+
-
+
);
}
diff --git a/app/src/modules/builder/wall/wallCreator/referenceWall.tsx b/app/src/modules/builder/wall/wallCreator/referenceWall.tsx
index f932f46..905c60d 100644
--- a/app/src/modules/builder/wall/wallCreator/referenceWall.tsx
+++ b/app/src/modules/builder/wall/wallCreator/referenceWall.tsx
@@ -36,46 +36,45 @@ function ReferenceWall({ tempPoints }: Readonly) {
setCurrentPosition([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z]);
- if (intersectionPoint) {
- const snapped = snapWallPoint([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z]);
-
- if (snapped.isSnapped && snapped.snappedPoint) {
- finalPosition.current = snapped.position;
- setSnappedPosition(snapped.position);
- setSnappedPoint(snapped.snappedPoint);
- } else if (directionalSnap.isSnapped) {
- finalPosition.current = directionalSnap.position;
- setSnappedPosition(directionalSnap.position);
- setSnappedPoint(null);
- } else {
- finalPosition.current = [intersectionPoint.x, intersectionPoint.y, intersectionPoint.z];
- setSnappedPosition(null);
- setSnappedPoint(null);
- }
-
- if (!finalPosition.current) return;
-
- const wallPoints: [Point, Point] = [
- tempPoints[0],
- {
- pointUuid: 'temp-point',
- pointType: 'Wall',
- position: finalPosition.current,
- layer: activeLayer,
- }
- ];
-
- setTempWall({
- wallUuid: 'temp-wall',
- points: wallPoints,
- outsideMaterial: 'default',
- insideMaterial: 'default',
- wallThickness: wallThickness,
- wallHeight: wallHeight,
- decals: []
- })
+ if (!intersectionPoint) return;
+ const snapped = snapWallPoint([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z], tempPoints[0]);
+ if (snapped.isSnapped && snapped.snappedPoint) {
+ finalPosition.current = snapped.position;
+ setSnappedPosition(snapped.position);
+ setSnappedPoint(snapped.snappedPoint);
+ } else if (directionalSnap.isSnapped) {
+ finalPosition.current = directionalSnap.position;
+ setSnappedPosition(directionalSnap.position);
+ setSnappedPoint(null);
+ } else {
+ finalPosition.current = [intersectionPoint.x, intersectionPoint.y, intersectionPoint.z];
+ setSnappedPosition(null);
+ setSnappedPoint(null);
}
+
+ if (!finalPosition.current) return;
+
+ const wallPoints: [Point, Point] = [
+ tempPoints[0],
+ {
+ pointUuid: 'temp-point',
+ pointType: 'Wall',
+ position: finalPosition.current,
+ layer: activeLayer,
+ }
+ ];
+
+ setTempWall({
+ wallUuid: 'temp-wall',
+ points: wallPoints,
+ outsideMaterial: 'default',
+ insideMaterial: 'default',
+ wallThickness: wallThickness,
+ wallHeight: wallHeight,
+ decals: []
+ })
+
} else if (tempWall !== null) {
setTempWall(null);
}
@@ -83,7 +82,7 @@ function ReferenceWall({ tempPoints }: Readonly) {
useEffect(() => {
setTempWall(null);
- }, [toolMode, toggleView, tempPoints.length, wallHeight, wallThickness]);
+ }, [toolMode, toggleView, tempPoints.length, wallHeight, wallThickness, activeLayer]);
if (!tempWall) return null;
diff --git a/app/src/modules/builder/wall/wallCreator/wallCreator.tsx b/app/src/modules/builder/wall/wallCreator/wallCreator.tsx
index a136a41..a80a62d 100644
--- a/app/src/modules/builder/wall/wallCreator/wallCreator.tsx
+++ b/app/src/modules/builder/wall/wallCreator/wallCreator.tsx
@@ -5,9 +5,15 @@ import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../.
import * as Constants from '../../../../types/world/worldConstants';
import { useSceneContext } from '../../../scene/sceneContext';
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
+import { useParams } from 'react-router-dom';
+import { useVersionContext } from '../../version/versionContext';
+import { getUserData } from '../../../../functions/getUserData';
+import getClosestIntersection from '../../line/helpers/getClosestIntersection';
import ReferencePoint from '../../point/reference/referencePoint';
import ReferenceWall from './referenceWall';
-import getClosestIntersection from '../../geomentries/lines/getClosestIntersection';
+
+// import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi';
+// import { deleteWallApi } from '../../../../services/factoryBuilder/wall/deleteWallApi';
function WallCreator() {
const { scene, camera, raycaster, gl, pointer } = useThree();
@@ -20,10 +26,14 @@ function WallCreator() {
const { addWall, getWallPointById, removeWall, getWallByPoints } = wallStore();
const drag = useRef(false);
const isLeftMouseDown = useRef(false);
- const { wallThickness, wallHeight, insideMaterial, outsideMaterial, snappedPosition, snappedPoint } = useBuilderStore();
+ const { selectedVersionStore } = useVersionContext();
+ const { selectedVersion } = selectedVersionStore();
+ const { userId, organization } = getUserData();
+ const { projectId } = useParams();
const [tempPoints, setTempPoints] = useState([]);
const [isCreating, setIsCreating] = useState(false);
+ const { wallThickness, wallHeight, insideMaterial, outsideMaterial, snappedPosition, snappedPoint, setSnappedPoint, setSnappedPosition } = useBuilderStore();
useEffect(() => {
const canvasElement = gl.domElement;
@@ -58,6 +68,7 @@ function WallCreator() {
const pointIntersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Wall-Point');
const wallIntersect = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Wall-Line');
+
if (wallIntersect && !pointIntersects) {
const wall = getWallByPoints(wallIntersect.object.userData.points);
if (wall) {
@@ -80,6 +91,25 @@ function WallCreator() {
const closestPoint = new THREE.Vector3().lerpVectors(point1Vec, point2Vec, t);
removeWall(wall.wallUuid);
+ 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);
+
+ }
const point1: Point = {
pointUuid: wall.points[0].pointUuid,
@@ -114,6 +144,24 @@ function WallCreator() {
}
addWall(wall2);
+ // API
+
+ // if (projectId) {
+ // upsertWallApi(projectId, selectedVersion?.versionId || '', wall2);
+ // }
+
+ // SOCKET
+
+ const data = {
+ wallData: wall2,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Wall:add', data);
+
const wall3: Wall = {
wallUuid: THREE.MathUtils.generateUUID(),
points: [point2, newPoint],
@@ -125,6 +173,24 @@ function WallCreator() {
}
addWall(wall3);
+ // API
+
+ // if (projectId) {
+ // upsertWallApi(projectId, selectedVersion?.versionId || '', wall3);
+ // }
+
+ // SOCKET
+
+ const data2 = {
+ wallData: wall3,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Wall:add', data2);
+
setTempPoints([newPoint]);
setIsCreating(true);
} else {
@@ -139,6 +205,24 @@ function WallCreator() {
};
addWall(wall1);
+ // API
+
+ // if (projectId) {
+ // upsertWallApi(projectId, selectedVersion?.versionId || '', wall1);
+ // }
+
+ // SOCKET
+
+ const data = {
+ wallData: wall1,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Wall:add', data);
+
const wall2: Wall = {
wallUuid: THREE.MathUtils.generateUUID(),
points: [point1, newPoint],
@@ -150,6 +234,24 @@ function WallCreator() {
}
addWall(wall2);
+ // API
+
+ // if (projectId) {
+ // upsertWallApi(projectId, selectedVersion?.versionId || '', wall2);
+ // }
+
+ // SOCKET
+
+ const data1 = {
+ wallData: wall2,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Wall:add', data1);
+
const wall3: Wall = {
wallUuid: THREE.MathUtils.generateUUID(),
points: [point2, newPoint],
@@ -161,6 +263,24 @@ function WallCreator() {
}
addWall(wall3);
+ // API
+
+ // if (projectId) {
+ // upsertWallApi(projectId, selectedVersion?.versionId || '', wall3);
+ // }
+
+ // SOCKET
+
+ const data3 = {
+ wallData: wall3,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Wall:add', data3);
+
setTempPoints([newPoint]);
}
@@ -181,6 +301,8 @@ function WallCreator() {
newPoint.layer = snappedPoint.layer;
}
+ if (snappedPoint && snappedPoint.pointUuid === tempPoints[0]?.pointUuid) { return }
+
if (snappedPosition && !snappedPoint) {
newPoint.position = snappedPosition;
}
@@ -208,6 +330,25 @@ function WallCreator() {
decals: []
};
addWall(wall);
+
+ // API
+
+ // if (projectId) {
+ // upsertWallApi(projectId, selectedVersion?.versionId || '', wall);
+ // }
+
+ // SOCKET
+
+ const data = {
+ wallData: wall,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+
+ socket.emit('v1:model-Wall:add', data);
+
setTempPoints([newPoint]);
}
@@ -222,6 +363,10 @@ function WallCreator() {
};
if (toolMode === "Wall" && toggleView) {
+ if (tempPoints.length === 0) {
+ setSnappedPosition(null);
+ setSnappedPoint(null);
+ }
canvasElement.addEventListener("mousedown", onMouseDown);
canvasElement.addEventListener("mouseup", onMouseUp);
canvasElement.addEventListener("mousemove", onMouseMove);
@@ -244,7 +389,7 @@ function WallCreator() {
canvasElement.removeEventListener("click", onMouseClick);
canvasElement.removeEventListener("contextmenu", onContext);
};
- }, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addWall, getWallPointById, wallThickness, wallHeight, insideMaterial, outsideMaterial, snappedPosition, snappedPoint]);
+ }, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addWall, getWallPointById, wallThickness, wallHeight, insideMaterial, outsideMaterial, snappedPosition, snappedPoint, selectedVersion?.versionId]);
return (
<>
diff --git a/app/src/modules/builder/wall/wallGroup.tsx b/app/src/modules/builder/wall/wallGroup.tsx
index aae36b9..084b969 100644
--- a/app/src/modules/builder/wall/wallGroup.tsx
+++ b/app/src/modules/builder/wall/wallGroup.tsx
@@ -1,21 +1,46 @@
import { useEffect } from 'react';
-import { useToggleView } from '../../../store/builder/store'
+import { useActiveTool, useToggleView } from '../../../store/builder/store';
import { useBuilderStore } from '../../../store/builder/useBuilderStore';
-import WallCreator from './wallCreator/wallCreator'
-import WallInstances from './Instances/wallInstances'
+import { useVersionContext } from '../version/versionContext';
+import { useSceneContext } from '../../scene/sceneContext';
+import { useParams } from 'react-router-dom';
import useModuleStore from '../../../store/useModuleStore';
+import WallCreator from './wallCreator/wallCreator';
+import WallInstances from './Instances/wallInstances';
+
+import { getWallsApi } from '../../../services/factoryBuilder/wall/getWallsApi';
function WallGroup() {
const { togglView } = useToggleView();
const { setSelectedWall, setSelectedDecal } = useBuilderStore();
const { activeModule } = useModuleStore();
+ const { activeTool } = useActiveTool();
+ const { selectedVersionStore } = useVersionContext();
+ const { selectedVersion } = selectedVersionStore();
+ const { wallStore } = useSceneContext();
+ const { setWalls } = wallStore();
+ const { projectId } = useParams();
useEffect(() => {
if (togglView || activeModule !== 'builder') {
setSelectedWall(null);
setSelectedDecal(null);
}
- }, [togglView, activeModule])
+ }, [togglView, activeModule, activeTool])
+
+ useEffect(() => {
+ if (projectId && selectedVersion) {
+ getWallsApi(projectId, selectedVersion?.versionId || '').then((walls) => {
+ if (walls && walls.length > 0) {
+ setWalls(walls);
+ } else {
+ setWalls([]);
+ }
+ }).catch((err) => {
+ console.log(err);
+ })
+ }
+ }, [projectId, selectedVersion?.versionId])
return (
<>
diff --git a/app/src/modules/builder/wallAsset/Instances/Instances/wallAssetInstance.tsx b/app/src/modules/builder/wallAsset/Instances/Instances/wallAssetInstance.tsx
new file mode 100644
index 0000000..d9f8df0
--- /dev/null
+++ b/app/src/modules/builder/wallAsset/Instances/Instances/wallAssetInstance.tsx
@@ -0,0 +1,261 @@
+import * as THREE from 'three';
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils';
+import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
+import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
+import { Base, Geometry, Subtraction } from '@react-three/csg';
+import useModuleStore from '../../../../../store/useModuleStore';
+import { useSceneContext } from '../../../../scene/sceneContext';
+import { useBuilderStore } from '../../../../../store/builder/useBuilderStore';
+import { useActiveTool, useToggleView } from '../../../../../store/builder/store';
+import closestPointOnLineSegment from '../../../line/helpers/getClosestPointOnLineSegment';
+import { useThree } from '@react-three/fiber';
+
+function WallAssetInstance({ wallAsset }: { wallAsset: WallAsset }) {
+ const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
+ const { raycaster, pointer, camera, scene, controls, gl } = useThree();
+ const { wallStore, wallAssetStore } = useSceneContext();
+ const { walls, getWallById } = wallStore();
+ const { updateWallAsset, removeWallAsset } = wallAssetStore();
+ const { toggleView } = useToggleView();
+ const { activeTool } = useActiveTool();
+ const { activeModule } = useModuleStore();
+ const { selectedWallAsset, setSelectedWallAsset, setDeletableWallAsset, deletableWallAsset } = useBuilderStore();
+ const [gltfScene, setGltfScene] = useState(null);
+ const [boundingBox, setBoundingBox] = useState(null);
+ const groupRef = useRef(null);
+ const wall = useMemo(() => getWallById(wallAsset.wallUuid), [getWallById, wallAsset.wallUuid, walls]);
+ const draggingRef = useRef(false);
+
+ useEffect(() => {
+ 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);
+ const loadModel = async () => {
+ try {
+ // Check Cache
+ const assetId = wallAsset.assetId;
+ const cachedModel = THREE.Cache.get(assetId);
+ if (cachedModel) {
+ setGltfScene(cachedModel.scene.clone());
+ calculateBoundingBox(cachedModel.scene);
+ return;
+ }
+
+ // Check IndexedDB
+ const indexedDBModel = await retrieveGLTF(assetId);
+ if (indexedDBModel) {
+ const blobUrl = URL.createObjectURL(indexedDBModel);
+ loader.load(blobUrl, (gltf) => {
+ URL.revokeObjectURL(blobUrl);
+ THREE.Cache.remove(blobUrl);
+ THREE.Cache.add(assetId, gltf);
+ setGltfScene(gltf.scene.clone());
+ calculateBoundingBox(gltf.scene);
+ },
+ undefined,
+ (error) => {
+ echo.error(`[IndexedDB] Error loading ${wallAsset.modelName}:`);
+ URL.revokeObjectURL(blobUrl);
+ }
+ );
+ return;
+ }
+
+ // Fetch from Backend
+ const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${assetId}`;
+ const handleBackendLoad = async (gltf: GLTF) => {
+ try {
+ const response = await fetch(modelUrl);
+ const modelBlob = await response.blob();
+ await storeGLTF(assetId, modelBlob);
+ THREE.Cache.add(assetId, gltf);
+ setGltfScene(gltf.scene.clone());
+ calculateBoundingBox(gltf.scene);
+ } catch (error) {
+ console.error(`[Backend] Error storing/loading ${wallAsset.modelName}:`, error);
+ }
+ };
+ loader.load(
+ modelUrl,
+ handleBackendLoad,
+ undefined,
+ (error) => {
+ echo.error(`[Backend] Error loading ${wallAsset.modelName}:`);
+ }
+ );
+ } catch (err) {
+ console.error("Failed to load model:", wallAsset.assetId, err);
+ }
+ };
+
+ const calculateBoundingBox = (scene: THREE.Object3D) => {
+ const box = new THREE.Box3().setFromObject(scene);
+ setBoundingBox(box);
+ };
+
+ loadModel();
+
+ }, []);
+
+ useEffect(() => {
+ const canvasElement = gl.domElement;
+
+ const onPointerUp = () => {
+ draggingRef.current = false;
+ if (controls) {
+ (controls as any).enabled = true;
+ }
+ };
+
+ const onPointerMove = (e: any) => {
+ if (!draggingRef.current || !wall || !selectedWallAsset) return;
+ if (controls) {
+ (controls as any).enabled = false;
+ }
+ pointer.x = (e.clientX / window.innerWidth) * 2 - 1;
+ pointer.y = -(e.clientY / window.innerHeight) * 2 + 1;
+
+ raycaster.setFromCamera(pointer, camera);
+ const intersects = raycaster.intersectObjects(scene.children, true);
+ const intersect = intersects.find((i: any) => i.object.name.includes('WallReference'));
+
+ if (intersect && intersect.object.userData.wallUuid) {
+ const newPoint = closestPointOnLineSegment(
+ new THREE.Vector3(intersect.point.x, 0, intersect.point.z),
+ new THREE.Vector3(...intersect.object.userData.points[0].position),
+ new THREE.Vector3(...intersect.object.userData.points[1].position)
+ );
+
+ const wallRotation = intersect.object.rotation.clone();
+
+ updateWallAsset(wallAsset.modelUuid, {
+ wallUuid: intersect.object.userData.wallUuid,
+ position: [newPoint.x, wallAsset.wallAssetType === 'fixed-move' ? 0 : intersect.point.y, newPoint.z],
+ rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
+ });
+ }
+ };
+
+ if (selectedWallAsset && !toggleView && activeModule === 'builder') {
+ canvasElement.addEventListener('mousemove', onPointerMove);
+ canvasElement.addEventListener('pointerup', onPointerUp);
+ }
+
+ return () => {
+ canvasElement.removeEventListener('mousemove', onPointerMove);
+ canvasElement.removeEventListener('pointerup', onPointerUp);
+ };
+
+ }, [gl, camera, toggleView, activeModule, selectedWallAsset])
+
+ const handlePointerClick = useCallback((wallAsset: WallAsset) => {
+ if (activeTool === 'delete' && deletableWallAsset && deletableWallAsset.userData.modelUuid === wallAsset.modelUuid) {
+ removeWallAsset(wallAsset.modelUuid);
+ }
+ }, [activeTool, activeModule, deletableWallAsset])
+
+ const handlePointerOver = useCallback((wallAsset: WallAsset, currentObject: THREE.Object3D) => {
+ if (activeTool === "delete" && activeModule === 'builder') {
+ if (deletableWallAsset && deletableWallAsset.userData.modelUuid === wallAsset.modelUuid) {
+ return;
+ } else {
+ setDeletableWallAsset(currentObject);
+ }
+ }
+ }, [activeTool, activeModule, deletableWallAsset]);
+
+ const handlePointerOut = useCallback((wallAsset: WallAsset) => {
+ if (activeTool === "delete" && deletableWallAsset && deletableWallAsset.userData.modelUuid === wallAsset.modelUuid) {
+ setDeletableWallAsset(null);
+ }
+ }, [activeTool, deletableWallAsset]);
+
+ if (!gltfScene || !boundingBox || !wall) { return null }
+ const size = new THREE.Vector3();
+ boundingBox.getSize(size);
+ const center = new THREE.Vector3();
+ boundingBox.getCenter(center);
+
+ return (
+ <>
+
+
+
+
+
+
+ {gltfScene && (
+ {
+ if (!toggleView && activeModule === 'builder' && selectedWallAsset && selectedWallAsset.userData.modelUuid === wallAsset.modelUuid) {
+ draggingRef.current = true;
+ e.stopPropagation();
+ setSelectedWallAsset(groupRef.current);
+ if (controls) {
+ (controls as any).enabled = false;
+ }
+ }
+ }}
+ onClick={(e) => {
+ if (!toggleView && activeModule === 'builder' && activeTool !== 'delete') {
+ if (e.object) {
+ e.stopPropagation();
+ let currentObject = e.object as THREE.Object3D;
+ while (currentObject) {
+ if (currentObject.name === "Scene") {
+ break;
+ }
+ currentObject = currentObject.parent as THREE.Object3D;
+ }
+ setSelectedWallAsset(currentObject);
+ }
+ } else if (!toggleView && activeModule === 'builder' && activeTool === 'delete') {
+ handlePointerClick(wallAsset);
+ }
+ }}
+ onPointerMissed={() => {
+ if (selectedWallAsset && selectedWallAsset.userData.modelUuid === wallAsset.modelUuid) {
+ setSelectedWallAsset(null);
+ }
+ }}
+ onPointerEnter={(e) => {
+ if (!toggleView) {
+ e.stopPropagation();
+ let currentObject = e.object as THREE.Object3D;
+ while (currentObject) {
+ if (currentObject.name === "Scene") {
+ break;
+ }
+ currentObject = currentObject.parent as THREE.Object3D;
+ }
+ handlePointerOver(wallAsset, currentObject);
+ }
+ }}
+ onPointerOut={(e) => {
+ if (!toggleView) {
+ e.stopPropagation();
+ handlePointerOut(wallAsset);
+ }
+ }}
+ userData={wallAsset}
+ >
+
+
+ )}
+
+ >
+ )
+}
+
+export default WallAssetInstance
\ No newline at end of file
diff --git a/app/src/modules/builder/wallAsset/Instances/wallAssetInstances.tsx b/app/src/modules/builder/wallAsset/Instances/wallAssetInstances.tsx
new file mode 100644
index 0000000..581dfe7
--- /dev/null
+++ b/app/src/modules/builder/wallAsset/Instances/wallAssetInstances.tsx
@@ -0,0 +1,30 @@
+import { useEffect } from 'react';
+import { useSceneContext } from '../../../scene/sceneContext'
+import { useToggleView } from '../../../../store/builder/store';
+import WallAssetInstance from './Instances/wallAssetInstance';
+
+function WallAssetInstances() {
+ const { wallAssetStore } = useSceneContext();
+ const { wallAssets } = wallAssetStore();
+ const { toggleView } = useToggleView();
+
+ useEffect(() => {
+ // console.log('wallAssets: ', wallAssets);
+ }, [wallAssets])
+
+ return (
+ <>
+
+ {!toggleView && wallAssets.length > 0 && (
+ <>
+ {wallAssets.map((wallAsset) => (
+
+ ))}
+ >
+ )}
+
+ >
+ )
+}
+
+export default WallAssetInstances
\ No newline at end of file
diff --git a/app/src/modules/builder/wallAsset/wallAssetCreator.tsx b/app/src/modules/builder/wallAsset/wallAssetCreator.tsx
new file mode 100644
index 0000000..aacca0e
--- /dev/null
+++ b/app/src/modules/builder/wallAsset/wallAssetCreator.tsx
@@ -0,0 +1,75 @@
+import { useThree } from '@react-three/fiber';
+import { useEffect } from 'react'
+import { useSelectedItem, useSocketStore, useToggleView } from '../../../store/builder/store';
+import useModuleStore from '../../../store/useModuleStore';
+import { MathUtils, Vector3 } from 'three';
+import { useSceneContext } from '../../scene/sceneContext';
+import closestPointOnLineSegment from '../line/helpers/getClosestPointOnLineSegment';
+
+function WallAssetCreator() {
+ const { socket } = useSocketStore();
+ const { pointer, camera, raycaster, scene, gl } = useThree();
+ const { togglView } = useToggleView();
+ const { activeModule } = useModuleStore();
+ const { wallAssetStore } = useSceneContext();
+ const { addWallAsset } = wallAssetStore();
+ const { selectedItem, setSelectedItem } = useSelectedItem();
+
+ useEffect(() => {
+ const canvasElement = gl.domElement;
+
+ const onDrop = (event: DragEvent) => {
+ if (!event.dataTransfer?.files[0]) return;
+ if (selectedItem.id !== "" && event.dataTransfer?.files[0] && selectedItem.category === 'Fenestration') {
+ pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
+ pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
+
+ raycaster.setFromCamera(pointer, camera);
+ const intersects = raycaster.intersectObjects(scene.children, true);
+ const intersect = intersects.find((intersect) => intersect.object.name.includes('WallReference'));
+
+ if (intersect) {
+ const wall = intersect.object.userData as Wall;
+ const closestPoint = closestPointOnLineSegment(
+ new Vector3(intersect.point.x, 0, intersect.point.z),
+ new Vector3(...wall.points[0].position),
+ new Vector3(...wall.points[1].position)
+ )
+
+ const wallRotation = intersect.object.rotation.clone();
+
+ const newWallAsset: WallAsset = {
+ modelName: selectedItem.name,
+ modelUuid: MathUtils.generateUUID(),
+ wallUuid: wall.wallUuid,
+ wallAssetType: selectedItem.subCategory,
+ assetId: selectedItem.id,
+ position: [closestPoint.x, selectedItem.subCategory === "fixed-move" ? 0 : intersect.point.y, closestPoint.z],
+ rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
+ isLocked: false,
+ isVisible: true,
+ opacity: 1,
+ };
+
+ addWallAsset(newWallAsset);
+ }
+ }
+ };
+
+ if (!togglView && activeModule === 'builder') {
+ canvasElement.addEventListener('drop', onDrop);
+ }
+
+ return () => {
+ canvasElement.removeEventListener('drop', onDrop);
+ };
+
+ }, [gl, camera, togglView, activeModule, socket, selectedItem, setSelectedItem]);
+
+ return (
+ <>
+ >
+ )
+}
+
+export default WallAssetCreator
\ No newline at end of file
diff --git a/app/src/modules/builder/wallAsset/wallAssetGroup.tsx b/app/src/modules/builder/wallAsset/wallAssetGroup.tsx
new file mode 100644
index 0000000..f9d1290
--- /dev/null
+++ b/app/src/modules/builder/wallAsset/wallAssetGroup.tsx
@@ -0,0 +1,40 @@
+import { useEffect } from 'react';
+import { useActiveTool, useToggleView } from '../../../store/builder/store';
+import { useBuilderStore } from '../../../store/builder/useBuilderStore';
+import { useVersionContext } from '../version/versionContext';
+import { useSceneContext } from '../../scene/sceneContext';
+import { useParams } from 'react-router-dom';
+import useModuleStore from '../../../store/useModuleStore';
+import WallAssetCreator from './wallAssetCreator'
+import WallAssetInstances from './Instances/wallAssetInstances'
+
+function WallAssetGroup() {
+ const { togglView } = useToggleView();
+ const { setSelectedFloorAsset, setDeletableWallAsset } = useBuilderStore();
+ const { activeModule } = useModuleStore();
+ const { activeTool } = useActiveTool();
+ const { selectedVersionStore } = useVersionContext();
+ const { selectedVersion } = selectedVersionStore();
+ const { wallAssetStore } = useSceneContext();
+ const { setWallAssets } = wallAssetStore();
+ const { projectId } = useParams();
+
+ useEffect(() => {
+ if (togglView || activeModule !== 'builder') {
+ setSelectedFloorAsset(null);
+ }
+ setDeletableWallAsset(null);
+ }, [togglView, activeModule, activeTool])
+
+ return (
+ <>
+
+
+
+
+
+ >
+ )
+}
+
+export default WallAssetGroup
\ No newline at end of file
diff --git a/app/src/modules/builder/zone/Instances/Instance/zone2DInstance.tsx b/app/src/modules/builder/zone/Instances/Instance/zone2DInstance.tsx
new file mode 100644
index 0000000..3489b32
--- /dev/null
+++ b/app/src/modules/builder/zone/Instances/Instance/zone2DInstance.tsx
@@ -0,0 +1,50 @@
+import { useMemo } from 'react';
+import { DoubleSide, Shape, Vector2 } from 'three';
+import { Extrude } from '@react-three/drei';
+import * as Constants from '../../../../../types/world/worldConstants';
+
+function Zone2DInstance({ zone }: { zone: Zone }) {
+ const savedTheme: string | null = localStorage.getItem("theme");
+
+ const shape = useMemo(() => {
+ const shape = new Shape();
+ const points = zone.points.map(p => new Vector2(p.position[0], p.position[2]));
+ if (points.length < 3) return null;
+ shape.moveTo(points[0].x, points[0].y);
+ for (let i = 1; i < points.length; i++) {
+ shape.lineTo(points[i].x, points[i].y);
+ }
+ return shape;
+ }, [zone]);
+
+ if (!shape) return null;
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default Zone2DInstance;
\ No newline at end of file
diff --git a/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx b/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx
new file mode 100644
index 0000000..e49400c
--- /dev/null
+++ b/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx
@@ -0,0 +1,73 @@
+import { useMemo } from 'react'
+import { Color, DoubleSide, ShaderMaterial } from 'three';
+import { Vector3 } from 'three';
+
+function ZoneInstance({ zone }: { zone: Zone }) {
+ const zoneLayer = zone.points[0].layer;
+
+ const zoneMaterial = useMemo(() => {
+ return new ShaderMaterial({
+ side: DoubleSide,
+ vertexShader: `
+ varying vec2 vUv;
+ void main(){
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
+ vUv = uv;
+ }
+ `,
+ fragmentShader: `
+ varying vec2 vUv;
+ uniform vec3 uOuterColor;
+ void main(){
+ float alpha = 1.0 - vUv.y;
+ gl_FragColor = vec4(uOuterColor, alpha);
+ }
+ `,
+ uniforms: {
+ uOuterColor: { value: new Color(zone.zoneColor) },
+ },
+ transparent: true,
+ depthWrite: false,
+ })
+ }, []);
+
+ return (
+ <>
+
+ {zone.points.map((point, index: number) => {
+ const nextPoint = zone.points[(index + 1) % zone.points.length];
+
+ const point1 = new Vector3(point.position[0], point.position[1], point.position[2]);
+ const point2 = new Vector3(nextPoint.position[0], nextPoint.position[1], nextPoint.position[2]);
+
+ const planeWidth = point1.distanceTo(point2);
+ const planeHeight = zone.zoneHeight;
+
+ const midpoint = new Vector3((point1.x + point2.x) / 2, zone.zoneHeight / 2 + (zoneLayer - 1) * zone.zoneHeight, (point1.z + point2.z) / 2);
+
+ const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x);
+
+ return (
+
+
+
+
+ );
+ })}
+
+ mesh>
+ >
+ )
+}
+
+export default ZoneInstance
\ No newline at end of file
diff --git a/app/src/modules/builder/zone/Instances/zoneInstances.tsx b/app/src/modules/builder/zone/Instances/zoneInstances.tsx
new file mode 100644
index 0000000..39a60a7
--- /dev/null
+++ b/app/src/modules/builder/zone/Instances/zoneInstances.tsx
@@ -0,0 +1,132 @@
+import React, { useEffect, useMemo } from 'react';
+import { Vector3 } from 'three';
+import { Html } from '@react-three/drei';
+import { useSceneContext } from '../../../scene/sceneContext';
+import { useToggleView } from '../../../../store/builder/store';
+import Line from '../../line/line';
+import Point from '../../point/point';
+import ZoneInstance from './Instance/zoneInstance';
+import Zone2DInstance from './Instance/zone2DInstance';
+
+function ZoneInstances() {
+ const { zoneStore } = useSceneContext();
+ const { zones } = zoneStore();
+ const { toggleView } = useToggleView();
+
+ useEffect(() => {
+ // console.log('zones: ', zones);
+ }, [zones])
+
+ const allPoints = useMemo(() => {
+ const points: Point[] = [];
+ const seenUuids = new Set();
+
+ zones.forEach(zone => {
+ zone.points.forEach(point => {
+ if (!seenUuids.has(point.pointUuid)) {
+ seenUuids.add(point.pointUuid);
+ points.push(point);
+ }
+ });
+ });
+
+ return points;
+ }, [zones]);
+
+ const allLines = useMemo(() => {
+ const lines: { start: Point; end: Point; key: string }[] = [];
+ const seenUuids = new Set();
+
+ zones.forEach((zone) => {
+ const points = zone.points;
+ if (points.length < 2) return;
+
+ for (let i = 0; i < points.length; i++) {
+ const current = points[i];
+ const next = points[(i + 1) % points.length];
+ const lineKey = `${current.pointUuid}-${next.pointUuid}`;
+ if (current.pointUuid !== next.pointUuid && !seenUuids.has(lineKey)) {
+ seenUuids.add(lineKey);
+ lines.push({
+ start: current,
+ end: next,
+ key: lineKey
+ });
+ }
+ }
+ });
+
+ return lines;
+ }, [zones]);
+
+ return (
+ <>
+
+ {!toggleView && zones.length > 0 && (
+
+ {zones.map((zone) => (
+
+ ))}
+
+ )}
+
+ {toggleView && zones.length > 0 && (
+
+ {zones.map((zone) => (
+
+ ))}
+
+ )}
+
+ {toggleView && (
+ <>
+
+ {allPoints.map((point) => (
+
+ ))}
+
+
+
+
+ {allLines.map(({ start, end, key }) => (
+
+ ))}
+
+ {allLines.map((line) => {
+ const { start, end, key } = line;
+ const textPosition = new Vector3().addVectors(new Vector3(...start.position), new Vector3(...end.position)).divideScalar(2);
+ const distance = new Vector3(...start.position).distanceTo(new Vector3(...end.position));
+
+ return (
+
+ {toggleView &&
+
+
+ {distance.toFixed(2)} m
+
+
+ }
+
+ )
+ })}
+
+
+ >
+ )}
+ >
+ )
+}
+
+export default ZoneInstances
\ No newline at end of file
diff --git a/app/src/modules/builder/zone/zoneCreator/referenceZone.tsx b/app/src/modules/builder/zone/zoneCreator/referenceZone.tsx
new file mode 100644
index 0000000..e5cdf9f
--- /dev/null
+++ b/app/src/modules/builder/zone/zoneCreator/referenceZone.tsx
@@ -0,0 +1,163 @@
+import { useEffect, useRef, useState, useMemo } from 'react';
+import * as THREE from 'three';
+import { useFrame, useThree } from '@react-three/fiber';
+import { Extrude, Html } from '@react-three/drei';
+import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
+import { useActiveLayer, useToolMode, useToggleView } from '../../../../store/builder/store';
+import { useDirectionalSnapping } from '../../point/helpers/useDirectionalSnapping';
+import { usePointSnapping } from '../../point/helpers/usePointSnapping';
+import ReferenceLine from '../../line/reference/referenceLine';
+
+interface ReferenceZoneProps {
+ tempPoints: Point[];
+}
+
+function ReferenceZone({ tempPoints }: Readonly) {
+ const { zoneColor, zoneHeight, setSnappedPosition, setSnappedPoint } = useBuilderStore();
+ const { pointer, raycaster, camera } = useThree();
+ const { toolMode } = useToolMode();
+ const { toggleView } = useToggleView();
+ const { activeLayer } = useActiveLayer();
+ const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
+ const finalPosition = useRef<[number, number, number] | null>(null);
+
+ const [tempZone, setTempZone] = useState(null);
+ const [currentPosition, setCurrentPosition] = useState<[number, number, number]>(tempPoints[0]?.position);
+
+ const directionalSnap = useDirectionalSnapping(currentPosition, tempPoints[tempPoints.length - 1]?.position || null);
+ const { snapZonePoint } = usePointSnapping({ uuid: 'temp-Zone', pointType: 'Zone', position: directionalSnap.position || [0, 0, 0], });
+
+ useFrame(() => {
+ if (toolMode === 'Zone' && toggleView && tempPoints.length > 0) {
+ raycaster.setFromCamera(pointer, camera);
+ const intersectionPoint = new THREE.Vector3();
+ raycaster.ray.intersectPlane(plane, intersectionPoint);
+
+ setCurrentPosition([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z]);
+
+ if (!intersectionPoint) return;
+ const snapped = snapZonePoint([intersectionPoint.x, intersectionPoint.y, intersectionPoint.z], tempPoints.length > 2 ? [tempPoints[0]] : []);
+
+ if (snapped.isSnapped && snapped.snappedPoint) {
+ finalPosition.current = snapped.position;
+ setSnappedPosition(snapped.position);
+ setSnappedPoint(snapped.snappedPoint);
+ } else if (directionalSnap.isSnapped) {
+ finalPosition.current = directionalSnap.position;
+ setSnappedPosition(directionalSnap.position);
+ setSnappedPoint(null);
+ } else {
+ finalPosition.current = [intersectionPoint.x, intersectionPoint.y, intersectionPoint.z];
+ setSnappedPosition(null);
+ setSnappedPoint(null);
+ }
+
+ if (!finalPosition.current) return;
+
+ const zonePoints: Point[] = [
+ ...tempPoints,
+ {
+ pointUuid: 'temp-point',
+ pointType: 'Zone',
+ position: finalPosition.current,
+ layer: activeLayer,
+ },
+ ];
+
+ setTempZone({
+ zoneUuid: 'temp-zone',
+ zoneName: 'temp-zone',
+ points: zonePoints,
+ zoneColor,
+ zoneHeight,
+ viewPortPosition: [0, 0, 0],
+ viewPortTarget: [0, 0, 0],
+ });
+
+ } else if (tempZone !== null) {
+ setTempZone(null);
+ }
+ });
+
+ useEffect(() => {
+ setTempZone(null);
+ }, [toolMode, toggleView, tempPoints.length, zoneColor, zoneHeight, activeLayer]);
+
+ const allLines = useMemo(() => {
+ if (!tempZone || tempZone.points.length < 2) return [];
+
+ const lines: [Point, Point][] = [];
+ const pts = tempZone.points;
+
+ for (let i = 0; i < pts.length - 1; i++) {
+ lines.push([pts[i], pts[i + 1]]);
+ }
+
+ return lines;
+ }, [tempZone]);
+
+ if (!tempZone) return null;
+
+ return (
+
+ {allLines.map(([p1, p2], idx) => {
+ const v1 = new THREE.Vector3(...p1.position);
+ const v2 = new THREE.Vector3(...p2.position);
+ const mid = new THREE.Vector3().addVectors(v1, v2).multiplyScalar(0.5);
+ const dist = v1.distanceTo(v2);
+
+ return (
+
+
+ {toggleView && (
+
+ {dist.toFixed(2)} m
+
+ )}
+
+ );
+ })}
+
+ {tempPoints.length >= 3 && (
+
+ )}
+
+ );
+}
+
+export default ReferenceZone;
+
+
+function Zone({ zone }: { zone: Point[] }) {
+ const savedTheme: string | null = localStorage.getItem('theme');
+
+ const shape = useMemo(() => {
+ const shape = new THREE.Shape();
+ const points = zone.map(p => new THREE.Vector2(p.position[0], p.position[2]));
+ if (points.length < 3) return null;
+ shape.moveTo(points[0].x, points[0].y);
+ points.forEach((pt) => { shape.lineTo(pt.x, pt.y); });
+ return shape;
+ }, [zone]);
+
+ if (!shape) return null;
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/app/src/modules/builder/zone/zoneCreator/zoneCreator.tsx b/app/src/modules/builder/zone/zoneCreator/zoneCreator.tsx
new file mode 100644
index 0000000..1df200f
--- /dev/null
+++ b/app/src/modules/builder/zone/zoneCreator/zoneCreator.tsx
@@ -0,0 +1,261 @@
+import * as THREE from 'three'
+import { useEffect, useMemo, useRef, useState } from 'react'
+import { useThree } from '@react-three/fiber';
+import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
+import { useSceneContext } from '../../../scene/sceneContext';
+import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
+import { useParams } from 'react-router-dom';
+import { useVersionContext } from '../../version/versionContext';
+import { getUserData } from '../../../../functions/getUserData';
+import ReferencePoint from '../../point/reference/referencePoint';
+import ReferenceZone from './referenceZone';
+
+// import { upsertZoneApi } from '../../../../services/factoryBuilder/zone/upsertZoneApi';
+
+function ZoneCreator() {
+ const { scene, camera, raycaster, gl, pointer } = useThree();
+ const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
+ const { toggleView } = useToggleView();
+ const { toolMode } = useToolMode();
+ const { activeLayer } = useActiveLayer();
+ const { socket } = useSocketStore();
+ const { zoneStore } = useSceneContext();
+ const { addZone, getZonePointById, getZoneByPoints } = zoneStore();
+ const drag = useRef(false);
+ const isLeftMouseDown = useRef(false);
+ const { selectedVersionStore } = useVersionContext();
+ const { selectedVersion } = selectedVersionStore();
+ const { userId, organization } = getUserData();
+ const { projectId } = useParams();
+
+ const [tempPoints, setTempPoints] = useState([]);
+ const [isCreating, setIsCreating] = useState(false);
+ const { zoneColor, zoneHeight, snappedPosition, snappedPoint, setSnappedPoint, setSnappedPosition } = useBuilderStore();
+
+ useEffect(() => {
+ const canvasElement = gl.domElement;
+
+ const onMouseDown = (evt: any) => {
+ if (evt.button === 0) {
+ isLeftMouseDown.current = true;
+ drag.current = false;
+ }
+ };
+
+ const onMouseUp = (evt: any) => {
+ if (evt.button === 0) {
+ isLeftMouseDown.current = false;
+ }
+ };
+
+ const onMouseMove = () => {
+ if (isLeftMouseDown) {
+ drag.current = true;
+ }
+ };
+
+ const onMouseClick = () => {
+ if (drag.current || !toggleView) return;
+
+ raycaster.setFromCamera(pointer, camera);
+ const intersectionPoint = new THREE.Vector3();
+ let position = raycaster.ray.intersectPlane(plane, intersectionPoint);
+ if (!position) return;
+
+ const pointIntersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Zone-Point');
+
+ // const zoneIntersect = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Zone-Line');
+
+ // if (zoneIntersect && !pointIntersects) {
+
+ // }
+
+ const newPoint: Point = {
+ pointUuid: THREE.MathUtils.generateUUID(),
+ pointType: 'Zone',
+ position: [position.x, position.y, position.z],
+ layer: activeLayer
+ };
+
+ if (snappedPosition && snappedPoint) {
+ newPoint.pointUuid = snappedPoint.pointUuid;
+ newPoint.position = snappedPosition;
+ newPoint.layer = snappedPoint.layer;
+ }
+
+ if (snappedPoint && snappedPoint.pointUuid === tempPoints[tempPoints.length - 1]?.pointUuid) { return }
+
+ if (snappedPosition && !snappedPoint) {
+ newPoint.position = snappedPosition;
+ }
+
+ if (tempPoints.length > 2 && isCreating && snappedPoint && snappedPoint.pointUuid === tempPoints[0].pointUuid) {
+ const zone: Zone = {
+ zoneUuid: THREE.MathUtils.generateUUID(),
+ zoneName: "Zone",
+ points: tempPoints,
+ zoneColor,
+ zoneHeight,
+ viewPortPosition: [0, 0, 0],
+ viewPortTarget: [0, 0, 0]
+ };
+
+ addZone(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);
+
+ }
+ setTempPoints([]);
+ setIsCreating(false);
+ } else if (isCreating && snappedPoint && !tempPoints.some(p => p.pointUuid === snappedPoint.pointUuid)) {
+ setTempPoints(prev => [...prev, newPoint]);
+ setIsCreating(true);
+ } else if (pointIntersects) {
+ if (tempPoints.length > 2 && isCreating && pointIntersects.object.uuid === tempPoints[0].pointUuid) {
+ const zone: Zone = {
+ zoneUuid: THREE.MathUtils.generateUUID(),
+ zoneName: "Zone",
+ points: tempPoints,
+ zoneColor,
+ zoneHeight,
+ viewPortPosition: [0, 0, 0],
+ viewPortTarget: [0, 0, 0]
+ };
+
+ addZone(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);
+
+ }
+ setTempPoints([]);
+ setIsCreating(false);
+ } else if (tempPoints.length === 0 || (tempPoints.length > 1 && !tempPoints.slice(1).some(p => p.pointUuid === pointIntersects.object.uuid))) {
+ tempPoints.push(pointIntersects.object.userData as Point);
+ setIsCreating(true);
+ }
+ } else {
+ setTempPoints(prev => [...prev, newPoint]);
+ setIsCreating(true);
+ }
+
+ };
+
+ const onContext = (event: any) => {
+ event.preventDefault();
+ if (isCreating) {
+ if (tempPoints.length >= 3) {
+ const zone: Zone = {
+ zoneUuid: THREE.MathUtils.generateUUID(),
+ zoneName: "Zone",
+ points: tempPoints,
+ zoneColor,
+ zoneHeight,
+ viewPortPosition: [0, 0, 0],
+ viewPortTarget: [0, 0, 0]
+ };
+
+ addZone(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);
+
+ }
+ }
+ setTempPoints([]);
+ setIsCreating(false);
+ }
+ };
+
+ if (toolMode === "Zone" && toggleView) {
+ if (tempPoints.length === 0) {
+ setSnappedPosition(null);
+ setSnappedPoint(null);
+ }
+ canvasElement.addEventListener("mousedown", onMouseDown);
+ canvasElement.addEventListener("mouseup", onMouseUp);
+ canvasElement.addEventListener("mousemove", onMouseMove);
+ canvasElement.addEventListener("click", onMouseClick);
+ canvasElement.addEventListener("contextmenu", onContext);
+ } else {
+ setTempPoints([]);
+ setIsCreating(false);
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ canvasElement.removeEventListener("click", onMouseClick);
+ canvasElement.removeEventListener("contextmenu", onContext);
+ }
+
+ return () => {
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ canvasElement.removeEventListener("click", onMouseClick);
+ canvasElement.removeEventListener("contextmenu", onContext);
+ };
+ }, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addZone, getZonePointById, getZoneByPoints, zoneColor, zoneHeight, snappedPosition, snappedPoint]);
+
+ return (
+ <>
+ {toggleView &&
+ <>
+
+ {tempPoints.map((point) => (
+
+ ))}
+
+
+ {tempPoints.length > 0 &&
+
+ }
+ >
+ }
+ >
+ )
+}
+
+export default ZoneCreator
\ No newline at end of file
diff --git a/app/src/modules/builder/zone/zoneGroup.tsx b/app/src/modules/builder/zone/zoneGroup.tsx
new file mode 100644
index 0000000..c44bf09
--- /dev/null
+++ b/app/src/modules/builder/zone/zoneGroup.tsx
@@ -0,0 +1,55 @@
+import { useEffect } from 'react';
+import { useActiveTool, useToggleView } from '../../../store/builder/store';
+import { useBuilderStore } from '../../../store/builder/useBuilderStore';
+import { useVersionContext } from '../version/versionContext';
+import { useSceneContext } from '../../scene/sceneContext';
+import { useParams } from 'react-router-dom';
+import useModuleStore from '../../../store/useModuleStore';
+import ZoneCreator from './zoneCreator/zoneCreator';
+import ZoneInstances from './Instances/zoneInstances';
+
+import { getZonesApi } from '../../../services/factoryBuilder/zone/getZonesApi';
+
+function ZoneGroup() {
+ const { togglView } = useToggleView();
+ const { setSelectedZone } = useBuilderStore();
+ const { activeModule } = useModuleStore();
+ const { activeTool } = useActiveTool();
+ const { selectedVersionStore } = useVersionContext();
+ const { selectedVersion } = selectedVersionStore();
+ const { zoneStore } = useSceneContext();
+ const { setZones } = zoneStore();
+ const { projectId } = useParams();
+
+ useEffect(() => {
+ if (togglView || activeModule !== 'builder') {
+ setSelectedZone(null);
+ }
+ }, [togglView, activeModule, activeTool])
+
+ useEffect(() => {
+ if (projectId && selectedVersion) {
+ getZonesApi(projectId, selectedVersion?.versionId || '').then((zones) => {
+ if (zones && zones.length > 0) {
+ setZones(zones);
+ } else {
+ setZones([]);
+ }
+ }).catch((err) => {
+ console.log(err);
+ })
+ }
+ }, [projectId, selectedVersion?.versionId])
+
+ return (
+ <>
+
+
+
+
+
+ >
+ )
+}
+
+export default ZoneGroup
\ No newline at end of file
diff --git a/app/src/modules/collaboration/socket/socketResponses.dev.tsx b/app/src/modules/collaboration/socket/socketResponses.dev.tsx
index 6028329..3f4bfdb 100644
--- a/app/src/modules/collaboration/socket/socketResponses.dev.tsx
+++ b/app/src/modules/collaboration/socket/socketResponses.dev.tsx
@@ -1,891 +1,9 @@
-import { useEffect } from "react";
-import * as THREE from "three";
-import gsap from "gsap";
-import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
-import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
-import {
- useSocketStore,
- useActiveLayer,
- useWallItems,
- useLayers,
- useUpdateScene,
- useWalls,
- useDeletedLines,
- useNewLines,
- useZonePoints,
- useZones,
-} from "../../../store/builder/store";
+import React from 'react';
-import * as Types from "../../../types/world/worldTypes";
-import * as CONSTANTS from "../../../types/world/worldConstants";
+export default function SocketResponses() {
-// import { setFloorItemApi } from "../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
-import objectLineToArray from "../../builder/geomentries/lines/lineConvertions/objectLineToArray";
-import addLineToScene from "../../builder/geomentries/lines/addLineToScene";
-import updateLinesPositions from "../../builder/geomentries/lines/updateLinesPositions";
-import updateLines from "../../builder/geomentries/lines/updateLines";
-import updateDistanceText from "../../builder/geomentries/lines/updateDistanceText";
-import updateFloorLines from "../../builder/geomentries/floors/updateFloorLines";
-import loadWalls from "../../builder/geomentries/walls/loadWalls";
-import RemoveConnectedLines from "../../builder/geomentries/lines/removeConnectedLines";
-import Layer2DVisibility from "../../builder/geomentries/layers/layer2DVisibility";
-import { retrieveGLTF, storeGLTF } from "../../../utils/indexDB/idbUtils";
-import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi";
-import { useParams } from "react-router-dom";
-import { getUserData } from "../../../functions/getUserData";
-import { useSceneContext } from "../../scene/sceneContext";
-import { useVersionContext } from "../../builder/version/versionContext";
-
-export default function SocketResponses({
- floorPlanGroup,
- lines,
- floorGroup,
- scene,
- onlyFloorlines,
- currentLayerPoint,
- floorPlanGroupPoint,
- floorPlanGroupLine,
- dragPointControls,
-}: any) {
- const { socket } = useSocketStore();
- const { activeLayer, setActiveLayer } = useActiveLayer();
- const { wallItems, setWallItems } = useWallItems();
- const { setLayers } = useLayers();
- const { setUpdateScene } = useUpdateScene();
- const { setWalls } = useWalls();
- const { setDeletedLines } = useDeletedLines();
- const { setNewLines } = useNewLines();
- const { zones, setZones } = useZones();
- const { zonePoints, setZonePoints } = useZonePoints();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { projectId } = useParams();
- const { assetStore, eventStore, productStore } = useSceneContext();
- const { addAsset, updateAsset, removeAsset } = assetStore();
- const { organization } = getUserData();
-
- useEffect(() => {
-
- if (!socket) return;
-
- socket.on("cameraCreateResponse", (data: any) => {
- //
- });
-
- socket.on("userConnectRespones", (data: any) => {
- //
- });
-
- socket.on("userDisConnectRespones", (data: any) => {
- //
- });
-
- socket.on("v1:camera:Response:update", (data: any) => {
- //
- });
-
- socket.on("EnvironmentUpdateResponse", (data: any) => {
- //
- });
-
- socket.on("v1:model-asset:response:add", async (data: any) => {
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
- if (data.message === "Model created successfully") {
- try {
-
- const asset: Asset = {
- modelUuid: data.data.modelUuid,
- modelName: data.data.modelName,
- assetId: data.data.assetId,
- position: data.data.position,
- rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z],
- isLocked: data.data.isLocked,
- isCollidable: false,
- isVisible: data.data.isVisible,
- opacity: 1,
- }
-
- addAsset(asset);
-
- echo.success("Added model through collaboration");
- } catch (error) {
- echo.error("Failed to create model through collaboration");
- }
- } else if (data.message === "Model updated successfully") {
- try {
-
- const asset: Asset = {
- modelUuid: data.data.modelUuid,
- modelName: data.data.modelName,
- assetId: data.data.assetId,
- position: data.data.position,
- rotation: [data.data.rotation.x, data.data.rotation.y, data.data.rotation.z],
- isLocked: data.data.isLocked,
- isCollidable: false,
- isVisible: data.data.isVisible,
- opacity: 1,
- }
-
- updateAsset(asset.modelUuid, {
- position: asset.position,
- rotation: asset.rotation,
- });
-
- echo.success("Updated model through collaboration");
- } catch (error) {
- echo.error("Failed to update model through collaboration");
- }
- } else {
- echo.error("Failed executing action from collaboration");
- }
- });
-
- socket.on("v1:model-asset:response:delete", (data: any) => {
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
- if (data.message === "Model deleted successfully") {
- try {
- const deletedUUID = data.data.modelUuid;
-
- eventStore.getState().removeEvent(deletedUUID);
- productStore.getState().deleteEvent(deletedUUID);
-
- removeAsset(deletedUUID);
-
- echo.success("Model Removed successfully through collaboration");
- } catch (error) {
- echo.error("Failed to remove model through collaboration");
- }
- }
- });
-
- socket.on("v1:Line:response:update", (data: any) => {
- // console.log('data: ', data);
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
- if (data.message === "line updated") {
- const DraggedUUID = data.data.uuid;
- const DraggedPosition = new THREE.Vector3(
- data.data.position.x,
- data.data.position.y,
- data.data.position.z
- );
-
- const point = floorPlanGroupPoint.current.getObjectByProperty(
- "uuid",
- DraggedUUID
- );
- point.position.set(
- DraggedPosition.x,
- DraggedPosition.y,
- DraggedPosition.z
- );
- const affectedLines = updateLinesPositions(
- { uuid: DraggedUUID, position: DraggedPosition },
- lines
- );
-
- updateLines(floorPlanGroupLine, affectedLines);
- updateDistanceText(scene, floorPlanGroupLine, affectedLines);
- updateFloorLines(onlyFloorlines, {
- uuid: DraggedUUID,
- position: DraggedPosition,
- });
-
- loadWalls(lines, setWalls);
- setUpdateScene(true);
- }
- });
-
- socket.on("v1:Line:response:delete", (data: any) => {
- // console.log('data: ', data);
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
- if (data.message === "line deleted") {
- const line = objectLineToArray(data.data);
- const linePoints = line;
- const connectedpoints = [linePoints[0][1], linePoints[1][1]];
-
- onlyFloorlines.current = onlyFloorlines.current
- .map((floorline: any) =>
- floorline.filter(
- (line: any) =>
- line[0][1] !== connectedpoints[0] &&
- line[1][1] !== connectedpoints[1]
- )
- )
- .filter((floorline: any) => floorline.length > 0);
-
- const removedLine = lines.current.find(
- (item: any) =>
- (item[0][1] === linePoints[0][1] &&
- item[1][1] === linePoints[1][1]) ||
- (item[0][1] === linePoints[1][1] && item[1][1] === linePoints[0][1])
- );
- lines.current = lines.current.filter(
- (item: any) => item !== removedLine
- );
-
- floorPlanGroupLine.current.children.forEach((line: any) => {
- const linePoints = line.userData.linePoints as [
- number,
- string,
- number
- ][];
- const uuid1 = linePoints[0][1];
- const uuid2 = linePoints[1][1];
-
- if (
- (uuid1 === connectedpoints[0] && uuid2 === connectedpoints[1]) ||
- (uuid1 === connectedpoints[1] && uuid2 === connectedpoints[0])
- ) {
- line.material.dispose();
- line.geometry.dispose();
- floorPlanGroupLine.current.remove(line);
- setDeletedLines([line.userData.linePoints]);
- }
- });
-
- connectedpoints.forEach((pointUUID) => {
- let isConnected = false;
- floorPlanGroupLine.current.children.forEach((line: any) => {
- const linePoints = line.userData.linePoints;
- const uuid1 = linePoints[0][1];
- const uuid2 = linePoints[1][1];
- if (uuid1 === pointUUID || uuid2 === pointUUID) {
- isConnected = true;
- }
- });
-
- if (!isConnected) {
- floorPlanGroupPoint.current.children.forEach((point: any) => {
- if (point.uuid === pointUUID) {
- point.material.dispose();
- point.geometry.dispose();
- floorPlanGroupPoint.current.remove(point);
- }
- });
- }
- });
-
- loadWalls(lines, setWalls);
- setUpdateScene(true);
-
- echo.success("Line Removed!");
- }
- });
-
- socket.on("v1:Line:response:delete:point", (data: any) => {
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
- if (data.message === "point deleted") {
- const point = floorPlanGroupPoint.current?.getObjectByProperty(
- "uuid",
- data.data
- );
- point.material.dispose();
- point.geometry.dispose();
- floorPlanGroupPoint.current.remove(point);
-
- onlyFloorlines.current = onlyFloorlines.current
- .map((floorline: any) =>
- floorline.filter(
- (line: any) =>
- line[0][1] !== data.data && line[1][1] !== data.data
- )
- )
- .filter((floorline: any) => floorline.length > 0);
-
- RemoveConnectedLines(
- data.data,
- floorPlanGroupLine,
- floorPlanGroupPoint,
- setDeletedLines,
- lines
- );
-
- loadWalls(lines, setWalls);
- setUpdateScene(true);
-
- echo.success("Point Removed!");
- }
- });
-
- socket.on("v1:Line:response:delete:layer", async (data: any) => {
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
- if (data.message === "layer deleted") {
- setActiveLayer(1);
- const removedLayer = data.data;
- const removedLines: Types.Lines = lines.current.filter(
- (line: any) => line[0][2] === removedLayer
- );
-
- ////////// Remove Points and lines from the removed layer //////////
-
- removedLines.forEach(async (line) => {
- line.forEach(async (removedPoint) => {
- const removableLines: THREE.Mesh[] = [];
- const connectedpoints: string[] = [];
-
- floorPlanGroupLine.current.children.forEach((line: any) => {
- const linePoints = line.userData.linePoints as [
- number,
- string,
- number
- ][];
- const uuid1 = linePoints[0][1];
- const uuid2 = linePoints[1][1];
-
- if (uuid1 === removedPoint[1] || uuid2 === removedPoint[1]) {
- connectedpoints.push(uuid1 === removedPoint[1] ? uuid2 : uuid1);
- removableLines.push(line as THREE.Mesh);
- }
- });
-
- if (removableLines.length > 0) {
- removableLines.forEach((line: any) => {
- lines.current = lines.current.filter(
- (item: any) =>
- JSON.stringify(item) !==
- JSON.stringify(line.userData.linePoints)
- );
- line.material.dispose();
- line.geometry.dispose();
- floorPlanGroupLine.current.remove(line);
- });
- }
-
- const point = floorPlanGroupPoint.current.getObjectByProperty(
- "uuid",
- removedPoint[1]
- );
- if (point) {
- point.material.dispose();
- point.geometry.dispose();
- floorPlanGroupPoint.current.remove(point);
- }
- });
- });
-
- ////////// Update the remaining lines layer values in the userData and in lines.current //////////
-
- let remaining = lines.current.filter(
- (line: any) => line[0][2] !== removedLayer
- );
- let updatedLines: Types.Lines = [];
- remaining.forEach((line: any) => {
- let newLines = JSON.parse(JSON.stringify(line));
- if (newLines[0][2] > removedLayer) {
- newLines[0][2] -= 1;
- newLines[1][2] -= 1;
- }
-
- const matchingLine = floorPlanGroupLine.current.children.find(
- (l: any) =>
- l.userData.linePoints[0][1] === line[0][1] &&
- l.userData.linePoints[1][1] === line[1][1]
- );
- if (matchingLine) {
- const updatedUserData = JSON.parse(
- JSON.stringify(matchingLine.userData)
- );
- updatedUserData.linePoints[0][2] = newLines[0][2];
- updatedUserData.linePoints[1][2] = newLines[1][2];
- matchingLine.userData = updatedUserData;
- }
- updatedLines.push(newLines);
- });
-
- lines.current = updatedLines;
- localStorage.setItem("Lines", JSON.stringify(lines.current));
-
- ////////// Also remove OnlyFloorLines and update it in localstorage //////////
-
- onlyFloorlines.current = onlyFloorlines.current.filter((floor: any) => {
- return floor[0][0][2] !== removedLayer;
- });
- const meshToRemove = floorGroup.current?.children.find(
- (mesh: any) => mesh.name === `Only_Floor_Line_${removedLayer}`
- );
- if (meshToRemove) {
- meshToRemove.geometry.dispose();
- meshToRemove.material.dispose();
- floorGroup.current?.remove(meshToRemove);
- }
-
- const zonesData = await getZonesApi(organization, projectId, selectedVersion?.versionId || '');
- const highestLayer = Math.max(
- 1,
- lines.current.reduce(
- (maxLayer: number, segment: any) =>
- Math.max(maxLayer, segment.layer || 0),
- 0
- ),
- zonesData.reduce(
- (maxLayer: number, zone: any) =>
- Math.max(maxLayer, zone.layer || 0),
- 0
- )
- );
-
- setLayers(highestLayer);
-
- loadWalls(lines, setWalls);
- setUpdateScene(true);
-
- echo.success("Layer Removed!");
- }
- });
-
- return () => {
- socket.off("cameraCreateResponse");
- socket.off("userConnectRespones");
- socket.off("userDisConnectRespones");
- socket.off("v1:camera:Response:update");
- socket.off("EnvironmentUpdateResponse");
- socket.off("v1:model-asset:response:add");
- socket.off("v1:model-asset:response:delete");
- socket.off("v1:Line:response:update");
- socket.off("v1:Line:response:delete");
- socket.off("v1:Line:response:delete:point");
- socket.off("v1:Line:response:delete:layer");
- }
- }, [socket, selectedVersion?.versionId]);
-
- useEffect(() => {
- if (!socket) return;
- let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
-
- socket.on("v1:wallItem:Response:Delete", (data: any) => {
- // console.log('data: ', data);
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
- if (data.message === "wall Item deleted successfully") {
- const deletedUUID = data.data.modelUuid;
- let WallItemsRef = wallItems;
- const Items = WallItemsRef.filter((item: any) => item.model?.uuid !== deletedUUID);
-
- setWallItems([]);
- setTimeout(async () => {
- WallItemsRef = Items;
- setWallItems(WallItemsRef);
- const WallItemsForStorage = WallItemsRef.map((item: any) => {
- const { model, ...rest } = item;
- return {
- ...rest,
- modelUuid: model?.uuid,
- };
- });
-
- localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
- echo.success("Model Removed!");
- }, 50);
- }
- });
-
- socket.on("v1:wallItems:Response:Update", (data: any) => {
- // console.log('data: ', data);
- //
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
- if (data.message === "wall Item created successfully") {
- 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);
-
- // Check THREE.js cache first
- const cachedModel = THREE.Cache.get(data.data.assetId);
- if (cachedModel) {
- handleModelLoad(cachedModel);
- return;
- }
-
- // Check IndexedDB cache
- retrieveGLTF(data.data.assetId).then((cachedModelBlob) => {
- if (cachedModelBlob) {
- const blobUrl = URL.createObjectURL(cachedModelBlob);
- loader.load(blobUrl, (gltf) => {
- URL.revokeObjectURL(blobUrl);
- THREE.Cache.remove(blobUrl);
- THREE.Cache.add(data.data.assetId, gltf);
- handleModelLoad(gltf);
- });
- return;
- }
- })
-
- // Load from backend if not in any cache
- loader.load(`${url_Backend_dwinzo}/api/v2/AssetFile/${data.data.assetId}`, async (gltf) => {
- try {
- const modelBlob = await fetch(`${url_Backend_dwinzo}/api/v2/AssetFile/${data.data.assetId}`).then((res) => res.blob());
- await storeGLTF(data.data.assetId, modelBlob);
- THREE.Cache.add(data.data.assetId, gltf);
- await handleModelLoad(gltf);
- } catch (error) {
-
- handleModelLoad(gltf);
- }
- });
-
- async function handleModelLoad(gltf: GLTF) {
- const model = gltf.scene.clone();
- model.uuid = data.data.modelUuid;
-
- model.children[0].children.forEach((child) => {
- if (child.name !== "CSG_REF") {
- child.castShadow = true;
- child.receiveShadow = true;
- }
- });
-
- const newWallItem = {
- type: data.data.type,
- model: model,
- modelName: data.data.modelName,
- assetId: data.data.assetId,
- scale: data.data.scale,
- csgscale: data.data.csgscale,
- csgposition: data.data.csgposition,
- position: data.data.position,
- quaternion: data.data.quaternion,
- };
-
- setWallItems((prevItems: Types.wallItems) => {
- const updatedItems = [...prevItems, newWallItem];
-
- const WallItemsForStorage = updatedItems.map(item => {
- const { model, ...rest } = item;
- return {
- ...rest,
- modelUuid: model?.uuid,
- };
- });
-
- localStorage.setItem("WallItems", JSON.stringify(WallItemsForStorage));
- echo.success("Model Added!");
- return updatedItems;
- });
- }
-
- } else if (data.message === "Updated successfully") {
- const updatedUUID = data.data.modelUuid;
-
- setWallItems((prevItems: any) => {
- const updatedItems = prevItems.map((item: any) => {
- if (item.model.uuid === updatedUUID) {
- return {
- ...item,
- position: data.data.position,
- quaternion: data.data.quaternion,
- scale: data.data.scale,
- csgscale: data.data.csgscale,
- csgposition: data.data.csgposition,
- };
- }
- return item;
- });
-
- const WallItemsForStorage = updatedItems.map((item: any) => {
- const { model, ...rest } = item;
- return {
- ...rest,
- modelUuid: model?.uuid,
- };
- });
-
- localStorage.setItem(
- "WallItems",
- JSON.stringify(WallItemsForStorage)
- );
- echo.success("Model Updated!");
-
- return updatedItems;
- });
- }
- });
-
- return () => {
- socket.off("v1:wallItem:Response:Delete");
- socket.off("v1:wallItems:Response:Update");
- };
- }, [socket, wallItems]);
-
- function getPointColor(lineType: string | undefined): string {
- switch (lineType) {
- case CONSTANTS.lineConfig.wallName:
- return CONSTANTS.pointConfig.wallOuterColor;
- case CONSTANTS.lineConfig.floorName:
- return CONSTANTS.pointConfig.floorOuterColor;
- case CONSTANTS.lineConfig.aisleName:
- return CONSTANTS.pointConfig.aisleOuterColor;
- default:
- return CONSTANTS.pointConfig.defaultOuterColor;
- }
- }
-
- function getLineColor(lineType: string | undefined): string {
- switch (lineType) {
- case CONSTANTS.lineConfig.wallName:
- return CONSTANTS.lineConfig.wallColor;
- case CONSTANTS.lineConfig.floorName:
- return CONSTANTS.lineConfig.floorColor;
- case CONSTANTS.lineConfig.aisleName:
- return CONSTANTS.lineConfig.aisleColor;
- default:
- return CONSTANTS.lineConfig.defaultColor;
- }
- }
-
- useEffect(() => {
- if (!socket) return;
-
- socket.on("v1:Line:response:create", async (data: any) => {
- //
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
- if (data.message === "line create") {
- const line: Types.Line = objectLineToArray(data.data);
- const type = line[0][3];
- const pointColour = getPointColor(type);
- const lineColour = getLineColor(type);
- setNewLines([line]);
-
- line.forEach((line) => {
- const existingPoint =
- floorPlanGroupPoint.current?.getObjectByProperty("uuid", line[1]);
- if (existingPoint) {
- return;
- }
- const geometry = new THREE.BoxGeometry(
- ...CONSTANTS.pointConfig.boxScale
- );
- const material = new THREE.ShaderMaterial({
- uniforms: {
- uOuterColor: { value: new THREE.Color(pointColour) }, // Blue color for the border
- uInnerColor: {
- value: new THREE.Color(CONSTANTS.pointConfig.defaultInnerColor),
- }, // White color for the inner square
- },
- vertexShader: `
- varying vec2 vUv;
-
- void main() {
- vUv = uv;
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
- }
- `,
- fragmentShader: `
- varying vec2 vUv;
- uniform vec3 uOuterColor;
- uniform vec3 uInnerColor;
-
- void main() {
- // Define the size of the white square as a proportion of the face
- float borderThickness = 0.2; // Adjust this value for border thickness
- if (vUv.x > borderThickness && vUv.x < 1.0 - borderThickness &&
- vUv.y > borderThickness && vUv.y < 1.0 - borderThickness) {
- gl_FragColor = vec4(uInnerColor, 1.0); // White inner square
- } else {
- gl_FragColor = vec4(uOuterColor, 1.0); // Blue border
- }
- }
- `,
- });
- const point = new THREE.Mesh(geometry, material);
- point.name = "point";
- point.uuid = line[1];
- point.userData = { type: type, color: pointColour };
- point.position.set(line[0].x, line[0].y, line[0].z);
- currentLayerPoint.current.push(point);
-
- floorPlanGroupPoint.current?.add(point);
- });
- if (dragPointControls.current) {
- dragPointControls.current!.objects = currentLayerPoint.current;
- }
- addLineToScene(
- new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z),
- new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z),
- lineColour,
- line,
- floorPlanGroupLine
- );
- lines.current.push(line);
-
- const zonesData = await getZonesApi(organization, projectId, selectedVersion?.versionId || '');
- const highestLayer = Math.max(
- 1,
- lines.current.reduce(
- (maxLayer: number, segment: any) =>
- Math.max(maxLayer, segment.layer || 0),
- 0
- ),
- zonesData.reduce(
- (maxLayer: number, zone: any) =>
- Math.max(maxLayer, zone.layer || 0),
- 0
- )
- );
-
- setLayers(highestLayer);
-
- Layer2DVisibility(
- activeLayer,
- floorPlanGroup,
- floorPlanGroupLine,
- floorPlanGroupPoint,
- currentLayerPoint,
- dragPointControls
- );
-
- loadWalls(lines, setWalls);
- setUpdateScene(true);
- }
- });
-
- return () => {
- socket.off("v1:Line:response:create");
- };
- }, [socket, activeLayer, selectedVersion?.versionId]);
-
- useEffect(() => {
- if (!socket) return;
-
- socket.on("v1:zone:response:updates", (data: any) => {
- // console.log('data: ', data);
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
-
- if (data.message === "zone created") {
- const pointsArray: [number, number, number][] = data.data.points;
- const vector3Array = pointsArray.map(
- ([x, y, z]) => new THREE.Vector3(x, y, z)
- );
- const newZones = [...zones, data.data];
- setZones(newZones);
- const updatedZonePoints = [...zonePoints, ...vector3Array];
- setZonePoints(updatedZonePoints);
-
- const highestLayer = Math.max(
- 1,
- lines.current.reduce(
- (maxLayer: number, segment: any) =>
- Math.max(maxLayer, segment.layer || 0),
- 0
- ),
- newZones.reduce(
- (maxLayer: number, zone: any) =>
- Math.max(maxLayer, zone.layer || 0),
- 0
- )
- );
-
- setLayers(highestLayer);
- setUpdateScene(true);
- }
-
- if (data.message === "zone updated") {
- const updatedZones = zones.map((zone: any) =>
- zone.zoneUuid === data.data.zoneUuid ? data.data : zone
- );
- setZones(updatedZones);
- setUpdateScene(true);
- }
- });
-
- socket.on("v1:zone:response:delete", (data: any) => {
- // console.log('data: ', data);
- if (socket.id === data.socketId) {
- return;
- }
- if (organization !== data.organization) {
- return;
- }
- if (data.message === "zone deleted") {
- const updatedZones = zones.filter(
- (zone: any) => zone.zoneUuid !== data.data.zoneUuid
- );
- setZones(updatedZones);
-
- const zoneIndex = zones.findIndex(
- (zone: any) => zone.zoneUuid === data.data.zoneUuid
- );
- if (zoneIndex !== -1) {
- const updatedzonePoints = zonePoints.filter(
- (_: any, index: any) =>
- index < zoneIndex * 4 || index >= zoneIndex * 4 + 4
- );
- setZonePoints(updatedzonePoints);
- }
-
- const highestLayer = Math.max(
- 1,
- lines.current.reduce(
- (maxLayer: number, segment: any) =>
- Math.max(maxLayer, segment.layer || 0),
- 0
- ),
- updatedZones.reduce(
- (maxLayer: number, zone: any) =>
- Math.max(maxLayer, zone.layer || 0),
- 0
- )
- );
-
- setLayers(highestLayer);
- setUpdateScene(true);
- }
- });
-
- return () => {
- socket.off("v1:zone:response:updates");
- socket.off("v1:zone:response:delete");
- };
- }, [socket, zones, zonePoints]);
-
- return <>>;
+ return (
+ <>
+ >
+ );
}
diff --git a/app/src/modules/market/MarketPlace.tsx b/app/src/modules/market/MarketPlace.tsx
index 1bf446e..85720d2 100644
--- a/app/src/modules/market/MarketPlace.tsx
+++ b/app/src/modules/market/MarketPlace.tsx
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from "react";
import FilterSearch from "./FilterSearch";
import CardsContainer from "./CardsContainer";
-import { getAssetImages } from "../../services/factoryBuilder/assest/assets/getAssetImages";
+import { getAssetImages } from "../../services/factoryBuilder/asset/assets/getAssetImages";
import SkeletonUI from "../../components/templates/SkeletonUI";
interface ModelData {
CreatedBy: string;
diff --git a/app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx b/app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx
index 05b43c6..b30b03e 100644
--- a/app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx
+++ b/app/src/modules/scene/controls/selectionControls/boundingBoxHelper.tsx
@@ -51,7 +51,7 @@ const BoundingBox = ({ boundingBoxRef, isPerAsset = true }: BoundingBoxProps) =>
return {
points: getBoxLines(min, max),
- position: [position.x, center.y, position.z],
+ position: [position.x, position.y, position.z],
rotation: rotation.toArray(),
size: size.toArray(),
};
@@ -93,7 +93,7 @@ const BoundingBox = ({ boundingBoxRef, isPerAsset = true }: BoundingBoxProps) =>
color={savedTheme === "dark" ? "#c4abf1" : "#6f42c1"}
lineWidth={2.7}
segments
- position={[box.position[0], 0, box.position[2]]}
+ position={[box.position[0], box.position[1], box.position[2]]}
quaternion={new THREE.Quaternion(...box.rotation)}
/>
;
- 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/modules/scene/controls/selectionControls/duplicationControls.tsx b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx
index ef56601..5194952 100644
--- a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx
@@ -2,7 +2,7 @@ import * as THREE from "three";
import { useEffect, useMemo } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/builder/store";
-// import { setAssetsApi } from '../../../../services/factoryBuilder/assest/floorAsset/setAssetsApi';
+// import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
import * as Types from "../../../../types/world/worldTypes";
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
import { useParams } from "react-router-dom";
diff --git a/app/src/modules/scene/controls/selectionControls/moveControls.tsx b/app/src/modules/scene/controls/selectionControls/moveControls.tsx
index 70d32e9..79cf195 100644
--- a/app/src/modules/scene/controls/selectionControls/moveControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/moveControls.tsx
@@ -2,7 +2,7 @@ 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/assest/floorAsset/setAssetsApi';
+// 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";
@@ -165,10 +165,21 @@ function MoveControls({
if (movedObjects.length > 0) {
const intersectionPoint = new THREE.Vector3();
raycaster.setFromCamera(pointer, camera);
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+ let point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+ const floorsGroup = scene.getObjectByName("Floors-Group") as Types.Group | null;
+ const floorChildren = floorsGroup?.children ?? [];
+ const floorIntersections = raycaster.intersectObjects([...floorChildren], true);
+ const intersectedFloor = floorIntersections.find((intersect) => intersect.object.name.includes("Floor"));
+
+ if (intersectedFloor && selectedAssets.length === 1) {
+ if (intersectedFloor.object.userData.floorUuid) {
+ point = new THREE.Vector3(intersectedFloor.point.x, intersectedFloor.object.userData.floorDepth, intersectedFloor.point.z);
+ }
+ }
if (point) {
let targetX = point.x;
+ let targetY = point.y;
let targetZ = point.z;
if (keyEvent === "Ctrl") {
@@ -192,7 +203,7 @@ function MoveControls({
selectionGroup.current.position.lerp(
new THREE.Vector3(
targetX - (position.x - selectionGroup.current.position.x),
- selectionGroup.current.position.y,
+ targetY - (position.y - selectionGroup.current.position.y),
targetZ - (position.z - selectionGroup.current.position.z)
),
moveSpeed
@@ -230,9 +241,13 @@ function MoveControls({
movedObjects.forEach(async (obj: THREE.Object3D) => {
if (obj && AssetGroup.current) {
- const worldPosition = new THREE.Vector3();
+ let worldPosition = new THREE.Vector3();
obj.getWorldPosition(worldPosition);
+ if (worldPosition.y < 0) {
+ worldPosition.y = 0;
+ }
+
selectionGroup.current.remove(obj);
obj.position.copy(worldPosition);
diff --git a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
index 6592e72..216d4f7 100644
--- a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
@@ -2,7 +2,7 @@ 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/assest/floorAsset/setAssetsApi';
+// import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
import * as Types from "../../../../types/world/worldTypes";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
import { useParams } from "react-router-dom";
diff --git a/app/src/modules/scene/controls/selectionControls/selectionControls.tsx b/app/src/modules/scene/controls/selectionControls/selectionControls.tsx
index 1f26a6b..645ed1c 100644
--- a/app/src/modules/scene/controls/selectionControls/selectionControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selectionControls.tsx
@@ -5,7 +5,7 @@ import { SelectionHelper } from "./selectionHelper";
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/assest/floorAsset/deleteFloorItemApi';
+// import { deleteFloorItem } from '../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi';
import * as Types from "../../../../types/world/worldTypes";
import DuplicationControls from "./duplicationControls";
@@ -225,7 +225,7 @@ const SelectionControls: React.FC = () => {
selectedObjects.forEach((object) => {
let currentObject: THREE.Object3D | null = object;
while (currentObject) {
- if (currentObject.userData.modelUuid) {
+ if (currentObject.userData.modelUuid && !currentObject.userData.wallAssetType) {
Objects.add(currentObject);
break;
}
diff --git a/app/src/modules/scene/controls/transformControls/transformControls.tsx b/app/src/modules/scene/controls/transformControls/transformControls.tsx
index 0b6a061..e0ce1cf 100644
--- a/app/src/modules/scene/controls/transformControls/transformControls.tsx
+++ b/app/src/modules/scene/controls/transformControls/transformControls.tsx
@@ -6,7 +6,7 @@ import { useThree } from "@react-three/fiber";
import { useEffect, useState } from "react";
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
-// import { setAssetsApi } from "../../../../services/factoryBuilder/assest/floorAsset/setAssetsApi";
+// import { setAssetsApi } from "../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
import { useParams } from "react-router-dom";
import { useProductContext } from "../../../simulation/products/productContext";
import { getUserData } from "../../../../functions/getUserData";
diff --git a/app/src/modules/scene/environment/ground.tsx b/app/src/modules/scene/environment/ground.tsx
index ef51791..f6baeef 100644
--- a/app/src/modules/scene/environment/ground.tsx
+++ b/app/src/modules/scene/environment/ground.tsx
@@ -1,14 +1,13 @@
import { useTileDistance, useToggleView } from "../../../store/builder/store";
import * as CONSTANTS from "../../../types/world/worldConstants";
-const Ground = ({ grid, plane }: any) => {
+const Ground = ({ plane }: any) => {
const { toggleView } = useToggleView();
const { planeValue, gridValue } = useTileDistance();
return (
diff --git a/app/src/modules/scene/postProcessing/postProcessing.tsx b/app/src/modules/scene/postProcessing/postProcessing.tsx
index 25d0e0c..6c2f8d6 100644
--- a/app/src/modules/scene/postProcessing/postProcessing.tsx
+++ b/app/src/modules/scene/postProcessing/postProcessing.tsx
@@ -15,7 +15,7 @@ export default function PostProcessing() {
const { selectedWallItem } = useSelectedWallItem();
const { selectedFloorItem } = useSelectedFloorItem();
const { selectedEventSphere } = useSelectedEventSphere();
- const { selectedAisle, selectedWall, selectedDecal } = useBuilderStore();
+ const { selectedAisle, selectedWall, selectedDecal, selectedFloor, selectedWallAsset, deletableWallAsset } = useBuilderStore();
function flattenChildren(children: any[]) {
const allChildren: any[] = [];
@@ -44,6 +44,18 @@ export default function PostProcessing() {
// console.log('selectedWall: ', selectedWall);
}, [selectedWall])
+ useEffect(() => {
+ // console.log('selectedFloor: ', selectedFloor);
+ }, [selectedFloor])
+
+ useEffect(() => {
+ // console.log('selectedWallAsset: ', selectedWallAsset);
+ }, [selectedWallAsset])
+
+ useEffect(() => {
+ // console.log('deletableWallAsset: ', deletableWallAsset);
+ }, [deletableWallAsset])
+
return (
+ {selectedWallAsset && (
+
+ )}
+ {deletableWallAsset && (
+
+ )}
{selectedAisle && (
)}
+ {selectedFloor && (
+
+ )}
{selectedDecal && (
-
-
+
+
diff --git a/app/src/modules/simulation/vehicle/navMesh/navMeshDetails.tsx b/app/src/modules/simulation/vehicle/navMesh/navMeshDetails.tsx
index df660fe..106f652 100644
--- a/app/src/modules/simulation/vehicle/navMesh/navMeshDetails.tsx
+++ b/app/src/modules/simulation/vehicle/navMesh/navMeshDetails.tsx
@@ -9,11 +9,9 @@ import * as Types from "../../../../types/world/worldTypes";
interface NavMeshDetailsProps {
setNavMesh: (navMesh: any) => void;
groupRef: React.MutableRefObject;
- lines: Types.RefLines;
}
export default function NavMeshDetails({
- lines,
setNavMesh,
groupRef,
}: NavMeshDetailsProps) {
@@ -63,7 +61,7 @@ export default function NavMeshDetails({
};
initializeNavigation();
- }, [scene, groupRef, lines.current]);
+ }, [scene, groupRef]);
return null;
}
diff --git a/app/src/modules/simulation/vehicle/navMesh/polygonGenerator.tsx b/app/src/modules/simulation/vehicle/navMesh/polygonGenerator.tsx
index eaf5a24..34d9f26 100644
--- a/app/src/modules/simulation/vehicle/navMesh/polygonGenerator.tsx
+++ b/app/src/modules/simulation/vehicle/navMesh/polygonGenerator.tsx
@@ -2,26 +2,23 @@ import * as THREE from "three";
import { useEffect } from "react";
import * as turf from "@turf/turf";
import * as Types from "../../../../types/world/worldTypes";
-import arrayLinesToObject from "../../../builder/geomentries/lines/lineConvertions/arrayLinesToObject";
import { useThree } from "@react-three/fiber";
import { useSceneContext } from "../../../scene/sceneContext";
interface PolygonGeneratorProps {
groupRef: React.MutableRefObject;
- lines: Types.RefLines;
}
export default function PolygonGenerator({
groupRef,
- lines,
}: PolygonGeneratorProps) {
const { aisleStore } = useSceneContext();
const { aisles } = aisleStore();
const { scene } = useThree();
useEffect(() => {
- let allLines = arrayLinesToObject(lines.current);
- const wallLines = allLines?.filter((line) => line?.type === "WallLine");
+ // let allLines = arrayLinesToObject(lines.current);
+ // const wallLines = allLines?.filter((line) => line?.type === "WallLine");
const result = aisles
.filter(
(aisle) =>
@@ -64,9 +61,9 @@ export default function PolygonGenerator({
});
});
- const wallPoints = wallLines
- .map((pair) => pair?.line.map((vals) => vals.position))
- .filter((wall): wall is THREE.Vector3[] => !!wall);
+ // const wallPoints = wallLines
+ // .map((pair) => pair?.line.map((vals) => vals.position))
+ // .filter((wall): wall is THREE.Vector3[] => !!wall);
if (!result || result.some((line) => !line)) {
@@ -84,7 +81,7 @@ export default function PolygonGenerator({
const polygons = turf.polygonize(turf.featureCollection(validLineFeatures));
- renderWallGeometry(wallPoints);
+ // renderWallGeometry(wallPoints);
if (polygons.features.length > 0) {
polygons.features.forEach((feature) => {
@@ -119,7 +116,7 @@ export default function PolygonGenerator({
});
}
- }, [lines.current, aisles, scene]);
+ }, [ aisles, scene]);
const renderWallGeometry = (walls: THREE.Vector3[][]) => {
walls.forEach((wall) => {
diff --git a/app/src/services/factoryBuilder/aisle/deleteAisleApi.ts b/app/src/services/factoryBuilder/aisle/deleteAisleApi.ts
index 5ef96a3..28fde46 100644
--- a/app/src/services/factoryBuilder/aisle/deleteAisleApi.ts
+++ b/app/src/services/factoryBuilder/aisle/deleteAisleApi.ts
@@ -10,7 +10,7 @@ export const deleteAisleApi = async (aisleUuid: string, projectId: string, versi
token: localStorage.getItem("token") || "", // Coerce null to empty string
refresh_token: localStorage.getItem("refreshToken") || "",
},
- body: JSON.stringify({ aisleUuid, projectId }),
+ body: JSON.stringify({ aisleUuid, projectId, versionId }),
});
const newAccessToken = response.headers.get("x-access-token");
if (newAccessToken) {
diff --git a/app/src/services/factoryBuilder/aisle/createAisleApi.ts b/app/src/services/factoryBuilder/aisle/upsertAisleApi.ts
similarity index 97%
rename from app/src/services/factoryBuilder/aisle/createAisleApi.ts
rename to app/src/services/factoryBuilder/aisle/upsertAisleApi.ts
index 27ae378..b980c61 100644
--- a/app/src/services/factoryBuilder/aisle/createAisleApi.ts
+++ b/app/src/services/factoryBuilder/aisle/upsertAisleApi.ts
@@ -1,6 +1,6 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-export const createAisleApi = async (
+export const upsertAisleApi = async (
aisleUuid: string,
points: any,
type: Object,
diff --git a/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts
deleted file mode 100644
index 84dee42..0000000
--- a/app/src/services/factoryBuilder/assest/wallAsset/deleteWallItemApi.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const deleteWallItem = async (
- organization: string,
- modelUuid: string,
- modelName: string
-) => {
- try {
- const response = await fetch(
- `${url_Backend_dwinzo}/api/v1/deleteWallItem`,
- {
- method: "DELETE",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- body: JSON.stringify({ organization, modelUuid, modelName }),
- }
- );
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
-
- if (!response.ok) {
- console.error("Failed to delete Wall Item");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to delete wall items");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts
deleted file mode 100644
index 55a09f0..0000000
--- a/app/src/services/factoryBuilder/assest/wallAsset/getWallItemsApi.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const getWallItems = async (organization: string, projectId?: string, versionId?: string) => {
- try {
- const response = await fetch(
- `${url_Backend_dwinzo}/api/V1/walls/${projectId}/${versionId}`,
- {
- method: "GET",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- }
- );
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
- // console.log('response: ', response);
- if (!response.ok) {
- console.error("Failed to get Wall Items");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to get wall items");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts b/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts
deleted file mode 100644
index b7a0dbd..0000000
--- a/app/src/services/factoryBuilder/assest/wallAsset/setWallItemApi.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const setWallItem = async (
- organization: string,
- modelUuid: string,
- modelName: string,
- type: string,
- csgposition: Object,
- csgscale: Object,
- position: Object,
- quaternion: Object,
- scale: Object
-) => {
- try {
- const response = await fetch(`${url_Backend_dwinzo}/api/v1/setWallItems`, {
- method: "POST",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- body: JSON.stringify({
- organization,
- modelUuid,
- modelName,
- position,
- type,
- csgposition,
- csgscale,
- quaternion,
- scale,
- }),
- });
-
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
- if (!response.ok) {
- console.error("Failed to set or update Wall Item");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to set wall items");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/assest/assets/getAssetImages.ts b/app/src/services/factoryBuilder/asset/assets/getAssetImages.ts
similarity index 96%
rename from app/src/services/factoryBuilder/assest/assets/getAssetImages.ts
rename to app/src/services/factoryBuilder/asset/assets/getAssetImages.ts
index faba588..7bc7fca 100644
--- a/app/src/services/factoryBuilder/assest/assets/getAssetImages.ts
+++ b/app/src/services/factoryBuilder/asset/assets/getAssetImages.ts
@@ -1,24 +1,24 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
-
-export const getAssetImages = async (cursor?: string) => {
- try {
- const response = await fetch(
- `${url_Backend_dwinzo}/api/v3/AssetDatas?limit=10${cursor ? `&cursor=${cursor}` : ""}`,
- {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- },
- }
- );
-
- if (!response.ok) {
- console.error("Failed to fetch assets");
- }
-
- return await response.json();
- } catch (error: any) {
- echo.error("Failed to get asset image");
- console.log(error.message);
- }
-};
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
+
+export const getAssetImages = async (cursor?: string) => {
+ try {
+ const response = await fetch(
+ `${url_Backend_dwinzo}/api/v3/AssetDatas?limit=10${cursor ? `&cursor=${cursor}` : ""}`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ if (!response.ok) {
+ console.error("Failed to fetch assets");
+ }
+
+ return await response.json();
+ } catch (error: any) {
+ echo.error("Failed to get asset image");
+ console.log(error.message);
+ }
+};
diff --git a/app/src/services/factoryBuilder/assest/assets/getAssetModel.ts b/app/src/services/factoryBuilder/asset/assets/getAssetModel.ts
similarity index 96%
rename from app/src/services/factoryBuilder/assest/assets/getAssetModel.ts
rename to app/src/services/factoryBuilder/asset/assets/getAssetModel.ts
index 91c33b3..27fe88a 100644
--- a/app/src/services/factoryBuilder/assest/assets/getAssetModel.ts
+++ b/app/src/services/factoryBuilder/asset/assets/getAssetModel.ts
@@ -1,29 +1,29 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
-
-export const getAssetModel = async (modelId: string) => {
- try {
- const response = await fetch(
- `${url_Backend_dwinzo}/api/v2/AssetFile/${modelId}`,
- {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- },
- }
- );
-
- if (!response.ok) {
- console.error("Failed to fetch model");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to get asset model");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
+
+export const getAssetModel = async (modelId: string) => {
+ try {
+ const response = await fetch(
+ `${url_Backend_dwinzo}/api/v2/AssetFile/${modelId}`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ if (!response.ok) {
+ console.error("Failed to fetch model");
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to get asset model");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/assest/assets/getCategoryAsset.ts b/app/src/services/factoryBuilder/asset/assets/getCategoryAsset.ts
similarity index 100%
rename from app/src/services/factoryBuilder/assest/assets/getCategoryAsset.ts
rename to app/src/services/factoryBuilder/asset/assets/getCategoryAsset.ts
diff --git a/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts b/app/src/services/factoryBuilder/asset/floorAsset/deleteFloorItemApi.ts
similarity index 96%
rename from app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts
rename to app/src/services/factoryBuilder/asset/floorAsset/deleteFloorItemApi.ts
index a509909..1e66ec7 100644
--- a/app/src/services/factoryBuilder/assest/floorAsset/deleteFloorItemApi.ts
+++ b/app/src/services/factoryBuilder/asset/floorAsset/deleteFloorItemApi.ts
@@ -1,42 +1,42 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const deleteFloorItem = async (
- organization: string,
- modelUuid: string,
- modelName: string
-) => {
- try {
- const response = await fetch(
- `${url_Backend_dwinzo}/api/v1/deletefloorItem`,
- {
- method: "DELETE",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- body: JSON.stringify({ organization, modelUuid, modelName }),
- }
- );
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
-
- if (!response.ok) {
- console.error("Failed to delete Floor Item");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to delete floor item");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const deleteFloorItem = async (
+ organization: string,
+ modelUuid: string,
+ modelName: string
+) => {
+ try {
+ const response = await fetch(
+ `${url_Backend_dwinzo}/api/v1/deletefloorItem`,
+ {
+ method: "DELETE",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ body: JSON.stringify({ organization, modelUuid, modelName }),
+ }
+ );
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ //console.log("New token received:", newAccessToken);
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ if (!response.ok) {
+ console.error("Failed to delete Floor Item");
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to delete floor item");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts b/app/src/services/factoryBuilder/asset/floorAsset/getFloorItemsApi.ts
similarity index 96%
rename from app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts
rename to app/src/services/factoryBuilder/asset/floorAsset/getFloorItemsApi.ts
index 83038fc..5ead053 100644
--- a/app/src/services/factoryBuilder/assest/floorAsset/getFloorItemsApi.ts
+++ b/app/src/services/factoryBuilder/asset/floorAsset/getFloorItemsApi.ts
@@ -1,39 +1,39 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const getFloorAssets = async (organization: string, projectId?: string, versionId?: string) => {
- try {
- const response = await fetch(
- `${url_Backend_dwinzo}/api/V1/floorAssets/${projectId}/${versionId}`,
- {
- method: "GET",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- }
- );
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
-
- // console.log('response: ', response);
- if (!response.ok) {
- console.error("Failed to get assets");
- }
-
- const result = await response.json();
-
- return result;
- } catch (error) {
- echo.error("Failed to get floor asset");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const getFloorAssets = async (organization: string, projectId?: string, versionId?: string) => {
+ try {
+ const response = await fetch(
+ `${url_Backend_dwinzo}/api/V1/floorAssets/${projectId}/${versionId}`,
+ {
+ method: "GET",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ }
+ );
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ //console.log("New token received:", newAccessToken);
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ // console.log('response: ', response);
+ if (!response.ok) {
+ console.error("Failed to get assets");
+ }
+
+ const result = await response.json();
+
+ return result;
+ } catch (error) {
+ echo.error("Failed to get floor asset");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/assest/floorAsset/setAssetsApi.ts b/app/src/services/factoryBuilder/asset/floorAsset/setAssetsApi.ts
similarity index 100%
rename from app/src/services/factoryBuilder/assest/floorAsset/setAssetsApi.ts
rename to app/src/services/factoryBuilder/asset/floorAsset/setAssetsApi.ts
diff --git a/app/src/services/factoryBuilder/floor/deleteFloorApi.ts b/app/src/services/factoryBuilder/floor/deleteFloorApi.ts
new file mode 100644
index 0000000..3043646
--- /dev/null
+++ b/app/src/services/factoryBuilder/floor/deleteFloorApi.ts
@@ -0,0 +1,39 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const deleteFloorApi = async (
+ projectId: string,
+ versionId: string,
+ floorUuid: string
+) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/V1/deleteFloor`, {
+ method: "PATCH",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ body: JSON.stringify({ projectId, versionId, floorUuid }),
+ });
+
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ if (!response.ok) {
+ console.error("Failed to delete floor:", response.statusText);
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to delete floor");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/floor/getFloorsApi.ts b/app/src/services/factoryBuilder/floor/getFloorsApi.ts
new file mode 100644
index 0000000..2659e61
--- /dev/null
+++ b/app/src/services/factoryBuilder/floor/getFloorsApi.ts
@@ -0,0 +1,37 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const getFloorsApi = async (
+ projectId: string,
+ versionId: string,
+) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/V1/floors/${projectId}/${versionId}`, {
+ method: "GET",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ });
+
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ if (!response.ok) {
+ console.error("Failed to get floors:", response.statusText);
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to get floors");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/floor/upsertFloorApi.ts b/app/src/services/factoryBuilder/floor/upsertFloorApi.ts
new file mode 100644
index 0000000..45590c1
--- /dev/null
+++ b/app/src/services/factoryBuilder/floor/upsertFloorApi.ts
@@ -0,0 +1,39 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const upsertFloorApi = async (
+ projectId: string,
+ versionId: string,
+ floorData: Floor
+) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/V1/UpsertFloor`, {
+ method: "POST",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ body: JSON.stringify({ projectId, versionId, floorData }),
+ });
+
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ if (!response.ok) {
+ console.error("Failed to upsert floor:", response.statusText);
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to upsert floor");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/lines/deleteLayerApi.ts b/app/src/services/factoryBuilder/lines/deleteLayerApi.ts
deleted file mode 100644
index f271061..0000000
--- a/app/src/services/factoryBuilder/lines/deleteLayerApi.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const deleteLayer = async (organization: string, layer: number) => {
- try {
- const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteLayer`, {
- method: "POST",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- body: JSON.stringify({ organization, layer }),
- });
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
- if (!response.ok) {
- console.error("Failed to delete line");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to delete line");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/lines/deleteLineApi.ts b/app/src/services/factoryBuilder/lines/deleteLineApi.ts
deleted file mode 100644
index bd04ee4..0000000
--- a/app/src/services/factoryBuilder/lines/deleteLineApi.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const deleteLineApi = async (organization: string, line: Object) => {
- try {
- const response = await fetch(`${url_Backend_dwinzo}/api/v1/deleteLine`, {
- method: "DELETE",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- body: JSON.stringify({ organization, line }),
- });
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
- if (!response.ok) {
- console.error("Failed to delete line");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to delete line");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/lines/deletePointApi.ts b/app/src/services/factoryBuilder/lines/deletePointApi.ts
deleted file mode 100644
index bc5b2d0..0000000
--- a/app/src/services/factoryBuilder/lines/deletePointApi.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const deletePointApi = async (organization: string, uuid: string) => {
- try {
- const response = await fetch(`${url_Backend_dwinzo}/api/v1/deletePoint`, {
- method: "DELETE",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- body: JSON.stringify({ organization, uuid }),
- });
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
-
- if (!response.ok) {
- console.error("Failed to delete point");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to delete point");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/lines/getLinesApi.ts b/app/src/services/factoryBuilder/lines/getLinesApi.ts
deleted file mode 100644
index ca520f1..0000000
--- a/app/src/services/factoryBuilder/lines/getLinesApi.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const getLines = async (organization: string, projectId?: string, versionId?: string) => {
- try {
- const response = await fetch(
- `${url_Backend_dwinzo}/api/V1/lines/${projectId}/${versionId}`,
- {
- method: "GET",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- }
- );
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
-
- if (!response.ok) {
- console.error("Failed to get Lines");
- }
-
- const result = await response.json();
- // console.log('result: ', result);
- return result;
- } catch (error) {
- echo.error("Failed to get Lines");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/lines/setLineApi.ts b/app/src/services/factoryBuilder/lines/setLineApi.ts
deleted file mode 100644
index 9269514..0000000
--- a/app/src/services/factoryBuilder/lines/setLineApi.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const setLine = async (
- organization: string,
- layer: number,
- line: Object,
- type: string
-) => {
- try {
- const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, {
- method: "POST",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- body: JSON.stringify({ organization, layer, line, type }),
- });
-
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
-
- if (!response.ok) {
- console.error("Failed to set line");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to set line");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/lines/updatePointApi.ts b/app/src/services/factoryBuilder/lines/updatePointApi.ts
deleted file mode 100644
index ae1b917..0000000
--- a/app/src/services/factoryBuilder/lines/updatePointApi.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const updatePoint = async (
- organization: string,
- position: Object,
- uuid: string
-) => {
- try {
- const response = await fetch(`${url_Backend_dwinzo}/api/v1/updatePoint`, {
- method: "POST",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- body: JSON.stringify({ organization, position, uuid }),
- });
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
- if (!response.ok) {
- console.error("Failed to update point");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to update point");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/wall/deleteWallApi.ts b/app/src/services/factoryBuilder/wall/deleteWallApi.ts
new file mode 100644
index 0000000..8a91d11
--- /dev/null
+++ b/app/src/services/factoryBuilder/wall/deleteWallApi.ts
@@ -0,0 +1,39 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const deleteWallApi = async (
+ projectId: string,
+ versionId: string,
+ wallUuid: string
+) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/V1/deleteWall`, {
+ method: "PATCH",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ body: JSON.stringify({ projectId, versionId, wallUuid }),
+ });
+
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ if (!response.ok) {
+ console.error("Failed to delete wall:", response.statusText);
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to delete wall");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/wall/getWallsApi.ts b/app/src/services/factoryBuilder/wall/getWallsApi.ts
new file mode 100644
index 0000000..b3f94b0
--- /dev/null
+++ b/app/src/services/factoryBuilder/wall/getWallsApi.ts
@@ -0,0 +1,37 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const getWallsApi = async (
+ projectId: string,
+ versionId: string,
+) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/V1/Walls/${projectId}/${versionId}`, {
+ method: "GET",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ });
+
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ if (!response.ok) {
+ console.error("Failed to get walls:", response.statusText);
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to get walls");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/wall/upsertWallApi.ts b/app/src/services/factoryBuilder/wall/upsertWallApi.ts
new file mode 100644
index 0000000..023da68
--- /dev/null
+++ b/app/src/services/factoryBuilder/wall/upsertWallApi.ts
@@ -0,0 +1,39 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const upsertWallApi = async (
+ projectId: string,
+ versionId: string,
+ wallData: Wall
+) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/V1/UpsertWall`, {
+ method: "POST",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ body: JSON.stringify({ projectId, versionId, wallData }),
+ });
+
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ if (!response.ok) {
+ console.error("Failed to upsert wall:", response.statusText);
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to upsert wall");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/zone/deleteZoneApi.ts b/app/src/services/factoryBuilder/zone/deleteZoneApi.ts
new file mode 100644
index 0000000..87b80dd
--- /dev/null
+++ b/app/src/services/factoryBuilder/zone/deleteZoneApi.ts
@@ -0,0 +1,39 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const deleteZoneApi = async (
+ projectId: string,
+ versionId: string,
+ zoneUuid: string
+) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/V1/zones/delete`, {
+ method: "PATCH",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ body: JSON.stringify({ projectId, versionId, zoneUuid }),
+ });
+
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ if (!response.ok) {
+ console.error("Failed to delete zone:", response.statusText);
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to delete zone");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/zone/getZonesApi.ts b/app/src/services/factoryBuilder/zone/getZonesApi.ts
new file mode 100644
index 0000000..f0ea687
--- /dev/null
+++ b/app/src/services/factoryBuilder/zone/getZonesApi.ts
@@ -0,0 +1,37 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const getZonesApi = async (
+ projectId: string,
+ versionId: string,
+) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/V1/zones/${projectId}/${versionId}`, {
+ method: "GET",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ });
+
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ if (!response.ok) {
+ console.error("Failed to get zones:", response.statusText);
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to get zones");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/zone/upsertZoneApi.ts b/app/src/services/factoryBuilder/zone/upsertZoneApi.ts
new file mode 100644
index 0000000..e19eae8
--- /dev/null
+++ b/app/src/services/factoryBuilder/zone/upsertZoneApi.ts
@@ -0,0 +1,39 @@
+let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
+
+export const upsertZoneApi = async (
+ projectId: string,
+ versionId: string,
+ zoneData: Zone
+) => {
+ try {
+ const response = await fetch(`${url_Backend_dwinzo}/api/V1/upsertZone`, {
+ method: "POST",
+ headers: {
+ Authorization: "Bearer ",
+ "Content-Type": "application/json",
+ token: localStorage.getItem("token") || "",
+ refresh_token: localStorage.getItem("refreshToken") || "",
+ },
+ body: JSON.stringify({ projectId, versionId, zoneData }),
+ });
+
+ const newAccessToken = response.headers.get("x-access-token");
+ if (newAccessToken) {
+ localStorage.setItem("token", newAccessToken);
+ }
+
+ if (!response.ok) {
+ console.error("Failed to upsert zone:", response.statusText);
+ }
+
+ const result = await response.json();
+ return result;
+ } catch (error) {
+ echo.error("Failed to upsert zone");
+ if (error instanceof Error) {
+ console.log(error.message);
+ } else {
+ console.log("An unknown error occurred");
+ }
+ }
+};
diff --git a/app/src/services/factoryBuilder/zones/deleteZoneApi.ts b/app/src/services/factoryBuilder/zones/deleteZoneApi.ts
deleted file mode 100644
index f0ee326..0000000
--- a/app/src/services/factoryBuilder/zones/deleteZoneApi.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const deleteZonesApi = async (
- userId: string,
- organization: string,
- zoneUuid: string
-) => {
- try {
- const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, {
- method: "POST",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- body: JSON.stringify({ userId, organization, zoneUuid }),
- });
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
- if (!response.ok) {
- console.error("Failed to delete zone");
- }
-
- const result = await response.json();
-
- return result;
- } catch (error) {
- echo.error("Failed to delete zone");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/zones/getZonesApi.ts b/app/src/services/factoryBuilder/zones/getZonesApi.ts
deleted file mode 100644
index 39f91a3..0000000
--- a/app/src/services/factoryBuilder/zones/getZonesApi.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-// let url_Backend_dwinzo = `http://192.168.0.102:5000`;
-
-export const getZonesApi = async (organization: string, projectId?: string, versionId?: string) => {
- try {
- const response = await fetch(
- `${url_Backend_dwinzo}/api/V1/zones/${projectId}/${versionId}`,
- {
- method: "GET",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- }
- );
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
-
- if (!response.ok) {
- console.error("Failed to get Zones");
- }
-
- const result = await response.json();
- // console.log('result:zone ', result);
-
- return result;
- } catch (error) {
- echo.error("Failed to get zone data");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/services/factoryBuilder/zones/setZonesApi.ts b/app/src/services/factoryBuilder/zones/setZonesApi.ts
deleted file mode 100644
index b5aa678..0000000
--- a/app/src/services/factoryBuilder/zones/setZonesApi.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
-
-export const setZonesApi = async (
- userId: string,
- organization: string,
- zoneData: any
-) => {
- try {
- const response = await fetch(`${url_Backend_dwinzo}/api/v1/setLine`, {
- method: "POST",
- headers: {
- Authorization: "Bearer ",
- "Content-Type": "application/json",
- token: localStorage.getItem("token") || "",
- refresh_token: localStorage.getItem("refreshToken") || "",
- },
- body: JSON.stringify({ userId, organization, zoneData }),
- });
- const newAccessToken = response.headers.get("x-access-token");
- if (newAccessToken) {
- //console.log("New token received:", newAccessToken);
- localStorage.setItem("token", newAccessToken);
- }
- if (!response.ok) {
- console.error("Failed to set zone");
- }
-
- const result = await response.json();
- return result;
- } catch (error) {
- echo.error("Failed to zone data");
- if (error instanceof Error) {
- console.log(error.message);
- } else {
- console.log("An unknown error occurred");
- }
- }
-};
diff --git a/app/src/store/builder/store.ts b/app/src/store/builder/store.ts
index 26bf8b8..1f237cb 100644
--- a/app/src/store/builder/store.ts
+++ b/app/src/store/builder/store.ts
@@ -523,6 +523,7 @@ export const useWidgetSubOption = create((set: any) => ({
widgetSubOption: "2D",
setWidgetSubOption: (x: any) => set({ widgetSubOption: x }),
}));
+
export const useLimitDistance = create((set: any) => ({
limitDistance: true,
setLimitDistance: (x: any) => set({ limitDistance: x }),
diff --git a/app/src/store/builder/useBuilderStore.ts b/app/src/store/builder/useBuilderStore.ts
index 7803df9..6147c0c 100644
--- a/app/src/store/builder/useBuilderStore.ts
+++ b/app/src/store/builder/useBuilderStore.ts
@@ -9,6 +9,13 @@ interface BuilderState {
snappedPosition: [number, number, number] | null;
hoveredLine: [Point, Point] | null;
+ // Wall Asset
+ selectedWallAsset: Object3D | null;
+ deletableWallAsset: Object3D | null;
+
+ // Floor Asset
+ selectedFloorAsset: Object3D | null;
+
// Wall Settings
selectedWall: Object3D | null;
wallThickness: number;
@@ -16,6 +23,19 @@ interface BuilderState {
outsideMaterial: string;
insideMaterial: string;
+ // Floor Settings
+ selectedFloor: Object3D | null;
+ floorDepth: number;
+ isBeveled: boolean;
+ bevelStrength: number;
+ sideMaterial: string;
+ topMaterial: string;
+
+ // Zone Settings
+ selectedZone: Object3D | null;
+ zoneHeight: number;
+ zoneColor: string;
+
// Decal Settings
selectedDecal: Object3D | null;
@@ -38,12 +58,31 @@ interface BuilderState {
setSnappedPosition: (position: [number, number, number] | null) => void;
setHoveredLine: (line: [Point, Point] | null) => void;
+ // Setters - Wall Asset
+ setSelectedWallAsset: (asset: Object3D | null) => void;
+ setDeletableWallAsset: (asset: Object3D | null) => void;
+
+ // Setters - Floor Asset
+ setSelectedFloorAsset: (asset: Object3D | null) => void;
+
// Setters - Wall
setSelectedWall: (wall: Object3D | null) => void;
setWallThickness: (thickness: number) => void;
setWallHeight: (height: number) => void;
setWallMaterial: (material: string, side: 'inside' | 'outside') => void;
+ // Setters - Floor
+ setSelectedFloor: (floor: Object3D | null) => void;
+ setFloorDepth: (depth: number) => void;
+ setIsBeveled: (isBeveled: boolean) => void;
+ setBevelStrength: (strength: number) => void;
+ setFloorMaterial: (material: string, side: 'side' | 'top') => void;
+
+ // Setters - Zone
+ setSelectedZone: (zone: Object3D | null) => void;
+ setZoneHeight: (height: number) => void;
+ setZoneColor: (color: string) => void;
+
// Setters - Decal
setSelectedDecal: (decal: Object3D | null) => void;
@@ -75,12 +114,28 @@ export const useBuilderStore = create()(
snappedPosition: null,
hoveredLine: null,
+ selectedWallAsset: null,
+ deletableWallAsset: null,
+
+ selectedFloorAsset: null,
+
selectedWall: null,
wallThickness: 0.5,
wallHeight: 7,
outsideMaterial: 'Default Material',
insideMaterial: 'Material 1',
+ selectedFloor: null,
+ floorDepth: 0.1,
+ isBeveled: false,
+ bevelStrength: 5,
+ sideMaterial: 'Material 1',
+ topMaterial: 'Default Material',
+
+ selectedZone: null,
+ zoneHeight: 7,
+ zoneColor: 'blue',
+
selectedDecal: null,
selectedAisle: null,
@@ -120,6 +175,28 @@ export const useBuilderStore = create()(
})
},
+ // === Setters: Wall Asset ===
+
+ setSelectedWallAsset(asset: Object3D | null) {
+ set((state) => {
+ state.selectedWallAsset = asset;
+ });
+ },
+
+ setDeletableWallAsset(asset: Object3D | null) {
+ set((state) => {
+ state.deletableWallAsset = asset;
+ });
+ },
+
+ // === Setters: Floor Asset ===
+
+ setSelectedFloorAsset(asset: Object3D | null) {
+ set((state) => {
+ state.selectedFloorAsset = asset;
+ });
+ },
+
// === Setters: Wall ===
setSelectedWall: (wall: Object3D | null) => {
@@ -147,6 +224,58 @@ export const useBuilderStore = create()(
});
},
+ // === Setters: Floor ===
+ setSelectedFloor: (floor: Object3D | null) => {
+ set((state) => {
+ state.selectedFloor = floor;
+ });
+ },
+
+ setFloorDepth: (depth: number) => {
+ set((state) => {
+ state.floorDepth = depth;
+ });
+ },
+
+ setIsBeveled: (isBeveled: boolean) => {
+ set((state) => {
+ state.isBeveled = isBeveled;
+ });
+ },
+
+ setBevelStrength: (strength: number) => {
+ set((state) => {
+ state.bevelStrength = strength;
+ });
+ },
+
+ setFloorMaterial: (material: string, side: 'side' | 'top') => {
+ set((state) => {
+ if (side === 'side') state.sideMaterial = material;
+ else state.topMaterial = material;
+ });
+ },
+
+ // === Setters: Zone ===
+
+ setSelectedZone: (zone: Object3D | null) => {
+ set((state) => {
+ state.selectedZone = zone;
+ });
+ },
+
+ setZoneHeight: (height: number) => {
+ set((state) => {
+ state.zoneHeight = height;
+ });
+ },
+
+ setZoneColor: (color: string) => {
+ set((state) => {
+ state.zoneColor = color;
+ });
+ },
+
// === Setters: Decal ===
setSelectedDecal: (decal: Object3D | null) => {
diff --git a/app/src/store/builder/useFloorStore.ts b/app/src/store/builder/useFloorStore.ts
index 4c89333..efb431b 100644
--- a/app/src/store/builder/useFloorStore.ts
+++ b/app/src/store/builder/useFloorStore.ts
@@ -5,16 +5,32 @@ 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;
+ setFloorName: (uuid: string, name: string) => void;
removeFloor: (uuid: string) => void;
- removePointFromFloors: (pointUuid: string) => void;
+ removePoint: (pointUuid: string) => { removedFloors: Floor[], updatedFloors: Floor[] };
+ removeFloorByPoints: (Points: [Point, Point]) => { removedFloors: Floor[], updatedFloors: Floor[] };
clearFloors: () => void;
+ setPosition: (
+ pointUuid: string,
+ position: [number, number, number]
+ ) => Floor[] | [];
setIsBeveled: (uuid: string, isBeveled: boolean) => void;
setBevelStrength: (uuid: string, strength: number) => void;
setDepth: (uuid: string, depth: number) => void;
setMaterial: (uuid: string, sideMaterial: string, topMaterial: string) => void;
+ addDecal: (floors: string, decal: Decal) => void;
+ updateDecal: (decalUuid: string, decal: Decal) => void;
+ removeDecal: (decalUuid: string) => void;
+ updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void;
+ updateDecalRotation: (decalUuid: string, rotation: number) => void;
+ updateDecalScale: (decalUuid: string, scale: number) => void;
getFloorById: (uuid: string) => Floor | undefined;
+ getFloorsByPointId: (uuid: string) => Floor[] | [];
+ getFloorByPoints: (points: Point[]) => Floor | undefined;
+ getFloorPointById: (uuid: string) => Point | undefined;
+ getConnectedPoints: (uuid: string) => Point[];
}
export const createFloorStore = () => {
@@ -30,10 +46,22 @@ export const createFloorStore = () => {
state.floors.push(floor);
}),
- updateFloor: (uuid, updated) => set(state => {
+ 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;
+ },
+
+ setFloorName: (uuid, name) => set(state => {
const floor = state.floors.find(f => f.floorUuid === uuid);
if (floor) {
- Object.assign(floor, updated);
+ floor.floorName = name;
}
}),
@@ -41,16 +69,97 @@ export const createFloorStore = () => {
state.floors = state.floors.filter(f => f.floorUuid !== uuid);
}),
- removePointFromFloors: (pointUuid) => set(state => {
- for (const floor of state.floors) {
- floor.points = floor.points.filter(p => p.pointUuid !== pointUuid);
- }
- }),
+ removePoint: (pointUuid) => {
+ const removedFloors: Floor[] = [];
+ const updatedFloors: Floor[] = [];
+
+ set(state => {
+ for (const floor of state.floors) {
+ const pointIndex = floor.points.findIndex(p => p.pointUuid === pointUuid);
+ if (pointIndex === -1) {
+ updatedFloors.push(JSON.parse(JSON.stringify(floor)));
+ continue;
+ }
+
+ const remainingPoints = floor.points.filter(p => p.pointUuid !== pointUuid);
+
+ if (remainingPoints.length <= 2) {
+ removedFloors.push(JSON.parse(JSON.stringify(floor)));
+ continue;
+ }
+ floor.points = remainingPoints;
+ updatedFloors.push(JSON.parse(JSON.stringify(floor)));
+ }
+
+ state.floors = updatedFloors;
+ });
+
+ return { removedFloors, updatedFloors };
+ },
+
+ removeFloorByPoints: ([pointA, pointB]) => {
+ const removedFloors: Floor[] = [];
+ const updatedFloors: Floor[] = [];
+
+ set(state => {
+
+ for (const floor of state.floors) {
+ const indices = floor.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
+
+ const idxA = indices.find(i => i.uuid === pointA.pointUuid)?.index ?? -1;
+ const idxB = indices.find(i => i.uuid === pointB.pointUuid)?.index ?? -1;
+
+ if (idxA === -1 || idxB === -1) {
+ updatedFloors.push(JSON.parse(JSON.stringify(floor)));
+ continue;
+ }
+
+ const areAdjacent =
+ Math.abs(idxA - idxB) === 1 ||
+ (idxA === 0 && idxB === floor.points.length - 1) ||
+ (idxB === 0 && idxA === floor.points.length - 1);
+
+ if (!areAdjacent) {
+ updatedFloors.push(JSON.parse(JSON.stringify(floor)));
+ continue;
+ }
+
+ const remainingPoints = floor.points.filter(
+ p => p.pointUuid !== pointA.pointUuid && p.pointUuid !== pointB.pointUuid
+ );
+
+ if (remainingPoints.length > 2) {
+ floor.points = remainingPoints;
+ updatedFloors.push(JSON.parse(JSON.stringify(floor)));
+ } else {
+ removedFloors.push(JSON.parse(JSON.stringify(floor)));
+ }
+ }
+
+ state.floors = updatedFloors;
+ });
+
+ return { removedFloors, updatedFloors };
+ },
clearFloors: () => set(state => {
state.floors = [];
}),
+ setPosition: (pointUuid, position) => {
+ let updatedFloor: Floor[] = [];
+ set((state) => {
+ for (const floor of state.floors) {
+ const point = floor.points.find((p) => p.pointUuid === pointUuid);
+ if (point) {
+ point.position = position;
+ updatedFloor.push(JSON.parse(JSON.stringify(floor)));
+ }
+ }
+ });
+ return updatedFloor;
+ },
+
setIsBeveled: (uuid, isBeveled) => set(state => {
const floor = state.floors.find(f => f.floorUuid === uuid);
if (floor) {
@@ -80,9 +189,96 @@ export const createFloorStore = () => {
}
}),
+ addDecal: (floorUuid, decal) => set(state => {
+ const floor = state.floors.find(f => f.floorUuid === floorUuid);
+ if (floor) {
+ floor.decals.push(decal);
+ }
+ }),
+
+ updateDecal: (decalUuid, updatedDecal) => set(state => {
+ for (const floor of state.floors) {
+ const index = floor.decals.findIndex(d => d.decalUuid === decalUuid);
+ if (index !== -1) {
+ floor.decals[index] = updatedDecal;
+ break;
+ }
+ }
+ }),
+
+ removeDecal: (decalUuid) => set(state => {
+ for (const floor of state.floors) {
+ floor.decals = floor.decals.filter(d => d.decalUuid !== decalUuid);
+ }
+ }),
+
+ updateDecalPosition: (decalUuid, position) => set(state => {
+ for (const floor of state.floors) {
+ const decal = floor.decals.find(d => d.decalUuid === decalUuid);
+ if (decal) {
+ decal.decalPosition = position;
+ break;
+ }
+ }
+ }),
+
+ updateDecalRotation: (decalUuid, rotation) => set(state => {
+ for (const floor of state.floors) {
+ const decal = floor.decals.find(d => d.decalUuid === decalUuid);
+ if (decal) {
+ decal.decalRotation = rotation;
+ break;
+ }
+ }
+ }),
+
+ updateDecalScale: (decalUuid, scale) => set(state => {
+ for (const floor of state.floors) {
+ const decal = floor.decals.find(d => d.decalUuid === decalUuid);
+ if (decal) {
+ decal.decalScale = scale;
+ break;
+ }
+ }
+ }),
+
+
getFloorById: (uuid) => {
return get().floors.find(f => f.floorUuid === uuid);
},
+
+ getFloorsByPointId: (pointUuid) => {
+ return get().floors.filter(floor => {
+ return floor.points.some(p => p.pointUuid === pointUuid);
+ });
+ },
+
+ getFloorByPoints: (points) => {
+ return get().floors.find(floor => {
+ const floorPointIds = new Set(floor.points.map(p => p.pointUuid));
+ const givenPointIds = new Set(points.map(p => p.pointUuid));
+ return floorPointIds.size === givenPointIds.size && [...floorPointIds].every(id => givenPointIds.has(id));
+ });
+ },
+
+ getFloorPointById: (pointUuid) => {
+ for (const floor of get().floors) {
+ const point = floor.points.find(p => p.pointUuid === pointUuid);
+ if (point) return point;
+ }
+ return undefined;
+ },
+
+ getConnectedPoints: (pointUuid) => {
+ const connected: Point[] = [];
+ for (const floor of get().floors) {
+ if (floor.points.some(p => p.pointUuid === pointUuid)) {
+ connected.push(...floor.points.filter(p => p.pointUuid !== pointUuid));
+ }
+ }
+ return connected;
+ }
+
}))
);
};
diff --git a/app/src/store/builder/useWallAssetStore.ts b/app/src/store/builder/useWallAssetStore.ts
index 408aade..3d4e89d 100644
--- a/app/src/store/builder/useWallAssetStore.ts
+++ b/app/src/store/builder/useWallAssetStore.ts
@@ -6,6 +6,7 @@ interface WallAssetStore {
setWallAssets: (assets: WallAsset[]) => void;
addWallAsset: (asset: WallAsset) => void;
updateWallAsset: (uuid: string, updated: Partial) => void;
+ setWallAssetPosition: (uuid: string, position: [number, number, number]) => void;
removeWallAsset: (uuid: string) => void;
clearWallAssets: () => void;
@@ -37,6 +38,13 @@ export const createWallAssetStore = () => {
}
}),
+ setWallAssetPosition: (uuid, position) => set(state => {
+ const asset = state.wallAssets.find(a => a.modelUuid === uuid);
+ if (asset) {
+ asset.position = position;
+ }
+ }),
+
removeWallAsset: (uuid) => set(state => {
state.wallAssets = state.wallAssets.filter(a => a.modelUuid !== uuid);
}),
diff --git a/app/src/store/builder/useWallStore.ts b/app/src/store/builder/useWallStore.ts
index 3547330..11f7130 100644
--- a/app/src/store/builder/useWallStore.ts
+++ b/app/src/store/builder/useWallStore.ts
@@ -5,7 +5,7 @@ interface WallStore {
walls: Wall[];
setWalls: (walls: Wall[]) => void;
addWall: (wall: Wall) => void;
- updateWall: (uuid: string, updated: Partial) => void;
+ updateWall: (uuid: string, updated: Partial) => Wall | undefined;
removeWall: (uuid: string) => void;
clearWalls: () => void;
removeWallByPoints: (Points: [Point, Point]) => Wall | undefined;
@@ -17,11 +17,11 @@ interface WallStore {
updateDecalScale: (decalUuid: string, scale: number) => void;
removePoint: (pointUuid: string) => Wall[];
- setPosition: (pointUuid: string, position: [number, number, number]) => void;
+ setPosition: (pointUuid: string, position: [number, number, number]) => Wall[] | [];
setLayer: (pointUuid: string, layer: number) => void;
getWallById: (uuid: string) => Wall | undefined;
- getWallByPointId: (uuid: string) => Wall | undefined;
+ getWallsByPointId: (uuid: string) => Wall[] | [];
getWallByPoints: (points: Point[]) => Wall | undefined;
getWallPointById: (uuid: string) => Point | undefined;
getConnectedPoints: (uuid: string) => Point[];
@@ -40,12 +40,17 @@ export const createWallStore = () => {
state.walls.push(wall);
}),
- updateWall: (uuid, updated) => set((state) => {
- const wall = state.walls.find(w => w.wallUuid === uuid);
- if (wall) {
- Object.assign(wall, updated);
- }
- }),
+ updateWall: (uuid, updated) => {
+ let updatedWall: Wall | undefined;
+ set((state) => {
+ const wall = state.walls.find(w => w.wallUuid === uuid);
+ if (wall) {
+ Object.assign(wall, updated);
+ updatedWall = JSON.parse(JSON.stringify(wall));
+ }
+ });
+ return updatedWall;
+ },
removeWall: (uuid) => set((state) => {
state.walls = state.walls.filter(w => w.wallUuid !== uuid);
@@ -144,14 +149,19 @@ export const createWallStore = () => {
return removedWalls;
},
- setPosition: (pointUuid, position) => set((state) => {
- for (const wall of state.walls) {
- const point = wall.points.find(p => p.pointUuid === pointUuid);
- if (point) {
- point.position = position;
+ setPosition: (pointUuid, position) => {
+ let updatedWalls: Wall[] = [];
+ set((state) => {
+ for (const wall of state.walls) {
+ const point = wall.points.find(p => p.pointUuid === pointUuid);
+ if (point) {
+ point.position = position;
+ updatedWalls.push(wall);
+ }
}
- }
- }),
+ });
+ return updatedWalls;
+ },
setLayer: (pointUuid, layer) => set((state) => {
for (const wall of state.walls) {
@@ -166,13 +176,10 @@ export const createWallStore = () => {
return get().walls.find(w => w.wallUuid === uuid);
},
- getWallByPointId: (uuid) => {
- for (const wall of get().walls) {
- if (wall.points.some(p => p.pointUuid === uuid)) {
- return wall;
- }
- }
- return undefined;
+ getWallsByPointId: (uuid) => {
+ return get().walls.filter((a) => {
+ return a.points.some((p) => p.pointUuid === uuid);
+ })
},
getWallByPoints: (point) => {
diff --git a/app/src/store/builder/useZoneStore.ts b/app/src/store/builder/useZoneStore.ts
index ee3c736..1a93e57 100644
--- a/app/src/store/builder/useZoneStore.ts
+++ b/app/src/store/builder/useZoneStore.ts
@@ -6,13 +6,24 @@ interface ZoneStore {
setZones: (zones: Zone[]) => void;
addZone: (zone: Zone) => void;
updateZone: (uuid: string, updated: Partial) => void;
+ setZoneName: (uuid: string, name: string) => void;
+ setZoneHeight: (uuid: string, height: number) => void;
+ setZoneColor: (uuid: string, color: string) => void;
removeZone: (uuid: string) => void;
- removePointFromZones: (pointUuid: string) => void;
+ removePoint: (pointUuid: string) => { removedZones: Zone[], updatedZones: Zone[] };
+ removeZoneByPoints: (points: Point[]) => { removedZones: Zone[], updatedZones: Zone[] };
clearZones: () => void;
+ setPosition: (
+ pointUuid: string,
+ position: [number, number, number]
+ ) => Zone[] | [];
setViewPort: (uuid: string, position: [number, number, number], target: [number, number, number]) => void;
- setColor: (uuid: string, color: string) => void;
getZoneById: (uuid: string) => Zone | undefined;
+ getZonesByPointId: (uuid: string) => Zone[] | [];
+ getZoneByPoints: (points: Point[]) => Zone | undefined;
+ getZonePointById: (uuid: string) => Point | undefined;
+ getConnectedPoints: (uuid: string) => Point[];
}
export const createZoneStore = () => {
@@ -35,20 +46,122 @@ export const createZoneStore = () => {
}
}),
+ setZoneName: (uuid, name) => set(state => {
+ const zone = state.zones.find(z => z.zoneUuid === uuid);
+ if (zone) {
+ zone.zoneName = name;
+ }
+ }),
+
+ setZoneHeight: (uuid, height) => set(state => {
+ const zone = state.zones.find(z => z.zoneUuid === uuid);
+ if (zone) {
+ zone.zoneHeight = height;
+ }
+ }),
+
+ setZoneColor: (uuid, color) => set(state => {
+ const zone = state.zones.find(z => z.zoneUuid === uuid);
+ if (zone) {
+ zone.zoneColor = color;
+ }
+ }),
+
removeZone: (uuid) => set(state => {
state.zones = state.zones.filter(z => z.zoneUuid !== uuid);
}),
- removePointFromZones: (pointUuid) => set(state => {
- for (const zone of state.zones) {
- zone.points = zone.points.filter(p => p.pointUuid !== pointUuid);
- }
- }),
+ removePoint: (pointUuid) => {
+ const removedZones: Zone[] = [];
+ const updatedZones: Zone[] = [];
+
+ set(state => {
+ for (const zone of state.zones) {
+ const pointIndex = zone.points.findIndex(p => p.pointUuid === pointUuid);
+ if (pointIndex === -1) {
+ updatedZones.push(JSON.parse(JSON.stringify(zone)));
+ continue;
+ }
+
+ const remainingPoints = zone.points.filter(p => p.pointUuid !== pointUuid);
+
+ if (remainingPoints.length <= 2) {
+ removedZones.push(JSON.parse(JSON.stringify(zone)));
+ continue;
+ }
+ zone.points = remainingPoints;
+ updatedZones.push(JSON.parse(JSON.stringify(zone)));
+ }
+
+ state.zones = updatedZones;
+ });
+
+ return { removedZones, updatedZones };
+ },
+
+ removeZoneByPoints: ([pointA, pointB]) => {
+ const removedZones: Zone[] = [];
+ const updatedZones: Zone[] = [];
+
+ set(state => {
+
+ for (const zone of state.zones) {
+ const indices = zone.points.map((p, i) => ({ uuid: p.pointUuid, index: i }));
+
+ const idxA = indices.find(i => i.uuid === pointA.pointUuid)?.index ?? -1;
+ const idxB = indices.find(i => i.uuid === pointB.pointUuid)?.index ?? -1;
+
+ if (idxA === -1 || idxB === -1) {
+ updatedZones.push(JSON.parse(JSON.stringify(zone)));
+ continue;
+ }
+
+ const areAdjacent =
+ Math.abs(idxA - idxB) === 1 ||
+ (idxA === 0 && idxB === zone.points.length - 1) ||
+ (idxB === 0 && idxA === zone.points.length - 1);
+
+ if (!areAdjacent) {
+ updatedZones.push(JSON.parse(JSON.stringify(zone)));
+ continue;
+ }
+
+ const remainingPoints = zone.points.filter(
+ p => p.pointUuid !== pointA.pointUuid && p.pointUuid !== pointB.pointUuid
+ );
+
+ if (remainingPoints.length > 2) {
+ zone.points = remainingPoints;
+ updatedZones.push(JSON.parse(JSON.stringify(zone)));
+ } else {
+ removedZones.push(JSON.parse(JSON.stringify(zone)));
+ }
+ }
+
+ state.zones = updatedZones;
+ });
+
+ return { removedZones, updatedZones };
+ },
clearZones: () => set(state => {
state.zones = [];
}),
+ setPosition: (pointUuid, position) => {
+ let updatedZone: Zone[] = [];
+ set((state) => {
+ for (const zone of state.zones) {
+ const point = zone.points.find((p) => p.pointUuid === pointUuid);
+ if (point) {
+ point.position = position;
+ updatedZone.push(JSON.parse(JSON.stringify(zone)));
+ }
+ }
+ });
+ return updatedZone;
+ },
+
setViewPort: (uuid, position, target) => set(state => {
const zone = state.zones.find(z => z.zoneUuid === uuid);
if (zone) {
@@ -57,16 +170,42 @@ export const createZoneStore = () => {
}
}),
- setColor: (uuid, color) => set(state => {
- const zone = state.zones.find(z => z.zoneUuid === uuid);
- if (zone) {
- zone.zoneColor = color;
- }
- }),
-
getZoneById: (uuid) => {
return get().zones.find(z => z.zoneUuid === uuid);
},
+
+ getZonesByPointId: (pointUuid) => {
+ return get().zones.filter(zone => {
+ return zone.points.some(p => p.pointUuid === pointUuid);
+ });
+ },
+
+ getZoneByPoints: (points) => {
+ return get().zones.find(zone => {
+ const zonePointIds = new Set(zone.points.map(p => p.pointUuid));
+ const givenPointIds = new Set(points.map(p => p.pointUuid));
+ return zonePointIds.size === givenPointIds.size && [...zonePointIds].every(id => givenPointIds.has(id));
+ });
+ },
+
+ getZonePointById: (pointUuid) => {
+ for (const zone of get().zones) {
+ const point = zone.points.find(p => p.pointUuid === pointUuid);
+ if (point) return point;
+ }
+ return undefined;
+ },
+
+ getConnectedPoints: (pointUuid) => {
+ const connected: Point[] = [];
+ for (const zone of get().zones) {
+ if (zone.points.some(p => p.pointUuid === pointUuid)) {
+ connected.push(...zone.points.filter(p => p.pointUuid !== pointUuid));
+ }
+ }
+ return connected;
+ }
+
}))
);
};
diff --git a/app/src/types/builderTypes.d.ts b/app/src/types/builderTypes.d.ts
index bbc9b7b..de7586a 100644
--- a/app/src/types/builderTypes.d.ts
+++ b/app/src/types/builderTypes.d.ts
@@ -51,9 +51,11 @@ type Assets = Asset[];
interface WallAsset {
modelUuid: string;
modelName: string;
+ wallAssetType: string;
assetId: string;
wallUuid: string;
position: [number, number, number];
+ rotation: [number, number, number];
isLocked: boolean;
isVisible: boolean;
opacity: number;
@@ -113,6 +115,7 @@ type Walls = Wall[];
interface Floor {
floorUuid: string;
+ floorName: string;
points: Point[];
sideMaterial: string;
topMaterial: string;
@@ -130,6 +133,7 @@ type Floors = Floor[];
interface Zone {
zoneUuid: string;
zoneName: string;
+ zoneHeight: number;
zoneColor: string;
points: Point[];
viewPortTarget: [number, number, number];