Refactor version management: Replace useSaveVersion with useIsComparing across components

- Updated MainScene, SideBarLeft, SideBarRight, Simulations, and CompareLayOut to utilize isComparing state instead of isVersionSaved.
- Adjusted conditional rendering and logic to reflect the new comparison state.
- Introduced SyncCam component to synchronize camera state during comparisons.
- Created useSceneStore to manage camera state with position and target vectors.
- Cleaned up imports and ensured consistent formatting across affected files.
This commit is contained in:
2025-09-05 18:09:43 +05:30
parent 8afa92cbeb
commit 0f10a84215
15 changed files with 288 additions and 291 deletions

View File

@@ -10,25 +10,24 @@ import ForgotPassword from "./pages/ForgotPassword";
import PageNotFound from "./pages/PageNotFound"; import PageNotFound from "./pages/PageNotFound";
const App: React.FC = () => { const App: React.FC = () => {
useEffect(() => {
Cache.clear();
Cache.enabled = true;
}, []);
useEffect(() => { return (
Cache.clear(); <LoggerProvider>
Cache.enabled = true; <Router>
}, []); <Routes>
<Route path="/" element={<UserAuth />} />
return ( <Route path="/forgot" element={<ForgotPassword />} />
<LoggerProvider> <Route path="/dashboard" element={<Dashboard />} />
<Router> <Route path="/projects/:projectId" element={<Project />} />
<Routes> <Route path="*" element={<PageNotFound />} />
<Route path="/" element={<UserAuth />} /> </Routes>
<Route path="/forgot" element={<ForgotPassword />} /> </Router>
<Route path="/dashboard" element={<Dashboard />} /> </LoggerProvider>
<Route path="/projects/:projectId" element={<Project />} /> );
<Route path="*" element={<PageNotFound />} />
</Routes>
</Router>
</LoggerProvider>
);
}; };
export default App; export default App;

View File

