From 226f6d7b2985adcbcd075dbab1b213b9725a06dd Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 10 May 2025 11:01:05 +0530 Subject: [PATCH 1/2] Enhance storage unit functionality: refactor StorageUnitInstance to use Readonly props, implement MaterialAnimator for dynamic material handling, and add StorageContentUi for displaying asset details. --- .../instances/material/materialModel.tsx | 2 +- .../instances/animator/MaterialAnimator.tsx | 73 +++++++++++++++++++ .../storageUnitInstance.tsx | 6 +- .../instances/storageUnitInstances.tsx | 3 +- .../simulation/ui3d/StorageContentUi.tsx | 38 ++++++++++ 5 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 app/src/modules/simulation/storageUnit/instances/animator/MaterialAnimator.tsx create mode 100644 app/src/modules/simulation/ui3d/StorageContentUi.tsx diff --git a/app/src/modules/simulation/materials/instances/material/materialModel.tsx b/app/src/modules/simulation/materials/instances/material/materialModel.tsx index 2093584..244c7bf 100644 --- a/app/src/modules/simulation/materials/instances/material/materialModel.tsx +++ b/app/src/modules/simulation/materials/instances/material/materialModel.tsx @@ -21,7 +21,7 @@ interface ModelProps extends React.ComponentProps<'group'> { matRef: React.Ref> } -export function MaterialModel({ materialType, matRef, ...props }: ModelProps) { +export function MaterialModel({ materialType, matRef, ...props }: Readonly) { const path = modelPaths[materialType] || modelPaths['Default material']; const gltf = useGLTF(path); const cloned = useMemo(() => gltf?.scene.clone(), [gltf]); diff --git a/app/src/modules/simulation/storageUnit/instances/animator/MaterialAnimator.tsx b/app/src/modules/simulation/storageUnit/instances/animator/MaterialAnimator.tsx new file mode 100644 index 0000000..b35a656 --- /dev/null +++ b/app/src/modules/simulation/storageUnit/instances/animator/MaterialAnimator.tsx @@ -0,0 +1,73 @@ +import React, { useEffect, useRef, useState, useMemo } from "react"; +import { MaterialModel } from "../../../materials/instances/material/materialModel"; +import { Object3D, Box3, Vector3 } from "three"; +import { useThree } from "@react-three/fiber"; + +const MaterialAnimator = ({ + storage, +}: Readonly<{ storage: StorageUnitStatus }>) => { + const meshRef = useRef(null!); + const [hasLoad, setHasLoad] = useState(false); + const { scene } = useThree(); + + useEffect(() => { + setHasLoad(storage.currentLoad > 0); + }, [storage.currentLoad]); + + const storageModel = useMemo(() => { + return scene.getObjectByProperty("uuid", storage.modelUuid) as Object3D; + }, [scene, storage.modelUuid]); + + const materialPositions = useMemo(() => { + if (!storageModel || storage.currentMaterials.length === 0) return []; + + // Get the bounding box of the model + const box = new Box3().setFromObject(storageModel); + const size = new Vector3(); + box.getSize(size); + + const padding = 0.1; // space between items + const matCount = storage.currentMaterials.length; + + // Estimate how many columns and rows fit (try square layout) + const aspectRatio = size.x / size.z; + const cols = Math.ceil(Math.sqrt(matCount * aspectRatio)); + const rows = Math.ceil(matCount / cols); + + const cellWidth = size.x / cols; + const cellDepth = size.z / rows; + + const origin = new Vector3( + box.min.x + cellWidth / 2, + box.max.y + 0, // place slightly above the model + box.min.z + cellDepth / 2 + ); + + // Generate grid positions + return Array.from({ length: matCount }, (_, i) => { + const row = Math.floor(i / cols); + const col = i % cols; + return new Vector3( + origin.x + col * cellWidth, + origin.y, + origin.z + row * cellDepth + ); + }); + }, [storageModel, storage.currentMaterials]); + + return ( + <> + {hasLoad && + storage.currentMaterials.map((mat, index) => ( + + ))} + + ); +}; + +export default MaterialAnimator; diff --git a/app/src/modules/simulation/storageUnit/instances/storageUnitInstance/storageUnitInstance.tsx b/app/src/modules/simulation/storageUnit/instances/storageUnitInstance/storageUnitInstance.tsx index c182433..b0f0514 100644 --- a/app/src/modules/simulation/storageUnit/instances/storageUnitInstance/storageUnitInstance.tsx +++ b/app/src/modules/simulation/storageUnit/instances/storageUnitInstance/storageUnitInstance.tsx @@ -1,14 +1,14 @@ import React, { useEffect } from 'react' +import MaterialAnimator from '../animator/MaterialAnimator' -function StorageUnitInstance({ storageUnit }: { storageUnit: StorageUnitStatus }) { +function StorageUnitInstance({ storageUnit }: Readonly<{ storageUnit: StorageUnitStatus }>) { useEffect(()=>{ // console.log('storageUnit: ', storageUnit); },[storageUnit]) return ( - <> - + ) } diff --git a/app/src/modules/simulation/storageUnit/instances/storageUnitInstances.tsx b/app/src/modules/simulation/storageUnit/instances/storageUnitInstances.tsx index d073254..29b6ea0 100644 --- a/app/src/modules/simulation/storageUnit/instances/storageUnitInstances.tsx +++ b/app/src/modules/simulation/storageUnit/instances/storageUnitInstances.tsx @@ -1,16 +1,17 @@ import React from 'react' import StorageUnitInstance from './storageUnitInstance/storageUnitInstance' import { useStorageUnitStore } from '../../../../store/simulation/useStorageUnitStore' +import StorageContentUi from '../../ui3d/StorageContentUi'; function StorageUnitInstances() { const { storageUnits } = useStorageUnitStore(); return ( <> - {storageUnits.map((storageUnit: StorageUnitStatus) => ( + ))} diff --git a/app/src/modules/simulation/ui3d/StorageContentUi.tsx b/app/src/modules/simulation/ui3d/StorageContentUi.tsx new file mode 100644 index 0000000..dbda5b3 --- /dev/null +++ b/app/src/modules/simulation/ui3d/StorageContentUi.tsx @@ -0,0 +1,38 @@ +import { Html } from "@react-three/drei"; +import React from "react"; +import AssetDetailsCard from "../../../components/ui/simulation/AssetDetailsCard"; +import { Vector3 } from "three"; + +type StorageContentUiProps = { + storageUnit: StorageUnitStatus; +}; + +const StorageContentUi: React.FC = ({ storageUnit }) => { + return ( + + + + ); +}; + +export default StorageContentUi; From 4e0cc7f39d4170e178228103efa525ec565d8434 Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 10 May 2025 12:26:50 +0530 Subject: [PATCH 2/2] Refactor MaterialAnimator: optimize material positioning logic, streamline grid generation, and enhance layout calculations for improved visual representation. --- .../instances/animator/MaterialAnimator.tsx | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/app/src/modules/simulation/storageUnit/instances/animator/MaterialAnimator.tsx b/app/src/modules/simulation/storageUnit/instances/animator/MaterialAnimator.tsx index b35a656..259b455 100644 --- a/app/src/modules/simulation/storageUnit/instances/animator/MaterialAnimator.tsx +++ b/app/src/modules/simulation/storageUnit/instances/animator/MaterialAnimator.tsx @@ -9,6 +9,7 @@ const MaterialAnimator = ({ const meshRef = useRef(null!); const [hasLoad, setHasLoad] = useState(false); const { scene } = useThree(); + const padding = 0.1; useEffect(() => { setHasLoad(storage.currentLoad > 0); @@ -21,42 +22,43 @@ const MaterialAnimator = ({ const materialPositions = useMemo(() => { if (!storageModel || storage.currentMaterials.length === 0) return []; - // Get the bounding box of the model const box = new Box3().setFromObject(storageModel); const size = new Vector3(); box.getSize(size); - const padding = 0.1; // space between items const matCount = storage.currentMaterials.length; - // Estimate how many columns and rows fit (try square layout) - const aspectRatio = size.x / size.z; - const cols = Math.ceil(Math.sqrt(matCount * aspectRatio)); - const rows = Math.ceil(matCount / cols); + // Assumed size each material needs in world units + const materialWidth = 0.45; + const materialDepth = 0.45; + const materialHeight = 0.3; - const cellWidth = size.x / cols; - const cellDepth = size.z / rows; + const cols = Math.floor(size.x / materialWidth); + const rows = Math.floor(size.z / materialDepth); + const itemsPerLayer = cols * rows; const origin = new Vector3( - box.min.x + cellWidth / 2, - box.max.y + 0, // place slightly above the model - box.min.z + cellDepth / 2 + box.min.x + materialWidth / 2, + box.max.y + padding, // slightly above the surface + box.min.z + materialDepth / 2 ); - // Generate grid positions return Array.from({ length: matCount }, (_, i) => { - const row = Math.floor(i / cols); - const col = i % cols; + const layer = Math.floor(i / itemsPerLayer); + const layerIndex = i % itemsPerLayer; + const row = Math.floor(layerIndex / cols); + const col = layerIndex % cols; + return new Vector3( - origin.x + col * cellWidth, - origin.y, - origin.z + row * cellDepth + origin.x + col * materialWidth, + origin.y + layer * (materialHeight + padding), + origin.z + row * materialDepth ); }); }, [storageModel, storage.currentMaterials]); return ( - <> + {hasLoad && storage.currentMaterials.map((mat, index) => ( ))} - + ); };