v2-ui #84

Merged
Vishnu merged 53 commits from v2-ui into main 2025-05-10 13:42:19 +00:00
5 changed files with 117 additions and 5 deletions
Showing only changes of commit 226f6d7b29 - Show all commits

View File

@ -21,7 +21,7 @@ interface ModelProps extends React.ComponentProps<'group'> {
matRef: React.Ref<THREE.Group<THREE.Object3DEventMap>>
}
export function MaterialModel({ materialType, matRef, ...props }: ModelProps) {
export function MaterialModel({ materialType, matRef, ...props }: Readonly<ModelProps>) {
const path = modelPaths[materialType] || modelPaths['Default material'];
const gltf = useGLTF(path);
const cloned = useMemo(() => gltf?.scene.clone(), [gltf]);

View File

@ -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<any>(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) => (
<MaterialModel
key={`${index}-${mat.materialId}`}
matRef={meshRef}
materialType={mat.materialType ?? "Default material"}
position={materialPositions[index]}
/>
))}
</>
);
};
export default MaterialAnimator;

View File

@ -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 (
<>
</>
<MaterialAnimator storage={storageUnit}/>
)
}

View File

@ -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) => (
<React.Fragment key={storageUnit.modelUuid}>
<StorageUnitInstance storageUnit={storageUnit} />
<StorageContentUi storageUnit={storageUnit}/>
</React.Fragment>
))}
</>

View File

@ -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<StorageContentUiProps> = ({ storageUnit }) => {
return (
<Html
// data
position={
new Vector3(
storageUnit.position[0],
storageUnit.point.position[1],
storageUnit.position[2]
)
}
// class none
// other
zIndexRange={[1, 0]}
prepend
sprite
center
distanceFactor={20}
>
<AssetDetailsCard
name={storageUnit.modelName}
status={storageUnit.state}
count={storageUnit.currentLoad}
/>
</Html>
);
};
export default StorageContentUi;