feat: Refactor human action handling to support animated travel and streamline action structure
This commit is contained in:
@@ -1,31 +1,25 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { MathUtils } from "three";
|
||||
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
||||
import RenameInput from "../../../../../ui/inputs/RenameInput";
|
||||
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
|
||||
import Trigger from "../trigger/Trigger";
|
||||
import { useSelectedEventData, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
|
||||
import PickAndPlaceAction from "../actions/PickAndPlaceAction";
|
||||
import ActionsList from "../components/ActionsList";
|
||||
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
|
||||
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useVersionContext } from "../../../../../../modules/builder/version/versionContext";
|
||||
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
|
||||
import InputToggle from "../../../../../ui/inputs/InputToggle";
|
||||
import ActionsList from "../components/ActionsList";
|
||||
|
||||
function HumanMechanics() {
|
||||
const [activeOption, setActiveOption] = useState<"animation" | "animatedTravel">("animation");
|
||||
const [activeAnimationOption, setActiveAnimationOption] = useState("");
|
||||
const [animationOptions, setAnimationOptions] = useState<string[]>([]);
|
||||
const [activeOption, setActiveOption] = useState<"animatedTravel">("animatedTravel");
|
||||
const [speed, setSpeed] = useState("0.5");
|
||||
const [currentAction, setCurrentAction] = useState<HumanAction | undefined>();
|
||||
const [isLoopAnimation, setIsLoopAnimation] = useState(false);
|
||||
const [selectedPointData, setSelectedPointData] = useState<HumanPointSchema | undefined>();
|
||||
const { selectedEventData } = useSelectedEventData();
|
||||
const { productStore, assetStore } = useSceneContext();
|
||||
const { getAssetById } = assetStore();
|
||||
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction } = productStore();
|
||||
const { productStore } = useSceneContext();
|
||||
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
|
||||
@@ -41,15 +35,10 @@ function HumanMechanics() {
|
||||
selectedEventData.selectedPoint
|
||||
) as HumanPointSchema | undefined;
|
||||
|
||||
if (point?.actions) {
|
||||
if (point?.action) {
|
||||
setSelectedPointData(point);
|
||||
if (point.actions.length > 0) {
|
||||
setSelectedAction(point.actions[0].actionUuid, point.actions[0].actionName);
|
||||
const asset = getAssetById(selectedEventData.data.modelUuid);
|
||||
if (asset && asset.animations) {
|
||||
setAnimationOptions(asset.animations)
|
||||
}
|
||||
}
|
||||
const action = point.action;
|
||||
setSelectedAction(action.actionUuid, action.actionName);
|
||||
}
|
||||
} else {
|
||||
clearSelectedAction();
|
||||
@@ -73,15 +62,11 @@ function HumanMechanics() {
|
||||
selectedEventData.selectedPoint
|
||||
) as HumanPointSchema | undefined;
|
||||
|
||||
if (point?.actions) {
|
||||
if (point?.action) {
|
||||
setSelectedPointData(point);
|
||||
const action = point.actions.find((a) => a.actionUuid === selectedAction.actionId);
|
||||
if (action) {
|
||||
setCurrentAction(action);
|
||||
setIsLoopAnimation(action.loopAnimation ?? false);
|
||||
setActiveOption(action.actionType as "animation" | "animatedTravel");
|
||||
setActiveAnimationOption(action.animation || '')
|
||||
}
|
||||
const action = point.action;
|
||||
setCurrentAction(action);
|
||||
setActiveOption(action.actionType as "animatedTravel");
|
||||
}
|
||||
} else {
|
||||
clearSelectedAction();
|
||||
@@ -106,73 +91,18 @@ function HumanMechanics() {
|
||||
};
|
||||
|
||||
const handleSelectActionType = (actionType: string) => {
|
||||
if (!selectedAction.actionId) return;
|
||||
setActiveOption(actionType as "animation" | "animatedTravel");
|
||||
if (!currentAction) return;
|
||||
setActiveOption(actionType as "animatedTravel");
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedAction.actionId,
|
||||
{ actionType: actionType as "animation" | "animatedTravel" }
|
||||
currentAction.actionUuid,
|
||||
{ actionType: actionType as "animatedTravel" }
|
||||
);
|
||||
|
||||
if (selectedPointData) {
|
||||
const updatedActions = selectedPointData.actions.map((action) =>
|
||||
action.actionUuid === selectedAction.actionId
|
||||
? { ...action, actionType: actionType as "animation" | "animatedTravel" }
|
||||
: action
|
||||
);
|
||||
setSelectedPointData({ ...selectedPointData, actions: updatedActions });
|
||||
}
|
||||
|
||||
if (event) {
|
||||
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
|
||||
}
|
||||
}
|
||||
|
||||
const handleSelectAnimation = (animationOption: string) => {
|
||||
if (!selectedAction.actionId) return;
|
||||
setActiveAnimationOption(animationOption);
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedAction.actionId,
|
||||
{ animation: animationOption }
|
||||
);
|
||||
|
||||
if (selectedPointData) {
|
||||
const updatedActions = selectedPointData.actions.map((action) =>
|
||||
action.actionUuid === selectedAction.actionId
|
||||
? { ...action, animation: animationOption }
|
||||
: action
|
||||
);
|
||||
setSelectedPointData({ ...selectedPointData, actions: updatedActions });
|
||||
}
|
||||
|
||||
if (event) {
|
||||
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
|
||||
}
|
||||
}
|
||||
|
||||
const handleLoopAnimationChange = () => {
|
||||
if (!selectedAction.actionId || !currentAction) return;
|
||||
|
||||
const updatedValue = !isLoopAnimation;
|
||||
setIsLoopAnimation(updatedValue);
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedAction.actionId,
|
||||
{ loopAnimation: updatedValue }
|
||||
);
|
||||
|
||||
if (selectedPointData) {
|
||||
const updatedActions = selectedPointData.actions.map((action) =>
|
||||
action.actionUuid === selectedAction.actionId
|
||||
? { ...action, loopAnimation: updatedValue }
|
||||
: action
|
||||
);
|
||||
setSelectedPointData({ ...selectedPointData, actions: updatedActions });
|
||||
setCurrentAction(updatedActions.find((a) => a.actionUuid === selectedAction.actionId));
|
||||
if (event && selectedPointData) {
|
||||
const updatedAction = { ...selectedPointData.action, actionType: actionType as "animatedTravel" };
|
||||
setSelectedPointData({ ...selectedPointData, action: updatedAction });
|
||||
}
|
||||
|
||||
if (event) {
|
||||
@@ -181,20 +111,17 @@ function HumanMechanics() {
|
||||
};
|
||||
|
||||
const handleRenameAction = (newName: string) => {
|
||||
if (!selectedAction.actionId) return;
|
||||
if (!currentAction) return;
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedAction.actionId,
|
||||
currentAction.actionUuid,
|
||||
{ actionName: newName }
|
||||
);
|
||||
|
||||
if (selectedPointData) {
|
||||
const updatedActions = selectedPointData.actions.map((action) =>
|
||||
action.actionUuid === selectedAction.actionId
|
||||
? { ...action, actionName: newName }
|
||||
: action
|
||||
);
|
||||
setSelectedPointData({ ...selectedPointData, actions: updatedActions });
|
||||
if (event && selectedPointData) {
|
||||
const updatedAction = { ...selectedPointData.action, actionName: newName };
|
||||
setSelectedPointData({ ...selectedPointData, action: updatedAction });
|
||||
}
|
||||
|
||||
if (event) {
|
||||
@@ -217,11 +144,11 @@ function HumanMechanics() {
|
||||
};
|
||||
|
||||
const handleClearPoints = () => {
|
||||
if (!selectedAction.actionId || !selectedPointData) return;
|
||||
if (!currentAction) return;
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedAction.actionId,
|
||||
currentAction.actionUuid,
|
||||
{
|
||||
travelPoints: {
|
||||
startPoint: null,
|
||||
@@ -235,66 +162,9 @@ function HumanMechanics() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleAddAction = () => {
|
||||
if (!selectedEventData || !selectedPointData) return;
|
||||
|
||||
const newAction: HumanAction = {
|
||||
actionUuid: MathUtils.generateUUID(),
|
||||
actionName: `Action ${selectedPointData.actions.length + 1}`,
|
||||
actionType: "animation",
|
||||
animation: null,
|
||||
loadCapacity: 1,
|
||||
loopAnimation: true,
|
||||
travelPoints: {
|
||||
startPoint: null,
|
||||
endPoint: null,
|
||||
},
|
||||
triggers: [],
|
||||
};
|
||||
|
||||
const event = addAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData.data.modelUuid,
|
||||
selectedEventData.selectedPoint,
|
||||
newAction
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
|
||||
}
|
||||
|
||||
const updatedPoint = { ...selectedPointData, actions: [...selectedPointData.actions, newAction] };
|
||||
setSelectedPointData(updatedPoint);
|
||||
setSelectedAction(newAction.actionUuid, newAction.actionName);
|
||||
};
|
||||
|
||||
const handleDeleteAction = (actionUuid: string) => {
|
||||
if (!selectedPointData) return;
|
||||
|
||||
const event = removeAction(selectedProduct.productUuid, actionUuid);
|
||||
|
||||
if (event) {
|
||||
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
|
||||
}
|
||||
|
||||
const index = selectedPointData.actions.findIndex((a) => a.actionUuid === actionUuid);
|
||||
const newActions = selectedPointData.actions.filter((a) => a.actionUuid !== actionUuid);
|
||||
const updatedPoint = { ...selectedPointData, actions: newActions };
|
||||
setSelectedPointData(updatedPoint);
|
||||
|
||||
if (selectedAction.actionId === actionUuid) {
|
||||
const nextAction = newActions[index] || newActions[index - 1];
|
||||
if (nextAction) {
|
||||
setSelectedAction(nextAction.actionUuid, nextAction.actionName);
|
||||
} else {
|
||||
clearSelectedAction();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const availableActions = {
|
||||
defaultOption: "animatedTravel",
|
||||
options: ["animation", "animatedTravel"],
|
||||
options: ["animatedTravel"],
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -316,19 +186,20 @@ function HumanMechanics() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section>
|
||||
<ActionsList
|
||||
selectedPointData={selectedPointData}
|
||||
multipleAction
|
||||
handleAddAction={handleAddAction}
|
||||
handleDeleteAction={handleDeleteAction}
|
||||
/>
|
||||
|
||||
{selectedAction.actionId && currentAction && (
|
||||
{currentAction && (
|
||||
<section>
|
||||
|
||||
<ActionsList
|
||||
selectedPointData={selectedPointData}
|
||||
multipleAction={false}
|
||||
handleAddAction={() => { }}
|
||||
handleDeleteAction={() => { }}
|
||||
/>
|
||||
<div className="selected-actions-details">
|
||||
<div className="selected-actions-header">
|
||||
<RenameInput
|
||||
value={selectedAction.actionName || ""}
|
||||
value={currentAction.actionName || ""}
|
||||
onRename={handleRenameAction}
|
||||
/>
|
||||
</div>
|
||||
@@ -340,32 +211,19 @@ function HumanMechanics() {
|
||||
onSelect={handleSelectActionType}
|
||||
disabled={true}
|
||||
/>
|
||||
<LabledDropdown
|
||||
label="Animation"
|
||||
defaultOption={activeAnimationOption}
|
||||
options={animationOptions}
|
||||
onSelect={handleSelectAnimation}
|
||||
disabled={true}
|
||||
/>
|
||||
<InputToggle
|
||||
value={isLoopAnimation}
|
||||
inputKey=""
|
||||
label="Loop Animation"
|
||||
onClick={handleLoopAnimationChange}
|
||||
/>
|
||||
{activeOption === 'animatedTravel' &&
|
||||
{activeOption === 'animatedTravel' && (
|
||||
<PickAndPlaceAction clearPoints={handleClearPoints} />
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
<div className="tirgger">
|
||||
<Trigger
|
||||
selectedPointData={selectedPointData as any}
|
||||
type={"Human"}
|
||||
type="Human"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
</section>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -256,21 +256,18 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
|
||||
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
|
||||
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
|
||||
rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0],
|
||||
actions: [
|
||||
{
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "animation",
|
||||
animation: null,
|
||||
loopAnimation: true,
|
||||
loadCapacity: 1,
|
||||
travelPoints: {
|
||||
startPoint: null,
|
||||
endPoint: null,
|
||||
},
|
||||
triggers: []
|
||||
}
|
||||
]
|
||||
action: {
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "animatedTravel",
|
||||
loadCapacity: 1,
|
||||
travelPoints: {
|
||||
startPoint: null,
|
||||
endPoint: null,
|
||||
},
|
||||
triggers: []
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
addEvent(humanEvent);
|
||||
|
||||
@@ -374,21 +374,18 @@ async function handleModelLoad(
|
||||
uuid: THREE.MathUtils.generateUUID(),
|
||||
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
||||
rotation: [0, 0, 0],
|
||||
actions: [
|
||||
{
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "animation",
|
||||
animation: null,
|
||||
loopAnimation: true,
|
||||
loadCapacity: 1,
|
||||
travelPoints: {
|
||||
startPoint: null,
|
||||
endPoint: null,
|
||||
},
|
||||
triggers: []
|
||||
}
|
||||
]
|
||||
action: {
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "animatedTravel",
|
||||
loadCapacity: 1,
|
||||
travelPoints: {
|
||||
startPoint: null,
|
||||
endPoint: null,
|
||||
},
|
||||
triggers: []
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
addEvent(humanEvent);
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { useCallback } from "react";
|
||||
import { useSceneContext } from "../../../../scene/sceneContext";
|
||||
import { useProductContext } from "../../../products/productContext";
|
||||
|
||||
export function useAnimationHandler() {
|
||||
const { materialStore, humanStore, productStore } = useSceneContext();
|
||||
const { getMaterialById } = materialStore();
|
||||
const { } = humanStore();
|
||||
const { getModelUuidByActionUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
|
||||
const animationLogStatus = (materialUuid: string, status: string) => {
|
||||
echo.info(`${materialUuid}, ${status}`);
|
||||
}
|
||||
|
||||
const handleAnimation = useCallback((action: HumanAction, materialId?: string) => {
|
||||
if (!action || action.actionType !== 'animation' || !materialId) return;
|
||||
|
||||
const material = getMaterialById(materialId);
|
||||
if (!material) return;
|
||||
|
||||
const modelUuid = getModelUuidByActionUuid(selectedProduct.productUuid, action.actionUuid);
|
||||
if (!modelUuid) return;
|
||||
|
||||
|
||||
animationLogStatus(material.materialName, `performing animation`);
|
||||
|
||||
}, [getMaterialById]);
|
||||
|
||||
return {
|
||||
handleAnimation,
|
||||
};
|
||||
}
|
||||
@@ -1,15 +1,9 @@
|
||||
import { useEffect, useCallback } from 'react';
|
||||
import { useAnimationHandler } from './actionHandler/useAnimationHandler';
|
||||
import { useAnimatedTravelHandler } from './actionHandler/useAnimatedTravelHandler';
|
||||
|
||||
export function useHumanActions() {
|
||||
const { handleAnimation } = useAnimationHandler();
|
||||
const { handleAnimatedTravel } = useAnimatedTravelHandler();
|
||||
|
||||
const handleAnimationAction = useCallback((action: HumanAction, materialId: string) => {
|
||||
handleAnimation(action, materialId);
|
||||
}, [handleAnimation]);
|
||||
|
||||
const handleAnimatedTravelAction = useCallback((action: HumanAction) => {
|
||||
handleAnimatedTravel(action);
|
||||
}, [handleAnimatedTravel]);
|
||||
@@ -18,16 +12,13 @@ export function useHumanActions() {
|
||||
if (!action) return;
|
||||
|
||||
switch (action.actionType) {
|
||||
case 'animation':
|
||||
handleAnimationAction(action, materialId);
|
||||
break;
|
||||
case 'animatedTravel':
|
||||
handleAnimatedTravelAction(action);
|
||||
break;
|
||||
default:
|
||||
console.warn(`Unknown Human action type: ${action.actionType}`);
|
||||
}
|
||||
}, [handleAnimationAction, handleAnimatedTravelAction]);
|
||||
}, [handleAnimatedTravelAction]);
|
||||
|
||||
const cleanup = useCallback(() => {
|
||||
}, []);
|
||||
|
||||
@@ -39,7 +39,7 @@ export function useActionHandler() {
|
||||
case 'store': case 'retrieve':
|
||||
handleStorageAction(action as StorageAction, materialId as string);
|
||||
break;
|
||||
case 'animation': case 'animatedTravel':
|
||||
case 'animatedTravel':
|
||||
handleHumanAction(action as HumanAction, materialId as string);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -155,8 +155,8 @@ function TriggerConnector() {
|
||||
// Handle Human point
|
||||
else if (event.type === "human" && 'point' in event) {
|
||||
const point = event.point;
|
||||
point.actions?.forEach(action => {
|
||||
action.triggers?.forEach(trigger => {
|
||||
if (point.action?.triggers) {
|
||||
point.action.triggers.forEach(trigger => {
|
||||
if (trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint) {
|
||||
newConnections.push({
|
||||
id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
|
||||
@@ -166,7 +166,7 @@ function TriggerConnector() {
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -24,11 +24,6 @@ interface HumansStore {
|
||||
getLastMaterial: (modelUuid: string) => { materialType: string; materialId: string } | undefined;
|
||||
clearCurrentMaterials: (modelUuid: string) => void;
|
||||
|
||||
setCurrentAction: (
|
||||
modelUuid: string,
|
||||
action: HumanStatus["currentAction"]
|
||||
) => void;
|
||||
|
||||
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||
incrementDistanceTraveled: (modelUuid: string, incrementBy: number) => void;
|
||||
@@ -175,15 +170,6 @@ export const createHumanStore = () => {
|
||||
});
|
||||
},
|
||||
|
||||
setCurrentAction: (modelUuid, action) => {
|
||||
set((state) => {
|
||||
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||
if (human) {
|
||||
human.currentAction = action;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||
|
||||
@@ -32,13 +32,13 @@ type ProductsStore = {
|
||||
productUuid: string,
|
||||
modelUuid: string,
|
||||
pointUuid: string,
|
||||
action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]
|
||||
action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['action']
|
||||
) => EventsSchema | undefined;
|
||||
removeAction: (productUuid: string, actionUuid: string) => EventsSchema | undefined;
|
||||
updateAction: (
|
||||
productUuid: string,
|
||||
actionUuid: string,
|
||||
updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]>
|
||||
updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['action']>
|
||||
) => EventsSchema | undefined;
|
||||
|
||||
// Trigger-level actionss
|
||||
|
||||
6
app/src/types/simulationTypes.d.ts
vendored
6
app/src/types/simulationTypes.d.ts
vendored
@@ -72,9 +72,7 @@ interface StorageAction {
|
||||
interface HumanAction {
|
||||
actionUuid: string;
|
||||
actionName: string;
|
||||
actionType: "animation" | "animatedTravel";
|
||||
animation: string | null;
|
||||
loopAnimation: boolean;
|
||||
actionType: "animatedTravel";
|
||||
loadCapacity: number;
|
||||
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }
|
||||
triggers: TriggerSchema[];
|
||||
@@ -122,7 +120,7 @@ interface HumanPointSchema {
|
||||
uuid: string;
|
||||
position: [number, number, number];
|
||||
rotation: [number, number, number];
|
||||
actions: HumanAction[];
|
||||
action: HumanAction;
|
||||
}
|
||||
|
||||
type PointsScheme = | ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema;
|
||||
|
||||
Reference in New Issue
Block a user