Merge remote-tracking branch 'origin/v2-ui' into v2
This commit is contained in:
commit
f2a2811af7
|
@ -21,7 +21,7 @@ interface ModelProps extends React.ComponentProps<'group'> {
|
||||||
matRef: React.Ref<THREE.Group<THREE.Object3DEventMap>>
|
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 path = modelPaths[materialType] || modelPaths['Default material'];
|
||||||
const gltf = useGLTF(path);
|
const gltf = useGLTF(path);
|
||||||
const cloned = useMemo(() => gltf?.scene.clone(), [gltf]);
|
const cloned = useMemo(() => gltf?.scene.clone(), [gltf]);
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
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();
|
||||||
|
const padding = 0.1;
|
||||||
|
|
||||||
|
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 [];
|
||||||
|
|
||||||
|
const box = new Box3().setFromObject(storageModel);
|
||||||
|
const size = new Vector3();
|
||||||
|
box.getSize(size);
|
||||||
|
|
||||||
|
const matCount = storage.currentMaterials.length;
|
||||||
|
|
||||||
|
// Assumed size each material needs in world units
|
||||||
|
const materialWidth = 0.45;
|
||||||
|
const materialDepth = 0.45;
|
||||||
|
const materialHeight = 0.3;
|
||||||
|
|
||||||
|
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 + materialWidth / 2,
|
||||||
|
box.max.y + padding, // slightly above the surface
|
||||||
|
box.min.z + materialDepth / 2
|
||||||
|
);
|
||||||
|
|
||||||
|
return Array.from({ length: matCount }, (_, i) => {
|
||||||
|
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 * materialWidth,
|
||||||
|
origin.y + layer * (materialHeight + padding),
|
||||||
|
origin.z + row * materialDepth
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, [storageModel, storage.currentMaterials]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<group position={[0, -padding, 0]}>
|
||||||
|
{hasLoad &&
|
||||||
|
storage.currentMaterials.map((mat, index) => (
|
||||||
|
<MaterialModel
|
||||||
|
key={`${index}-${mat.materialId}`}
|
||||||
|
matRef={meshRef}
|
||||||
|
materialType={mat.materialType ?? "Default material"}
|
||||||
|
position={materialPositions[index]}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</group>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MaterialAnimator;
|
|
@ -1,14 +1,14 @@
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
|
import MaterialAnimator from '../animator/MaterialAnimator'
|
||||||
|
|
||||||
function StorageUnitInstance({ storageUnit }: { storageUnit: StorageUnitStatus }) {
|
function StorageUnitInstance({ storageUnit }: Readonly<{ storageUnit: StorageUnitStatus }>) {
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
// console.log('storageUnit: ', storageUnit);
|
// console.log('storageUnit: ', storageUnit);
|
||||||
},[storageUnit])
|
},[storageUnit])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<MaterialAnimator storage={storageUnit}/>
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import StorageUnitInstance from './storageUnitInstance/storageUnitInstance'
|
import StorageUnitInstance from './storageUnitInstance/storageUnitInstance'
|
||||||
import { useStorageUnitStore } from '../../../../store/simulation/useStorageUnitStore'
|
import { useStorageUnitStore } from '../../../../store/simulation/useStorageUnitStore'
|
||||||
|
import StorageContentUi from '../../ui3d/StorageContentUi';
|
||||||
|
|
||||||
function StorageUnitInstances() {
|
function StorageUnitInstances() {
|
||||||
const { storageUnits } = useStorageUnitStore();
|
const { storageUnits } = useStorageUnitStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
{storageUnits.map((storageUnit: StorageUnitStatus) => (
|
{storageUnits.map((storageUnit: StorageUnitStatus) => (
|
||||||
<React.Fragment key={storageUnit.modelUuid}>
|
<React.Fragment key={storageUnit.modelUuid}>
|
||||||
<StorageUnitInstance storageUnit={storageUnit} />
|
<StorageUnitInstance storageUnit={storageUnit} />
|
||||||
|
<StorageContentUi storageUnit={storageUnit}/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue