human to conveyor, conveyor to human multiple actions completed
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||
import Vector3Input from "../customInput/Vector3Input";
|
||||
import { useSelectedZoneStore } from "../../../../store/visualization/useZoneStore";
|
||||
import {
|
||||
useEditPosition,
|
||||
usezonePosition,
|
||||
useZones,
|
||||
usezoneTarget,
|
||||
} from "../../../../store/builder/store";
|
||||
import { zoneCameraUpdate } from "../../../../services/visulization/zone/zoneCameraUpdation";
|
||||
@@ -19,12 +18,11 @@ const ZoneProperties: React.FC = () => {
|
||||
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
|
||||
const { zonePosition, setZonePosition } = usezonePosition();
|
||||
const { zoneTarget, setZoneTarget } = usezoneTarget();
|
||||
// const { zones, setZones } = useZones();
|
||||
const { assetStore, zoneStore } = useSceneContext();
|
||||
const { zoneStore } = useSceneContext();
|
||||
const { zones, setZoneName } = zoneStore()
|
||||
|
||||
const { projectId } = useParams();
|
||||
const { userName, userId, organization, email } = getUserData();
|
||||
const { organization } = getUserData();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ interface AssemblyActionProps {
|
||||
swapOptions: string[];
|
||||
swapDefaultOption: string;
|
||||
onSwapSelect: (value: string) => void;
|
||||
clearPoints: () => void;
|
||||
}
|
||||
|
||||
const AssemblyAction: React.FC<AssemblyActionProps> = ({
|
||||
@@ -20,6 +21,7 @@ const AssemblyAction: React.FC<AssemblyActionProps> = ({
|
||||
swapOptions,
|
||||
swapDefaultOption,
|
||||
onSwapSelect,
|
||||
clearPoints
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
@@ -37,6 +39,19 @@ const AssemblyAction: React.FC<AssemblyActionProps> = ({
|
||||
defaultOption={swapDefaultOption}
|
||||
onSelect={onSwapSelect}
|
||||
/>
|
||||
<div className="selected-actions-list">
|
||||
<div className="value-field-container">
|
||||
<div className="label">Reset Points</div>
|
||||
<button
|
||||
id="reset-button"
|
||||
type="button"
|
||||
className="regularDropdown-container"
|
||||
onClick={clearPoints}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,18 +8,29 @@ interface WorkerActionProps {
|
||||
max: number;
|
||||
step: number;
|
||||
defaultValue: string;
|
||||
disabled?: boolean,
|
||||
disabled?: boolean;
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
loadCount?: {
|
||||
value: number;
|
||||
min: number;
|
||||
max: number;
|
||||
step: number;
|
||||
defaultValue: string,
|
||||
disabled: false,
|
||||
onChange: (value: number) => void;
|
||||
};
|
||||
clearPoints: () => void;
|
||||
}
|
||||
|
||||
const WorkerAction: React.FC<WorkerActionProps> = ({
|
||||
loadCapacity,
|
||||
loadCount,
|
||||
clearPoints,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<div className="worker-action-container">
|
||||
{/* Load Capacity Input */}
|
||||
<InputWithDropDown
|
||||
label="Load Capacity"
|
||||
value={loadCapacity.value}
|
||||
@@ -32,23 +43,39 @@ const WorkerAction: React.FC<WorkerActionProps> = ({
|
||||
onClick={() => { }}
|
||||
onChange={loadCapacity.onChange}
|
||||
/>
|
||||
|
||||
{/* Load Count Input */}
|
||||
{loadCount && (
|
||||
<InputWithDropDown
|
||||
label="Load Count"
|
||||
value={loadCount.value.toString()}
|
||||
min={loadCount.min}
|
||||
max={loadCount.max}
|
||||
disabled={loadCount.disabled}
|
||||
defaultValue={loadCount.defaultValue}
|
||||
step={loadCount.step}
|
||||
activeOption="unit"
|
||||
onClick={() => { }}
|
||||
onChange={(value) => loadCount.onChange(parseInt(value))}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Clear Points Button */}
|
||||
<div className="selected-actions-list">
|
||||
<div className="value-field-container">
|
||||
<div className="label">Reset</div>
|
||||
<div className="label">Reset Points</div>
|
||||
<button
|
||||
id="rest-button"
|
||||
id="reset-button"
|
||||
type="button"
|
||||
className="regularDropdown-container"
|
||||
onClick={() => {
|
||||
clearPoints();
|
||||
}}
|
||||
onClick={clearPoints}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WorkerAction;
|
||||
export default WorkerAction;
|
||||
@@ -18,10 +18,17 @@ import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
|
||||
|
||||
function ConveyorMechanics() {
|
||||
const [activeOption, setActiveOption] = useState<"default" | "spawn" | "swap" | "delay" | "despawn">("default");
|
||||
const [speed, setSpeed] = useState("0.5");
|
||||
const [actionName, setActionName] = useState("Action Name");
|
||||
const [material, setMaterial] = useState("Default material");
|
||||
const [spawnCount, setSpawnCount] = useState("1");
|
||||
const [spawnInterval, setSpawnInterval] = useState("1");
|
||||
const [delay, setDelay] = useState("0");
|
||||
const [selectedPointData, setSelectedPointData] = useState<ConveyorPointSchema | undefined>();
|
||||
|
||||
const { selectedEventData } = useSelectedEventData();
|
||||
const { productStore } = useSceneContext();
|
||||
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction } = productStore();
|
||||
const { getPointByUuid, updateEvent, updateAction, getEventByModelUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { setSelectedAction, clearSelectedAction } = useSelectedAction();
|
||||
@@ -36,9 +43,21 @@ function ConveyorMechanics() {
|
||||
selectedEventData?.data.modelUuid,
|
||||
selectedEventData?.selectedPoint
|
||||
) as ConveyorPointSchema | undefined;
|
||||
if (point && "action" in point) {
|
||||
|
||||
const event = getEventByModelUuid(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData?.data.modelUuid
|
||||
) as ConveyorEventSchema | undefined;
|
||||
|
||||
if (point && "action" in point && event) {
|
||||
setSelectedPointData(point);
|
||||
setActiveOption(point.action.actionType as | "default" | "spawn" | "swap" | "delay" | "despawn");
|
||||
setActiveOption(point.action.actionType);
|
||||
setActionName(point.action.actionName);
|
||||
setSpeed(event.speed?.toString() || "0.5");
|
||||
setMaterial(point.action.material || "Default material");
|
||||
setSpawnCount(point.action.spawnCount?.toString() || "1");
|
||||
setSpawnInterval(point.action.spawnInterval?.toString() || "1");
|
||||
setDelay(point.action.delay?.toString() || "0");
|
||||
setSelectedAction(point.action.actionUuid, point.action.actionName);
|
||||
}
|
||||
} else {
|
||||
@@ -53,19 +72,25 @@ function ConveyorMechanics() {
|
||||
eventData: EventsSchema
|
||||
) => {
|
||||
upsertProductOrEventApi({
|
||||
productName: productName,
|
||||
productUuid: productUuid,
|
||||
projectId: projectId,
|
||||
productName,
|
||||
productUuid,
|
||||
projectId,
|
||||
eventDatas: eventData,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
})
|
||||
}
|
||||
versionId: selectedVersion?.versionId || "",
|
||||
});
|
||||
};
|
||||
|
||||
const handleSpeedChange = (value: string) => {
|
||||
if (!selectedEventData) return;
|
||||
const event = updateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, {
|
||||
speed: parseFloat(value),
|
||||
});
|
||||
|
||||
const numericValue = parseFloat(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
const event = updateEvent(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData.data.modelUuid,
|
||||
{ speed: numericValue }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -75,16 +100,20 @@ function ConveyorMechanics() {
|
||||
event
|
||||
);
|
||||
}
|
||||
setSpeed(value);
|
||||
};
|
||||
|
||||
const handleActionTypeChange = (option: string) => {
|
||||
if (!selectedEventData || !selectedPointData) return;
|
||||
const validOption = option as | "default" | "spawn" | "swap" | "delay" | "despawn";
|
||||
if (!selectedPointData) return;
|
||||
|
||||
const validOption = option as "default" | "spawn" | "swap" | "delay" | "despawn";
|
||||
setActiveOption(validOption);
|
||||
|
||||
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, {
|
||||
actionType: validOption,
|
||||
});
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{ actionType: validOption }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -97,8 +126,14 @@ function ConveyorMechanics() {
|
||||
};
|
||||
|
||||
const handleRenameAction = (newName: string) => {
|
||||
if (!selectedEventData || !selectedPointData) return;
|
||||
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { actionName: newName });
|
||||
if (!selectedPointData) return;
|
||||
|
||||
setActionName(newName);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{ actionName: newName }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -111,10 +146,17 @@ function ConveyorMechanics() {
|
||||
};
|
||||
|
||||
const handleSpawnCountChange = (value: string) => {
|
||||
if (!selectedEventData || !selectedPointData) return;
|
||||
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, {
|
||||
spawnCount: parseFloat(value),
|
||||
});
|
||||
if (!selectedPointData) return;
|
||||
|
||||
const numericValue = parseFloat(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
setSpawnCount(value);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{ spawnCount: numericValue }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -127,10 +169,17 @@ function ConveyorMechanics() {
|
||||
};
|
||||
|
||||
const handleSpawnIntervalChange = (value: string) => {
|
||||
if (!selectedEventData || !selectedPointData) return;
|
||||
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, {
|
||||
spawnInterval: parseFloat(value),
|
||||
});
|
||||
if (!selectedPointData) return;
|
||||
|
||||
const numericValue = parseFloat(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
setSpawnInterval(value);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{ spawnInterval: numericValue }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -142,9 +191,15 @@ function ConveyorMechanics() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleMaterialSelect = (material: string) => {
|
||||
if (!selectedEventData || !selectedPointData) return;
|
||||
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { material });
|
||||
const handleMaterialSelect = (selectedMaterial: string) => {
|
||||
if (!selectedPointData) return;
|
||||
|
||||
setMaterial(selectedMaterial);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{ material: selectedMaterial }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -157,10 +212,17 @@ function ConveyorMechanics() {
|
||||
};
|
||||
|
||||
const handleDelayChange = (value: string) => {
|
||||
if (!selectedEventData || !selectedPointData) return;
|
||||
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, {
|
||||
delay: parseFloat(value),
|
||||
});
|
||||
if (!selectedPointData) return;
|
||||
|
||||
const numericValue = parseFloat(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
setDelay(value);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{ delay: numericValue }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -177,31 +239,6 @@ function ConveyorMechanics() {
|
||||
options: ["default", "spawn", "swap", "delay", "despawn"],
|
||||
};
|
||||
|
||||
// Get current values from store
|
||||
const currentSpeed = (getEventByModelUuid(
|
||||
selectedProduct.productUuid, selectedEventData?.data.modelUuid || ""
|
||||
) as ConveyorEventSchema | undefined)?.speed?.toString() || "0.5";
|
||||
|
||||
const currentActionName = selectedPointData
|
||||
? selectedPointData.action.actionName
|
||||
: "Action Name";
|
||||
|
||||
const currentMaterial = selectedPointData
|
||||
? selectedPointData.action.material
|
||||
: "Default material";
|
||||
|
||||
const currentSpawnCount = selectedPointData
|
||||
? selectedPointData.action.spawnCount?.toString() || "1"
|
||||
: "1";
|
||||
|
||||
const currentSpawnInterval = selectedPointData
|
||||
? selectedPointData.action.spawnInterval?.toString() || "1"
|
||||
: "1";
|
||||
|
||||
const currentDelay = selectedPointData
|
||||
? selectedPointData.action.delay?.toString() || "0"
|
||||
: "0";
|
||||
|
||||
return (
|
||||
<>
|
||||
<div key={selectedPointData?.uuid} className="global-props section">
|
||||
@@ -209,10 +246,10 @@ function ConveyorMechanics() {
|
||||
<div className="property-item">
|
||||
<InputWithDropDown
|
||||
label="Speed"
|
||||
value={currentSpeed}
|
||||
value={speed}
|
||||
min={0}
|
||||
step={0.1}
|
||||
defaultValue={"0.5"}
|
||||
defaultValue="0.5"
|
||||
max={10}
|
||||
activeOption="m/s"
|
||||
onClick={() => { }}
|
||||
@@ -222,24 +259,18 @@ function ConveyorMechanics() {
|
||||
</div>
|
||||
</div>
|
||||
<section>
|
||||
<ActionsList
|
||||
selectedPointData={selectedPointData}
|
||||
/>
|
||||
<ActionsList selectedPointData={selectedPointData} />
|
||||
|
||||
<div className="selected-actions-details">
|
||||
<div className="selected-actions-header">
|
||||
<RenameInput
|
||||
value={currentActionName}
|
||||
onRename={handleRenameAction}
|
||||
value={actionName}
|
||||
canEdit={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="selected-actions-list">
|
||||
<LabledDropdown
|
||||
defaultOption={
|
||||
selectedPointData
|
||||
? selectedPointData.action.actionType
|
||||
: "default"
|
||||
}
|
||||
defaultOption={activeOption}
|
||||
options={availableActions.options}
|
||||
onSelect={handleActionTypeChange}
|
||||
/>
|
||||
@@ -248,11 +279,11 @@ function ConveyorMechanics() {
|
||||
<SpawnAction
|
||||
onChangeCount={handleSpawnCountChange}
|
||||
options={["Default material", "Material 1", "Material 2", "Material 3"]}
|
||||
defaultOption={currentMaterial}
|
||||
defaultOption={material}
|
||||
onSelect={handleMaterialSelect}
|
||||
onChangeInterval={handleSpawnIntervalChange}
|
||||
intervalValue={currentSpawnInterval}
|
||||
countValue={currentSpawnCount}
|
||||
intervalValue={spawnInterval}
|
||||
countValue={spawnCount}
|
||||
intervalMin={1}
|
||||
intervalMax={60}
|
||||
intervalDefaultValue="1"
|
||||
@@ -264,14 +295,14 @@ function ConveyorMechanics() {
|
||||
{activeOption === "swap" && (
|
||||
<SwapAction
|
||||
options={["Default material", "Material 1", "Material 2", "Material 3"]}
|
||||
defaultOption={currentMaterial}
|
||||
defaultOption={material}
|
||||
onSelect={handleMaterialSelect}
|
||||
/>
|
||||
)}
|
||||
{activeOption === "despawn" && <DespawnAction />}
|
||||
{activeOption === "delay" && (
|
||||
<DelayAction
|
||||
value={currentDelay}
|
||||
value={delay}
|
||||
defaultValue="0"
|
||||
min={0}
|
||||
max={60}
|
||||
@@ -288,4 +319,4 @@ function ConveyorMechanics() {
|
||||
);
|
||||
}
|
||||
|
||||
export default ConveyorMechanics;
|
||||
export default ConveyorMechanics;
|
||||
@@ -1,22 +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 ActionsList from "../components/ActionsList";
|
||||
import WorkerAction from "../actions/workerAction";
|
||||
import AssemblyAction from "../actions/assemblyAction";
|
||||
|
||||
import { useSelectedEventData, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
|
||||
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
|
||||
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
|
||||
import { useVersionContext } from "../../../../../../modules/builder/version/versionContext";
|
||||
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
|
||||
import { useParams } from "react-router-dom";
|
||||
import WorkerAction from "../actions/workerAction";
|
||||
import AssemblyAction from "../actions/assemblyAction";
|
||||
|
||||
function HumanMechanics() {
|
||||
const [activeOption, setActiveOption] = useState<"worker" | "assembly">("worker");
|
||||
const [speed, setSpeed] = useState("0.5");
|
||||
const [loadCount, setLoadCount] = useState(0);
|
||||
const [loadCapacity, setLoadCapacity] = useState("1");
|
||||
const [processTime, setProcessTime] = useState(10);
|
||||
const [swappedMaterial, setSwappedMaterial] = useState("Default material");
|
||||
@@ -24,7 +27,7 @@ function HumanMechanics() {
|
||||
const [selectedPointData, setSelectedPointData] = useState<HumanPointSchema | undefined>();
|
||||
const { selectedEventData } = useSelectedEventData();
|
||||
const { productStore } = useSceneContext();
|
||||
const { getPointByUuid, updateEvent, updateAction, addAction, removeAction, getEventByModelUuid } = productStore();
|
||||
const { getPointByUuid, updateEvent, updateAction, addAction, removeAction, getEventByModelUuid, getActionByUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
|
||||
@@ -40,19 +43,21 @@ function HumanMechanics() {
|
||||
selectedEventData.selectedPoint
|
||||
) as HumanPointSchema | undefined;
|
||||
|
||||
if (point?.action) {
|
||||
if (point?.actions?.length) {
|
||||
setSelectedPointData(point);
|
||||
setCurrentAction(point.action);
|
||||
setSelectedAction(point.action.actionUuid, point.action.actionName);
|
||||
const firstAction = point.actions[0];
|
||||
setCurrentAction(firstAction);
|
||||
setSpeed((
|
||||
getEventByModelUuid(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData?.data.modelUuid || ""
|
||||
) as HumanEventSchema | undefined
|
||||
)?.speed?.toString() || "1");
|
||||
setLoadCapacity(point.action.loadCapacity.toString());
|
||||
setProcessTime(point.action.processTime || 10);
|
||||
setSwappedMaterial(point.action.swapMaterial || "Default material");
|
||||
setLoadCapacity(firstAction.loadCapacity.toString());
|
||||
setActiveOption(firstAction.actionType);
|
||||
setLoadCount(firstAction.loadCount || 0);
|
||||
setProcessTime(firstAction.processTime || 10);
|
||||
setSwappedMaterial(firstAction.swapMaterial || "Default material");
|
||||
}
|
||||
} else {
|
||||
clearSelectedAction();
|
||||
@@ -60,26 +65,36 @@ function HumanMechanics() {
|
||||
}, [selectedEventData, selectedProduct]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedEventData && selectedProduct.productUuid) {
|
||||
if (selectedEventData && selectedEventData.data.type === "human") {
|
||||
const point = getPointByUuid(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData.data.modelUuid,
|
||||
selectedEventData.selectedPoint
|
||||
) as HumanPointSchema | undefined;
|
||||
|
||||
if (point?.action) {
|
||||
setSelectedPointData(point);
|
||||
setCurrentAction(point.action);
|
||||
setActiveOption(point.action.actionType);
|
||||
setSelectedAction(point.action.actionUuid, point.action.actionName);
|
||||
const actionUuid = selectedAction.actionId || point?.actions[0].actionUuid || '';
|
||||
|
||||
const newCurrentAction = getActionByUuid(selectedProduct.productUuid, actionUuid);
|
||||
|
||||
if (newCurrentAction && (newCurrentAction.actionType === 'assembly' || newCurrentAction?.actionType === 'worker')) {
|
||||
if (!selectedAction.actionId) {
|
||||
setSelectedAction(newCurrentAction.actionUuid, newCurrentAction.actionName);
|
||||
}
|
||||
setCurrentAction(newCurrentAction);
|
||||
setActiveOption(newCurrentAction.actionType);
|
||||
setLoadCapacity(newCurrentAction.loadCapacity.toString());
|
||||
setLoadCount(newCurrentAction.loadCount || 0);
|
||||
|
||||
if (newCurrentAction.actionType === 'assembly') {
|
||||
setProcessTime(newCurrentAction.processTime || 10);
|
||||
setSwappedMaterial(newCurrentAction.swapMaterial || "Default material");
|
||||
}
|
||||
} else {
|
||||
clearSelectedAction();
|
||||
setCurrentAction(undefined);
|
||||
}
|
||||
} else {
|
||||
clearSelectedAction();
|
||||
setCurrentAction(undefined);
|
||||
setSpeed("0.5");
|
||||
setLoadCapacity("1");
|
||||
}
|
||||
}, [selectedEventData, selectedProduct, selectedAction]);
|
||||
}, [selectedAction, selectedProduct, selectedEventData]);
|
||||
|
||||
const updateBackend = (
|
||||
productName: string,
|
||||
@@ -99,8 +114,9 @@ function HumanMechanics() {
|
||||
const handleSelectActionType = (actionType: string) => {
|
||||
if (!selectedAction.actionId || !currentAction || !selectedPointData) return;
|
||||
|
||||
const updatedAction = { ...currentAction, actionType: actionType as "worker" };
|
||||
const updatedPoint = { ...selectedPointData, action: updatedAction };
|
||||
const updatedAction = { ...currentAction, actionType: actionType as "worker" | "assembly" };
|
||||
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
|
||||
const updatedPoint = { ...selectedPointData, actions: updatedActions };
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
@@ -143,10 +159,9 @@ function HumanMechanics() {
|
||||
const handleLoadCapacityChange = (value: string) => {
|
||||
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
|
||||
|
||||
const updatedAction = { ...currentAction };
|
||||
updatedAction.loadCapacity = parseInt(value)
|
||||
|
||||
const updatedPoint = { ...selectedPointData, action: updatedAction };
|
||||
const updatedAction = { ...currentAction, loadCapacity: parseInt(value) };
|
||||
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
|
||||
const updatedPoint = { ...selectedPointData, actions: updatedActions };
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
@@ -163,13 +178,34 @@ function HumanMechanics() {
|
||||
setLoadCapacity(value);
|
||||
};
|
||||
|
||||
const handleLoadCountChange = (value: number) => {
|
||||
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
|
||||
|
||||
const updatedAction = { ...currentAction, loadCount: value };
|
||||
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
|
||||
const updatedPoint = { ...selectedPointData, actions: updatedActions };
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedAction.actionId,
|
||||
updatedAction
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
|
||||
}
|
||||
|
||||
setCurrentAction(updatedAction);
|
||||
setSelectedPointData(updatedPoint);
|
||||
setLoadCount(value);
|
||||
};
|
||||
|
||||
const handleProcessTimeChange = (value: number) => {
|
||||
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
|
||||
|
||||
const updatedAction = { ...currentAction };
|
||||
updatedAction.processTime = value
|
||||
|
||||
const updatedPoint = { ...selectedPointData, action: updatedAction };
|
||||
const updatedAction = { ...currentAction, processTime: value };
|
||||
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
|
||||
const updatedPoint = { ...selectedPointData, actions: updatedActions };
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
@@ -189,10 +225,9 @@ function HumanMechanics() {
|
||||
const handleMaterialChange = (value: string) => {
|
||||
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
|
||||
|
||||
const updatedAction = { ...currentAction };
|
||||
updatedAction.swapMaterial = value
|
||||
|
||||
const updatedPoint = { ...selectedPointData, action: updatedAction };
|
||||
const updatedAction = { ...currentAction, swapMaterial: value };
|
||||
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
|
||||
const updatedPoint = { ...selectedPointData, actions: updatedActions };
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
@@ -212,11 +247,17 @@ function HumanMechanics() {
|
||||
const handleClearPoints = () => {
|
||||
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
|
||||
|
||||
const updatedAction = { ...currentAction };
|
||||
delete updatedAction.pickUpPoint;
|
||||
delete updatedAction.dropPoint;
|
||||
const updatedAction: HumanAction = JSON.parse(JSON.stringify(currentAction));
|
||||
|
||||
const updatedPoint = { ...selectedPointData, action: updatedAction };
|
||||
if (updatedAction.actionType === 'assembly') {
|
||||
updatedAction.assemblyPoint = { position: null, rotation: null, }
|
||||
} else {
|
||||
updatedAction.pickUpPoint = { position: null, rotation: null, };
|
||||
updatedAction.dropPoint = { position: null, rotation: null, }
|
||||
}
|
||||
|
||||
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
|
||||
const updatedPoint = { ...selectedPointData, actions: updatedActions };
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
@@ -237,12 +278,17 @@ function HumanMechanics() {
|
||||
|
||||
const newAction: HumanAction = {
|
||||
actionUuid: MathUtils.generateUUID(),
|
||||
actionName: `Action`,
|
||||
actionName: `Action ${selectedPointData.actions.length + 1}`,
|
||||
actionType: "worker",
|
||||
loadCount: 1,
|
||||
loadCapacity: 1,
|
||||
processTime: 10,
|
||||
triggers: [],
|
||||
};
|
||||
|
||||
const updatedActions = [...(selectedPointData.actions || []), newAction];
|
||||
const updatedPoint = { ...selectedPointData, actions: updatedActions };
|
||||
|
||||
const event = addAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData.data.modelUuid,
|
||||
@@ -254,27 +300,39 @@ function HumanMechanics() {
|
||||
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
|
||||
}
|
||||
|
||||
const updatedPoint = { ...selectedPointData, action: newAction };
|
||||
setSelectedPointData(updatedPoint);
|
||||
setSelectedAction(newAction.actionUuid, newAction.actionName);
|
||||
};
|
||||
|
||||
const handleDeleteAction = () => {
|
||||
if (!selectedPointData) return;
|
||||
if (!selectedPointData || !selectedAction.actionId) return;
|
||||
|
||||
const updatedActions = selectedPointData.actions.filter(action => action.actionUuid !== selectedAction.actionId);
|
||||
const updatedPoint = { ...selectedPointData, actions: updatedActions };
|
||||
|
||||
const event = removeAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid
|
||||
selectedAction.actionId
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
|
||||
}
|
||||
|
||||
const updatedPoint = { ...selectedPointData, action: undefined as any };
|
||||
setSelectedPointData(updatedPoint);
|
||||
clearSelectedAction();
|
||||
setCurrentAction(undefined);
|
||||
|
||||
const index = selectedPointData.actions.findIndex((a) => a.actionUuid === selectedAction.actionId);
|
||||
const nextAction = updatedPoint.actions[index] || updatedPoint.actions[index - 1];
|
||||
if (nextAction) {
|
||||
setSelectedAction(nextAction.actionUuid, nextAction.actionName);
|
||||
const action = getActionByUuid(selectedProduct.productUuid, nextAction.actionUuid);
|
||||
if (action) {
|
||||
setCurrentAction(action as HumanAction);
|
||||
}
|
||||
} else {
|
||||
clearSelectedAction();
|
||||
setCurrentAction(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -299,7 +357,7 @@ function HumanMechanics() {
|
||||
<section>
|
||||
<ActionsList
|
||||
selectedPointData={selectedPointData}
|
||||
multipleAction={false}
|
||||
multipleAction={true}
|
||||
handleAddAction={handleAddAction}
|
||||
handleDeleteAction={handleDeleteAction}
|
||||
/>
|
||||
@@ -315,7 +373,7 @@ function HumanMechanics() {
|
||||
defaultOption={activeOption}
|
||||
options={["worker", "assembly"]}
|
||||
onSelect={handleSelectActionType}
|
||||
disabled={true}
|
||||
disabled={false}
|
||||
/>
|
||||
</div>
|
||||
{currentAction.actionType === 'worker' &&
|
||||
@@ -323,12 +381,21 @@ function HumanMechanics() {
|
||||
loadCapacity={{
|
||||
value: loadCapacity,
|
||||
min: 1,
|
||||
max: 5,
|
||||
max: 20,
|
||||
step: 1,
|
||||
defaultValue: "10",
|
||||
defaultValue: "1",
|
||||
disabled: true,
|
||||
onChange: handleLoadCapacityChange,
|
||||
}}
|
||||
loadCount={{
|
||||
value: loadCount,
|
||||
min: 0,
|
||||
max: 20,
|
||||
step: 1,
|
||||
defaultValue: "1",
|
||||
disabled: false,
|
||||
onChange: handleLoadCountChange,
|
||||
}}
|
||||
clearPoints={handleClearPoints}
|
||||
/>
|
||||
}
|
||||
@@ -343,6 +410,7 @@ function HumanMechanics() {
|
||||
swapOptions={["Default material", "Material 1", "Material 2", "Material 3"]}
|
||||
swapDefaultOption={swappedMaterial}
|
||||
onSwapSelect={handleMaterialChange}
|
||||
clearPoints={handleClearPoints}
|
||||
/>
|
||||
}
|
||||
<div className="tirgger">
|
||||
|
||||
@@ -12,8 +12,12 @@ import { useVersionContext } from "../../../../../../modules/builder/version/ver
|
||||
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
|
||||
|
||||
function MachineMechanics() {
|
||||
const [activeOption, setActiveOption] = useState<"default" | "process">("default");
|
||||
const [activeOption, setActiveOption] = useState<"process">("process");
|
||||
const [actionName, setActionName] = useState("Action Name");
|
||||
const [processTime, setProcessTime] = useState("1");
|
||||
const [material, setMaterial] = useState("Default material");
|
||||
const [selectedPointData, setSelectedPointData] = useState<MachinePointSchema | undefined>();
|
||||
|
||||
const { selectedEventData } = useSelectedEventData();
|
||||
const { productStore } = useSceneContext();
|
||||
const { getPointByUuid, updateAction } = productStore();
|
||||
@@ -31,9 +35,13 @@ function MachineMechanics() {
|
||||
selectedEventData?.data.modelUuid,
|
||||
selectedEventData?.selectedPoint
|
||||
) as MachinePointSchema | undefined;
|
||||
|
||||
if (point && "action" in point) {
|
||||
setSelectedPointData(point);
|
||||
setActiveOption(point.action.actionType as "process");
|
||||
setActionName(point.action.actionName);
|
||||
setProcessTime(point.action.processTime?.toString() || "1");
|
||||
setMaterial(point.action.swapMaterial || "Default material");
|
||||
setSelectedAction(point.action.actionUuid, point.action.actionName);
|
||||
}
|
||||
} else {
|
||||
@@ -48,22 +56,25 @@ function MachineMechanics() {
|
||||
eventData: EventsSchema
|
||||
) => {
|
||||
upsertProductOrEventApi({
|
||||
productName: productName,
|
||||
productUuid: productUuid,
|
||||
projectId: projectId,
|
||||
productName,
|
||||
productUuid,
|
||||
projectId,
|
||||
eventDatas: eventData,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
})
|
||||
}
|
||||
versionId: selectedVersion?.versionId || "",
|
||||
});
|
||||
};
|
||||
|
||||
const handleActionTypeChange = (option: string) => {
|
||||
if (!selectedEventData || !selectedPointData) return;
|
||||
if (!selectedPointData) return;
|
||||
|
||||
const validOption = option as "process";
|
||||
setActiveOption(validOption);
|
||||
|
||||
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, {
|
||||
actionType: validOption,
|
||||
});
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{ actionType: validOption }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -77,7 +88,13 @@ function MachineMechanics() {
|
||||
|
||||
const handleRenameAction = (newName: string) => {
|
||||
if (!selectedPointData) return;
|
||||
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { actionName: newName });
|
||||
|
||||
setActionName(newName);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{ actionName: newName }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -91,9 +108,16 @@ function MachineMechanics() {
|
||||
|
||||
const handleProcessTimeChange = (value: string) => {
|
||||
if (!selectedPointData) return;
|
||||
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, {
|
||||
processTime: parseFloat(value),
|
||||
});
|
||||
|
||||
const numericValue = parseFloat(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
setProcessTime(value);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{ processTime: numericValue }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -105,11 +129,15 @@ function MachineMechanics() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleMaterialSelect = (material: string) => {
|
||||
const handleMaterialSelect = (selectedMaterial: string) => {
|
||||
if (!selectedPointData) return;
|
||||
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, {
|
||||
swapMaterial: material,
|
||||
});
|
||||
|
||||
setMaterial(selectedMaterial);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{ swapMaterial: selectedMaterial }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -121,19 +149,6 @@ function MachineMechanics() {
|
||||
}
|
||||
};
|
||||
|
||||
// Get current values from store
|
||||
const currentActionName = selectedPointData
|
||||
? selectedPointData.action.actionName
|
||||
: "Action Name";
|
||||
|
||||
const currentProcessTime = selectedPointData
|
||||
? selectedPointData.action.processTime.toString()
|
||||
: "1";
|
||||
|
||||
const currentMaterial = selectedPointData
|
||||
? selectedPointData.action.swapMaterial
|
||||
: "Default material";
|
||||
|
||||
const availableActions = {
|
||||
defaultOption: "process",
|
||||
options: ["process"],
|
||||
@@ -146,28 +161,26 @@ function MachineMechanics() {
|
||||
<div className="selected-actions-details">
|
||||
<div className="selected-actions-header">
|
||||
<RenameInput
|
||||
value={currentActionName}
|
||||
onRename={handleRenameAction}
|
||||
value={actionName}
|
||||
canEdit={false}
|
||||
/>
|
||||
</div>
|
||||
<ActionsList
|
||||
selectedPointData={selectedPointData}
|
||||
/>
|
||||
<ActionsList selectedPointData={selectedPointData} />
|
||||
<div className="selected-actions-list">
|
||||
<LabledDropdown
|
||||
defaultOption="process"
|
||||
defaultOption={activeOption}
|
||||
options={availableActions.options}
|
||||
onSelect={handleActionTypeChange}
|
||||
/>
|
||||
{activeOption === "process" && (
|
||||
<ProcessAction
|
||||
value={currentProcessTime}
|
||||
value={processTime}
|
||||
min={0.1}
|
||||
max={60}
|
||||
defaultValue="1"
|
||||
onChange={handleProcessTimeChange}
|
||||
swapOptions={["Default material", "Material 1", "Material 2", "Material 3"]}
|
||||
swapDefaultOption={currentMaterial}
|
||||
swapDefaultOption={material}
|
||||
onSwapSelect={handleMaterialSelect}
|
||||
/>
|
||||
)}
|
||||
@@ -182,4 +195,4 @@ function MachineMechanics() {
|
||||
);
|
||||
}
|
||||
|
||||
export default MachineMechanics;
|
||||
export default MachineMechanics;
|
||||
@@ -14,11 +14,13 @@ import { useVersionContext } from "../../../../../../modules/builder/version/ver
|
||||
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
|
||||
|
||||
function RoboticArmMechanics() {
|
||||
const [activeOption, setActiveOption] = useState<"default" | "pickAndPlace">("default");
|
||||
const [activeOption, setActiveOption] = useState<"pickAndPlace">("pickAndPlace");
|
||||
const [speed, setSpeed] = useState("0.5");
|
||||
const [selectedPointData, setSelectedPointData] = useState<RoboticArmPointSchema | undefined>();
|
||||
|
||||
const { selectedEventData } = useSelectedEventData();
|
||||
const { productStore } = useSceneContext();
|
||||
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction, } = productStore();
|
||||
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
|
||||
@@ -33,16 +35,20 @@ function RoboticArmMechanics() {
|
||||
selectedEventData.data.modelUuid,
|
||||
selectedEventData.selectedPoint
|
||||
) as RoboticArmPointSchema | undefined;
|
||||
|
||||
if (point?.actions) {
|
||||
setSelectedPointData(point);
|
||||
setSpeed(
|
||||
(getEventByModelUuid(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData.data.modelUuid
|
||||
) as RoboticArmEventSchema | undefined)?.speed?.toString() || "0.5"
|
||||
);
|
||||
|
||||
if (point.actions.length > 0) {
|
||||
setActiveOption(
|
||||
point.actions[0].actionType as "default" | "pickAndPlace"
|
||||
);
|
||||
setSelectedAction(
|
||||
point.actions[0].actionUuid,
|
||||
point.actions[0].actionName
|
||||
);
|
||||
const firstAction = point.actions[0];
|
||||
setActiveOption(firstAction.actionType);
|
||||
setSelectedAction(firstAction.actionUuid, firstAction.actionName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -57,33 +63,33 @@ function RoboticArmMechanics() {
|
||||
eventData: EventsSchema
|
||||
) => {
|
||||
upsertProductOrEventApi({
|
||||
productName: productName,
|
||||
productUuid: productUuid,
|
||||
projectId: projectId,
|
||||
productName,
|
||||
productUuid,
|
||||
projectId,
|
||||
eventDatas: eventData,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
versionId: selectedVersion?.versionId || "",
|
||||
});
|
||||
};
|
||||
|
||||
const handleRenameAction = (newName: string) => {
|
||||
if (!selectedAction.actionId) return;
|
||||
if (!selectedAction.actionId || !selectedPointData) return;
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedAction.actionId,
|
||||
{ actionName: newName }
|
||||
);
|
||||
|
||||
if (selectedPointData) {
|
||||
const updatedActions = selectedPointData.actions.map((action) =>
|
||||
action.actionUuid === selectedAction.actionId
|
||||
? { ...action, actionName: newName }
|
||||
: action
|
||||
);
|
||||
setSelectedPointData({
|
||||
...selectedPointData,
|
||||
actions: updatedActions,
|
||||
});
|
||||
}
|
||||
const updatedActions = selectedPointData.actions.map(action =>
|
||||
action.actionUuid === selectedAction.actionId
|
||||
? { ...action, actionName: newName }
|
||||
: action
|
||||
);
|
||||
|
||||
setSelectedPointData({
|
||||
...selectedPointData,
|
||||
actions: updatedActions,
|
||||
});
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -97,10 +103,15 @@ function RoboticArmMechanics() {
|
||||
|
||||
const handleSpeedChange = (value: string) => {
|
||||
if (!selectedEventData) return;
|
||||
|
||||
const numericValue = parseFloat(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
setSpeed(value);
|
||||
const event = updateEvent(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData.data.modelUuid,
|
||||
{ speed: parseFloat(value), }
|
||||
{ speed: numericValue }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
@@ -112,6 +123,7 @@ function RoboticArmMechanics() {
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClearPoints = () => {
|
||||
if (!selectedAction.actionId || !selectedPointData) return;
|
||||
|
||||
@@ -166,15 +178,20 @@ function RoboticArmMechanics() {
|
||||
);
|
||||
}
|
||||
|
||||
const updatedPoint = { ...selectedPointData, actions: [...selectedPointData.actions, newAction], };
|
||||
setSelectedPointData(updatedPoint);
|
||||
setSelectedPointData({
|
||||
...selectedPointData,
|
||||
actions: [...selectedPointData.actions, newAction],
|
||||
});
|
||||
setSelectedAction(newAction.actionUuid, newAction.actionName);
|
||||
};
|
||||
|
||||
const handleDeleteAction = (actionUuid: string) => {
|
||||
if (!selectedPointData) return;
|
||||
|
||||
const event = removeAction(selectedProduct.productUuid, actionUuid);
|
||||
const event = removeAction(
|
||||
selectedProduct.productUuid,
|
||||
actionUuid
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -185,14 +202,13 @@ function RoboticArmMechanics() {
|
||||
);
|
||||
}
|
||||
|
||||
const index = selectedPointData.actions.findIndex((a) => a.actionUuid === actionUuid);
|
||||
const newActions = selectedPointData.actions.filter((a) => a.actionUuid !== actionUuid);
|
||||
const index = selectedPointData.actions.findIndex(a => a.actionUuid === actionUuid);
|
||||
const newActions = selectedPointData.actions.filter(a => a.actionUuid !== actionUuid);
|
||||
|
||||
const updatedPoint = {
|
||||
setSelectedPointData({
|
||||
...selectedPointData,
|
||||
actions: newActions,
|
||||
};
|
||||
setSelectedPointData(updatedPoint);
|
||||
});
|
||||
|
||||
if (selectedAction.actionId === actionUuid) {
|
||||
const nextAction = newActions[index] || newActions[index - 1];
|
||||
@@ -209,16 +225,7 @@ function RoboticArmMechanics() {
|
||||
options: ["pickAndPlace"],
|
||||
};
|
||||
|
||||
const currentSpeed = (getEventByModelUuid(selectedProduct.productUuid, selectedEventData?.data.modelUuid || "") as RoboticArmEventSchema | undefined)?.speed?.toString() || "0.5";
|
||||
|
||||
const currentAction = selectedPointData?.actions.find((a) => a.actionUuid === selectedAction.actionId);
|
||||
|
||||
const currentPickPoint = currentAction?.process.startPoint
|
||||
? `${currentAction.process.startPoint[0]},${currentAction.process.startPoint[1]},${currentAction.process.startPoint[2]}`
|
||||
: "";
|
||||
const currentPlacePoint = currentAction?.process.endPoint
|
||||
? `${currentAction.process.endPoint[0]},${currentAction.process.endPoint[1]},${currentAction.process.endPoint[2]}`
|
||||
: "";
|
||||
const currentAction = selectedPointData?.actions.find(a => a.actionUuid === selectedAction.actionId);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -227,10 +234,10 @@ function RoboticArmMechanics() {
|
||||
<div className="property-item">
|
||||
<InputWithDropDown
|
||||
label="Speed"
|
||||
value={currentSpeed}
|
||||
value={speed}
|
||||
min={0}
|
||||
step={0.1}
|
||||
defaultValue={"0.5"}
|
||||
defaultValue="0.5"
|
||||
max={10}
|
||||
activeOption="m/s"
|
||||
onClick={() => { }}
|
||||
@@ -252,7 +259,7 @@ function RoboticArmMechanics() {
|
||||
<div className="selected-actions-header">
|
||||
<RenameInput
|
||||
value={selectedAction.actionName || ""}
|
||||
onRename={handleRenameAction}
|
||||
canEdit={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="selected-actions-list">
|
||||
@@ -277,4 +284,4 @@ function RoboticArmMechanics() {
|
||||
);
|
||||
}
|
||||
|
||||
export default RoboticArmMechanics;
|
||||
export default RoboticArmMechanics;
|
||||
@@ -192,7 +192,7 @@ function StorageMechanics() {
|
||||
<div className="selected-actions-header">
|
||||
<RenameInput
|
||||
value={currentActionName}
|
||||
onRename={handleRenameAction}
|
||||
canEdit={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="selected-actions-list">
|
||||
|
||||
@@ -3,10 +3,7 @@ import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
||||
import RenameInput from "../../../../../ui/inputs/RenameInput";
|
||||
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
|
||||
import Trigger from "../trigger/Trigger";
|
||||
import {
|
||||
useSelectedAction,
|
||||
useSelectedEventData,
|
||||
} from "../../../../../../store/simulation/useSimulationStore";
|
||||
import { useSelectedAction, useSelectedEventData } from "../../../../../../store/simulation/useSimulationStore";
|
||||
import TravelAction from "../actions/TravelAction";
|
||||
import ActionsList from "../components/ActionsList";
|
||||
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
|
||||
@@ -17,18 +14,23 @@ import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
|
||||
import { useSelectedPath } from "../../../../../../store/builder/store";
|
||||
|
||||
function VehicleMechanics() {
|
||||
const [activeOption, setActiveOption] = useState<"default" | "travel">("default");
|
||||
const [activeOption, setActiveOption] = useState<"travel">("travel");
|
||||
const [speed, setSpeed] = useState("0.5");
|
||||
const [actionName, setActionName] = useState("Action Name");
|
||||
const [loadCapacity, setLoadCapacity] = useState("1");
|
||||
const [unloadDuration, setUnloadDuration] = useState("1");
|
||||
const [selectedPointData, setSelectedPointData] = useState<VehiclePointSchema | undefined>();
|
||||
|
||||
const { selectedEventData } = useSelectedEventData();
|
||||
const { productStore } = useSceneContext();
|
||||
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction } = productStore();
|
||||
const { getPointByUuid, updateEvent, updateAction, getEventByModelUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { setSelectedAction, clearSelectedAction } = useSelectedAction();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
const { projectId } = useParams();
|
||||
const { selectedPath, setSelectedPath } = useSelectedPath();
|
||||
const { setSelectedPath } = useSelectedPath();
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedEventData && selectedEventData.data.type === "vehicle") {
|
||||
@@ -41,6 +43,15 @@ function VehicleMechanics() {
|
||||
if (point) {
|
||||
setSelectedPointData(point);
|
||||
setActiveOption(point.action.actionType as "travel");
|
||||
setActionName(point.action.actionName);
|
||||
setSpeed(
|
||||
(getEventByModelUuid(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData.data.modelUuid
|
||||
) as VehicleEventSchema | undefined)?.speed?.toString() || "0.5"
|
||||
);
|
||||
setLoadCapacity(point.action.loadCapacity?.toString() || "1");
|
||||
setUnloadDuration(point.action.unLoadDuration?.toString() || "1");
|
||||
setSelectedAction(point.action.actionUuid, point.action.actionName);
|
||||
}
|
||||
} else {
|
||||
@@ -55,22 +66,25 @@ function VehicleMechanics() {
|
||||
eventData: EventsSchema
|
||||
) => {
|
||||
upsertProductOrEventApi({
|
||||
productName: productName,
|
||||
productUuid: productUuid,
|
||||
projectId: projectId,
|
||||
productName,
|
||||
productUuid,
|
||||
projectId,
|
||||
eventDatas: eventData,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
versionId: selectedVersion?.versionId || "",
|
||||
});
|
||||
};
|
||||
|
||||
const handleSpeedChange = (value: string) => {
|
||||
if (!selectedEventData) return;
|
||||
|
||||
const numericValue = parseFloat(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
setSpeed(value);
|
||||
const event = updateEvent(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData.data.modelUuid,
|
||||
{
|
||||
speed: parseFloat(value),
|
||||
}
|
||||
{ speed: numericValue }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
@@ -84,16 +98,15 @@ function VehicleMechanics() {
|
||||
};
|
||||
|
||||
const handleActionTypeChange = (option: string) => {
|
||||
if (!selectedEventData || !selectedPointData) return;
|
||||
if (!selectedPointData) return;
|
||||
|
||||
const validOption = option as "travel";
|
||||
setActiveOption(validOption);
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{
|
||||
actionType: validOption,
|
||||
}
|
||||
{ actionType: validOption }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
@@ -108,6 +121,8 @@ function VehicleMechanics() {
|
||||
|
||||
const handleRenameAction = (newName: string) => {
|
||||
if (!selectedPointData) return;
|
||||
|
||||
setActionName(newName);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
@@ -126,12 +141,15 @@ function VehicleMechanics() {
|
||||
|
||||
const handleLoadCapacityChange = (value: string) => {
|
||||
if (!selectedPointData) return;
|
||||
|
||||
const numericValue = parseFloat(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
setLoadCapacity(value);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{
|
||||
loadCapacity: parseFloat(value),
|
||||
}
|
||||
{ loadCapacity: numericValue }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
@@ -146,12 +164,15 @@ function VehicleMechanics() {
|
||||
|
||||
const handleUnloadDurationChange = (value: string) => {
|
||||
if (!selectedPointData) return;
|
||||
|
||||
const numericValue = parseFloat(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
setUnloadDuration(value);
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{
|
||||
unLoadDuration: parseFloat(value),
|
||||
}
|
||||
{ unLoadDuration: numericValue }
|
||||
);
|
||||
|
||||
if (event) {
|
||||
@@ -164,46 +185,18 @@ function VehicleMechanics() {
|
||||
}
|
||||
};
|
||||
|
||||
const handlePickPointChange = (value: string) => {
|
||||
const handleClearPoints = () => {
|
||||
if (!selectedPointData) return;
|
||||
};
|
||||
|
||||
const handleUnloadPointChange = (value: string) => {
|
||||
if (!selectedPointData) return;
|
||||
};
|
||||
|
||||
// Get current values from store
|
||||
|
||||
const currentSpeed =
|
||||
(
|
||||
getEventByModelUuid(
|
||||
selectedProduct.productUuid,
|
||||
selectedEventData?.data.modelUuid || ""
|
||||
) as VehicleEventSchema | undefined
|
||||
)?.speed?.toString() || "0.5";
|
||||
|
||||
const currentActionName = selectedPointData
|
||||
? selectedPointData.action.actionName
|
||||
: "Action Name";
|
||||
|
||||
const currentLoadCapacity = selectedPointData
|
||||
? selectedPointData.action.loadCapacity.toString()
|
||||
: "1";
|
||||
|
||||
const currentUnloadDuration = selectedPointData
|
||||
? selectedPointData.action.unLoadDuration.toString()
|
||||
: "1";
|
||||
|
||||
function handleClearPoints() {
|
||||
|
||||
if (!selectedEventData || !selectedPointData?.action.actionUuid) return;
|
||||
|
||||
const event = updateAction(
|
||||
selectedProduct.productUuid, selectedPointData.action.actionUuid, {
|
||||
pickUpPoint: null,
|
||||
unLoadPoint: null,
|
||||
steeringAngle: 0,
|
||||
})
|
||||
selectedProduct.productUuid,
|
||||
selectedPointData.action.actionUuid,
|
||||
{
|
||||
pickUpPoint: null,
|
||||
unLoadPoint: null,
|
||||
steeringAngle: 0,
|
||||
}
|
||||
);
|
||||
|
||||
if (event) {
|
||||
updateBackend(
|
||||
@@ -213,7 +206,7 @@ function VehicleMechanics() {
|
||||
event
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const availableActions = {
|
||||
defaultOption: "travel",
|
||||
@@ -229,10 +222,10 @@ function VehicleMechanics() {
|
||||
<div className="property-item">
|
||||
<InputWithDropDown
|
||||
label="Speed"
|
||||
value={currentSpeed}
|
||||
value={speed}
|
||||
min={0}
|
||||
step={0.1}
|
||||
defaultValue={"0.5"}
|
||||
defaultValue="0.5"
|
||||
max={10}
|
||||
activeOption="m/s"
|
||||
onClick={() => { }}
|
||||
@@ -246,13 +239,13 @@ function VehicleMechanics() {
|
||||
<div className="selected-actions-details">
|
||||
<div className="selected-actions-header">
|
||||
<RenameInput
|
||||
value={currentActionName}
|
||||
onRename={handleRenameAction}
|
||||
value={actionName}
|
||||
canEdit={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="selected-actions-list">
|
||||
<LabledDropdown
|
||||
defaultOption="travel"
|
||||
defaultOption={activeOption}
|
||||
options={availableActions.options}
|
||||
onSelect={handleActionTypeChange}
|
||||
/>
|
||||
@@ -260,14 +253,14 @@ function VehicleMechanics() {
|
||||
{activeOption === "travel" && (
|
||||
<TravelAction
|
||||
loadCapacity={{
|
||||
value: currentLoadCapacity,
|
||||
value: loadCapacity,
|
||||
min: 1,
|
||||
max: 100,
|
||||
defaultValue: "1",
|
||||
onChange: handleLoadCapacityChange,
|
||||
}}
|
||||
unloadDuration={{
|
||||
value: currentUnloadDuration,
|
||||
value: unloadDuration,
|
||||
min: 1,
|
||||
max: 60,
|
||||
defaultValue: "1",
|
||||
@@ -284,36 +277,48 @@ function VehicleMechanics() {
|
||||
type={"Vehicle"}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: "10px", flexDirection: "column", alignItems: "center" }}>
|
||||
<button style={{
|
||||
backgroundColor: "#6f42c1",
|
||||
color: "#f3f3fd",
|
||||
borderRadius: "15px",
|
||||
height: "30px",
|
||||
width: "150px",
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
padding: "0 5px",
|
||||
|
||||
}} onClick={() => setSelectedPath("auto")}>Auto Generate Path</button>
|
||||
<button style={{
|
||||
backgroundColor: "#6f42c1",
|
||||
color: "#f3f3fd",
|
||||
borderRadius: "15px",
|
||||
height: "30px",
|
||||
width: "150px",
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
padding: "0 5px",
|
||||
|
||||
}} onClick={() => setSelectedPath("manual")}>Create Path</button>
|
||||
<div style={{
|
||||
display: "flex",
|
||||
gap: "10px",
|
||||
flexDirection: "column",
|
||||
alignItems: "center"
|
||||
}}>
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "#6f42c1",
|
||||
color: "#f3f3fd",
|
||||
borderRadius: "15px",
|
||||
height: "30px",
|
||||
width: "150px",
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
padding: "0 5px",
|
||||
}}
|
||||
onClick={() => setSelectedPath("auto")}
|
||||
>
|
||||
Auto Generate Path
|
||||
</button>
|
||||
<button
|
||||
style={{
|
||||
backgroundColor: "#6f42c1",
|
||||
color: "#f3f3fd",
|
||||
borderRadius: "15px",
|
||||
height: "30px",
|
||||
width: "150px",
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
padding: "0 5px",
|
||||
}}
|
||||
onClick={() => setSelectedPath("manual")}
|
||||
>
|
||||
Create Path
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
)
|
||||
}
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default VehicleMechanics;
|
||||
export default VehicleMechanics;
|
||||
@@ -65,8 +65,11 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, currentAction);
|
||||
const actionTriggers = action?.triggers || [];
|
||||
setTriggers(actionTriggers);
|
||||
if (actionTriggers.length === 0) {
|
||||
setSelectedTrigger(undefined);
|
||||
}
|
||||
setSelectedTrigger(actionTriggers[0]);
|
||||
}, [currentAction, selectedProduct]);
|
||||
}, [currentAction, selectedProduct, selectedTrigger, selectedPointData]);
|
||||
|
||||
const triggeredModel = useMemo(() => {
|
||||
if (!selectedProduct || !selectedTrigger?.triggeredAsset?.triggeredModel?.modelUuid)
|
||||
|
||||
@@ -22,7 +22,6 @@ import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
||||
import {
|
||||
useActiveTool,
|
||||
useAddAction,
|
||||
useRefTextUpdate,
|
||||
useSelectedWallItem,
|
||||
useSocketStore,
|
||||
useToggleView,
|
||||
@@ -75,7 +74,6 @@ const Tools: React.FC = () => {
|
||||
|
||||
const { setActiveSubTool, activeSubTool } = useActiveSubTool();
|
||||
const { setSelectedWallItem } = useSelectedWallItem();
|
||||
const { setRefTextUpdate } = useRefTextUpdate();
|
||||
const { setToggleUI } = useToggleStore();
|
||||
const { setToggleView, toggleView } = useToggleView();
|
||||
|
||||
@@ -131,7 +129,6 @@ const Tools: React.FC = () => {
|
||||
const resetTools = () => {
|
||||
setToolMode(null);
|
||||
setAddAction(null);
|
||||
setRefTextUpdate((prev) => prev - 1);
|
||||
};
|
||||
|
||||
const updateToolBehavior = (tool: string, is2D: boolean) => {
|
||||
@@ -406,7 +403,6 @@ const useStoreHooks = () => {
|
||||
...useActiveTool(),
|
||||
...useToolMode(),
|
||||
...useAddAction(),
|
||||
...useRefTextUpdate(),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -2,93 +2,89 @@ import React, { useState } from "react";
|
||||
import RenameInput from "./RenameInput";
|
||||
|
||||
type InputWithDropDownProps = {
|
||||
label: string;
|
||||
value: string;
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
defaultValue?: string;
|
||||
disabled?: boolean;
|
||||
options?: string[]; // Array of dropdown options
|
||||
activeOption?: string; // The currently active dropdown option
|
||||
onClick?: () => void;
|
||||
onChange: (newValue: string) => void;
|
||||
editableLabel?: boolean;
|
||||
placeholder?: string; // New placeholder prop
|
||||
label: string;
|
||||
value: string;
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
defaultValue?: string;
|
||||
disabled?: boolean;
|
||||
options?: string[];
|
||||
activeOption?: string;
|
||||
onClick?: () => void;
|
||||
onChange: (newValue: string) => void;
|
||||
editableLabel?: boolean;
|
||||
placeholder?: string;
|
||||
};
|
||||
|
||||
const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
||||
label,
|
||||
value,
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
defaultValue,
|
||||
disabled = false,
|
||||
options,
|
||||
activeOption,
|
||||
onClick,
|
||||
onChange,
|
||||
editableLabel = false,
|
||||
placeholder = "Inherit", // Default empty placeholder
|
||||
label,
|
||||
value,
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
defaultValue,
|
||||
disabled = false,
|
||||
options,
|
||||
activeOption,
|
||||
onClick,
|
||||
onChange,
|
||||
editableLabel = false,
|
||||
placeholder = "Inherit",
|
||||
}) => {
|
||||
const separatedWords = label
|
||||
.split(/(?=[A-Z])/)
|
||||
.map((word) => word.trim())
|
||||
.toString();
|
||||
const [openDropdown, setOpenDropdown] = useState(false);
|
||||
|
||||
const [openDropdown, setOpenDropdown] = useState(false);
|
||||
const separatedWords = label
|
||||
.split(/(?=[A-Z])/)
|
||||
.map((word) => word.trim())
|
||||
.join(" ");
|
||||
|
||||
return (
|
||||
<div className="value-field-container">
|
||||
{editableLabel ? (
|
||||
<RenameInput value={label} />
|
||||
) : (
|
||||
<label htmlFor={separatedWords} className="label">
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<div className="input default" id={separatedWords}>
|
||||
<input
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
type="number"
|
||||
defaultValue={value}
|
||||
// value={value}
|
||||
disabled={disabled}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.value);
|
||||
}}
|
||||
placeholder={placeholder} // Added placeholder prop
|
||||
/>
|
||||
|
||||
{activeOption && (
|
||||
<div
|
||||
className="dropdown"
|
||||
onClick={() => {
|
||||
setOpenDropdown(true);
|
||||
}}
|
||||
>
|
||||
<div className="active-option">{activeOption}</div>
|
||||
{options && openDropdown && (
|
||||
<div className="dropdown-options-list">
|
||||
{options.map((option, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={"dropdown-option"}
|
||||
onClick={onClick}
|
||||
>
|
||||
{option}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
return (
|
||||
<div className="value-field-container">
|
||||
{editableLabel ? (
|
||||
<RenameInput value={label} />
|
||||
) : (
|
||||
<label htmlFor={separatedWords} className="label">
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
<div className="input default" id={separatedWords}>
|
||||
<input
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
type="number"
|
||||
value={value} // Controlled input
|
||||
disabled={disabled}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
|
||||
{activeOption && (
|
||||
<div
|
||||
className="dropdown"
|
||||
onClick={() => setOpenDropdown((prev) => !prev)}
|
||||
>
|
||||
<div className="active-option">{activeOption}</div>
|
||||
{options && openDropdown && (
|
||||
<div className="dropdown-options-list">
|
||||
{options.map((option, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="dropdown-option"
|
||||
onClick={onClick}
|
||||
>
|
||||
{option}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default InputWithDropDown;
|
||||
export default InputWithDropDown;
|
||||
|
||||
@@ -2,7 +2,6 @@ import React, { useEffect, useState } from "react";
|
||||
import List from "./List";
|
||||
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
|
||||
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
|
||||
import { useZones } from "../../../store/builder/store";
|
||||
import { useSceneContext } from "../../../modules/scene/sceneContext";
|
||||
|
||||
interface DropDownListProps {
|
||||
@@ -44,14 +43,12 @@ const DropDownList: React.FC<DropDownListProps> = ({
|
||||
remove,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState<boolean>(defaultOpen);
|
||||
// const { zones } = useZones();
|
||||
|
||||
const handleToggle = () => {
|
||||
setIsOpen((prev) => !prev); // Toggle the state
|
||||
};
|
||||
|
||||
const [zoneDataList, setZoneDataList] = useState<ZoneData[]>([]);
|
||||
// const { assetStore } = useSceneContext();
|
||||
const { assetStore, zoneStore } = useSceneContext();
|
||||
const { assets } = assetStore();
|
||||
const { zones } = zoneStore()
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
} from "../../icons/ExportCommonIcons";
|
||||
import {
|
||||
useZoneAssetId,
|
||||
useZones,
|
||||
} from "../../../store/builder/store";
|
||||
import { zoneCameraUpdate } from "../../../services/visulization/zone/zoneCameraUpdation";
|
||||
import { setAssetsApi } from "../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
|
||||
|
||||
@@ -34,7 +34,7 @@ import { useComparisonProduct } from "../../../store/simulation/useSimulationSto
|
||||
import InputToggle from "../inputs/InputToggle";
|
||||
|
||||
const SimulationPlayer: React.FC = () => {
|
||||
const MAX_SPEED = 4; // Maximum speed
|
||||
const MAX_SPEED = 8; // Maximum speed
|
||||
|
||||
const isDragging = useRef(false);
|
||||
const sliderRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -256,14 +256,17 @@ 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],
|
||||
action: {
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "worker",
|
||||
loadCapacity: 1,
|
||||
triggers: []
|
||||
}
|
||||
|
||||
actions: [
|
||||
{
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "worker",
|
||||
loadCount: 1,
|
||||
loadCapacity: 1,
|
||||
processTime: 10,
|
||||
triggers: []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
addEvent(humanEvent);
|
||||
|
||||
@@ -373,14 +373,17 @@ async function handleModelLoad(
|
||||
uuid: THREE.MathUtils.generateUUID(),
|
||||
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
||||
rotation: [0, 0, 0],
|
||||
action: {
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "worker",
|
||||
loadCapacity: 1,
|
||||
triggers: []
|
||||
}
|
||||
|
||||
actions: [
|
||||
{
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "worker",
|
||||
loadCount: 1,
|
||||
loadCapacity: 1,
|
||||
processTime: 10,
|
||||
triggers: []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
addEvent(humanEvent);
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
useToolMode,
|
||||
useRenderDistance,
|
||||
useLimitDistance,
|
||||
useLoadingProgress,
|
||||
} from "../../store/builder/store";
|
||||
|
||||
////////// 3D Function Imports //////////
|
||||
@@ -57,7 +56,6 @@ export default function Builder() {
|
||||
const { projectId } = useParams();
|
||||
const { setHoveredPoint, setHoveredLine } = useBuilderStore();
|
||||
const { userId, organization } = getUserData();
|
||||
const { loadingProgress } = useLoadingProgress();
|
||||
|
||||
useEffect(() => {
|
||||
if (!toggleView) {
|
||||
@@ -117,7 +115,8 @@ export default function Builder() {
|
||||
|
||||
<CalculateAreaGroup />
|
||||
|
||||
{loadingProgress == 0 && <NavMesh />}
|
||||
<NavMesh />
|
||||
|
||||
<DxfFile />
|
||||
|
||||
<LayoutImage />
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useActiveLayer, useDfxUpload, useSocketStore, useToggleView, useUpdateScene } from '../../../store/builder/store';
|
||||
import { useActiveLayer, useDfxUpload, useSocketStore, useToggleView } from '../../../store/builder/store';
|
||||
import { LineBasicMaterial, Line } from 'three';
|
||||
import { TransformControls } from '@react-three/drei';
|
||||
import { getWallPointsFromBlueprint } from './functions/getWallPointsFromBlueprint';
|
||||
import * as Types from '../../../types/world/worldTypes';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { getUserData } from '../../../functions/getUserData';
|
||||
import { useVersionContext } from '../version/versionContext';
|
||||
|
||||
@@ -347,13 +347,17 @@ const CopyPasteControls3D = ({
|
||||
uuid: THREE.MathUtils.generateUUID(),
|
||||
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
||||
rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
|
||||
action: {
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "worker",
|
||||
loadCapacity: 1,
|
||||
triggers: []
|
||||
}
|
||||
actions: [
|
||||
{
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "worker",
|
||||
loadCapacity: 1,
|
||||
loadCount: 1,
|
||||
processTime: 10,
|
||||
triggers: []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
addEvent(humanEvent);
|
||||
|
||||
@@ -321,13 +321,17 @@ const DuplicationControls3D = ({
|
||||
uuid: THREE.MathUtils.generateUUID(),
|
||||
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
||||
rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
|
||||
action: {
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "worker",
|
||||
loadCapacity: 1,
|
||||
triggers: []
|
||||
}
|
||||
actions: [
|
||||
{
|
||||
actionUuid: THREE.MathUtils.generateUUID(),
|
||||
actionName: "Action 1",
|
||||
actionType: "worker",
|
||||
loadCapacity: 1,
|
||||
loadCount: 1,
|
||||
processTime: 10,
|
||||
triggers: []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
addEvent(humanEvent);
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
useElevation,
|
||||
useShadows,
|
||||
useSunPosition,
|
||||
useWallItems,
|
||||
useTileDistance,
|
||||
} from "../../../store/builder/store";
|
||||
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||
@@ -25,13 +24,12 @@ export default function Shadows() {
|
||||
const { controls, gl } = useThree();
|
||||
const { elevation, setElevation } = useElevation();
|
||||
const { azimuth, setAzimuth } = useAzimuth();
|
||||
const { wallItems } = useWallItems();
|
||||
const { planeValue } = useTileDistance();
|
||||
|
||||
useEffect(() => {
|
||||
gl.shadowMap.enabled = true;
|
||||
gl.shadowMap.type = THREE.PCFShadowMap;
|
||||
}, [gl, wallItems]);
|
||||
}, [gl]);
|
||||
|
||||
useEffect(() => {
|
||||
if (lightRef.current && targetRef.current) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useSceneContext } from "../../../../scene/sceneContext";
|
||||
|
||||
export function useDespawnHandler() {
|
||||
const { materialStore } = useSceneContext();
|
||||
const { getMaterialById, removeMaterial, setEndTime } = materialStore();
|
||||
const { getMaterialById, removeMaterial, setEndTime, clearLocations } = materialStore();
|
||||
|
||||
const deSpawnLogStatus = (materialUuid: string, status: string) => {
|
||||
echo.info(`${materialUuid}, ${status}`);
|
||||
@@ -17,6 +17,7 @@ export function useDespawnHandler() {
|
||||
|
||||
setEndTime(material.materialId, performance.now());
|
||||
removeMaterial(material.materialId);
|
||||
clearLocations(material.materialId);
|
||||
|
||||
deSpawnLogStatus(material.materialName, `Despawned`);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export function useAssemblyHandler() {
|
||||
const { getModelUuidByActionUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { incrementHumanLoad, addCurrentMaterial } = humanStore();
|
||||
const { incrementHumanLoad, addCurrentMaterial, addCurrentAction } = humanStore();
|
||||
|
||||
const assemblyLogStatus = (materialUuid: string, status: string) => {
|
||||
echo.info(`${materialUuid}, ${status}`);
|
||||
@@ -24,6 +24,7 @@ export function useAssemblyHandler() {
|
||||
if (!modelUuid) return;
|
||||
|
||||
incrementHumanLoad(modelUuid, 1);
|
||||
addCurrentAction(modelUuid, action.actionUuid);
|
||||
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
|
||||
|
||||
assemblyLogStatus(material.materialName, `performing assembly action`);
|
||||
|
||||
@@ -8,7 +8,7 @@ export function useWorkerHandler() {
|
||||
const { getModelUuidByActionUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { incrementHumanLoad, addCurrentMaterial } = humanStore();
|
||||
const { incrementHumanLoad, incrementLoadCount, addCurrentMaterial, addCurrentAction } = humanStore();
|
||||
|
||||
const workerLogStatus = (materialUuid: string, status: string) => {
|
||||
echo.info(`${materialUuid}, ${status}`);
|
||||
@@ -24,6 +24,8 @@ export function useWorkerHandler() {
|
||||
if (!modelUuid) return;
|
||||
|
||||
incrementHumanLoad(modelUuid, 1);
|
||||
incrementLoadCount(modelUuid, 1);
|
||||
addCurrentAction(modelUuid, action.actionUuid);
|
||||
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
|
||||
|
||||
workerLogStatus(material.materialName, `performing worker action`);
|
||||
|
||||
@@ -11,7 +11,7 @@ export function useRetrieveHandler() {
|
||||
const { getModelUuidByActionUuid, getPointUuidByActionUuid, getEventByModelUuid, getActionByUuid } = productStore();
|
||||
const { getStorageUnitById, getLastMaterial, updateCurrentLoad, removeLastMaterial } = storageUnitStore();
|
||||
const { getVehicleById, incrementVehicleLoad, addCurrentMaterial } = vehicleStore();
|
||||
const { getHumanById, incrementHumanLoad, addCurrentMaterial: addCurrentMaterialToHuman } = humanStore();
|
||||
const { getHumanById, incrementHumanLoad, incrementLoadCount, addCurrentMaterial: addCurrentMaterialToHuman } = humanStore();
|
||||
const { getAssetById, setCurrentAnimation } = assetStore();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { getArmBotById, addCurrentAction } = armBotStore();
|
||||
@@ -298,14 +298,15 @@ export function useRetrieveHandler() {
|
||||
} else if (triggeredModel.type === 'human') {
|
||||
const human = getHumanById(triggeredModel.modelUuid);
|
||||
const humanAsset = getAssetById(triggeredModel.modelUuid);
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
|
||||
if (human && !human.isScheduled && human.state === 'idle' && human.currentLoad < human.point.action.loadCapacity) {
|
||||
if (human && !human.isScheduled && human.state === 'idle' && human.currentLoad < (action as HumanAction).loadCapacity) {
|
||||
if (humanAsset && humanAsset.animationState?.current === 'idle') {
|
||||
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
|
||||
} else if (humanAsset && humanAsset.animationState?.current === 'pickup' && humanAsset.animationState.isCompleted) {
|
||||
const lastMaterial = getLastMaterial(storageUnit.modelUuid);
|
||||
if (lastMaterial) {
|
||||
if (human.currentLoad < human.point.action.loadCapacity) {
|
||||
if (action && human.currentLoad < (action as HumanAction).loadCapacity) {
|
||||
const material = createNewMaterial(
|
||||
lastMaterial.materialId,
|
||||
lastMaterial.materialType,
|
||||
@@ -315,10 +316,11 @@ export function useRetrieveHandler() {
|
||||
removeLastMaterial(storageUnit.modelUuid);
|
||||
updateCurrentLoad(storageUnit.modelUuid, -1);
|
||||
incrementHumanLoad(human.modelUuid, 1);
|
||||
incrementLoadCount(human.modelUuid, 1);
|
||||
addCurrentMaterialToHuman(human.modelUuid, material.materialType, material.materialId);
|
||||
retrieveLogStatus(material.materialName, `is picked by ${human.modelName}`);
|
||||
}
|
||||
if (human.currentLoad + 1 < human.point.action.loadCapacity) {
|
||||
if (human.currentLoad + 1 < (action as HumanAction).loadCapacity) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,65 +6,92 @@ import { useSceneContext } from '../../../scene/sceneContext';
|
||||
type ConveyorCallback = {
|
||||
conveyorId: string;
|
||||
callback: () => void;
|
||||
except: string[];
|
||||
};
|
||||
|
||||
export function useConveyorEventManager() {
|
||||
const { conveyorStore } = useSceneContext();
|
||||
const { getConveyorById } = conveyorStore();
|
||||
const callbacksRef = useRef<ConveyorCallback[]>([]);
|
||||
const { materialStore } = useSceneContext();
|
||||
const { getMaterialsByCurrentModelUuid } = materialStore();
|
||||
const callbacksRef = useRef<Map<string, ConveyorCallback[]>>(new Map());
|
||||
const isCooldownRef = useRef<Map<string, boolean>>(new Map());
|
||||
const isMonitoringRef = useRef(false);
|
||||
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { isPaused } = usePauseButtonStore();
|
||||
const { isReset } = useResetButtonStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (isReset) {
|
||||
callbacksRef.current = [];
|
||||
callbacksRef.current.clear();
|
||||
isCooldownRef.current.clear();
|
||||
isMonitoringRef.current = false;
|
||||
}
|
||||
}, [isReset])
|
||||
}, [isReset]);
|
||||
|
||||
// Add a new conveyor to monitor
|
||||
const addConveyorToMonitor = (conveyorId: string, callback: () => void) => {
|
||||
// Avoid duplicates
|
||||
if (!callbacksRef.current.some((entry) => entry.conveyorId === conveyorId)) {
|
||||
callbacksRef.current.push({ conveyorId, callback });
|
||||
const addConveyorToMonitor = (conveyorId: string, callback: () => void, except?: string[]) => {
|
||||
if (!callbacksRef.current.has(conveyorId)) {
|
||||
callbacksRef.current.set(conveyorId, []);
|
||||
}
|
||||
|
||||
// Start monitoring if not already running
|
||||
if (!isMonitoringRef.current) {
|
||||
isMonitoringRef.current = true;
|
||||
}
|
||||
callbacksRef.current.get(conveyorId)!.push({ conveyorId, callback, except: except || [] });
|
||||
isMonitoringRef.current = true;
|
||||
};
|
||||
|
||||
// Remove a conveyor from monitoring
|
||||
const removeConveyorFromMonitor = (conveyorId: string) => {
|
||||
callbacksRef.current = callbacksRef.current.filter(
|
||||
(entry) => entry.conveyorId !== conveyorId
|
||||
);
|
||||
|
||||
// Stop monitoring if no more conveyors to track
|
||||
if (callbacksRef.current.length === 0) {
|
||||
callbacksRef.current.delete(conveyorId);
|
||||
isCooldownRef.current.delete(conveyorId);
|
||||
if (callbacksRef.current.size === 0) {
|
||||
isMonitoringRef.current = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Check conveyor states every frame
|
||||
useFrame(() => {
|
||||
if (!isMonitoringRef.current || callbacksRef.current.length === 0 || !isPlaying || isPaused) return;
|
||||
if (!isMonitoringRef.current || !isPlaying || isPaused) return;
|
||||
|
||||
callbacksRef.current.forEach(({ conveyorId, callback }) => {
|
||||
const conveyor = getConveyorById(conveyorId);
|
||||
if (conveyor?.isPaused === false) {
|
||||
callback();
|
||||
removeConveyorFromMonitor(conveyorId); // Remove after triggering
|
||||
callbacksRef.current.forEach((queue, conveyorId) => {
|
||||
if (!queue || queue.length === 0) return;
|
||||
if (isCooldownRef.current.get(conveyorId)) return;
|
||||
|
||||
const { callback, except } = queue[0];
|
||||
const conveyorMaterials = getMaterialsByCurrentModelUuid(conveyorId);
|
||||
|
||||
let conditionMet = false;
|
||||
|
||||
if (!conveyorMaterials || conveyorMaterials.length === 0) {
|
||||
conditionMet = true;
|
||||
} else {
|
||||
const pausedMaterials = conveyorMaterials.filter(m => m.isPaused);
|
||||
|
||||
if (pausedMaterials.length === 0) {
|
||||
conditionMet = true;
|
||||
} else {
|
||||
const allPausedInExcept = pausedMaterials.filter(m => !except.includes(m.materialId));
|
||||
if (allPausedInExcept.length === 0) {
|
||||
conditionMet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (conditionMet) {
|
||||
queue.shift();
|
||||
if (callback) callback();
|
||||
|
||||
if (queue.length === 0) {
|
||||
removeConveyorFromMonitor(conveyorId);
|
||||
} else {
|
||||
isCooldownRef.current.set(conveyorId, true);
|
||||
setTimeout(() => {
|
||||
isCooldownRef.current.set(conveyorId, false);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Cleanup on unmount
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
callbacksRef.current = [];
|
||||
callbacksRef.current.clear();
|
||||
isCooldownRef.current.clear();
|
||||
isMonitoringRef.current = false;
|
||||
};
|
||||
}, []);
|
||||
@@ -73,4 +100,4 @@ export function useConveyorEventManager() {
|
||||
addConveyorToMonitor,
|
||||
removeConveyorFromMonitor,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import * as THREE from "three";
|
||||
import { useSubModuleStore } from "../../../../store/useModuleStore";
|
||||
import { useSelectedAction, useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
|
||||
import { useSelectedAction, useSelectedAsset, useSelectedEventData } from "../../../../store/simulation/useSimulationStore";
|
||||
import { handleAddEventToProduct } from "../points/functions/handleAddEventToProduct";
|
||||
import { QuadraticBezierLine } from "@react-three/drei";
|
||||
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
|
||||
@@ -38,6 +38,7 @@ function TriggerConnector() {
|
||||
const { selectedAction } = useSelectedAction();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
const { setSelectedEventData } = useSelectedEventData();
|
||||
const { projectId } = useParams();
|
||||
|
||||
const [firstSelectedPoint, setFirstSelectedPoint] = useState<{
|
||||
@@ -62,6 +63,10 @@ function TriggerConnector() {
|
||||
eventDatas: eventData,
|
||||
versionId: selectedVersion?.versionId || '',
|
||||
})
|
||||
|
||||
if (firstSelectedPoint?.pointUuid) {
|
||||
setSelectedEventData(eventData, firstSelectedPoint.pointUuid)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@@ -155,8 +160,8 @@ function TriggerConnector() {
|
||||
// Handle Human point
|
||||
else if (event.type === "human" && 'point' in event) {
|
||||
const point = event.point;
|
||||
if (point.action?.triggers) {
|
||||
point.action.triggers.forEach(trigger => {
|
||||
point.actions?.forEach(action => {
|
||||
action.triggers?.forEach(trigger => {
|
||||
if (trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint) {
|
||||
newConnections.push({
|
||||
id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
|
||||
@@ -166,7 +171,7 @@ function TriggerConnector() {
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -2,14 +2,19 @@ import { useEffect, useRef } from 'react';
|
||||
import { useFrame } from '@react-three/fiber';
|
||||
import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../store/usePlayButtonStore';
|
||||
import { useSceneContext } from '../../../scene/sceneContext';
|
||||
import { useProductContext } from '../../products/productContext';
|
||||
|
||||
export function useHumanEventManager() {
|
||||
const { humanStore } = useSceneContext();
|
||||
const { getHumanById } = humanStore();
|
||||
const { humanStore, productStore } = useSceneContext();
|
||||
const { getHumanById, clearLoadCount } = humanStore();
|
||||
const { getActionByUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
|
||||
const callbacksRef = useRef<Map<string, (() => void)[]>>(new Map());
|
||||
const isMonitoringRef = useRef(false);
|
||||
const actionQueueRef = useRef<Map<string, { actionType: "worker" | "assembly", actionUuid: string }[]>>(new Map());
|
||||
const isCooldownRef = useRef<Map<string, boolean>>(new Map());
|
||||
const isMonitoringRef = useRef(false);
|
||||
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { isPaused } = usePauseButtonStore();
|
||||
@@ -18,23 +23,34 @@ export function useHumanEventManager() {
|
||||
useEffect(() => {
|
||||
if (isReset) {
|
||||
callbacksRef.current.clear();
|
||||
actionQueueRef.current.clear();
|
||||
isCooldownRef.current.clear();
|
||||
isMonitoringRef.current = false;
|
||||
}
|
||||
}, [isReset]);
|
||||
|
||||
const addHumanToMonitor = (humanId: string, callback: () => void) => {
|
||||
const addHumanToMonitor = (humanId: string, callback: () => void, actionUuid: string) => {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, actionUuid || '') as HumanAction | undefined;
|
||||
|
||||
if (!action) return;
|
||||
|
||||
const actionType = action.actionType;
|
||||
if (actionType !== "worker" && actionType !== "assembly") return;
|
||||
|
||||
if (!callbacksRef.current.has(humanId)) {
|
||||
callbacksRef.current.set(humanId, []);
|
||||
actionQueueRef.current.set(humanId, []);
|
||||
}
|
||||
callbacksRef.current.get(humanId)!.push(callback);
|
||||
|
||||
if (!isMonitoringRef.current) {
|
||||
isMonitoringRef.current = true;
|
||||
}
|
||||
callbacksRef.current.get(humanId)!.push(callback);
|
||||
actionQueueRef.current.get(humanId)!.push({ actionType, actionUuid });
|
||||
|
||||
isMonitoringRef.current = true;
|
||||
};
|
||||
|
||||
const removeHumanFromMonitor = (humanId: string) => {
|
||||
callbacksRef.current.delete(humanId);
|
||||
actionQueueRef.current.delete(humanId);
|
||||
isCooldownRef.current.delete(humanId);
|
||||
|
||||
if (callbacksRef.current.size === 0) {
|
||||
@@ -43,47 +59,80 @@ export function useHumanEventManager() {
|
||||
};
|
||||
|
||||
useFrame(() => {
|
||||
|
||||
if (!isMonitoringRef.current || !isPlaying || isPaused) return;
|
||||
|
||||
callbacksRef.current.forEach((queue, humanId) => {
|
||||
if (queue.length === 0 || isCooldownRef.current.get(humanId)) return;
|
||||
|
||||
const actionQueue = actionQueueRef.current.get(humanId);
|
||||
if (!actionQueue || actionQueue.length === 0) return;
|
||||
|
||||
const { actionType: expectedActionType, actionUuid } = actionQueue[0];
|
||||
const human = getHumanById(humanId);
|
||||
const actionType = human?.point.action.actionType;
|
||||
const action = getActionByUuid(selectedProduct.productUuid, actionUuid) as HumanAction | undefined;
|
||||
|
||||
if (!human || !action || action.actionType !== expectedActionType) return;
|
||||
|
||||
let conditionMet = false;
|
||||
|
||||
if (actionType === 'worker') {
|
||||
conditionMet = Boolean(
|
||||
human &&
|
||||
human.isActive === false &&
|
||||
human.state === 'idle' &&
|
||||
human.isScheduled === false &&
|
||||
human.currentLoad < human.point.action.loadCapacity
|
||||
);
|
||||
} else if (actionType === 'assembly') {
|
||||
conditionMet = Boolean(
|
||||
human &&
|
||||
human.isActive === false &&
|
||||
human.state === 'idle' &&
|
||||
human.isScheduled === false
|
||||
);
|
||||
const currentAction = getActionByUuid(selectedProduct.productUuid, human.currentAction?.actionUuid || '') as HumanAction | undefined;
|
||||
|
||||
if (expectedActionType === "worker") {
|
||||
if (currentAction && currentAction.actionType === 'worker') {
|
||||
conditionMet = (
|
||||
!human.isActive &&
|
||||
human.state === "idle" &&
|
||||
human.currentLoad < currentAction.loadCapacity
|
||||
);
|
||||
|
||||
if (human.totalLoadCount >= currentAction.loadCount) {
|
||||
queue.shift();
|
||||
actionQueue.shift();
|
||||
if (queue.length === 0) {
|
||||
removeHumanFromMonitor(humanId);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
conditionMet = (
|
||||
!human.isActive &&
|
||||
human.state === "idle" &&
|
||||
human.currentLoad < action.loadCapacity
|
||||
);
|
||||
}
|
||||
|
||||
} else if (expectedActionType === "assembly") {
|
||||
if (currentAction && currentAction.actionType === 'worker') {
|
||||
conditionMet = (
|
||||
!human.isActive &&
|
||||
human.state === "idle" &&
|
||||
human.currentLoad < currentAction.loadCapacity
|
||||
);
|
||||
} else {
|
||||
conditionMet = (
|
||||
!human.isActive &&
|
||||
human.state === "idle" &&
|
||||
human.currentLoad < action.loadCapacity
|
||||
)
|
||||
}
|
||||
if (conditionMet) {
|
||||
clearLoadCount(human.modelUuid);
|
||||
}
|
||||
}
|
||||
|
||||
if (conditionMet) {
|
||||
const callback = queue.shift();
|
||||
if (callback) {
|
||||
callback();
|
||||
actionQueue.shift();
|
||||
|
||||
if (queue.length === 0) {
|
||||
removeHumanFromMonitor(humanId);
|
||||
} else {
|
||||
isCooldownRef.current.set(humanId, true);
|
||||
setTimeout(() => {
|
||||
isCooldownRef.current.set(humanId, false);
|
||||
}, 1000);
|
||||
}
|
||||
if (callback) callback();
|
||||
|
||||
if (queue.length === 0) {
|
||||
removeHumanFromMonitor(humanId);
|
||||
} else {
|
||||
isCooldownRef.current.set(humanId, true);
|
||||
setTimeout(() => {
|
||||
isCooldownRef.current.set(humanId, false);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -92,8 +141,9 @@ export function useHumanEventManager() {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
callbacksRef.current.clear();
|
||||
isMonitoringRef.current = false;
|
||||
actionQueueRef.current.clear();
|
||||
isCooldownRef.current.clear();
|
||||
isMonitoringRef.current = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import * as THREE from 'three';
|
||||
import { Line } from '@react-three/drei';
|
||||
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
|
||||
import { useSceneContext } from '../../../../scene/sceneContext';
|
||||
import { useProductContext } from '../../../products/productContext';
|
||||
|
||||
interface HumanAnimatorProps {
|
||||
path: [number, number, number][];
|
||||
@@ -15,7 +16,10 @@ interface HumanAnimatorProps {
|
||||
}
|
||||
|
||||
function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, startUnloadingProcess }: Readonly<HumanAnimatorProps>) {
|
||||
const { humanStore, assetStore } = useSceneContext();
|
||||
const { humanStore, assetStore, productStore } = useSceneContext();
|
||||
const { getActionByUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { getHumanById } = humanStore();
|
||||
const { setCurrentAnimation } = assetStore();
|
||||
const { isPaused } = usePauseButtonStore();
|
||||
@@ -25,26 +29,29 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
|
||||
const progressRef = useRef<number>(0);
|
||||
const movingForward = useRef<boolean>(true);
|
||||
const completedRef = useRef<boolean>(false);
|
||||
const [objectRotation, setObjectRotation] = useState<[number, number, number] | null>(human.point?.action?.pickUpPoint?.rotation || [0, 0, 0])
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
const [objectRotation, setObjectRotation] = useState<[number, number, number] | null>((action as HumanAction)?.pickUpPoint?.rotation || [0, 0, 0])
|
||||
const [restRotation, setRestingRotation] = useState<boolean>(true);
|
||||
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
|
||||
const { scene } = useThree();
|
||||
|
||||
useEffect(() => {
|
||||
if (!human.currentAction?.actionUuid) return;
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
if (currentPhase === 'init-pickup' && path.length > 0) {
|
||||
setCurrentPath(path);
|
||||
setObjectRotation(human.point.action.pickUpPoint?.rotation ?? null)
|
||||
setObjectRotation((action as HumanAction).pickUpPoint?.rotation ?? null)
|
||||
} else if (currentPhase === 'init_assembly' && path.length > 0) {
|
||||
setObjectRotation(human.point.action?.assemblyPoint?.rotation ?? null)
|
||||
setObjectRotation((action as HumanAction)?.assemblyPoint?.rotation ?? null)
|
||||
setCurrentPath(path);
|
||||
} else if (currentPhase === 'pickup-drop' && path.length > 0) {
|
||||
setObjectRotation(human.point.action?.dropPoint?.rotation ?? null)
|
||||
setObjectRotation((action as HumanAction)?.dropPoint?.rotation ?? null)
|
||||
setCurrentPath(path);
|
||||
} else if (currentPhase === 'drop-pickup' && path.length > 0) {
|
||||
setObjectRotation(human.point.action?.pickUpPoint?.rotation ?? null)
|
||||
setObjectRotation((action as HumanAction)?.pickUpPoint?.rotation ?? null)
|
||||
setCurrentPath(path);
|
||||
}
|
||||
}, [currentPhase, path, objectRotation]);
|
||||
}, [currentPhase, path, objectRotation, selectedProduct, human.currentAction?.actionUuid]);
|
||||
|
||||
useEffect(() => {
|
||||
completedRef.current = false;
|
||||
@@ -77,7 +84,7 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
|
||||
|
||||
const object = scene.getObjectByProperty('uuid', human.modelUuid);
|
||||
if (!object || currentPath.length < 2) return;
|
||||
if (isPaused) return;
|
||||
if (isPaused || !isPlaying) return;
|
||||
|
||||
let totalDistance = 0;
|
||||
const distances = [];
|
||||
@@ -128,13 +135,13 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
|
||||
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
|
||||
const position = start.clone().lerp(end, t);
|
||||
object.position.copy(position);
|
||||
if (human.currentMaterials.length > 0) {
|
||||
if (human.currentMaterials.length > 0 && action?.actionType === 'worker' && (currentPhase !== 'init-pickup' && currentPhase !== 'init_assembly')) {
|
||||
setCurrentAnimation(human.modelUuid, 'walk_with_box', true, true, true);
|
||||
} else {
|
||||
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
|
||||
}
|
||||
} else {
|
||||
if (human.currentMaterials.length > 0) {
|
||||
if (human.currentMaterials.length > 0 && action?.actionType === 'worker' && (currentPhase !== 'init-pickup' && currentPhase !== 'init_assembly')) {
|
||||
setCurrentAnimation(human.modelUuid, 'idle_with_box', true, true, true);
|
||||
} else {
|
||||
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
|
||||
|
||||
@@ -2,11 +2,18 @@ import { useEffect, useRef, useState } from 'react';
|
||||
import { useThree } from '@react-three/fiber';
|
||||
import * as THREE from 'three';
|
||||
import { MaterialModel } from '../../../materials/instances/material/materialModel';
|
||||
import { useSceneContext } from '../../../../scene/sceneContext';
|
||||
import { useProductContext } from '../../../products/productContext';
|
||||
|
||||
const MaterialAnimator = ({ human }: { human: HumanStatus }) => {
|
||||
const MaterialAnimator = ({ human, currentPhase }: { human: HumanStatus, currentPhase: string; }) => {
|
||||
const { productStore } = useSceneContext();
|
||||
const { getActionByUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const meshRef = useRef<any>(null!);
|
||||
const [hasLoad, setHasLoad] = useState(false);
|
||||
const [isAttached, setIsAttached] = useState(false);
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
const { scene } = useThree();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -39,11 +46,11 @@ const MaterialAnimator = ({ human }: { human: HumanStatus }) => {
|
||||
meshRef.current.visible = true;
|
||||
setIsAttached(true);
|
||||
}
|
||||
}, [hasLoad, human.modelUuid, scene]);
|
||||
}, [hasLoad, human.modelUuid, scene, currentPhase]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{hasLoad && human.point.action.actionType === 'worker' && human.currentMaterials.length > 0 && (
|
||||
{hasLoad && (action as HumanAction).actionType === 'worker' && human.currentMaterials.length > 0 && currentPhase !== 'init-pickup' && currentPhase !== 'init_assembly' && (
|
||||
<MaterialModel
|
||||
matRef={meshRef}
|
||||
materialId={human.currentMaterials[0].materialId || ''}
|
||||
|
||||
@@ -16,7 +16,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { scene } = useThree();
|
||||
const { assetStore, materialStore, armBotStore, conveyorStore, machineStore, vehicleStore, humanStore, storageUnitStore, productStore } = useSceneContext();
|
||||
const { removeMaterial, setEndTime, setMaterial } = materialStore();
|
||||
const { removeMaterial, setEndTime, setMaterial, setIsVisible } = materialStore();
|
||||
const { getStorageUnitById } = storageUnitStore();
|
||||
const { getArmBotById } = armBotStore();
|
||||
const { getConveyorById } = conveyorStore();
|
||||
@@ -120,15 +120,21 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
|
||||
useEffect(() => {
|
||||
if (isPlaying) {
|
||||
if (!human.point.action.assemblyPoint || human.point.action.actionType === 'worker') return;
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
|
||||
if (!action || !(action as HumanAction).assemblyPoint || (action as HumanAction).actionType === 'worker') return;
|
||||
|
||||
if (!human.isActive && human.state === 'idle' && (currentPhase === 'init' || currentPhase === 'picking')) {
|
||||
|
||||
const humanMesh = scene.getObjectByProperty('uuid', human.modelUuid);
|
||||
if (!humanMesh) return;
|
||||
|
||||
if (!human.isActive && human.state === 'idle' && currentPhase === 'init') {
|
||||
const toPickupPath = computePath(
|
||||
new THREE.Vector3(human?.position[0], human?.position[1], human?.position[2]),
|
||||
new THREE.Vector3(...humanMesh.position.toArray()),
|
||||
new THREE.Vector3(
|
||||
human?.point?.action?.assemblyPoint?.position?.[0] ?? 0,
|
||||
human?.point?.action?.assemblyPoint?.position?.[1] ?? 0,
|
||||
human?.point?.action?.assemblyPoint?.position?.[2] ?? 0
|
||||
(action as HumanAction)?.assemblyPoint?.position?.[0] ?? 0,
|
||||
(action as HumanAction)?.assemblyPoint?.position?.[1] ?? 0,
|
||||
(action as HumanAction)?.assemblyPoint?.position?.[2] ?? 0
|
||||
)
|
||||
);
|
||||
setPath(toPickupPath);
|
||||
@@ -138,6 +144,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
|
||||
humanStatus(human.modelUuid, 'Human is waiting for material in assembly');
|
||||
} else if (!human.isActive && human.state === 'idle' && currentPhase === 'waiting') {
|
||||
|
||||
if (human.currentMaterials.length > 0 && humanAsset && humanAsset.animationState?.current !== 'working_standing') {
|
||||
setCurrentAnimation(human.modelUuid, 'working_standing', true, true, false);
|
||||
setHumanState(human.modelUuid, 'running');
|
||||
@@ -145,7 +152,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
setHumanActive(human.modelUuid, true);
|
||||
|
||||
processStartTimeRef.current = performance.now();
|
||||
processTimeRef.current = human.point.action.processTime || 0;
|
||||
processTimeRef.current = (action as HumanAction).processTime || 0;
|
||||
accumulatedPausedTimeRef.current = 0;
|
||||
lastPauseTimeRef.current = null;
|
||||
hasLoggedHalfway.current = false;
|
||||
@@ -156,7 +163,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
}
|
||||
}
|
||||
} else if (human.isActive && human.state === 'running' && human.currentMaterials.length > 0 && humanAsset && humanAsset.animationState?.current === 'working_standing' && humanAsset.animationState?.isCompleted) {
|
||||
if (human.point.action.assemblyPoint && currentPhase === 'assembling') {
|
||||
if ((action as HumanAction).assemblyPoint && currentPhase === 'assembling') {
|
||||
setHumanState(human.modelUuid, 'idle');
|
||||
setCurrentPhase('waiting');
|
||||
setHumanActive(human.modelUuid, false);
|
||||
@@ -167,7 +174,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
decrementHumanLoad(human.modelUuid, 1);
|
||||
const material = removeLastMaterial(human.modelUuid);
|
||||
if (material) {
|
||||
triggerPointActions(human.point.action, material.materialId);
|
||||
triggerPointActions((action as HumanAction), material.materialId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,9 +186,11 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
}, [human, currentPhase, path, isPlaying, humanAsset?.animationState?.isCompleted]);
|
||||
|
||||
const trackAssemblyProcess = useCallback(() => {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
|
||||
const now = performance.now();
|
||||
|
||||
if (!processStartTimeRef.current || !human.point.action.processTime) {
|
||||
if (!processStartTimeRef.current || !(action as HumanAction).processTime || !action) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -197,12 +206,12 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
}
|
||||
|
||||
const elapsed = (now - processStartTimeRef.current - accumulatedPausedTimeRef.current) * isSpeedRef.current;
|
||||
const totalProcessTimeMs = human.point.action.processTime * 1000;
|
||||
const totalProcessTimeMs = ((action as HumanAction).processTime || 1) * 1000;
|
||||
|
||||
if (elapsed >= totalProcessTimeMs / 2 && !hasLoggedHalfway.current) {
|
||||
hasLoggedHalfway.current = true;
|
||||
if (human.currentMaterials.length > 0) {
|
||||
setMaterial(human.currentMaterials[0].materialId, human.point.action.swapMaterial || 'Default Material');
|
||||
setMaterial(human.currentMaterials[0].materialId, (action as HumanAction).swapMaterial || 'Default Material');
|
||||
}
|
||||
humanStatus(human.modelUuid, `🟡 Human ${human.modelUuid} reached halfway in assembly.`);
|
||||
}
|
||||
@@ -219,19 +228,24 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
}
|
||||
|
||||
processAnimationIdRef.current = requestAnimationFrame(trackAssemblyProcess);
|
||||
}, [human.modelUuid, human.point.action.processTime, human.currentMaterials]);
|
||||
}, [human.modelUuid, human.currentMaterials]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isPlaying) {
|
||||
if (!human.point.action.pickUpPoint || !human.point.action.dropPoint || human.point.action.actionType === 'assembly') return;
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
if (!action || action.actionType !== 'worker' || !action.pickUpPoint || !action.dropPoint) return;
|
||||
|
||||
if (!human.isActive && human.state === 'idle' && (currentPhase === 'init' || currentPhase === 'waiting')) {
|
||||
|
||||
const humanMesh = scene.getObjectByProperty('uuid', human.modelUuid);
|
||||
if (!humanMesh) return;
|
||||
|
||||
if (!human.isActive && human.state === 'idle' && currentPhase === 'init') {
|
||||
const toPickupPath = computePath(
|
||||
new THREE.Vector3(human?.position[0], human?.position[1], human?.position[2]),
|
||||
new THREE.Vector3(...humanMesh.position.toArray()),
|
||||
new THREE.Vector3(
|
||||
human?.point?.action?.pickUpPoint?.position?.[0] ?? 0,
|
||||
human?.point?.action?.pickUpPoint?.position?.[1] ?? 0,
|
||||
human?.point?.action?.pickUpPoint?.position?.[2] ?? 0
|
||||
action?.pickUpPoint?.position?.[0] ?? 0,
|
||||
action?.pickUpPoint?.position?.[1] ?? 0,
|
||||
action?.pickUpPoint?.position?.[2] ?? 0
|
||||
)
|
||||
);
|
||||
setPath(toPickupPath);
|
||||
@@ -242,18 +256,18 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
humanStatus(human.modelUuid, 'Started from init, heading to pickup');
|
||||
return;
|
||||
} else if (!human.isActive && human.state === 'idle' && currentPhase === 'picking') {
|
||||
if (humanAsset && human.currentLoad === human.point.action.loadCapacity && human.currentMaterials.length > 0 && humanAsset.animationState?.current === 'pickup' && humanAsset.animationState?.isCompleted) {
|
||||
if (human.point.action.pickUpPoint && human.point.action.dropPoint) {
|
||||
if (humanAsset && human.currentLoad === action.loadCapacity && human.currentMaterials.length > 0 && humanAsset.animationState?.current === 'pickup' && humanAsset.animationState?.isCompleted) {
|
||||
if (action.pickUpPoint && action.dropPoint) {
|
||||
const toDrop = computePath(
|
||||
new THREE.Vector3(
|
||||
human.point.action.pickUpPoint.position?.[0] ?? 0,
|
||||
human.point.action.pickUpPoint.position?.[1] ?? 0,
|
||||
human.point.action.pickUpPoint.position?.[2] ?? 0
|
||||
action.pickUpPoint.position?.[0] ?? 0,
|
||||
action.pickUpPoint.position?.[1] ?? 0,
|
||||
action.pickUpPoint.position?.[2] ?? 0
|
||||
),
|
||||
new THREE.Vector3(
|
||||
human.point.action.dropPoint.position?.[0] ?? 0,
|
||||
human.point.action.dropPoint.position?.[1] ?? 0,
|
||||
human.point.action.dropPoint.position?.[2] ?? 0
|
||||
action.dropPoint.position?.[0] ?? 0,
|
||||
action.dropPoint.position?.[1] ?? 0,
|
||||
action.dropPoint.position?.[2] ?? 0
|
||||
)
|
||||
);
|
||||
setPath(toDrop);
|
||||
@@ -262,21 +276,24 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
setCurrentAnimation(human.modelUuid, 'walk_with_box', true, true, true);
|
||||
humanStatus(human.modelUuid, 'Started from pickup point, heading to drop point');
|
||||
}
|
||||
} else if (human.currentLoad === human.point.action.loadCapacity && human.currentMaterials.length > 0 && humanAsset?.animationState?.current !== 'pickup') {
|
||||
} else if (human.currentLoad === action.loadCapacity && human.currentMaterials.length > 0 && humanAsset?.animationState?.current !== 'pickup') {
|
||||
if (human.currentMaterials[0]?.materialId) {
|
||||
setIsVisible(human.currentMaterials[0]?.materialId, false);
|
||||
}
|
||||
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
|
||||
}
|
||||
} else if (!human.isActive && human.state === 'idle' && currentPhase === 'dropping' && human.currentLoad === 0) {
|
||||
if (human.point.action.pickUpPoint && human.point.action.dropPoint) {
|
||||
if (action.pickUpPoint && action.dropPoint) {
|
||||
const dropToPickup = computePath(
|
||||
new THREE.Vector3(
|
||||
human.point.action.dropPoint.position?.[0] ?? 0,
|
||||
human.point.action.dropPoint.position?.[1] ?? 0,
|
||||
human.point.action.dropPoint.position?.[2] ?? 0
|
||||
action.dropPoint.position?.[0] ?? 0,
|
||||
action.dropPoint.position?.[1] ?? 0,
|
||||
action.dropPoint.position?.[2] ?? 0
|
||||
),
|
||||
new THREE.Vector3(
|
||||
human.point.action.pickUpPoint.position?.[0] ?? 0,
|
||||
human.point.action.pickUpPoint.position?.[1] ?? 0,
|
||||
human.point.action.pickUpPoint.position?.[2] ?? 0
|
||||
action.pickUpPoint.position?.[0] ?? 0,
|
||||
action.pickUpPoint.position?.[1] ?? 0,
|
||||
action.pickUpPoint.position?.[2] ?? 0
|
||||
)
|
||||
);
|
||||
setPath(dropToPickup);
|
||||
@@ -373,38 +390,35 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
}, [human, isPlaying]);
|
||||
|
||||
function startUnloadingProcess() {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
|
||||
const humanAsset = getAssetById(human.modelUuid);
|
||||
if (humanAsset?.animationState?.current !== 'drop') {
|
||||
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||
}
|
||||
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
|
||||
if (human.point.action.triggers.length > 0) {
|
||||
const trigger = getTriggerByUuid(selectedProduct.productUuid, human.point.action.triggers[0]?.triggerUuid);
|
||||
if ((action as HumanAction).triggers.length > 0) {
|
||||
const trigger = getTriggerByUuid(selectedProduct.productUuid, (action as HumanAction).triggers[0]?.triggerUuid);
|
||||
const model = getEventByModelUuid(selectedProduct.productUuid, trigger?.triggeredAsset?.triggeredModel?.modelUuid || '');
|
||||
|
||||
if (trigger && model) {
|
||||
if (model.type === 'transfer') {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human.point.action.actionUuid);
|
||||
if (action) {
|
||||
handleMaterialDropToConveyor(model);
|
||||
}
|
||||
} else if (model.type === 'machine') {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human.point.action.actionUuid);
|
||||
if (action) {
|
||||
handleMaterialDropToMachine(model);
|
||||
}
|
||||
} else if (model.type === 'roboticArm') {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human.point.action.actionUuid);
|
||||
if (action) {
|
||||
handleMaterialDropToArmBot(model);
|
||||
}
|
||||
} else if (model.type === 'storageUnit') {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human.point.action.actionUuid);
|
||||
if (action) {
|
||||
handleMaterialDropToStorageUnit(model);
|
||||
}
|
||||
} else if (model.type === 'vehicle') {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human.point.action.actionUuid);
|
||||
if (action) {
|
||||
handleMaterialDropToVehicle(model);
|
||||
}
|
||||
@@ -423,6 +437,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
}
|
||||
|
||||
function handleMaterialDropToStorageUnit(model: StorageEventSchema) {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
const humanAsset = getAssetById(human.modelUuid);
|
||||
if (model && humanAsset?.animationState?.current !== 'drop') {
|
||||
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||
@@ -436,7 +451,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
human.currentLoad,
|
||||
model.modelUuid,
|
||||
model.point.action.storageCapacity,
|
||||
human.point.action
|
||||
(action as HumanAction)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -490,6 +505,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
}
|
||||
|
||||
function handleMaterialDropToConveyor(model: ConveyorEventSchema) {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
const humanAsset = getAssetById(human.modelUuid);
|
||||
if (humanAsset?.animationState?.current !== 'drop') {
|
||||
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||
@@ -503,7 +519,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
human.modelUuid,
|
||||
human.currentLoad,
|
||||
conveyor.modelUuid,
|
||||
human.point.action
|
||||
(action as HumanAction)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -555,6 +571,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
}
|
||||
|
||||
function handleMaterialDropToArmBot(model: RoboticArmEventSchema) {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
const humanAsset = getAssetById(human.modelUuid);
|
||||
if (humanAsset?.animationState?.current !== 'drop') {
|
||||
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||
@@ -568,7 +585,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
human.modelUuid,
|
||||
human.currentLoad,
|
||||
model.modelUuid,
|
||||
human.point.action
|
||||
(action as HumanAction)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -625,6 +642,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
}
|
||||
|
||||
function handleMaterialDropToVehicle(model: VehicleEventSchema) {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
const humanAsset = getAssetById(human.modelUuid);
|
||||
if (humanAsset?.animationState?.current !== 'drop') {
|
||||
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||
@@ -638,7 +656,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
human.modelUuid,
|
||||
human.currentLoad,
|
||||
model.modelUuid,
|
||||
human.point.action
|
||||
(action as HumanAction)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -695,6 +713,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
}
|
||||
|
||||
function handleMaterialDropToMachine(model: MachineEventSchema) {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
|
||||
const humanAsset = getAssetById(human.modelUuid);
|
||||
if (humanAsset?.animationState?.current !== 'drop') {
|
||||
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||
@@ -708,7 +727,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
human.modelUuid,
|
||||
human.currentLoad,
|
||||
model.modelUuid,
|
||||
human.point.action
|
||||
(action as HumanAction)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -804,7 +823,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
||||
startUnloadingProcess={startUnloadingProcess}
|
||||
/>
|
||||
|
||||
<MaterialAnimator human={human} />
|
||||
<MaterialAnimator currentPhase={currentPhase} human={human} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ function HumanUi() {
|
||||
const { humanStore, productStore } = useSceneContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { humans, getHumanById } = humanStore();
|
||||
const { updateEvent } = productStore();
|
||||
const { updateEvent, updateAction, getActionByUuid } = productStore();
|
||||
const [startPosition, setStartPosition] = useState<[number, number, number]>([0, 1, 0]);
|
||||
const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 1, 0]);
|
||||
const [assemblyPosition, setAssemblyPosition] = useState<[number, number, number]>([0, 1, 0]);
|
||||
@@ -49,9 +49,8 @@ function HumanUi() {
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
const { projectId } = useParams();
|
||||
|
||||
const selectedHuman = selectedEventSphere ? getHumanById(selectedEventSphere.userData.modelUuid) : null;
|
||||
const actionType = selectedHuman?.point?.action?.actionType || null;
|
||||
const isAssembly = actionType === 'assembly';
|
||||
const currentAction = getActionByUuid(selectedProduct.productUuid, selectedAction.actionId || '');
|
||||
const isAssembly = currentAction?.actionType === 'assembly';
|
||||
|
||||
const updateBackend = (
|
||||
productName: string,
|
||||
@@ -69,10 +68,10 @@ function HumanUi() {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedEventSphere) return;
|
||||
if (!selectedEventSphere || !selectedAction?.actionId) return;
|
||||
|
||||
const selectedHuman = getHumanById(selectedEventSphere.userData.modelUuid);
|
||||
if (!selectedHuman || !selectedHuman.point?.action) return;
|
||||
if (!selectedHuman || !selectedHuman.point?.actions) return;
|
||||
|
||||
setSelectedHumanData({
|
||||
position: selectedHuman.position,
|
||||
@@ -87,7 +86,8 @@ function HumanUi() {
|
||||
);
|
||||
}
|
||||
|
||||
const action = selectedHuman.point.action;
|
||||
const action = selectedHuman.point.actions.find(a => a.actionUuid === selectedAction.actionId);
|
||||
if (!action) return;
|
||||
|
||||
if (isAssembly) {
|
||||
if (action.assemblyPoint?.position && outerGroup.current) {
|
||||
@@ -170,44 +170,46 @@ function HumanUi() {
|
||||
if (!selectedEventSphere?.userData.modelUuid || !selectedAction?.actionId) return;
|
||||
|
||||
const selectedHuman = getHumanById(selectedEventSphere.userData.modelUuid);
|
||||
if (!selectedHuman || !outerGroup.current) return;
|
||||
if (!selectedHuman || !outerGroup.current || !currentAction) return;
|
||||
|
||||
let updatedAction;
|
||||
const updatedActions = selectedHuman.point.actions.map(action => {
|
||||
if (action.actionUuid !== currentAction.actionUuid) return action;
|
||||
|
||||
if (isAssembly) {
|
||||
if (!assemblyMarker.current) return;
|
||||
if (isAssembly) {
|
||||
if (!assemblyMarker.current || !outerGroup.current) return action;
|
||||
|
||||
const worldPosAssembly = new Vector3(...assemblyPosition);
|
||||
const globalAssemblyPosition = outerGroup.current.localToWorld(worldPosAssembly.clone());
|
||||
const worldPosAssembly = new Vector3(...assemblyPosition);
|
||||
const globalAssemblyPosition = outerGroup.current.localToWorld(worldPosAssembly.clone());
|
||||
|
||||
updatedAction = {
|
||||
...selectedHuman.point.action,
|
||||
assemblyPoint: {
|
||||
position: [globalAssemblyPosition.x, globalAssemblyPosition.y, globalAssemblyPosition.z] as [number, number, number],
|
||||
rotation: assemblyRotation
|
||||
},
|
||||
};
|
||||
} else {
|
||||
if (!startMarker.current || !endMarker.current) return;
|
||||
return {
|
||||
...action,
|
||||
assemblyPoint: {
|
||||
position: [globalAssemblyPosition.x, globalAssemblyPosition.y, globalAssemblyPosition.z] as [number, number, number],
|
||||
rotation: assemblyRotation
|
||||
},
|
||||
};
|
||||
} else {
|
||||
if (!startMarker.current || !endMarker.current || !outerGroup.current) return action;
|
||||
|
||||
const worldPosStart = new Vector3(...startPosition);
|
||||
const globalStartPosition = outerGroup.current.localToWorld(worldPosStart.clone());
|
||||
const worldPosStart = new Vector3(...startPosition);
|
||||
const globalStartPosition = outerGroup.current.localToWorld(worldPosStart.clone());
|
||||
|
||||
const worldPosEnd = new Vector3(...endPosition);
|
||||
const globalEndPosition = outerGroup.current.localToWorld(worldPosEnd.clone());
|
||||
const worldPosEnd = new Vector3(...endPosition);
|
||||
const globalEndPosition = outerGroup.current.localToWorld(worldPosEnd.clone());
|
||||
|
||||
updatedAction = {
|
||||
...selectedHuman.point.action,
|
||||
pickUpPoint: {
|
||||
position: [globalStartPosition.x, globalStartPosition.y, globalStartPosition.z] as [number, number, number],
|
||||
rotation: startRotation,
|
||||
},
|
||||
dropPoint: {
|
||||
position: [globalEndPosition.x, globalEndPosition.y, globalEndPosition.z] as [number, number, number],
|
||||
rotation: endRotation,
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
...action,
|
||||
pickUpPoint: {
|
||||
position: [globalStartPosition.x, globalStartPosition.y, globalStartPosition.z] as [number, number, number],
|
||||
rotation: startRotation,
|
||||
},
|
||||
dropPoint: {
|
||||
position: [globalEndPosition.x, globalEndPosition.y, globalEndPosition.z] as [number, number, number],
|
||||
rotation: endRotation,
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const event = updateEvent(
|
||||
selectedProduct.productUuid,
|
||||
@@ -216,7 +218,7 @@ function HumanUi() {
|
||||
...selectedHuman,
|
||||
point: {
|
||||
...selectedHuman.point,
|
||||
action: updatedAction,
|
||||
actions: updatedActions,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
@@ -12,7 +12,8 @@ function MaterialInstance({ material }: { readonly material: MaterialSchema }) {
|
||||
const matRef: any = useRef();
|
||||
const { scene } = useThree();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { productStore } = useSceneContext();
|
||||
const { productStore, materialStore } = useSceneContext();
|
||||
const { setIsPaused } = materialStore();
|
||||
const { getModelUuidByPointUuid, getPointByUuid, getEventByModelUuid, getActionByPointUuid } = productStore();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { speed } = useAnimationPlaySpeed();
|
||||
@@ -80,16 +81,23 @@ function MaterialInstance({ material }: { readonly material: MaterialSchema }) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (event.type === 'human') {
|
||||
return event.speed;
|
||||
}
|
||||
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
const callTrigger = () => {
|
||||
if (!material.next) return;
|
||||
const action = getActionByPointUuid(selectedProduct.productUuid, material.next.pointUuid);
|
||||
if (action) {
|
||||
triggerPointActions(action, material.materialId);
|
||||
if (material.next) {
|
||||
const action = getActionByPointUuid(selectedProduct.productUuid, material.next.pointUuid);
|
||||
if (action) {
|
||||
triggerPointActions(action, material.materialId);
|
||||
}
|
||||
} else {
|
||||
setIsPaused(material.materialId, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +105,7 @@ function MaterialInstance({ material }: { readonly material: MaterialSchema }) {
|
||||
<>
|
||||
|
||||
{material.isRendered &&
|
||||
<MaterialModel materialId={material.materialId} matRef={matRef} materialType={material.materialType} visible={material.isVisible} position={position} />
|
||||
<MaterialModel materialId={material.materialId} matRef={matRef} materialType={material.materialType} visible={material.isVisible} position={position} rotation={[rotation.x, rotation.y, rotation.z]} />
|
||||
}
|
||||
|
||||
<MaterialAnimator
|
||||
|
||||
@@ -20,7 +20,7 @@ function Products() {
|
||||
const { addMachine, clearMachines } = machineStore();
|
||||
const { addConveyor, clearConveyors } = conveyorStore();
|
||||
const { setCurrentMaterials, clearStorageUnits, updateCurrentLoad, addStorageUnit } = storageUnitStore();
|
||||
const { addHuman, clearHumans } = humanStore();
|
||||
const { addHuman, addCurrentAction, clearHumans } = humanStore();
|
||||
const { isReset } = useResetButtonStore();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { mainProduct } = useMainProduct();
|
||||
@@ -162,6 +162,10 @@ function Products() {
|
||||
product.eventDatas.forEach(events => {
|
||||
if (events.type === 'human') {
|
||||
addHuman(selectedProduct.productUuid, events);
|
||||
|
||||
if (events.point.actions.length > 0) {
|
||||
addCurrentAction(events.modelUuid, events.point.actions[0].actionUuid);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -330,9 +330,6 @@ export function useTriggerHandler() {
|
||||
if (vehicle) {
|
||||
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
|
||||
// Handle current action from vehicle
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
handleAction(action, materialId);
|
||||
@@ -343,88 +340,51 @@ export function useTriggerHandler() {
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
|
||||
addVehicleToMonitor(vehicle.modelUuid,
|
||||
() => {
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
handleAction(action, materialId);
|
||||
}
|
||||
)
|
||||
addVehicleToMonitor(vehicle.modelUuid, () => {
|
||||
handleAction(action, materialId);
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
addHumanToMonitor(human.modelUuid, () => {
|
||||
const vehicle = getVehicleById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
|
||||
if (vehicle) {
|
||||
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
|
||||
// Handle current action from vehicle
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
handleAction(action, materialId);
|
||||
|
||||
} else {
|
||||
|
||||
// Handle current action using Event Manager
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
|
||||
addVehicleToMonitor(vehicle.modelUuid,
|
||||
() => {
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
handleAction(action, materialId);
|
||||
}
|
||||
)
|
||||
addVehicleToMonitor(vehicle.modelUuid, () => {
|
||||
handleAction(action, materialId);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}, action.actionUuid)
|
||||
}
|
||||
}
|
||||
} else if (model?.type === 'transfer') {
|
||||
const human = getHumanById(trigger.triggeredAsset?.triggeredModel.modelUuid);
|
||||
if (human) {
|
||||
if (human.isActive === false && human.state === 'idle') {
|
||||
const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
addHumanToMonitor(human.modelUuid, () => {
|
||||
const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
|
||||
if (conveyor) {
|
||||
// Handle current action using Event Manager
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
|
||||
addConveyorToMonitor(conveyor.modelUuid,
|
||||
() => {
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
handleAction(action, materialId);
|
||||
}
|
||||
)
|
||||
addConveyorToMonitor(conveyor.modelUuid, () => {
|
||||
handleAction(action, materialId);
|
||||
}, [materialId])
|
||||
}
|
||||
} else {
|
||||
setIsPaused(materialId, true);
|
||||
addHumanToMonitor(human.modelUuid, () => {
|
||||
const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
|
||||
if (conveyor) {
|
||||
// Handle current action using Event Manager
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
|
||||
addConveyorToMonitor(conveyor.modelUuid,
|
||||
() => {
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
handleAction(action, materialId);
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}, action.actionUuid)
|
||||
}
|
||||
} else if (model?.type === 'machine') {
|
||||
const human = getHumanById(trigger.triggeredAsset?.triggeredModel.modelUuid);
|
||||
@@ -434,9 +394,6 @@ export function useTriggerHandler() {
|
||||
if (machine) {
|
||||
if (machine.isActive === false && machine.state === 'idle' && !machine.currentAction) {
|
||||
setIsPaused(materialId, true);
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
handleAction(action, materialId);
|
||||
} else {
|
||||
@@ -445,46 +402,31 @@ export function useTriggerHandler() {
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
|
||||
addMachineToMonitor(machine.modelUuid,
|
||||
() => {
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
handleAction(action, materialId);
|
||||
}
|
||||
)
|
||||
addMachineToMonitor(machine.modelUuid, () => {
|
||||
handleAction(action, materialId);
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
addHumanToMonitor(human.modelUuid, () => {
|
||||
const machine = getMachineById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
|
||||
if (machine) {
|
||||
if (machine.isActive === false && machine.state === 'idle' && !machine.currentAction) {
|
||||
setIsPaused(materialId, true);
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
handleAction(action, materialId);
|
||||
} else {
|
||||
|
||||
// Handle current action using Event Manager
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
|
||||
addMachineToMonitor(machine.modelUuid,
|
||||
() => {
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
handleAction(action, materialId);
|
||||
}
|
||||
)
|
||||
addMachineToMonitor(machine.modelUuid, () => {
|
||||
handleAction(action, materialId);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}, action.actionUuid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -492,23 +434,16 @@ export function useTriggerHandler() {
|
||||
|
||||
// Handle current action from arm bot
|
||||
setIsPaused(materialId, true);
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
handleAction(action, materialId);
|
||||
|
||||
} else {
|
||||
|
||||
// Handle current action using Event Manager
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
setIsPaused(materialId, true);
|
||||
addHumanToMonitor(human.modelUuid,
|
||||
() => {
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
handleAction(action, materialId)
|
||||
}
|
||||
);
|
||||
addHumanToMonitor(human.modelUuid, () => {
|
||||
handleAction(action, materialId)
|
||||
}, action.actionUuid);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -517,9 +452,6 @@ export function useTriggerHandler() {
|
||||
|
||||
// Handle current action from arm bot
|
||||
setIsPaused(materialId, true);
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
handleAction(action, materialId);
|
||||
|
||||
@@ -528,14 +460,9 @@ export function useTriggerHandler() {
|
||||
// Handle current action using Event Manager
|
||||
setIsPaused(materialId, true);
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
addHumanToMonitor(human.modelUuid,
|
||||
() => {
|
||||
if (action.actionType === 'worker') {
|
||||
setIsVisible(materialId, false);
|
||||
}
|
||||
handleAction(action, materialId)
|
||||
}
|
||||
);
|
||||
addHumanToMonitor(human.modelUuid, () => {
|
||||
handleAction(action, materialId)
|
||||
}, action.actionUuid);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -698,27 +625,12 @@ export function useTriggerHandler() {
|
||||
setNextLocation(material.materialId, null);
|
||||
|
||||
if (action && human) {
|
||||
|
||||
if (human.isActive === false && human.state === 'idle') {
|
||||
|
||||
// Handle current action from arm bot
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
addHumanToMonitor(human.modelUuid, () => {
|
||||
setIsVisible(materialId, false);
|
||||
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
|
||||
handleAction(action, materialId);
|
||||
|
||||
} else {
|
||||
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
addHumanToMonitor(human.modelUuid,
|
||||
() => {
|
||||
setIsVisible(materialId, false);
|
||||
|
||||
handleAction(action, materialId);
|
||||
}
|
||||
)
|
||||
}
|
||||
}, action.actionUuid)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -964,8 +876,7 @@ export function useTriggerHandler() {
|
||||
setHumanScheduled(human.modelUuid, true);
|
||||
handleAction(action, materialId)
|
||||
}
|
||||
}
|
||||
);
|
||||
}, action.actionUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1256,11 +1167,11 @@ export function useTriggerHandler() {
|
||||
|
||||
setNextLocation(material.materialId, null);
|
||||
|
||||
if (action) {
|
||||
if (action && action.actionType === 'worker') {
|
||||
|
||||
if (human) {
|
||||
|
||||
if (human.isActive === false && human.state === 'idle' && !human.isScheduled && human.currentLoad < human.point.action.loadCapacity) {
|
||||
if (human.isActive === false && human.state === 'idle' && !human.isScheduled && human.currentLoad < action.loadCapacity) {
|
||||
|
||||
setIsVisible(materialId, false);
|
||||
|
||||
@@ -1506,7 +1417,7 @@ export function useTriggerHandler() {
|
||||
})
|
||||
|
||||
setIsPaused(material.materialId, false);
|
||||
})
|
||||
}, action.actionUuid)
|
||||
} else {
|
||||
setNextLocation(material.materialId, {
|
||||
modelUuid: trigger.triggeredAsset?.triggeredModel.modelUuid || '',
|
||||
|
||||
@@ -180,7 +180,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
|
||||
setCurrentPath(updated);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{selectedPath === "auto" &&
|
||||
|
||||
@@ -11,16 +11,20 @@ import InteractivePoints from '../animator/interactivePoint';
|
||||
import MaterialAnimator from '../animator/materialAnimator';
|
||||
import VehicleAnimator from '../animator/vehicleAnimator';
|
||||
|
||||
import { useHumanEventManager } from '../../../human/eventManager/useHumanEventManager';
|
||||
|
||||
function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) {
|
||||
const { navMesh } = useNavMesh();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { materialStore, armBotStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, productStore } = useSceneContext();
|
||||
const { removeMaterial, setEndTime } = materialStore();
|
||||
const { materialStore, armBotStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, productStore, assetStore } = useSceneContext();
|
||||
const { removeMaterial, setEndTime, setIsVisible } = materialStore();
|
||||
const { getStorageUnitById } = storageUnitStore();
|
||||
const { getHumanById } = humanStore();
|
||||
const { getHumanById, addCurrentAction } = humanStore();
|
||||
const { getArmBotById } = armBotStore();
|
||||
const { getConveyorById } = conveyorStore();
|
||||
const { triggerPointActions } = useTriggerHandler();
|
||||
const { setCurrentAnimation, getAssetById } = assetStore();
|
||||
const { addHumanToMonitor } = useHumanEventManager();
|
||||
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
@@ -96,7 +100,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isPlaying || selectedPath === "auto") {
|
||||
if (isPlaying && selectedPath === "auto") {
|
||||
if (!agvDetail.point.action.unLoadPoint || !agvDetail.point.action.pickUpPoint) return;
|
||||
|
||||
if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') {
|
||||
@@ -223,6 +227,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
if (agvDetail.point.action.triggers.length > 0) {
|
||||
const trigger = getTriggerByUuid(selectedProduct.productUuid, agvDetail.point.action.triggers[0]?.triggerUuid);
|
||||
const model = getEventByModelUuid(selectedProduct.productUuid, trigger?.triggeredAsset?.triggeredModel?.modelUuid || '');
|
||||
const triggeredAction = getActionByUuid(selectedProduct.productUuid, trigger?.triggeredAsset?.triggeredAction?.actionUuid || '');
|
||||
|
||||
if (trigger && model) {
|
||||
if (model.type === 'transfer') {
|
||||
@@ -244,8 +249,8 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
}
|
||||
} else if (model.type === 'human') {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, agvDetail.point.action.actionUuid);
|
||||
if (action) {
|
||||
handleMaterialDropToHuman(model);
|
||||
if (action && (triggeredAction?.actionType === 'assembly' || triggeredAction?.actionType === 'worker')) {
|
||||
handleMaterialDropToHuman(model, triggeredAction);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -260,75 +265,56 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
}
|
||||
}
|
||||
|
||||
function handleMaterialDropToHuman(model: HumanEventSchema) {
|
||||
function handleMaterialDropToHuman(model: HumanEventSchema, action: HumanAction) {
|
||||
|
||||
if (model) {
|
||||
if (model.point.action.actionType === 'worker') {
|
||||
loopMaterialDropToHuman(
|
||||
agvDetail.modelUuid,
|
||||
agvDetail.currentLoad,
|
||||
agvDetail.point.action.unLoadDuration,
|
||||
model.modelUuid,
|
||||
model.point.action.loadCapacity,
|
||||
agvDetail.point.action
|
||||
);
|
||||
if (action.actionType === 'worker') {
|
||||
addHumanToMonitor(model.modelUuid, () => {
|
||||
loopMaterialDropToHuman(
|
||||
agvDetail,
|
||||
model.modelUuid,
|
||||
agvDetail.point.action,
|
||||
action.actionUuid
|
||||
);
|
||||
}, action.actionUuid || '')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loopMaterialDropToHuman(
|
||||
vehicleId: string,
|
||||
vehicleCurrentLoad: number,
|
||||
unLoadDuration: number,
|
||||
vehicle: VehicleStatus,
|
||||
humanId: string,
|
||||
storageMaxCapacity: number,
|
||||
action: VehicleAction
|
||||
vehicleAction: VehicleAction,
|
||||
humanActionId: string
|
||||
) {
|
||||
startTime = performance.now();
|
||||
const fixedInterval = ((unLoadDuration / vehicleCurrentLoad) * (1000 / isSpeedRef.current));
|
||||
let currentVehicleLoad = vehicle.currentLoad;
|
||||
|
||||
const unloadLoop = () => {
|
||||
if (isPausedRef.current) {
|
||||
pauseTimeRef.current ??= performance.now();
|
||||
requestAnimationFrame(unloadLoop);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pauseTimeRef.current) {
|
||||
const pauseDuration = performance.now() - pauseTimeRef.current;
|
||||
startTime += pauseDuration;
|
||||
pauseTimeRef.current = null;
|
||||
}
|
||||
|
||||
const elapsedTime = performance.now() - startTime;
|
||||
const human = getHumanById(humanId);
|
||||
const humanAsset = getAssetById(humanId);
|
||||
const humanAction = human?.point.actions.find((action) => action.actionUuid === humanActionId);
|
||||
|
||||
if (elapsedTime >= fixedInterval) {
|
||||
if (human && agvDetail &&
|
||||
human.currentLoad < storageMaxCapacity &&
|
||||
vehicleCurrentLoad > 0) {
|
||||
if (!human || human.currentAction?.actionUuid !== humanAction?.actionUuid) return;
|
||||
|
||||
decrementVehicleLoad(vehicleId, 1);
|
||||
vehicleCurrentLoad -= 1;
|
||||
|
||||
const material = removeLastMaterial(vehicleId);
|
||||
if (material) {
|
||||
|
||||
triggerPointActions(action, material.materialId);
|
||||
|
||||
}
|
||||
|
||||
if (vehicleCurrentLoad > 0 && human.currentLoad < storageMaxCapacity) {
|
||||
startTime = performance.now();
|
||||
requestAnimationFrame(unloadLoop);
|
||||
}
|
||||
if (humanAsset && human.currentMaterials.length > 0 && humanAsset.animationState?.current === 'pickup' && humanAsset.animationState?.isCompleted) {
|
||||
decrementVehicleLoad(vehicle.modelUuid, 1);
|
||||
currentVehicleLoad -= 1;
|
||||
const material = removeLastMaterial(vehicle.modelUuid);
|
||||
if (material) {
|
||||
setIsVisible(material.materialId, false);
|
||||
}
|
||||
} else {
|
||||
requestAnimationFrame(unloadLoop);
|
||||
} else if (!human.isActive && human.currentLoad < (humanAction?.loadCapacity || 0) && humanAsset?.animationState?.current === 'waiting') {
|
||||
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
|
||||
}
|
||||
setTimeout(() => {
|
||||
requestAnimationFrame(unloadLoop);
|
||||
}, 150)
|
||||
};
|
||||
|
||||
const human = getHumanById(humanId);
|
||||
if (human && vehicleCurrentLoad > 0 && human?.currentLoad < storageMaxCapacity) {
|
||||
const humanAction = human?.point.actions.find((action) => action.actionUuid === humanActionId);
|
||||
if (human && human.currentAction?.actionUuid !== humanActionId && human.currentLoad < (humanAction?.loadCapacity || 0)) {
|
||||
addCurrentAction(humanId, humanActionId);
|
||||
unloadLoop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,32 @@
|
||||
import { useRef } from "react";
|
||||
import { useNavMesh } from "../../../../store/builder/store";
|
||||
import PolygonGenerator from "./polygonGenerator";
|
||||
import NavMeshDetails from "./navMeshDetails";
|
||||
import * as CONSTANTS from "../../../../types/world/worldConstants";
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
import { useLoadingProgress, useNavMesh, useTileDistance } from "../../../../store/builder/store";
|
||||
import useModuleStore from "../../../../store/useModuleStore";
|
||||
import PolygonGenerator from "./polygonGenerator";
|
||||
import NavMeshDetails from "./navMeshDetails";
|
||||
|
||||
function NavMesh() {
|
||||
let groupRef = useRef() as Types.RefGroup;
|
||||
const { setNavMesh } = useNavMesh();
|
||||
const { loadingProgress } = useLoadingProgress();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { planeValue, gridValue } = useTileDistance();
|
||||
|
||||
return (
|
||||
<>
|
||||
<PolygonGenerator groupRef={groupRef} />
|
||||
<NavMeshDetails setNavMesh={setNavMesh} groupRef={groupRef} />
|
||||
{activeModule === 'simulation' && loadingProgress === 0 &&
|
||||
<>
|
||||
<PolygonGenerator groupRef={groupRef} />
|
||||
<NavMeshDetails setNavMesh={setNavMesh} groupRef={groupRef} />
|
||||
|
||||
<group ref={groupRef} visible={false} name="Meshes">
|
||||
<mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} receiveShadow>
|
||||
<planeGeometry args={[300, 300]} />
|
||||
<meshBasicMaterial color={CONSTANTS.planeConfig.color} />
|
||||
</mesh>
|
||||
</group>
|
||||
<group ref={groupRef} visible={false} name="Meshes">
|
||||
<mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} receiveShadow>
|
||||
<planeGeometry args={[planeValue.width, planeValue.height]} />
|
||||
</mesh>
|
||||
</group>
|
||||
</>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect, useMemo } from "react";
|
||||
import * as THREE from "three";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import { generateSoloNavMesh } from "@recast-navigation/generators";
|
||||
import { init as initRecastNavigation } from "@recast-navigation/core";
|
||||
import { DebugDrawer, getPositionsAndIndices } from "@recast-navigation/three";
|
||||
import { useSceneContext } from "../../../scene/sceneContext";
|
||||
import { useToggleView } from "../../../../store/builder/store";
|
||||
|
||||
interface NavMeshDetailsProps {
|
||||
@@ -12,45 +11,48 @@ interface NavMeshDetailsProps {
|
||||
groupRef: React.MutableRefObject<THREE.Group | null>;
|
||||
}
|
||||
|
||||
const NAVMESH_CONFIG = {
|
||||
|
||||
// cellSize: 0.2,
|
||||
// cellHeight: 0.7,
|
||||
// walkableRadius: 0.5,
|
||||
|
||||
cellSize: 0.3,
|
||||
cellHeight: 0.7,
|
||||
walkableRadius: 0.7,
|
||||
};
|
||||
|
||||
export default function NavMeshDetails({
|
||||
setNavMesh,
|
||||
groupRef,
|
||||
}: NavMeshDetailsProps) {
|
||||
const { aisleStore, wallStore } = useSceneContext();
|
||||
const { aisles } = aisleStore();
|
||||
const { scene } = useThree();
|
||||
const { walls } = wallStore();
|
||||
const { toggleView } = useToggleView();
|
||||
|
||||
const meshes = useMemo(() => {
|
||||
return groupRef.current?.children.filter((child): child is THREE.Mesh =>
|
||||
child instanceof THREE.Mesh
|
||||
) || [];
|
||||
}, [groupRef.current?.children]);
|
||||
|
||||
useEffect(() => {
|
||||
if (toggleView) return;
|
||||
if (toggleView || meshes.length === 0) return;
|
||||
|
||||
const initializeNavigation = async () => {
|
||||
try {
|
||||
await initRecastNavigation();
|
||||
|
||||
if (!groupRef.current || groupRef.current.children.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const meshes = groupRef?.current?.children as THREE.Mesh[];
|
||||
const [positions, indices] = getPositionsAndIndices(meshes);
|
||||
|
||||
// const cellSize = 0.2;
|
||||
// const cellHeight = 0.7;
|
||||
// const walkableRadius = 0.5;
|
||||
const { cellSize, cellHeight, walkableRadius } = NAVMESH_CONFIG;
|
||||
|
||||
const cellSize = 0.3;
|
||||
const cellHeight = 0.7;
|
||||
const walkableRadius = 0.7;
|
||||
const { success, navMesh } = generateSoloNavMesh(positions, indices, {
|
||||
cs: cellSize,
|
||||
ch: cellHeight,
|
||||
walkableRadius: Math.round(walkableRadius / cellHeight),
|
||||
});
|
||||
|
||||
if (!success || !navMesh) {
|
||||
return;
|
||||
}
|
||||
if (!success || !navMesh) return;
|
||||
|
||||
setNavMesh(navMesh);
|
||||
|
||||
@@ -62,12 +64,12 @@ export default function NavMeshDetails({
|
||||
debugDrawer.drawNavMesh(navMesh);
|
||||
// scene.add(debugDrawer);
|
||||
} catch (error) {
|
||||
echo.error("Failed to initialize navigation")
|
||||
console.error("Failed to initialize navigation:", error);
|
||||
}
|
||||
};
|
||||
|
||||
initializeNavigation();
|
||||
}, [scene, groupRef, aisles, walls, toggleView]);
|
||||
}, [meshes, setNavMesh, toggleView, scene]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -76,42 +76,18 @@ export default function PolygonGenerator({
|
||||
turf.lineString(line.map((p: any) => p?.position))
|
||||
);
|
||||
|
||||
const validLineFeatures = lineFeatures.map(ls => {
|
||||
const coords = ls.geometry.coordinates.map(coord => coord.join(','));
|
||||
|
||||
if (coords.length < 2) return null;
|
||||
|
||||
const start = coords[0];
|
||||
const end = coords[coords.length - 1];
|
||||
const middle = coords.slice(1, -1);
|
||||
|
||||
const seen = new Set<string>([start, end]);
|
||||
const filteredMiddle: string[] = [];
|
||||
|
||||
for (const point of middle) {
|
||||
if (!seen.has(point)) {
|
||||
seen.add(point);
|
||||
filteredMiddle.push(point);
|
||||
}
|
||||
let validLineFeatures = lineFeatures.filter((line) => {
|
||||
const coords = line.geometry.coordinates;
|
||||
return coords.length >= 2;
|
||||
}).filter((line) => {
|
||||
if (line.geometry.coordinates[0].toString() !== line.geometry.coordinates[1].toString()) {
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
const newCoords = [start, ...filteredMiddle, end];
|
||||
if (validLineFeatures.length < 3) { validLineFeatures = [] }
|
||||
|
||||
if (newCoords.length >= 4) {
|
||||
const resultCoords = newCoords.map(str => str.split(',').map(Number));
|
||||
return {
|
||||
...ls,
|
||||
geometry: {
|
||||
...ls.geometry,
|
||||
coordinates: resultCoords,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}).filter(Boolean);
|
||||
|
||||
const polygons = turf.polygonize(turf.featureCollection(validLineFeatures as any) as any);
|
||||
const polygons = turf.polygonize(turf.featureCollection(validLineFeatures));
|
||||
|
||||
renderWallGeometry(wallPoints);
|
||||
|
||||
|
||||
@@ -4,10 +4,8 @@ import {
|
||||
useSocketStore,
|
||||
useOrganization,
|
||||
useUserName,
|
||||
useWallItems,
|
||||
useSaveVersion,
|
||||
useProjectName,
|
||||
useZones,
|
||||
useActiveTool,
|
||||
} from "../store/builder/store";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
@@ -36,8 +34,6 @@ const Project: React.FC = () => {
|
||||
const { setActiveModule } = useModuleStore();
|
||||
const { setUserName } = useUserName();
|
||||
const { setOrganization } = useOrganization();
|
||||
const { setWallItems } = useWallItems();
|
||||
const { setZones } = useZones();
|
||||
const { isVersionSaved } = useSaveVersion();
|
||||
const { projectId } = useParams();
|
||||
const { setProjectName } = useProjectName();
|
||||
@@ -110,8 +106,6 @@ const Project: React.FC = () => {
|
||||
}, [isVersionSaved]);
|
||||
|
||||
useEffect(() => {
|
||||
setWallItems([]);
|
||||
setZones([]);
|
||||
setActiveModule("builder");
|
||||
if (email) {
|
||||
const token = localStorage.getItem("token");
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as THREE from "three";
|
||||
import { create } from "zustand";
|
||||
import { io } from "socket.io-client";
|
||||
import * as CONSTANTS from "../../types/world/worldConstants";
|
||||
@@ -146,39 +145,11 @@ export const useToggleView = create<any>((set: any) => ({
|
||||
setToggleView: (x: any) => set(() => ({ toggleView: x })),
|
||||
}));
|
||||
|
||||
export const useUpdateScene = create<any>((set: any) => ({
|
||||
updateScene: false,
|
||||
setUpdateScene: (x: any) => set(() => ({ updateScene: x })),
|
||||
}));
|
||||
|
||||
export const useWalls = create<any>((set: any) => ({
|
||||
walls: [],
|
||||
setWalls: (x: any) => set(() => ({ walls: x })),
|
||||
}));
|
||||
|
||||
export const useRoomsState = create<any>((set: any) => ({
|
||||
roomsState: [],
|
||||
setRoomsState: (x: any) => set(() => ({ roomsState: x })),
|
||||
}));
|
||||
|
||||
export const useZones = create<any>((set: any) => ({
|
||||
zones: [],
|
||||
setZones: (callback: any) =>
|
||||
set((state: any) => ({
|
||||
zones: typeof callback === "function" ? callback(state.zones) : callback,
|
||||
})),
|
||||
}));
|
||||
|
||||
interface ZonePointsState {
|
||||
zonePoints: THREE.Vector3[];
|
||||
setZonePoints: (points: THREE.Vector3[]) => void;
|
||||
}
|
||||
|
||||
export const useZonePoints = create<ZonePointsState>((set) => ({
|
||||
zonePoints: [],
|
||||
setZonePoints: (points) => set({ zonePoints: points }),
|
||||
}));
|
||||
|
||||
export const useSelectedItem = create<any>((set: any) => ({
|
||||
selectedItem: {
|
||||
name: "",
|
||||
@@ -215,45 +186,11 @@ export const useMenuVisible = create<any>((set: any) => ({
|
||||
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
|
||||
}));
|
||||
|
||||
// export const useDeleteTool = create<any>((set: any) => ({
|
||||
// deleteTool: false,
|
||||
// setDeleteTool: (x: any) => set(() => ({ deleteTool: x })),
|
||||
// }));
|
||||
|
||||
export const useToolMode = create<any>((set: any) => ({
|
||||
toolMode: null,
|
||||
setToolMode: (x: any) => set(() => ({ toolMode: x })),
|
||||
}));
|
||||
|
||||
export const useNewLines = create<any>((set: any) => ({
|
||||
newLines: [],
|
||||
setNewLines: (x: any) => set(() => ({ newLines: x })),
|
||||
}));
|
||||
|
||||
export const useDeletedLines = create<any>((set: any) => ({
|
||||
deletedLines: [],
|
||||
setDeletedLines: (x: any) => set(() => ({ deletedLines: x })),
|
||||
}));
|
||||
|
||||
export const useMovePoint = create<any>((set: any) => ({
|
||||
movePoint: false,
|
||||
setMovePoint: (x: any) => set(() => ({ movePoint: x })),
|
||||
}));
|
||||
|
||||
// export const useDeletePointOrLine = create<any>((set: any) => ({
|
||||
// deletePointOrLine: false,
|
||||
// setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })),
|
||||
// }));
|
||||
|
||||
export const useWallItems = create<any>((set: any) => ({
|
||||
wallItems: [],
|
||||
setWallItems: (callback: any) =>
|
||||
set((state: any) => ({
|
||||
wallItems:
|
||||
typeof callback === "function" ? callback(state.wallItems) : callback,
|
||||
})),
|
||||
}));
|
||||
|
||||
export const useSelectedWallItem = create<any>((set: any) => ({
|
||||
selectedWallItem: null,
|
||||
setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
|
||||
@@ -315,24 +252,6 @@ export const useActiveLayer = create<any>((set: any) => ({
|
||||
setActiveLayer: (x: any) => set({ activeLayer: x }),
|
||||
}));
|
||||
|
||||
interface RefTextUpdateState {
|
||||
refTextupdate: number;
|
||||
setRefTextUpdate: (
|
||||
callback: (currentValue: number) => number | number
|
||||
) => void;
|
||||
}
|
||||
|
||||
export const useRefTextUpdate = create<RefTextUpdateState>((set) => ({
|
||||
refTextupdate: -1000,
|
||||
setRefTextUpdate: (callback) =>
|
||||
set((state) => ({
|
||||
refTextupdate:
|
||||
typeof callback === "function"
|
||||
? callback(state.refTextupdate)
|
||||
: callback,
|
||||
})),
|
||||
}));
|
||||
|
||||
export const useResetCamera = create<any>((set: any) => ({
|
||||
resetCamera: false,
|
||||
setResetCamera: (x: any) => set({ resetCamera: x }),
|
||||
@@ -353,11 +272,6 @@ export const useActiveSubTool = create<any>((set: any) => ({
|
||||
setActiveSubTool: (x: any) => set({ activeSubTool: x }),
|
||||
}));
|
||||
|
||||
export const use2DUndoRedo = create<any>((set: any) => ({
|
||||
is2DUndoRedo: null,
|
||||
set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }),
|
||||
}));
|
||||
|
||||
export const useElevation = create<any>((set: any) => ({
|
||||
elevation: 45,
|
||||
setElevation: (x: any) => set({ elevation: x }),
|
||||
@@ -434,21 +348,6 @@ export const useDrieUIValue = create<any>((set: any) => ({
|
||||
})),
|
||||
}));
|
||||
|
||||
export const useStartSimulation = create<any>((set: any) => ({
|
||||
startSimulation: false,
|
||||
setStartSimulation: (x: any) => set({ startSimulation: x }),
|
||||
}));
|
||||
|
||||
export const useEyeDropMode = create<any>((set: any) => ({
|
||||
eyeDropMode: false,
|
||||
setEyeDropMode: (x: any) => set({ eyeDropMode: x }),
|
||||
}));
|
||||
|
||||
export const useEditingPoint = create<any>((set: any) => ({
|
||||
editingPoint: false,
|
||||
setEditingPoint: (x: any) => set({ editingPoint: x }),
|
||||
}));
|
||||
|
||||
export const usezoneTarget = create<any>((set: any) => ({
|
||||
zoneTarget: [],
|
||||
setZoneTarget: (x: any) => set({ zoneTarget: x }),
|
||||
|
||||
@@ -12,6 +12,9 @@ interface HumansStore {
|
||||
) => void;
|
||||
clearHumans: () => void;
|
||||
|
||||
addCurrentAction: (modelUuid: string, actionUuid: string) => void;
|
||||
removeCurrentAction: (modelUuid: string) => void;
|
||||
|
||||
setHumanActive: (modelUuid: string, isActive: boolean) => void;
|
||||
setHumanScheduled: (modelUuid: string, isPicking: boolean) => void;
|
||||
setHumanLoad: (modelUuid: string, load: number) => void;
|
||||
@@ -22,6 +25,11 @@ interface HumansStore {
|
||||
incrementHumanLoad: (modelUuid: string, incrementBy: number) => void;
|
||||
decrementHumanLoad: (modelUuid: string, decrementBy: number) => void;
|
||||
|
||||
incrementLoadCount: (modelUuid: string, incrementBy: number) => void;
|
||||
decrementLoadCount: (modelUuid: string, decrementBy: number) => void;
|
||||
|
||||
clearLoadCount: (modelUuid: string) => void;
|
||||
|
||||
addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void;
|
||||
setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string }[]) => void;
|
||||
removeLastMaterial: (modelUuid: string) => { materialType: string; materialId: string } | undefined;
|
||||
@@ -54,6 +62,7 @@ export const createHumanStore = () => {
|
||||
isScheduled: false,
|
||||
idleTime: 0,
|
||||
activeTime: 0,
|
||||
totalLoadCount: 0,
|
||||
currentLoad: 0,
|
||||
currentMaterials: [],
|
||||
distanceTraveled: 0
|
||||
@@ -83,6 +92,30 @@ export const createHumanStore = () => {
|
||||
});
|
||||
},
|
||||
|
||||
addCurrentAction: (modelUuid, actionUuid) => {
|
||||
set((state) => {
|
||||
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||
if (human) {
|
||||
const action = human.point.actions.find(h => h.actionUuid === actionUuid);
|
||||
if (action) {
|
||||
human.currentAction = {
|
||||
actionUuid: action.actionUuid,
|
||||
actionName: action.actionName
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeCurrentAction: (modelUuid) => {
|
||||
set((state) => {
|
||||
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||
if (human) {
|
||||
human.currentAction = undefined;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setHumanActive: (modelUuid, isActive) => {
|
||||
set((state) => {
|
||||
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||
@@ -137,6 +170,33 @@ export const createHumanStore = () => {
|
||||
});
|
||||
},
|
||||
|
||||
incrementLoadCount: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||
if (human) {
|
||||
human.totalLoadCount += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
decrementLoadCount: (modelUuid, decrementBy) => {
|
||||
set((state) => {
|
||||
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||
if (human) {
|
||||
human.totalLoadCount -= decrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
clearLoadCount: (modelUuid) => {
|
||||
set((state) => {
|
||||
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||
if (human) {
|
||||
human.totalLoadCount = 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addCurrentMaterial: (modelUuid, materialType, materialId) => {
|
||||
set((state) => {
|
||||
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||
|
||||
@@ -36,6 +36,8 @@ type MaterialsStore = {
|
||||
} | null
|
||||
) => MaterialSchema | undefined;
|
||||
|
||||
clearLocations: (materialId: string) => void;
|
||||
|
||||
setMaterial: (materialId: string, materialType: string) => MaterialSchema | undefined;
|
||||
setStartTime: (materialId: string, startTime: number) => MaterialSchema | undefined;
|
||||
setEndTime: (materialId: string, endTime: number) => MaterialSchema | undefined;
|
||||
@@ -140,6 +142,18 @@ export const createMaterialStore = () => {
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
clearLocations: (materialId) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
delete material.previous;
|
||||
delete material.next;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
}
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
setMaterial: (materialId, materialType) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
|
||||
@@ -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['action']
|
||||
action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]
|
||||
) => 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['action']>
|
||||
updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]>
|
||||
) => EventsSchema | undefined;
|
||||
|
||||
// Trigger-level actionss
|
||||
@@ -66,8 +66,8 @@ type ProductsStore = {
|
||||
getEventByTriggerUuid: (productUuid: string, triggerUuid: string) => EventsSchema | undefined;
|
||||
getEventByPointUuid: (productUuid: string, pointUuid: string) => EventsSchema | undefined;
|
||||
getPointByUuid: (productUuid: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema | undefined;
|
||||
getActionByUuid: (productUuid: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['action']) | undefined;
|
||||
getActionByPointUuid: (productUuid: string, pointUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['action']) | undefined;
|
||||
getActionByUuid: (productUuid: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]) | undefined;
|
||||
getActionByPointUuid: (productUuid: string, pointUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]) | undefined;
|
||||
getModelUuidByPointUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
||||
getModelUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
||||
getPointUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
||||
|
||||
9
app/src/types/simulationTypes.d.ts
vendored
9
app/src/types/simulationTypes.d.ts
vendored
@@ -73,11 +73,12 @@ interface HumanAction {
|
||||
actionUuid: string;
|
||||
actionName: string;
|
||||
actionType: "worker" | "assembly";
|
||||
processTime?: number;
|
||||
processTime: number;
|
||||
swapMaterial?: string;
|
||||
assemblyPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; }
|
||||
pickUpPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; }
|
||||
dropPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; }
|
||||
loadCount: number;
|
||||
loadCapacity: number;
|
||||
triggers: TriggerSchema[];
|
||||
}
|
||||
@@ -124,7 +125,7 @@ interface HumanPointSchema {
|
||||
uuid: string;
|
||||
position: [number, number, number];
|
||||
rotation: [number, number, number];
|
||||
action: HumanAction;
|
||||
actions: HumanAction[];
|
||||
}
|
||||
|
||||
type PointsScheme = | ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema;
|
||||
@@ -227,15 +228,13 @@ interface HumanStatus extends HumanEventSchema {
|
||||
isScheduled: boolean;
|
||||
idleTime: number;
|
||||
activeTime: number;
|
||||
totalLoadCount: number;
|
||||
currentLoad: number;
|
||||
currentMaterials: { materialType: string; materialId: string; }[];
|
||||
distanceTraveled: number;
|
||||
currentAction?: {
|
||||
actionUuid: string;
|
||||
actionName: string;
|
||||
animationUuid: string;
|
||||
materialType?: string | null;
|
||||
materialId?: string | null;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user