feat: Enhance material handling and storage unit interactions; refactor MaterialAnimator and useRetrieveHandler for improved state management
This commit is contained in:
@@ -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
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from 'react'
|
|
||||||
import StorageUnitInstances from './instances/storageUnitInstances'
|
import StorageUnitInstances from './instances/storageUnitInstances'
|
||||||
|
|
||||||
function StorageUnit() {
|
function StorageUnit() {
|
||||||
|
|||||||
@@ -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);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user