Refactor asset management to use scene context

- Updated MainSceneProvider to clear assets on mount using scene context.
- Replaced useAssetsStore with useSceneContext in DropDownList, List, AssetsGroup, Model, Models, SocketResponses, and various control components.
- Introduced clearAssets method in asset store for better asset management.
- Updated Project component to wrap scene providers correctly.
- Fixed naming inconsistencies in vehicle store methods.
- Removed unnecessary state management in MaterialAnimator.
- Improved code readability and organization across multiple components.
This commit is contained in:
2025-06-18 18:13:53 +05:30
parent e1213e6929
commit e61f860d21
23 changed files with 343 additions and 289 deletions

View File

@@ -1,7 +1,16 @@
import { useEffect } from 'react';
import { ProductProvider } from '../../../modules/simulation/products/productContext'
import ComparisonScene from './ComparisonScene';
import { useSceneContext } from '../../../modules/scene/sceneContext';
function ComparisonSceneProvider() {
const { assetStore } = useSceneContext();
const { clearAssets } = assetStore();
useEffect(() => {
clearAssets();
}, [])
return (
<ProductProvider>
<ComparisonScene />

View File

@@ -34,9 +34,9 @@ import { useProductStore } from "../../../store/simulation/useProductStore";
import RegularDropDown from "../../ui/inputs/RegularDropDown";
import RenameTooltip from "../../ui/features/RenameTooltip";
import { setFloorItemApi } from "../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
import { useAssetsStore } from "../../../store/builder/useAssetStore";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../functions/getUserData";
import { useSceneContext } from "../../../modules/scene/sceneContext";
function MainScene() {
const { products } = useProductStore();
@@ -55,10 +55,11 @@ function MainScene() {
const { setFloatingWidget } = useFloatingWidget();
const { clearComparisonProduct } = useComparisonProduct();
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
const { setName } = useAssetsStore();
const { assetStore } = useSceneContext();
const { setName } = assetStore();
const { projectId } = useParams()
const { isRenameMode, setIsRenameMode } = useRenameModeStore();
const { userName, userId, organization, email } = getUserData();
const { organization } = getUserData();
useEffect(() => {
if (activeModule !== 'simulation') {

View File

@@ -1,7 +1,16 @@
import { useEffect } from 'react'
import { ProductProvider } from '../../../modules/simulation/products/productContext'
import MainScene from './MainScene'
import { useSceneContext } from '../../../modules/scene/sceneContext';
function MainSceneProvider() {
const { assetStore } = useSceneContext();
const { clearAssets } = assetStore();
useEffect(() => {
clearAssets();
}, [])
return (
<ProductProvider>
<MainScene />

View File

@@ -3,7 +3,7 @@ import List from "./List";
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
import { useZones } from "../../../store/builder/store";
import { useAssetsStore } from "../../../store/builder/useAssetStore";
import { useSceneContext } from "../../../modules/scene/sceneContext";
interface DropDownListProps {
value?: string; // Value to display in the DropDownList
@@ -51,8 +51,9 @@ const DropDownList: React.FC<DropDownListProps> = ({
};
const [zoneDataList, setZoneDataList] = useState<ZoneData[]>([]);
const { assets } = useAssetsStore();
const { assetStore } = useSceneContext();
const { assets } = assetStore();
const isPointInsidePolygon = (
point: [number, number],
polygon: [number, number][]
@@ -129,7 +130,7 @@ const DropDownList: React.FC<DropDownListProps> = ({
title="collapse-btn"
className="collapse-icon option"
style={{ transform: isOpen ? "rotate(0deg)" : "rotate(-90deg)" }}
// onClick={handleToggle}
// onClick={handleToggle}
>
<ArrowIcon />
</button>

View File

@@ -19,8 +19,8 @@ import {
import { zoneCameraUpdate } from "../../../services/visulization/zone/zoneCameraUpdation";
import { setFloorItemApi } from "../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
import { useParams } from "react-router-dom";
import { useAssetsStore } from "../../../store/builder/useAssetStore";
import { getUserData } from "../../../functions/getUserData";
import { useSceneContext } from "../../../modules/scene/sceneContext";
interface Asset {
id: string;
@@ -47,13 +47,12 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
const { zones, setZones } = useZones();
const { setSubModule } = useSubModuleStore();
const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>(
{}
);
const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>({});
const { projectId } = useParams();
const { assetStore } = useSceneContext();
const { setName } = assetStore();
const { organization } = getUserData();
const { setName } = useAssetsStore();
const { userName, userId, organization, email } = getUserData();
useEffect(() => {
useSelectedZoneStore.getState().setSelectedZone({
zoneName: "",
@@ -82,7 +81,6 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
setSubModule("zoneProperties");
let response = await getZoneData(id, organization, projectId);
setSelectedZone({
zoneName: response?.zoneName,
@@ -99,6 +97,7 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
console.log(error);
}
}
function handleAssetClick(asset: Asset) {
setZoneAssetId(asset);
}
@@ -141,7 +140,6 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
projectId
);
// console.log("response: ", response);
console.log(' zoneAssetId.id,: ', zoneAssetId.id,);
setName(zoneAssetId.id, response.modelName);
}

View File

@@ -5,7 +5,6 @@ import { useLoadingProgress, useRenameModeStore, useSelectedFloorItem, useSelect
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import { FloorItems, RefGroup, RefMesh } from "../../../types/world/worldTypes";
import { useAssetsStore } from "../../../store/builder/useAssetStore";
import { useEventsStore } from "../../../store/simulation/useEventsStore";
import Models from "./models/models";
import useModuleStore from "../../../store/useModuleStore";
@@ -15,6 +14,7 @@ import addAssetModel from "./functions/addAssetModel";
import { useParams } from "react-router-dom";
import { useLeftData, useTopData } from "../../../store/visualization/useZone3DWidgetStore";
import { getUserData } from "../../../functions/getUserData";
import { useSceneContext } from "../../scene/sceneContext";
const gltfLoaderWorker = new Worker(
new URL(
@@ -28,13 +28,14 @@ function AssetsGroup({ floorGroup, plane }: { readonly floorGroup: RefGroup, rea
const { socket } = useSocketStore();
const { controls, gl, pointer, camera, raycaster } = useThree();
const { setLoadingProgress } = useLoadingProgress();
const { setAssets, addAsset } = useAssetsStore();
const { assetStore } = useSceneContext();
const { setAssets, addAsset } = assetStore();
const { addEvent } = useEventsStore();
const { setSelectedFloorItem } = useSelectedFloorItem();
const { selectedItem, setSelectedItem } = useSelectedItem();
const { projectId } = useParams();
const { isRenameMode, setIsRenameMode } = useRenameModeStore();
const { userId, organization, email } = getUserData();
const { userId, organization } = getUserData();
const { setTop } = useTopData();
const { setLeft } = useLeftData();

View File

@@ -7,7 +7,6 @@ import { ThreeEvent, useFrame, useThree } from '@react-three/fiber';
import { useActiveTool, useDeletableFloorItem, useRenderDistance, useSelectedFloorItem, useSocketStore, useToggleView, useToolMode } from '../../../../../store/builder/store';
import { AssetBoundingBox } from '../../functions/assetBoundingBox';
import { CameraControls } from '@react-three/drei';
import { useAssetsStore } from '../../../../../store/builder/useAssetStore';
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import useModuleStore, { useSubModuleStore } from '../../../../../store/useModuleStore';
@@ -16,6 +15,7 @@ import { useSelectedAsset } from '../../../../../store/simulation/useSimulationS
import { useProductContext } from '../../../../simulation/products/productContext';
import { useParams } from 'react-router-dom';
import { getUserData } from '../../../../../functions/getUserData';
import { useSceneContext } from '../../../../scene/sceneContext';
function Model({ asset }: { readonly asset: Asset }) {
const { camera, controls, gl } = useThree();
@@ -23,7 +23,8 @@ function Model({ asset }: { readonly asset: Asset }) {
const { toggleView } = useToggleView();
const { subModule } = useSubModuleStore();
const { activeModule } = useModuleStore();
const { removeAsset } = useAssetsStore();
const { assetStore } = useSceneContext();
const { removeAsset } = assetStore();
const { setTop } = useTopData();
const { setLeft } = useLeftData();
const { getIsEventInProduct } = useProductStore();

View File

@@ -1,14 +1,15 @@
import { useAssetsStore } from '../../../../store/builder/useAssetStore';
import Model from './model/model';
import { useThree } from '@react-three/fiber';
import { CameraControls } from '@react-three/drei';
import { Vector3 } from 'three';
import { useSelectedFloorItem } from '../../../../store/builder/store';
import { useSelectedAsset } from '../../../../store/simulation/useSimulationStore';
import { useSceneContext } from '../../../scene/sceneContext';
function Models() {
const { controls } = useThree();
const { assets } = useAssetsStore();
const { assetStore } = useSceneContext();
const { assets } = assetStore();
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();

View File

@@ -32,10 +32,10 @@ import Layer2DVisibility from "../../builder/geomentries/layers/layer2DVisibilit
import { retrieveGLTF, storeGLTF } from "../../../utils/indexDB/idbUtils";
import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi";
import { useParams } from "react-router-dom";
import { useAssetsStore } from "../../../store/builder/useAssetStore";
import { useEventsStore } from "../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../store/simulation/useProductStore";
import { getUserData } from "../../../functions/getUserData";
import { useSceneContext } from "../../scene/sceneContext";
export default function SocketResponses({
floorPlanGroup,
@@ -59,8 +59,10 @@ export default function SocketResponses({
const { zones, setZones } = useZones();
const { zonePoints, setZonePoints } = useZonePoints();
const { projectId } = useParams();
const { addAsset, updateAsset, removeAsset } = useAssetsStore();
const { userId, organization, email } = getUserData();
const { assetStore } = useSceneContext();
const { addAsset, updateAsset, removeAsset } = assetStore();
const { organization } = getUserData();
useEffect(() => {
if (!socket) return;

View File

@@ -7,8 +7,8 @@ import * as Types from "../../../../types/world/worldTypes";
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useParams } from "react-router-dom";
import { useAssetsStore } from "../../../../store/builder/useAssetStore";
import { getUserData } from "../../../../functions/getUserData";
import { useSceneContext } from "../../sceneContext";
const CopyPasteControls = ({
copiedObjects,
@@ -30,8 +30,9 @@ const CopyPasteControls = ({
const { socket } = useSocketStore();
const { addEvent } = useEventsStore();
const { projectId } = useParams();
const { assets, addAsset } = useAssetsStore();
const { userId, organization, email } = getUserData();
const { assetStore } = useSceneContext();
const { assets, addAsset } = assetStore();
const { userId, organization } = getUserData();
useEffect(() => {
if (!camera || !scene || toggleView) return;

View File

@@ -7,8 +7,8 @@ import * as Types from "../../../../types/world/worldTypes";
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useParams } from "react-router-dom";
import { useAssetsStore } from "../../../../store/builder/useAssetStore";
import { getUserData } from "../../../../functions/getUserData";
import { useSceneContext } from "../../sceneContext";
const DuplicationControls = ({
duplicatedObjects,
@@ -28,8 +28,9 @@ const DuplicationControls = ({
const { socket } = useSocketStore();
const { addEvent } = useEventsStore();
const { projectId } = useParams();
const { assets, addAsset } = useAssetsStore();
const { userId, organization, email } = getUserData();
const { assetStore } = useSceneContext();
const { assets, addAsset } = assetStore();
const { userId, organization } = getUserData();
useEffect(() => {
if (!camera || !scene || toggleView) return;

View File

@@ -11,9 +11,9 @@ import { upsertProductOrEventApi } from "../../../../services/simulation/product
import { snapControls } from "../../../../utils/handleSnap";
import DistanceFindingControls from "./distanceFindingControls";
import { useParams } from "react-router-dom";
import { useAssetsStore } from "../../../../store/builder/useAssetStore";
import { useProductContext } from "../../../simulation/products/productContext";
import { getUserData } from "../../../../functions/getUserData";
import { useSceneContext } from "../../sceneContext";
function MoveControls({
movedObjects,
@@ -36,9 +36,10 @@ function MoveControls({
const { selectedProduct } = selectedProductStore();
const { socket } = useSocketStore();
const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">("");
const { userId, organization, email } = getUserData();
const { userId, organization } = getUserData();
const { projectId } = useParams();
const { updateAsset } = useAssetsStore();
const { assetStore } = useSceneContext();
const { updateAsset } = assetStore();
const AssetGroup = useRef<THREE.Group | undefined>(undefined);
const updateBackend = (

View File

@@ -8,9 +8,9 @@ import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
import { useParams } from "react-router-dom";
import { useAssetsStore } from "../../../../store/builder/useAssetStore";
import { useProductContext } from "../../../simulation/products/productContext";
import { getUserData } from "../../../../functions/getUserData";
import { useSceneContext } from "../../sceneContext";
function RotateControls({
rotatedObjects,
@@ -32,9 +32,10 @@ function RotateControls({
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { socket } = useSocketStore();
const { userId, organization, email } = getUserData();
const { userId, organization } = getUserData();
const { projectId } = useParams();
const { updateAsset } = useAssetsStore();
const { assetStore } = useSceneContext();
const { updateAsset } = assetStore();
const AssetGroup = useRef<THREE.Group | undefined>(undefined);
const updateBackend = (

View File

@@ -16,8 +16,8 @@ import useModuleStore from "../../../../store/useModuleStore";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useParams } from "react-router-dom";
import { useAssetsStore } from "../../../../store/builder/useAssetStore";
import { getUserData } from "../../../../functions/getUserData";
import { useSceneContext } from "../../sceneContext";
const SelectionControls: React.FC = () => {
const { camera, controls, gl, scene, raycaster, pointer } = useThree();
@@ -32,7 +32,8 @@ const SelectionControls: React.FC = () => {
const boundingBoxRef = useRef<THREE.Mesh>();
const { activeModule } = useModuleStore();
const { socket } = useSocketStore();
const { removeAsset } = useAssetsStore();
const { assetStore } = useSceneContext();
const { removeAsset } = assetStore();
const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]);
const { toolMode } = useToolMode();
const { projectId } = useParams();

View File

@@ -8,11 +8,11 @@ import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifie
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
// import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
import { useParams } from "react-router-dom";
import { useAssetsStore } from "../../../../store/builder/useAssetStore";
import { useProductContext } from "../../../simulation/products/productContext";
import { getUserData } from "../../../../functions/getUserData";
import { useSceneContext } from "../../sceneContext";
export default function TransformControl() {
const state = useThree();
@@ -24,8 +24,9 @@ export default function TransformControl() {
const { socket } = useSocketStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { updateAsset, getAssetById } = useAssetsStore();
const { userId, organization, email } = getUserData();
const { assetStore } = useSceneContext();
const { updateAsset, getAssetById } = assetStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
const updateBackend = (

View File

@@ -1,7 +1,7 @@
import { useEffect, useMemo } from "react";
import { Canvas } from "@react-three/fiber";
import { KeyboardControls } from "@react-three/drei";
import { SceneProvider } from "./sceneContext";
import { SceneProvider, useSceneContext } from "./sceneContext";
import Builder from "../builder/builder";
import Visualization from "../visualization/visualization";
@@ -13,7 +13,6 @@ import { useParams } from "react-router-dom";
import { getAllProjects } from "../../services/dashboard/getAllProjects";
import { getUserData } from "../../functions/getUserData";
import { useLoadingProgress, useSocketStore } from "../../store/builder/store";
import { useAssetsStore } from "../../store/builder/useAssetStore";
import { Color } from "three";
export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Comparison Layout' }) {
@@ -23,12 +22,14 @@ export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Co
{ name: "left", keys: ["ArrowLeft", "a", "A"] },
{ name: "right", keys: ["ArrowRight", "d", "D"] },
], []);
const { assets } = useAssetsStore();
const { assetStore } = useSceneContext();
const { assets } = assetStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
const { projectSocket } = useSocketStore();
const { activeModule } = useModuleStore();
const { loadingProgress } = useLoadingProgress();
const handleUpdatingProject = async () => {
if (!projectId && loadingProgress > 1) return;
try {
@@ -51,33 +52,32 @@ export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Co
}
} catch (error) { }
};
useEffect(() => {
handleUpdatingProject()
}, [activeModule, assets, loadingProgress])
return (
<SceneProvider layout={layout}>
<KeyboardControls map={map}>
<Canvas
id="sceneCanvas"
shadows
color="#aaaa"
eventPrefix="client"
onContextMenu={(e) => {
e.preventDefault();
}}
onCreated={(e) => {
e.scene.background = layout === 'Main Layout' ? null : new Color(0x19191d);
}}
gl={{ powerPreference: "high-performance", antialias: true, preserveDrawingBuffer: true }}
>
<Setup />
<Collaboration />
<Builder />
<Simulation />
<Visualization />
</Canvas>
</KeyboardControls>
</SceneProvider>
<KeyboardControls map={map}>
<Canvas
id="sceneCanvas"
shadows
color="#aaaa"
eventPrefix="client"
onContextMenu={(e) => {
e.preventDefault();
}}
onCreated={(e) => {
e.scene.background = layout === 'Main Layout' ? null : new Color(0x19191d);
}}
gl={{ powerPreference: "high-performance", antialias: true, preserveDrawingBuffer: true }}
>
<Setup />
<Collaboration />
<Builder />
<Simulation />
<Visualization />
</Canvas>
</KeyboardControls>
);
}

View File

@@ -1,4 +1,7 @@
import { createContext, useContext, useMemo } from 'react';
import { createAssetStore, AssetStoreType } from '../../store/builder/useAssetStore';
import { createMaterialStore, MaterialStoreType } from '../../store/simulation/useMaterialStore';
import { createArmBotStore, ArmBotStoreType } from '../../store/simulation/useArmBotStore';
import { createMachineStore, MachineStoreType } from '../../store/simulation/useMachineStore';
@@ -7,6 +10,9 @@ import { createVehicleStore, VehicleStoreType } from '../../store/simulation/use
import { createStorageUnitStore, StorageUnitStoreType } from '../../store/simulation/useStorageUnitStore';
type SceneContextValue = {
assetStore: AssetStoreType,
materialStore: MaterialStoreType;
armBotStore: ArmBotStoreType;
machineStore: MachineStoreType;
@@ -25,6 +31,9 @@ export function SceneProvider({
readonly children: React.ReactNode;
readonly layout: 'Main Layout' | 'Comparison Layout';
}) {
const assetStore = useMemo(() => createAssetStore(), []);
const materialStore = useMemo(() => createMaterialStore(), []);
const armBotStore = useMemo(() => createArmBotStore(), []);
const machineStore = useMemo(() => createMachineStore(), []);
@@ -32,17 +41,23 @@ export function SceneProvider({
const vehicleStore = useMemo(() => createVehicleStore(), []);
const storageUnitStore = useMemo(() => createStorageUnitStore(), []);
const clearStores = useMemo(() => () => {
assetStore().clearAssets();
}, [assetStore]);
const contextValue = useMemo(() => (
{
assetStore,
materialStore,
armBotStore,
machineStore,
conveyorStore,
vehicleStore,
storageUnitStore,
clearStores,
layout
}
), [materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, layout]);
), [assetStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, clearStores, layout]);
return (
<SceneContext.Provider value={contextValue}>

View File

@@ -15,7 +15,7 @@ function Products() {
const { selectedProductStore } = useProductContext();
const { setMainProduct } = useMainProduct();
const { selectedProduct, setSelectedProduct } = selectedProductStore();
const { addVehicle, clearvehicles } = vehicleStore();
const { addVehicle, clearVehicles } = vehicleStore();
const { addArmBot, clearArmBots } = armBotStore();
const { addMachine, clearMachines } = machineStore();
const { addConveyor, clearConveyors } = conveyorStore();
@@ -68,7 +68,7 @@ function Products() {
if (selectedProduct.productUuid) {
const product = getProductById(selectedProduct.productUuid);
if (product) {
clearvehicles();
clearVehicles();
product.eventDatas.forEach(events => {
if (events.type === 'vehicle') {
addVehicle(selectedProduct.productUuid, events);

View File

@@ -1,23 +1,20 @@
import React, { useEffect, useRef, useState, useMemo } from "react";
import { useRef, useMemo } from "react";
import { MaterialModel } from "../../../materials/instances/material/materialModel";
import { Object3D, Box3, Vector3 } from "three";
import { useThree } from "@react-three/fiber";
import { useLoadingProgress } from "../../../../../store/builder/store";
const MaterialAnimator = ({
storage,
}: Readonly<{ storage: StorageUnitStatus }>) => {
const meshRef = useRef<any>(null!);
const [hasLoad, setHasLoad] = useState(false);
const { scene } = useThree();
const padding = 0.1;
useEffect(() => {
setHasLoad(storage.currentLoad > 0);
}, [storage.currentLoad]);
const { loadingProgress } = useLoadingProgress();
const storageModel = useMemo(() => {
return scene.getObjectByProperty("uuid", storage.modelUuid) as Object3D;
}, [scene, storage.modelUuid]);
}, [scene, storage.modelUuid, loadingProgress]);
const materialPositions = useMemo(() => {
if (!storageModel || storage.currentMaterials.length === 0) return [];
@@ -59,16 +56,15 @@ const MaterialAnimator = ({
return (
<group {...{ position: [0, -padding, 0] }}>
{hasLoad &&
storage.currentMaterials.map((mat, index) => (
<MaterialModel
key={`${index}-${mat.materialId}`}
materialId={mat.materialId}
matRef={meshRef}
materialType={mat.materialType ?? "Default material"}
position={materialPositions[index]}
/>
))}
{storage.currentMaterials.map((mat, index) => (
<MaterialModel
key={`${index}-${mat.materialId}`}
materialId={mat.materialId}
matRef={meshRef}
materialType={mat.materialType ?? "Default material"}
position={materialPositions[index]}
/>
))}
</group>
);
};

View File

@@ -5,20 +5,21 @@ import { useSceneContext } from "../../../scene/sceneContext";
import { useViewSceneStore } from "../../../../store/builder/store";
function StorageUnitInstances() {
const { storageUnitStore } = useSceneContext();
const { storageUnits } = storageUnitStore();
const { viewSceneLabels } = useViewSceneStore();
const { storageUnitStore } = useSceneContext();
const { storageUnits } = storageUnitStore();
// console.log('storageUnits: ', storageUnits);
const { viewSceneLabels } = useViewSceneStore();
return (
<>
{storageUnits.map((storageUnit: StorageUnitStatus) => (
<React.Fragment key={storageUnit.modelUuid}>
<StorageUnitInstance storageUnit={storageUnit} />
{viewSceneLabels && <StorageContentUi storageUnit={storageUnit} />}
</React.Fragment>
))}
</>
);
return (
<>
{storageUnits.map((storageUnit: StorageUnitStatus) => (
<React.Fragment key={storageUnit.modelUuid}>
<StorageUnitInstance storageUnit={storageUnit} />
{viewSceneLabels && <StorageContentUi storageUnit={storageUnit} />}
</React.Fragment>
))}
</>
);
}
export default StorageUnitInstances;

View File

@@ -21,17 +21,16 @@ import VersionSaved from "../components/layout/sidebarRight/versionHisory/Versio
import { useProductStore } from "../store/simulation/useProductStore";
import { getAllProjects } from "../services/dashboard/getAllProjects";
import { viewProject } from "../services/dashboard/viewProject";
import { useAssetsStore } from "../store/builder/useAssetStore";
import ComparisonSceneProvider from "../components/layout/scenes/ComparisonSceneProvider";
import MainSceneProvider from "../components/layout/scenes/MainSceneProvider";
import { getUserData } from "../functions/getUserData";
import { SceneProvider } from "../modules/scene/sceneContext";
const Project: React.FC = () => {
let navigate = useNavigate();
const echo = useLogger();
const { setToggleUI } = useToggleStore();
const { activeModule, setActiveModule } = useModuleStore();
const { setAssets } = useAssetsStore();
const { setUserName } = useUserName();
const { setOrganization } = useOrganization();
const { setWallItems } = useWallItems();
@@ -69,7 +68,6 @@ const Project: React.FC = () => {
}, [isVersionSaved]);
useEffect(() => {
setAssets([]);
setWallItems([]);
setZones([]);
setProducts([]);
@@ -92,8 +90,12 @@ const Project: React.FC = () => {
return (
<div className="project-main">
<ComparisonSceneProvider />
<MainSceneProvider />
<SceneProvider layout="Main Layout">
<MainSceneProvider />
</SceneProvider>
<SceneProvider layout="Comparison Layout">
<ComparisonSceneProvider />
</SceneProvider>
{selectedUser && <FollowPerson />}
{isLogListVisible && (
<RenderOverlay>

View File

@@ -8,6 +8,7 @@ interface AssetsStore {
addAsset: (asset: Asset) => void;
removeAsset: (modelUuid: string) => void;
updateAsset: (modelUuid: string, updates: Partial<Asset>) => void;
clearAssets: () => void;
setAssets: (assets: Assets) => void;
// Asset properties
@@ -36,196 +37,206 @@ interface AssetsStore {
hasAsset: (modelUuid: string) => boolean;
}
export const useAssetsStore = create<AssetsStore>()(
immer((set, get) => ({
assets: [],
export const createAssetStore = () => {
return create<AssetsStore>()(
immer((set, get) => ({
assets: [],
// Asset CRUD operations
addAsset: (asset) => {
set((state) => {
if (!state.assets.some(a => a.modelUuid === asset.modelUuid)) {
state.assets.push(asset);
}
});
},
removeAsset: (modelUuid) => {
set((state) => {
state.assets = state.assets.filter(a => a.modelUuid !== modelUuid);
});
},
updateAsset: (modelUuid, updates) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
Object.assign(asset, updates);
}
});
},
setAssets: (assets) => {
set((state) => {
state.assets = assets;
});
},
// Asset properties
setName: (modelUuid, newName) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.modelName = newName;
}
});
},
setPosition: (modelUuid, position) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.position = position;
}
});
},
setRotation: (modelUuid, rotation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.rotation = rotation;
}
});
},
setLock: (modelUuid, isLocked) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.isLocked = isLocked;
}
});
},
setCollision: (modelUuid, isCollidable) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.isCollidable = isCollidable;
}
});
},
setVisibility: (modelUuid, isVisible) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.isVisible = isVisible;
}
});
},
setOpacity: (modelUuid, opacity) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.opacity = opacity;
}
});
},
// Animation controls
setAnimation: (modelUuid, animation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
if (!asset.animationState) {
asset.animationState = { current: animation, playing: false };
} else {
asset.animationState.current = animation;
// Asset CRUD operations
addAsset: (asset) => {
set((state) => {
if (!state.assets.some(a => a.modelUuid === asset.modelUuid)) {
state.assets.push(asset);
}
}
});
},
});
},
setCurrentAnimation: (modelUuid, current, isPlaying) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset?.animationState) {
asset.animationState.current = current;
asset.animationState.playing = isPlaying;
}
});
},
removeAsset: (modelUuid) => {
set((state) => {
state.assets = state.assets.filter(a => a.modelUuid !== modelUuid);
});
},
addAnimation: (modelUuid, animation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
if (!asset.animations) {
asset.animations = [animation];
} else if (!asset.animations.includes(animation)) {
asset.animations.push(animation);
updateAsset: (modelUuid, updates) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
Object.assign(asset, updates);
}
}
});
},
});
},
removeAnimation: (modelUuid, animation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset?.animations) {
asset.animations = asset.animations.filter(a => a !== animation);
if (asset.animationState?.current === animation) {
asset.animationState.playing = false;
asset.animationState.current = '';
clearAssets: () => {
set((state) => {
state.assets = [];
});
},
setAssets: (assets) => {
set((state) => {
state.assets = assets;
});
},
// Asset properties
setName: (modelUuid, newName) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.modelName = newName;
}
}
});
},
});
},
// Event data operations
addEventData: (modelUuid, eventData) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.eventData = eventData;
}
});
},
setPosition: (modelUuid, position) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.position = position;
}
});
},
updateEventData: (modelUuid, updates) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset?.eventData) {
asset.eventData = { ...asset.eventData, ...updates };
}
});
},
setRotation: (modelUuid, rotation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.rotation = rotation;
}
});
},
removeEventData: (modelUuid) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
delete asset.eventData;
}
});
},
setLock: (modelUuid, isLocked) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.isLocked = isLocked;
}
});
},
// Helper functions
getAssetById: (modelUuid) => {
return get().assets.find(a => a.modelUuid === modelUuid);
},
setCollision: (modelUuid, isCollidable) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.isCollidable = isCollidable;
}
});
},
getAssetByPointUuid: (pointUuid) => {
return get().assets.find(asset =>
asset.eventData?.point?.uuid === pointUuid ||
asset.eventData?.points?.some(p => p.uuid === pointUuid)
);
},
setVisibility: (modelUuid, isVisible) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.isVisible = isVisible;
}
});
},
hasAsset: (modelUuid) => {
return get().assets.some(a => a.modelUuid === modelUuid);
}
}))
);
setOpacity: (modelUuid, opacity) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.opacity = opacity;
}
});
},
// Animation controls
setAnimation: (modelUuid, animation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
if (!asset.animationState) {
asset.animationState = { current: animation, playing: false };
} else {
asset.animationState.current = animation;
}
}
});
},
setCurrentAnimation: (modelUuid, current, isPlaying) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset?.animationState) {
asset.animationState.current = current;
asset.animationState.playing = isPlaying;
}
});
},
addAnimation: (modelUuid, animation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
if (!asset.animations) {
asset.animations = [animation];
} else if (!asset.animations.includes(animation)) {
asset.animations.push(animation);
}
}
});
},
removeAnimation: (modelUuid, animation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset?.animations) {
asset.animations = asset.animations.filter(a => a !== animation);
if (asset.animationState?.current === animation) {
asset.animationState.playing = false;
asset.animationState.current = '';
}
}
});
},
// Event data operations
addEventData: (modelUuid, eventData) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.eventData = eventData;
}
});
},
updateEventData: (modelUuid, updates) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset?.eventData) {
asset.eventData = { ...asset.eventData, ...updates };
}
});
},
removeEventData: (modelUuid) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
delete asset.eventData;
}
});
},
// Helper functions
getAssetById: (modelUuid) => {
return get().assets.find(a => a.modelUuid === modelUuid);
},
getAssetByPointUuid: (pointUuid) => {
return get().assets.find(asset =>
asset.eventData?.point?.uuid === pointUuid ||
asset.eventData?.points?.some(p => p.uuid === pointUuid)
);
},
hasAsset: (modelUuid) => {
return get().assets.some(a => a.modelUuid === modelUuid);
}
}))
)
}
export type AssetStoreType = ReturnType<typeof createAssetStore>;

View File

@@ -10,7 +10,7 @@ interface VehiclesStore {
modelUuid: string,
updates: Partial<Omit<VehicleStatus, "modelUuid" | "productUuid">>
) => void;
clearvehicles: () => void;
clearVehicles: () => void;
setVehicleActive: (modelUuid: string, isActive: boolean) => void;
setVehiclePicking: (modelUuid: string, isPicking: boolean) => void;
@@ -79,7 +79,7 @@ export const createVehicleStore = () => {
});
},
clearvehicles: () => {
clearVehicles: () => {
set((state) => {
state.vehicles = [];
});