Refactor builder module and remove unused components
- Removed CalculateAreaGroup and computeArea function as they were no longer needed. - Updated Floor2DInstance and Zone2DInstance to calculate area and centroid using new utility functions. - Refactored WallInstances to include Floor2D rendering and improved area display. - Cleaned up imports and ensured consistent formatting across files. - Enhanced performance by memoizing calculations for area and centroid. - Removed deprecated state management for rooms and version history visibility.
This commit is contained in:
@@ -4,7 +4,7 @@ import { useLogger } from "../ui/log/LoggerContext";
|
||||
import { GetLogIcon } from "./getLogIcons";
|
||||
import { CurserLeftIcon, CurserMiddleIcon, CurserRightIcon } from "../icons/LogIcons";
|
||||
import ShortcutHelper from "./shortcutHelper";
|
||||
import useVersionHistoryVisibleStore, { useShortcutStore } from "../../store/builder/store";
|
||||
import { useShortcutStore } from "../../store/builder/store";
|
||||
import { usePlayButtonStore } from "../../store/ui/usePlayButtonStore";
|
||||
import useModuleStore, { useSubModuleStore } from "../../store/ui/useModuleStore";
|
||||
import { mouseActionHelper } from "../../utils/mouseUtils/mouseHelper";
|
||||
@@ -12,123 +12,118 @@ import { useMouseNoteStore } from "../../store/ui/useUIToggleStore";
|
||||
import { useSceneContext } from "../../modules/scene/sceneContext";
|
||||
|
||||
const Footer: React.FC = () => {
|
||||
const { logs, setIsLogListVisible } = useLogger();
|
||||
const lastLog = logs[logs.length - 1] || null;
|
||||
const { logs, setIsLogListVisible } = useLogger();
|
||||
const lastLog = logs[logs.length - 1] || null;
|
||||
|
||||
const { setActiveModule } = useModuleStore();
|
||||
const { setSubModule } = useSubModuleStore();
|
||||
const { setVersionHistoryVisible } = useVersionHistoryVisibleStore();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { showShortcuts, setShowShortcuts } = useShortcutStore();
|
||||
const { versionStore } = useSceneContext();
|
||||
const { selectedVersion } = versionStore();
|
||||
const { setActiveModule } = useModuleStore();
|
||||
const { setSubModule } = useSubModuleStore();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { showShortcuts, setShowShortcuts } = useShortcutStore();
|
||||
const { versionStore } = useSceneContext();
|
||||
const { selectedVersion, setVersionHistoryVisible } = versionStore();
|
||||
|
||||
const { Leftnote, Middlenote, Rightnote } = useMouseNoteStore();
|
||||
const [isOnline, setIsOnline] = useState<boolean>(navigator.onLine);
|
||||
const { Leftnote, Middlenote, Rightnote } = useMouseNoteStore();
|
||||
const [isOnline, setIsOnline] = useState<boolean>(navigator.onLine);
|
||||
|
||||
// -------------------- Online/Offline Handlers --------------------
|
||||
const handleOnline = useCallback(() => {
|
||||
echo.success("You are back Online");
|
||||
setIsOnline(true);
|
||||
}, []);
|
||||
// -------------------- Online/Offline Handlers --------------------
|
||||
const handleOnline = useCallback(() => {
|
||||
echo.success("You are back Online");
|
||||
setIsOnline(true);
|
||||
}, []);
|
||||
|
||||
const handleOffline = useCallback(() => {
|
||||
echo.warn("Changes made now might not be saved");
|
||||
echo.error("You are now Offline.");
|
||||
setIsOnline(false);
|
||||
}, []);
|
||||
const handleOffline = useCallback(() => {
|
||||
echo.warn("Changes made now might not be saved");
|
||||
echo.error("You are now Offline.");
|
||||
setIsOnline(false);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("online", handleOnline);
|
||||
window.addEventListener("offline", handleOffline);
|
||||
return () => {
|
||||
window.removeEventListener("online", handleOnline);
|
||||
window.removeEventListener("offline", handleOffline);
|
||||
};
|
||||
}, [handleOnline, handleOffline]);
|
||||
useEffect(() => {
|
||||
window.addEventListener("online", handleOnline);
|
||||
window.addEventListener("offline", handleOffline);
|
||||
return () => {
|
||||
window.removeEventListener("online", handleOnline);
|
||||
window.removeEventListener("offline", handleOffline);
|
||||
};
|
||||
}, [handleOnline, handleOffline]);
|
||||
|
||||
// -------------------- Mouse Buttons --------------------
|
||||
const mouseButtons = useMemo(
|
||||
() => [
|
||||
{ icon: <CurserLeftIcon />, label: Leftnote || "Pan", mouse: "left" },
|
||||
{ icon: <CurserMiddleIcon />, label: Middlenote || "Scroll Zoom", mouse: "middle" },
|
||||
{ icon: <CurserRightIcon />, label: Rightnote || "Orbit / Cancel action", mouse: "right" },
|
||||
],
|
||||
[Leftnote, Middlenote, Rightnote]
|
||||
);
|
||||
// -------------------- Mouse Buttons --------------------
|
||||
const mouseButtons = useMemo(
|
||||
() => [
|
||||
{ icon: <CurserLeftIcon />, label: Leftnote || "Pan", mouse: "left" },
|
||||
{ icon: <CurserMiddleIcon />, label: Middlenote || "Scroll Zoom", mouse: "middle" },
|
||||
{ icon: <CurserRightIcon />, label: Rightnote || "Orbit / Cancel action", mouse: "right" },
|
||||
],
|
||||
[Leftnote, Middlenote, Rightnote]
|
||||
);
|
||||
|
||||
// -------------------- Mouse Helper --------------------
|
||||
useEffect(() => {
|
||||
const cleanup = mouseActionHelper();
|
||||
return () => cleanup();
|
||||
}, []);
|
||||
// -------------------- Mouse Helper --------------------
|
||||
useEffect(() => {
|
||||
const cleanup = mouseActionHelper();
|
||||
return () => cleanup();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="footer-container">
|
||||
<div className="footer-wrapper">
|
||||
{/* Mouse Button Info */}
|
||||
<div className="selection-wrapper">
|
||||
{mouseButtons.map(({ icon, label, mouse }) => (
|
||||
<div className="selector-wrapper" key={mouse}>
|
||||
<div className="icon">{icon}</div>
|
||||
<div className="selector">{label}</div>
|
||||
return (
|
||||
<div className="footer-container">
|
||||
<div className="footer-wrapper">
|
||||
{/* Mouse Button Info */}
|
||||
<div className="selection-wrapper">
|
||||
{mouseButtons.map(({ icon, label, mouse }) => (
|
||||
<div className="selector-wrapper" key={mouse}>
|
||||
<div className="icon">{icon}</div>
|
||||
<div className="selector">{label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Logs and Version */}
|
||||
<div className="logs-wrapper">
|
||||
<div className="bg-dummy left-top" />
|
||||
<div className="bg-dummy right-bottom" />
|
||||
|
||||
<div className="log-container">
|
||||
<button id="log-details-buttton" className={`logs-detail ${lastLog?.type ?? ""}`} onClick={() => setIsLogListVisible(true)}>
|
||||
{lastLog ? (
|
||||
<>
|
||||
<span className="log-icon">{GetLogIcon(lastLog.type)}</span>
|
||||
<span className="log-message">{lastLog.message}</span>
|
||||
</>
|
||||
) : (
|
||||
"There are no logs to display at the moment."
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="version"
|
||||
onClick={() => {
|
||||
setVersionHistoryVisible(true);
|
||||
setSubModule("properties");
|
||||
setActiveModule("builder");
|
||||
}}
|
||||
>
|
||||
{selectedVersion?.version ?? "v 0.0.0"}
|
||||
<div className="icon">
|
||||
<HelpIcon />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={`wifi-connection ${isOnline ? "connected" : "disconnected"}`}>
|
||||
<div className="icon">
|
||||
<WifiIcon />
|
||||
</div>
|
||||
<div className="tooltip">{isOnline ? "Online" : "Offline"}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Shortcut Helper */}
|
||||
{!isPlaying && showShortcuts && (
|
||||
<div className="shortcut-helper-overlay visible">
|
||||
<ShortcutHelper setShowShortcuts={setShowShortcuts} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Logs and Version */}
|
||||
<div className="logs-wrapper">
|
||||
<div className="bg-dummy left-top" />
|
||||
<div className="bg-dummy right-bottom" />
|
||||
|
||||
<div className="log-container">
|
||||
<button
|
||||
id="log-details-buttton"
|
||||
className={`logs-detail ${lastLog?.type ?? ""}`}
|
||||
onClick={() => setIsLogListVisible(true)}
|
||||
>
|
||||
{lastLog ? (
|
||||
<>
|
||||
<span className="log-icon">{GetLogIcon(lastLog.type)}</span>
|
||||
<span className="log-message">{lastLog.message}</span>
|
||||
</>
|
||||
) : (
|
||||
"There are no logs to display at the moment."
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="version"
|
||||
onClick={() => {
|
||||
setVersionHistoryVisible(true);
|
||||
setSubModule("properties");
|
||||
setActiveModule("builder");
|
||||
}}
|
||||
>
|
||||
{selectedVersion?.version ?? "v 0.0.0"}
|
||||
<div className="icon">
|
||||
<HelpIcon />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={`wifi-connection ${isOnline ? "connected" : "disconnected"}`}>
|
||||
<div className="icon">
|
||||
<WifiIcon />
|
||||
</div>
|
||||
<div className="tooltip">{isOnline ? "Online" : "Offline"}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Shortcut Helper */}
|
||||
{!isPlaying && showShortcuts && (
|
||||
<div className="shortcut-helper-overlay visible">
|
||||
<ShortcutHelper setShowShortcuts={setShowShortcuts} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Header from "./Header";
|
||||
import useModuleStore, { useSubModuleStore } from "../../../store/ui/useModuleStore";
|
||||
import { AnalysisIcon, FilePackageIcon, MechanicsIcon, PropertiesIcon, SimulationIcon, } from "../../icons/SimulationIcons";
|
||||
import { AnalysisIcon, FilePackageIcon, MechanicsIcon, PropertiesIcon, SimulationIcon } from "../../icons/SimulationIcons";
|
||||
import { useToggleStore } from "../../../store/ui/useUIToggleStore";
|
||||
import Visualization from "./visualization/Visualization";
|
||||
import Analysis from "./analysis/Analysis";
|
||||
import Simulations from "./simulation/Simulations";
|
||||
import useVersionHistoryVisibleStore, { useIsComparing, useToolMode } from "../../../store/builder/store";
|
||||
import { useSelectedEventData, useSelectedEventSphere, } from "../../../store/simulation/useSimulationStore";
|
||||
import { useIsComparing, useToolMode } from "../../../store/builder/store";
|
||||
import { useSelectedEventData, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
|
||||
import { useBuilderStore } from "../../../store/builder/useBuilderStore";
|
||||
import GlobalProperties from "./properties/GlobalProperties";
|
||||
import AssetProperties from "./properties/AssetProperties";
|
||||
@@ -22,6 +22,7 @@ import SelectedFloorProperties from "./properties/SelectedFloorProperties";
|
||||
import SelectedDecalProperties from "./properties/SelectedDecalProperties";
|
||||
import SelectedAisleProperties from "./properties/SelectedAisleProperties";
|
||||
import ResourceManagement from "./resourceManagement/ResourceManagement";
|
||||
import { useSceneContext } from "../../../modules/scene/sceneContext";
|
||||
|
||||
type DisplayComponent =
|
||||
| "versionHistory"
|
||||
@@ -51,7 +52,8 @@ const SideBarRight: React.FC = () => {
|
||||
const { selectedWall, selectedFloor, selectedAisle, selectedFloorAsset } = useBuilderStore();
|
||||
const { selectedEventData } = useSelectedEventData();
|
||||
const { selectedEventSphere } = useSelectedEventSphere();
|
||||
const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore();
|
||||
const { versionStore } = useSceneContext();
|
||||
const { viewVersionHistory, setVersionHistoryVisible } = versionStore();
|
||||
const { isComparing } = useIsComparing();
|
||||
|
||||
const [displayComponent, setDisplayComponent] = useState<DisplayComponent>("none");
|
||||
@@ -207,8 +209,7 @@ const SideBarRight: React.FC = () => {
|
||||
<>
|
||||
<button
|
||||
id="sidebar-action-list-properties"
|
||||
className={`sidebar-action-list ${subModule === "properties" ? "active" : ""
|
||||
}`}
|
||||
className={`sidebar-action-list ${subModule === "properties" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setSubModule("properties");
|
||||
setVersionHistoryVisible(false);
|
||||
@@ -224,8 +225,7 @@ const SideBarRight: React.FC = () => {
|
||||
<>
|
||||
<button
|
||||
id="sidebar-action-list-simulation"
|
||||
className={`sidebar-action-list ${subModule === "simulations" ? "active" : ""
|
||||
}`}
|
||||
className={`sidebar-action-list ${subModule === "simulations" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setSubModule("simulations");
|
||||
setVersionHistoryVisible(false);
|
||||
@@ -236,8 +236,7 @@ const SideBarRight: React.FC = () => {
|
||||
</button>
|
||||
<button
|
||||
id="sidebar-action-list-mechanics"
|
||||
className={`sidebar-action-list ${subModule === "mechanics" ? "active" : ""
|
||||
}`}
|
||||
className={`sidebar-action-list ${subModule === "mechanics" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setSubModule("mechanics");
|
||||
setVersionHistoryVisible(false);
|
||||
@@ -248,8 +247,7 @@ const SideBarRight: React.FC = () => {
|
||||
</button>
|
||||
<button
|
||||
id="sidebar-action-list-analysis"
|
||||
className={`sidebar-action-list ${subModule === "analysis" ? "active" : ""
|
||||
}`}
|
||||
className={`sidebar-action-list ${subModule === "analysis" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setSubModule("analysis");
|
||||
setVersionHistoryVisible(false);
|
||||
@@ -261,23 +259,19 @@ const SideBarRight: React.FC = () => {
|
||||
</>
|
||||
)}
|
||||
|
||||
{(activeModule === "builder" ||
|
||||
activeModule === "simulation") && (
|
||||
<button
|
||||
id="sidebar-action-list-properties"
|
||||
className={`sidebar-action-list ${subModule === "resourceManagement" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setSubModule("resourceManagement");
|
||||
setVersionHistoryVisible(false);
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">Resource Management</div>
|
||||
<FilePackageIcon
|
||||
isActive={subModule === "resourceManagement"}
|
||||
/>
|
||||
</button>
|
||||
)}
|
||||
{(activeModule === "builder" || activeModule === "simulation") && (
|
||||
<button
|
||||
id="sidebar-action-list-properties"
|
||||
className={`sidebar-action-list ${subModule === "resourceManagement" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setSubModule("resourceManagement");
|
||||
setVersionHistoryVisible(false);
|
||||
}}
|
||||
>
|
||||
<div className="tooltip">Resource Management</div>
|
||||
<FilePackageIcon isActive={subModule === "resourceManagement"} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import { useParams } from "react-router-dom";
|
||||
import { AddIcon, ArrowIcon, CloseIcon, KebabIcon, LocationIcon } from "../../../icons/ExportCommonIcons";
|
||||
import { useSubModuleStore } from "../../../../store/ui/useModuleStore";
|
||||
import { useSceneContext } from "../../../../modules/scene/sceneContext";
|
||||
import useVersionHistoryVisibleStore from "../../../../store/builder/store";
|
||||
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||
|
||||
import { getVersionDataApi } from "../../../../services/factoryBuilder/versionControl/getVersionDataApi";
|
||||
@@ -10,8 +9,7 @@ import { getVersionDataApi } from "../../../../services/factoryBuilder/versionCo
|
||||
const VersionHistory = () => {
|
||||
const { setSubModule } = useSubModuleStore();
|
||||
const { versionStore } = useSceneContext();
|
||||
const { setVersionHistoryVisible } = useVersionHistoryVisibleStore();
|
||||
const { versionHistory, setCreateNewVersion, selectedVersion, setSelectedVersion } = versionStore();
|
||||
const { versionHistory, setCreateNewVersion, selectedVersion, setSelectedVersion, setVersionHistoryVisible } = versionStore();
|
||||
const { projectId } = useParams();
|
||||
|
||||
const addNewVersion = () => {
|
||||
@@ -21,16 +19,16 @@ const VersionHistory = () => {
|
||||
const handleSelectVersion = (version: Version) => {
|
||||
if (!projectId) return;
|
||||
|
||||
getVersionDataApi(projectId, version.versionId).then((versionData) => {
|
||||
setSelectedVersion(version);
|
||||
}).catch((err) => {
|
||||
echo.error(err);
|
||||
})
|
||||
getVersionDataApi(projectId, version.versionId)
|
||||
.then((versionData) => {
|
||||
setSelectedVersion(version);
|
||||
})
|
||||
.catch((err) => {
|
||||
echo.error(err);
|
||||
});
|
||||
};
|
||||
|
||||
const handleVersionNameChange = (newName: string, versionId: string) => {
|
||||
|
||||
};
|
||||
const handleVersionNameChange = (newName: string, versionId: string) => {};
|
||||
|
||||
return (
|
||||
<div className="version-history-container">
|
||||
@@ -38,11 +36,7 @@ const VersionHistory = () => {
|
||||
<div className="version-history-header">
|
||||
<div className="version-history-title">Version History</div>
|
||||
<div className="version-history-icons">
|
||||
<button
|
||||
id="add-version"
|
||||
className="icon add-icon"
|
||||
onClick={addNewVersion}
|
||||
>
|
||||
<button id="add-version" className="icon add-icon" onClick={addNewVersion}>
|
||||
<AddIcon />
|
||||
</button>
|
||||
<div id="version-kebab" className="icon kebab-icon">
|
||||
@@ -64,9 +58,7 @@ const VersionHistory = () => {
|
||||
{/* Shortcut Info */}
|
||||
<div className="version-history-shortcut-info">
|
||||
<div className="info-icon">i</div>
|
||||
<div className="shortcut-text">
|
||||
Press Ctrl + Alt + S to add to version history while editing
|
||||
</div>
|
||||
<div className="shortcut-text">Press Ctrl + Alt + S to add to version history while editing</div>
|
||||
</div>
|
||||
|
||||
{/* Current Version Display */}
|
||||
@@ -76,12 +68,8 @@ const VersionHistory = () => {
|
||||
<LocationIcon />
|
||||
</div>
|
||||
<div className="location-details">
|
||||
<div className="current-version">
|
||||
Current Version ({selectedVersion.version})
|
||||
</div>
|
||||
<div className="saved-history-count">
|
||||
{versionHistory.length} Saved History
|
||||
</div>
|
||||
<div className="current-version">Current Version ({selectedVersion.version})</div>
|
||||
<div className="saved-history-count">{versionHistory.length} Saved History</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -93,16 +81,8 @@ const VersionHistory = () => {
|
||||
) : (
|
||||
versionHistory.map((version) => {
|
||||
const key = `version-${version.versionId}`;
|
||||
return (
|
||||
<VersionHistoryItem
|
||||
key={key}
|
||||
version={version}
|
||||
onSelect={handleSelectVersion}
|
||||
onRename={handleVersionNameChange}
|
||||
/>
|
||||
);
|
||||
return <VersionHistoryItem key={key} version={version} onSelect={handleSelectVersion} onRename={handleVersionNameChange} />;
|
||||
})
|
||||
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -119,22 +99,14 @@ type VersionHistoryItemProps = {
|
||||
|
||||
const VersionHistoryItem: React.FC<VersionHistoryItemProps> = ({ version, onSelect, onRename }) => {
|
||||
return (
|
||||
<button
|
||||
className="saved-version"
|
||||
>
|
||||
<div
|
||||
className="version-name"
|
||||
onClick={() => onSelect(version)}
|
||||
>
|
||||
<button className="saved-version">
|
||||
<div className="version-name" onClick={() => onSelect(version)}>
|
||||
v {version.version}
|
||||
</div>
|
||||
<div className="version-details">
|
||||
<div className="details">
|
||||
<span className="timestamp">
|
||||
<RenameInput
|
||||
value={version.versionName ? version.versionName : version.timeStamp}
|
||||
onRename={(newName) => onRename(newName, version.versionId)}
|
||||
/>
|
||||
<RenameInput value={version.versionName ? version.versionName : version.timeStamp} onRename={(newName) => onRename(newName, version.versionId)} />
|
||||
</span>
|
||||
<span className="saved-by">
|
||||
<div className="user-profile">{version.createdBy[0]}</div>
|
||||
|
||||
@@ -1,104 +1,84 @@
|
||||
import React from "react";
|
||||
import useModuleStore from "../../store/ui/useModuleStore";
|
||||
import {
|
||||
BuilderIcon,
|
||||
CartIcon,
|
||||
SimulationIcon,
|
||||
VisualizationIcon,
|
||||
} from "../icons/ExportModuleIcons";
|
||||
import {useToggleStore} from "../../store/ui/useUIToggleStore";
|
||||
import useVersionStore from "../../store/builder/store";
|
||||
import { BuilderIcon, CartIcon, SimulationIcon, VisualizationIcon } from "../icons/ExportModuleIcons";
|
||||
import { useToggleStore } from "../../store/ui/useUIToggleStore";
|
||||
import { useSceneContext } from "../../modules/scene/sceneContext";
|
||||
|
||||
const ModuleToggle: React.FC = () => {
|
||||
const { activeModule, setActiveModule } = useModuleStore();
|
||||
const { setToggleUI } = useToggleStore();
|
||||
const { setVersionHistoryVisible } = useVersionStore();
|
||||
const { activeModule, setActiveModule } = useModuleStore();
|
||||
const { setToggleUI } = useToggleStore();
|
||||
const { versionStore } = useSceneContext();
|
||||
const { setVersionHistoryVisible } = versionStore();
|
||||
|
||||
return (
|
||||
<div className="module-toggle-container">
|
||||
<button
|
||||
id={"builder"}
|
||||
className={`module-list ${activeModule === "builder" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setActiveModule("builder");
|
||||
setVersionHistoryVisible(false);
|
||||
setToggleUI(
|
||||
localStorage.getItem("navBarUiLeft")
|
||||
? localStorage.getItem("navBarUiLeft") === "true"
|
||||
: true,
|
||||
localStorage.getItem("navBarUiRight")
|
||||
? localStorage.getItem("navBarUiRight") === "true"
|
||||
: true
|
||||
);
|
||||
}}
|
||||
>
|
||||
<div className="icon">
|
||||
<BuilderIcon isActive={activeModule === "builder"} />
|
||||
return (
|
||||
<div className="module-toggle-container">
|
||||
<button
|
||||
id={"builder"}
|
||||
className={`module-list ${activeModule === "builder" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setActiveModule("builder");
|
||||
setVersionHistoryVisible(false);
|
||||
setToggleUI(
|
||||
localStorage.getItem("navBarUiLeft") ? localStorage.getItem("navBarUiLeft") === "true" : true,
|
||||
localStorage.getItem("navBarUiRight") ? localStorage.getItem("navBarUiRight") === "true" : true
|
||||
);
|
||||
}}
|
||||
>
|
||||
<div className="icon">
|
||||
<BuilderIcon isActive={activeModule === "builder"} />
|
||||
</div>
|
||||
<div className="module">Builder</div>
|
||||
</button>
|
||||
<button
|
||||
id={"simulation"}
|
||||
className={`module-list ${activeModule === "simulation" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setActiveModule("simulation");
|
||||
setVersionHistoryVisible(false);
|
||||
setToggleUI(
|
||||
localStorage.getItem("navBarUiLeft") ? localStorage.getItem("navBarUiLeft") === "true" : true,
|
||||
localStorage.getItem("navBarUiRight") ? localStorage.getItem("navBarUiRight") === "true" : true
|
||||
);
|
||||
}}
|
||||
>
|
||||
<div className="icon">
|
||||
<SimulationIcon isActive={activeModule === "simulation"} />
|
||||
</div>
|
||||
<div className="module">Simulation</div>
|
||||
</button>
|
||||
<button
|
||||
id={"visualization"}
|
||||
className={`module-list ${activeModule === "visualization" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setActiveModule("visualization");
|
||||
setVersionHistoryVisible(false);
|
||||
setToggleUI(
|
||||
localStorage.getItem("navBarUiLeft") ? localStorage.getItem("navBarUiLeft") === "true" : true,
|
||||
localStorage.getItem("navBarUiRight") ? localStorage.getItem("navBarUiRight") === "true" : true
|
||||
);
|
||||
}}
|
||||
>
|
||||
<div className="icon">
|
||||
<VisualizationIcon isActive={activeModule === "visualization"} />
|
||||
</div>
|
||||
<div className="module">Visualization</div>
|
||||
</button>
|
||||
<button
|
||||
id={"market"}
|
||||
className={`module-list ${activeModule === "market" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setActiveModule("market");
|
||||
setVersionHistoryVisible(false);
|
||||
setToggleUI(false, false);
|
||||
}}
|
||||
>
|
||||
<div className="icon">
|
||||
<CartIcon isActive={activeModule === "market"} />
|
||||
</div>
|
||||
<div className="module">Market Place</div>
|
||||
</button>
|
||||
</div>
|
||||
<div className="module">Builder</div>
|
||||
</button>
|
||||
<button
|
||||
id={"simulation"}
|
||||
className={`module-list ${
|
||||
activeModule === "simulation" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveModule("simulation");
|
||||
setVersionHistoryVisible(false);
|
||||
setToggleUI(
|
||||
localStorage.getItem("navBarUiLeft")
|
||||
? localStorage.getItem("navBarUiLeft") === "true"
|
||||
: true,
|
||||
localStorage.getItem("navBarUiRight")
|
||||
? localStorage.getItem("navBarUiRight") === "true"
|
||||
: true
|
||||
);
|
||||
}}
|
||||
>
|
||||
<div className="icon">
|
||||
<SimulationIcon isActive={activeModule === "simulation"} />
|
||||
</div>
|
||||
<div className="module">Simulation</div>
|
||||
</button>
|
||||
<button
|
||||
id={"visualization"}
|
||||
className={`module-list ${
|
||||
activeModule === "visualization" ? "active" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
setActiveModule("visualization");
|
||||
setVersionHistoryVisible(false);
|
||||
setToggleUI(
|
||||
localStorage.getItem("navBarUiLeft")
|
||||
? localStorage.getItem("navBarUiLeft") === "true"
|
||||
: true,
|
||||
localStorage.getItem("navBarUiRight")
|
||||
? localStorage.getItem("navBarUiRight") === "true"
|
||||
: true
|
||||
);
|
||||
}}
|
||||
>
|
||||
<div className="icon">
|
||||
<VisualizationIcon isActive={activeModule === "visualization"} />
|
||||
</div>
|
||||
<div className="module">Visualization</div>
|
||||
</button>
|
||||
<button
|
||||
id={"market"}
|
||||
className={`module-list ${activeModule === "market" ? "active" : ""}`}
|
||||
onClick={() => {
|
||||
setActiveModule("market");
|
||||
setVersionHistoryVisible(false);
|
||||
setToggleUI(false, false);
|
||||
}}
|
||||
>
|
||||
<div className="icon">
|
||||
<CartIcon isActive={activeModule === "market"} />
|
||||
</div>
|
||||
<div className="module">Market Place</div>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
export default ModuleToggle;
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { ArrowIcon } from "../../icons/ExportCommonIcons";
|
||||
import { toggleTheme } from "../../../utils/theme";
|
||||
import useVersionHistoryVisibleStore, { useShortcutStore } from "../../../store/builder/store";
|
||||
import { useShortcutStore } from "../../../store/builder/store";
|
||||
import useModuleStore, { useSubModuleStore } from "../../../store/ui/useModuleStore";
|
||||
import { useSceneContext } from "../../../modules/scene/sceneContext";
|
||||
|
||||
@@ -25,8 +25,7 @@ const MenuBar: React.FC<MenuBarProps> = ({ setOpenMenu }) => {
|
||||
const [selectedItems, setSelectedItems] = useState<Record<string, boolean>>({});
|
||||
|
||||
const { versionStore } = useSceneContext();
|
||||
const { setCreateNewVersion } = versionStore();
|
||||
const { setVersionHistoryVisible } = useVersionHistoryVisibleStore();
|
||||
const { setCreateNewVersion, setVersionHistoryVisible } = versionStore();
|
||||
const { setActiveModule } = useModuleStore();
|
||||
const { setSubModule } = useSubModuleStore();
|
||||
const { showShortcuts, setShowShortcuts } = useShortcutStore();
|
||||
@@ -79,7 +78,16 @@ const MenuBar: React.FC<MenuBarProps> = ({ setOpenMenu }) => {
|
||||
{ label: "Import" },
|
||||
{ label: "Close File" },
|
||||
],
|
||||
Edit: [{ label: "Undo", shortcut: "Ctrl + Z" }, { label: "Redo", shortcut: "Ctrl + Shift + Z" }, { label: "Undo History" }, { label: "Redo History" }, { label: "Find", shortcut: "Ctrl + F" }, { label: "Delete" }, { label: "Select by..." }, { label: "Keymap" }],
|
||||
Edit: [
|
||||
{ label: "Undo", shortcut: "Ctrl + Z" },
|
||||
{ label: "Redo", shortcut: "Ctrl + Shift + Z" },
|
||||
{ label: "Undo History" },
|
||||
{ label: "Redo History" },
|
||||
{ label: "Find", shortcut: "Ctrl + F" },
|
||||
{ label: "Delete" },
|
||||
{ label: "Select by..." },
|
||||
{ label: "Keymap" },
|
||||
],
|
||||
View: [
|
||||
{ label: "Grid" },
|
||||
{
|
||||
@@ -172,7 +180,13 @@ const MenuBar: React.FC<MenuBarProps> = ({ setOpenMenu }) => {
|
||||
<div className="dropdown-menu">
|
||||
{items.map((item) =>
|
||||
item.submenu ? (
|
||||
<button id={item.label} key={item.label} className="menu-item-container" onMouseEnter={() => setActiveSubMenu(item.label)} onMouseLeave={() => setActiveSubMenu(null)}>
|
||||
<button
|
||||
id={item.label}
|
||||
key={item.label}
|
||||
className="menu-item-container"
|
||||
onMouseEnter={() => setActiveSubMenu(item.label)}
|
||||
onMouseLeave={() => setActiveSubMenu(null)}
|
||||
>
|
||||
<div className="menu-item">
|
||||
<span>{item.label}</span>
|
||||
<span className="dropdown-icon">
|
||||
|
||||
@@ -17,7 +17,6 @@ import SocketResponses from "../collaboration/socket/socketResponses.dev";
|
||||
import Ground from "../scene/environment/ground";
|
||||
import MeasurementTool from "../scene/tools/measurementTool";
|
||||
import NavMesh from "../simulation/vehicle/navMesh/navMesh";
|
||||
import CalculateAreaGroup from "./groups/calculateAreaGroup";
|
||||
import LayoutImage from "./layout/layoutImage";
|
||||
import AssetsGroup from "./asset/assetsGroup";
|
||||
import DxfFile from "./dfx/LoadBlueprint";
|
||||
@@ -51,8 +50,8 @@ export default function Builder() {
|
||||
if (!toggleView) {
|
||||
setHoveredLine(null);
|
||||
setHoveredPoint(null);
|
||||
state.gl.domElement.style.cursor = 'default';
|
||||
setToolMode('cursor');
|
||||
state.gl.domElement.style.cursor = "default";
|
||||
setToolMode("cursor");
|
||||
}
|
||||
}, [toggleView]);
|
||||
|
||||
@@ -65,14 +64,14 @@ export default function Builder() {
|
||||
setShadows(data.shadowVisibility);
|
||||
setRenderDistance(data.renderDistance);
|
||||
setLimitDistance(data.limitDistance);
|
||||
})
|
||||
});
|
||||
}, [projectId]);
|
||||
|
||||
useFrame(() => {
|
||||
if (csgRef.current && selectedWallAsset) {
|
||||
csgRef.current.update();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -82,13 +81,11 @@ export default function Builder() {
|
||||
|
||||
<AssetsGroup plane={plane} />
|
||||
|
||||
<mesh name='Walls-And-WallAssets-Group'>
|
||||
<mesh name="Walls-And-WallAssets-Group">
|
||||
<Geometry ref={csgRef} useGroups>
|
||||
|
||||
<WallGroup />
|
||||
|
||||
<WallAssetGroup />
|
||||
|
||||
</Geometry>
|
||||
</mesh>
|
||||
|
||||
@@ -102,8 +99,6 @@ export default function Builder() {
|
||||
|
||||
<MeasurementTool />
|
||||
|
||||
<CalculateAreaGroup />
|
||||
|
||||
<NavMesh />
|
||||
|
||||
<DxfFile />
|
||||
|
||||
@@ -1,50 +1,61 @@
|
||||
import { useMemo } from 'react';
|
||||
import { DoubleSide, Shape, Vector2 } from 'three';
|
||||
import { Extrude } from '@react-three/drei';
|
||||
import * as Constants from '../../../../../types/world/worldConstants';
|
||||
import { useMemo } from "react";
|
||||
import { DoubleSide, Shape, Vector2 } from "three";
|
||||
import { Extrude, Html } from "@react-three/drei";
|
||||
import * as Constants from "../../../../../types/world/worldConstants";
|
||||
import getCenteroidPoint from "../../../functions/getCenteroid";
|
||||
import getArea from "../../../functions/getArea";
|
||||
|
||||
function Floor2DInstance({ floor }: { readonly floor: Floor }) {
|
||||
const savedTheme: string | null = localStorage.getItem("theme");
|
||||
|
||||
const points2D = useMemo(() => {
|
||||
return floor.points.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2))));
|
||||
}, [floor]);
|
||||
|
||||
const shape = useMemo(() => {
|
||||
const shape = new Shape();
|
||||
const points = floor.points.map(p => new Vector2(p.position[0], p.position[2]));
|
||||
if (points.length < 3) return null;
|
||||
shape.moveTo(points[0].x, points[0].y);
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
shape.lineTo(points[i].x, points[i].y);
|
||||
shape.moveTo(points2D[0].x, points2D[0].y);
|
||||
for (let i = 1; i < points2D.length; i++) {
|
||||
shape.lineTo(points2D[i].x, points2D[i].y);
|
||||
}
|
||||
shape.lineTo(points2D[0].x, points2D[0].y);
|
||||
return shape;
|
||||
}, [floor]);
|
||||
}, [points2D]);
|
||||
|
||||
const area = useMemo(() => getArea(points2D), [points2D]);
|
||||
|
||||
const centroid: [number, number, number] = useMemo(() => {
|
||||
const center = getCenteroidPoint(points2D);
|
||||
if (!center) return [0, Constants.floorConfig.height + 0.01, 0];
|
||||
|
||||
return [center.x, Constants.floorConfig.height + 0.01, center.y] as [number, number, number];
|
||||
}, [points2D]);
|
||||
|
||||
if (!shape) return null;
|
||||
|
||||
const formattedArea = `${area.toFixed(2)} m²`;
|
||||
|
||||
return (
|
||||
<mesh
|
||||
castShadow
|
||||
receiveShadow
|
||||
name={`Floor-2D-${floor.floorUuid}`}
|
||||
rotation={[Math.PI / 2, 0, 0]}
|
||||
position={[0, 0, 0]}
|
||||
userData={floor}
|
||||
>
|
||||
<Extrude
|
||||
name={`Floor-${floor.floorUuid}`}
|
||||
args={[shape, {
|
||||
depth: Constants.floorConfig.height,
|
||||
}]}
|
||||
userData={floor}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
color={savedTheme === "dark" ? "#808080" : "#808080"}
|
||||
side={DoubleSide}
|
||||
transparent
|
||||
opacity={0.4}
|
||||
depthWrite={false}
|
||||
/>
|
||||
</Extrude>
|
||||
</mesh>
|
||||
<>
|
||||
<mesh castShadow receiveShadow name={`Floor-2D-${floor.floorUuid}`} rotation={[Math.PI / 2, 0, 0]} position={[0, 0, 0]} userData={floor}>
|
||||
<Extrude name={`Floor-${floor.floorUuid}`} args={[shape, { depth: Constants.floorConfig.height }]} userData={floor}>
|
||||
<meshBasicMaterial
|
||||
color={savedTheme === "dark" ? Constants.lineConfig.floorColor : Constants.lineConfig.floorColor}
|
||||
side={DoubleSide}
|
||||
transparent
|
||||
opacity={0.4}
|
||||
depthWrite={false}
|
||||
/>
|
||||
</Extrude>
|
||||
</mesh>
|
||||
|
||||
<Html key={floor.floorUuid} position={centroid} wrapperClass="distance-text-wrapper" className="distance-text" zIndexRange={[1, 0]} prepend center sprite>
|
||||
<div className="distance area">
|
||||
{floor.floorName} ({formattedArea})
|
||||
</div>
|
||||
</Html>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default Floor2DInstance;
|
||||
export default Floor2DInstance;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { Vector3 } from 'three';
|
||||
import { Html } from '@react-three/drei';
|
||||
import { useSceneContext } from '../../../scene/sceneContext';
|
||||
import { useToggleView, useToolMode } from '../../../../store/builder/store';
|
||||
import Line from '../../line/line';
|
||||
import Point from '../../point/point';
|
||||
import FloorInstance from './Instance/floorInstance';
|
||||
import Floor2DInstance from './Instance/floor2DInstance';
|
||||
import useModuleStore from '../../../../store/ui/useModuleStore';
|
||||
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
|
||||
import React, { useEffect, useMemo } from "react";
|
||||
import { Vector3 } from "three";
|
||||
import { Html } from "@react-three/drei";
|
||||
import { useSceneContext } from "../../../scene/sceneContext";
|
||||
import { useToggleView, useToolMode } from "../../../../store/builder/store";
|
||||
import Line from "../../line/line";
|
||||
import Point from "../../point/point";
|
||||
import FloorInstance from "./Instance/floorInstance";
|
||||
import Floor2DInstance from "./Instance/floor2DInstance";
|
||||
import useModuleStore from "../../../../store/ui/useModuleStore";
|
||||
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
|
||||
|
||||
function FloorInstances() {
|
||||
const { floorStore } = useSceneContext();
|
||||
@@ -20,11 +20,11 @@ function FloorInstances() {
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('floors: ', floors);
|
||||
}, [floors])
|
||||
}, [floors]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!toggleView && activeModule === 'builder') {
|
||||
if (toolMode !== 'cursor') {
|
||||
if (!toggleView && activeModule === "builder") {
|
||||
if (toolMode !== "cursor") {
|
||||
if (selectedFloor) setSelectedFloor(null);
|
||||
}
|
||||
} else if (selectedFloor) {
|
||||
@@ -36,8 +36,8 @@ function FloorInstances() {
|
||||
const points: Point[] = [];
|
||||
const seenUuids = new Set<string>();
|
||||
|
||||
floors.forEach(floor => {
|
||||
floor.points.forEach(point => {
|
||||
floors.forEach((floor) => {
|
||||
floor.points.forEach((point) => {
|
||||
if (!seenUuids.has(point.pointUuid)) {
|
||||
seenUuids.add(point.pointUuid);
|
||||
points.push(point);
|
||||
@@ -65,7 +65,7 @@ function FloorInstances() {
|
||||
lines.push({
|
||||
start: current,
|
||||
end: next,
|
||||
key: lineKey
|
||||
key: lineKey,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -76,9 +76,8 @@ function FloorInstances() {
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
{!toggleView && floors.length > 0 && (
|
||||
<mesh name='Floors-Group'>
|
||||
<mesh name="Floors-Group">
|
||||
{floors.map((floor) => (
|
||||
<FloorInstance key={floor.floorUuid} floor={floor} />
|
||||
))}
|
||||
@@ -86,7 +85,7 @@ function FloorInstances() {
|
||||
)}
|
||||
|
||||
{toggleView && floors.length > 0 && (
|
||||
<mesh name='Floors-2D-Group'>
|
||||
<mesh name="Floors-2D-Group">
|
||||
{floors.map((floor) => (
|
||||
<Floor2DInstance key={floor.floorUuid} floor={floor} />
|
||||
))}
|
||||
@@ -95,14 +94,13 @@ function FloorInstances() {
|
||||
|
||||
{toggleView && (
|
||||
<>
|
||||
<group name='Floor-Points-Group'>
|
||||
<group name="Floor-Points-Group">
|
||||
{allPoints.map((point) => (
|
||||
<Point key={point.pointUuid} point={point} />
|
||||
))}
|
||||
</group>
|
||||
|
||||
<group name='Floor-Lines-Group'>
|
||||
|
||||
<group name="Floor-Lines-Group">
|
||||
{allLines.map(({ start, end, key }) => (
|
||||
<Line key={key} points={[start, end]} />
|
||||
))}
|
||||
@@ -114,7 +112,7 @@ function FloorInstances() {
|
||||
|
||||
return (
|
||||
<React.Fragment key={key}>
|
||||
{toggleView &&
|
||||
{toggleView && (
|
||||
<Html
|
||||
key={`${start.pointUuid}_${end.pointUuid}`}
|
||||
userData={line}
|
||||
@@ -125,24 +123,19 @@ function FloorInstances() {
|
||||
prepend
|
||||
sprite
|
||||
>
|
||||
<div
|
||||
key={key}
|
||||
className={`distance ${key}`}
|
||||
>
|
||||
<div key={key} className={`distance ${key}`}>
|
||||
{distance.toFixed(2)} m
|
||||
</div>
|
||||
</Html>
|
||||
}
|
||||
)}
|
||||
</React.Fragment>
|
||||
)
|
||||
);
|
||||
})}
|
||||
|
||||
</group>
|
||||
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default FloorInstances;
|
||||
export default FloorInstances;
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Vector2 } from "three";
|
||||
|
||||
export function computeArea(data: any, type: "zone" | "rooms" | "aisle"): any {
|
||||
if (type === "zone") {
|
||||
const points3D = data.map((p: any) => new Vector2(p[0], p[2]));
|
||||
let area = 0;
|
||||
for (let i = 0; i < points3D.length - 1; i++) {
|
||||
const current = points3D[i];
|
||||
const next = points3D[i + 1];
|
||||
area += current.x * next.y - next.x * current.y;
|
||||
}
|
||||
|
||||
return Math.abs(area) / 2;
|
||||
}
|
||||
|
||||
if (type === "rooms") {
|
||||
const points2D = data.coordinates.map(
|
||||
(coordinate: any) =>
|
||||
new Vector2(coordinate.position.x, coordinate.position.z)
|
||||
);
|
||||
let area = 0;
|
||||
for (let i = 0; i < points2D.length - 1; i++) {
|
||||
const current = points2D[i];
|
||||
const next = points2D[i + 1];
|
||||
area += current.x * next.y - next.x * current.y;
|
||||
}
|
||||
return Math.abs(area) / 2;
|
||||
}
|
||||
}
|
||||
10
app/src/modules/builder/functions/getArea.ts
Normal file
10
app/src/modules/builder/functions/getArea.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Vector2 } from "three";
|
||||
|
||||
export default function getArea(points: Vector2[]): number {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < points.length; i++) {
|
||||
const j = (i + 1) % points.length;
|
||||
sum += points[i].x * points[j].y - points[j].x * points[i].y;
|
||||
}
|
||||
return Math.abs(sum / 2);
|
||||
}
|
||||
48
app/src/modules/builder/functions/getCenteroid.tsx
Normal file
48
app/src/modules/builder/functions/getCenteroid.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Vector2 } from "three";
|
||||
|
||||
export default function getCenteroidPoint(points: Vector2[]): Vector2 | null {
|
||||
if (points.length < 3) return null;
|
||||
|
||||
let minZ = points[0].y;
|
||||
let maxZ = points[0].y;
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
minZ = Math.min(minZ, points[i].y);
|
||||
maxZ = Math.max(maxZ, points[i].y);
|
||||
}
|
||||
|
||||
const scanZ = minZ + (maxZ - minZ) * 0.51;
|
||||
|
||||
const intersections: number[] = [];
|
||||
|
||||
for (let i = 0; i < points.length; i++) {
|
||||
const p1 = points[i];
|
||||
const p2 = points[(i + 1) % points.length];
|
||||
|
||||
if (p1.y === p2.y) continue;
|
||||
|
||||
const [top, bottom] = p1.y > p2.y ? [p1, p2] : [p2, p1];
|
||||
|
||||
if (scanZ >= bottom.y && scanZ < top.y) {
|
||||
const t = (scanZ - bottom.y) / (top.y - bottom.y);
|
||||
const x = bottom.x + t * (top.x - bottom.x);
|
||||
intersections.push(x);
|
||||
}
|
||||
}
|
||||
|
||||
intersections.sort((a, b) => a - b);
|
||||
|
||||
if (intersections.length >= 2) {
|
||||
const x = (intersections[0] + intersections[1]) / 2;
|
||||
return new Vector2(x, scanZ);
|
||||
}
|
||||
|
||||
let x = 0,
|
||||
z = 0;
|
||||
for (const p of points) {
|
||||
x += p.x;
|
||||
z += p.y;
|
||||
}
|
||||
x /= points.length;
|
||||
z /= points.length;
|
||||
return new Vector2(x, z);
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
import { useRoomsState, useToggleView } from "../../../store/builder/store";
|
||||
import { computeArea } from "../functions/computeArea";
|
||||
import { Html } from "@react-three/drei";
|
||||
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||
import * as turf from "@turf/turf";
|
||||
import * as THREE from "three";
|
||||
|
||||
const CalculateAreaGroup = () => {
|
||||
const { roomsState } = useRoomsState();
|
||||
const { toggleView } = useToggleView();
|
||||
const savedTheme: string | null = localStorage.getItem("theme");
|
||||
|
||||
return (
|
||||
<group name="roomArea" visible={toggleView}>
|
||||
<group name="roomFills" visible={toggleView}>
|
||||
{roomsState.length > 0 &&
|
||||
roomsState.flat().map((room: any, index: number) => {
|
||||
const coordinates = room.coordinates;
|
||||
if (!coordinates || coordinates.length < 3) return null;
|
||||
|
||||
const coords2D = coordinates.map((p: any) => new THREE.Vector2(p.position.x, p.position.z));
|
||||
|
||||
if (!coords2D[0].equals(coords2D[coords2D.length - 1])) {
|
||||
coords2D.push(coords2D[0]);
|
||||
}
|
||||
|
||||
const shape = new THREE.Shape(coords2D);
|
||||
const extrudeSettings = {
|
||||
depth: 0.01,
|
||||
bevelEnabled: false,
|
||||
};
|
||||
|
||||
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
|
||||
geometry.rotateX(Math.PI / 2);
|
||||
|
||||
const material = new THREE.MeshBasicMaterial({
|
||||
color: savedTheme === "dark" ? "#d2baff" : "#6f42c1",
|
||||
side: THREE.DoubleSide,
|
||||
transparent: true,
|
||||
opacity: 0.4,
|
||||
depthWrite: false,
|
||||
});
|
||||
|
||||
return (
|
||||
<group key={`roomFill-${index}`}>
|
||||
<mesh
|
||||
geometry={geometry}
|
||||
material={material}
|
||||
position={[0, 0.12, 0]}
|
||||
/>
|
||||
</group>
|
||||
);
|
||||
})}
|
||||
</group>
|
||||
{roomsState.length > 0 &&
|
||||
roomsState.flat().map((room: any, index: number) => {
|
||||
if (!toggleView) return null;
|
||||
const coordinates = room.coordinates;
|
||||
|
||||
if (!coordinates || coordinates.length < 3) return null;
|
||||
|
||||
let coords2D = coordinates.map((p: any) => [p.position.x, p.position.z,]);
|
||||
|
||||
const first = coords2D[0];
|
||||
const last = coords2D[coords2D.length - 1];
|
||||
if (first[0] !== last[0] || first[1] !== last[1]) {
|
||||
coords2D.push(first);
|
||||
}
|
||||
|
||||
const polygon = turf.polygon([coords2D]);
|
||||
const center2D = turf.center(polygon).geometry.coordinates;
|
||||
|
||||
const sumY = coordinates.reduce((sum: number, p: any) => sum + p.position.y, 0);
|
||||
const avgY = sumY / coordinates.length;
|
||||
|
||||
const area = computeArea(room, "rooms");
|
||||
const formattedArea = `${area.toFixed(2)} m²`;
|
||||
|
||||
const htmlPosition: [number, number, number] = [
|
||||
center2D[0],
|
||||
avgY + CONSTANTS.zoneConfig.height,
|
||||
center2D[1],
|
||||
];
|
||||
|
||||
return (
|
||||
<Html
|
||||
key={`${index}-${room.layer || index}`}
|
||||
position={htmlPosition}
|
||||
wrapperClass="distance-text-wrapper"
|
||||
className="distance-text"
|
||||
zIndexRange={[1, 0]}
|
||||
prepend
|
||||
center
|
||||
sprite
|
||||
>
|
||||
<div className={`distance area line-${room.layer || index}`}>
|
||||
Room ({formattedArea})
|
||||
</div>
|
||||
</Html>
|
||||
);
|
||||
})}
|
||||
</group>
|
||||
);
|
||||
};
|
||||
|
||||
export default CalculateAreaGroup;
|
||||
@@ -1,19 +1,21 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from 'three';
|
||||
import { Html, Extrude } from '@react-three/drei';
|
||||
import { useLoader } from '@react-three/fiber';
|
||||
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
|
||||
import { useSceneContext } from '../../../scene/sceneContext';
|
||||
import { useToggleView, useToolMode } from '../../../../store/builder/store';
|
||||
import { useWallClassification } from './instance/helpers/useWallClassification';
|
||||
import Line from '../../line/line';
|
||||
import Point from '../../point/point';
|
||||
import WallInstance from './instance/wallInstance';
|
||||
import * as Constants from '../../../../types/world/worldConstants';
|
||||
import React, { useEffect, useMemo } from "react";
|
||||
import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from "three";
|
||||
import { Html, Extrude } from "@react-three/drei";
|
||||
import { useLoader } from "@react-three/fiber";
|
||||
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
|
||||
import { useSceneContext } from "../../../scene/sceneContext";
|
||||
import { useToggleView, useToolMode } from "../../../../store/builder/store";
|
||||
import { useWallClassification } from "./instance/helpers/useWallClassification";
|
||||
import Line from "../../line/line";
|
||||
import Point from "../../point/point";
|
||||
import WallInstance from "./instance/wallInstance";
|
||||
import * as Constants from "../../../../types/world/worldConstants";
|
||||
|
||||
import texturePath from "../../../../assets/textures/floor/white.png";
|
||||
import texturePathDark from "../../../../assets/textures/floor/black.png";
|
||||
import useModuleStore from '../../../../store/ui/useModuleStore';
|
||||
import useModuleStore from "../../../../store/ui/useModuleStore";
|
||||
import getCenteroidPoint from "../../functions/getCenteroid";
|
||||
import getArea from "../../functions/getArea";
|
||||
|
||||
function WallInstances() {
|
||||
const { wallStore } = useSceneContext();
|
||||
@@ -26,11 +28,11 @@ function WallInstances() {
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('walls: ', walls);
|
||||
}, [walls])
|
||||
}, [walls]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!toggleView && activeModule === 'builder') {
|
||||
if (toolMode !== 'cursor') {
|
||||
if (!toggleView && activeModule === "builder") {
|
||||
if (toolMode !== "cursor") {
|
||||
if (selectedWall) setSelectedWall(null);
|
||||
}
|
||||
} else {
|
||||
@@ -42,8 +44,8 @@ function WallInstances() {
|
||||
const points: Point[] = [];
|
||||
const seenUuids = new Set<string>();
|
||||
|
||||
walls.forEach(wall => {
|
||||
wall.points.forEach(point => {
|
||||
walls.forEach((wall) => {
|
||||
wall.points.forEach((point) => {
|
||||
if (!seenUuids.has(point.pointUuid)) {
|
||||
seenUuids.add(point.pointUuid);
|
||||
points.push(point);
|
||||
@@ -62,9 +64,9 @@ function WallInstances() {
|
||||
<WallInstance key={wall.wallUuid} wall={wall} />
|
||||
))}
|
||||
|
||||
<group name='Wall-Floors-Group'>
|
||||
<group name="Wall-Floors-Group">
|
||||
{rooms.map((room, index) => (
|
||||
<Floor key={index} room={room} />
|
||||
<Floor3D key={index} room={room} />
|
||||
))}
|
||||
</group>
|
||||
</>
|
||||
@@ -72,14 +74,19 @@ function WallInstances() {
|
||||
|
||||
{toggleView && (
|
||||
<>
|
||||
<group name='Wall-Points-Group'>
|
||||
<group name="Wall-Points-Group">
|
||||
{allPoints.map((point) => (
|
||||
<Point key={point.pointUuid} point={point} />
|
||||
))}
|
||||
</group>
|
||||
|
||||
<group name='Wall-Lines-Group'>
|
||||
<group name="Wall-Floors-Group">
|
||||
{rooms.map((room, index) => (
|
||||
<Floor2D key={index} room={room} />
|
||||
))}
|
||||
</group>
|
||||
|
||||
<group name="Wall-Lines-Group">
|
||||
{walls.map((wall) => (
|
||||
<React.Fragment key={wall.wallUuid}>
|
||||
<Line points={wall.points} />
|
||||
@@ -91,8 +98,8 @@ function WallInstances() {
|
||||
const distance = new Vector3(...wall.points[0].position).distanceTo(new Vector3(...wall.points[1].position));
|
||||
|
||||
return (
|
||||
< React.Fragment key={wall.wallUuid}>
|
||||
{toggleView &&
|
||||
<React.Fragment key={wall.wallUuid}>
|
||||
{toggleView && (
|
||||
<Html
|
||||
key={`${wall.points[0].pointUuid}_${wall.points[1].pointUuid}`}
|
||||
userData={wall}
|
||||
@@ -103,29 +110,25 @@ function WallInstances() {
|
||||
prepend
|
||||
sprite
|
||||
>
|
||||
<div
|
||||
key={wall.wallUuid}
|
||||
className={`distance ${wall.wallUuid}`}
|
||||
>
|
||||
<div key={wall.wallUuid} className={`distance ${wall.wallUuid}`}>
|
||||
{distance.toFixed(2)} m
|
||||
</div>
|
||||
</Html>
|
||||
}
|
||||
)}
|
||||
</React.Fragment>
|
||||
)
|
||||
);
|
||||
})}
|
||||
|
||||
</group>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default WallInstances;
|
||||
|
||||
function Floor({ room }: { readonly room: Point[] }) {
|
||||
const savedTheme: string | null = localStorage.getItem('theme');
|
||||
function Floor3D({ room }: { readonly room: Point[] }) {
|
||||
const savedTheme: string | null = localStorage.getItem("theme");
|
||||
const textureScale = Constants.floorConfig.textureScale;
|
||||
const floorTexture = useLoader(TextureLoader, savedTheme === "dark" ? texturePathDark : texturePath);
|
||||
floorTexture.wrapS = floorTexture.wrapT = RepeatWrapping;
|
||||
@@ -134,10 +137,12 @@ function Floor({ room }: { readonly room: Point[] }) {
|
||||
|
||||
const shape = useMemo(() => {
|
||||
const shape = new Shape();
|
||||
const points = room.map(p => new Vector2(p.position[0], p.position[2]));
|
||||
const points = room.map((p) => new Vector2(p.position[0], p.position[2]));
|
||||
if (points.length < 3) return null;
|
||||
shape.moveTo(points[0].x, points[0].y);
|
||||
points.forEach((pt) => { shape.lineTo(pt.x, pt.y); });
|
||||
points.forEach((pt) => {
|
||||
shape.lineTo(pt.x, pt.y);
|
||||
});
|
||||
return shape;
|
||||
}, [room]);
|
||||
|
||||
@@ -145,15 +150,54 @@ function Floor({ room }: { readonly room: Point[] }) {
|
||||
|
||||
return (
|
||||
<mesh name="Wall-Floor" rotation={[Math.PI / 2, 0, 0]}>
|
||||
<Extrude
|
||||
receiveShadow
|
||||
castShadow
|
||||
name="Wall-Floor"
|
||||
args={[shape, { depth: Constants.floorConfig.height, bevelEnabled: false }]}
|
||||
position={[0, 0, 0]}
|
||||
>
|
||||
<Extrude receiveShadow castShadow name="Wall-Floor" args={[shape, { depth: Constants.floorConfig.height, bevelEnabled: false }]} position={[0, 0, 0]}>
|
||||
<meshStandardMaterial color={Constants.floorConfig.defaultColor} map={floorTexture} side={DoubleSide} />
|
||||
</Extrude>
|
||||
</mesh>
|
||||
);
|
||||
}
|
||||
|
||||
function Floor2D({ room }: { readonly room: Point[] }) {
|
||||
const savedTheme: string | null = localStorage.getItem("theme");
|
||||
|
||||
const points2D = useMemo(() => {
|
||||
return room.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2))));
|
||||
}, [room]);
|
||||
|
||||
const shape = useMemo(() => {
|
||||
const shape = new Shape();
|
||||
shape.moveTo(points2D[0].x, points2D[0].y);
|
||||
for (let i = 1; i < points2D.length; i++) {
|
||||
shape.lineTo(points2D[i].x, points2D[i].y);
|
||||
}
|
||||
shape.lineTo(points2D[0].x, points2D[0].y);
|
||||
return shape;
|
||||
}, [points2D]);
|
||||
|
||||
const area = useMemo(() => getArea(points2D), [points2D]);
|
||||
|
||||
const centroid: [number, number, number] = useMemo(() => {
|
||||
const center = getCenteroidPoint(points2D);
|
||||
if (!center) return [0, Constants.floorConfig.height + 0.01, 0];
|
||||
|
||||
return [center.x, Constants.floorConfig.height + 0.01, center.y] as [number, number, number];
|
||||
}, [points2D]);
|
||||
|
||||
if (!shape) return null;
|
||||
|
||||
const formattedArea = `${area.toFixed(2)} m²`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<mesh castShadow receiveShadow name="Wall-Floor" rotation={[Math.PI / 2, 0, 0]}>
|
||||
<Extrude receiveShadow castShadow name="Wall-Floor" args={[shape, { depth: Constants.floorConfig.height }]} position={[0, 0, 0]}>
|
||||
<meshBasicMaterial color={savedTheme === "dark" ? Constants.lineConfig.wallColor : Constants.lineConfig.wallColor} side={DoubleSide} transparent opacity={0.4} depthWrite={false} />
|
||||
</Extrude>
|
||||
</mesh>
|
||||
|
||||
<Html position={centroid} wrapperClass="distance-text-wrapper" className="distance-text" zIndexRange={[1, 0]} prepend center sprite>
|
||||
<div className="distance area">({formattedArea})</div>
|
||||
</Html>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,50 +1,55 @@
|
||||
import { useMemo } from 'react';
|
||||
import { DoubleSide, Shape, Vector2 } from 'three';
|
||||
import { Extrude } from '@react-three/drei';
|
||||
import * as Constants from '../../../../../types/world/worldConstants';
|
||||
import { useMemo } from "react";
|
||||
import { DoubleSide, Shape, Vector2 } from "three";
|
||||
import { Extrude, Html } from "@react-three/drei";
|
||||
import * as Constants from "../../../../../types/world/worldConstants";
|
||||
import getCenteroid from "../../../functions/getCenteroid";
|
||||
import getArea from "../../../functions/getArea";
|
||||
|
||||
function Zone2DInstance({ zone }: { readonly zone: Zone }) {
|
||||
const savedTheme: string | null = localStorage.getItem("theme");
|
||||
|
||||
const points2D = useMemo(() => {
|
||||
return zone.points.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2))));
|
||||
}, [zone]);
|
||||
|
||||
const shape = useMemo(() => {
|
||||
const shape = new Shape();
|
||||
const points = zone.points.map(p => new Vector2(p.position[0], p.position[2]));
|
||||
if (points.length < 3) return null;
|
||||
shape.moveTo(points[0].x, points[0].y);
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
shape.lineTo(points[i].x, points[i].y);
|
||||
shape.moveTo(points2D[0].x, points2D[0].y);
|
||||
for (let i = 1; i < points2D.length; i++) {
|
||||
shape.lineTo(points2D[i].x, points2D[i].y);
|
||||
}
|
||||
shape.lineTo(points2D[0].x, points2D[0].y);
|
||||
return shape;
|
||||
}, [zone]);
|
||||
}, [points2D]);
|
||||
|
||||
const area = useMemo(() => getArea(points2D), [points2D]);
|
||||
|
||||
const centroid: [number, number, number] = useMemo(() => {
|
||||
const center = getCenteroid(points2D);
|
||||
if (!center) return [0, Constants.floorConfig.height + 0.01, 0];
|
||||
|
||||
return [center.x, Constants.floorConfig.height + 0.01, center.y] as [number, number, number];
|
||||
}, [points2D]);
|
||||
|
||||
if (!shape) return null;
|
||||
|
||||
const formattedArea = `${area.toFixed(2)} m²`;
|
||||
|
||||
return (
|
||||
<mesh
|
||||
castShadow
|
||||
receiveShadow
|
||||
name={`Zone-2D-${zone.zoneUuid}`}
|
||||
rotation={[Math.PI / 2, 0, 0]}
|
||||
position={[0, 0, 0]}
|
||||
userData={zone}
|
||||
>
|
||||
<Extrude
|
||||
name={`Zone-${zone.zoneUuid}`}
|
||||
args={[shape, {
|
||||
depth: Constants.floorConfig.height,
|
||||
}]}
|
||||
userData={zone}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
color={savedTheme === "dark" ? "#007BFF" : "#007BFF"}
|
||||
side={DoubleSide}
|
||||
transparent
|
||||
opacity={0.4}
|
||||
depthWrite={false}
|
||||
/>
|
||||
</Extrude>
|
||||
</mesh>
|
||||
<>
|
||||
<mesh castShadow receiveShadow name={`Zone-2D-${zone.zoneUuid}`} rotation={[Math.PI / 2, 0, 0]} position={[0, 0, 0]} userData={zone}>
|
||||
<Extrude name={`Zone-${zone.zoneUuid}`} args={[shape, { depth: Constants.floorConfig.height }]} userData={zone}>
|
||||
<meshBasicMaterial color={savedTheme === "dark" ? Constants.lineConfig.zoneColor : Constants.lineConfig.zoneColor} side={DoubleSide} transparent opacity={0.4} depthWrite={false} />
|
||||
</Extrude>
|
||||
</mesh>
|
||||
|
||||
<Html key={zone.zoneUuid} position={centroid} wrapperClass="distance-text-wrapper" className="distance-text" zIndexRange={[1, 0]} prepend center sprite>
|
||||
<div className="distance area">
|
||||
{zone.zoneName} ({formattedArea})
|
||||
</div>
|
||||
</Html>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default Zone2DInstance;
|
||||
export default Zone2DInstance;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { Vector3 } from 'three';
|
||||
import { Html } from '@react-three/drei';
|
||||
import { useSceneContext } from '../../../scene/sceneContext';
|
||||
import { useToggleView } from '../../../../store/builder/store';
|
||||
import Line from '../../line/line';
|
||||
import Point from '../../point/point';
|
||||
import ZoneInstance from './Instance/zoneInstance';
|
||||
import Zone2DInstance from './Instance/zone2DInstance';
|
||||
import React, { useEffect, useMemo } from "react";
|
||||
import { Vector3 } from "three";
|
||||
import { Html } from "@react-three/drei";
|
||||
import { useSceneContext } from "../../../scene/sceneContext";
|
||||
import { useToggleView } from "../../../../store/builder/store";
|
||||
import Line from "../../line/line";
|
||||
import Point from "../../point/point";
|
||||
import ZoneInstance from "./Instance/zoneInstance";
|
||||
import Zone2DInstance from "./Instance/zone2DInstance";
|
||||
|
||||
function ZoneInstances() {
|
||||
const { zoneStore } = useSceneContext();
|
||||
@@ -15,14 +15,14 @@ function ZoneInstances() {
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('zones: ', zones);
|
||||
}, [zones])
|
||||
}, [zones]);
|
||||
|
||||
const allPoints = useMemo(() => {
|
||||
const points: Point[] = [];
|
||||
const seenUuids = new Set<string>();
|
||||
|
||||
zones.forEach(zone => {
|
||||
zone.points.forEach(point => {
|
||||
zones.forEach((zone) => {
|
||||
zone.points.forEach((point) => {
|
||||
if (!seenUuids.has(point.pointUuid)) {
|
||||
seenUuids.add(point.pointUuid);
|
||||
points.push(point);
|
||||
@@ -50,7 +50,7 @@ function ZoneInstances() {
|
||||
lines.push({
|
||||
start: current,
|
||||
end: next,
|
||||
key: lineKey
|
||||
key: lineKey,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -61,9 +61,8 @@ function ZoneInstances() {
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
{!toggleView && zones.length > 0 && (
|
||||
<mesh name='Zones-Group'>
|
||||
<mesh name="Zones-Group">
|
||||
{zones.map((zone) => (
|
||||
<ZoneInstance key={zone.zoneUuid} zone={zone} />
|
||||
))}
|
||||
@@ -71,7 +70,7 @@ function ZoneInstances() {
|
||||
)}
|
||||
|
||||
{toggleView && zones.length > 0 && (
|
||||
<mesh name='Zones-2D-Group'>
|
||||
<mesh name="Zones-2D-Group">
|
||||
{zones.map((zone) => (
|
||||
<Zone2DInstance key={zone.zoneUuid} zone={zone} />
|
||||
))}
|
||||
@@ -80,14 +79,13 @@ function ZoneInstances() {
|
||||
|
||||
{toggleView && (
|
||||
<>
|
||||
<group name='Zone-Points-Group'>
|
||||
<group name="Zone-Points-Group">
|
||||
{allPoints.map((point) => (
|
||||
<Point key={point.pointUuid} point={point} />
|
||||
))}
|
||||
</group>
|
||||
|
||||
<group name='Zone-Lines-Group'>
|
||||
|
||||
<group name="Zone-Lines-Group">
|
||||
{allLines.map(({ start, end, key }) => (
|
||||
<Line key={key} points={[start, end]} />
|
||||
))}
|
||||
@@ -99,7 +97,7 @@ function ZoneInstances() {
|
||||
|
||||
return (
|
||||
<React.Fragment key={key}>
|
||||
{toggleView &&
|
||||
{toggleView && (
|
||||
<Html
|
||||
key={`${start.pointUuid}_${end.pointUuid}`}
|
||||
userData={line}
|
||||
@@ -110,23 +108,19 @@ function ZoneInstances() {
|
||||
prepend
|
||||
sprite
|
||||
>
|
||||
<div
|
||||
key={key}
|
||||
className={`distance ${key}`}
|
||||
>
|
||||
<div key={key} className={`distance ${key}`}>
|
||||
{distance.toFixed(2)} m
|
||||
</div>
|
||||
</Html>
|
||||
}
|
||||
)}
|
||||
</React.Fragment>
|
||||
)
|
||||
);
|
||||
})}
|
||||
|
||||
</group>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default ZoneInstances
|
||||
export default ZoneInstances;
|
||||
|
||||
@@ -71,11 +71,6 @@ export const useToggleView = create<any>((set: any) => ({
|
||||
setToggleView: (x: any) => set(() => ({ toggleView: x })),
|
||||
}));
|
||||
|
||||
export const useRoomsState = create<any>((set: any) => ({
|
||||
roomsState: [],
|
||||
setRoomsState: (x: any) => set(() => ({ roomsState: x })),
|
||||
}));
|
||||
|
||||
export const useSelectedItem = create<any>((set: any) => ({
|
||||
selectedItem: {
|
||||
name: "",
|
||||
@@ -315,11 +310,6 @@ export const useTileDistance = create<any>((set: any) => ({
|
||||
})),
|
||||
}));
|
||||
|
||||
export const usePlayAgv = create<any>((set, get) => ({
|
||||
PlayAgv: [],
|
||||
setPlayAgv: (updateFn: (prev: any[]) => any[]) => set({ PlayAgv: updateFn(get().PlayAgv) }),
|
||||
}));
|
||||
|
||||
// Define the Asset type
|
||||
type Asset = {
|
||||
id: string;
|
||||
@@ -350,19 +340,6 @@ export const useResourceManagementId = create<ResourceManagementState>((set) =>
|
||||
setResourceManagementId: (id: string) => set({ resourceManagementId: id }),
|
||||
}));
|
||||
|
||||
// version visible hidden
|
||||
interface VersionHistoryState {
|
||||
viewVersionHistory: boolean;
|
||||
setVersionHistoryVisible: (value: boolean) => void;
|
||||
}
|
||||
|
||||
const useVersionHistoryVisibleStore = create<VersionHistoryState>((set) => ({
|
||||
viewVersionHistory: false,
|
||||
setVersionHistoryVisible: (value) => set({ viewVersionHistory: value }),
|
||||
}));
|
||||
|
||||
export default useVersionHistoryVisibleStore;
|
||||
|
||||
interface ShortcutStore {
|
||||
showShortcuts: boolean;
|
||||
setShowShortcuts: (value: boolean) => void;
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { create } from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { create } from "zustand";
|
||||
import { immer } from "zustand/middleware/immer";
|
||||
|
||||
interface VersionStore {
|
||||
versionHistory: VersionHistory;
|
||||
selectedVersion: Version | null;
|
||||
viewVersionHistory: boolean;
|
||||
createNewVersion: boolean;
|
||||
|
||||
setSelectedVersion: (version: Version) => void;
|
||||
clearSelectedVersion: () => void;
|
||||
|
||||
setVersionHistoryVisible: (visibility: boolean) => void;
|
||||
setCreateNewVersion: (createNewVersion: boolean) => void;
|
||||
|
||||
addVersion: (version: Version) => void;
|
||||
@@ -26,6 +28,7 @@ export const createVersionStore = () => {
|
||||
immer((set, get) => ({
|
||||
versionHistory: [],
|
||||
selectedVersion: null,
|
||||
viewVersionHistory: false,
|
||||
createNewVersion: false,
|
||||
|
||||
setSelectedVersion: (version) => {
|
||||
@@ -40,30 +43,36 @@ export const createVersionStore = () => {
|
||||
});
|
||||
},
|
||||
|
||||
setVersionHistoryVisible: (visibility: boolean) => {
|
||||
set((state) => {
|
||||
state.viewVersionHistory = visibility;
|
||||
});
|
||||
},
|
||||
|
||||
setCreateNewVersion: (createNewVersion: boolean) => {
|
||||
set((state) => {
|
||||
state.createNewVersion = createNewVersion;
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
addVersion: (version: Version) => {
|
||||
set((state) => {
|
||||
state.versionHistory.unshift(version);
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
setVersions: (versions: Version[]) => {
|
||||
set((state) => {
|
||||
state.versionHistory = versions;
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
clearVersions: () => {
|
||||
set((state) => {
|
||||
state.versionHistory = [];
|
||||
state.selectedVersion = null;
|
||||
state.createNewVersion = false
|
||||
})
|
||||
state.createNewVersion = false;
|
||||
});
|
||||
},
|
||||
|
||||
setVersionName: (versionId: string, versionName: string) => {
|
||||
@@ -72,7 +81,7 @@ export const createVersionStore = () => {
|
||||
if (version) {
|
||||
version.versionName = versionName;
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
updateVersion: (versionId: string, versionName: string, versionDescription: string) => {
|
||||
@@ -82,16 +91,16 @@ export const createVersionStore = () => {
|
||||
version.versionName = versionName;
|
||||
version.versionDescription = versionDescription;
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
getVersionById: (versionId: string) => {
|
||||
return get().versionHistory.find((v) => {
|
||||
return v.versionId === versionId
|
||||
})
|
||||
}
|
||||
return v.versionId === versionId;
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
||||
};
|
||||
|
||||
export type VersionStoreType = ReturnType<typeof createVersionStore>;
|
||||
export type VersionStoreType = ReturnType<typeof createVersionStore>;
|
||||
|
||||
@@ -202,7 +202,7 @@ export const firstPersonControls: Controls = {
|
||||
leftSpeed: -0.1, // Speed of left movement
|
||||
rightSpeed: 0.1, // Speed of right movement
|
||||
walkSpeed: 1, // Walk speed
|
||||
sprintSpeed: 4 // Sprint Speed
|
||||
sprintSpeed: 4, // Sprint Speed
|
||||
};
|
||||
|
||||
export const thirdPersonControls: ThirdPersonControls = {
|
||||
@@ -359,7 +359,7 @@ export const roofConfig: RoofConfig = {
|
||||
export const aisleConfig: AisleConfig = {
|
||||
width: 0.1, // Width of the aisles
|
||||
height: 0.01, // Height of the aisles
|
||||
defaultColor: '#E2AC09', // Default color of the aisles
|
||||
defaultColor: "#E2AC09", // Default color of the aisles
|
||||
};
|
||||
|
||||
export const zoneConfig: ZoneConfig = {
|
||||
@@ -384,4 +384,4 @@ export const distanceConfig: DistanceConfig = {
|
||||
|
||||
export const undoRedoConfig: undoRedoCount = {
|
||||
undoRedoCount: 50,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,19 @@
|
||||
import React, { useEffect } from "react";
|
||||
import useModuleStore, { useSubModuleStore, useThreeDStore } from "../../store/ui/useModuleStore";
|
||||
import { usePlayerStore, useToggleStore } from "../../store/ui/useUIToggleStore";
|
||||
import useVersionHistoryVisibleStore, { useActiveSubTool, useActiveTool, useAddAction, useDfxUpload, useRenameModeStore, useIsComparing, useSelectedComment, useShortcutStore, useToggleView, useToolMode, useViewSceneStore } from "../../store/builder/store";
|
||||
import {
|
||||
useActiveSubTool,
|
||||
useActiveTool,
|
||||
useAddAction,
|
||||
useDfxUpload,
|
||||
useRenameModeStore,
|
||||
useIsComparing,
|
||||
useSelectedComment,
|
||||
useShortcutStore,
|
||||
useToggleView,
|
||||
useToolMode,
|
||||
useViewSceneStore,
|
||||
} from "../../store/builder/store";
|
||||
import useCameraModeStore, { usePlayButtonStore } from "../../store/ui/usePlayButtonStore";
|
||||
import { detectModifierKeys } from "./detectModifierKeys";
|
||||
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
||||
@@ -33,8 +45,7 @@ const KeyPressListener: React.FC = () => {
|
||||
const { setViewSceneLabels } = useViewSceneStore();
|
||||
const { isRenameMode, setIsRenameMode } = useRenameModeStore();
|
||||
const { selectedFloorAsset, setSelectedWallAsset } = useBuilderStore();
|
||||
const { setCreateNewVersion } = versionStore();
|
||||
const { setVersionHistoryVisible } = useVersionHistoryVisibleStore();
|
||||
const { setCreateNewVersion, setVersionHistoryVisible } = versionStore();
|
||||
const { setSelectedComment } = useSelectedComment();
|
||||
const { setDfxUploaded } = useDfxUpload();
|
||||
const isTextInput = (element: Element | null): boolean => element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element?.getAttribute("contenteditable") === "true";
|
||||
|
||||
Reference in New Issue
Block a user