diff --git a/app/src/assets/textures/floor/black.png b/app/src/assets/textures/floor/black.png
new file mode 100644
index 0000000..5562e8a
Binary files /dev/null and b/app/src/assets/textures/floor/black.png differ
diff --git a/app/src/assets/textures/floor/factory wall texture.jpg b/app/src/assets/textures/floor/factory wall texture.jpg
new file mode 100644
index 0000000..65e39c3
Binary files /dev/null and b/app/src/assets/textures/floor/factory wall texture.jpg differ
diff --git a/app/src/assets/textures/floor/wall-tex.png b/app/src/assets/textures/floor/wall-tex.png
new file mode 100644
index 0000000..d1a09a8
Binary files /dev/null and b/app/src/assets/textures/floor/wall-tex.png differ
diff --git a/app/src/assets/textures/floor/white.png b/app/src/assets/textures/floor/white.png
new file mode 100644
index 0000000..efc1ea4
Binary files /dev/null and b/app/src/assets/textures/floor/white.png differ
diff --git a/app/src/components/layout/sidebarLeft/Assets.tsx b/app/src/components/layout/sidebarLeft/Assets.tsx
index b863500..dd2c2a2 100644
--- a/app/src/components/layout/sidebarLeft/Assets.tsx
+++ b/app/src/components/layout/sidebarLeft/Assets.tsx
@@ -1,9 +1,6 @@
import React, { useEffect, useState } from "react";
import Search from "../../ui/inputs/Search";
import { getCategoryAsset } from "../../../services/factoryBuilder/assest/assets/getCategoryAsset";
-import arch from "../../../assets/gltf-glb/arch.glb";
-import door from "../../../assets/gltf-glb/door.glb";
-import window from "../../../assets/gltf-glb/window.glb";
import { fetchAssets } from "../../../services/marketplace/fetchAssets";
import { useSelectedItem } from "../../../store/store";
@@ -16,8 +13,6 @@ import storage from "../../../assets/image/categories/storage.png";
import office from "../../../assets/image/categories/office.png";
import safety from "../../../assets/image/categories/safety.png";
import feneration from "../../../assets/image/categories/feneration.png";
-import archThumbnail from "../../../assets/image/localAssets/arch.png";
-import windowThumbnail from "../../../assets/image/localAssets/window.png";
import SkeletonUI from "../../templates/SkeletonUI";
// -------------------------------------
@@ -90,24 +85,7 @@ const Assets: React.FC = () => {
useEffect(() => {
setCategoryList([
- {
- assetName: "Doors",
- assetImage: "",
- category: "Feneration",
- categoryImage: feneration,
- },
- {
- assetName: "Windows",
- assetImage: "",
- category: "Feneration",
- categoryImage: feneration,
- },
- {
- assetName: "Pillars",
- assetImage: "",
- category: "Feneration",
- categoryImage: feneration,
- },
+ { category: "Fenestration", categoryImage: feneration },
{ category: "Vehicles", categoryImage: vehicle },
{ category: "Workstation", categoryImage: workStation },
{ category: "Machines", categoryImage: machines },
@@ -121,44 +99,15 @@ const Assets: React.FC = () => {
const fetchCategoryAssets = async (asset: any) => {
setisLoading(true);
setSelectedCategory(asset);
- if (asset === "Feneration") {
- const localAssets: AssetProp[] = [
- {
- filename: "arch",
- category: "Feneration",
- url: arch,
- thumbnail: archThumbnail,
- tags: "arch",
- },
- {
- filename: "door",
- category: "Feneration",
- url: door,
- thumbnail: feneration,
- tags: "door",
- },
- {
- filename: "window",
- category: "Feneration",
- url: window,
- thumbnail: windowThumbnail,
- tags: "window",
- },
- ];
- setCategoryAssets(localAssets);
- setFiltereredAssets(localAssets);
+ try {
+ const res = await getCategoryAsset(asset);
+ setCategoryAssets(res);
+ setFiltereredAssets(res);
+ setisLoading(false); // End loading
+ // eslint-disable-next-line
+ } catch (error) {
+ echo.error("failed to fetch assets");
setisLoading(false);
- } else {
- try {
- const res = await getCategoryAsset(asset);
- setCategoryAssets(res);
- setFiltereredAssets(res);
- setisLoading(false); // End loading
- // eslint-disable-next-line
- } catch (error) {
- echo.error("failed to fetch assets");
- setisLoading(false);
- }
}
};
@@ -167,64 +116,21 @@ const Assets: React.FC = () => {
- {isLoading ? (
- // Show skeleton when loading
- ) : searchValue ? (
-
-
-
-
Results for {searchValue}
-
-
- {categoryAssets?.map((asset: any, index: number) => (
-
-
-
-
- {asset.filename
- .split("_")
- .map(
- (word: any) =>
- word.charAt(0).toUpperCase() + word.slice(1)
- )
- .join(" ")}
-
+ {(() => {
+ if (isLoading) {
+ return
; // Show skeleton when loading
+ }
+ if (searchValue) {
+ return (
+
+
+
+
Results for {searchValue}
- ))}
-
-
-
- ) : (
- <>
- {selectedCategory ? (
-
-
- {selectedCategory}{" "}
- {
- setSelectedCategory(null);
- setCategoryAssets([]);
- }}
- >
- ← Back
-
-
-
- {categoryAssets &&
- categoryAssets?.map((asset: any, index: number) => (
+
+ {categoryAssets?.map((asset: any, index: number) => (
{
alt={asset.filename}
className="asset-image"
onPointerDown={() => {
- setSelectedItem({
- name: asset.filename,
- id: asset.AssetID,
- type:
- asset.type === "undefined"
- ? undefined
- : asset.type,
- });
+ if (asset.category !== 'Feneration') {
+ setSelectedItem({
+ name: asset.filename,
+ id: asset.AssetID,
+ type:
+ asset.type === "undefined"
+ ? undefined
+ : asset.type,
+ });
+ }
}}
/>
+
{asset.filename
.split("_")
@@ -255,40 +164,104 @@ const Assets: React.FC = () => {
))}
+
- ) : (
+ );
+ }
+
+ if (selectedCategory) {
+ return (
-
Categories
-
- {Array.from(
- new Set(categoryList.map((asset) => asset.category))
- ).map((category, index) => {
- const categoryInfo = categoryList.find(
- (asset) => asset.category === category
- );
- return (
-
fetchCategoryAssets(category)}
- >
-
-
{category}
+
+ {selectedCategory}
+ {
+ setSelectedCategory(null);
+ setCategoryAssets([]);
+ }}
+ >
+ ← Back
+
+
+
+ {categoryAssets?.map((asset: any, index: number) => (
+
+
{
+ setSelectedItem({
+ name: asset.filename,
+ id: asset.AssetID,
+ type:
+ asset.type === "undefined"
+ ? undefined
+ : asset.type,
+ });
+ }}
+ />
+
+ {asset.filename
+ .split("_")
+ .map(
+ (word: any) =>
+ word.charAt(0).toUpperCase() + word.slice(1)
+ )
+ .join(" ")}
- );
- })}
+
+ ))}
+ {categoryAssets.length === 0 && (
+
+ 🚧 The asset shelf is empty. We're working on filling it
+ up!
+
+ )}
- )}
- >
- )}
+ );
+ }
+
+ return (
+
+
Categories
+
+ {Array.from(
+ new Set(categoryList.map((asset) => asset.category))
+ ).map((category, index) => {
+ const categoryInfo = categoryList.find(
+ (asset) => asset.category === category
+ );
+ return (
+
fetchCategoryAssets(category)}
+ >
+
+ {category}
+
+ );
+ })}
+
+
+ );
+ })()}
diff --git a/app/src/components/layout/sidebarLeft/Header.tsx b/app/src/components/layout/sidebarLeft/Header.tsx
index 70668af..f26f4fa 100644
--- a/app/src/components/layout/sidebarLeft/Header.tsx
+++ b/app/src/components/layout/sidebarLeft/Header.tsx
@@ -6,7 +6,7 @@ import useToggleStore from "../../../store/useUIToggleStore";
import useModuleStore from "../../../store/useModuleStore";
const Header: React.FC = () => {
- const { toggleUI, setToggleUI } = useToggleStore();
+ const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore();
const { activeModule } = useModuleStore();
return (
@@ -20,15 +20,17 @@ const Header: React.FC = () => {
{
if (activeModule !== "market") {
- setToggleUI(!toggleUI);
- localStorage.setItem("navBarUi", JSON.stringify(!toggleUI));
+ setToggleUI(!toggleUILeft, toggleUIRight);
+ localStorage.setItem("navBarUiLeft", JSON.stringify(!toggleUILeft));
}
}}
>
- {toggleUI ? "Hide" : "Show"} sidebar (ctrl + \)
+
+ {toggleUILeft ? "Hide" : "Show"} sidebar (ctrl + [)
+
diff --git a/app/src/components/layout/sidebarLeft/SideBarLeft.tsx b/app/src/components/layout/sidebarLeft/SideBarLeft.tsx
index 0765b95..eb618ec 100644
--- a/app/src/components/layout/sidebarLeft/SideBarLeft.tsx
+++ b/app/src/components/layout/sidebarLeft/SideBarLeft.tsx
@@ -12,7 +12,7 @@ import Search from "../../ui/inputs/Search";
const SideBarLeft: React.FC = () => {
const [activeOption, setActiveOption] = useState("Widgets");
- const { toggleUI } = useToggleStore();
+ const { toggleUILeft } = useToggleStore();
const { activeModule } = useModuleStore();
// Reset activeOption whenever activeModule changes
@@ -31,47 +31,55 @@ const SideBarLeft: React.FC = () => {
};
return (
-
+
- {toggleUI && (
+ {toggleUILeft && (
- {activeModule === "visualization" ? (
- <>
-
-
-
- {activeOption === "Widgets" ? : }
-
- >
- ) : activeModule === "market" ? (
- <>>
- ) : activeModule === "builder" ? (
- <>
-
-
- {activeOption === "Outline" ?
:
}
-
- >
- ) : (
- <>
-
-
- {activeOption === "Outline" ?
:
}
-
- >
- )}
+ {(() => {
+ if (activeModule === "visualization") {
+ return (
+ <>
+
+
+
+ {activeOption === "Widgets" ? : }
+
+ >
+ );
+ } else if (activeModule === "market") {
+ return <>>;
+ } else if (activeModule === "builder") {
+ return (
+ <>
+
+
+ {activeOption === "Outline" ?
:
}
+
+ >
+ );
+ } else {
+ return (
+ <>
+
+
+ {activeOption === "Outline" ?
:
}
+
+ >
+ );
+ }
+ })()}
)}
diff --git a/app/src/components/layout/sidebarRight/Header.tsx b/app/src/components/layout/sidebarRight/Header.tsx
index 3684157..c7c3070 100644
--- a/app/src/components/layout/sidebarRight/Header.tsx
+++ b/app/src/components/layout/sidebarRight/Header.tsx
@@ -5,10 +5,15 @@ import { ActiveUser } from "../../../types/users";
import CollaborationPopup from "../../templates/CollaborationPopup";
import { getAvatarColor } from "../../../modules/collaboration/functions/getAvatarColor";
import { useSelectedUserStore } from "../../../store/useCollabStore";
+import useToggleStore from "../../../store/useUIToggleStore";
+import { ToggleSidebarIcon } from "../../icons/HeaderIcons";
+import useModuleStore from "../../../store/useModuleStore";
const Header: React.FC = () => {
const { activeUsers } = useActiveUsers();
const userName = localStorage.getItem("userName") ?? "Anonymous";
+ const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore();
+ const { activeModule } = useModuleStore();
const guestUsers: ActiveUser[] = activeUsers.filter(
(user: ActiveUser) => user.userName !== userName
@@ -55,6 +60,25 @@ const Header: React.FC = () => {
)}
+
{
+ if (activeModule !== "market") {
+ setToggleUI(toggleUILeft, !toggleUIRight);
+ localStorage.setItem(
+ "navBarUiRight",
+ JSON.stringify(!toggleUIRight)
+ );
+ }
+ }}
+ >
+
+ {toggleUIRight ? "Hide" : "Show"} sidebar (ctrl + ])
+
+
+
{
diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx
index 0cff6eb..d643d69 100644
--- a/app/src/components/layout/sidebarRight/SideBarRight.tsx
+++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx
@@ -25,7 +25,7 @@ import EventProperties from "./properties/eventProperties/EventProperties";
const SideBarRight: React.FC = () => {
const { activeModule } = useModuleStore();
- const { toggleUI } = useToggleStore();
+ const { toggleUIRight } = useToggleStore();
const { subModule, setSubModule } = useSubModuleStore();
const { selectedFloorItem } = useSelectedFloorItem();
const { selectedEventData } = useSelectedEventData();
@@ -55,9 +55,9 @@ const SideBarRight: React.FC = () => {
}, [activeModule, selectedEventData, selectedEventSphere, setSubModule]);
return (
-
+
- {toggleUI && (
+ {toggleUIRight && (
{activeModule !== "simulation" && (
{
)}
{/* process builder */}
- {toggleUI &&
+ {toggleUIRight &&
subModule === "properties" &&
activeModule !== "visualization" &&
!selectedFloorItem && (
@@ -114,7 +114,7 @@ const SideBarRight: React.FC = () => {
)}
- {toggleUI &&
+ {toggleUIRight &&
subModule === "properties" &&
activeModule !== "visualization" &&
selectedFloorItem && (
@@ -124,7 +124,7 @@ const SideBarRight: React.FC = () => {
)}
- {toggleUI &&
+ {toggleUIRight &&
subModule === "zoneProperties" &&
(activeModule === "builder" || activeModule === "simulation") && (
@@ -134,7 +134,7 @@ const SideBarRight: React.FC = () => {
)}
{/* simulation */}
- {toggleUI && activeModule === "simulation" && (
+ {toggleUIRight && activeModule === "simulation" && (
<>
{subModule === "simulations" && (
@@ -160,7 +160,7 @@ const SideBarRight: React.FC = () => {
>
)}
{/* realtime visualization */}
- {toggleUI && activeModule === "visualization" && }
+ {toggleUIRight && activeModule === "visualization" && }
);
};
diff --git a/app/src/components/templates/SkeletonUI.tsx b/app/src/components/templates/SkeletonUI.tsx
index 76c3fbd..2928916 100644
--- a/app/src/components/templates/SkeletonUI.tsx
+++ b/app/src/components/templates/SkeletonUI.tsx
@@ -7,7 +7,6 @@ interface SkeletonUIProps {
// Define the SkeletonUI component
const SkeletonUI: React.FC
= ({ type }) => {
-
// Function to render skeleton content based on 'type'
const renderSkeleton = () => {
switch (type) {
@@ -38,17 +37,28 @@ const SkeletonUI: React.FC = ({ type }) => {
case "asset":
return (
<>
-
-
-
-
+
+
>
);
-
+
default:
return (
diff --git a/app/src/components/ui/FileMenu.tsx b/app/src/components/ui/FileMenu.tsx
index 9997ee4..4ad40c5 100644
--- a/app/src/components/ui/FileMenu.tsx
+++ b/app/src/components/ui/FileMenu.tsx
@@ -32,7 +32,7 @@ const FileMenu: React.FC = () => {
}, []);
// project
- const [projectName, setProjectName] = useState("project 1");
+ const [projectName, setProjectName] = useState("Demo Project");
// Load project name from localStorage on mount
useEffect(() => {
diff --git a/app/src/components/ui/ModuleToggle.tsx b/app/src/components/ui/ModuleToggle.tsx
index a1583e1..4a1532f 100644
--- a/app/src/components/ui/ModuleToggle.tsx
+++ b/app/src/components/ui/ModuleToggle.tsx
@@ -19,8 +19,11 @@ const ModuleToggle: React.FC = () => {
onClick={() => {
setActiveModule("builder");
setToggleUI(
- localStorage.getItem("navBarUi")
- ? localStorage.getItem("navBarUi") === "true"
+ localStorage.getItem("navBarUiLeft")
+ ? localStorage.getItem("navBarUiLeft") === "true"
+ : true,
+ localStorage.getItem("navBarUiRight")
+ ? localStorage.getItem("navBarUiRight") === "true"
: true
);
}}
@@ -37,8 +40,11 @@ const ModuleToggle: React.FC = () => {
onClick={() => {
setActiveModule("simulation");
setToggleUI(
- localStorage.getItem("navBarUi")
- ? localStorage.getItem("navBarUi") === "true"
+ localStorage.getItem("navBarUiLeft")
+ ? localStorage.getItem("navBarUiLeft") === "true"
+ : true,
+ localStorage.getItem("navBarUiRight")
+ ? localStorage.getItem("navBarUiRight") === "true"
: true
);
}}
@@ -55,8 +61,11 @@ const ModuleToggle: React.FC = () => {
onClick={() => {
setActiveModule("visualization");
setToggleUI(
- localStorage.getItem("navBarUi")
- ? localStorage.getItem("navBarUi") === "true"
+ localStorage.getItem("navBarUiLeft")
+ ? localStorage.getItem("navBarUiLeft") === "true"
+ : true,
+ localStorage.getItem("navBarUiRight")
+ ? localStorage.getItem("navBarUiRight") === "true"
: true
);
}}
@@ -70,7 +79,7 @@ const ModuleToggle: React.FC = () => {
className={`module-list ${activeModule === "market" ? "active" : ""}`}
onClick={() => {
setActiveModule("market");
- setToggleUI(false);
+ setToggleUI(false, false);
}}
>
diff --git a/app/src/components/ui/Tools.tsx b/app/src/components/ui/Tools.tsx
index 2187fdc..cf77f9e 100644
--- a/app/src/components/ui/Tools.tsx
+++ b/app/src/components/ui/Tools.tsx
@@ -29,7 +29,6 @@ import {
useSocketStore,
useToggleView,
useToolMode,
- useTransformMode,
useActiveSubTool,
} from "../../store/store";
import useToggleStore from "../../store/useUIToggleStore";
@@ -61,7 +60,6 @@ const Tools: React.FC = () => {
const { setAddAction } = useAddAction();
const { setSelectedWallItem } = useSelectedWallItem();
- const { setTransformMode } = useTransformMode();
const { setDeletePointOrLine } = useDeletePointOrLine();
const { setToolMode } = useToolMode();
const { activeTool, setActiveTool } = useActiveTool();
@@ -70,8 +68,11 @@ const Tools: React.FC = () => {
// Reset activeTool whenever activeModule changes
useEffect(() => {
setToggleUI(
- localStorage.getItem("navBarUi")
- ? localStorage.getItem("navBarUi") === "true"
+ localStorage.getItem("navBarUiLeft")
+ ? localStorage.getItem("navBarUiLeft") === "true"
+ : true,
+ localStorage.getItem("navBarUiRight")
+ ? localStorage.getItem("navBarUiRight") === "true"
: true
);
}, []);
@@ -92,8 +93,11 @@ const Tools: React.FC = () => {
setToggleView(false);
}
setToggleUI(
- localStorage.getItem("navBarUi")
- ? localStorage.getItem("navBarUi") === "true"
+ localStorage.getItem("navBarUiLeft")
+ ? localStorage.getItem("navBarUiLeft") === "true"
+ : true,
+ localStorage.getItem("navBarUiRight")
+ ? localStorage.getItem("navBarUiRight") === "true"
: true
);
setToggleThreeD(!toggleThreeD);
@@ -118,7 +122,7 @@ const Tools: React.FC = () => {
}, []);
useEffect(() => {
if (!toggleThreeD) {
- setToggleUI(false);
+ setToggleUI(false, false);
}
}, [toggleThreeD]);
@@ -126,7 +130,6 @@ const Tools: React.FC = () => {
setToolMode(null);
setDeleteTool(false);
setAddAction(null);
- setTransformMode(null);
setDeletePointOrLine(false);
setRefTextUpdate((prevUpdate) => prevUpdate - 1);
@@ -134,20 +137,6 @@ const Tools: React.FC = () => {
case "cursor":
if (toggleView) {
setToolMode('move');
- } else {
- setTransformMode("translate");
- }
- break;
-
- case "Rotate":
- if (!toggleView) {
- setTransformMode("rotate");
- }
- break;
-
- case "Scale":
- if (!toggleView) {
- setTransformMode("scale");
}
break;
@@ -208,8 +197,9 @@ const Tools: React.FC = () => {
{activeSubTool == "cursor" && (
{
setActiveTool("cursor");
}}
@@ -220,8 +210,9 @@ const Tools: React.FC = () => {
)}
{activeSubTool == "free-hand" && (
{
setActiveTool("free-hand");
}}
@@ -232,8 +223,9 @@ const Tools: React.FC = () => {
)}
{activeSubTool == "delete" && (
{
setActiveTool("delete");
}}
@@ -306,8 +298,9 @@ const Tools: React.FC = () => {
{
setActiveTool("draw-wall");
}}
@@ -316,8 +309,9 @@ const Tools: React.FC = () => {
{
setActiveTool("draw-zone");
}}
@@ -326,8 +320,9 @@ const Tools: React.FC = () => {
{
setActiveTool("draw-aisle");
}}
@@ -336,8 +331,9 @@ const Tools: React.FC = () => {
{
setActiveTool("draw-floor");
}}
@@ -353,8 +349,9 @@ const Tools: React.FC = () => {
{
setActiveTool("measure");
}}
@@ -370,8 +367,9 @@ const Tools: React.FC = () => {
{
setActiveTool("pen");
}}
@@ -408,8 +406,9 @@ const Tools: React.FC = () => {
{
setActiveTool("comment");
}}
@@ -419,8 +418,9 @@ const Tools: React.FC = () => {
{toggleThreeD && (
{
setIsPlaying(!isPlaying);
}}
@@ -434,8 +434,9 @@ const Tools: React.FC = () => {
<>
toggle view (tab)
diff --git a/app/src/components/ui/analysis/ROISummary.tsx b/app/src/components/ui/analysis/ROISummary.tsx
index 0c4d80e..e0edb74 100644
--- a/app/src/components/ui/analysis/ROISummary.tsx
+++ b/app/src/components/ui/analysis/ROISummary.tsx
@@ -205,7 +205,7 @@ const ROISummary = ({
-
+ {/*
@@ -224,7 +224,7 @@ const ROISummary = ({
Get ROI Boost Tips
-
+
*/}
>
) : (
diff --git a/app/src/components/ui/analysis/ThroughputSummary.tsx b/app/src/components/ui/analysis/ThroughputSummary.tsx
index 82116cf..8abdf22 100644
--- a/app/src/components/ui/analysis/ThroughputSummary.tsx
+++ b/app/src/components/ui/analysis/ThroughputSummary.tsx
@@ -5,7 +5,7 @@ import SkeletonUI from "../../templates/SkeletonUI";
const ProductionCapacity = ({
progressPercent = 50,
- avgProcessTime = "28.4 Secs/unit",
+ avgProcessTime = "28.4",
machineUtilization = "78%",
throughputValue = 128,
timeRange = { startTime: "08:00 AM", endTime: "09:00 AM" },
@@ -34,7 +34,7 @@ const ProductionCapacity = ({
<>
- {throughputValue} Units/hour
+ {avgProcessTime} secs/unit
{/* Dynamic Progress Bar */}
@@ -56,8 +56,8 @@ const ProductionCapacity = ({
- Avg. Process Time
- {avgProcessTime}
+ Units/hour
+ {throughputValue} avg.
Machine Utilization
diff --git a/app/src/components/ui/menu/menu.tsx b/app/src/components/ui/menu/menu.tsx
index 39508b6..e784808 100644
--- a/app/src/components/ui/menu/menu.tsx
+++ b/app/src/components/ui/menu/menu.tsx
@@ -1,12 +1,14 @@
import React, { useState } from "react";
import { ArrowIcon } from "../../icons/ExportCommonIcons";
import { toggleTheme } from "../../../utils/theme";
+import { useNavigate } from "react-router-dom";
interface MenuBarProps {
setOpenMenu: (isOpen: boolean) => void; // Function to update menu state
}
const MenuBar: React.FC
= ({ setOpenMenu }) => {
+ const navigate = useNavigate();
const [activeMenu, setActiveMenu] = useState(null);
const [activeSubMenu, setActiveSubMenu] = useState(null);
@@ -23,13 +25,19 @@ const MenuBar: React.FC = ({ setOpenMenu }) => {
}));
};
- function handleThemeChange(){
+ function handleThemeChange() {
toggleTheme();
window.location.reload();
}
const savedTheme: string | null = localStorage.getItem("theme") ?? "light";
+
+ const handleLogout = () => {
+ localStorage.clear(); // 1. Clear all localStorage
+ navigate('/'); // 2. Redirect to homepage
+ };
+
return (
= ({ setOpenMenu }) => {
)}
+
);
diff --git a/app/src/modules/builder/builder.tsx b/app/src/modules/builder/builder.tsx
index dfae129..f43cf3d 100644
--- a/app/src/modules/builder/builder.tsx
+++ b/app/src/modules/builder/builder.tsx
@@ -54,57 +54,57 @@ import NavMesh from "../simulation/vehicle/navMesh/navMesh";
import CalculateAreaGroup from "./groups/calculateAreaGroup";
export default function Builder() {
- const state = useThree
(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
- const csg = useRef(); // Reference for CSG object, used for 3D modeling.
- const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects.
- const scene = useRef() as Types.RefScene; // Reference to the scene.
- const camera = useRef() as Types.RefCamera; // Reference to the camera object.
- const controls = useRef(); // Reference to the controls object.
- const raycaster = useRef() as Types.RefRaycaster; // Reference for raycaster used for detecting objects being pointed at in the scene.
- const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control.
+ const state = useThree(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements.
+ const csg = useRef(); // Reference for CSG object, used for 3D modeling.
+ const CSGGroup = useRef() as Types.RefMesh; // Reference to a group of CSG objects.
+ const scene = useRef() as Types.RefScene; // Reference to the scene.
+ const camera = useRef() as Types.RefCamera; // Reference to the camera object.
+ const controls = useRef(); // Reference to the controls object.
+ const raycaster = useRef() as Types.RefRaycaster; // Reference for raycaster used for detecting objects being pointed at in the scene.
+ const dragPointControls = useRef() as Types.RefDragControl; // Reference for drag point controls, an array for drag control.
- // Assigning the scene and camera from the Three.js state to the references.
+ // Assigning the scene and camera from the Three.js state to the references.
- scene.current = state.scene;
- camera.current = state.camera;
- controls.current = state.controls;
- raycaster.current = state.raycaster;
+ scene.current = state.scene;
+ camera.current = state.camera;
+ controls.current = state.controls;
+ raycaster.current = state.raycaster;
- const plane = useRef(null); // Reference for a plane object for raycaster reference.
- const grid = useRef() as any; // Reference for a grid object for raycaster reference.
- const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line.
- const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end).
- const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc...
- const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active.
- const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point.
- const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start).
- const tempLoader = useRef() as Types.RefMesh; // Reference for a temporary loader for the floor items.
- const isTempLoader = useRef() as Types.RefBoolean; // Reference to check if a temporary loader is active.
- const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation.
- const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn.
- const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn.
- const onlyFloorline = useRef([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn.
- const onlyFloorlines = useRef([]); // Reference for all the floor lines that are ever drawn.
- const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw.
- const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not.
- const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed.
- const itemsGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the floor items (Gltf).
- const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors.
- const AttachedObject = useRef() as Types.RefMesh; // Reference for an object that is attached using dbl click for transform controls rotation.
- const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group.
- const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn.
- const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created.
- const floorGroupAisle = useRef() as Types.RefGroup;
- const zoneGroup = useRef() as Types.RefGroup;
- const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls.
- const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted.
- const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted.
- const hoveredDeletableFloorItem = useRef() as Types.RefMesh; // Reference for the currently hovered floor item that can be deleted.
- const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted.
- const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted.
- const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc...
+ const plane = useRef(null); // Reference for a plane object for raycaster reference.
+ const grid = useRef() as any; // Reference for a grid object for raycaster reference.
+ const snappedPoint = useRef() as Types.RefVector3; // Reference for storing a snapped point at the (end = isSnapped) and (start = ispreSnapped) of the line.
+ const isSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (end).
+ const anglesnappedPoint = useRef() as Types.RefVector3; // Reference for storing an angle-snapped point when the line is in 90 degree etc...
+ const isAngleSnapped = useRef(false) as Types.RefBoolean; // Boolean to indicate if angle snapping is active.
+ const isSnappedUUID = useRef() as Types.RefString; // UUID reference to identify the snapped point.
+ const ispreSnapped = useRef(false) as Types.RefBoolean; // Boolean reference to indicate if an object is snapped at the (start).
+ const tempLoader = useRef() as Types.RefMesh; // Reference for a temporary loader for the floor items.
+ const isTempLoader = useRef() as Types.RefBoolean; // Reference to check if a temporary loader is active.
+ const Tube = useRef() as Types.RefTubeGeometry; // Reference for tubes used for reference line creation and updation.
+ const line = useRef([]) as Types.RefLine; // Reference for line which stores the current line that is being drawn.
+ const lines = useRef([]) as Types.RefLines; // Reference for lines which stores all the lines that are ever drawn.
+ const onlyFloorline = useRef([]); // Reference for floor lines which does not have walls or roof and have only floor used to store the current line that is being drawn.
+ const onlyFloorlines = useRef([]); // Reference for all the floor lines that are ever drawn.
+ const ReferenceLineMesh = useRef() as Types.RefMesh; // Reference for storing the mesh of the reference line for moving it during draw.
+ const LineCreated = useRef(false) as Types.RefBoolean; // Boolean to track whether the reference line is created or not.
+ const referencePole = useRef() as Types.RefMesh; // Reference for a pole that is used as the reference for the user to show where it is placed.
+ const itemsGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the floor items (Gltf).
+ const floorGroup = useRef() as Types.RefGroup; // Reference to the THREE.Group that has the roofs and the floors.
+ const AttachedObject = useRef() as Types.RefMesh; // Reference for an object that is attached using dbl click for transform controls rotation.
+ const floorPlanGroup = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines group and the points group.
+ const floorPlanGroupLine = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the lines that are drawn.
+ const floorPlanGroupPoint = useRef() as Types.RefGroup; // Reference for a THREE.Group that has the points that are created.
+ const floorGroupAisle = useRef() as Types.RefGroup;
+ const zoneGroup = useRef() as Types.RefGroup;
+ const currentLayerPoint = useRef([]) as Types.RefMeshArray; // Reference for points that re in the current layer used to update the points in drag controls.
+ const hoveredDeletablePoint = useRef() as Types.RefMesh; // Reference for the currently hovered point that can be deleted.
+ const hoveredDeletableLine = useRef() as Types.RefMesh; // Reference for the currently hovered line that can be deleted.
+ const hoveredDeletableFloorItem = useRef() as Types.RefMesh; // Reference for the currently hovered floor item that can be deleted.
+ const hoveredDeletableWallItem = useRef() as Types.RefMesh; // Reference for the currently hovered wall item that can be deleted.
+ const hoveredDeletablePillar = useRef() as Types.RefMesh; // Reference for the currently hovered pillar that can be deleted.
+ const currentWallItem = useRef() as Types.RefMesh; // Reference for the currently selected wall item that can be scaled, dragged etc...
- const cursorPosition = new THREE.Vector3(); // 3D vector for storing the cursor position.
+ const 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.
@@ -120,42 +120,39 @@ export default function Builder() {
const { setWalls } = useWalls();
const { refTextupdate, setRefTextUpdate } = useRefTextUpdate();
- // const loader = new GLTFLoader();
- // const dracoLoader = new 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);
+ // dracoLoader.setDecoderPath('https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/');
+ // loader.setDRACOLoader(dracoLoader);
- ////////// Assest Configuration Values //////////
+ ////////// Assest Configuration Values //////////
- const AssetConfigurations: Types.AssetConfigurations = {
- arch: {
- modelUrl: arch,
- scale: [0.75, 0.75, 0.75],
- csgscale: [2, 4, 0.5],
- csgposition: [0, 2, 0],
- positionY: () => 0,
- type: "Fixed-Move",
- },
- door: {
- modelUrl: door,
- scale: [0.75, 0.75, 0.75],
- csgscale: [2, 4, 0.5],
- csgposition: [0, 2, 0],
- positionY: () => 0,
- type: "Fixed-Move",
- },
- window: {
- modelUrl: Window,
- scale: [0.75, 0.75, 0.75],
- csgscale: [5, 3, 0.5],
- csgposition: [0, 1.5, 0],
- positionY: (intersectionPoint) => intersectionPoint.point.y,
- type: "Free-Move",
- },
- };
+ const AssetConfigurations: Types.AssetConfigurations = {
+ arch: {
+ modelUrl: arch,
+ scale: [0.75, 0.75, 0.75],
+ csgscale: [2, 4, 0.5],
+ csgposition: [0, 2, 0],
+ type: "Fixed-Move",
+ },
+ door: {
+ modelUrl: door,
+ scale: [0.75, 0.75, 0.75],
+ csgscale: [2, 4, 0.5],
+ csgposition: [0, 2, 0],
+ type: "Fixed-Move",
+ },
+ window: {
+ modelUrl: Window,
+ scale: [0.75, 0.75, 0.75],
+ csgscale: [5, 3, 0.5],
+ csgposition: [0, 1.5, 0],
+ type: "Free-Move",
+ },
+ };
- ////////// All Toggle's //////////
+ ////////// All Toggle's //////////
useEffect(() => {
setRefTextUpdate((prevUpdate: number) => prevUpdate - 1);
@@ -177,167 +174,167 @@ export default function Builder() {
}
}, [toggleView]);
- useEffect(() => {
- THREE.Cache.clear();
- THREE.Cache.enabled = true;
- }, []);
+ useEffect(() => {
+ THREE.Cache.clear();
+ THREE.Cache.enabled = true;
+ }, []);
- useEffect(() => {
- const email = localStorage.getItem("email");
- const organization = email!.split("@")[1].split(".")[0];
+ useEffect(() => {
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
- async function fetchVisibility() {
- const visibility = await findEnvironment(
- organization,
- localStorage.getItem("userId")!
- );
- if (visibility) {
- setRoofVisibility(visibility.roofVisibility);
- setWallVisibility(visibility.wallVisibility);
- setShadows(visibility.shadowVisibility);
- setRenderDistance(visibility.renderDistance);
- setLimitDistance(visibility.limitDistance);
- }
- }
- fetchVisibility();
- }, []);
+ async function fetchVisibility() {
+ const visibility = await findEnvironment(
+ organization,
+ localStorage.getItem("userId")!
+ );
+ if (visibility) {
+ setRoofVisibility(visibility.roofVisibility);
+ setWallVisibility(visibility.wallVisibility);
+ setShadows(visibility.shadowVisibility);
+ setRenderDistance(visibility.renderDistance);
+ setLimitDistance(visibility.limitDistance);
+ }
+ }
+ fetchVisibility();
+ }, []);
- ////////// UseFrame is Here //////////
+ ////////// UseFrame is Here //////////
- useFrame(() => {
- if (toolMode) {
- Draw(
- state,
- plane,
- cursorPosition,
- floorPlanGroupPoint,
- floorPlanGroupLine,
- snappedPoint,
- isSnapped,
- isSnappedUUID,
- line,
- lines,
- ispreSnapped,
- floorPlanGroup,
- ReferenceLineMesh,
- LineCreated,
- setRefTextUpdate,
- Tube,
- anglesnappedPoint,
- isAngleSnapped,
- toolMode
- );
- }
- });
+ useFrame(() => {
+ if (toolMode) {
+ Draw(
+ state,
+ plane,
+ cursorPosition,
+ floorPlanGroupPoint,
+ floorPlanGroupLine,
+ snappedPoint,
+ isSnapped,
+ isSnappedUUID,
+ line,
+ lines,
+ ispreSnapped,
+ floorPlanGroup,
+ ReferenceLineMesh,
+ LineCreated,
+ setRefTextUpdate,
+ Tube,
+ anglesnappedPoint,
+ isAngleSnapped,
+ toolMode
+ );
+ }
+ });
- ////////// Return //////////
+ ////////// Return //////////
- return (
- <>
-
+ return (
+ <>
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
- >
- );
+
+
+
+ >
+ );
}
diff --git a/app/src/modules/builder/csg/csg.tsx b/app/src/modules/builder/csg/csg.tsx
index 7e49598..eab8edc 100644
--- a/app/src/modules/builder/csg/csg.tsx
+++ b/app/src/modules/builder/csg/csg.tsx
@@ -4,51 +4,51 @@ import { useDeleteTool } from "../../../store/store";
import { useRef } from "react";
export interface CsgProps {
- position: THREE.Vector3 | [number, number, number];
- scale: THREE.Vector3 | [number, number, number];
- model: THREE.Object3D;
- hoveredDeletableWallItem: { current: THREE.Mesh | null };
+ position: THREE.Vector3 | [number, number, number];
+ scale: THREE.Vector3 | [number, number, number];
+ model: THREE.Object3D;
+ hoveredDeletableWallItem: { current: THREE.Mesh | null };
}
export const Csg: React.FC = (props) => {
- const { deleteTool } = useDeleteTool();
- const modelRef = useRef();
- const originalMaterials = useRef>(new Map());
+ const { deleteTool } = useDeleteTool();
+ const modelRef = useRef();
+ const originalMaterials = useRef>(new Map());
- const handleHover = (hovered: boolean, object: THREE.Mesh | null) => {
- if (modelRef.current && deleteTool) {
- modelRef.current.traverse((child) => {
- if (child instanceof THREE.Mesh) {
- if (!originalMaterials.current.has(child)) {
- originalMaterials.current.set(child, child.material);
- }
- child.material = child.material.clone();
- child.material.color.set(hovered && deleteTool ? 0xff0000 : (originalMaterials.current.get(child) as any).color);
+ const handleHover = (hovered: boolean, object: THREE.Mesh | null) => {
+ if (modelRef.current && deleteTool) {
+ modelRef.current.traverse((child) => {
+ if (child instanceof THREE.Mesh) {
+ if (!originalMaterials.current.has(child)) {
+ originalMaterials.current.set(child, child.material);
+ }
+ child.material = child.material.clone();
+ child.material.color.set(hovered && deleteTool ? 0xff0000 : (originalMaterials.current.get(child) as any).color);
+ }
+ });
}
- });
- }
- props.hoveredDeletableWallItem.current = hovered ? object : null;
- };
+ props.hoveredDeletableWallItem.current = hovered ? object : null;
+ };
- return (
-
-
+ return (
-
+
+
+
+
+
+ {
+ e.stopPropagation();
+ handleHover(true, e.object.parent);
+ }}
+ onPointerOut={(e: any) => {
+ e.stopPropagation();
+ handleHover(false, null);
+ }}
+ />
-
- {
- e.stopPropagation();
- handleHover(true, e.object.parent);
- }}
- onPointerOut={(e: any) => {
- e.stopPropagation();
- handleHover(false, null);
- }}
- />
-
- );
+ );
};
diff --git a/app/src/modules/builder/geomentries/floors/addFloorToScene.ts b/app/src/modules/builder/geomentries/floors/addFloorToScene.ts
index c951ba0..71f2d24 100644
--- a/app/src/modules/builder/geomentries/floors/addFloorToScene.ts
+++ b/app/src/modules/builder/geomentries/floors/addFloorToScene.ts
@@ -2,8 +2,8 @@ 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/concreteFloorWorn001Diff2k.jpg";
-import normalPath from "../../../../assets/textures/floor/concreteFloorWorn001NorGl2k.jpg";
+import texturePath from "../../../../assets/textures/floor/white.png";
+import texturePathDark from "../../../../assets/textures/floor/black.png";
// Cache for materials
const materialCache = new Map();
@@ -14,6 +14,8 @@ export default function addFloorToScene(
floorGroup: Types.RefGroup,
userData: any,
) {
+ const savedTheme: string | null = localStorage.getItem('theme');
+
const textureLoader = new THREE.TextureLoader();
const textureScale = CONSTANTS.floorConfig.textureScale;
@@ -25,19 +27,15 @@ export default function addFloorToScene(
if (materialCache.has(materialKey)) {
material = materialCache.get(materialKey) as THREE.Material;
} else {
- const floorTexture = textureLoader.load(texturePath);
- const normalMap = textureLoader.load(normalPath);
+ 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;
- normalMap.wrapS = normalMap.wrapT = THREE.RepeatWrapping;
- normalMap.repeat.set(textureScale, textureScale);
-
material = new THREE.MeshStandardMaterial({
map: floorTexture,
- normalMap: normalMap,
side: THREE.DoubleSide,
});
diff --git a/app/src/modules/builder/geomentries/walls/addWallItems.ts b/app/src/modules/builder/geomentries/walls/addWallItems.ts
index fd9eb48..8b472ec 100644
--- a/app/src/modules/builder/geomentries/walls/addWallItems.ts
+++ b/app/src/modules/builder/geomentries/walls/addWallItems.ts
@@ -35,7 +35,7 @@ async function AddWallItems(
});
const config = AssetConfigurations[selected];
- let positionY = typeof config.positionY === 'function' ? config.positionY(intersectionPoint) : config.positionY;
+ let positionY = config.type === 'Fixed-Move' ? 0 : intersectionPoint.point.y;
if (positionY === 0) {
positionY = Math.floor(intersectionPoint.point.y / CONSTANTS.wallConfig.height) * CONSTANTS.wallConfig.height;
}
diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx
index 1ab9d59..e58530b 100644
--- a/app/src/modules/builder/groups/floorItemsGroup.tsx
+++ b/app/src/modules/builder/groups/floorItemsGroup.tsx
@@ -1,7 +1,6 @@
import { useFrame, useThree } from "@react-three/fiber";
import {
useActiveTool,
- useAsset3dWidget,
useCamMode,
useDeletableFloorItem,
useDeleteTool,
@@ -12,9 +11,7 @@ import {
useSelectedItem,
useSocketStore,
useToggleView,
- useTransformMode,
} from "../../../store/store";
-import assetVisibility from "../geomentries/assets/assetVisibility";
import { useEffect } from "react";
import * as THREE from "three";
import * as Types from "../../../types/world/worldTypes";
@@ -29,7 +26,6 @@ import loadInitialFloorItems from "../IntialLoad/loadInitialFloorItems";
import addAssetModel from "../geomentries/assets/addAssetModel";
import { getFloorAssets } from "../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi";
import useModuleStore from "../../../store/useModuleStore";
-// import { retrieveGLTF } from "../../../utils/indexDB/idbUtils";
import { useEventsStore } from "../../../store/simulation/useEventsStore";
const assetManagerWorker = new Worker(
@@ -62,7 +58,6 @@ const FloorItemsGroup = ({
const { camMode } = useCamMode();
const { deleteTool } = useDeleteTool();
const { setDeletableFloorItem } = useDeletableFloorItem();
- const { transformMode } = useTransformMode();
const { setSelectedFloorItem } = useSelectedFloorItem();
const { activeTool } = useActiveTool();
const { selectedItem, setSelectedItem } = useSelectedItem();
@@ -198,9 +193,7 @@ const FloorItemsGroup = ({
};
const startInterval = () => {
- if (!intervalId) {
- intervalId = setInterval(handleChange, 50);
- }
+ intervalId ??= setInterval(handleChange, 50);
};
const stopInterval = () => {
@@ -262,9 +255,8 @@ const FloorItemsGroup = ({
socket
);
}
- const Mode = transformMode;
- if (Mode !== null || activeTool === "cursor") {
+ if (activeTool === "cursor") {
if (!itemsGroup.current) return;
let intersects = raycaster.intersectObjects(
itemsGroup.current.children,
@@ -301,9 +293,8 @@ const FloorItemsGroup = ({
isLeftMouseDown = false;
if (drag) return;
- const Mode = transformMode;
- if (Mode !== null || activeTool === "cursor") {
+ if (activeTool === "cursor") {
if (!itemsGroup.current) return;
let intersects = raycaster.intersectObjects(
itemsGroup.current.children,
@@ -417,16 +408,7 @@ const FloorItemsGroup = ({
canvasElement.removeEventListener("drop", onDrop);
canvasElement.removeEventListener("dragover", onDragOver);
};
- }, [
- deleteTool,
- transformMode,
- controls,
- selectedItem,
- state.camera,
- state.pointer,
- activeTool,
- activeModule,
- ]);
+ }, [deleteTool, controls, selectedItem, state.camera, state.pointer, activeTool, activeModule,]);
useFrame(() => {
if (controls)
diff --git a/app/src/modules/builder/groups/wallItemsGroup.tsx b/app/src/modules/builder/groups/wallItemsGroup.tsx
index 76ba502..faae06d 100644
--- a/app/src/modules/builder/groups/wallItemsGroup.tsx
+++ b/app/src/modules/builder/groups/wallItemsGroup.tsx
@@ -1,12 +1,12 @@
import { useEffect } from "react";
import {
- useDeleteTool,
- useDeletePointOrLine,
- useObjectPosition,
- useObjectRotation,
- useSelectedWallItem,
- useSocketStore,
- useWallItems,
+ useDeleteTool,
+ useDeletePointOrLine,
+ useObjectPosition,
+ useObjectRotation,
+ useSelectedWallItem,
+ useSocketStore,
+ useWallItems,
} from "../../../store/store";
import { Csg } from "../csg/csg";
import * as Types from "../../../types/world/worldTypes";
@@ -20,276 +20,276 @@ import AddWallItems from "../geomentries/walls/addWallItems";
import useModuleStore from "../../../store/useModuleStore";
const WallItemsGroup = ({
- currentWallItem,
- AssetConfigurations,
- hoveredDeletableWallItem,
- selectedItemsIndex,
- setSelectedItemsIndex,
- CSGGroup,
+ currentWallItem,
+ AssetConfigurations,
+ hoveredDeletableWallItem,
+ selectedItemsIndex,
+ setSelectedItemsIndex,
+ CSGGroup,
}: any) => {
- const state = useThree();
- const { socket } = useSocketStore();
- const { pointer, camera, raycaster } = state;
- const { deleteTool } = useDeleteTool();
- const { wallItems, setWallItems } = useWallItems();
- const { setObjectPosition } = useObjectPosition();
- const { setObjectRotation } = useObjectRotation();
- const { deletePointOrLine } = useDeletePointOrLine();
- const { setSelectedWallItem } = useSelectedWallItem();
- const { activeModule } = useModuleStore();
+ const state = useThree();
+ const { socket } = useSocketStore();
+ const { pointer, camera, raycaster } = state;
+ const { deleteTool } = useDeleteTool();
+ const { wallItems, setWallItems } = useWallItems();
+ const { setObjectPosition } = useObjectPosition();
+ const { setObjectRotation } = useObjectRotation();
+ const { deletePointOrLine } = useDeletePointOrLine();
+ const { setSelectedWallItem } = useSelectedWallItem();
+ const { activeModule } = useModuleStore();
- useEffect(() => {
- // Load Wall Items from the backend
- loadInitialWallItems(setWallItems, AssetConfigurations);
- }, []);
+ useEffect(() => {
+ // Load Wall Items from the backend
+ loadInitialWallItems(setWallItems, AssetConfigurations);
+ }, []);
- ////////// Update the Scale value changes in thewallItems State //////////
+ ////////// Update the Scale value changes in thewallItems State //////////
- ////////// Update the Position value changes in the selected item //////////
+ ////////// Update the Position value changes in the selected item //////////
- ////////// Update the Rotation value changes in the selected item //////////
+ ////////// Update the Rotation value changes in the selected item //////////
- useEffect(() => {
- const canvasElement = state.gl.domElement;
- function handlePointerMove(e: any) {
- if (
- selectedItemsIndex !== null &&
- !deletePointOrLine &&
- 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 &&
+ !deletePointOrLine &&
+ 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),
+ });
+ });
+
+ updatedItems[selectedItemsIndex] = {
+ ...updatedItems[selectedItemsIndex],
+ position: position,
+ quaternion:
+ Object!.object.quaternion.clone() as Types.QuaternionType,
+ };
+
+ return updatedItems;
+ });
+ }
}
-
- 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,
- };
-
- 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,
- };
- });
-
- currentItem = updatedItems[selectedItemsIndex];
- localStorage.setItem(
- "WallItems",
- JSON.stringify(WallItemsForStorage)
+ async function handlePointerUp() {
+ const Raycaster = state.raycaster;
+ const intersects = Raycaster.intersectObjects(
+ CSGGroup.current?.children[0].children!,
+ true
);
- return updatedItems;
- });
+ 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,
+ };
+ });
- setTimeout(async () => {
- const email = localStorage.getItem("email");
- const organization = email!.split("@")[1].split(".")[0];
+ currentItem = updatedItems[selectedItemsIndex];
+ localStorage.setItem(
+ "WallItems",
+ JSON.stringify(WallItemsForStorage)
+ );
+ return updatedItems;
+ });
- //REST
+ setTimeout(async () => {
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
- // await setWallItem(
- // organization,
- // currentItem?.model?.uuid,
- // currentItem.modelName,
- // currentItem.type!,
- // currentItem.csgposition!,
- // currentItem.csgscale!,
- // currentItem.position,
- // currentItem.quaternion,
- // currentItem.scale!,
- // )
+ //REST
- //SOCKET
+ // await setWallItem(
+ // organization,
+ // currentItem?.model?.uuid,
+ // currentItem.modelName,
+ // currentItem.type!,
+ // currentItem.csgposition!,
+ // currentItem.csgscale!,
+ // currentItem.position,
+ // currentItem.quaternion,
+ // currentItem.scale!,
+ // )
- const data = {
- organization: organization,
- modelUuid: currentItem.model?.uuid!,
- modelName: currentItem.modelName!,
- type: currentItem.type!,
- csgposition: currentItem.csgposition!,
- csgscale: currentItem.csgscale!,
- position: currentItem.position!,
- quaternion: currentItem.quaternion,
- scale: currentItem.scale!,
- socketId: socket.id,
- };
+ //SOCKET
- socket.emit("v1:wallItems:set", data);
- }, 0);
- (state.controls as any)!.enabled = true;
+ const data = {
+ organization: organization,
+ modelUuid: currentItem.model?.uuid!,
+ modelName: currentItem.modelName!,
+ type: currentItem.type!,
+ csgposition: currentItem.csgposition!,
+ csgscale: currentItem.csgscale!,
+ position: currentItem.position!,
+ quaternion: currentItem.quaternion,
+ scale: currentItem.scale!,
+ socketId: socket.id,
+ };
+
+ 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]);
+ return () => {
+ canvasElement.removeEventListener("pointermove", handlePointerMove);
+ canvasElement.removeEventListener("pointerup", handlePointerUp);
+ };
+ }, [selectedItemsIndex]);
- 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 && deleteTool && activeModule === "builder") {
- DeleteWallItems(
- hoveredDeletableWallItem,
- setWallItems,
- wallItems,
- socket
- );
+ const onMouseUp = (evt: any) => {
+ if (evt.button === 0) {
+ isLeftMouseDown = false;
+ if (!drag && deleteTool && activeModule === "builder") {
+ DeleteWallItems(
+ hoveredDeletableWallItem,
+ setWallItems,
+ wallItems,
+ socket
+ );
+ }
+ }
+ };
+
+ const onMouseMove = () => {
+ if (isLeftMouseDown) {
+ drag = true;
+ }
+ };
+
+ const onDrop = (event: any) => {
+ if (!event.dataTransfer?.files[0]) return;
+
+ pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
+ pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
+ raycaster.setFromCamera(pointer, camera);
+
+ if (AssetConfigurations[event.dataTransfer.files[0].name.split(".")[0]]) {
+ const selected = event.dataTransfer.files[0].name.split(".")[0];
+
+ if (AssetConfigurations[selected]?.type) {
+ AddWallItems(
+ selected,
+ raycaster,
+ CSGGroup,
+ AssetConfigurations,
+ setWallItems,
+ socket
+ );
+ }
+ 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);
+
+ return () => {
+ canvasElement.removeEventListener("mousedown", onMouseDown);
+ canvasElement.removeEventListener("mouseup", onMouseUp);
+ canvasElement.removeEventListener("mousemove", onMouseMove);
+ canvasElement.removeEventListener("drop", onDrop);
+ canvasElement.removeEventListener("dragover", onDragOver);
+ };
+ }, [deleteTool, wallItems]);
+
+ useEffect(() => {
+ if (deleteTool && activeModule === "builder") {
+ handleMeshMissed(
+ currentWallItem,
+ setSelectedWallItem,
+ setSelectedItemsIndex
+ );
+ setSelectedWallItem(null);
+ setSelectedItemsIndex(null);
}
- }
- };
+ }, [deleteTool]);
- const onMouseMove = () => {
- if (isLeftMouseDown) {
- drag = true;
- }
- };
-
- const onDrop = (event: any) => {
- if (!event.dataTransfer?.files[0]) return;
-
- pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
- pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
- raycaster.setFromCamera(pointer, camera);
-
- if (AssetConfigurations[event.dataTransfer.files[0].name.split(".")[0]]) {
- const selected = event.dataTransfer.files[0].name.split(".")[0];
-
- if (AssetConfigurations[selected]?.type) {
- AddWallItems(
- selected,
- raycaster,
- CSGGroup,
- AssetConfigurations,
- setWallItems,
- socket
- );
- }
- 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);
-
- return () => {
- canvasElement.removeEventListener("mousedown", onMouseDown);
- canvasElement.removeEventListener("mouseup", onMouseUp);
- canvasElement.removeEventListener("mousemove", onMouseMove);
- canvasElement.removeEventListener("drop", onDrop);
- canvasElement.removeEventListener("dragover", onDragOver);
- };
- }, [deleteTool, wallItems]);
-
- useEffect(() => {
- if (deleteTool && activeModule === "builder") {
- handleMeshMissed(
- currentWallItem,
- setSelectedWallItem,
- setSelectedItemsIndex
- );
- setSelectedWallItem(null);
- setSelectedItemsIndex(null);
- }
- }, [deleteTool]);
-
- return (
- <>
- {wallItems.map((item: Types.WallItem, index: number) => (
-
-
-
- ))}
- >
- );
+ return (
+ <>
+ {wallItems.map((item: Types.WallItem, index: number) => (
+
+
+
+ ))}
+ >
+ );
};
export default WallItemsGroup;
diff --git a/app/src/modules/builder/groups/wallsAndWallItems.tsx b/app/src/modules/builder/groups/wallsAndWallItems.tsx
index 6b6c97d..19d5833 100644
--- a/app/src/modules/builder/groups/wallsAndWallItems.tsx
+++ b/app/src/modules/builder/groups/wallsAndWallItems.tsx
@@ -1,29 +1,32 @@
import { Geometry } from "@react-three/csg";
-import { useDeleteTool, useSelectedWallItem, useToggleView, useTransformMode, useWallItems, useWalls } from "../../../store/store";
+import {
+ useDeleteTool,
+ useSelectedWallItem,
+ useToggleView,
+ useWallItems,
+ useWalls,
+} from "../../../store/store";
import handleMeshDown from "../eventFunctions/handleMeshDown";
import handleMeshMissed from "../eventFunctions/handleMeshMissed";
import WallsMesh from "./wallsMesh";
import WallItemsGroup from "./wallItemsGroup";
import { useEffect } from "react";
-
-const WallsAndWallItems = ({ CSGGroup, AssetConfigurations, setSelectedItemsIndex, selectedItemsIndex, currentWallItem, csg, lines, hoveredDeletableWallItem }: any) => {
- const { walls, setWalls } = useWalls();
- const { wallItems, setWallItems } = useWallItems();
- const { toggleView, setToggleView } = useToggleView();
- const { deleteTool, setDeleteTool } = useDeleteTool();
- const { transformMode, setTransformMode } = useTransformMode();
- const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
-
- useEffect(() => {
- if (transformMode === null) {
- if (!deleteTool) {
- handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex);
- setSelectedWallItem(null);
- setSelectedItemsIndex(null);
- }
- }
- }, [transformMode])
+const WallsAndWallItems = ({
+ CSGGroup,
+ AssetConfigurations,
+ setSelectedItemsIndex,
+ selectedItemsIndex,
+ currentWallItem,
+ csg,
+ lines,
+ hoveredDeletableWallItem,
+}: any) => {
+ const { walls } = useWalls();
+ const { wallItems } = useWallItems();
+ const { toggleView } = useToggleView();
+ const { deleteTool } = useDeleteTool();
+ const { setSelectedWallItem } = useSelectedWallItem();
return (
{
- if (!deleteTool && transformMode !== null) {
- handleMeshDown(event, currentWallItem, setSelectedWallItem, setSelectedItemsIndex, wallItems, toggleView);
+ if (!deleteTool) {
+ handleMeshDown(
+ event,
+ currentWallItem,
+ setSelectedWallItem,
+ setSelectedItemsIndex,
+ wallItems,
+ toggleView
+ );
}
}}
onPointerMissed={() => {
if (!deleteTool) {
- handleMeshMissed(currentWallItem, setSelectedWallItem, setSelectedItemsIndex);
+ handleMeshMissed(
+ currentWallItem,
+ setSelectedWallItem,
+ setSelectedItemsIndex
+ );
setSelectedWallItem(null);
setSelectedItemsIndex(null);
}
@@ -47,10 +61,17 @@ const WallsAndWallItems = ({ CSGGroup, AssetConfigurations, setSelectedItemsInde
>
-
+
- )
-}
+ );
+};
-export default WallsAndWallItems;
\ No newline at end of file
+export default WallsAndWallItems;
diff --git a/app/src/modules/builder/groups/wallsMesh.tsx b/app/src/modules/builder/groups/wallsMesh.tsx
index 92a0ee3..9abf59d 100644
--- a/app/src/modules/builder/groups/wallsMesh.tsx
+++ b/app/src/modules/builder/groups/wallsMesh.tsx
@@ -1,23 +1,27 @@
-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/store';
-import { useEffect } from 'react';
-import { getLines } from '../../../services/factoryBuilder/lines/getLinesApi';
-import objectLinesToArray from '../geomentries/lines/lineConvertions/objectLinesToArray';
-import loadWalls from '../geomentries/walls/loadWalls';
+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/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";
+// texture
+import texturePath from "../../../assets/textures/floor/wall-tex.png";
-const WallsMesh = ({ lines }: any) => {
+// Cache for materials
+const materialCache = new Map();
+
+const WallsMeshComponent = ({ lines }: any) => {
const { walls, setWalls } = useWalls();
const { updateScene, setUpdateScene } = useUpdateScene();
useEffect(() => {
if (updateScene) {
-
- const email = localStorage.getItem('email')
- const organization = (email!.split("@")[1]).split(".")[0];
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
getLines(organization).then((data) => {
const Lines: Types.Lines = objectLinesToArray(data);
@@ -26,15 +30,22 @@ const WallsMesh = ({ lines }: any) => {
if (Lines) {
loadWalls(lines, setWalls);
}
- })
+ });
setUpdateScene(false);
}
- }, [updateScene])
+ }, [updateScene]);
+
+ 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;
return (
<>
{walls.map((wall: Types.Wall, index: number) => (
-
+
{
{
))}
>
- )
-}
+ );
+};
-export default WallsMesh;
\ No newline at end of file
+const WallsMesh = React.memo(WallsMeshComponent);
+export default WallsMesh;
diff --git a/app/src/modules/scene/controls/controls.tsx b/app/src/modules/scene/controls/controls.tsx
index 8bdd3aa..1420d89 100644
--- a/app/src/modules/scene/controls/controls.tsx
+++ b/app/src/modules/scene/controls/controls.tsx
@@ -10,6 +10,7 @@ import updateCamPosition from "../camera/updateCameraPosition";
import CamMode from "../camera/camMode";
import SwitchView from "../camera/switchView";
import SelectionControls from "./selectionControls/selectionControls";
+import TransformControl from "./transformControls/transformControls";
export default function Controls() {
const controlsRef = useRef(null);
@@ -138,6 +139,8 @@ export default function Controls() {
+
+
>
);
}
\ No newline at end of file
diff --git a/app/src/modules/scene/controls/selectionControls/distanceFindingControls.tsx b/app/src/modules/scene/controls/selectionControls/distanceFindingControls.tsx
index 25e6c96..1cfe244 100644
--- a/app/src/modules/scene/controls/selectionControls/distanceFindingControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/distanceFindingControls.tsx
@@ -1,270 +1,270 @@
import React, { useRef } from "react";
import {
- Vector3,
- Raycaster,
- BufferGeometry,
- LineBasicMaterial,
- Line,
- Mesh,
- Group,
+ Vector3,
+ Raycaster,
+ BufferGeometry,
+ LineBasicMaterial,
+ Line,
+ Mesh,
+ Group,
} from "three";
import { useThree, useFrame } from "@react-three/fiber";
import { Html } from "@react-three/drei";
interface DistanceFindingControlsProps {
- boundingBoxRef: React.RefObject;
- object: number;
+ boundingBoxRef: React.RefObject;
+ object: number;
}
const DistanceFindingControls = ({
- boundingBoxRef,
- object,
+ boundingBoxRef,
+ object,
}: DistanceFindingControlsProps) => {
- const { camera, scene } = useThree();
+ const { camera, scene } = useThree();
- // 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 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);
+ // 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(),
- });
+ // 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;
+ useFrame(() => {
+ if (!boundingBoxRef?.current) return;
- boundingBoxRef.current.geometry.computeBoundingBox();
- const bbox = boundingBoxRef.current.geometry.boundingBox;
+ boundingBoxRef.current.geometry.computeBoundingBox();
+ const bbox = boundingBoxRef.current.geometry.boundingBox;
- if (!bbox) return;
+ 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 size = {
+ x: bbox.max.x - bbox.min.x,
+ y: bbox.max.y - bbox.min.y,
+ z: bbox.max.z - bbox.min.z,
+ };
+
+ const vec = boundingBoxRef.current?.getWorldPosition(new Vector3()).clone();
+
+ 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,
+ });
+ updateLine({
+ line: line2.current,
+ geometry: lineGeometries.current.negX,
+ direction: new Vector3(-1, 0, 0), // Negative X
+ angle: "neg",
+ mesh: textNegX,
+ vec,
+ size,
+ });
+ 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 points = [];
+
+ 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 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;
+
+ // Find intersection points
+ const wallsGroup = scene.children.find((val) =>
+ val?.name.includes("Walls")
+ );
+ 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;
+ }
+ }
+ }
+
+ // Update line geometry
+ if (points[1]) {
+ geometry.dispose();
+ geometry.setFromPoints([points[0], points[1]]);
+ line.geometry = geometry;
+
+ // 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 = `${points[0].distanceTo(points[1]).toFixed(2)}m`;
+ }
+ }
+ } 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 = "";
+ }
};
- const vec = boundingBoxRef.current?.getWorldPosition(new Vector3()).clone();
+ const Material = new LineBasicMaterial({ color: "#d2baff" });
- 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,
- });
- updateLine({
- line: line2.current,
- geometry: lineGeometries.current.negX,
- direction: new Vector3(-1, 0, 0), // Negative X
- angle: "neg",
- mesh: textNegX,
- vec,
- size,
- });
- 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 points = [];
-
- 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 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;
-
- // Find intersection points
- const wallsGroup = scene.children.find((val) =>
- val?.name.includes("Walls")
- );
- 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;
- }
- }
- }
-
- // Update line geometry
- if (points[1]) {
- geometry.dispose();
- geometry.setFromPoints([points[0], points[1]]);
- line.geometry = geometry;
-
- // 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 = `${points[0].distanceTo(points[1]).toFixed(2)}m`;
- }
- }
- } 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 = "";
- }
- };
-
- const Material = new LineBasicMaterial({ color: "#d2baff" });
-
- return (
- <>
- {/* Measurement text labels */}
- {boundingBoxRef.current && object > 0 && (
+ return (
<>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ {/* Measurement text labels */}
+ {boundingBoxRef.current && object > 0 && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- {/* Measurement lines */}
-
-
-
-
+ {/* Measurement lines */}
+
+
+
+
+ >
+ )}
>
- )}
- >
- );
+ );
};
export default DistanceFindingControls;
diff --git a/app/src/modules/scene/controls/selectionControls/moveControls.tsx b/app/src/modules/scene/controls/selectionControls/moveControls.tsx
index 498056a..5398fe6 100644
--- a/app/src/modules/scene/controls/selectionControls/moveControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/moveControls.tsx
@@ -2,10 +2,10 @@ import * as THREE from "three";
import { useEffect, useMemo, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import {
- useFloorItems,
- useSelectedAssets,
- useSocketStore,
- useToggleView,
+ useFloorItems,
+ useSelectedAssets,
+ useSocketStore,
+ useToggleView,
} from "../../../../store/store";
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
import { toast } from "react-toastify";
@@ -19,370 +19,337 @@ import { snapControls } from "../../../../utils/handleSnap";
import DistanceFindingControls from "./distanceFindingControls";
function MoveControls({
- movedObjects,
- setMovedObjects,
- itemsGroupRef,
- copiedObjects,
- setCopiedObjects,
- pastedObjects,
- setpastedObjects,
- duplicatedObjects,
- setDuplicatedObjects,
- selectionGroup,
- rotatedObjects,
- setRotatedObjects,
- boundingBoxRef,
-}: any) {
- const { camera, controls, gl, scene, pointer, raycaster } = useThree();
- const plane = useMemo(
- () => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0),
- []
- );
-
- const { toggleView } = useToggleView();
- const { selectedAssets, setSelectedAssets } = useSelectedAssets();
- const { selectedProduct } = useSelectedProduct();
- const { floorItems, setFloorItems } = useFloorItems();
- const { socket } = useSocketStore();
- const itemsData = useRef([]);
- const [keyEvent, setKeyEvent] = useState<
- "Ctrl" | "Shift" | "Ctrl+Shift" | ""
- >("");
- const email = localStorage.getItem("email");
- const organization = email!.split("@")[1].split(".")[0];
-
- const updateBackend = (
- productName: string,
- productId: string,
- organization: string,
- eventData: EventsSchema
- ) => {
- upsertProductOrEventApi({
- productName: productName,
- productId: productId,
- organization: organization,
- eventDatas: eventData,
- });
- };
-
- useEffect(() => {
- if (!camera || !scene || toggleView || !itemsGroupRef.current) return;
-
- const canvasElement = gl.domElement;
- canvasElement.tabIndex = 0;
-
- let isMoving = false;
-
- const onPointerDown = () => {
- isMoving = false;
- };
-
- const onPointerMove = () => {
- isMoving = true;
- };
- const onKeyUp = (event: KeyboardEvent) => {
- // When any modifier is released, reset snap
- const isModifierKey = event.key === "Control" || event.key === "Shift";
-
- if (isModifierKey) {
- setKeyEvent("");
- }
- };
-
- const onPointerUp = (event: PointerEvent) => {
- if (!isMoving && movedObjects.length > 0 && event.button === 0) {
- event.preventDefault();
- placeMovedAssets();
- }
- if (!isMoving && movedObjects.length > 0 && event.button === 2) {
- event.preventDefault();
-
- clearSelection();
- movedObjects.forEach((asset: any) => {
- if (itemsGroupRef.current) {
- itemsGroupRef.current.attach(asset);
- }
- });
-
- setFloorItems([...floorItems, ...itemsData.current]);
-
- setMovedObjects([]);
- itemsData.current = [];
- }
- setKeyEvent("");
- };
-
- const onKeyDown = (event: KeyboardEvent) => {
- const keyCombination = detectModifierKeys(event);
-
- if (
- pastedObjects.length > 0 ||
- duplicatedObjects.length > 0 ||
- rotatedObjects.length > 0
- )
- return;
-
- if (
- keyCombination === "Ctrl" ||
- keyCombination === "Ctrl+Shift" ||
- keyCombination === "Shift"
- ) {
- // update state here
- setKeyEvent(keyCombination);
- } else {
- setKeyEvent("");
- }
-
- if (keyCombination === "G") {
- if (selectedAssets.length > 0) {
- moveAssets();
- itemsData.current = floorItems.filter((item: { modelUuid: string }) =>
- selectedAssets.some((asset: any) => asset.uuid === item.modelUuid)
- );
- }
- }
-
- if (keyCombination === "ESCAPE") {
- event.preventDefault();
-
- clearSelection();
- movedObjects.forEach((asset: any) => {
- if (itemsGroupRef.current) {
- itemsGroupRef.current.attach(asset);
- }
- });
-
- setFloorItems([...floorItems, ...itemsData.current]);
-
- setMovedObjects([]);
- itemsData.current = [];
- }
- };
-
- if (!toggleView) {
- canvasElement.addEventListener("pointerdown", onPointerDown);
- canvasElement.addEventListener("pointermove", onPointerMove);
- canvasElement.addEventListener("pointerup", onPointerUp);
- canvasElement.addEventListener("keydown", onKeyDown);
- canvasElement?.addEventListener("keyup", onKeyUp);
- }
-
- return () => {
- canvasElement.removeEventListener("pointerdown", onPointerDown);
- canvasElement.removeEventListener("pointermove", onPointerMove);
- canvasElement.removeEventListener("pointerup", onPointerUp);
- canvasElement.removeEventListener("keydown", onKeyDown);
- canvasElement?.removeEventListener("keyup", onKeyUp);
- };
- }, [
- camera,
- controls,
- scene,
- toggleView,
- selectedAssets,
- socket,
- floorItems,
- pastedObjects,
- duplicatedObjects,
movedObjects,
+ setMovedObjects,
+ itemsGroupRef,
+ pastedObjects,
+ setpastedObjects,
+ duplicatedObjects,
+ setDuplicatedObjects,
+ selectionGroup,
rotatedObjects,
- keyEvent,
- ]);
+ setRotatedObjects,
+ boundingBoxRef,
+}: any) {
+ const { camera, controls, gl, scene, pointer, raycaster } = useThree();
+ const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
- let moveSpeed = keyEvent === "Ctrl" || "Ctrl+Shift" ? 1 : 0.25;
+ const { toggleView } = useToggleView();
+ const { selectedAssets, setSelectedAssets } = useSelectedAssets();
+ const { selectedProduct } = useSelectedProduct();
+ const { floorItems, setFloorItems } = useFloorItems();
+ const { socket } = useSocketStore();
+ const itemsData = useRef([]);
+ const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">("");
+ const email = localStorage.getItem("email");
+ const organization = email!.split("@")[1].split(".")[0];
- useFrame(() => {
- if (movedObjects.length > 0) {
- const intersectionPoint = new THREE.Vector3();
- raycaster.setFromCamera(pointer, camera);
- const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+ const updateBackend = (
+ productName: string,
+ productId: string,
+ organization: string,
+ eventData: EventsSchema
+ ) => {
+ upsertProductOrEventApi({
+ productName: productName,
+ productId: productId,
+ organization: organization,
+ eventDatas: eventData,
+ });
+ };
- if (point) {
- let targetX = point.x;
- let targetZ = point.z;
- if (keyEvent === "Ctrl") {
- targetX = snapControls(targetX, "Ctrl");
- targetZ = snapControls(targetZ, "Ctrl");
- }
- // else if (keyEvent === "Ctrl+Shift") {
- // targetX = snapControls(targetX, "Ctrl+Shift");
- // targetZ = snapControls(targetZ, "Ctrl+Shift");
- // } else if (keyEvent === "Shift") {
- // targetX = snapControls(targetX, "Shift");
- // targetZ = snapControls(targetZ, "Shift");
- // } else {
- // }
+ useEffect(() => {
+ if (!camera || !scene || toggleView || !itemsGroupRef.current) return;
- const position = new THREE.Vector3();
+ const canvasElement = gl.domElement;
+ canvasElement.tabIndex = 0;
- if (boundingBoxRef.current) {
- boundingBoxRef.current.getWorldPosition(position);
- selectionGroup.current.position.lerp(
- new THREE.Vector3(
- targetX - (position.x - selectionGroup.current.position.x),
- selectionGroup.current.position.y,
- targetZ - (position.z - selectionGroup.current.position.z)
- ),
- moveSpeed
- );
- } else {
- const box = new THREE.Box3();
- movedObjects.forEach((obj: THREE.Object3D) =>
- box.expandByObject(obj)
- );
- const center = new THREE.Vector3();
- box.getCenter(center);
+ let isMoving = false;
- selectionGroup.current.position.lerp(
- new THREE.Vector3(
- targetX - (center.x - selectionGroup.current.position.x),
- selectionGroup.current.position.y,
- targetZ - (center.z - selectionGroup.current.position.z)
- ),
- moveSpeed
- );
- }
- }
- }
- });
-
- const moveAssets = () => {
- const updatedItems = floorItems.filter(
- (item: { modelUuid: string }) =>
- !selectedAssets.some((asset: any) => asset.uuid === item.modelUuid)
- );
- setFloorItems(updatedItems);
- setMovedObjects(selectedAssets);
- selectedAssets.forEach((asset: any) => {
- selectionGroup.current.attach(asset);
- });
- };
-
- const placeMovedAssets = () => {
- if (movedObjects.length === 0) return;
-
- movedObjects.forEach(async (obj: THREE.Object3D) => {
- const worldPosition = new THREE.Vector3();
- obj.getWorldPosition(worldPosition);
-
- selectionGroup.current.remove(obj);
- obj.position.copy(worldPosition);
-
- if (itemsGroupRef.current) {
- const newFloorItem: Types.FloorItemType = {
- modelUuid: obj.uuid,
- modelName: obj.userData.name,
- modelfileID: obj.userData.modelId,
- position: [worldPosition.x, worldPosition.y, worldPosition.z],
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
+ const onPointerDown = () => {
+ isMoving = false;
};
- if (obj.userData.eventData) {
- const eventData = useEventsStore
- .getState()
- .getEventByModelUuid(obj.userData.modelUuid);
- const productData = useProductStore
- .getState()
- .getEventByModelUuid(
- useSelectedProduct.getState().selectedProduct.productId,
- obj.userData.modelUuid
- );
+ const onPointerMove = () => {
+ isMoving = true;
+ };
- if (eventData) {
- useEventsStore.getState().updateEvent(obj.userData.modelUuid, {
- position: [worldPosition.x, worldPosition.y, worldPosition.z],
- rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
- });
- }
- if (productData) {
- const event = useProductStore
- .getState()
- .updateEvent(
- useSelectedProduct.getState().selectedProduct.productId,
- obj.userData.modelUuid,
- {
- position: [worldPosition.x, worldPosition.y, worldPosition.z],
- rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
- }
- );
+ const onKeyUp = (event: KeyboardEvent) => {
+ const isModifierKey = event.key === "Control" || event.key === "Shift";
- if (event) {
- updateBackend(
- selectedProduct.productName,
- selectedProduct.productId,
- organization,
- event
- );
+ if (isModifierKey) {
+ setKeyEvent("");
+ }
+ };
+
+ const onPointerUp = (event: PointerEvent) => {
+ if (!isMoving && movedObjects.length > 0 && event.button === 0) {
+ event.preventDefault();
+ placeMovedAssets();
+ }
+ if (!isMoving && movedObjects.length > 0 && event.button === 2) {
+ event.preventDefault();
+
+ clearSelection();
+ movedObjects.forEach((asset: any) => {
+ if (itemsGroupRef.current) {
+ itemsGroupRef.current.attach(asset);
+ }
+ });
+
+ setFloorItems([...floorItems, ...itemsData.current]);
+
+ setMovedObjects([]);
+ itemsData.current = [];
+ }
+ setKeyEvent("");
+ };
+
+ const onKeyDown = (event: KeyboardEvent) => {
+ const keyCombination = detectModifierKeys(event);
+
+ if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0)
+ return;
+
+ if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") {
+ setKeyEvent(keyCombination);
+ } else {
+ setKeyEvent("");
}
- newFloorItem.eventData = eventData;
- }
- }
+ if (keyCombination === "G") {
+ if (selectedAssets.length > 0) {
+ moveAssets();
+ itemsData.current = floorItems.filter((item: { modelUuid: string }) =>
+ selectedAssets.some((asset: any) => asset.uuid === item.modelUuid)
+ );
+ }
+ }
- setFloorItems((prevItems: Types.FloorItems) => {
- const updatedItems = [...(prevItems || []), newFloorItem];
- localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
- return updatedItems;
- });
+ if (keyCombination === "ESCAPE") {
+ event.preventDefault();
- //REST
+ clearSelection();
+ movedObjects.forEach((asset: any) => {
+ if (itemsGroupRef.current) {
+ itemsGroupRef.current.attach(asset);
+ }
+ });
- // await setFloorItemApi(
- // organization,
- // obj.uuid,
- // obj.userData.name,
- // [worldPosition.x, worldPosition.y, worldPosition.z],
- // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
- // obj.userData.modelId,
- // false,
- // true,
- // );
+ setFloorItems([...floorItems, ...itemsData.current]);
- //SOCKET
-
- const data = {
- organization,
- modelUuid: newFloorItem.modelUuid,
- modelName: newFloorItem.modelName,
- modelfileID: newFloorItem.modelfileID,
- position: newFloorItem.position,
- rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
- isLocked: false,
- isVisible: true,
- socketId: socket.id,
+ setMovedObjects([]);
+ itemsData.current = [];
+ }
};
- socket.emit("v2:model-asset:add", data);
+ if (!toggleView) {
+ canvasElement.addEventListener("pointerdown", onPointerDown);
+ canvasElement.addEventListener("pointermove", onPointerMove);
+ canvasElement.addEventListener("pointerup", onPointerUp);
+ canvasElement.addEventListener("keydown", onKeyDown);
+ canvasElement?.addEventListener("keyup", onKeyUp);
+ }
- itemsGroupRef.current.add(obj);
- }
+ return () => {
+ canvasElement.removeEventListener("pointerdown", onPointerDown);
+ canvasElement.removeEventListener("pointermove", onPointerMove);
+ canvasElement.removeEventListener("pointerup", onPointerUp);
+ canvasElement.removeEventListener("keydown", onKeyDown);
+ canvasElement?.removeEventListener("keyup", onKeyUp);
+ };
+ }, [camera, controls, scene, toggleView, selectedAssets, socket, floorItems, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, keyEvent,]);
+
+ let moveSpeed = keyEvent === "Ctrl" || "Ctrl+Shift" ? 1 : 0.25;
+
+ useFrame(() => {
+ if (movedObjects.length > 0) {
+ const intersectionPoint = new THREE.Vector3();
+ raycaster.setFromCamera(pointer, camera);
+ const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
+
+ if (point) {
+ let targetX = point.x;
+ let targetZ = point.z;
+
+ if (keyEvent === "Ctrl") {
+ targetX = snapControls(targetX, "Ctrl");
+ targetZ = snapControls(targetZ, "Ctrl");
+ }
+
+ // else if (keyEvent === "Ctrl+Shift") {
+ // targetX = snapControls(targetX, "Ctrl+Shift");
+ // targetZ = snapControls(targetZ, "Ctrl+Shift");
+ // } else if (keyEvent === "Shift") {
+ // targetX = snapControls(targetX, "Shift");
+ // targetZ = snapControls(targetZ, "Shift");
+ // } else {
+ // }
+
+ const position = new THREE.Vector3();
+
+ if (boundingBoxRef.current) {
+ boundingBoxRef.current.getWorldPosition(position);
+ selectionGroup.current.position.lerp(
+ new THREE.Vector3(
+ targetX - (position.x - selectionGroup.current.position.x),
+ selectionGroup.current.position.y,
+ targetZ - (position.z - selectionGroup.current.position.z)
+ ),
+ moveSpeed
+ );
+ } else {
+ const box = new THREE.Box3();
+ movedObjects.forEach((obj: THREE.Object3D) =>
+ box.expandByObject(obj)
+ );
+ const center = new THREE.Vector3();
+ box.getCenter(center);
+
+ selectionGroup.current.position.lerp(
+ new THREE.Vector3(
+ targetX - (center.x - selectionGroup.current.position.x),
+ selectionGroup.current.position.y,
+ targetZ - (center.z - selectionGroup.current.position.z)
+ ),
+ moveSpeed
+ );
+ }
+ }
+ }
});
- toast.success("Object moved!");
- itemsData.current = [];
- clearSelection();
- };
+ const moveAssets = () => {
+ const updatedItems = floorItems.filter(
+ (item: { modelUuid: string }) =>
+ !selectedAssets.some((asset: any) => asset.uuid === item.modelUuid)
+ );
+ setFloorItems(updatedItems);
+ setMovedObjects(selectedAssets);
+ selectedAssets.forEach((asset: any) => {
+ selectionGroup.current.attach(asset);
+ });
+ };
- const clearSelection = () => {
- selectionGroup.current.children = [];
- selectionGroup.current.position.set(0, 0, 0);
- selectionGroup.current.rotation.set(0, 0, 0);
- setpastedObjects([]);
- setDuplicatedObjects([]);
- setMovedObjects([]);
- setRotatedObjects([]);
- setSelectedAssets([]);
- setKeyEvent("");
- };
+ const placeMovedAssets = () => {
+ if (movedObjects.length === 0) return;
- return (
-
- );
+ movedObjects.forEach(async (obj: THREE.Object3D) => {
+ const worldPosition = new THREE.Vector3();
+ obj.getWorldPosition(worldPosition);
+
+ selectionGroup.current.remove(obj);
+ obj.position.copy(worldPosition);
+
+ if (itemsGroupRef.current) {
+ const newFloorItem: Types.FloorItemType = {
+ modelUuid: obj.uuid,
+ modelName: obj.userData.name,
+ modelfileID: obj.userData.modelId,
+ position: [worldPosition.x, worldPosition.y, worldPosition.z],
+ rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
+ isLocked: false,
+ isVisible: true,
+ };
+
+ if (obj.userData.eventData) {
+ const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modelUuid);
+ const productData = useProductStore.getState().getEventByModelUuid(selectedProduct.productId, obj.userData.modelUuid);
+
+ if (eventData) {
+ useEventsStore.getState().updateEvent(obj.userData.modelUuid, {
+ position: [worldPosition.x, worldPosition.y, worldPosition.z],
+ rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
+ });
+ }
+
+ if (productData) {
+ const event = useProductStore
+ .getState()
+ .updateEvent(
+ selectedProduct.productId,
+ obj.userData.modelUuid,
+ {
+ position: [worldPosition.x, worldPosition.y, worldPosition.z],
+ rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
+ }
+ );
+
+ if (event) {
+ updateBackend(
+ selectedProduct.productName,
+ selectedProduct.productId,
+ organization,
+ event
+ );
+ }
+
+ newFloorItem.eventData = eventData;
+ }
+ }
+
+ setFloorItems((prevItems: Types.FloorItems) => {
+ const updatedItems = [...(prevItems || []), newFloorItem];
+ localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
+ return updatedItems;
+ });
+
+ //REST
+
+ // await setFloorItemApi(
+ // organization,
+ // obj.uuid,
+ // obj.userData.name,
+ // [worldPosition.x, worldPosition.y, worldPosition.z],
+ // { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
+ // obj.userData.modelId,
+ // false,
+ // true,
+ // );
+
+ //SOCKET
+
+ const data = {
+ organization,
+ modelUuid: newFloorItem.modelUuid,
+ modelName: newFloorItem.modelName,
+ modelfileID: newFloorItem.modelfileID,
+ position: newFloorItem.position,
+ rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
+ isLocked: false,
+ isVisible: true,
+ socketId: socket.id,
+ };
+
+ socket.emit("v2:model-asset:add", data);
+
+ itemsGroupRef.current.add(obj);
+ }
+ });
+ toast.success("Object moved!");
+
+ itemsData.current = [];
+ clearSelection();
+ };
+
+ const clearSelection = () => {
+ selectionGroup.current.children = [];
+ selectionGroup.current.position.set(0, 0, 0);
+ selectionGroup.current.rotation.set(0, 0, 0);
+ setpastedObjects([]);
+ setDuplicatedObjects([]);
+ setMovedObjects([]);
+ setRotatedObjects([]);
+ setSelectedAssets([]);
+ setKeyEvent("");
+ };
+
+ return (
+
+ );
}
export default MoveControls;
diff --git a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
index 58dab0c..31ba8c9 100644
--- a/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
+++ b/app/src/modules/scene/controls/selectionControls/rotateControls.tsx
@@ -22,7 +22,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
const itemsData = useRef([]);
const email = localStorage.getItem('email')
- const organization = (email!.split("@")[1]).split(".")[0];
+ const organization = (email?.split("@")[1])?.split(".")[0] ?? null;
const updateBackend = (
productName: string,
@@ -214,7 +214,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
- if (event) {
+ if (event && organization) {
updateBackend(
selectedProduct.productName,
selectedProduct.productId,
diff --git a/app/src/modules/scene/controls/transformControls/transformControls.tsx b/app/src/modules/scene/controls/transformControls/transformControls.tsx
new file mode 100644
index 0000000..5311f4f
--- /dev/null
+++ b/app/src/modules/scene/controls/transformControls/transformControls.tsx
@@ -0,0 +1,206 @@
+import { TransformControls } from "@react-three/drei";
+import * as THREE from "three";
+import { useSelectedFloorItem, useObjectPosition, useObjectRotation, useFloorItems, useActiveTool, useSocketStore } from "../../../../store/store";
+import { useThree } from "@react-three/fiber";
+
+import * as Types from '../../../../types/world/worldTypes';
+import { useEffect, useState } from "react";
+import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
+import { useEventsStore } from "../../../../store/simulation/useEventsStore";
+import { useProductStore } from "../../../../store/simulation/useProductStore";
+import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
+import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
+import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
+
+export default function TransformControl() {
+ const state = useThree();
+ const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
+ const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
+ const { setObjectPosition } = useObjectPosition();
+ const { setObjectRotation } = useObjectRotation();
+ const { setFloorItems } = useFloorItems();
+ const { activeTool } = useActiveTool();
+ const { socket } = useSocketStore();
+ const { selectedProduct } = useSelectedProduct();
+
+ const email = localStorage.getItem('email')
+ const organization = (email!.split("@")[1]).split(".")[0];
+
+ const updateBackend = (
+ productName: string,
+ productId: string,
+ organization: string,
+ eventData: EventsSchema
+ ) => {
+ upsertProductOrEventApi({
+ productName: productName,
+ productId: productId,
+ organization: organization,
+ eventDatas: eventData,
+ });
+ };
+
+ function handleObjectChange() {
+ if (selectedFloorItem) {
+ setObjectPosition(selectedFloorItem.position);
+ setObjectRotation({
+ x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x),
+ y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y),
+ z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z),
+ });
+ }
+ }
+
+ function handleMouseUp() {
+ if (selectedFloorItem) {
+ setObjectPosition(selectedFloorItem.position);
+ setObjectRotation({
+ x: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.x),
+ y: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.y),
+ z: THREE.MathUtils.radToDeg(selectedFloorItem.rotation.z),
+ });
+ }
+ setFloorItems((prevItems: Types.FloorItems) => {
+ if (!prevItems) {
+ return
+ }
+ let updatedItem: any = null;
+ const updatedItems = prevItems.map((item) => {
+ if (item.modelUuid === selectedFloorItem?.uuid) {
+ updatedItem = {
+ ...item,
+ position: [selectedFloorItem.position.x, 0, selectedFloorItem.position.z] as [number, number, number],
+ rotation: { x: selectedFloorItem.rotation.x, y: selectedFloorItem.rotation.y, z: selectedFloorItem.rotation.z },
+ };
+ return updatedItem;
+ }
+ return item;
+ });
+ if (updatedItem && selectedFloorItem) {
+ if (updatedItem.eventData) {
+ const eventData = useEventsStore.getState().getEventByModelUuid(updatedItem.modelUuid);
+ const productData = useProductStore.getState().getEventByModelUuid(selectedProduct.productId, updatedItem.modelUuid);
+
+ if (eventData) {
+ useEventsStore.getState().updateEvent(updatedItem.modelUuid, {
+ position: [selectedFloorItem.position.x, 0, selectedFloorItem.position.z],
+ rotation: [selectedFloorItem.rotation.x, selectedFloorItem.rotation.y, selectedFloorItem.rotation.z],
+ });
+ }
+
+ if (productData) {
+ const event = useProductStore
+ .getState()
+ .updateEvent(
+ selectedProduct.productId,
+ updatedItem.modelUuid,
+ {
+ position: [selectedFloorItem.position.x, 0, selectedFloorItem.position.z],
+ rotation: [selectedFloorItem.rotation.x, selectedFloorItem.rotation.y, selectedFloorItem.rotation.z],
+ }
+ );
+
+ if (event) {
+ updateBackend(
+ selectedProduct.productName,
+ selectedProduct.productId,
+ organization,
+ event
+ );
+ }
+
+ updatedItem.eventData = eventData;
+ }
+ }
+
+ setFloorItems((prevItems: Types.FloorItems) => {
+ const updatedItems = [...(prevItems || []), updatedItem];
+ localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
+ return updatedItems;
+ });
+
+ // REST
+
+ // setFloorItemApi(
+ // organization,
+ // updatedItem.modelUuid,
+ // updatedItem.modelName,
+ // updatedItem.modelfileid,
+ // [selectedFloorItem.position.x, 0, selectedFloorItem.position.z,],
+ // { "x": selectedFloorItem.rotation.x, "y": selectedFloorItem.rotation.y, "z": selectedFloorItem.rotation.z },
+ // false,
+ // true,
+ // );
+
+ // SOCKET
+
+ const data = {
+ organization: organization,
+ modelUuid: updatedItem.modelUuid,
+ modelName: updatedItem.modelName,
+ modelfileID: updatedItem.modelfileID,
+ position: [selectedFloorItem.position.x, 0, selectedFloorItem.position.z],
+ rotation: { "x": selectedFloorItem.rotation.x, "y": selectedFloorItem.rotation.y, "z": selectedFloorItem.rotation.z },
+ isLocked: false,
+ isVisible: true,
+ socketId: socket.id
+ }
+
+ socket.emit("v2:model-asset:add", data);
+ }
+ localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
+ return updatedItems;
+ });
+ }
+
+ useEffect(() => {
+ const handleKeyDown = (e: KeyboardEvent) => {
+ const keyCombination = detectModifierKeys(e);
+ if (!selectedFloorItem) return;
+ if (keyCombination === "G") {
+ setTransformMode((prev) => (prev === "translate" ? null : "translate"));
+ }
+ if (keyCombination === "R") {
+ setTransformMode((prev) => (prev === "rotate" ? null : "rotate"));
+ }
+ };
+
+ if (selectedFloorItem) {
+ window.addEventListener("keydown", handleKeyDown);
+ } else {
+ setTransformMode(null);
+ }
+
+ return () => {
+ window.removeEventListener("keydown", handleKeyDown);
+ };
+ }, [selectedFloorItem]);
+
+ useEffect(() => {
+ if (activeTool === "delete") {
+ if (state.controls) {
+ const target = (state.controls as any).getTarget(new THREE.Vector3());
+ (state.controls as any).setTarget(target.x, 0, target.z, true);
+ }
+ setSelectedFloorItem(null);
+ setObjectPosition({ x: undefined, y: undefined, z: undefined });
+ setObjectRotation({ x: undefined, y: undefined, z: undefined });
+ }
+ }, [activeTool]);
+
+ return (
+ <>
+ {(selectedFloorItem && transformMode) &&
+
+ }
+ >
+ );
+}
diff --git a/app/src/modules/visualization/RealTimeVisulization.tsx b/app/src/modules/visualization/RealTimeVisulization.tsx
index 23f2532..bbc996f 100644
--- a/app/src/modules/visualization/RealTimeVisulization.tsx
+++ b/app/src/modules/visualization/RealTimeVisulization.tsx
@@ -187,6 +187,7 @@ const RealTimeVisulization: React.FC = () => {
((set: any) => ({
setMovePoint: (x: any) => set(() => ({ movePoint: x })),
}));
-export const useTransformMode = create
((set: any) => ({
- transformMode: null,
- setTransformMode: (x: any) => set(() => ({ transformMode: x })),
-}));
-
export const useDeletePointOrLine = create((set: any) => ({
deletePointOrLine: false,
setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })),
diff --git a/app/src/store/useUIToggleStore.ts b/app/src/store/useUIToggleStore.ts
index a508b38..9f5f583 100644
--- a/app/src/store/useUIToggleStore.ts
+++ b/app/src/store/useUIToggleStore.ts
@@ -1,13 +1,17 @@
import { create } from "zustand";
interface ToggleState {
- toggleUI: boolean; // State to track UI toggle
- setToggleUI: (value: boolean) => void; // Action to update toggleUI
+ toggleUILeft: boolean;
+ toggleUIRight: boolean;
+ setToggleUI: (value1: boolean, value2: boolean) => void;
}
const useToggleStore = create((set) => ({
- toggleUI: true, // Initial state
- setToggleUI: (value: boolean) => set({ toggleUI: value }), // Update the state
+ toggleUILeft: true,
+ toggleUIRight: false,
+ setToggleUI: (value1: boolean, value2: boolean) => {
+ set({ toggleUILeft: value1, toggleUIRight: value2 });
+ },
}));
export default useToggleStore;
diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss
index 4d321d4..e6b8f10 100644
--- a/app/src/styles/layout/sidebar.scss
+++ b/app/src/styles/layout/sidebar.scss
@@ -1,6 +1,55 @@
@use "../abstracts/variables" as *;
@use "../abstracts/mixins" as *;
+.toggle-sidebar-ui-button {
+ @include flex-center;
+ cursor: pointer;
+ height: 32px;
+ width: 32px;
+ min-height: 32px;
+ min-width: 32px;
+ border-radius: #{$border-radius-large};
+ position: relative;
+
+ .tooltip {
+ top: 6px;
+ right: -168px;
+
+ &::after {
+ left: 0px;
+ bottom: 50%;
+ }
+ }
+
+ &:hover {
+ outline: 1px solid var(--border-color);
+ outline-offset: -1px;
+ background: var(--background-color-solid);
+
+ .tooltip {
+ opacity: 1;
+ transform: translateX(2px);
+ }
+ }
+}
+
+.toggle-sidebar-ui-button.active {
+ background: var(--background-color-accent);
+
+ rect {
+ stroke: var(--icon-default-color-active);
+ }
+
+ circle {
+ fill: var(--icon-default-color-active);
+ }
+
+ &:hover {
+ filter: saturate(0.8);
+ background: var(--background-color-accent);
+ }
+}
+
.sidebar-left-wrapper {
width: 270px;
position: fixed;
@@ -34,15 +83,6 @@
}
.toggle-sidebar-ui-button {
- @include flex-center;
- cursor: pointer;
- height: 32px;
- width: 32px;
- min-height: 32px;
- min-width: 32px;
- border-radius: #{$border-radius-large};
- position: relative;
-
.tooltip {
top: 6px;
right: -168px;
@@ -52,34 +92,6 @@
bottom: 50%;
}
}
-
- &:hover {
- outline: 1px solid var(--border-color);
- outline-offset: -1px;
- background: var(--background-color-solid);
-
- .tooltip {
- opacity: 1;
- transform: translateX(2px);
- }
- }
- }
-
- .active {
- background: var(--background-color-accent);
-
- rect {
- stroke: var(--icon-default-color-active);
- }
-
- circle {
- fill: var(--icon-default-color-active);
- }
-
- &:hover {
- filter: saturate(0.8);
- background: var(--background-color-accent);
- }
}
}
@@ -295,7 +307,7 @@
padding: 10px;
padding-left: 16px;
width: 100%;
- gap: 12px;
+ gap: 8px;
height: 52px;
.options-container {
@@ -318,7 +330,7 @@
.split {
height: 20px;
- width: 2px;
+ min-width: 1px;
background: var(--text-disabled);
}
@@ -1002,8 +1014,7 @@
height: 100%;
width: 1px;
position: absolute;
- color: var(--text-color);
- opacity: 0.4;
+ color: var(--accent-color);
font-size: var(--font-size-regular);
outline-offset: -1px;
top: 0;
@@ -1266,6 +1277,18 @@
}
}
}
+ .toggle-sidebar-ui-button {
+ svg {
+ transform: scaleX(-1);
+ }
+ .tooltip {
+ right: 56px;
+ &::after {
+ left: 100%;
+ bottom: 50%;
+ }
+ }
+ }
}
.assets-container-main {
@@ -1432,7 +1455,11 @@
height: 100%;
gap: 6px;
padding: 2px;
-
+ .no-asset {
+ text-align: center;
+ margin: 12px;
+ width: 100%;
+ }
.assets {
width: 122px;
height: 95px;
@@ -1491,20 +1518,6 @@
}
}
-.skeleton-wrapper {
- display: flex;
-
- .asset-name {
- width: 40%;
- height: 10px;
- }
-
- .asset {
- width: 100%;
- height: 100%;
- }
-}
-
.sidebar-left-wrapper,
.sidebar-right-wrapper {
transition: height 0.2s ease-in-out;
diff --git a/app/src/styles/layout/skeleton.scss b/app/src/styles/layout/skeleton.scss
index 9df0331..9dbc069 100644
--- a/app/src/styles/layout/skeleton.scss
+++ b/app/src/styles/layout/skeleton.scss
@@ -1,61 +1,90 @@
.skeleton-wrapper {
- // max-width: 600px;
- margin: 0 auto;
- width: 100%;
+ margin: 0 auto;
+ width: 100%;
- .skeleton {
- background: var(--background-color-gray);
+ .skeleton {
+ background: var(--background-color-gray);
- border-radius: 8px;
- position: relative;
- overflow: hidden;
+ border-radius: 8px;
+ position: relative;
+ overflow: hidden;
- &::after {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-image: linear-gradient(90deg,
- rgba(255, 255, 255, 0) 0%,
- rgba(255, 255, 255, 0.2) 20%,
- rgba(255, 255, 255, 0.5) 60%,
- rgba(255, 255, 255, 0) 100%);
- transform: translateX(-100%);
- animation: shimmer 1.5s infinite;
- }
+ &::after {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-image: linear-gradient(
+ 90deg,
+ rgba(255, 255, 255, 0) 0%,
+ rgba(255, 255, 255, 0.2) 20%,
+ rgba(255, 255, 255, 0.39) 60%,
+ rgba(255, 255, 255, 0) 100%
+ );
+ transform: translateX(-100%);
+ animation: shimmer 1.5s infinite;
+ }
+ }
+
+ .skeleton-header {
+ margin-bottom: 20px;
+
+ .skeleton-title {
+ width: 100%;
+ height: 25px;
+ margin-bottom: 12px;
}
- .skeleton-header {
- margin-bottom: 20px;
-
- .skeleton-title {
- width: 100%;
- height: 25px;
- margin-bottom: 12px;
- }
-
- .skeleton-subtitle {
- width: 100%;
- height: 4px;
- }
+ .skeleton-subtitle {
+ width: 100%;
+ height: 4px;
}
+ }
- .skeleton-content {
- display: flex;
- flex-direction: column;
- gap: 16px;
+ .skeleton-content {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
- .skeleton-card {
- width: 100%;
- height: 15px;
- }
+ .skeleton-card {
+ width: 100%;
+ height: 15px;
}
+ }
+}
+
+.asset-category-title{
+ width: 60%;
+ height: 12px;
+ margin-bottom: 12px;
+ margin-top: 4px;
+}
+.skeleton-content-asset{
+ display: flex;
+ height: calc(95px * 2 + 10px);
+ gap: 10px;
+ flex-wrap: wrap;
+ .skeleton-content {
+ gap: 8px;
+ flex-direction: column;
+ min-width: 122px;
+ min-height: 95px;
+ .asset-name {
+ width: 40%;
+ height: 10px;
+ }
+ .asset {
+ flex: 1;
+ width: 100%;
+ height: 100%;
+ }
+ }
}
@keyframes shimmer {
- 100% {
- transform: translateX(100%);
- }
-}
\ No newline at end of file
+ 100% {
+ transform: translateX(100%);
+ }
+}
diff --git a/app/src/types/world/worldConstants.ts b/app/src/types/world/worldConstants.ts
index 0374c8a..aaa8466 100644
--- a/app/src/types/world/worldConstants.ts
+++ b/app/src/types/world/worldConstants.ts
@@ -326,7 +326,7 @@ export const lineConfig: LineConfig = {
};
export const wallConfig: WallConfig = {
- defaultColor: "white", // Default color of the walls
+ defaultColor: "#f2f2f2", // Default color of the walls
height: 7, // Height of the walls
width: 0.05, // Width of the walls
};
@@ -334,7 +334,7 @@ export const wallConfig: WallConfig = {
export const floorConfig: FloorConfig = {
defaultColor: "grey", // Default color of the floors
height: 0.1, // Height of the floors
- textureScale: 0.1, // Scale of the floor texture
+ textureScale: 1, // Scale of the floor texture
};
export const roofConfig: RoofConfig = {
@@ -345,7 +345,7 @@ export const roofConfig: RoofConfig = {
export const aisleConfig: AisleConfig = {
width: 0.1, // Width of the aisles
height: 0.01, // Height of the aisles
- defaultColor: 0xffff00, // Default color of the aisles
+ defaultColor: 0xE2AC09, // Default color of the aisles
};
export const zoneConfig: ZoneConfig = {
diff --git a/app/src/types/world/worldTypes.d.ts b/app/src/types/world/worldTypes.d.ts
index c148038..3d6115a 100644
--- a/app/src/types/world/worldTypes.d.ts
+++ b/app/src/types/world/worldTypes.d.ts
@@ -225,7 +225,6 @@ interface AssetConfiguration {
scale?: [number, number, number];
csgscale?: [number, number, number];
csgposition?: [number, number, number];
- positionY?: (intersectionPoint: { point: THREE.Vector3 }) => number;
type?: "Fixed-Move" | "Free-Move";
}
diff --git a/app/src/utils/shortcutkeys/handleShortcutKeys.ts b/app/src/utils/shortcutkeys/handleShortcutKeys.ts
index 2ff5f39..c3346b8 100644
--- a/app/src/utils/shortcutkeys/handleShortcutKeys.ts
+++ b/app/src/utils/shortcutkeys/handleShortcutKeys.ts
@@ -17,7 +17,7 @@ import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
const KeyPressListener: React.FC = () => {
const { activeModule, setActiveModule } = useModuleStore();
const { setActiveSubTool } = useActiveSubTool();
- const { toggleUI, setToggleUI } = useToggleStore();
+ const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore();
const { setToggleThreeD } = useThreeDStore();
const { setToolMode } = useToolMode();
const { setIsPlaying } = usePlayButtonStore();
@@ -26,7 +26,7 @@ const KeyPressListener: React.FC = () => {
const { setAddAction } = useAddAction();
const { setSelectedWallItem } = useSelectedWallItem();
const { setActiveTool } = useActiveTool();
- const { clearSelectedZone} = useSelectedZoneStore();
+ const { clearSelectedZone } = useSelectedZoneStore();
const isTextInput = (element: Element | null): boolean =>
element instanceof HTMLInputElement ||
@@ -42,9 +42,10 @@ const KeyPressListener: React.FC = () => {
};
const module = modules[keyCombination];
if (module && !toggleView) {
+ console.log("hi");
setActiveTool("cursor");
setActiveSubTool("cursor");
- if (module === "market") setToggleUI(false);
+ if (module === "market") setToggleUI(false, false);
setActiveModule(module);
}
};
@@ -69,6 +70,7 @@ const KeyPressListener: React.FC = () => {
const toggleTo2D = toggleView;
setToggleView(!toggleTo2D);
setToggleThreeD(toggleTo2D);
+ setToggleUI(toggleTo2D, toggleTo2D);
if (toggleTo2D) {
setSelectedWallItem(null);
setDeleteTool(false);
@@ -105,6 +107,29 @@ const KeyPressListener: React.FC = () => {
};
+ const handleSidebarShortcuts = (key: string) => {
+ if (activeModule !== "market") {
+ if (key === "Ctrl+\\") {
+ if (toggleUILeft === toggleUIRight) {
+ setToggleUI(!toggleUILeft, !toggleUIRight);
+ }
+ else {
+ setToggleUI(true, true);
+ }
+ return;
+ }
+ if (key === "Ctrl+]") {
+ setToggleUI(toggleUILeft, !toggleUIRight);
+ return;
+ }
+ if (key === "Ctrl+[") {
+ setToggleUI(!toggleUILeft, toggleUIRight);
+ return;
+ }
+ }
+ }
+
+
const handleKeyPress = (event: KeyboardEvent) => {
if (isTextInput(document.activeElement)) return;
@@ -113,11 +138,8 @@ const KeyPressListener: React.FC = () => {
event.preventDefault();
- if (keyCombination === "Ctrl+\\") {
- if (activeModule !== "market") setToggleUI(!toggleUI);
- return;
- }
-
+ // Shortcuts specific for sidebar visibility toggle and others specific to sidebar if added
+ handleSidebarShortcuts(keyCombination);
// Active module selection (builder, simulation, etc.)
handleModuleSwitch(keyCombination);
// Common editing tools: cursor | delete | free-hand
@@ -132,6 +154,7 @@ const KeyPressListener: React.FC = () => {
if (keyCombination === "ESCAPE") {
setActiveTool("cursor");
+ setActiveSubTool("cursor");
setIsPlaying(false);
clearSelectedZone();
}
@@ -146,7 +169,7 @@ const KeyPressListener: React.FC = () => {
window.addEventListener("keydown", handleKeyPress);
return () => window.removeEventListener("keydown", handleKeyPress);
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [activeModule, toggleUI, toggleView]);
+ }, [activeModule, toggleUIRight, toggleUILeft, toggleView]);
return null;
};
diff --git a/app/src/utils/theme.ts b/app/src/utils/theme.ts
index 9395129..541f4ba 100644
--- a/app/src/utils/theme.ts
+++ b/app/src/utils/theme.ts
@@ -4,7 +4,7 @@ export { };
function setTheme() {
const savedTheme: string | null = localStorage.getItem('theme');
const systemPrefersDark: boolean = window.matchMedia('(prefers-color-scheme: dark)').matches;
- const defaultTheme: string = savedTheme || (systemPrefersDark ? 'dark' : 'light');
+ const defaultTheme: string = savedTheme ?? (systemPrefersDark ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', defaultTheme);
localStorage.setItem('theme', defaultTheme);
}