feat: Enhance material handling and storage unit interactions; refactor MaterialAnimator and useRetrieveHandler for improved state management

This commit is contained in:
2025-08-04 12:00:48 +05:30
parent 0da9e8997c
commit c9cc8d3534
6 changed files with 168 additions and 63 deletions

View File

@@ -60,9 +60,9 @@ export function useRetrieveHandler() {
actionUuid: action.actionUuid actionUuid: action.actionUuid
}, },
current: { current: {
modelUuid: action.triggers[0]?.triggeredAsset.triggeredModel.modelUuid, modelUuid: modelUuid,
pointUuid: action.triggers[0]?.triggeredAsset.triggeredPoint.pointUuid, pointUuid: pointUuid,
actionUuid: action.triggers[0]?.triggeredAsset.triggeredAction.actionUuid actionUuid: action.actionUuid
}, },
}; };

View File

@@ -33,8 +33,8 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
const [customCurvePoints, setCustomCurvePoints] = useState<THREE.Vector3[] | null>(null); const [customCurvePoints, setCustomCurvePoints] = useState<THREE.Vector3[] | null>(null);
const { armBotStore, productStore, materialStore } = useSceneContext(); const { armBotStore, productStore, materialStore } = useSceneContext();
const { getArmBotById } = armBotStore(); const { getArmBotById } = armBotStore();
const { getMaterialById } = materialStore(); const { getMaterialById, getMaterialPosition } = materialStore();
const { getEventByModelUuid } = productStore(); const { getEventByModelUuid, getActionByUuid, getPointByUuid } = productStore();
const { selectedProductStore } = useProductContext(); const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore(); const { selectedProduct } = selectedProductStore();
const { scene } = useThree(); const { scene } = useThree();
@@ -167,13 +167,18 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
let start = currentPath[0]; let start = currentPath[0];
let end = currentPath[currentPath.length - 1]; let end = currentPath[currentPath.length - 1];
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
const armbotStatus = getArmBotById(armBot.modelUuid); const armbotStatus = getArmBotById(armBot.modelUuid);
const currentMaterial = armbotStatus?.currentAction?.materialId; const currentMaterial = armbotStatus?.currentAction?.materialId;
if (armbotStatus && currentMaterial && (currentPhase === 'rest-to-start' || currentPhase === 'start-to-end')) { const currentAction = getActionByUuid(selectedProduct.productUuid, armbotStatus?.currentAction?.actionUuid || '');
if (armbotStatus && currentMaterial && currentAction && (currentPhase === 'rest-to-start' || currentPhase === 'start-to-end' || currentPhase === 'end-to-rest')) {
const materialData = getMaterialById(currentMaterial); const materialData = getMaterialById(currentMaterial);
if (materialData) { if (materialData) {
const prevModel = getEventByModelUuid(selectedProduct.productUuid, materialData.current.modelUuid); const prevModel = getEventByModelUuid(selectedProduct.productUuid, materialData.current.modelUuid);
const nextModel = getEventByModelUuid(selectedProduct.productUuid, currentAction?.triggers[0]?.triggeredAsset?.triggeredModel?.modelUuid || '');
const nextPoint = getPointByUuid(selectedProduct.productUuid, currentAction?.triggers[0]?.triggeredAsset?.triggeredModel?.modelUuid || '', currentAction?.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid || '');
if (prevModel && prevModel.type === 'transfer') { if (prevModel && prevModel.type === 'transfer') {
const material = scene.getObjectByProperty("uuid", currentMaterial); const material = scene.getObjectByProperty("uuid", currentMaterial);
@@ -194,7 +199,69 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
start = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z]; start = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z];
} }
} }
} else if (prevModel && prevModel.type === 'storageUnit') {
const position = getMaterialPosition(currentMaterial);
const armbotModel = scene.getObjectByProperty("uuid", armBot.modelUuid);
if (armbotModel) {
const armbotWorldPos = new THREE.Vector3();
let materialWorldPos = new THREE.Vector3();
if (position) {
materialWorldPos.copy(position);
} else {
materialWorldPos.copy(bone.getWorldPosition(armbotWorldPos));
}
const materialLocalPos = materialWorldPos.clone();
armbotModel.worldToLocal(materialLocalPos);
if (currentPhase === 'rest-to-start') {
end = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z];
} else if (currentPhase === 'start-to-end') {
start = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z];
} else if (currentPhase === 'end-to-rest') {
start = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z];
}
}
} }
if (nextModel && nextPoint && nextModel.type === 'transfer') {
const conveyorModel = scene.getObjectByProperty("uuid", nextModel.modelUuid);
const armbotModel = scene.getObjectByProperty("uuid", armBot.modelUuid);
if (conveyorModel && armbotModel) {
const localPoint = new THREE.Vector3(
nextPoint.position[0],
nextPoint.position[1],
nextPoint.position[2]
);
const worldPoint = conveyorModel.localToWorld(localPoint);
armbotModel.worldToLocal(worldPoint);
if (currentPhase === 'start-to-end') {
end = [worldPoint.x, worldPoint.y + 0.35, worldPoint.z];
}
}
}
}
}
if (currentPhase === 'end-to-rest') {
console.log('currentPhase: ', currentPhase);
const armbotModel = scene.getObjectByProperty("uuid", armBot.modelUuid);
const armbotWorldPos = new THREE.Vector3();
if (armbotModel) {
let materialWorldPos = new THREE.Vector3();
materialWorldPos.copy(bone.getWorldPosition(armbotWorldPos));
const materialLocalPos = materialWorldPos.clone();
armbotModel.worldToLocal(materialLocalPos);
start = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z];
} }
} }