@@ -1,5 +1,5 @@
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useCompareProductDataStore, useLoadingProgress, useSaveVersion } from "../../../store/builder/store"; import { useCompareProductDataStore, useLoadingProgress, useIsComparing } from "../../../store/builder/store";
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore"; import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore"; import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@@ -9,21 +9,18 @@ import CompareLayOut from "../../ui/compareVersion/CompareLayOut";
import ComparisonResult from "../../ui/compareVersion/ComparisonResult"; import ComparisonResult from "../../ui/compareVersion/ComparisonResult";
import RegularDropDown from "../../ui/inputs/RegularDropDown"; import RegularDropDown from "../../ui/inputs/RegularDropDown";
import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi";
function ComparisonScene() { function ComparisonScene() {
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { productStore, versionStore } = useSceneContext(); const { productStore, versionStore } = useSceneContext();
const { versionHistory, selectedVersion, setSelectedVersion, setVersions } = versionStore(); const { versionHistory, selectedVersion, setSelectedVersion } = versionStore();
const { products, selectedProduct } = productStore(); const { products, selectedProduct } = productStore();
const { isVersionSaved } = useSaveVersion(); const { isComparing } = useIsComparing();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { comparisonProduct, setComparisonProduct } = useComparisonProduct(); const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
const { mainProduct } = useMainProduct(); const { mainProduct } = useMainProduct();
const { loadingProgress } = useLoadingProgress(); const { loadingProgress } = useLoadingProgress();
const { compareProductsData } = useCompareProductDataStore(); const { compareProductsData } = useCompareProductDataStore();
const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false); const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false);
const { projectId } = useParams();
const handleSelectVersion = (option: string) => { const handleSelectVersion = (option: string) => {
const version = versionHistory.find((version) => version.versionName === option); const version = versionHistory.find((version) => version.versionName === option);
@@ -39,30 +36,6 @@ function ComparisonScene() {
} }
}; };
useEffect(() => {
if (!projectId) return;
getVersionHistoryApi(projectId)
.then((data) => {
const versions: VersionHistory = [];
data.versions.forEach((version: any) => {
versions.push({
version: version.version,
versionId: version.versionId,
versionName: version.versionName,
versionDescription: version.description,
timeStamp: version.createdAt,
createdBy: version.createdBy.userName,
});
});
setVersions(versions);
})
.catch(() => {
console.error("Error fetching version history");
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [projectId]);
useEffect(() => { useEffect(() => {
if (mainProduct && comparisonProduct && compareProductsData.length > 1) { if (mainProduct && comparisonProduct && compareProductsData.length > 1) {
const hasMain = compareProductsData.some((val) => val.productUuid === mainProduct.productUuid); const hasMain = compareProductsData.some((val) => val.productUuid === mainProduct.productUuid);
@@ -79,7 +52,7 @@ function ComparisonScene() {
return ( return (
<> <>
{isVersionSaved && activeModule === "simulation" && selectedProduct && ( {isComparing && activeModule === "simulation" && selectedProduct && (
<> <>
{selectedVersion && !isPlaying && ( {selectedVersion && !isPlaying && (
<div className="initial-selectLayout-wrapper"> <div className="initial-selectLayout-wrapper">

View File

@@ -1,6 +1,6 @@
import { useEffect } from "react"; import { useEffect } from "react";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useLoadingProgress, useRenameModeStore, useSaveVersion, useSelectedComment, useSocketStore, useWidgetSubOption } from "../../../store/builder/store"; import { useLoadingProgress, useRenameModeStore, useIsComparing, useSelectedComment, useSocketStore, useWidgetSubOption } from "../../../store/builder/store";
import useModuleStore, { useThreeDStore } from "../../../store/ui/useModuleStore"; import useModuleStore, { useThreeDStore } from "../../../store/ui/useModuleStore";
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore"; import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore"; import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore";
@@ -36,7 +36,7 @@ import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionCo
function MainScene() { function MainScene() {
const { setMainProduct } = useMainProduct(); const { setMainProduct } = useMainProduct();
const { isVersionSaved, setIsVersionSaved } = useSaveVersion(); const { isComparing, setIsComparing } = useIsComparing();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { selectedUser } = useSelectedUserStore(); const { selectedUser } = useSelectedUserStore();
const { loadingProgress } = useLoadingProgress(); const { loadingProgress } = useLoadingProgress();
@@ -67,9 +67,9 @@ function MainScene() {
useEffect(() => { useEffect(() => {
if (activeModule !== "simulation") { if (activeModule !== "simulation") {
clearComparisonProduct(); clearComparisonProduct();
setIsVersionSaved(false); setIsComparing(false);
} }
}, [activeModule, clearComparisonProduct, setIsVersionSaved]); }, [activeModule, clearComparisonProduct, setIsComparing]);
useEffect(() => { useEffect(() => {
if (!projectId) return; if (!projectId) return;
@@ -162,14 +162,14 @@ function MainScene() {
{loadingProgress > 0 && <LoadingPage progress={loadingProgress} />} {loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
{!isPlaying && ( {!isPlaying && (
<> <>
{toggleThreeD && !isVersionSaved && <ModuleToggle />} {toggleThreeD && !isComparing && <ModuleToggle />}
<SideBarLeft /> <SideBarLeft />
<SideBarRight /> <SideBarRight />
</> </>
)} )}
<RealTimeVisulization /> <RealTimeVisulization />
{activeModule === "market" && <MarketPlace />} {activeModule === "market" && <MarketPlace />}
{activeModule !== "market" && !isPlaying && !isVersionSaved && <Tools />} {activeModule !== "market" && !isPlaying && !isComparing && <Tools />}
{isPlaying && activeModule === "simulation" && loadingProgress === 0 && <SimulationPlayer />} {isPlaying && activeModule === "simulation" && loadingProgress === 0 && <SimulationPlayer />}
{isPlaying && activeModule !== "simulation" && <ControlsPlayer />} {isPlaying && activeModule !== "simulation" && <ControlsPlayer />}
@@ -204,7 +204,7 @@ function MainScene() {
<Scene layout="Main Layout" /> <Scene layout="Main Layout" />
</div> </div>
{selectedProduct && selectedVersion && isVersionSaved && !isPlaying && activeModule === "simulation" && ( {selectedProduct && selectedVersion && isComparing && !isPlaying && activeModule === "simulation" && (
<div className="selectLayout-wrapper"> <div className="selectLayout-wrapper">
<RegularDropDown <RegularDropDown
header={selectedVersion.versionName} header={selectedVersion.versionName}

View File

@@ -8,7 +8,7 @@ import useModuleStore from "../../../store/ui/useModuleStore";
import Widgets from "./visualization/widgets/Widgets"; import Widgets from "./visualization/widgets/Widgets";
import Templates from "../../../modules/visualization/template/Templates"; import Templates from "../../../modules/visualization/template/Templates";
import Search from "../../ui/inputs/Search"; import Search from "../../ui/inputs/Search";
import { useSaveVersion } from "../../../store/builder/store"; import { useIsComparing } from "../../../store/builder/store";
const SideBarLeft: React.FC = () => { const SideBarLeft: React.FC = () => {
const [activeOption, setActiveOption] = useState("Widgets"); const [activeOption, setActiveOption] = useState("Widgets");
@@ -16,7 +16,7 @@ const SideBarLeft: React.FC = () => {
const { toggleUILeft } = useToggleStore(); const { toggleUILeft } = useToggleStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { isVersionSaved } = useSaveVersion(); const { isComparing } = useIsComparing();
// Reset activeOption whenever activeModule changes // Reset activeOption whenever activeModule changes
useEffect(() => { useEffect(() => {
@@ -35,7 +35,7 @@ const SideBarLeft: React.FC = () => {
return ( return (
<div <div
className={`sidebar-left-wrapper ${toggleUILeft && (!isVersionSaved || activeModule !== "simulation") ? "open" : "closed" className={`sidebar-left-wrapper ${toggleUILeft && (!isComparing || activeModule !== "simulation") ? "open" : "closed"
}`} }`}
> >
<Header /> <Header />
@@ -74,7 +74,7 @@ const SideBarLeft: React.FC = () => {
} else { } else {
return ( return (
<> <>
{!isVersionSaved && ( {!isComparing && (
<> <>
<ToggleHeader <ToggleHeader
options={["Outline"]} options={["Outline"]}

View File

@@ -6,7 +6,7 @@ import { useToggleStore } from "../../../store/ui/useUIToggleStore";
import Visualization from "./visualization/Visualization"; import Visualization from "./visualization/Visualization";
import Analysis from "./analysis/Analysis"; import Analysis from "./analysis/Analysis";
import Simulations from "./simulation/Simulations"; import Simulations from "./simulation/Simulations";
import useVersionHistoryVisibleStore, { useSaveVersion, useToolMode } from "../../../store/builder/store"; import useVersionHistoryVisibleStore, { useIsComparing, useToolMode } from "../../../store/builder/store";
import { useSelectedEventData, useSelectedEventSphere, } from "../../../store/simulation/useSimulationStore"; import { useSelectedEventData, useSelectedEventSphere, } from "../../../store/simulation/useSimulationStore";
import { useBuilderStore } from "../../../store/builder/useBuilderStore"; import { useBuilderStore } from "../../../store/builder/useBuilderStore";
import GlobalProperties from "./properties/GlobalProperties"; import GlobalProperties from "./properties/GlobalProperties";
@@ -52,7 +52,7 @@ const SideBarRight: React.FC = () => {
const { selectedEventData } = useSelectedEventData(); const { selectedEventData } = useSelectedEventData();
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventSphere } = useSelectedEventSphere();
const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore(); const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore();
const { isVersionSaved } = useSaveVersion(); const { isComparing } = useIsComparing();
const [displayComponent, setDisplayComponent] = useState<DisplayComponent>("none"); const [displayComponent, setDisplayComponent] = useState<DisplayComponent>("none");
@@ -80,7 +80,7 @@ const SideBarRight: React.FC = () => {
return; return;
} }
if (!isVersionSaved && activeModule === "simulation") { if (!isComparing && activeModule === "simulation") {
if (subModule === "simulations") { if (subModule === "simulations") {
setDisplayComponent("simulations"); setDisplayComponent("simulations");
return; return;
@@ -155,7 +155,7 @@ const SideBarRight: React.FC = () => {
} }
setDisplayComponent("none"); setDisplayComponent("none");
}, [viewVersionHistory, activeModule, subModule, isVersionSaved, selectedFloorAsset, selectedWall, selectedFloor, selectedAisle, toolMode, selectedDecal]); }, [viewVersionHistory, activeModule, subModule, isComparing, selectedFloorAsset, selectedWall, selectedFloor, selectedAisle, toolMode, selectedDecal]);
const renderComponent = () => { const renderComponent = () => {
switch (displayComponent) { switch (displayComponent) {
@@ -197,11 +197,11 @@ const SideBarRight: React.FC = () => {
}; };
return ( return (
<div className={`sidebar-right-wrapper ${toggleUIRight && (!isVersionSaved || activeModule !== "simulation") ? "open" : "closed"}`} onPointerDown={(e) => e.stopPropagation()}> <div className={`sidebar-right-wrapper ${toggleUIRight && (!isComparing || activeModule !== "simulation") ? "open" : "closed"}`} onPointerDown={(e) => e.stopPropagation()}>
<Header /> <Header />
{toggleUIRight && ( {toggleUIRight && (
<> <>
{(!isVersionSaved || activeModule !== "simulation") && ( {(!isComparing || activeModule !== "simulation") && (
<div className="sidebar-actions-container"> <div className="sidebar-actions-container">
{activeModule !== "simulation" && ( {activeModule !== "simulation" && (
<> <>

View File

@@ -13,7 +13,7 @@ import { deleteProductApi } from "../../../../services/simulation/products/delet
import { renameProductApi } from "../../../../services/simulation/products/renameProductApi"; import { renameProductApi } from "../../../../services/simulation/products/renameProductApi";
import { determineExecutionMachineSequences } from "../../../../modules/simulation/simulator/functions/determineExecutionMachineSequences"; import { determineExecutionMachineSequences } from "../../../../modules/simulation/simulator/functions/determineExecutionMachineSequences";
import ComparePopUp from "../../../ui/compareVersion/Compare"; import ComparePopUp from "../../../ui/compareVersion/Compare";
import { useCompareStore, useSaveVersion } from "../../../../store/builder/store"; import { useCompareStore, useIsComparing } from "../../../../store/builder/store";
import { useToggleStore } from "../../../../store/ui/useUIToggleStore"; import { useToggleStore } from "../../../../store/ui/useUIToggleStore";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../modules/scene/sceneContext"; import { useSceneContext } from "../../../../modules/scene/sceneContext";
@@ -36,10 +36,10 @@ const Simulations: React.FC = () => {
const { setMainProduct } = useMainProduct(); const { setMainProduct } = useMainProduct();
const { selectedVersion } = versionStore(); const { selectedVersion } = versionStore();
const { comparePopUp, setComparePopUp } = useCompareStore(); const { comparePopUp, setComparePopUp } = useCompareStore();
const { setIsVersionSaved } = useSaveVersion(); const { setIsComparing } = useIsComparing();
const handleSaveVersion = () => { const handleSaveVersion = () => {
setIsVersionSaved(true); setIsComparing(true);
setComparePopUp(false); setComparePopUp(false);
setToggleUI(false, false); setToggleUI(false, false);
}; };

View File

@@ -1,19 +1,22 @@
import { useParams } from "react-router-dom";
import React, { useState, useRef, useEffect, Suspense } from "react"; import React, { useState, useRef, useEffect, Suspense } from "react";
import { CompareLayoutIcon, LayoutIcon, ResizerIcon } from "../../icons/SimulationIcons"; import { CompareLayoutIcon, LayoutIcon, ResizerIcon } from "../../icons/SimulationIcons";
import { useLoadingProgress, useSaveVersion } from "../../../store/builder/store"; import { useLoadingProgress, useIsComparing } from "../../../store/builder/store";
import Search from "../inputs/Search";
import OuterClick from "../../../utils/outerClick";
import Scene from "../../../modules/scene/scene";
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore"; import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore"; import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../modules/scene/sceneContext"; import { useSceneContext } from "../../../modules/scene/sceneContext";
import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi"; import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi";
import { useParams } from "react-router-dom"; import Search from "../inputs/Search";
import OuterClick from "../../../utils/outerClick";
import Scene from "../../../modules/scene/scene";
import useRestStates from "../../../hooks/useResetStates";
import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi";
const CompareLayOut = () => { const CompareLayOut = () => {
const { clearComparisonProduct, comparisonProduct, setComparisonProduct } = useComparisonProduct(); const { clearComparisonProduct, comparisonProduct, setComparisonProduct } = useComparisonProduct();
const { versionStore } = useSceneContext(); const { versionStore } = useSceneContext();
const { versionHistory, selectedVersion, setSelectedVersion, clearSelectedVersion } = versionStore(); const { versionHistory, selectedVersion, setSelectedVersion, clearSelectedVersion, setVersions } = versionStore();
const { setLoadingProgress } = useLoadingProgress(); const { setLoadingProgress } = useLoadingProgress();
const [width, setWidth] = useState("50vw"); const [width, setWidth] = useState("50vw");
const [isResizing, setIsResizing] = useState(false); const [isResizing, setIsResizing] = useState(false);
@@ -21,10 +24,43 @@ const CompareLayOut = () => {
const wrapperRef = useRef<HTMLDivElement>(null); const wrapperRef = useRef<HTMLDivElement>(null);
const startWidthRef = useRef<number>(0); const startWidthRef = useRef<number>(0);
const startXRef = useRef<number>(0); const startXRef = useRef<number>(0);
const { setIsVersionSaved } = useSaveVersion(); const { setIsComparing } = useIsComparing();
const { loadingProgress } = useLoadingProgress(); const { loadingProgress } = useLoadingProgress();
const { setIsPlaying } = usePlayButtonStore(); const { setIsPlaying } = usePlayButtonStore();
const { projectId } = useParams(); const { projectId } = useParams();
const { resetStates } = useRestStates();
useEffect(() => {
return () => {
if (selectedVersion?.versionId) {
resetStates();
}
};
}, [selectedVersion?.versionId]);
useEffect(() => {
if (!projectId) return;
getVersionHistoryApi(projectId)
.then((data) => {
const versions: VersionHistory = [];
data.versions.forEach((version: any) => {
versions.push({
version: version.version,
versionId: version.versionId,
versionName: version.versionName,
versionDescription: version.description,
timeStamp: version.createdAt,
createdBy: version.createdBy.userName,
});
});
setVersions(versions);
})
.catch(() => {
console.error("Error fetching version history");
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [projectId]);
useEffect(() => { useEffect(() => {
if (!comparisonProduct) { if (!comparisonProduct) {
@@ -71,7 +107,7 @@ const CompareLayOut = () => {
if (finalWidthVw <= 10) { if (finalWidthVw <= 10) {
setWidth("0px"); setWidth("0px");
setIsVersionSaved(false); setIsComparing(false);
clearComparisonProduct(); clearComparisonProduct();
setIsPlaying(false); setIsPlaying(false);
} else { } else {

View File

@@ -1,17 +1,17 @@
import * as THREE from 'three'; import * as THREE from "three";
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from "react";
import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils'; import { retrieveGLTF, storeGLTF } from "../../../../../utils/indexDB/idbUtils";
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { useToggleView, useToolMode } from '../../../../../store/builder/store'; import { useToggleView, useToolMode } from "../../../../../store/builder/store";
import { AssetBoundingBox } from '../../functions/assetBoundingBox'; import { AssetBoundingBox } from "../../functions/assetBoundingBox";
import { useBuilderStore } from '../../../../../store/builder/useBuilderStore'; import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
import useModuleStore from '../../../../../store/ui/useModuleStore'; import useModuleStore from "../../../../../store/ui/useModuleStore";
import { useSceneContext } from '../../../../scene/sceneContext'; import { useSceneContext } from "../../../../scene/sceneContext";
import { SkeletonUtils } from 'three-stdlib'; import { SkeletonUtils } from "three-stdlib";
import { getAssetFieldApi } from '../../../../../services/factoryBuilder/asset/floorAsset/getAssetField'; import { getAssetFieldApi } from "../../../../../services/factoryBuilder/asset/floorAsset/getAssetField";
import { ModelAnimator } from './animator/modelAnimator'; import { ModelAnimator } from "./animator/modelAnimator";
import { useModelEventHandlers } from './eventHandlers/useModelEventHandlers'; import { useModelEventHandlers } from "./eventHandlers/useModelEventHandlers";
function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendered: boolean; loader: GLTFLoader }>) { function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendered: boolean; loader: GLTFLoader }>) {
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
@@ -31,33 +31,33 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
useEffect(() => { useEffect(() => {
if (!fieldData && asset.eventData) { if (!fieldData && asset.eventData) {
getAssetFieldApi(asset.assetId).then((data) => { getAssetFieldApi(asset.assetId).then((data) => {
if (data.type === 'ArmBot') { if (data.type === "ArmBot") {
if (data.data) { if (data.data) {
const fieldData: IK[] = data.data; const fieldData: IK[] = data.data;
setFieldData(fieldData); setFieldData(fieldData);
} }
} else if (data.type === 'Conveyor' || data.type === 'Crane') { } else if (data.type === "Conveyor" || data.type === "Crane") {
if (data.data) { if (data.data) {
const fieldData = data.data; const fieldData = data.data;
setFieldData(fieldData); setFieldData(fieldData);
} }
} }
}) });
} }
}, [asset.modelUuid, fieldData]) }, [asset.modelUuid, fieldData]);
useEffect(() => { useEffect(() => {
setDeletableFloorAsset(null); setDeletableFloorAsset(null);
if (selectedFloorAsset === null || selectedFloorAsset.userData.modelUuid !== asset.modelUuid) { if (selectedFloorAsset === null || selectedFloorAsset.userData.modelUuid !== asset.modelUuid) {
resetAnimation(asset.modelUuid); resetAnimation(asset.modelUuid);
} }
}, [activeModule, toolMode, selectedFloorAsset]) }, [activeModule, toolMode, selectedFloorAsset]);
useEffect(() => { useEffect(() => {
if (selectedFloorAsset && selectedFloorAsset.userData.modelUuid === asset.modelUuid) { if (selectedFloorAsset && selectedFloorAsset.userData.modelUuid === asset.modelUuid) {
setSelectedFloorAsset(groupRef.current); setSelectedFloorAsset(groupRef.current);
} }
}, [isRendered, selectedFloorAsset]) }, [isRendered, selectedFloorAsset]);
useEffect(() => { useEffect(() => {
if (selectedAssets.length > 0) { if (selectedAssets.length > 0) {
@@ -69,7 +69,7 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
} else { } else {
setIsSelected(false); setIsSelected(false);
} }
}, [selectedAssets]) }, [selectedAssets]);
useEffect(() => { useEffect(() => {
if (gltfScene) { if (gltfScene) {
@@ -78,13 +78,13 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
child.castShadow = true; child.castShadow = true;
child.receiveShadow = true; child.receiveShadow = true;
} }
}) });
} }
}, [gltfScene]); }, [gltfScene]);
const logModelStatus = (modelId: string, status: string) => { const logModelStatus = (modelId: string, status: string) => {
// console.log(modelId, status); // console.log(modelId, status);
} };
useEffect(() => { useEffect(() => {
// Calculate Bounding Box // Calculate Bounding Box
@@ -101,62 +101,61 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
clone.animations = cachedModel.animations || []; clone.animations = cachedModel.animations || [];
setGltfScene(clone); setGltfScene(clone);
calculateBoundingBox(clone); calculateBoundingBox(clone);
logModelStatus(assetId, 'cache-loaded'); logModelStatus(assetId, "cache-loaded");
return; return;
} }
// Check IndexedDB // Check IndexedDB
retrieveGLTF(assetId).then((indexedDBModel) => { retrieveGLTF(assetId)
if (indexedDBModel) { .then((indexedDBModel) => {
const blobUrl = URL.createObjectURL(indexedDBModel); if (indexedDBModel) {
loader.load( const blobUrl = URL.createObjectURL(indexedDBModel);
blobUrl, loader.load(
(gltf) => { blobUrl,
URL.revokeObjectURL(blobUrl); (gltf) => {
THREE.Cache.remove(blobUrl); URL.revokeObjectURL(blobUrl);
THREE.Cache.add(assetId, gltf); THREE.Cache.remove(blobUrl);
setGltfScene(gltf.scene.clone());
calculateBoundingBox(gltf.scene);
logModelStatus(assetId, 'indexedDB-loaded');
},
undefined,
(error) => {
echo.error(`[IndexedDB] Error loading ${asset.modelName}:`);
URL.revokeObjectURL(blobUrl);
}
);
return;
}
// Fetch from Backend
const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${assetId}`;
loader.load(
modelUrl,
(gltf: GLTF) => {
fetch(modelUrl)
.then((response) => response.blob())
.then((modelBlob) => storeGLTF(assetId, modelBlob))
.then(() => {
THREE.Cache.add(assetId, gltf); THREE.Cache.add(assetId, gltf);
setGltfScene(gltf.scene.clone()); setGltfScene(gltf.scene.clone());
calculateBoundingBox(gltf.scene); calculateBoundingBox(gltf.scene);
logModelStatus(assetId, 'backend-loaded'); logModelStatus(assetId, "indexedDB-loaded");
}) },
.catch((error) => { undefined,
console.error( () => {
`[Backend] Error storing/loading ${asset.modelName}:`, echo.error(`[IndexedDB] Error loading ${asset.modelName}:`);
error URL.revokeObjectURL(blobUrl);
); }
}); );
}, return;
undefined,
(error) => {
echo.error(`[Backend] Error loading ${asset.modelName}:`);
} }
);
}).catch((err) => { // Fetch from Backend
console.error("Failed to load model:", asset.assetId, err); const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${assetId}`;
}); loader.load(
modelUrl,
(gltf: GLTF) => {
fetch(modelUrl)
.then((response) => response.blob())
.then((modelBlob) => storeGLTF(assetId, modelBlob))
.then(() => {
THREE.Cache.add(assetId, gltf);
setGltfScene(gltf.scene.clone());
calculateBoundingBox(gltf.scene);
logModelStatus(assetId, "backend-loaded");
})
.catch((error) => {
console.error(`[Backend] Error storing/loading ${asset.modelName}:`, error);
});
},
undefined,
() => {
echo.error(`[Backend] Error loading ${asset.modelName}:`);
}
);
})
.catch((err) => {
console.error("Failed to load model:", asset.assetId, err);
});
}, []); }, []);
const { handleDblClick, handleClick, handlePointerOver, handlePointerOut, handleContextMenu } = useModelEventHandlers({ boundingBox, groupRef, asset }); const { handleDblClick, handleClick, handlePointerOver, handlePointerOut, handleContextMenu } = useModelEventHandlers({ boundingBox, groupRef, asset });
@@ -164,7 +163,7 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
return ( return (
<group <group
key={asset.modelUuid} key={asset.modelUuid}
name='Asset Model' name="Asset Model"
ref={groupRef} ref={groupRef}
uuid={asset.modelUuid} uuid={asset.modelUuid}
position={asset.position} position={asset.position}
@@ -206,22 +205,14 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
<> <>
{isRendered ? ( {isRendered ? (
<> <>
<primitive object={gltfScene} /> <primitive object={gltfScene} />
<ModelAnimator asset={asset} gltfScene={gltfScene} /> <ModelAnimator asset={asset} gltfScene={gltfScene} />
</> </>
) : ( ) : (
<> <>{!isSelected && <AssetBoundingBox name="Asset Fallback" boundingBox={boundingBox} color="gray" lineWidth={2.5} />}</>
{!isSelected &&
<AssetBoundingBox name='Asset Fallback' boundingBox={boundingBox} color='gray' lineWidth={2.5} />
}
</>
)} )}
{isSelected && {isSelected && <AssetBoundingBox name="Asset BBox" boundingBox={boundingBox} color={savedTheme === "dark" ? "#c4abf1" : "#6f42c1"} lineWidth={2.7} />}
<AssetBoundingBox name='Asset BBox' boundingBox={boundingBox} color={savedTheme === "dark" ? "#c4abf1" : "#6f42c1"} lineWidth={2.7} />
}
</> </>
)} )}
</group> </group>

View File

@@ -1,13 +1,13 @@
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useThree, useFrame } from "@react-three/fiber"; import { useThree, useFrame } from "@react-three/fiber";
import { Group, Vector3 } from "three"; import { Group, Vector3 } from "three";
import { CameraControls } from '@react-three/drei'; import { CameraControls } from "@react-three/drei";
import { useLimitDistance, useRenderDistance } from '../../../../store/builder/store'; import { useLimitDistance, useRenderDistance } from "../../../../store/builder/store";
import { useSelectedAsset } from '../../../../store/simulation/useSimulationStore'; import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
import { useSceneContext } from '../../../scene/sceneContext'; import { useSceneContext } from "../../../scene/sceneContext";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore"; import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import Model from './model/model'; import Model from "./model/model";
import { GLTFLoader } from "three/examples/jsm/Addons"; import { GLTFLoader } from "three/examples/jsm/Addons";
const distanceWorker = new Worker(new URL("../../../../services/factoryBuilder/webWorkers/distanceWorker.js", import.meta.url)); const distanceWorker = new Worker(new URL("../../../../services/factoryBuilder/webWorkers/distanceWorker.js", import.meta.url));
@@ -15,7 +15,7 @@ const distanceWorker = new Worker(new URL("../../../../services/factoryBuilder/w
function Models({ loader }: { readonly loader: GLTFLoader }) { function Models({ loader }: { readonly loader: GLTFLoader }) {
const { controls, camera } = useThree(); const { controls, camera } = useThree();
const assetGroupRef = useRef<Group>(null); const assetGroupRef = useRef<Group>(null);
const { assetStore } = useSceneContext(); const { assetStore, layout } = useSceneContext();
const { assets } = assetStore(); const { assets } = assetStore();
const { selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore(); const { selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset(); const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
@@ -40,13 +40,13 @@ function Models({ loader }: { readonly loader: GLTFLoader }) {
camera.getWorldPosition(cameraPos.current); camera.getWorldPosition(cameraPos.current);
for (const asset of assets) { for (const asset of assets) {
const isRendered = renderMap[asset.modelUuid] ?? false; const isRendered = renderMap[asset.modelUuid] ?? false;
distanceWorker.postMessage({ modelUuid: asset.modelUuid, assetPosition: { x: asset.position[0], y: asset.position[1], z: asset.position[2], }, cameraPosition: cameraPos.current, limitDistance, renderDistance, isRendered, }); distanceWorker.postMessage({ modelUuid: asset.modelUuid, assetPosition: { x: asset.position[0], y: asset.position[1], z: asset.position[2] }, cameraPosition: cameraPos.current, limitDistance, renderDistance, isRendered });
} }
}); });
return ( return (
<group <group
name='Asset Group' name="Asset Group"
ref={assetGroupRef} ref={assetGroupRef}
onPointerMissed={(e) => { onPointerMissed={(e) => {
e.stopPropagation(); e.stopPropagation();

View File

@@ -0,0 +1,32 @@
import { useFrame, useThree } from "@react-three/fiber";
import { useSceneContext } from "../sceneContext";
import { CameraControls } from "@react-three/drei";
import { useIsComparing } from "../../../store/builder/store";
import useModuleStore from "../../../store/ui/useModuleStore";
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
import { useSceneStore } from "../../../store/scene/useSceneStore";
import { Vector3 } from "three";
function SyncCam() {
const { layout } = useSceneContext();
const { controls } = useThree();
const { isComparing } = useIsComparing();
const { activeModule } = useModuleStore();
const { comparisonProduct } = useComparisonProduct();
const { setCamera, camState } = useSceneStore();
useFrame(() => {
if (layout === "Comparison Layout" && controls && camState) {
(controls as CameraControls).setLookAt(camState.position.x, camState.position.y, camState.position.z, camState.target.x, camState.target.y, camState.target.z, true);
}
if (layout === "Main Layout" && controls && isComparing && activeModule === "simulation" && comparisonProduct) {
const position = (controls as CameraControls).getPosition(new Vector3());
const target = (controls as CameraControls).getTarget(new Vector3());
setCamera(position, target);
}
});
return <></>;
}
export default SyncCam;

View File

@@ -2,7 +2,7 @@ import { CameraControls } from "@react-three/drei";
import { useRef, useEffect } from "react"; import { useRef, useEffect } from "react";
import { useThree } from "@react-three/fiber"; import { useThree } from "@react-three/fiber";
import * as THREE from "three"; import * as THREE from "three";
import * as CONSTANTS from '../../../types/world/worldConstants'; import * as CONSTANTS from "../../../types/world/worldConstants";
import { useSocketStore, useToggleView, useResetCamera } from "../../../store/builder/store"; import { useSocketStore, useToggleView, useResetCamera } from "../../../store/builder/store";
import CamMode from "../camera/camMode"; import CamMode from "../camera/camMode";
@@ -20,6 +20,7 @@ import { getUserData } from "../../../functions/getUserData";
import { getCameraApi } from "../../../services/factoryBuilder/camera/getCameraApi"; import { getCameraApi } from "../../../services/factoryBuilder/camera/getCameraApi";
import { setCameraApi } from "../../../services/factoryBuilder/camera/setCameraApi"; import { setCameraApi } from "../../../services/factoryBuilder/camera/setCameraApi";
import updateCamPosition from "../camera/functions/updateCameraPosition"; import updateCamPosition from "../camera/functions/updateCameraPosition";
import SyncCam from "../camera/syncCam";
export default function Controls() { export default function Controls() {
const controlsRef = useRef<CameraControls>(null); const controlsRef = useRef<CameraControls>(null);
@@ -38,15 +39,17 @@ export default function Controls() {
} }
if (!projectId) return; if (!projectId) return;
getCameraApi(projectId).then((data) => { getCameraApi(projectId)
if (data?.position && data?.target) { .then((data) => {
controlsRef.current?.setPosition(data.position.x, data.position.y, data.position.z); if (data?.position && data?.target) {
controlsRef.current?.setTarget(data.target.x, data.target.y, data.target.z); controlsRef.current?.setPosition(data.position.x, data.position.y, data.position.z);
} else { controlsRef.current?.setTarget(data.target.x, data.target.y, data.target.z);
controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition); } else {
controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget); controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition);
} controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget);
}).catch((error) => console.error("Failed to fetch camera data:", error)); }
})
.catch((error) => console.error("Failed to fetch camera data:", error));
}, [projectId]); }, [projectId]);
useEffect(() => { useEffect(() => {
@@ -56,12 +59,7 @@ export default function Controls() {
controlsRef.current?.rotateAzimuthTo(CONSTANTS.threeDimension.defaultAzimuth); controlsRef.current?.rotateAzimuthTo(CONSTANTS.threeDimension.defaultAzimuth);
if (!socket?.connected) { if (!socket?.connected) {
setCameraApi( setCameraApi(projectId, new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition), new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget), new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation));
projectId,
new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition),
new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget),
new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation),
)
} else { } else {
const camData = { const camData = {
organization, organization,
@@ -70,9 +68,9 @@ export default function Controls() {
target: new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget), target: new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget),
rotation: new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation), rotation: new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation),
socketId: socket.id, socketId: socket.id,
projectId projectId,
}; };
socket.emit('v1:Camera:set', camData) socket.emit("v1:Camera:set", camData);
} }
setResetCamera(false); setResetCamera(false);
@@ -152,6 +150,7 @@ export default function Controls() {
<CameraShortcutsControls /> <CameraShortcutsControls />
<SyncCam />
</CameraControls> </CameraControls>
<SelectionControls3D /> <SelectionControls3D />
@@ -165,7 +164,6 @@ export default function Controls() {
<TransformControl /> <TransformControl />
<ContextControls /> <ContextControls />
</> </>
); );
} }

View File

@@ -1,13 +1,7 @@
import { useRef, useEffect } from "react"; import { useRef, useEffect } from "react";
import { useThree } from "@react-three/fiber"; import { useThree } from "@react-three/fiber";
import * as THREE from "three"; import * as THREE from "three";
import { import { useAzimuth, useElevation, useShadows, useSunPosition, useTileDistance } from "../../../store/builder/store";
useAzimuth,
useElevation,
useShadows,
useSunPosition,
useTileDistance,
} from "../../../store/builder/store";
import * as CONSTANTS from "../../../types/world/worldConstants"; import * as CONSTANTS from "../../../types/world/worldConstants";
const shadowWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/shadowWorker", import.meta.url)); const shadowWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/shadowWorker", import.meta.url));
@@ -67,31 +61,11 @@ export default function Shadows() {
{/* {(lightRef.current?.shadow) && {/* {(lightRef.current?.shadow) &&
<cameraHelper visible={shadows} args={[lightRef.current.shadow.camera]} /> <cameraHelper visible={shadows} args={[lightRef.current.shadow.camera]} />
} */} } */}
<directionalLight <directionalLight ref={lightRef} castShadow={shadows} shadow-mapSize-width={CONSTANTS.shadowConfig.shadowmapSizewidth} shadow-mapSize-height={CONSTANTS.shadowConfig.shadowmapSizeheight} shadow-camera-far={CONSTANTS.shadowConfig.shadowcamerafar} shadow-camera-near={CONSTANTS.shadowConfig.shadowcameranear} shadow-camera-top={CONSTANTS.shadowConfig.shadowcameratop} shadow-camera-bottom={CONSTANTS.shadowConfig.shadowcamerabottom} shadow-camera-left={CONSTANTS.shadowConfig.shadowcameraleft} shadow-camera-right={CONSTANTS.shadowConfig.shadowcameraright} shadow-bias={CONSTANTS.shadowConfig.shadowbias} shadow-normalBias={CONSTANTS.shadowConfig.shadownormalBias} />
ref={lightRef}
castShadow={shadows}
shadow-mapSize-width={CONSTANTS.shadowConfig.shadowmapSizewidth}
shadow-mapSize-height={CONSTANTS.shadowConfig.shadowmapSizeheight}
shadow-camera-far={CONSTANTS.shadowConfig.shadowcamerafar}
shadow-camera-near={CONSTANTS.shadowConfig.shadowcameranear}
shadow-camera-top={CONSTANTS.shadowConfig.shadowcameratop}
shadow-camera-bottom={CONSTANTS.shadowConfig.shadowcamerabottom}
shadow-camera-left={CONSTANTS.shadowConfig.shadowcameraleft}
shadow-camera-right={CONSTANTS.shadowConfig.shadowcameraright}
shadow-bias={CONSTANTS.shadowConfig.shadowbias}
shadow-normalBias={CONSTANTS.shadowConfig.shadownormalBias}
/>
<object3D ref={targetRef} /> <object3D ref={targetRef} />
<mesh <mesh position={CONSTANTS.shadowConfig.shadowMaterialPosition} rotation={CONSTANTS.shadowConfig.shadowMaterialRotation} receiveShadow>
position={CONSTANTS.shadowConfig.shadowMaterialPosition}
rotation={CONSTANTS.shadowConfig.shadowMaterialRotation}
receiveShadow
>
<planeGeometry args={[planeValue.width, planeValue.height]} /> <planeGeometry args={[planeValue.width, planeValue.height]} />
<shadowMaterial <shadowMaterial opacity={CONSTANTS.shadowConfig.shadowMaterialOpacity} transparent />
opacity={CONSTANTS.shadowConfig.shadowMaterialOpacity}
transparent
/>
</mesh> </mesh>
</> </>
); );

View File

@@ -8,12 +8,7 @@ type SocketStore = {
dashBoardSocket?: ReturnType<typeof io> | null; dashBoardSocket?: ReturnType<typeof io> | null;
projectSocket?: ReturnType<typeof io> | null; projectSocket?: ReturnType<typeof io> | null;
threadSocket?: ReturnType<typeof io> | null; threadSocket?: ReturnType<typeof io> | null;
initializeSocket: ( initializeSocket: (email?: string, organization?: string, token?: string, refreshToken?: string) => void;
email?: string,
organization?: string,
token?: string,
refreshToken?: string
) => void;
disconnectSocket: () => void; disconnectSocket: () => void;
}; };
@@ -23,54 +18,34 @@ export const useSocketStore = create<SocketStore>((set, get) => ({
dashBoardSocket: null, dashBoardSocket: null,
projectSocket: null, projectSocket: null,
threadSocket: null, threadSocket: null,
initializeSocket: ( initializeSocket: (email?: string, organization?: string, token?: string, refreshToken?: string) => {
email?: string,
organization?: string,
token?: string,
refreshToken?: string
) => {
const existingSocket = get().socket; const existingSocket = get().socket;
if (existingSocket) { if (existingSocket) {
return; return;
} }
const socket = io( const socket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder_v1`, {
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder_v1`, reconnection: true,
{ auth: { token, refreshToken },
reconnection: true, });
auth: { token, refreshToken },
}
);
const visualizationSocket = io( const visualizationSocket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization_v1`, {
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization_v1`, reconnection: true,
{ auth: { token, refreshToken },
reconnection: true, });
auth: { token, refreshToken },
}
);
const dashBoardSocket = io( const dashBoardSocket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`, {
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`, reconnection: true,
{ auth: { token, refreshToken },
reconnection: true, });
auth: { token, refreshToken }, const projectSocket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`, {
} reconnection: true,
); auth: { token, refreshToken },
const projectSocket = io( });
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`, const threadSocket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/thread`, {
{ reconnection: true,
reconnection: true, auth: { token, refreshToken },
auth: { token, refreshToken }, });
}
);
const threadSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/thread`,
{
reconnection: true,
auth: { token, refreshToken },
}
);
set({ set({
socket, socket,
@@ -154,8 +129,7 @@ export const useShadows = create<any>((set: any) => ({
export const useSunPosition = create<any>((set: any) => ({ export const useSunPosition = create<any>((set: any) => ({
sunPosition: { x: undefined, y: undefined, z: undefined }, sunPosition: { x: undefined, y: undefined, z: undefined },
setSunPosition: (newSuntPosition: any) => setSunPosition: (newSuntPosition: any) => set({ sunPosition: newSuntPosition }),
set({ sunPosition: newSuntPosition }),
})); }));
export const useProjectName = create<any>((set: any) => ({ export const useProjectName = create<any>((set: any) => ({
@@ -215,14 +189,12 @@ export const useRenameModeStore = create<any>((set: any) => ({
export const useObjectPosition = create<any>((set: any) => ({ export const useObjectPosition = create<any>((set: any) => ({
objectPosition: { x: undefined, y: undefined, z: undefined }, objectPosition: { x: undefined, y: undefined, z: undefined },
setObjectPosition: (newObjectPosition: any) => setObjectPosition: (newObjectPosition: any) => set({ objectPosition: newObjectPosition }),
set({ objectPosition: newObjectPosition }),
})); }));
export const useObjectRotation = create<any>((set: any) => ({ export const useObjectRotation = create<any>((set: any) => ({
objectRotation: { x: undefined, y: undefined, z: undefined }, objectRotation: { x: undefined, y: undefined, z: undefined },
setObjectRotation: (newObjectRotation: any) => setObjectRotation: (newObjectRotation: any) => set({ objectRotation: newObjectRotation }),
set({ objectRotation: newObjectRotation }),
})); }));
export const useDrieTemp = create<any>((set: any) => ({ export const useDrieTemp = create<any>((set: any) => ({
@@ -234,16 +206,14 @@ export const useActiveUsers = create<any>((set: any) => ({
activeUsers: [], activeUsers: [],
setActiveUsers: (callback: (prev: any[]) => any[] | any[]) => setActiveUsers: (callback: (prev: any[]) => any[] | any[]) =>
set((state: { activeUsers: any[] }) => ({ set((state: { activeUsers: any[] }) => ({
activeUsers: activeUsers: typeof callback === "function" ? callback(state.activeUsers) : callback,
typeof callback === "function" ? callback(state.activeUsers) : callback,
})), })),
})); }));
export const useDrieUIValue = create<any>((set: any) => ({ export const useDrieUIValue = create<any>((set: any) => ({
drieUIValue: { touch: null, temperature: null, humidity: null }, drieUIValue: { touch: null, temperature: null, humidity: null },
setDrieUIValue: (x: any) => setDrieUIValue: (x: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })),
set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })),
setTouch: (value: any) => setTouch: (value: any) =>
set((state: any) => ({ set((state: any) => ({
@@ -367,8 +337,7 @@ interface ShortcutStore {
export const useShortcutStore = create<ShortcutStore>((set) => ({ export const useShortcutStore = create<ShortcutStore>((set) => ({
showShortcuts: false, showShortcuts: false,
setShowShortcuts: (value) => set({ showShortcuts: value }), setShowShortcuts: (value) => set({ showShortcuts: value }),
toggleShortcuts: () => toggleShortcuts: () => set((state) => ({ showShortcuts: !state.showShortcuts })),
set((state) => ({ showShortcuts: !state.showShortcuts })),
})); }));
export const useMachineCount = create<any>((set: any) => ({ export const useMachineCount = create<any>((set: any) => ({
@@ -470,19 +439,18 @@ interface CompareStore {
export const useCompareStore = create<CompareStore>((set) => ({ export const useCompareStore = create<CompareStore>((set) => ({
comparePopUp: false, comparePopUp: false,
setComparePopUp: (value) => set({ comparePopUp: value }), setComparePopUp: (value) => set({ comparePopUp: value }),
toggleComparePopUp: () => toggleComparePopUp: () => set((state) => ({ comparePopUp: !state.comparePopUp })),
set((state) => ({ comparePopUp: !state.comparePopUp })),
})); }));
// Save state store // Save state store
interface SaveVersionStore { interface IsComparingStore {
isVersionSaved: boolean; isComparing: boolean;
setIsVersionSaved: (value: boolean) => void; setIsComparing: (value: boolean) => void;
} }
export const useSaveVersion = create<SaveVersionStore>((set) => ({ export const useIsComparing = create<IsComparingStore>((set) => ({
isVersionSaved: false, isComparing: false,
setIsVersionSaved: (value: boolean) => set({ isVersionSaved: value }), setIsComparing: (value: boolean) => set({ isComparing: value }),
})); }));
interface ViewSceneState { interface ViewSceneState {
@@ -494,8 +462,7 @@ export const useViewSceneStore = create<ViewSceneState>((set) => ({
viewSceneLabels: getInitialViewSceneLabels(), viewSceneLabels: getInitialViewSceneLabels(),
setViewSceneLabels: (value) => { setViewSceneLabels: (value) => {
set((state) => { set((state) => {
const newValue = const newValue = typeof value === "function" ? value(state.viewSceneLabels) : value;
typeof value === "function" ? value(state.viewSceneLabels) : value;
// Store in localStorage manually // Store in localStorage manually
localStorage.setItem("viewSceneLabels", JSON.stringify(newValue)); localStorage.setItem("viewSceneLabels", JSON.stringify(newValue));

View File

@@ -0,0 +1,27 @@
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
import * as THREE from "three";
type SceneStore = {
camState: {
position: THREE.Vector3;
target: THREE.Vector3;
};
setCamera: (pos: THREE.Vector3, target: THREE.Vector3) => void;
};
export const useSceneStore = create<SceneStore>()(
immer((set) => ({
camState: {
position: new THREE.Vector3(0, 5, 10),
target: new THREE.Vector3(0, 0, 0),
},
setCamera: (pos, target) =>
set((state) => {
state.camState.position.copy(pos);
state.camState.target.copy(target);
}),
}))
);

View File

@@ -1,7 +1,7 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import useModuleStore, { useSubModuleStore, useThreeDStore } from "../../store/ui/useModuleStore"; import useModuleStore, { useSubModuleStore, useThreeDStore } from "../../store/ui/useModuleStore";
import { usePlayerStore, useToggleStore } from "../../store/ui/useUIToggleStore"; import { usePlayerStore, useToggleStore } from "../../store/ui/useUIToggleStore";
import useVersionHistoryVisibleStore, { useActiveSubTool, useActiveTool, useAddAction, useDfxUpload, useRenameModeStore, useSaveVersion, useSelectedComment, useShortcutStore, useToggleView, useToolMode, useViewSceneStore } from "../../store/builder/store"; import useVersionHistoryVisibleStore, { useActiveSubTool, useActiveTool, useAddAction, useDfxUpload, useRenameModeStore, useIsComparing, useSelectedComment, useShortcutStore, useToggleView, useToolMode, useViewSceneStore } from "../../store/builder/store";
import useCameraModeStore, { usePlayButtonStore } from "../../store/ui/usePlayButtonStore"; import useCameraModeStore, { usePlayButtonStore } from "../../store/ui/usePlayButtonStore";
import { detectModifierKeys } from "./detectModifierKeys"; import { detectModifierKeys } from "./detectModifierKeys";
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore"; import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
@@ -27,7 +27,7 @@ const KeyPressListener: React.FC = () => {
const { clearSelectedZone } = useSelectedZoneStore(); const { clearSelectedZone } = useSelectedZoneStore();
const { showShortcuts, setShowShortcuts } = useShortcutStore(); const { showShortcuts, setShowShortcuts } = useShortcutStore();
const { setWalkMode } = useCameraModeStore(); const { setWalkMode } = useCameraModeStore();
const { setIsVersionSaved } = useSaveVersion(); const { setIsComparing } = useIsComparing();
const { isLogListVisible, setIsLogListVisible } = useLogger(); const { isLogListVisible, setIsLogListVisible } = useLogger();
const { hidePlayer, setHidePlayer } = usePlayerStore(); const { hidePlayer, setHidePlayer } = usePlayerStore();
const { setViewSceneLabels } = useViewSceneStore(); const { setViewSceneLabels } = useViewSceneStore();
@@ -177,7 +177,7 @@ const KeyPressListener: React.FC = () => {
setIsPlaying(false); setIsPlaying(false);
clearSelectedZone(); clearSelectedZone();
setShowShortcuts(false); setShowShortcuts(false);
setIsVersionSaved(false); setIsComparing(false);
clearComparisonProduct(); clearComparisonProduct();
setIsLogListVisible(false); setIsLogListVisible(false);
setIsRenameMode(false); setIsRenameMode(false);