Merge remote-tracking branch 'origin/v2' into simulation-agv-v2
This commit is contained in:
commit
dd402184e4
app/src
components/layout/sidebarRight/properties/eventProperties
modules/simulation
actions
materials/instances
triggers/triggerHandler
store/simulation
types
|
@ -237,7 +237,7 @@ function ConveyorMechanics() {
|
||||||
{activeOption === "spawn" && (
|
{activeOption === "spawn" && (
|
||||||
<SpawnAction
|
<SpawnAction
|
||||||
onChangeCount={handleSpawnCountChange}
|
onChangeCount={handleSpawnCountChange}
|
||||||
options={["Default material", "Material 1", "Material 2"]}
|
options={["Default material", "Material 1", "Material 2", "Material 3"]}
|
||||||
defaultOption={currentMaterial}
|
defaultOption={currentMaterial}
|
||||||
onSelect={handleMaterialSelect}
|
onSelect={handleMaterialSelect}
|
||||||
onChangeInterval={handleSpawnIntervalChange}
|
onChangeInterval={handleSpawnIntervalChange}
|
||||||
|
@ -253,7 +253,7 @@ function ConveyorMechanics() {
|
||||||
)}
|
)}
|
||||||
{activeOption === "swap" && (
|
{activeOption === "swap" && (
|
||||||
<SwapAction
|
<SwapAction
|
||||||
options={["Default material", "Material 1", "Material 2"]}
|
options={["Default material", "Material 1", "Material 2", "Material 3"]}
|
||||||
defaultOption={currentMaterial}
|
defaultOption={currentMaterial}
|
||||||
onSelect={handleMaterialSelect}
|
onSelect={handleMaterialSelect}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -129,7 +129,7 @@ function MachineMechanics() {
|
||||||
max={60}
|
max={60}
|
||||||
defaultValue="1"
|
defaultValue="1"
|
||||||
onChange={handleProcessTimeChange}
|
onChange={handleProcessTimeChange}
|
||||||
swapOptions={["Default material", "Material 1", "Material 2"]}
|
swapOptions={["Default material", "Material 1", "Material 2", "Material 3"]}
|
||||||
swapDefaultOption={currentMaterial}
|
swapDefaultOption={currentMaterial}
|
||||||
onSwapSelect={handleMaterialSelect}
|
onSwapSelect={handleMaterialSelect}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -359,7 +359,8 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
|
||||||
<LabledDropdown
|
<LabledDropdown
|
||||||
label="Trigger Type"
|
label="Trigger Type"
|
||||||
defaultOption={selectedTrigger.triggerType}
|
defaultOption={selectedTrigger.triggerType}
|
||||||
options={["onComplete", "onStart", "onStop", "delay", "onError"]}
|
// options={["onComplete", "onStart", "onStop", "delay", "onError"]}
|
||||||
|
options={["onComplete"]}
|
||||||
onSelect={handleTriggerTypeChange}
|
onSelect={handleTriggerTypeChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ export function useSpawnHandler() {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const spawnLogStatus = (materialUuid: string, status: string) => {
|
const spawnLogStatus = (materialUuid: string, status: string) => {
|
||||||
console.log(`${materialUuid}, ${status}`);
|
// console.log(`${materialUuid}, ${status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const createNewMaterial = useCallback((materialType: string, action: ConveyorAction) => {
|
const createNewMaterial = useCallback((materialType: string, action: ConveyorAction) => {
|
||||||
|
@ -51,6 +51,17 @@ export function useSpawnHandler() {
|
||||||
cost: 1
|
cost: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (action.triggers[0].triggeredAsset?.triggeredModel.modelUuid &&
|
||||||
|
action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid &&
|
||||||
|
action.triggers[0].triggeredAsset?.triggeredAction?.actionUuid
|
||||||
|
) {
|
||||||
|
newMaterial.next = {
|
||||||
|
modelUuid: action.triggers[0].triggeredAsset?.triggeredModel.modelUuid,
|
||||||
|
pointUuid: action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid,
|
||||||
|
actionUuid: action.triggers[0].triggeredAsset?.triggeredAction?.actionUuid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addMaterial(newMaterial);
|
addMaterial(newMaterial);
|
||||||
return newMaterial;
|
return newMaterial;
|
||||||
}, [addMaterial]);
|
}, [addMaterial]);
|
||||||
|
|
|
@ -5,7 +5,7 @@ export function useConveyorActions() {
|
||||||
const { handleSpawn, clearCurrentSpawn } = useSpawnHandler();
|
const { handleSpawn, clearCurrentSpawn } = useSpawnHandler();
|
||||||
|
|
||||||
const handleDefaultAction = useCallback((action: ConveyorAction) => {
|
const handleDefaultAction = useCallback((action: ConveyorAction) => {
|
||||||
console.log(`Default conveyor action ${action.actionUuid}`);
|
// console.log(`Default conveyor action ${action.actionUuid}`);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleSpawnAction = useCallback((action: ConveyorAction) => {
|
const handleSpawnAction = useCallback((action: ConveyorAction) => {
|
||||||
|
|
|
@ -6,14 +6,12 @@ import { useVehicleActions } from "./vehicle/useVehicleActions";
|
||||||
import { useCallback, useEffect } from "react";
|
import { useCallback, useEffect } from "react";
|
||||||
|
|
||||||
export function useActionHandler() {
|
export function useActionHandler() {
|
||||||
// Initialize all action handlers
|
|
||||||
const { handleConveyorAction, cleanup: cleanupConveyor } = useConveyorActions();
|
const { handleConveyorAction, cleanup: cleanupConveyor } = useConveyorActions();
|
||||||
const { handleVehicleAction, cleanup: cleanupVehicle } = useVehicleActions();
|
const { handleVehicleAction, cleanup: cleanupVehicle } = useVehicleActions();
|
||||||
const { handleRoboticArmAction, cleanup: cleanupRoboticArm } = useRoboticArmActions();
|
const { handleRoboticArmAction, cleanup: cleanupRoboticArm } = useRoboticArmActions();
|
||||||
const { handleMachineAction, cleanup: cleanupMachine } = useMachineActions();
|
const { handleMachineAction, cleanup: cleanupMachine } = useMachineActions();
|
||||||
const { handleStorageAction, cleanup: cleanupStorage } = useStorageActions();
|
const { handleStorageAction, cleanup: cleanupStorage } = useStorageActions();
|
||||||
|
|
||||||
// Main handler function
|
|
||||||
const handleAction = useCallback((action: Action) => {
|
const handleAction = useCallback((action: Action) => {
|
||||||
if (!action) return;
|
if (!action) return;
|
||||||
|
|
||||||
|
@ -39,32 +37,17 @@ export function useActionHandler() {
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error handling action:', error);
|
console.error('Error handling action:', error);
|
||||||
// Consider adding error recovery or notification here
|
|
||||||
}
|
}
|
||||||
}, [
|
}, [handleConveyorAction, handleVehicleAction, handleRoboticArmAction, handleMachineAction, handleStorageAction]);
|
||||||
handleConveyorAction,
|
|
||||||
handleVehicleAction,
|
|
||||||
handleRoboticArmAction,
|
|
||||||
handleMachineAction,
|
|
||||||
handleStorageAction
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Cleanup all actions
|
|
||||||
const cleanup = useCallback(() => {
|
const cleanup = useCallback(() => {
|
||||||
cleanupConveyor();
|
cleanupConveyor();
|
||||||
cleanupVehicle();
|
cleanupVehicle();
|
||||||
cleanupRoboticArm();
|
cleanupRoboticArm();
|
||||||
cleanupMachine();
|
cleanupMachine();
|
||||||
cleanupStorage();
|
cleanupStorage();
|
||||||
}, [
|
}, [cleanupConveyor, cleanupVehicle, cleanupRoboticArm, cleanupMachine, cleanupStorage]);
|
||||||
cleanupConveyor,
|
|
||||||
cleanupVehicle,
|
|
||||||
cleanupRoboticArm,
|
|
||||||
cleanupMachine,
|
|
||||||
cleanupStorage
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Auto cleanup on unmount
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
|
@ -1,9 +1,74 @@
|
||||||
import React from 'react'
|
import React, { useEffect, useState, useRef } from 'react';
|
||||||
|
import * as THREE from 'three';
|
||||||
|
import { useFrame, useThree } from '@react-three/fiber';
|
||||||
|
|
||||||
function MaterialAnimator() {
|
interface MaterialAnimatorProps {
|
||||||
return (
|
matRef: React.RefObject<THREE.Mesh>;
|
||||||
<></>
|
material: MaterialSchema;
|
||||||
)
|
speed: number; // units per second
|
||||||
|
onAnimationComplete?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MaterialAnimator
|
function MaterialAnimator({
|
||||||
|
matRef,
|
||||||
|
material,
|
||||||
|
speed,
|
||||||
|
onAnimationComplete
|
||||||
|
}: MaterialAnimatorProps) {
|
||||||
|
const { scene } = useThree();
|
||||||
|
const [targetPosition, setTargetPosition] = useState<THREE.Vector3 | null>(null);
|
||||||
|
const [isAnimating, setIsAnimating] = useState(false);
|
||||||
|
const animationStartTime = useRef<number>(0);
|
||||||
|
const startPosition = useRef<THREE.Vector3>(new THREE.Vector3());
|
||||||
|
const totalDistance = useRef<number>(0);
|
||||||
|
|
||||||
|
const getWorldPosition = (uuid: string): THREE.Vector3 | null => {
|
||||||
|
const obj = scene.getObjectByProperty('uuid', uuid);
|
||||||
|
if (!obj) return null;
|
||||||
|
const position = new THREE.Vector3();
|
||||||
|
obj.getWorldPosition(position);
|
||||||
|
return position;
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!material.next?.pointUuid) {
|
||||||
|
setTargetPosition(null);
|
||||||
|
setIsAnimating(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newTarget = getWorldPosition(material.next.pointUuid);
|
||||||
|
if (newTarget && matRef.current) {
|
||||||
|
startPosition.current.copy(matRef.current.position);
|
||||||
|
totalDistance.current = startPosition.current.distanceTo(newTarget);
|
||||||
|
animationStartTime.current = performance.now();
|
||||||
|
setTargetPosition(newTarget);
|
||||||
|
setIsAnimating(true);
|
||||||
|
}
|
||||||
|
}, [material.next?.pointUuid]);
|
||||||
|
|
||||||
|
useFrame(() => {
|
||||||
|
if (!matRef.current || !targetPosition || !isAnimating) return;
|
||||||
|
|
||||||
|
// Calculate exact position based on constant speed
|
||||||
|
const elapsed = (performance.now() - animationStartTime.current) / 1000;
|
||||||
|
const progress = Math.min(1, (speed * elapsed) / totalDistance.current);
|
||||||
|
|
||||||
|
matRef.current.position.lerpVectors(
|
||||||
|
startPosition.current,
|
||||||
|
targetPosition,
|
||||||
|
progress
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if animation is complete
|
||||||
|
if (progress >= 1) {
|
||||||
|
matRef.current.position.copy(targetPosition);
|
||||||
|
setIsAnimating(false);
|
||||||
|
onAnimationComplete?.();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(MaterialAnimator);
|
|
@ -1,10 +1,82 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import MaterialAnimator from '../animator/materialAnimator'
|
import MaterialAnimator from '../animator/materialAnimator';
|
||||||
|
import { useProductStore } from '../../../../../store/simulation/useProductStore';
|
||||||
|
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
|
||||||
|
import { MaterialModel } from '../material/materialModel';
|
||||||
|
import { useThree } from '@react-three/fiber';
|
||||||
|
|
||||||
function MaterialInstance({ material }: { material: MaterialSchema }) {
|
function MaterialInstance({ material }: { material: MaterialSchema }) {
|
||||||
const [position, setPosition] = useState<THREE.Vector3>();
|
const matRef: any = useRef();
|
||||||
const [rotation, setRotation] = useState<THREE.Vector3>();
|
const { scene } = useThree();
|
||||||
|
const { getModelUuidByPointUuid, getPointByUuid, getEventByModelUuid } = useProductStore();
|
||||||
|
const { selectedProduct } = useSelectedProduct();
|
||||||
|
|
||||||
|
const getWorldPositionFromScene = (pointUuid: string): THREE.Vector3 | null => {
|
||||||
|
const pointObj = scene.getObjectByProperty("uuid", pointUuid);
|
||||||
|
if (!pointObj) return null;
|
||||||
|
|
||||||
|
const worldPosition = new THREE.Vector3();
|
||||||
|
pointObj.getWorldPosition(worldPosition);
|
||||||
|
return worldPosition;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { position, rotation, speed } = useMemo(() => {
|
||||||
|
if (!material.current?.pointUuid) {
|
||||||
|
return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), speed: 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelUuid = getModelUuidByPointUuid(selectedProduct.productId, material.current.pointUuid);
|
||||||
|
if (!modelUuid) {
|
||||||
|
return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), speed: 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
const speed = getCurrentSpeed(selectedProduct.productId, modelUuid);
|
||||||
|
|
||||||
|
const point = getPointByUuid(selectedProduct.productId, modelUuid, material.current.pointUuid);
|
||||||
|
if (!point) {
|
||||||
|
return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), speed: 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
const position = getWorldPositionFromScene(point.uuid);
|
||||||
|
if (position) {
|
||||||
|
return { position: position, rotation: new THREE.Vector3(0, 0, 0), speed: 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
position: new THREE.Vector3(...point.position),
|
||||||
|
rotation: new THREE.Vector3(...point.rotation),
|
||||||
|
speed: speed || 1
|
||||||
|
};
|
||||||
|
}, [material, getPointByUuid]);
|
||||||
|
|
||||||
|
function getCurrentSpeed(productId: string, modelUuid: string) {
|
||||||
|
const event = getEventByModelUuid(productId, modelUuid)
|
||||||
|
if (event) {
|
||||||
|
if (event.type === 'transfer') {
|
||||||
|
return event.speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'vehicle') {
|
||||||
|
return event.speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'machine') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'roboticArm') {
|
||||||
|
return event.speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.type === 'storageUnit') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// console.log('material: ', material);
|
// console.log('material: ', material);
|
||||||
|
@ -13,8 +85,14 @@ function MaterialInstance({ material }: { material: MaterialSchema }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<MaterialAnimator />
|
<MaterialModel matRef={matRef} materialType={material.materialType} position={position} />
|
||||||
|
|
||||||
|
<MaterialAnimator
|
||||||
|
matRef={matRef}
|
||||||
|
material={material}
|
||||||
|
speed={speed}
|
||||||
|
onAnimationComplete={() => { console.log('123');}}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { useGLTF } from '@react-three/drei'
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import * as THREE from 'three';
|
||||||
|
|
||||||
|
import defaultMaterial from '../../../../../assets/gltf-glb/default.glb';
|
||||||
|
import material1 from '../../../../../assets/gltf-glb/material1.glb';
|
||||||
|
import material2 from '../../../../../assets/gltf-glb/material2.glb';
|
||||||
|
import material3 from '../../../../../assets/gltf-glb/material3.glb';
|
||||||
|
|
||||||
|
const modelPaths: Record<string, string> = {
|
||||||
|
'Default material': defaultMaterial,
|
||||||
|
'Material 1': material1,
|
||||||
|
'Material 2': material2,
|
||||||
|
'Material 3': material3,
|
||||||
|
};
|
||||||
|
|
||||||
|
type ModelType = keyof typeof modelPaths;
|
||||||
|
|
||||||
|
interface ModelProps extends React.ComponentProps<'group'> {
|
||||||
|
materialType: ModelType;
|
||||||
|
matRef: React.Ref<THREE.Group<THREE.Object3DEventMap>>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MaterialModel({ materialType, matRef, ...props }: ModelProps) {
|
||||||
|
const path = modelPaths[materialType] || modelPaths['Default material'];
|
||||||
|
const gltf = useGLTF(path);
|
||||||
|
const cloned = useMemo(() => gltf?.scene.clone(), [gltf]);
|
||||||
|
|
||||||
|
if (!cloned) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<group ref={matRef} {...props} dispose={null}>
|
||||||
|
<primitive
|
||||||
|
object={cloned}
|
||||||
|
scale={[0.25, 0.25, 0.25]}
|
||||||
|
/>
|
||||||
|
</group>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.values(modelPaths).forEach((path) => {
|
||||||
|
useGLTF.preload(path);
|
||||||
|
});
|
|
@ -1,10 +1,35 @@
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
import { useActionHandler } from '../../actions/useActionHandler';
|
import { useActionHandler } from '../../actions/useActionHandler';
|
||||||
|
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||||
|
|
||||||
export function useTriggerHandler() {
|
export function useTriggerHandler() {
|
||||||
|
const { getActionByUuid } = useProductStore();
|
||||||
|
const { handleAction } = useActionHandler();
|
||||||
|
|
||||||
const triggerPointActions = useCallback((point: PointsScheme) => {
|
const handleTrigger = (trigger: TriggerSchema) => {
|
||||||
if (!point) return;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const triggerPointActions = useCallback((action: Action) => {
|
||||||
|
if (!action) return;
|
||||||
|
|
||||||
|
action.triggers.forEach(trigger => {
|
||||||
|
switch (trigger.triggerType) {
|
||||||
|
case 'onStart':
|
||||||
|
break;
|
||||||
|
case 'onComplete':
|
||||||
|
handleTrigger(trigger);
|
||||||
|
break;
|
||||||
|
case 'onStop':
|
||||||
|
break;
|
||||||
|
case 'onError':
|
||||||
|
break;
|
||||||
|
case 'delay':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warn(`Unknown trigger type: ${trigger.triggerType}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -84,6 +84,7 @@ export const useArmBotStore = create<ArmBotStore>()(
|
||||||
armBot.currentAction = {
|
armBot.currentAction = {
|
||||||
actionUuid: action.actionUuid,
|
actionUuid: action.actionUuid,
|
||||||
actionName: action.actionName,
|
actionName: action.actionName,
|
||||||
|
materialType: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ export const useMachineStore = create<MachineStore>()(
|
||||||
armBot.currentAction = {
|
armBot.currentAction = {
|
||||||
actionUuid: action.actionUuid,
|
actionUuid: action.actionUuid,
|
||||||
actionName: action.actionName,
|
actionName: action.actionName,
|
||||||
|
materialType: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ type ProductsStore = {
|
||||||
getEventByModelUuid: (productId: string, modelUuid: string) => EventsSchema | undefined;
|
getEventByModelUuid: (productId: string, modelUuid: string) => EventsSchema | undefined;
|
||||||
getPointByUuid: (productId: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
|
getPointByUuid: (productId: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
|
||||||
getActionByUuid: (productId: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
|
getActionByUuid: (productId: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
|
||||||
|
getModelUuidByPointUuid: (productId: string, actionUuid: string) => (string) | undefined;
|
||||||
getModelUuidByActionUuid: (productId: string, actionUuid: string) => (string) | undefined;
|
getModelUuidByActionUuid: (productId: string, actionUuid: string) => (string) | undefined;
|
||||||
getPointUuidByActionUuid: (productId: string, actionUuid: string) => (string) | undefined;
|
getPointUuidByActionUuid: (productId: string, actionUuid: string) => (string) | undefined;
|
||||||
getTriggerByUuid: (productId: string, triggerUuid: string) => TriggerSchema | undefined;
|
getTriggerByUuid: (productId: string, triggerUuid: string) => TriggerSchema | undefined;
|
||||||
|
@ -575,6 +576,27 @@ export const useProductStore = create<ProductsStore>()(
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getModelUuidByPointUuid: (productId, pointUuid) => {
|
||||||
|
const product = get().products.find(p => p.productId === productId);
|
||||||
|
if (!product) return undefined;
|
||||||
|
|
||||||
|
for (const event of product.eventDatas) {
|
||||||
|
if ('points' in event) {
|
||||||
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
|
if (point.uuid === pointUuid) {
|
||||||
|
return event.modelUuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ('point' in event) {
|
||||||
|
const point = (event as any).point;
|
||||||
|
if (point.uuid === pointUuid) {
|
||||||
|
return event.modelUuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
|
||||||
getModelUuidByActionUuid: (productId, actionUuid) => {
|
getModelUuidByActionUuid: (productId, actionUuid) => {
|
||||||
const product = get().products.find(p => p.productId === productId);
|
const product = get().products.find(p => p.productId === productId);
|
||||||
if (!product) return undefined;
|
if (!product) return undefined;
|
||||||
|
|
|
@ -2,15 +2,6 @@
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { immer } from 'zustand/middleware/immer';
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
interface VehicleStatus extends VehicleEventSchema {
|
|
||||||
productId: string;
|
|
||||||
isActive: boolean;
|
|
||||||
idleTime: number;
|
|
||||||
activeTime: number;
|
|
||||||
currentLoad: number;
|
|
||||||
distanceTraveled: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface VehiclesStore {
|
interface VehiclesStore {
|
||||||
vehicles: VehicleStatus[];
|
vehicles: VehicleStatus[];
|
||||||
|
|
||||||
|
@ -27,6 +18,7 @@ interface VehiclesStore {
|
||||||
incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void;
|
incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void;
|
||||||
decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void;
|
decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void;
|
||||||
setVehicleState: (modelUuid: string, newState: VehicleStatus['state']) => void;
|
setVehicleState: (modelUuid: string, newState: VehicleStatus['state']) => void;
|
||||||
|
setMaterialType: (modelUuid: string, materialType: string | null) => void;
|
||||||
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
|
||||||
|
@ -51,6 +43,7 @@ export const useVehicleStore = create<VehiclesStore>()(
|
||||||
idleTime: 0,
|
idleTime: 0,
|
||||||
activeTime: 0,
|
activeTime: 0,
|
||||||
currentLoad: 0,
|
currentLoad: 0,
|
||||||
|
materialType: null,
|
||||||
distanceTraveled: 0,
|
distanceTraveled: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -123,6 +116,15 @@ export const useVehicleStore = create<VehiclesStore>()(
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setMaterialType: (modelUuid, materialType) => {
|
||||||
|
set((state) => {
|
||||||
|
const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
|
||||||
|
if (vehicle) {
|
||||||
|
vehicle.materialType = materialType;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
incrementActiveTime: (modelUuid, incrementBy) => {
|
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
|
const vehicle = state.vehicles.find(v => v.modelUuid === modelUuid);
|
||||||
|
|
|
@ -22,74 +22,35 @@ interface ConveyorPointSchema {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
rotation: [number, number, number];
|
rotation: [number, number, number];
|
||||||
action: {
|
action: ConveyorAction;
|
||||||
actionUuid: string;
|
|
||||||
actionName: string;
|
|
||||||
actionType: "default" | "spawn" | "swap" | "delay" | "despawn";
|
|
||||||
material: string;
|
|
||||||
delay: number;
|
|
||||||
spawnInterval: number;
|
|
||||||
spawnCount: number;
|
|
||||||
triggers: TriggerSchema[];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VehiclePointSchema {
|
interface VehiclePointSchema {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
rotation: [number, number, number];
|
rotation: [number, number, number];
|
||||||
action: {
|
action: VehicleAction;
|
||||||
actionUuid: string;
|
|
||||||
actionName: string;
|
|
||||||
actionType: "travel";
|
|
||||||
unLoadDuration: number;
|
|
||||||
loadCapacity: number;
|
|
||||||
steeringAngle: number;
|
|
||||||
pickUpPoint: { position: { x: number; y: number, z: number }, rotation: { x: number; y: number, z: number } } | null;
|
|
||||||
unLoadPoint: { position: { x: number; y: number, z: number }, rotation: { x: number; y: number, z: number } } | null;
|
|
||||||
triggers: TriggerSchema[];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RoboticArmPointSchema {
|
interface RoboticArmPointSchema {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
rotation: [number, number, number];
|
rotation: [number, number, number];
|
||||||
actions: {
|
actions: RoboticArmAction[];
|
||||||
actionUuid: string;
|
|
||||||
actionName: string;
|
|
||||||
actionType: "pickAndPlace";
|
|
||||||
process: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; };
|
|
||||||
triggers: TriggerSchema[];
|
|
||||||
}[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MachinePointSchema {
|
interface MachinePointSchema {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
rotation: [number, number, number];
|
rotation: [number, number, number];
|
||||||
action: {
|
action: MachineAction;
|
||||||
actionUuid: string;
|
|
||||||
actionName: string;
|
|
||||||
actionType: "process";
|
|
||||||
processTime: number;
|
|
||||||
swapMaterial: string;
|
|
||||||
triggers: TriggerSchema[];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StoragePointSchema {
|
interface StoragePointSchema {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
rotation: [number, number, number];
|
rotation: [number, number, number];
|
||||||
action: {
|
action: StorageAction;
|
||||||
actionUuid: string;
|
|
||||||
actionName: string;
|
|
||||||
actionType: "store";
|
|
||||||
materials: { materialName: string; materialId: string; }[];
|
|
||||||
storageCapacity: number;
|
|
||||||
triggers: TriggerSchema[];
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConveyorEventSchema extends AssetEventSchema {
|
interface ConveyorEventSchema extends AssetEventSchema {
|
||||||
|
@ -120,92 +81,6 @@ interface StorageEventSchema extends AssetEventSchema {
|
||||||
point: StoragePointSchema;
|
point: StoragePointSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
type PointsScheme = ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema;
|
|
||||||
|
|
||||||
type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema;
|
|
||||||
|
|
||||||
type productsSchema = {
|
|
||||||
productName: string;
|
|
||||||
productId: string;
|
|
||||||
eventDatas: EventsSchema[];
|
|
||||||
}[]
|
|
||||||
|
|
||||||
|
|
||||||
interface ConveyorStatus extends ConveyorEventSchema {
|
|
||||||
productId: string;
|
|
||||||
isActive: boolean;
|
|
||||||
idleTime: number;
|
|
||||||
activeTime: number;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MachineStatus extends MachineEventSchema {
|
|
||||||
productId: string;
|
|
||||||
isActive: boolean;
|
|
||||||
idleTime: number;
|
|
||||||
activeTime: number;
|
|
||||||
currentAction?: {
|
|
||||||
actionUuid: string;
|
|
||||||
actionName: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ArmBotStatus extends RoboticArmEventSchema {
|
|
||||||
productId: string;
|
|
||||||
isActive: boolean;
|
|
||||||
idleTime: number;
|
|
||||||
activeTime: number;
|
|
||||||
currentAction?: {
|
|
||||||
actionUuid: string;
|
|
||||||
actionName: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface VehicleStatus extends VehicleEventSchema {
|
|
||||||
productId: string;
|
|
||||||
isActive: boolean;
|
|
||||||
idleTime: number;
|
|
||||||
activeTime: number;
|
|
||||||
currentLoad: number;
|
|
||||||
distanceTraveled: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface StorageUnitStatus extends StorageEventSchema {
|
|
||||||
productId: string;
|
|
||||||
isActive: boolean;
|
|
||||||
idleTime: number;
|
|
||||||
activeTime: number;
|
|
||||||
currentLoad: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface MaterialSchema {
|
|
||||||
materialId: string;
|
|
||||||
materialName: stri9ng;
|
|
||||||
materialType: string;
|
|
||||||
isActive: boolean;
|
|
||||||
isVisible: boolean;
|
|
||||||
isRendered: boolean;
|
|
||||||
startTime?: string;
|
|
||||||
endTime?: string;
|
|
||||||
cost?: number;
|
|
||||||
weight?: number;
|
|
||||||
|
|
||||||
current: {
|
|
||||||
modelUuid: string;
|
|
||||||
pointUuid: string;
|
|
||||||
actionUuid: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
next?: {
|
|
||||||
modelUuid: string;
|
|
||||||
pointUuid: string;
|
|
||||||
actionUuid: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
type MaterialsSchema = MaterialSchema[];
|
|
||||||
|
|
||||||
|
|
||||||
interface ConveyorAction {
|
interface ConveyorAction {
|
||||||
actionUuid: string;
|
actionUuid: string;
|
||||||
actionName: string;
|
actionName: string;
|
||||||
|
@ -256,3 +131,90 @@ interface StorageAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Action = ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction;
|
type Action = ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction;
|
||||||
|
|
||||||
|
type PointsScheme = ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema;
|
||||||
|
|
||||||
|
type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema;
|
||||||
|
|
||||||
|
type productsSchema = {
|
||||||
|
productName: string;
|
||||||
|
productId: string;
|
||||||
|
eventDatas: EventsSchema[];
|
||||||
|
}[]
|
||||||
|
|
||||||
|
|
||||||
|
interface ConveyorStatus extends ConveyorEventSchema {
|
||||||
|
productId: string;
|
||||||
|
isActive: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MachineStatus extends MachineEventSchema {
|
||||||
|
productId: string;
|
||||||
|
isActive: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
currentAction?: {
|
||||||
|
actionUuid: string;
|
||||||
|
actionName: string;
|
||||||
|
materialType: string | null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArmBotStatus extends RoboticArmEventSchema {
|
||||||
|
productId: string;
|
||||||
|
isActive: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
currentAction?: {
|
||||||
|
actionUuid: string;
|
||||||
|
actionName: string;
|
||||||
|
materialType: string | null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VehicleStatus extends VehicleEventSchema {
|
||||||
|
productId: string;
|
||||||
|
isActive: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
currentLoad: number;
|
||||||
|
materialType: string | null;
|
||||||
|
distanceTraveled: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StorageUnitStatus extends StorageEventSchema {
|
||||||
|
productId: string;
|
||||||
|
isActive: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
currentLoad: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MaterialSchema {
|
||||||
|
materialId: string;
|
||||||
|
materialName: stri9ng;
|
||||||
|
materialType: string;
|
||||||
|
isActive: boolean;
|
||||||
|
isVisible: boolean;
|
||||||
|
isRendered: boolean;
|
||||||
|
startTime?: string;
|
||||||
|
endTime?: string;
|
||||||
|
cost?: number;
|
||||||
|
weight?: number;
|
||||||
|
|
||||||
|
current: {
|
||||||
|
modelUuid: string;
|
||||||
|
pointUuid: string;
|
||||||
|
actionUuid: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
next?: {
|
||||||
|
modelUuid: string;
|
||||||
|
pointUuid: string;
|
||||||
|
actionUuid: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type MaterialsSchema = MaterialSchema[];
|
Loading…
Reference in New Issue