View File

@@ -1,72 +1,83 @@
import { useRef, useMemo } from "react"; import { useEffect, useMemo } from "react";
import { MaterialModel } from "../../../materials/instances/material/materialModel";
import { Object3D, Box3, Vector3 } from "three"; import { Object3D, Box3, Vector3 } from "three";
import { useThree } from "@react-three/fiber"; import { useThree } from "@react-three/fiber";
import { useLoadingProgress } from "../../../../../store/builder/store"; import { useLoadingProgress } from "../../../../../store/builder/store";
import { MaterialModel } from "../../../materials/instances/material/materialModel";
import { useSceneContext } from "../../../../scene/sceneContext";
const MaterialAnimator = ({ const MaterialAnimator = ({
storage, storage,
}: Readonly<{ storage: StorageUnitStatus }>) => { }: Readonly<{ storage: StorageUnitStatus }>) => {
const meshRef = useRef<any>(null!); const { scene } = useThree();
const { scene } = useThree(); const padding = 0.1;
const padding = 0.1; const { loadingProgress } = useLoadingProgress();
const { loadingProgress } = useLoadingProgress(); const { materialStore } = useSceneContext();
const { materialPositions, setMaterialPositions } = materialStore();
const storageModel = useMemo(() => { const storageModel = useMemo(() => {
return scene.getObjectByProperty("uuid", storage.modelUuid) as Object3D; return scene.getObjectByProperty("uuid", storage.modelUuid) as Object3D;
}, [scene, storage.modelUuid, loadingProgress]); }, [scene, storage.modelUuid, loadingProgress]);
const materialPositions = useMemo(() => { useEffect(() => {
if (!storageModel || storage.currentMaterials.length === 0) return []; if (!storageModel || storage.currentMaterials.length === 0) {
setMaterialPositions([]);
return;
}
const box = new Box3().setFromObject(storageModel); const box = new Box3().setFromObject(storageModel);
const size = new Vector3(); const size = new Vector3();
box.getSize(size); box.getSize(size);
const matCount = storage.currentMaterials.length; 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;
// Assumed size each material needs in world units const origin = new Vector3(
const materialWidth = 0.45; box.min.x + materialWidth / 2,
const materialDepth = 0.45; box.max.y + padding,
const materialHeight = 0.3; box.min.z + materialDepth / 2
);
const cols = Math.floor(size.x / materialWidth); const newMaterials = storage.currentMaterials.map((mat, i) => {
const rows = Math.floor(size.z / materialDepth); const layer = Math.floor(i / itemsPerLayer);
const itemsPerLayer = cols * rows; const layerIndex = i % itemsPerLayer;
const row = Math.floor(layerIndex / cols);
const col = layerIndex % cols;
const origin = new Vector3( const position = new Vector3(
box.min.x + materialWidth / 2, origin.x + col * materialWidth,
box.max.y + padding, // slightly above the surface origin.y + layer * (materialHeight + padding),
box.min.z + materialDepth / 2 origin.z + row * materialDepth
);
return {
materialId: mat.materialId,
position,
};
});
setMaterialPositions(newMaterials);
}, [storageModel, storage.currentMaterials, setMaterialPositions]);
return (
<group position={[0, -padding, 0]}>
{materialPositions.map(({ materialId, position }) => {
const mat = storage.currentMaterials.find((m) => m.materialId === materialId);
return (
<MaterialModel
key={materialId}
materialId={materialId}
matRef={null}
materialType={mat?.materialType ?? "Default material"}
position={position}
/>
);
})}
</group>
); );
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] }}>
{storage.currentMaterials.map((mat, index) => (
<MaterialModel
key={`${index}-${mat.materialId}`}
materialId={mat.materialId}
matRef={meshRef}
materialType={mat.materialType ?? "Default material"}
position={materialPositions[index]}
/>
))}
</group>
);
}; };
export default MaterialAnimator; export default MaterialAnimator;

View File

@@ -7,7 +7,6 @@ import { useViewSceneStore } from "../../../../store/builder/store";
function StorageUnitInstances() { function StorageUnitInstances() {
const { storageUnitStore } = useSceneContext(); const { storageUnitStore } = useSceneContext();
const { storageUnits } = storageUnitStore(); const { storageUnits } = storageUnitStore();
// console.log('storageUnits: ', storageUnits);
const { viewSceneLabels } = useViewSceneStore(); const { viewSceneLabels } = useViewSceneStore();
return ( return (

View File

@@ -1,4 +1,3 @@
import React from 'react'
import StorageUnitInstances from './instances/storageUnitInstances' import StorageUnitInstances from './instances/storageUnitInstances'
function StorageUnit() { function StorageUnit() {

View File

@@ -1,15 +1,26 @@
import * as THREE from 'three';
import { create } from 'zustand'; import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer'; import { immer } from 'zustand/middleware/immer';
interface MaterialPosition {
materialId: string;
position: THREE.Vector3;
}
type MaterialsStore = { type MaterialsStore = {
materials: MaterialsSchema; materials: MaterialsSchema;
materialHistory: MaterialHistorySchema; materialHistory: MaterialHistorySchema;
materialPositions: MaterialPosition[];
addMaterial: (material: MaterialSchema) => MaterialSchema | undefined; addMaterial: (material: MaterialSchema) => MaterialSchema | undefined;
removeMaterial: (materialId: string) => MaterialSchema | undefined; removeMaterial: (materialId: string) => MaterialSchema | undefined;
clearMaterials: () => void; clearMaterials: () => void;
updateMaterial: (materialId: string, updates: Partial<MaterialSchema>) => MaterialSchema | undefined; updateMaterial: (materialId: string, updates: Partial<MaterialSchema>) => MaterialSchema | undefined;
setMaterialPositions: (materialPosition: MaterialPosition[]) => void;
getMaterialPosition: (materialId: string) => THREE.Vector3 | undefined;
setPreviousLocation: ( setPreviousLocation: (
materialId: string, materialId: string,
location: { location: {
@@ -61,6 +72,7 @@ export const createMaterialStore = () => {
immer((set, get) => ({ immer((set, get) => ({
materials: [], materials: [],
materialHistory: [], materialHistory: [],
materialPositions: [],
addMaterial: (material) => { addMaterial: (material) => {
let updatedMaterial: MaterialSchema | undefined; let updatedMaterial: MaterialSchema | undefined;
@@ -262,6 +274,23 @@ export const createMaterialStore = () => {
return updatedMaterial; return updatedMaterial;
}, },
setMaterialPositions: (materials) => {
set((state) => {
state.materialPositions = materials;
});
},
getMaterialPosition: (materialid) => {
let position: THREE.Vector3 | undefined;
set((state) => {
const material = state.materialPositions.find(m => m.materialId === materialid);
if (material) {
position = material.position;
}
});
return position;
},
getMaterialById: (materialId) => { getMaterialById: (materialId) => {
return get().materials.find(m => m.materialId === materialId); return get().materials.find(m => m.materialId === materialId);
}, },