integerated product context to scene context

This commit is contained in:
2025-09-05 15:54:38 +05:30
parent 9904a5079d
commit 23570d7007
67 changed files with 2573 additions and 4197 deletions

View File

@@ -1,5 +1,4 @@
import { useParams } from "react-router-dom";
import { useProductContext } from "../../../modules/simulation/products/productContext";
import { useCompareProductDataStore, useLoadingProgress, useSaveVersion } from "../../../store/builder/store";
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
@@ -16,17 +15,15 @@ function ComparisonScene() {
const { isPlaying } = usePlayButtonStore();
const { productStore, versionStore } = useSceneContext();
const { versionHistory, selectedVersion, setSelectedVersion, setVersions } = versionStore();
const { products } = productStore();
const { products, selectedProduct } = productStore();
const { isVersionSaved } = useSaveVersion();
const { activeModule } = useModuleStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { comparisonProduct, setComparisonProduct } = useComparisonProduct();
const { mainProduct } = useMainProduct();
const { loadingProgress } = useLoadingProgress();
const { compareProductsData } = useCompareProductDataStore();
const [shouldShowComparisonResult, setShouldShowComparisonResult] = useState(false);
const { projectId } = useParams()
const { projectId } = useParams();
const handleSelectVersion = (option: string) => {
const version = versionHistory.find((version) => version.versionName === option);

View File

@@ -1,4 +1,5 @@
import { useEffect } from "react";
import { useParams } from "react-router-dom";
import { useLoadingProgress, useRenameModeStore, useSaveVersion, useSelectedComment, useSocketStore, useWidgetSubOption } from "../../../store/builder/store";
import useModuleStore, { useThreeDStore } from "../../../store/ui/useModuleStore";
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
@@ -7,11 +8,8 @@ import { useFloatingWidget } from "../../../store/visualization/useDroppedObject
import { useSelectedUserStore } from "../../../store/collaboration/useCollabStore";
import { createHandleDrop } from "../../../modules/visualization/functions/handleUiDrop";
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
import { useProductContext } from "../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../modules/scene/sceneContext";
import { useBuilderStore } from "../../../store/builder/useBuilderStore";
import { getUserData } from "../../../functions/getUserData";
import useRestStates from "../../../hooks/useResetStates";
import KeyPressListener from "../../../utils/shortcutkeys/handleShortcutKeys";
import LoadingPage from "../../templates/LoadingPage";
@@ -31,14 +29,13 @@ import Footer from "../../footer/Footer";
import ThreadChat from "../../ui/collaboration/ThreadChat";
import Scene from "../../../modules/scene/scene";
import { getUserData } from "../../../functions/getUserData";
import { recentlyViewed } from "../../../services/dashboard/recentlyViewed";
import { setAssetsApi } from "../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi";
function MainScene() {
const { setMainProduct } = useMainProduct();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { isVersionSaved, setIsVersionSaved } = useSaveVersion();
const { activeModule } = useModuleStore();
const { selectedUser } = useSelectedUserStore();
@@ -52,7 +49,7 @@ function MainScene() {
const { clearComparisonProduct } = useComparisonProduct();
const { selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
const { assetStore, productStore, versionStore } = useSceneContext();
const { products } = productStore();
const { products, selectedProduct } = productStore();
const { versionHistory, setVersions, selectedVersion, setSelectedVersion } = versionStore();
const { setName, selectedAssets, setSelectedAssets } = assetStore();
const { projectId } = useParams();

View File

@@ -1,8 +1,5 @@
import React, { useEffect, useState } from "react";
import {
useSelectedEventData,
useSelectedEventSphere,
} from "../../../../../store/simulation/useSimulationStore";
import { useSelectedEventData, useSelectedEventSphere } from "../../../../../store/simulation/useSimulationStore";
import ConveyorMechanics from "./mechanics/conveyorMechanics";
import VehicleMechanics from "./mechanics/vehicleMechanics";
import RoboticArmMechanics from "./mechanics/roboticArmMechanics";
@@ -11,19 +8,16 @@ import StorageMechanics from "./mechanics/storageMechanics";
import HumanMechanics from "./mechanics/humanMechanics";
import { AddIcon } from "../../../../icons/ExportCommonIcons";
import { handleAddEventToProduct } from "../../../../../modules/simulation/events/points/functions/handleAddEventToProduct";
import { useProductContext } from "../../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../../modules/scene/sceneContext";
import CraneMechanics from "./mechanics/craneMechanics";
const EventProperties: React.FC = () => {
const { selectedEventData } = useSelectedEventData();
const { selectedProductStore } = useProductContext();
const { eventStore, productStore, versionStore } = useSceneContext();
const { selectedProduct } = selectedProductStore();
const [currentEventData, setCurrentEventData] = useState<EventsSchema | null>(null);
const [assetType, setAssetType] = useState<string | null>(null);
const { products, addEvent, getEventByModelUuid } = productStore();
const { products, addEvent, getEventByModelUuid, selectedProduct } = productStore();
const { selectedEventSphere } = useSelectedEventSphere();
const { selectedVersion } = versionStore();
const { projectId } = useParams();
@@ -39,12 +33,7 @@ const EventProperties: React.FC = () => {
const getCurrentEventData = () => {
if (!selectedEventData?.data || !selectedProduct) return null;
return (
getEventByModelUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid
) ?? null
);
return getEventByModelUuid(selectedProduct.productUuid, selectedEventData.data.modelUuid) ?? null;
};
const determineAssetType = (event: EventsSchema | null) => {
@@ -75,9 +64,7 @@ const EventProperties: React.FC = () => {
{currentEventData && (
<>
<div className="header">
<div className="header-value">
{selectedEventData?.data.modelName}
</div>
<div className="header-value">{selectedEventData?.data.modelName}</div>
</div>
{assetType === "conveyor" && <ConveyorMechanics />}
{assetType === "vehicle" && <VehicleMechanics />}
@@ -91,9 +78,7 @@ const EventProperties: React.FC = () => {
{!currentEventData && selectedEventSphere && (
<div className="no-event-selected">
<p>
<strong>Oops!</strong> It looks like this object doesn't have an
event assigned yet. To continue, please link it to one of the
products below.
<strong>Oops!</strong> It looks like this object doesn't have an event assigned yet. To continue, please link it to one of the products below.
</p>
<div className="products-list">
@@ -108,15 +93,11 @@ const EventProperties: React.FC = () => {
onClick={() => {
if (selectedEventData) {
handleAddEventToProduct({
event: eventStore
.getState()
.getEventByModelUuid(
selectedEventData?.data.modelUuid
),
event: eventStore.getState().getEventByModelUuid(selectedEventData?.data.modelUuid),
addEvent,
selectedProduct,
projectId: projectId || '',
versionId: selectedVersion?.versionId || '',
projectId: projectId || "",
versionId: selectedVersion?.versionId || "",
});
}
}}
@@ -132,8 +113,7 @@ const EventProperties: React.FC = () => {
{!selectedEventSphere && (
<div className="no-event-selected">
<p>
<strong>Oops!</strong> It looks like you haven't selected an event
point yet. Please select an event to view its properties.
<strong>Oops!</strong> It looks like you haven't selected an event point yet. Please select an event to view its properties.
</p>
</div>
)}

View File

@@ -1,16 +1,9 @@
import React, { useRef } from "react";
import {
AddIcon,
RemoveIcon,
ResizeHeightIcon,
} from "../../../../../icons/ExportCommonIcons";
import { AddIcon, RemoveIcon, ResizeHeightIcon } from "../../../../../icons/ExportCommonIcons";
import RenameInput from "../../../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../../../functions/handleResizePannel";
import {
useSelectedAction,
} from "../../../../../../store/simulation/useSimulationStore";
import { useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
@@ -21,31 +14,20 @@ interface ActionsListProps {
handleDeleteAction?: (actionUuid: string) => void;
}
const ActionsList: React.FC<ActionsListProps> = ({
selectedPointData,
multipleAction = false,
handleAddAction,
handleDeleteAction,
}) => {
const ActionsList: React.FC<ActionsListProps> = ({ selectedPointData, multipleAction = false, handleAddAction, handleDeleteAction }) => {
const actionsContainerRef = useRef<HTMLDivElement>(null);
// store
const { productStore, versionStore } = useSceneContext();
const { renameAction } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { renameAction, selectedProduct } = productStore();
const { selectedAction, setSelectedAction } = useSelectedAction();
const { selectedVersion } = versionStore();
const { projectId } = useParams();
const handleRenameAction = (newName: string) => {
if (!selectedAction.actionId) return;
const event = renameAction(
selectedProduct.productUuid,
selectedAction.actionId,
newName
);
const event = renameAction(selectedProduct.productUuid, selectedAction.actionId, newName);
setSelectedAction(selectedAction.actionId, newName);
if (event) {
upsertProductOrEventApi({
@@ -53,7 +35,7 @@ const ActionsList: React.FC<ActionsListProps> = ({
productUuid: selectedProduct.productUuid,
projectId,
eventDatas: event,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
});
}
};
@@ -81,32 +63,13 @@ const ActionsList: React.FC<ActionsListProps> = ({
<AddIcon /> Add
</button>
</div>
<div
className="lists-main-container"
ref={actionsContainerRef}
style={{ height: "120px" }}
>
<div className="lists-main-container" ref={actionsContainerRef} style={{ height: "120px" }}>
<div className="list-container">
{multipleAction &&
selectedPointData?.actions?.map((action: any) => (
<div
key={action.actionUuid}
className={`list-item ${selectedAction.actionId === action.actionUuid
? "active"
: ""
}`}
>
<button
id="action-button"
className="value"
onClick={() =>
handleActionSelect(action.actionUuid, action.actionName)
}
>
<RenameInput
value={action.actionName}
onRename={(value) => handleRenameAction(value)}
/>
<div key={action.actionUuid} className={`list-item ${selectedAction.actionId === action.actionUuid ? "active" : ""}`}>
<button id="action-button" className="value" onClick={() => handleActionSelect(action.actionUuid, action.actionName)}>
<RenameInput value={action.actionName} onRename={(value) => handleRenameAction(value)} />
</button>
{selectedPointData?.actions?.length > 1 && (
<button
@@ -124,34 +87,15 @@ const ActionsList: React.FC<ActionsListProps> = ({
</div>
))}
{!multipleAction && selectedPointData?.action && (
<div
key={selectedPointData.action.actionUuid}
className={`list-item active`}
>
<button
id="action-button"
className="value"
onClick={() =>
handleActionSelect(
selectedPointData.action.actionUuid,
selectedPointData.action.actionName
)
}
>
<RenameInput
value={selectedPointData.action.actionName}
onRename={handleRenameAction}
/>
<div key={selectedPointData.action.actionUuid} className={`list-item active`}>
<button id="action-button" className="value" onClick={() => handleActionSelect(selectedPointData.action.actionUuid, selectedPointData.action.actionName)}>
<RenameInput value={selectedPointData.action.actionName} onRename={handleRenameAction} />
</button>
</div>
)}
</div>
{multipleAction && (
<button
className="resize-icon"
id="action-resize"
onMouseDown={(e: any) => handleResize(e, actionsContainerRef)}
>
<button className="resize-icon" id="action-resize" onMouseDown={(e: any) => handleResize(e, actionsContainerRef)}>
<ResizeHeightIcon />
</button>
)}

View File

@@ -11,7 +11,6 @@ import Trigger from "../trigger/Trigger";
import { useSelectedAction, useSelectedEventData } from "../../../../../../store/simulation/useSimulationStore";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
@@ -27,25 +26,16 @@ function ConveyorMechanics() {
const { selectedEventData } = useSelectedEventData();
const { productStore, versionStore } = useSceneContext();
const { getPointByUuid, updateEvent, updateAction, getEventByModelUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getPointByUuid, updateEvent, updateAction, getEventByModelUuid, selectedProduct } = productStore();
const { setSelectedAction, clearSelectedAction } = useSelectedAction();
const { selectedVersion } = versionStore();
const { projectId } = useParams();
useEffect(() => {
if (selectedEventData) {
const point = getPointByUuid(
selectedProduct.productUuid,
selectedEventData?.data.modelUuid,
selectedEventData?.selectedPoint
) as ConveyorPointSchema | undefined;
const point = getPointByUuid(selectedProduct.productUuid, selectedEventData?.data.modelUuid, selectedEventData?.selectedPoint) as ConveyorPointSchema | undefined;
const event = getEventByModelUuid(
selectedProduct.productUuid,
selectedEventData?.data.modelUuid
) as ConveyorEventSchema | undefined;
const event = getEventByModelUuid(selectedProduct.productUuid, selectedEventData?.data.modelUuid) as ConveyorEventSchema | undefined;
if (point && "action" in point && event) {
setSelectedPointData(point);
@@ -63,12 +53,7 @@ function ConveyorMechanics() {
}
}, [selectedProduct, selectedEventData]);
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName,
productUuid,
@@ -84,19 +69,10 @@ function ConveyorMechanics() {
const numericValue = parseFloat(value);
if (isNaN(numericValue)) return;
const event = updateEvent(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
{ speed: numericValue }
);
const event = updateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, { speed: numericValue });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSpeed(value);
};
@@ -107,19 +83,10 @@ function ConveyorMechanics() {
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(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -130,19 +97,10 @@ function ConveyorMechanics() {
if (isNaN(numericValue)) return;
setSpawnCount(value);
const event = updateAction(
selectedProduct.productUuid,
selectedPointData.action.actionUuid,
{ spawnCount: numericValue }
);
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { spawnCount: numericValue });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -153,19 +111,10 @@ function ConveyorMechanics() {
if (isNaN(numericValue)) return;
setSpawnInterval(value);
const event = updateAction(
selectedProduct.productUuid,
selectedPointData.action.actionUuid,
{ spawnInterval: numericValue }
);
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { spawnInterval: numericValue });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -173,19 +122,10 @@ function ConveyorMechanics() {
if (!selectedPointData) return;
setMaterial(selectedMaterial);
const event = updateAction(
selectedProduct.productUuid,
selectedPointData.action.actionUuid,
{ material: selectedMaterial }
);
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { material: selectedMaterial });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -196,19 +136,10 @@ function ConveyorMechanics() {
if (isNaN(numericValue)) return;
setDelay(value);
const event = updateAction(
selectedProduct.productUuid,
selectedPointData.action.actionUuid,
{ delay: numericValue }
);
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { delay: numericValue });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -222,17 +153,7 @@ function ConveyorMechanics() {
<div key={selectedPointData?.uuid} className="global-props section">
<div className="property-list-container">
<div className="property-item">
<InputWithDropDown
label="Speed"
value={speed}
min={0}
step={0.1}
defaultValue="0.5"
max={10}
activeOption="m/s"
onClick={() => { }}
onChange={handleSpeedChange}
/>
<InputWithDropDown label="Speed" value={speed} min={0} step={0.1} defaultValue="0.5" max={10} activeOption="m/s" onClick={() => {}} onChange={handleSpeedChange} />
</div>
</div>
</div>
@@ -241,56 +162,19 @@ function ConveyorMechanics() {
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput
value={actionName}
canEdit={false}
/>
<RenameInput value={actionName} canEdit={false} />
</div>
<div className="selected-actions-list">
<LabledDropdown
defaultOption={activeOption}
options={availableActions.options}
onSelect={handleActionTypeChange}
/>
<LabledDropdown defaultOption={activeOption} options={availableActions.options} onSelect={handleActionTypeChange} />
{activeOption === "default" && <DefaultAction />}
{activeOption === "spawn" && (
<SpawnAction
onChangeCount={handleSpawnCountChange}
options={["Default material", "Material 1", "Material 2", "Material 3"]}
defaultOption={material}
onSelect={handleMaterialSelect}
onChangeInterval={handleSpawnIntervalChange}
intervalValue={spawnInterval}
countValue={spawnCount}
intervalMin={1}
intervalMax={60}
intervalDefaultValue="1"
countMin={1}
countMax={100}
countDefaultValue="1"
/>
)}
{activeOption === "swap" && (
<SwapAction
options={["Default material", "Material 1", "Material 2", "Material 3"]}
defaultOption={material}
onSelect={handleMaterialSelect}
/>
)}
{activeOption === "spawn" && <SpawnAction onChangeCount={handleSpawnCountChange} options={["Default material", "Material 1", "Material 2", "Material 3"]} defaultOption={material} onSelect={handleMaterialSelect} onChangeInterval={handleSpawnIntervalChange} intervalValue={spawnInterval} countValue={spawnCount} intervalMin={1} intervalMax={60} intervalDefaultValue="1" countMin={1} countMax={100} countDefaultValue="1" />}
{activeOption === "swap" && <SwapAction options={["Default material", "Material 1", "Material 2", "Material 3"]} defaultOption={material} onSelect={handleMaterialSelect} />}
{activeOption === "despawn" && <DespawnAction />}
{activeOption === "delay" && (
<DelayAction
value={delay}
defaultValue="0"
min={0}
max={60}
onChange={handleDelayChange}
/>
)}
{activeOption === "delay" && <DelayAction value={delay} defaultValue="0" min={0} max={60} onChange={handleDelayChange} />}
</div>
</div>
<div className="tirgger">
<Trigger selectedPointData={selectedPointData as any} type={'Conveyor'} />
<Trigger selectedPointData={selectedPointData as any} type={"Conveyor"} />
</div>
</section>
</>

View File

@@ -6,7 +6,6 @@ import Trigger from "../trigger/Trigger";
import { useSelectedEventData, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
@@ -16,20 +15,14 @@ function CraneMechanics() {
const { selectedEventData } = useSelectedEventData();
const { productStore, versionStore } = useSceneContext();
const { getPointByUuid, addAction, removeAction } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getPointByUuid, addAction, removeAction, selectedProduct } = productStore();
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
const { selectedVersion } = versionStore();
const { projectId } = useParams();
useEffect(() => {
if (selectedEventData) {
const point = getPointByUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint
) as CranePointSchema | undefined;
const point = getPointByUuid(selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint) as CranePointSchema | undefined;
if (point?.actions) {
setSelectedPointData(point);
@@ -45,12 +38,7 @@ function CraneMechanics() {
}
}, [selectedEventData, selectedProduct]);
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName,
productUuid,
@@ -71,20 +59,10 @@ function CraneMechanics() {
triggers: [] as TriggerSchema[],
};
const event = addAction(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint,
newAction
);
const event = addAction(selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint, newAction);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSelectedPointData({
@@ -97,22 +75,14 @@ function CraneMechanics() {
const handleDeleteAction = (actionUuid: string) => {
if (!selectedPointData) return;
const event = removeAction(
selectedProduct.productUuid,
actionUuid
);
const event = removeAction(selectedProduct.productUuid, actionUuid);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
const index = selectedPointData.actions.findIndex(a => a.actionUuid === actionUuid);
const newActions = selectedPointData.actions.filter(a => a.actionUuid !== actionUuid);
const index = selectedPointData.actions.findIndex((a) => a.actionUuid === actionUuid);
const newActions = selectedPointData.actions.filter((a) => a.actionUuid !== actionUuid);
setSelectedPointData({
...selectedPointData,
@@ -134,39 +104,23 @@ function CraneMechanics() {
options: ["pickAndDrop"],
};
const currentAction = selectedPointData?.actions.find(a => a.actionUuid === selectedAction.actionId);
const currentAction = selectedPointData?.actions.find((a) => a.actionUuid === selectedAction.actionId);
return (
<>
<section>
<ActionsList
selectedPointData={selectedPointData}
multipleAction
handleAddAction={handleAddAction}
handleDeleteAction={handleDeleteAction}
/>
<ActionsList selectedPointData={selectedPointData} multipleAction handleAddAction={handleAddAction} handleDeleteAction={handleDeleteAction} />
{selectedAction.actionId && currentAction && (
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput
value={selectedAction.actionName || ""}
canEdit={false}
/>
<RenameInput value={selectedAction.actionName || ""} canEdit={false} />
</div>
<div className="selected-actions-list">
<LabledDropdown
defaultOption={activeOption}
options={availableActions.options}
onSelect={() => { }}
disabled={true}
/>
<LabledDropdown defaultOption={activeOption} options={availableActions.options} onSelect={() => {}} disabled={true} />
</div>
<div className="tirgger">
<Trigger
selectedPointData={selectedPointData as any}
type={"RoboticArm"}
/>
<Trigger selectedPointData={selectedPointData as any} type={"RoboticArm"} />
</div>
</div>
)}
@@ -175,4 +129,4 @@ function CraneMechanics() {
);
}
export default CraneMechanics
export default CraneMechanics;

View File

@@ -11,7 +11,6 @@ import ManufactureAction from "../actions/ManufactureAction";
import { useSelectedEventData, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
import { useParams } from "react-router-dom";
@@ -27,32 +26,21 @@ function HumanMechanics() {
const [selectedPointData, setSelectedPointData] = useState<HumanPointSchema | undefined>();
const { selectedEventData } = useSelectedEventData();
const { productStore, versionStore } = useSceneContext();
const { getPointByUuid, updateEvent, updateAction, addAction, removeAction, getEventByModelUuid, getActionByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getPointByUuid, updateEvent, updateAction, addAction, removeAction, getEventByModelUuid, getActionByUuid, selectedProduct } = productStore();
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
const { selectedVersion } = versionStore();
const { projectId } = useParams();
useEffect(() => {
if (selectedEventData && selectedEventData.data.type === "human") {
const point = getPointByUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint
) as HumanPointSchema | undefined;
const point = getPointByUuid(selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint) as HumanPointSchema | undefined;
if (point?.actions?.length) {
setSelectedPointData(point);
const firstAction = point.actions[0];
setSelectedAction(firstAction.actionUuid, firstAction.actionName);
setCurrentAction(firstAction);
setSpeed((
getEventByModelUuid(
selectedProduct.productUuid,
selectedEventData?.data.modelUuid || ""
) as HumanEventSchema | undefined
)?.speed?.toString() || "1");
setSpeed((getEventByModelUuid(selectedProduct.productUuid, selectedEventData?.data.modelUuid || "") as HumanEventSchema | undefined)?.speed?.toString() || "1");
setLoadCapacity(firstAction.loadCapacity.toString());
setActiveOption(firstAction.actionType);
setLoadCount(firstAction.loadCount || 0);
@@ -67,17 +55,13 @@ function HumanMechanics() {
useEffect(() => {
if (selectedEventData && selectedEventData.data.type === "human") {
const point = getPointByUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint
) as HumanPointSchema | undefined;
const point = getPointByUuid(selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint) as HumanPointSchema | undefined;
const actionUuid = selectedAction.actionId || point?.actions[0].actionUuid || '';
const actionUuid = selectedAction.actionId || point?.actions[0].actionUuid || "";
const newCurrentAction = getActionByUuid(selectedProduct.productUuid, actionUuid);
if (newCurrentAction && (newCurrentAction.actionType === 'manufacturer' || newCurrentAction?.actionType === 'worker' || newCurrentAction?.actionType === "operator")) {
if (newCurrentAction && (newCurrentAction.actionType === "manufacturer" || newCurrentAction?.actionType === "worker" || newCurrentAction?.actionType === "operator")) {
if (!selectedAction.actionId) {
setSelectedAction(newCurrentAction.actionUuid, newCurrentAction.actionName);
}
@@ -87,7 +71,7 @@ function HumanMechanics() {
setLoadCount(newCurrentAction.loadCount || 0);
setManufactureCount(newCurrentAction.manufactureCount || 0);
if (newCurrentAction.actionType === 'manufacturer') {
if (newCurrentAction.actionType === "manufacturer") {
setProcessTime(newCurrentAction.processTime || 10);
setSwappedMaterial(newCurrentAction.swapMaterial || "Default material");
}
@@ -98,12 +82,7 @@ function HumanMechanics() {
}
}, [selectedAction, selectedProduct, selectedEventData]);
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName,
productUuid,
@@ -117,17 +96,13 @@ function HumanMechanics() {
if (!selectedAction.actionId || !currentAction || !selectedPointData) return;
const updatedAction = { ...currentAction, actionType: actionType as "worker" | "manufacturer" | "operator" | "assembler" };
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
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
);
const event = updateAction(selectedProduct.productUuid, selectedAction.actionId, updatedAction);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setCurrentAction(updatedAction);
@@ -141,17 +116,13 @@ function HumanMechanics() {
if (isNaN(numericValue)) return;
const updatedEvent = {
speed: numericValue
speed: numericValue,
} as HumanEventSchema;
const event = updateEvent(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
updatedEvent
);
const event = updateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, updatedEvent);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSpeed(value);
@@ -161,17 +132,13 @@ function HumanMechanics() {
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
const updatedAction = { ...currentAction, loadCapacity: parseInt(value) };
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
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
);
const event = updateAction(selectedProduct.productUuid, selectedAction.actionId, updatedAction);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setCurrentAction(updatedAction);
@@ -183,17 +150,13 @@ function HumanMechanics() {
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
const updatedAction = { ...currentAction, loadCount: value };
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
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
);
const event = updateAction(selectedProduct.productUuid, selectedAction.actionId, updatedAction);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setCurrentAction(updatedAction);
@@ -205,17 +168,13 @@ function HumanMechanics() {
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
const updatedAction = { ...currentAction, manufactureCount: value };
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
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
);
const event = updateAction(selectedProduct.productUuid, selectedAction.actionId, updatedAction);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setCurrentAction(updatedAction);
@@ -227,17 +186,13 @@ function HumanMechanics() {
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
const updatedAction = { ...currentAction, processTime: value };
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
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
);
const event = updateAction(selectedProduct.productUuid, selectedAction.actionId, updatedAction);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setCurrentAction(updatedAction);
@@ -249,17 +204,13 @@ function HumanMechanics() {
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
const updatedAction = { ...currentAction, swapMaterial: value };
const updatedActions = selectedPointData.actions.map(action => action.actionUuid === updatedAction.actionUuid ? updatedAction : action);
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
);
const event = updateAction(selectedProduct.productUuid, selectedAction.actionId, updatedAction);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setCurrentAction(updatedAction);
@@ -272,24 +223,20 @@ function HumanMechanics() {
const updatedAction: HumanAction = JSON.parse(JSON.stringify(currentAction));
if (updatedAction.actionType === 'manufacturer') {
updatedAction.manufacturePoint = { position: null, rotation: null, }
if (updatedAction.actionType === "manufacturer") {
updatedAction.manufacturePoint = { position: null, rotation: null };
} else {
updatedAction.pickUpPoint = { position: null, rotation: null, };
updatedAction.dropPoint = { position: null, rotation: null, }
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 updatedActions = selectedPointData.actions.map((action) => (action.actionUuid === updatedAction.actionUuid ? updatedAction : action));
const updatedPoint = { ...selectedPointData, actions: updatedActions };
const event = updateAction(
selectedProduct.productUuid,
selectedAction.actionId,
updatedAction
);
const event = updateAction(selectedProduct.productUuid, selectedAction.actionId, updatedAction);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setCurrentAction(updatedAction);
@@ -306,8 +253,8 @@ function HumanMechanics() {
loadCount: 1,
assemblyCount: 1,
assemblyCondition: {
conditionType: 'material',
materialType: "Default material"
conditionType: "material",
materialType: "Default material",
},
manufactureCount: 1,
loadCapacity: 1,
@@ -318,15 +265,10 @@ function HumanMechanics() {
const updatedActions = [...(selectedPointData.actions || []), newAction];
const updatedPoint = { ...selectedPointData, actions: updatedActions };
const event = addAction(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint,
newAction
);
const event = addAction(selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint, newAction);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSelectedPointData(updatedPoint);
@@ -336,16 +278,13 @@ function HumanMechanics() {
const handleDeleteAction = (actionUuid: string) => {
if (!selectedPointData || !actionUuid) return;
const updatedActions = selectedPointData.actions.filter(action => action.actionUuid !== actionUuid);
const updatedActions = selectedPointData.actions.filter((action) => action.actionUuid !== actionUuid);
const updatedPoint = { ...selectedPointData, actions: updatedActions };
const event = removeAction(
selectedProduct.productUuid,
actionUuid
);
const event = removeAction(selectedProduct.productUuid, actionUuid);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSelectedPointData(updatedPoint);
@@ -369,27 +308,12 @@ function HumanMechanics() {
<div className="global-props section">
<div className="property-list-container">
<div className="property-item">
<InputWithDropDown
label="Speed"
value={speed}
min={0}
step={0.1}
defaultValue="0.5"
max={10}
activeOption="m/s"
onClick={() => { }}
onChange={handleSpeedChange}
/>
<InputWithDropDown label="Speed" value={speed} min={0} step={0.1} defaultValue="0.5" max={10} activeOption="m/s" onClick={() => {}} onChange={handleSpeedChange} />
</div>
</div>
</div>
<section>
<ActionsList
selectedPointData={selectedPointData}
multipleAction={true}
handleAddAction={handleAddAction}
handleDeleteAction={handleDeleteAction}
/>
<ActionsList selectedPointData={selectedPointData} multipleAction={true} handleAddAction={handleAddAction} handleDeleteAction={handleDeleteAction} />
{selectedAction.actionId && currentAction && (
<div className="selected-actions-details">
@@ -397,15 +321,9 @@ function HumanMechanics() {
<RenameInput value={selectedAction.actionName || ""} canEdit={false} />
</div>
<div className="selected-actions-list">
<LabledDropdown
label="Action Type"
defaultOption={activeOption}
options={["worker", "manufacturer", "operator"]}
onSelect={handleSelectActionType}
disabled={false}
/>
<LabledDropdown label="Action Type" defaultOption={activeOption} options={["worker", "manufacturer", "operator"]} onSelect={handleSelectActionType} disabled={false} />
</div>
{(currentAction.actionType === 'worker' || currentAction.actionType === "operator") &&
{(currentAction.actionType === "worker" || currentAction.actionType === "operator") && (
<WorkerAction
loadCapacity={{
value: loadCapacity,
@@ -427,8 +345,8 @@ function HumanMechanics() {
}}
clearPoints={handleClearPoints}
/>
}
{currentAction.actionType === 'manufacturer' &&
)}
{currentAction.actionType === "manufacturer" && (
<ManufactureAction
processTime={{
value: processTime,
@@ -450,7 +368,7 @@ function HumanMechanics() {
onSwapSelect={handleMaterialChange}
clearPoints={handleClearPoints}
/>
}
)}
<div className="tirgger">
<Trigger selectedPointData={selectedPointData as any} type="Human" />
</div>

View File

@@ -6,7 +6,6 @@ import { useSelectedAction, useSelectedEventData } from "../../../../../../store
import ProcessAction from "../actions/ProcessAction";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
@@ -19,20 +18,14 @@ function MachineMechanics() {
const { selectedEventData } = useSelectedEventData();
const { productStore, versionStore } = useSceneContext();
const { getPointByUuid, updateAction } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getPointByUuid, updateAction, selectedProduct } = productStore();
const { setSelectedAction, clearSelectedAction } = useSelectedAction();
const { selectedVersion } = versionStore();
const { projectId } = useParams();
useEffect(() => {
if (selectedEventData) {
const point = getPointByUuid(
selectedProduct.productUuid,
selectedEventData?.data.modelUuid,
selectedEventData?.selectedPoint
) as MachinePointSchema | undefined;
const point = getPointByUuid(selectedProduct.productUuid, selectedEventData?.data.modelUuid, selectedEventData?.selectedPoint) as MachinePointSchema | undefined;
if (point && "action" in point) {
setSelectedPointData(point);
@@ -47,12 +40,7 @@ function MachineMechanics() {
}
}, [selectedProduct, selectedEventData]);
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName,
productUuid,
@@ -68,19 +56,10 @@ function MachineMechanics() {
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(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -88,19 +67,10 @@ function MachineMechanics() {
if (!selectedPointData) return;
setActionName(newName);
const event = updateAction(
selectedProduct.productUuid,
selectedPointData.action.actionUuid,
{ actionName: newName }
);
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { actionName: newName });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -111,19 +81,10 @@ function MachineMechanics() {
if (isNaN(numericValue)) return;
setProcessTime(value);
const event = updateAction(
selectedProduct.productUuid,
selectedPointData.action.actionUuid,
{ processTime: numericValue }
);
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { processTime: numericValue });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -131,19 +92,10 @@ function MachineMechanics() {
if (!selectedPointData) return;
setMaterial(selectedMaterial);
const event = updateAction(
selectedProduct.productUuid,
selectedPointData.action.actionUuid,
{ swapMaterial: selectedMaterial }
);
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { swapMaterial: selectedMaterial });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -158,34 +110,16 @@ function MachineMechanics() {
<section>
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput
value={actionName}
canEdit={false}
/>
<RenameInput value={actionName} canEdit={false} />
</div>
<ActionsList selectedPointData={selectedPointData} />
<div className="selected-actions-list">
<LabledDropdown
defaultOption={activeOption}
options={availableActions.options}
onSelect={handleActionTypeChange}
/>
{activeOption === "process" && (
<ProcessAction
value={processTime}
min={0.1}
max={60}
defaultValue="1"
onChange={handleProcessTimeChange}
swapOptions={["Default material", "Material 1", "Material 2", "Material 3"]}
swapDefaultOption={material}
onSwapSelect={handleMaterialSelect}
/>
)}
<LabledDropdown defaultOption={activeOption} options={availableActions.options} onSelect={handleActionTypeChange} />
{activeOption === "process" && <ProcessAction value={processTime} min={0.1} max={60} defaultValue="1" onChange={handleProcessTimeChange} swapOptions={["Default material", "Material 1", "Material 2", "Material 3"]} swapDefaultOption={material} onSwapSelect={handleMaterialSelect} />}
</div>
</div>
<div className="tirgger">
<Trigger selectedPointData={selectedPointData as any} type={'Machine'} />
<Trigger selectedPointData={selectedPointData as any} type={"Machine"} />
</div>
</section>
)}

View File

@@ -8,7 +8,6 @@ import { useSelectedEventData, useSelectedAction } from "../../../../../../store
import PickAndPlaceAction from "../actions/PickAndPlaceAction";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
@@ -19,29 +18,18 @@ function RoboticArmMechanics() {
const { selectedEventData } = useSelectedEventData();
const { productStore, versionStore } = useSceneContext();
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction, selectedProduct } = productStore();
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
const { selectedVersion } = versionStore();
const { projectId } = useParams();
useEffect(() => {
if (selectedEventData && selectedEventData.data.type === 'roboticArm') {
const point = getPointByUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint
) as RoboticArmPointSchema | undefined;
if (selectedEventData && selectedEventData.data.type === "roboticArm") {
const point = getPointByUuid(selectedProduct.productUuid, 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"
);
setSpeed((getEventByModelUuid(selectedProduct.productUuid, selectedEventData.data.modelUuid) as RoboticArmEventSchema | undefined)?.speed?.toString() || "0.5");
if (point.actions.length > 0) {
const firstAction = point.actions[0];
@@ -54,12 +42,7 @@ function RoboticArmMechanics() {
}
}, [selectedEventData, selectedProduct]);
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName,
productUuid,
@@ -76,43 +59,25 @@ function RoboticArmMechanics() {
if (isNaN(numericValue)) return;
setSpeed(value);
const event = updateEvent(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
{ speed: numericValue }
);
const event = updateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, { speed: numericValue });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
const handleClearPoints = () => {
if (!selectedAction.actionId || !selectedPointData) return;
const event = updateAction(
selectedProduct.productUuid,
selectedAction.actionId,
{
const event = updateAction(selectedProduct.productUuid, selectedAction.actionId, {
process: {
startPoint: null,
endPoint: null,
},
}
);
});
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -130,20 +95,10 @@ function RoboticArmMechanics() {
triggers: [] as TriggerSchema[],
};
const event = addAction(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint,
newAction
);
const event = addAction(selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint, newAction);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSelectedPointData({
@@ -156,22 +111,14 @@ function RoboticArmMechanics() {
const handleDeleteAction = (actionUuid: string) => {
if (!selectedPointData) return;
const event = removeAction(
selectedProduct.productUuid,
actionUuid
);
const event = removeAction(selectedProduct.productUuid, actionUuid);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
const index = selectedPointData.actions.findIndex(a => a.actionUuid === actionUuid);
const newActions = selectedPointData.actions.filter(a => a.actionUuid !== actionUuid);
const index = selectedPointData.actions.findIndex((a) => a.actionUuid === actionUuid);
const newActions = selectedPointData.actions.filter((a) => a.actionUuid !== actionUuid);
setSelectedPointData({
...selectedPointData,
@@ -193,57 +140,31 @@ function RoboticArmMechanics() {
options: ["pickAndPlace"],
};
const currentAction = selectedPointData?.actions.find(a => a.actionUuid === selectedAction.actionId);
const currentAction = selectedPointData?.actions.find((a) => a.actionUuid === selectedAction.actionId);
return (
<>
<div className="global-props section">
<div className="property-list-container">
<div className="property-item">
<InputWithDropDown
label="Speed"
value={speed}
min={0}
step={0.1}
defaultValue="0.5"
max={10}
activeOption="m/s"
onClick={() => { }}
onChange={handleSpeedChange}
/>
<InputWithDropDown label="Speed" value={speed} min={0} step={0.1} defaultValue="0.5" max={10} activeOption="m/s" onClick={() => {}} onChange={handleSpeedChange} />
</div>
</div>
</div>
<section>
<ActionsList
selectedPointData={selectedPointData}
multipleAction
handleAddAction={handleAddAction}
handleDeleteAction={handleDeleteAction}
/>
<ActionsList selectedPointData={selectedPointData} multipleAction handleAddAction={handleAddAction} handleDeleteAction={handleDeleteAction} />
{selectedAction.actionId && currentAction && (
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput
value={selectedAction.actionName || ""}
canEdit={false}
/>
<RenameInput value={selectedAction.actionName || ""} canEdit={false} />
</div>
<div className="selected-actions-list">
<LabledDropdown
defaultOption={activeOption}
options={availableActions.options}
onSelect={() => { }}
disabled={true}
/>
<LabledDropdown defaultOption={activeOption} options={availableActions.options} onSelect={() => {}} disabled={true} />
<PickAndPlaceAction clearPoints={handleClearPoints} />
</div>
<div className="tirgger">
<Trigger
selectedPointData={selectedPointData as any}
type={"RoboticArm"}
/>
<Trigger selectedPointData={selectedPointData as any} type={"RoboticArm"} />
</div>
</div>
)}

View File

@@ -7,7 +7,6 @@ import StorageAction from "../actions/StorageAction";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useSelectedAction, useSelectedEventData } from "../../../../../../store/simulation/useSimulationStore";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
@@ -19,29 +18,20 @@ function StorageMechanics() {
const [selectedPointData, setSelectedPointData] = useState<StoragePointSchema | undefined>();
const { selectedEventData } = useSelectedEventData();
const { productStore, versionStore } = useSceneContext();
const { getPointByUuid, updateAction, updateEvent, getEventByModelUuid, getActionByUuid, addAction, removeAction } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getPointByUuid, updateAction, updateEvent, getEventByModelUuid, getActionByUuid, addAction, removeAction, selectedProduct } = productStore();
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
const { selectedVersion } = versionStore();
const { projectId } = useParams();
useEffect(() => {
if (selectedEventData && selectedEventData.data.type === "storageUnit") {
const point = getPointByUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint
) as StoragePointSchema | undefined;
const point = getPointByUuid(selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint) as StoragePointSchema | undefined;
if (point?.actions?.length) {
setSelectedPointData(point);
const firstAction = point.actions[0];
const eventData = getEventByModelUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid
) as StorageEventSchema | undefined;
const eventData = getEventByModelUuid(selectedProduct.productUuid, selectedEventData.data.modelUuid) as StorageEventSchema | undefined;
setCurrentCapacity(eventData?.storageCapacity?.toString() || "1");
setSpawnedCount(eventData?.storageCount?.toString() || "0");
@@ -56,17 +46,13 @@ function StorageMechanics() {
useEffect(() => {
if (selectedEventData && selectedEventData.data.type === "storageUnit" && selectedAction.actionId) {
const point = getPointByUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint
) as StoragePointSchema | undefined;
const point = getPointByUuid(selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint) as StoragePointSchema | undefined;
const actionUuid = selectedAction.actionId || point?.actions[0].actionUuid || '';
const actionUuid = selectedAction.actionId || point?.actions[0].actionUuid || "";
const newCurrentAction = getActionByUuid(selectedProduct.productUuid, actionUuid);
if (newCurrentAction && (newCurrentAction.actionType === 'store' || newCurrentAction.actionType === 'retrieve')) {
if (newCurrentAction && (newCurrentAction.actionType === "store" || newCurrentAction.actionType === "retrieve")) {
if (!selectedAction.actionId) {
setSelectedAction(newCurrentAction.actionUuid, newCurrentAction.actionName);
}
@@ -78,20 +64,15 @@ function StorageMechanics() {
}
}, [selectedAction, selectedProduct, selectedEventData]);
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName: productName,
productUuid: productUuid,
projectId: projectId,
eventDatas: eventData,
versionId: selectedVersion?.versionId || '',
})
}
versionId: selectedVersion?.versionId || "",
});
};
const handleActionTypeChange = (option: string) => {
if (!selectedAction.actionId || !selectedPointData) return;
@@ -99,31 +80,24 @@ function StorageMechanics() {
const internalOption = option === "spawn" ? "retrieve" : "store";
const updatedAction = {
actionType: internalOption as "store" | "retrieve"
actionType: internalOption as "store" | "retrieve",
};
const updatedActions = selectedPointData.actions.map(action =>
action.actionUuid === selectedAction.actionId ? {
const updatedActions = selectedPointData.actions.map((action) =>
action.actionUuid === selectedAction.actionId
? {
...action,
actionType: updatedAction.actionType
} : action
actionType: updatedAction.actionType,
}
: action
);
const updatedPoint = { ...selectedPointData, actions: updatedActions };
const event = updateAction(
selectedProduct.productUuid,
selectedAction.actionId,
updatedAction
);
const event = updateAction(selectedProduct.productUuid, selectedAction.actionId, updatedAction);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSelectedPointData(updatedPoint);
@@ -137,7 +111,7 @@ function StorageMechanics() {
if (isNaN(numericValue)) return;
const updatedEvent = {
storageCapacity: numericValue
storageCapacity: numericValue,
} as StorageEventSchema;
const currentCount = parseInt(spawnedCount);
@@ -146,19 +120,10 @@ function StorageMechanics() {
setSpawnedCount(numericValue.toString());
}
const event = updateEvent(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
updatedEvent
);
const event = updateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, updatedEvent);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setCurrentCapacity(value);
@@ -174,22 +139,13 @@ function StorageMechanics() {
if (numericValue > maxCapacity) return;
const updatedEvent = {
storageCount: numericValue
storageCount: numericValue,
} as StorageEventSchema;
const event = updateEvent(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
updatedEvent
);
const event = updateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, updatedEvent);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSpawnedCount(value);
@@ -199,22 +155,13 @@ function StorageMechanics() {
if (!selectedEventData) return;
const updatedEvent = {
materialType: value
materialType: value,
} as StorageEventSchema;
const event = updateEvent(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
updatedEvent
);
const event = updateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, updatedEvent);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSpawnedMaterial(value);
@@ -233,15 +180,10 @@ function StorageMechanics() {
const updatedActions = [...(selectedPointData.actions || []), newAction];
const updatedPoint = { ...selectedPointData, actions: updatedActions };
const event = addAction(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint,
newAction
);
const event = addAction(selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint, newAction);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSelectedPointData(updatedPoint);
@@ -251,16 +193,13 @@ function StorageMechanics() {
const handleDeleteAction = (actionUuid: string) => {
if (!selectedPointData || !actionUuid) return;
const updatedActions = selectedPointData.actions.filter(action => action.actionUuid !== actionUuid);
const updatedActions = selectedPointData.actions.filter((action) => action.actionUuid !== actionUuid);
const updatedPoint = { ...selectedPointData, actions: updatedActions };
const event = removeAction(
selectedProduct.productUuid,
actionUuid
);
const event = removeAction(selectedProduct.productUuid, actionUuid);
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
setSelectedPointData(updatedPoint);
@@ -279,45 +218,21 @@ function StorageMechanics() {
{selectedEventData && selectedEventData.data.type === "storageUnit" && (
<>
<section>
<StorageAction
maxCapacity={currentCapacity}
spawnedCount={spawnedCount}
maxCapacityDefault="0"
spawnedCountCefault="0"
min={0}
currentMaterialType={spawnedMaterial}
handleCapacityChange={handleCapacityChange}
handleSpawnCountChange={handleSpawnCountChange}
handleMaterialTypeChange={handleMaterialTypeChange}
/>
<StorageAction maxCapacity={currentCapacity} spawnedCount={spawnedCount} maxCapacityDefault="0" spawnedCountCefault="0" min={0} currentMaterialType={spawnedMaterial} handleCapacityChange={handleCapacityChange} handleSpawnCountChange={handleSpawnCountChange} handleMaterialTypeChange={handleMaterialTypeChange} />
</section>
<section>
<ActionsList
selectedPointData={selectedPointData}
multipleAction={true}
handleAddAction={handleAddAction}
handleDeleteAction={handleDeleteAction}
/>
<ActionsList selectedPointData={selectedPointData} multipleAction={true} handleAddAction={handleAddAction} handleDeleteAction={handleDeleteAction} />
{selectedAction.actionId && (
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput
value={selectedAction.actionName || ""}
canEdit={false}
/>
<RenameInput value={selectedAction.actionName || ""} canEdit={false} />
</div>
<div className="selected-actions-list">
<LabledDropdown
label="Action Type"
defaultOption={activeOption}
options={["store", "spawn"]}
onSelect={handleActionTypeChange}
disabled={false}
/>
<LabledDropdown label="Action Type" defaultOption={activeOption} options={["store", "spawn"]} onSelect={handleActionTypeChange} disabled={false} />
</div>
<div className="tirgger">
<Trigger selectedPointData={selectedPointData as any} type={'StorageUnit'} />
<Trigger selectedPointData={selectedPointData as any} type={"StorageUnit"} />
</div>
</div>
)}

View File

@@ -7,7 +7,6 @@ import { useSelectedAction, useSelectedEventData } from "../../../../../../store
import TravelAction from "../actions/TravelAction";
import ActionsList from "../components/ActionsList";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
import { useSelectedPath } from "../../../../../../store/builder/store";
@@ -22,9 +21,7 @@ function VehicleMechanics() {
const { selectedEventData } = useSelectedEventData();
const { productStore, versionStore } = useSceneContext();
const { getPointByUuid, updateEvent, updateAction, getEventByModelUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getPointByUuid, updateEvent, updateAction, getEventByModelUuid, selectedProduct } = productStore();
const { setSelectedAction, clearSelectedAction } = useSelectedAction();
const { selectedVersion } = versionStore();
const { projectId } = useParams();
@@ -32,22 +29,13 @@ function VehicleMechanics() {
useEffect(() => {
if (selectedEventData && selectedEventData.data.type === "vehicle") {
const point = getPointByUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
selectedEventData.selectedPoint
) as VehiclePointSchema | undefined;
const point = getPointByUuid(selectedProduct.productUuid, selectedEventData.data.modelUuid, selectedEventData.selectedPoint) as VehiclePointSchema | undefined;
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"
);
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);
@@ -57,12 +45,7 @@ function VehicleMechanics() {
}
}, [selectedProduct, selectedEventData]);
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName,
productUuid,
@@ -79,19 +62,10 @@ function VehicleMechanics() {
if (isNaN(numericValue)) return;
setSpeed(value);
const event = updateEvent(
selectedProduct.productUuid,
selectedEventData.data.modelUuid,
{ speed: numericValue }
);
const event = updateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, { speed: numericValue });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -101,19 +75,10 @@ function VehicleMechanics() {
const validOption = option as "travel";
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(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -124,19 +89,10 @@ function VehicleMechanics() {
if (isNaN(numericValue)) return;
setLoadCapacity(value);
const event = updateAction(
selectedProduct.productUuid,
selectedPointData.action.actionUuid,
{ loadCapacity: numericValue }
);
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { loadCapacity: numericValue });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -147,42 +103,24 @@ function VehicleMechanics() {
if (isNaN(numericValue)) return;
setUnloadDuration(value);
const event = updateAction(
selectedProduct.productUuid,
selectedPointData.action.actionUuid,
{ unLoadDuration: numericValue }
);
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, { unLoadDuration: numericValue });
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
const handleClearPoints = () => {
if (!selectedPointData) return;
const event = updateAction(
selectedProduct.productUuid,
selectedPointData.action.actionUuid,
{
const event = updateAction(selectedProduct.productUuid, selectedPointData.action.actionUuid, {
pickUpPoint: null,
unLoadPoint: null,
steeringAngle: 0,
}
);
});
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -198,17 +136,7 @@ function VehicleMechanics() {
<div className="global-props section">
<div className="property-list-container">
<div className="property-item">
<InputWithDropDown
label="Speed"
value={speed}
min={0}
step={0.1}
defaultValue="0.5"
max={10}
activeOption="m/s"
onClick={() => { }}
onChange={handleSpeedChange}
/>
<InputWithDropDown label="Speed" value={speed} min={0} step={0.1} defaultValue="0.5" max={10} activeOption="m/s" onClick={() => {}} onChange={handleSpeedChange} />
</div>
</div>
</div>
@@ -216,17 +144,10 @@ function VehicleMechanics() {
<ActionsList selectedPointData={selectedPointData} />
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput
value={actionName}
canEdit={false}
/>
<RenameInput value={actionName} canEdit={false} />
</div>
<div className="selected-actions-list">
<LabledDropdown
defaultOption={activeOption}
options={availableActions.options}
onSelect={handleActionTypeChange}
/>
<LabledDropdown defaultOption={activeOption} options={availableActions.options} onSelect={handleActionTypeChange} />
{activeOption === "travel" && (
<TravelAction
@@ -250,17 +171,16 @@ function VehicleMechanics() {
</div>
</div>
<div className="tirgger">
<Trigger
selectedPointData={selectedPointData as any}
type={"Vehicle"}
/>
<Trigger selectedPointData={selectedPointData as any} type={"Vehicle"} />
</div>
<div style={{
<div
style={{
display: "flex",
gap: "10px",
flexDirection: "column",
alignItems: "center"
}}>
alignItems: "center",
}}
>
<button
style={{
backgroundColor: "#6f42c1",

View File

@@ -6,7 +6,6 @@ import RenameInput from "../../../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../../../functions/handleResizePannel";
import { useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
@@ -17,10 +16,8 @@ type TriggerProps = {
const Trigger = ({ selectedPointData, type }: TriggerProps) => {
const [currentAction, setCurrentAction] = useState<string | undefined>();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { productStore, versionStore } = useSceneContext();
const { getActionByUuid, getEventByModelUuid, getPointByUuid, getTriggerByUuid, addTrigger, removeTrigger, updateTrigger, renameTrigger, getProductById, } = productStore();
const { getActionByUuid, getEventByModelUuid, getPointByUuid, getTriggerByUuid, addTrigger, removeTrigger, updateTrigger, renameTrigger, getProductById, selectedProduct } = productStore();
const [triggers, setTriggers] = useState<TriggerSchema[]>([]);
const [selectedTrigger, setSelectedTrigger] = useState<TriggerSchema | undefined>();
const [activeOption, setActiveOption] = useState<"onComplete" | "onStart" | "onStop" | "delay" | "onError">("onComplete");
@@ -35,26 +32,21 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
let actionUuid: string | undefined;
if (type === "Conveyor" || type === "Vehicle" || type === "Machine") {
actionUuid = (selectedPointData as | ConveyorPointSchema | VehiclePointSchema | MachinePointSchema).action?.actionUuid;
} else if ((type === "RoboticArm" || type === "Human" || type === "StorageUnit" || type === 'Crane') && selectedAction.actionId) {
actionUuid = (selectedPointData as ConveyorPointSchema | VehiclePointSchema | MachinePointSchema).action?.actionUuid;
} else if ((type === "RoboticArm" || type === "Human" || type === "StorageUnit" || type === "Crane") && selectedAction.actionId) {
actionUuid = selectedAction.actionId;
}
setCurrentAction(actionUuid);
}, [selectedPointData, selectedProduct, type, selectedAction]);
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName: productName,
productUuid: productUuid,
projectId: projectId,
eventDatas: eventData,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
});
};
@@ -70,31 +62,18 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
}, [currentAction, selectedProduct, selectedTrigger, selectedPointData]);
const triggeredModel = useMemo(() => {
if (!selectedProduct || !selectedTrigger?.triggeredAsset?.triggeredModel?.modelUuid)
return undefined;
return getEventByModelUuid(
selectedProduct.productUuid,
selectedTrigger.triggeredAsset.triggeredModel.modelUuid
);
if (!selectedProduct || !selectedTrigger?.triggeredAsset?.triggeredModel?.modelUuid) return undefined;
return getEventByModelUuid(selectedProduct.productUuid, selectedTrigger.triggeredAsset.triggeredModel.modelUuid);
}, [selectedProduct, selectedTrigger]);
const triggeredPoint = useMemo(() => {
if (!selectedProduct || !triggeredModel || !selectedTrigger?.triggeredAsset?.triggeredPoint?.pointUuid)
return undefined;
return getPointByUuid(
selectedProduct.productUuid,
triggeredModel.modelUuid,
selectedTrigger.triggeredAsset.triggeredPoint.pointUuid
);
if (!selectedProduct || !triggeredModel || !selectedTrigger?.triggeredAsset?.triggeredPoint?.pointUuid) return undefined;
return getPointByUuid(selectedProduct.productUuid, triggeredModel.modelUuid, selectedTrigger.triggeredAsset.triggeredPoint.pointUuid);
}, [selectedProduct, triggeredModel, selectedTrigger]);
const triggeredAction = useMemo(() => {
if (!selectedProduct || !selectedTrigger?.triggeredAsset?.triggeredAction?.actionUuid)
return undefined;
return getActionByUuid(
selectedProduct.productUuid,
selectedTrigger.triggeredAsset.triggeredAction.actionUuid
);
if (!selectedProduct || !selectedTrigger?.triggeredAsset?.triggeredAction?.actionUuid) return undefined;
return getActionByUuid(selectedProduct.productUuid, selectedTrigger.triggeredAsset.triggeredAction.actionUuid);
}, [selectedProduct, selectedTrigger]);
const modelOptions = getProductById(selectedProduct.productUuid)?.eventDatas || [];
@@ -106,7 +85,7 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
if (!model) return [];
if ("points" in model) {
return (model).points;
return model.points;
} else if ("point" in model) {
return [model.point];
}
@@ -146,18 +125,10 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
});
if (event) {
const updatedTrigger = getTriggerByUuid(
selectedProduct.productUuid,
triggerUuid
);
const updatedTrigger = getTriggerByUuid(selectedProduct.productUuid, triggerUuid);
setSelectedTrigger(updatedTrigger);
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -180,18 +151,10 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
});
if (event) {
const updatedTrigger = getTriggerByUuid(
selectedProduct.productUuid,
triggerUuid
);
const updatedTrigger = getTriggerByUuid(selectedProduct.productUuid, triggerUuid);
setSelectedTrigger(updatedTrigger);
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
}
};
@@ -215,12 +178,7 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
});
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
}
};
@@ -236,25 +194,13 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
triggeredAsset: null,
};
const event = addTrigger(
selectedProduct.productUuid,
currentAction,
newTrigger
);
const event = addTrigger(selectedProduct.productUuid, currentAction, newTrigger);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
const updatedAction = getActionByUuid(
selectedProduct.productUuid,
currentAction
);
const updatedAction = getActionByUuid(selectedProduct.productUuid, currentAction);
const updatedTriggers = updatedAction?.triggers || [];
setTriggers(updatedTriggers);
@@ -267,12 +213,7 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
const event = removeTrigger(selectedProduct.productUuid, triggerUuid);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
const index = triggers.findIndex((t) => t.triggerUuid === triggerUuid);
@@ -287,44 +228,26 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
const handleTriggerRename = (triggerUuid: string, newName: string) => {
if (!selectedProduct) return;
const event = renameTrigger(
selectedProduct.productUuid,
triggerUuid,
newName
);
const event = renameTrigger(selectedProduct.productUuid, triggerUuid, newName);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
const handleTriggerTypeChange = (option: string) => {
if (!selectedTrigger || !selectedProduct) return;
const validTypes: Array<TriggerSchema["triggerType"]> = ["onComplete", "onStart", "onStop", "delay", "onError",];
const validTypes: Array<TriggerSchema["triggerType"]> = ["onComplete", "onStart", "onStop", "delay", "onError"];
if (!validTypes.includes(option as TriggerSchema["triggerType"])) return;
setActiveOption(option as TriggerSchema["triggerType"]);
const event = updateTrigger(
selectedProduct.productUuid,
selectedTrigger.triggerUuid,
{
const event = updateTrigger(selectedProduct.productUuid, selectedTrigger.triggerUuid, {
triggerType: option as TriggerSchema["triggerType"],
}
);
});
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
};
@@ -332,39 +255,17 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
<div className="trigger-wrapper">
<div className="header">
<div className="title">Trigger</div>
<button
id="add-trigger-button"
className="add-button"
onClick={handleAddTrigger}
style={{ cursor: "pointer" }}
disabled={!currentAction}
>
<button id="add-trigger-button" className="add-button" onClick={handleAddTrigger} style={{ cursor: "pointer" }} disabled={!currentAction}>
<AddIcon /> Add
</button>
</div>
<div className="trigger-list">
<div
className="lists-main-container"
ref={triggersContainerRef}
style={{ height: "120px" }}
>
<div className="lists-main-container" ref={triggersContainerRef} style={{ height: "120px" }}>
<div className="list-container">
{triggers.map((trigger) => (
<div
key={trigger.triggerUuid}
className={`list-item ${selectedTrigger?.triggerUuid === trigger.triggerUuid
? "active"
: ""
}`}
onClick={() => setSelectedTrigger(trigger)}
>
<div key={trigger.triggerUuid} className={`list-item ${selectedTrigger?.triggerUuid === trigger.triggerUuid ? "active" : ""}`} onClick={() => setSelectedTrigger(trigger)}>
<button id="trigger" className="value">
<RenameInput
value={trigger.triggerName}
onRename={(newName) =>
handleTriggerRename(trigger.triggerUuid, newName)
}
/>
<RenameInput value={trigger.triggerName} onRename={(newName) => handleTriggerRename(trigger.triggerUuid, newName)} />
</button>
<button
id="remove-trigger-button"
@@ -379,11 +280,7 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
</div>
))}
</div>
<button
className="resize-icon"
id="action-resize"
onMouseDown={(e: any) => handleResize(e, triggersContainerRef)}
>
<button className="resize-icon" id="action-resize" onMouseDown={(e: any) => handleResize(e, triggersContainerRef)}>
<ResizeHeightIcon />
</button>
</div>
@@ -410,16 +307,8 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
/>
<LabledDropdown
label="Triggered Point"
defaultOption={
triggeredPoint?.uuid
? `Point ${triggeredPoint?.uuid.slice(0, 4)}`
: ""
}
options={[
...pointOptions.map(
(option) => `Point ${option.uuid.slice(0, 4)}`
),
]}
defaultOption={triggeredPoint?.uuid ? `Point ${triggeredPoint?.uuid.slice(0, 4)}` : ""}
options={[...pointOptions.map((option) => `Point ${option.uuid.slice(0, 4)}`)]}
onSelect={(option) => {
handlePointSelect(option, selectedTrigger.triggerUuid);
}}
@@ -427,9 +316,7 @@ const Trigger = ({ selectedPointData, type }: TriggerProps) => {
<LabledDropdown
label="Triggered Action"
defaultOption={triggeredAction?.actionName || ""}
options={[
...actionOptions.map((option: any) => option.actionName),
]}
options={[...actionOptions.map((option: any) => option.actionName)]}
onSelect={(option) => {
handleActionSelect(option, selectedTrigger.triggerUuid);
}}

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from "react";
import { AddIcon, ArrowIcon, RemoveIcon, ResizeHeightIcon, } from "../../../icons/ExportCommonIcons";
import { AddIcon, ArrowIcon, RemoveIcon, ResizeHeightIcon } from "../../../icons/ExportCommonIcons";
import RenameInput from "../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../functions/handleResizePannel";
import { useMainProduct, useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
@@ -13,9 +13,8 @@ import { deleteProductApi } from "../../../../services/simulation/products/delet
import { renameProductApi } from "../../../../services/simulation/products/renameProductApi";
import { determineExecutionMachineSequences } from "../../../../modules/simulation/simulator/functions/determineExecutionMachineSequences";
import ComparePopUp from "../../../ui/compareVersion/Compare";
import { useCompareStore, useSaveVersion, } from "../../../../store/builder/store";
import { useCompareStore, useSaveVersion } from "../../../../store/builder/store";
import { useToggleStore } from "../../../../store/ui/useUIToggleStore";
import { useProductContext } from "../../../../modules/simulation/products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
@@ -39,9 +38,7 @@ const List: React.FC<ListProps> = ({ val }) => {
const Simulations: React.FC = () => {
const productsContainerRef = useRef<HTMLDivElement>(null);
const { eventStore, productStore, versionStore } = useSceneContext();
const { products, addProduct, removeProduct, renameProduct, addEvent, removeEvent, getProductById, } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct, setSelectedProduct } = selectedProductStore();
const { products, addProduct, removeProduct, renameProduct, addEvent, removeEvent, getProductById, selectedProduct, setSelectedProduct } = productStore();
const { getEventByModelUuid } = eventStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const [openObjects, setOpenObjects] = useState(true);
@@ -67,7 +64,7 @@ const Simulations: React.FC = () => {
productName: name,
productUuid: id,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
});
};
@@ -83,14 +80,8 @@ const Simulations: React.FC = () => {
if (currentIndex >= updatedProducts.length) {
newSelectedIndex = updatedProducts.length - 1;
}
setSelectedProduct(
updatedProducts[newSelectedIndex].productUuid,
updatedProducts[newSelectedIndex].productName
);
setMainProduct(
updatedProducts[newSelectedIndex].productUuid,
updatedProducts[newSelectedIndex].productName
);
setSelectedProduct(updatedProducts[newSelectedIndex].productUuid, updatedProducts[newSelectedIndex].productName);
setMainProduct(updatedProducts[newSelectedIndex].productUuid, updatedProducts[newSelectedIndex].productName);
} else {
setSelectedProduct("", "");
setMainProduct("", "");
@@ -100,14 +91,14 @@ const Simulations: React.FC = () => {
removeProduct(productUuid);
deleteProductApi({
productUuid,
versionId: selectedVersion?.versionId || '',
projectId
versionId: selectedVersion?.versionId || "",
projectId,
});
};
const handleRenameProduct = (productUuid: string, newName: string) => {
renameProduct(productUuid, newName);
renameProductApi({ productName: newName, productUuid, projectId: projectId || '', versionId: selectedVersion?.versionId || '' });
renameProductApi({ productName: newName, productUuid, projectId: projectId || "", versionId: selectedVersion?.versionId || "" });
if (selectedProduct.productUuid === productUuid) {
setSelectedProduct(productUuid, newName);
setMainProduct(productUuid, newName);
@@ -116,11 +107,10 @@ const Simulations: React.FC = () => {
const handleRemoveEventFromProduct = () => {
if (selectedAsset) {
deleteEventDataApi({
productUuid: selectedProduct.productUuid,
modelUuid: selectedAsset.modelUuid,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId: projectId,
});
removeEvent(selectedProduct.productUuid, selectedAsset.modelUuid);
@@ -133,8 +123,7 @@ const Simulations: React.FC = () => {
const selectedProductData = getProductById(selectedProduct.productUuid);
if (selectedProductData) {
determineExecutionMachineSequences([selectedProductData]).then(
(sequences) => {
determineExecutionMachineSequences([selectedProductData]).then((sequences) => {
sequences.forEach((sequence) => {
const events: Event[] =
sequence.map((event) => ({
@@ -144,10 +133,8 @@ const Simulations: React.FC = () => {
processes.push(events);
});
setProcesses(processes);
});
}
);
}
}, [selectedProduct.productUuid, products]);
return (
@@ -157,77 +144,41 @@ const Simulations: React.FC = () => {
<div className="actions section">
<div className="header">
<div className="header-value">Products</div>
<button
id="add-simulation"
className="add-button"
onClick={handleAddProduct}
>
<button id="add-simulation" className="add-button" onClick={handleAddProduct}>
<AddIcon /> Add
</button>
</div>
<div
className="lists-main-container"
ref={productsContainerRef}
style={{ height: "120px" }}
>
<div className="lists-main-container" ref={productsContainerRef} style={{ height: "120px" }}>
<div className="list-container">
{products.map((product, index) => (
<div
key={product.productUuid}
className={`list-item ${selectedProduct.productUuid === product.productUuid
? "active"
: ""
}`}
>
<div key={product.productUuid} className={`list-item ${selectedProduct.productUuid === product.productUuid ? "active" : ""}`}>
{/* eslint-disable-next-line */}
<div
className="value"
onClick={() => {
setSelectedProduct(product.productUuid, product.productName)
setMainProduct(product.productUuid, product.productName)
setSelectedProduct(product.productUuid, product.productName);
setMainProduct(product.productUuid, product.productName);
}}
>
<input
type="radio"
name="products"
checked={selectedProduct.productUuid === product.productUuid}
readOnly
/>
<RenameInput
value={product.productName}
onRename={(newName) =>
handleRenameProduct(product.productUuid, newName)
}
/>
<input type="radio" name="products" checked={selectedProduct.productUuid === product.productUuid} readOnly />
<RenameInput value={product.productName} onRename={(newName) => handleRenameProduct(product.productUuid, newName)} />
</div>
{products.length > 1 && (
<button
id="remove-product-button"
className="remove-button"
onClick={() => handleRemoveProduct(product.productUuid)}
>
<button id="remove-product-button" className="remove-button" onClick={() => handleRemoveProduct(product.productUuid)}>
<RemoveIcon />
</button>
)}
</div>
))}
</div>
<button
className="resize-icon"
id="action-resize"
onMouseDown={(e: any) => handleResize(e, productsContainerRef)}
>
<button className="resize-icon" id="action-resize" onMouseDown={(e: any) => handleResize(e, productsContainerRef)}>
<ResizeHeightIcon />
</button>
</div>
</div>
<div className="simulation-process section">
<button
id="collapse-header"
className="collapse-header-container"
onClick={() => setOpenObjects(!openObjects)}
>
<button id="collapse-header" className="collapse-header-container" onClick={() => setOpenObjects(!openObjects)}>
<div className="header">Process Flow</div>
<div className="arrow-container">
<ArrowIcon />
@@ -244,12 +195,9 @@ const Simulations: React.FC = () => {
</div>
<div className="compare-simulations-container">
<div className="compare-simulations-header">
Need to Compare Layout?
</div>
<div className="compare-simulations-header">Need to Compare Layout?</div>
<div className="content">
Click '<span>Compare</span>' to review and analyze the layout
differences between them.
Click '<span>Compare</span>' to review and analyze the layout differences between them.
</div>
<button className="input" onClick={() => setComparePopUp(true)}>
<input type="button" value={"Compare"} className="submit" />
@@ -268,8 +216,8 @@ const Simulations: React.FC = () => {
addEvent,
selectedProduct,
clearSelectedAsset,
projectId: projectId || '',
versionId: selectedVersion?.versionId || '',
projectId: projectId || "",
versionId: selectedVersion?.versionId || "",
});
} else {
handleRemoveEventFromProduct();

View File

@@ -1,13 +1,9 @@
import { useSceneContext } from "../modules/scene/sceneContext";
import { useProductContext } from "../modules/simulation/products/productContext";
const useRestStates = () => {
const { selectedProductStore } = useProductContext();
const { clearSelectedProduct } = selectedProductStore();
const { clearStores } = useSceneContext();
const resetStates = () => {
clearSelectedProduct();
clearStores();
};

View File

@@ -1,30 +1,21 @@
import * as THREE from 'three';
import { CameraControls } from '@react-three/drei';
import { ThreeEvent, useThree } from '@react-three/fiber';
import { useCallback, useEffect, useRef } from 'react';
import * as THREE from "three";
import { CameraControls } from "@react-three/drei";
import { ThreeEvent, useThree } from "@react-three/fiber";
import { useCallback, useEffect, useRef } from "react";
import { useActiveTool, useResourceManagementId, useToggleView, useZoneAssetId, useSocketStore } from '../../../../../../store/builder/store';
import useModuleStore, { useSubModuleStore } from '../../../../../../store/ui/useModuleStore';
import { useSceneContext } from '../../../../../scene/sceneContext';
import { useProductContext } from '../../../../../simulation/products/productContext';
import { useParams } from 'react-router-dom';
import { getUserData } from '../../../../../../functions/getUserData';
import { useLeftData, useTopData } from '../../../../../../store/visualization/useZone3DWidgetStore';
import { useSelectedAsset } from '../../../../../../store/simulation/useSimulationStore';
import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore';
import { useActiveTool, useResourceManagementId, useToggleView, useZoneAssetId, useSocketStore } from "../../../../../../store/builder/store";
import useModuleStore, { useSubModuleStore } from "../../../../../../store/ui/useModuleStore";
import { useSceneContext } from "../../../../../scene/sceneContext";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../../functions/getUserData";
import { useLeftData, useTopData } from "../../../../../../store/visualization/useZone3DWidgetStore";
import { useSelectedAsset } from "../../../../../../store/simulation/useSimulationStore";
import { useBuilderStore } from "../../../../../../store/builder/useBuilderStore";
import { upsertProductOrEventApi } from '../../../../../../services/simulation/products/UpsertProductOrEventApi';
import { deleteFloorAssetApi } from '../../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorAssetApi';
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
import { deleteFloorAssetApi } from "../../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorAssetApi";
export function useModelEventHandlers({
boundingBox,
groupRef,
asset
}: {
boundingBox: THREE.Box3 | null,
groupRef: React.RefObject<THREE.Group>,
asset: Asset
}) {
export function useModelEventHandlers({ boundingBox, groupRef, asset }: { boundingBox: THREE.Box3 | null; groupRef: React.RefObject<THREE.Group>; asset: Asset }) {
const { controls, gl, camera } = useThree();
const { activeTool } = useActiveTool();
const { activeModule } = useModuleStore();
@@ -37,11 +28,9 @@ export function useModelEventHandlers({
const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
const { resourceManagementId, setResourceManagementId } = useResourceManagementId();
const { removeEvent, getEventByModelUuid } = eventStore();
const { getIsEventInProduct, addPoint, deleteEvent } = productStore();
const { getIsEventInProduct, addPoint, deleteEvent, selectedProduct } = productStore();
const { setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
const { deletableFloorAsset, setDeletableFloorAsset, selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { selectedVersion } = versionStore();
const { projectId } = useParams();
const { userId, organization } = getUserData();
@@ -52,47 +41,38 @@ export function useModelEventHandlers({
const { setTop } = useTopData();
const { setLeft } = useLeftData();
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName: productName,
productUuid: productUuid,
projectId: projectId,
eventDatas: eventData,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
});
};
useEffect(() => {
if (!zoneAssetId) return
if (!zoneAssetId) return;
if (zoneAssetId.id === asset.modelUuid) {
handleDblClick(asset);
}
}, [zoneAssetId])
}, [zoneAssetId]);
useEffect(() => {
if (!resourceManagementId) return
if (!resourceManagementId) return;
if (resourceManagementId === asset.modelUuid) {
handleDblClick(asset);
}
}, [resourceManagementId])
}, [resourceManagementId]);
useEffect(() => {
if (!selectedFloorAsset) {
setZoneAssetId(null);
}
}, [selectedFloorAsset])
}, [selectedFloorAsset]);
const handleDblClick = (asset: Asset) => {
if (asset && activeTool === "cursor" && boundingBox && groupRef.current && (activeModule === 'builder' || (activeModule === 'simulation' && resourceManagementId))) {
if (asset && activeTool === "cursor" && boundingBox && groupRef.current && (activeModule === "builder" || (activeModule === "simulation" && resourceManagementId))) {
const frontView = false;
if (frontView) {
const size = boundingBox.getSize(new THREE.Vector3());
@@ -114,9 +94,7 @@ export function useModelEventHandlers({
paddingBottom: 5,
paddingRight: 5,
});
} else {
const collisionPos = new THREE.Vector3();
groupRef.current.getWorldPosition(collisionPos);
@@ -141,18 +119,16 @@ export function useModelEventHandlers({
const handleClick = async (evt: ThreeEvent<MouseEvent>, asset: Asset) => {
if (leftDrag.current || toggleView) return;
if (activeTool === 'delete' && deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
if (activeTool === "delete" && deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
if (!socket?.connected) {
// REST
deleteFloorAssetApi({
modelUuid: asset.modelUuid,
modelName: asset.modelName,
versionId: selectedVersion?.versionId || '',
projectId: projectId || ''
versionId: selectedVersion?.versionId || "",
projectId: projectId || "",
});
} else {
// SOCKET
@@ -162,29 +138,24 @@ export function useModelEventHandlers({
modelName: asset.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
}
versionId: selectedVersion?.versionId || "",
projectId,
};
socket.emit('v1:model-asset:delete', data)
socket.emit("v1:model-asset:delete", data);
}
removeEvent(asset.modelUuid);
const updatedEvents = deleteEvent(asset.modelUuid);
updatedEvents.forEach((event) => {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
})
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
});
removeAsset(asset.modelUuid);
push3D({
type: 'Scene',
type: "Scene",
actions: [
{
module: "builder",
@@ -192,16 +163,15 @@ export function useModelEventHandlers({
asset: {
type: "Asset",
assetData: asset,
timeStap: new Date().toISOString()
}
}
]
timeStap: new Date().toISOString(),
},
},
],
});
echo.success("Model Removed!");
} else if (activeModule === 'simulation' && subModule === "simulations" && activeTool === 'pen') {
if (asset.eventData && asset.eventData.type === 'Conveyor') {
} else if (activeModule === "simulation" && subModule === "simulations" && activeTool === "pen") {
if (asset.eventData && asset.eventData.type === "Conveyor") {
const intersectedPoint = evt.point;
const localPosition = groupRef.current?.worldToLocal(intersectedPoint.clone());
if (localPosition) {
@@ -212,49 +182,50 @@ export function useModelEventHandlers({
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: `Action 1`,
actionType: 'default',
material: 'Default Material',
actionType: "default",
material: "Default Material",
delay: 0,
spawnInterval: 5,
spawnCount: 1,
triggers: []
}
}
triggers: [],
},
};
const event = addPoint(selectedProduct.productUuid, asset.modelUuid, conveyorPoint);
if (event) {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
}
}
}
};
const handlePointerOver = useCallback((asset: Asset) => {
if (activeTool === "delete" && activeModule === 'builder') {
const handlePointerOver = useCallback(
(asset: Asset) => {
if (activeTool === "delete" && activeModule === "builder") {
if (deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
return;
} else {
setDeletableFloorAsset(groupRef.current);
}
}
}, [activeTool, activeModule, deletableFloorAsset]);
},
[activeTool, activeModule, deletableFloorAsset]
);
const handlePointerOut = useCallback((evt: ThreeEvent<MouseEvent>, asset: Asset) => {
const handlePointerOut = useCallback(
(evt: ThreeEvent<MouseEvent>, asset: Asset) => {
if (evt.intersections.length === 0 && activeTool === "delete" && deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
setDeletableFloorAsset(null);
}
}, [activeTool, deletableFloorAsset]);
},
[activeTool, deletableFloorAsset]
);
const handleContextMenu = (asset: Asset, evt: ThreeEvent<MouseEvent>) => {
if (rightDrag.current || toggleView) return;
if (activeTool === "cursor" && subModule === 'simulations') {
if (activeTool === "cursor" && subModule === "simulations") {
if (asset.modelUuid) {
const canvasElement = gl.domElement;
const isInProduct = getIsEventInProduct(selectedProduct.productUuid, asset.modelUuid);
@@ -270,12 +241,12 @@ export function useModelEventHandlers({
clearSelectedAsset();
}
} else {
clearSelectedAsset()
clearSelectedAsset();
}
} else {
clearSelectedAsset()
}
clearSelectedAsset();
}
};
useEffect(() => {
const canvasElement = gl.domElement;
@@ -309,23 +280,22 @@ export function useModelEventHandlers({
}
};
canvasElement.addEventListener('pointerdown', onPointerDown);
canvasElement.addEventListener('pointermove', onPointerMove);
canvasElement.addEventListener('pointerup', onPointerUp);
canvasElement.addEventListener("pointerdown", onPointerDown);
canvasElement.addEventListener("pointermove", onPointerMove);
canvasElement.addEventListener("pointerup", onPointerUp);
return () => {
canvasElement.removeEventListener('pointerdown', onPointerDown);
canvasElement.removeEventListener('pointermove', onPointerMove);
canvasElement.removeEventListener('pointerup', onPointerUp);
}
}, [gl])
canvasElement.removeEventListener("pointerdown", onPointerDown);
canvasElement.removeEventListener("pointermove", onPointerMove);
canvasElement.removeEventListener("pointerup", onPointerUp);
};
}, [gl]);
return {
handleDblClick,
handleClick,
handlePointerOver,
handlePointerOut,
handleContextMenu
handleContextMenu,
};
}

View File

@@ -8,7 +8,6 @@ import { upsertProductOrEventApi } from "../../../../../services/simulation/prod
import { handleAssetPositionSnap } from "./functions/handleAssetPositionSnap";
import DistanceFindingControls from "./distanceFindingControls";
import { useParams } from "react-router-dom";
import { useProductContext } from "../../../../simulation/products/productContext";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import useModuleStore from "../../../../../store/ui/useModuleStore";
@@ -22,8 +21,6 @@ function MoveControls3D({ boundingBoxRef }: any) {
const { toggleView } = useToggleView();
const { toolMode } = useToolMode();
const { activeModule } = useModuleStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { socket } = useSocketStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
@@ -172,7 +169,7 @@ function MoveControls3D({ boundingBoxRef }: any) {
canvasElement?.removeEventListener("keyup", onKeyUp);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [camera, controls, scene, toggleView, toolMode, selectedAssets, socket, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, keyEvent, initialStates]);
}, [camera, controls, scene, toggleView, toolMode, selectedAssets, socket, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, keyEvent, initialStates, productStore]);
useEffect(() => {
if (activeModule !== "builder" || toolMode !== "cursor" || toggleView) {
@@ -345,7 +342,7 @@ function MoveControls3D({ boundingBoxRef }: any) {
if (movedAsset.userData.eventData) {
const eventData = eventStore.getState().getEventByModelUuid(movedAsset.userData.modelUuid);
const productData = productStore.getState().getEventByModelUuid(selectedProduct.productUuid, movedAsset.userData.modelUuid);
const productData = productStore.getState().getEventByModelUuid(productStore.getState().selectedProduct.productUuid, movedAsset.userData.modelUuid);
if (eventData) {
eventStore.getState().updateEvent(movedAsset.userData.modelUuid, {
@@ -355,13 +352,13 @@ function MoveControls3D({ boundingBoxRef }: any) {
}
if (productData) {
const event = productStore.getState().updateEvent(selectedProduct.productUuid, movedAsset.userData.modelUuid, {
const event = productStore.getState().updateEvent(productStore.getState().selectedProduct.productUuid, movedAsset.userData.modelUuid, {
position: [position.x, position.y, position.z],
rotation: [movedAsset.rotation.x, movedAsset.rotation.y, movedAsset.rotation.z],
});
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
updateBackend(productStore.getState().selectedProduct.productName, productStore.getState().selectedProduct.productUuid, projectId || "", event);
}
newFloorItem.eventData = eventData;

View File

@@ -5,7 +5,6 @@ import { useContextActionStore, useSocketStore, useToggleView, useToolMode } fro
import * as Types from "../../../../../types/world/worldTypes";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useParams } from "react-router-dom";
import { useProductContext } from "../../../../simulation/products/productContext";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
@@ -19,8 +18,6 @@ function RotateControls3D() {
const { toggleView } = useToggleView();
const { toolMode } = useToolMode();
const { activeModule } = useModuleStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { socket } = useSocketStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
@@ -302,7 +299,7 @@ function RotateControls3D() {
if (obj.userData.eventData) {
const eventData = eventStore.getState().getEventByModelUuid(obj.userData.modelUuid);
const productData = productStore.getState().getEventByModelUuid(selectedProduct.productUuid, obj.userData.modelUuid);
const productData = productStore.getState().getEventByModelUuid(productStore.getState().selectedProduct.productUuid, obj.userData.modelUuid);
if (eventData) {
eventStore.getState().updateEvent(obj.userData.modelUuid, {
@@ -312,13 +309,13 @@ function RotateControls3D() {
}
if (productData) {
const event = productStore.getState().updateEvent(selectedProduct.productUuid, obj.userData.modelUuid, {
const event = productStore.getState().updateEvent(productStore.getState().selectedProduct.productUuid, obj.userData.modelUuid, {
position: positionArray,
rotation: rotationArray,
});
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
updateBackend(productStore.getState().selectedProduct.productName, productStore.getState().selectedProduct.productUuid, projectId || "", event);
}
newFloorItem.eventData = eventData;
@@ -391,7 +388,7 @@ function RotateControls3D() {
setIsRotating(false);
setIsIndividualRotating(false);
clearSelection();
}, [rotatedObjects, eventStore, productStore, selectedProduct, updateBackend, projectId, updateAsset, organization, socket, selectedVersion, userId, initialPositions, initialRotations]);
}, [rotatedObjects, eventStore, productStore, updateBackend, projectId, updateAsset, organization, socket, selectedVersion, userId, initialPositions, initialRotations]);
const clearSelection = () => {
setPastedObjects([]);

View File

@@ -8,7 +8,6 @@ import useModuleStore from "../../../../../store/ui/useModuleStore";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import { useProductContext } from "../../../../simulation/products/productContext";
import { useContextActionStore, useSocketStore, useToggleView, useToolMode } from "../../../../../store/builder/store";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
import DuplicationControls3D from "./duplicationControls3D";
@@ -34,8 +33,6 @@ const SelectionControls3D: React.FC = () => {
const { removeAsset, getAssetById, selectedAssets, setSelectedAssets, movedObjects, rotatedObjects, copiedObjects, pastedObjects, duplicatedObjects, setPastedObjects, setDuplicatedObjects } = assetStore();
const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]);
const { selectedVersion } = versionStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { projectId } = useParams();
const isDragging = useRef(false);
@@ -206,7 +203,7 @@ const SelectionControls3D: React.FC = () => {
helper.dispose();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, rotatedObjects, activeModule, toolMode, selectedDecal, selectedWall, selectedAisle, selectedFloor, selectedFloorAsset, selectedWallAsset]);
}, [camera, controls, scene, toggleView, selectedAssets, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, rotatedObjects, activeModule, toolMode, selectedDecal, selectedWall, selectedAisle, selectedFloor, selectedFloorAsset, selectedWallAsset, productStore]);
useEffect(() => {
if (activeModule !== "builder" || (toolMode !== "cursor" && toolMode !== "Move-Asset" && toolMode !== "Rotate-Asset") || toggleView) {
@@ -294,7 +291,7 @@ const SelectionControls3D: React.FC = () => {
const updatedEvents = productStore.getState().deleteEvent(selectedMesh.uuid);
updatedEvents.forEach((event) => {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
updateBackend(productStore.getState().selectedProduct.productName, productStore.getState().selectedProduct.productUuid, projectId || "", event);
});
removeAsset(selectedMesh.uuid);

View File

@@ -3,7 +3,6 @@ import { useRef, useEffect, useState, useCallback } from "react";
import { useThree } from "@react-three/fiber";
import { TransformControls } from "@react-three/drei";
import { useSocketStore, useToolMode } from "../../../../../store/builder/store";
import { useProductContext } from "../../../../simulation/products/productContext";
import { useSceneContext } from "../../../sceneContext";
import { useParams } from "react-router-dom";
@@ -19,8 +18,6 @@ function TransformControls3D() {
const [visible, setVisible] = useState(false);
const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">("");
const { socket } = useSocketStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { assetStore, eventStore, productStore, undoRedo3DStore, versionStore } = useSceneContext();
const { push3D, subscribeUndoRedo } = undoRedo3DStore();
const { updateAsset, getAssetById, selectedAssets, setSelectedAssets } = assetStore();
@@ -93,7 +90,7 @@ function TransformControls3D() {
if (asset.eventData) {
const eventData = eventStore.getState().getEventByModelUuid(asset.modelUuid);
const productData = productStore.getState().getEventByModelUuid(selectedProduct.productUuid, asset.modelUuid);
const productData = productStore.getState().getEventByModelUuid(productStore.getState().selectedProduct.productUuid, asset.modelUuid);
if (eventData) {
eventStore.getState().updateEvent(asset.modelUuid, {
@@ -103,13 +100,13 @@ function TransformControls3D() {
}
if (productData) {
const event = productStore.getState().updateEvent(selectedProduct.productUuid, asset.modelUuid, {
const event = productStore.getState().updateEvent(productStore.getState().selectedProduct.productUuid, asset.modelUuid, {
position: [obj.position.x, obj.position.y, obj.position.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
});
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
updateBackend(productStore.getState().selectedProduct.productName, productStore.getState().selectedProduct.productUuid, projectId || "", event);
}
}
}
@@ -149,7 +146,7 @@ function TransformControls3D() {
socket.emit("v1:model-asset:add", data);
}
});
}, [selectedAssets, setSelectedAssets, getAssetById, updateAsset, eventStore, productStore, selectedProduct, updateBackend, projectId, organization, socket, selectedVersion, userId, push3D]);
}, [selectedAssets, setSelectedAssets, getAssetById, updateAsset, eventStore, productStore, updateBackend, projectId, organization, socket, selectedVersion, userId, push3D]);
useEffect(() => {
const temp = tempObjectRef.current;

View File

@@ -3,7 +3,6 @@ import { useParams } from "react-router-dom";
import { useThree } from "@react-three/fiber";
import { TransformControls } from "@react-three/drei";
import { useEffect, useRef, useState } from "react";
import { useProductContext } from "../../../simulation/products/productContext";
import { getUserData } from "../../../../functions/getUserData";
import { useSceneContext } from "../../sceneContext";
import { useObjectPosition, useObjectRotation, useActiveTool, useSocketStore } from "../../../../store/builder/store";
@@ -22,8 +21,6 @@ export default function TransformControl() {
const { setObjectRotation } = useObjectRotation();
const { activeTool } = useActiveTool();
const { socket } = useSocketStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { assetStore, eventStore, productStore, undoRedo3DStore, versionStore } = useSceneContext();
const { push3D } = undoRedo3DStore();
const { updateAsset, getAssetById } = assetStore();
@@ -53,7 +50,7 @@ export default function TransformControl() {
}
function handleMouseUp() {
if (!selectedProduct || !selectedFloorAsset) return;
if (!productStore.getState().selectedProduct || !selectedFloorAsset) return;
if (selectedFloorAsset) {
setObjectPosition(selectedFloorAsset.position);
setObjectRotation({
@@ -66,7 +63,7 @@ export default function TransformControl() {
if (asset) {
if (asset.eventData) {
const eventData = eventStore.getState().getEventByModelUuid(asset.modelUuid);
const productData = productStore.getState().getEventByModelUuid(selectedProduct.productUuid, asset.modelUuid);
const productData = productStore.getState().getEventByModelUuid(productStore.getState().selectedProduct.productUuid, asset.modelUuid);
if (eventData) {
eventStore.getState().updateEvent(asset.modelUuid, {
@@ -76,13 +73,13 @@ export default function TransformControl() {
}
if (productData) {
const event = productStore.getState().updateEvent(selectedProduct.productUuid, asset.modelUuid, {
const event = productStore.getState().updateEvent(productStore.getState().selectedProduct.productUuid, asset.modelUuid, {
position: [selectedFloorAsset.position.x, 0, selectedFloorAsset.position.z] as [number, number, number],
rotation: [selectedFloorAsset.rotation.x, selectedFloorAsset.rotation.y, selectedFloorAsset.rotation.z] as [number, number, number],
});
if (event) {
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
updateBackend(productStore.getState().selectedProduct.productName, productStore.getState().selectedProduct.productUuid, projectId || "", event);
}
}
}

View File

@@ -1,7 +1,6 @@
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import { useProductContext } from "../../../../simulation/products/productContext";
import { useSocketStore } from "../../../../../store/builder/store";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
@@ -11,29 +10,22 @@ import { deleteFloorAssetApi } from "../../../../../services/factoryBuilder/asse
function use3DRedoHandler() {
const { undoRedo3DStore, assetStore, productStore, eventStore, versionStore } = useSceneContext();
const { deleteEvent } = productStore();
const { deleteEvent, selectedProduct } = productStore();
const { addEvent, removeEvent } = eventStore();
const { updateAsset, removeAsset, addAsset } = assetStore();
const { redo3D, peekRedo3D } = undoRedo3DStore();
const { selectedVersion } = versionStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
const { socket } = useSocketStore();
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName: productName,
productUuid: productUuid,
projectId: projectId,
eventDatas: eventData,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
});
};
@@ -41,87 +33,104 @@ function use3DRedoHandler() {
const redoData = peekRedo3D();
if (!redoData) return;
if (redoData.type === 'Scene') {
if (redoData.type === "Scene") {
const { actions } = redoData;
actions.forEach(action => {
actions.forEach((action) => {
const { actionType } = action;
if ('asset' in action) {
if ("asset" in action) {
const asset = action.asset;
if (actionType === 'Asset-Add') {
if (actionType === "Asset-Add") {
handleAdd(asset);
} else if (actionType === 'Asset-Delete') {
} else if (actionType === "Asset-Delete") {
handleDelete(asset);
} else if (actionType === 'Asset-Update') {
} else if (actionType === "Asset-Update") {
handleUpdate(asset);
} else if (actionType === 'Asset-Copied') {
} else if (actionType === "Asset-Copied") {
handleCopy(asset);
} else if (actionType === 'Asset-Duplicated') {
} else if (actionType === "Asset-Duplicated") {
handleDuplicate(asset);
}
} else if ('assets' in action) {
} else if ("assets" in action) {
const assets = action.assets;
if (actionType === 'Assets-Add') {
if (actionType === "Assets-Add") {
assets.forEach(handleAdd);
} else if (actionType === 'Assets-Delete') {
} else if (actionType === "Assets-Delete") {
assets.forEach(handleDelete);
} else if (actionType === 'Assets-Update') {
} else if (actionType === "Assets-Update") {
assets.forEach(handleUpdate);
} else if (actionType === 'Assets-Copied') {
} else if (actionType === "Assets-Copied") {
assets.forEach(handleCopy);
} else if (actionType === 'Assets-Duplicated') {
} else if (actionType === "Assets-Duplicated") {
assets.forEach(handleDuplicate);
}
}
});
} else if (redoData.type === 'UI') {
} else if (redoData.type === "UI") {
// Handle UI actions if needed
}
redo3D();
};
const handleAdd = (asset: AssetData) => {
switch (asset.type) {
case 'Asset': addAssetToBackend(asset.assetData); break;
case 'WallAsset': addWallAssetToBackend(asset.assetData); break;
case "Asset":
addAssetToBackend(asset.assetData);
break;
case "WallAsset":
addWallAssetToBackend(asset.assetData);
break;
}
};
const handleDelete = (asset: AssetData) => {
switch (asset.type) {
case 'Asset': deleteAssetToBackend(asset.assetData); break;
case 'WallAsset': deleteWallAssetToBackend(asset.assetData); break;
}
case "Asset":
deleteAssetToBackend(asset.assetData);
break;
case "WallAsset":
deleteWallAssetToBackend(asset.assetData);
break;
}
};
const handleUpdate = (asset: AssetData) => {
if (!asset.newData) return;
switch (asset.type) {
case 'Asset': updateAssetToBackend(asset.newData.modelUuid, asset.newData); break;
case 'WallAsset': updateWallAssetToBackend(asset.newData.modelUuid, asset.newData); break;
}
case "Asset":
updateAssetToBackend(asset.newData.modelUuid, asset.newData);
break;
case "WallAsset":
updateWallAssetToBackend(asset.newData.modelUuid, asset.newData);
break;
}
};
const handleCopy = (asset: AssetData) => {
switch (asset.type) {
case 'Asset': copyAssetToBackend(asset.assetData); break;
case 'WallAsset': copyWallAssetToBackend(asset.assetData); break;
}
case "Asset":
copyAssetToBackend(asset.assetData);
break;
case "WallAsset":
copyWallAssetToBackend(asset.assetData);
break;
}
};
const handleDuplicate = (asset: AssetData) => {
switch (asset.type) {
case 'Asset': duplicateAssetToBackend(asset.assetData); break;
case 'WallAsset': duplicateWallAssetToBackend(asset.assetData); break;
case "Asset":
duplicateAssetToBackend(asset.assetData);
break;
case "WallAsset":
duplicateWallAssetToBackend(asset.assetData);
break;
}
}
};
const addAssetToBackend = (assetData: Asset) => {
addAsset(assetData);
@@ -137,9 +146,9 @@ function use3DRedoHandler() {
isVisible: true,
eventData: {},
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId,
userId
userId,
};
if (assetData.eventData) {
@@ -159,17 +168,16 @@ function use3DRedoHandler() {
isLocked: false,
isVisible: true,
eventData: data.eventData,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId: projectId,
});
} else {
// SOCKET
socket.emit("v1:model-asset:add", data);
}
}
}
};
const deleteAssetToBackend = (assetData: Asset) => {
if (!socket?.connected) {
@@ -178,11 +186,10 @@ function use3DRedoHandler() {
deleteFloorAssetApi({
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
versionId: selectedVersion?.versionId || '',
projectId: projectId || ''
versionId: selectedVersion?.versionId || "",
projectId: projectId || "",
});
} else {
// SOCKET
const data = {
@@ -191,27 +198,22 @@ function use3DRedoHandler() {
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
}
versionId: selectedVersion?.versionId || "",
projectId,
};
socket.emit('v1:model-asset:delete', data)
socket.emit("v1:model-asset:delete", data);
}
removeEvent(assetData.modelUuid);
const updatedEvents = deleteEvent(assetData.modelUuid);
updatedEvents.forEach((event) => {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
})
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
});
removeAsset(assetData.modelUuid);
}
};
const updateAssetToBackend = (modelUuid: string, updatedData: Asset) => {
updateAsset(modelUuid, updatedData);
@@ -226,9 +228,9 @@ function use3DRedoHandler() {
isLocked: false,
isVisible: true,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId,
userId
userId,
};
if (!socket?.connected) {
@@ -242,17 +244,16 @@ function use3DRedoHandler() {
rotation: { x: updatedData.rotation[0], y: updatedData.rotation[1], z: updatedData.rotation[2] },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId: projectId,
});
} else {
// SOCKET
socket.emit("v1:model-asset:add", data);
}
}
}
};
const copyAssetToBackend = (assetData: Asset) => {
addAsset(assetData);
@@ -268,9 +269,9 @@ function use3DRedoHandler() {
isVisible: true,
eventData: {},
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId,
userId
userId,
};
if (assetData.eventData) {
@@ -290,17 +291,16 @@ function use3DRedoHandler() {
isLocked: false,
isVisible: true,
eventData: data.eventData,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId: projectId,
});
} else {
// SOCKET
socket.emit("v1:model-asset:add", data);
}
}
}
};
const duplicateAssetToBackend = (assetData: Asset) => {
addAsset(assetData);
@@ -316,9 +316,9 @@ function use3DRedoHandler() {
isVisible: true,
eventData: {},
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId,
userId
userId,
};
if (assetData.eventData) {
@@ -338,37 +338,26 @@ function use3DRedoHandler() {
isLocked: false,
isVisible: true,
eventData: data.eventData,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId: projectId,
});
} else {
//SOCKET
socket.emit("v1:model-asset:add", data);
}
}
}
};
const addWallAssetToBackend = (assetData: WallAsset) => {
const addWallAssetToBackend = (assetData: WallAsset) => {};
}
const deleteWallAssetToBackend = (assetData: WallAsset) => {};
const deleteWallAssetToBackend = (assetData: WallAsset) => {
const updateWallAssetToBackend = (modelUuid: string, updatedData: WallAsset) => {};
}
const copyWallAssetToBackend = (assetData: WallAsset) => {};
const updateWallAssetToBackend = (modelUuid: string, updatedData: WallAsset) => {
}
const copyWallAssetToBackend = (assetData: WallAsset) => {
}
const duplicateWallAssetToBackend = (assetData: WallAsset) => {
}
const duplicateWallAssetToBackend = (assetData: WallAsset) => {};
return { handleRedo };
}

View File

@@ -1,7 +1,6 @@
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
import { useProductContext } from "../../../../simulation/products/productContext";
import { useSocketStore } from "../../../../../store/builder/store";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
@@ -11,29 +10,22 @@ import { deleteFloorAssetApi } from "../../../../../services/factoryBuilder/asse
function use3DUndoHandler() {
const { undoRedo3DStore, assetStore, productStore, eventStore, versionStore } = useSceneContext();
const { deleteEvent } = productStore();
const { deleteEvent, selectedProduct } = productStore();
const { addEvent, removeEvent } = eventStore();
const { updateAsset, removeAsset, addAsset } = assetStore();
const { undo3D, peekUndo3D } = undoRedo3DStore();
const { selectedVersion } = versionStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
const { socket } = useSocketStore();
const updateBackend = (
productName: string,
productUuid: string,
projectId: string,
eventData: EventsSchema
) => {
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName: productName,
productUuid: productUuid,
projectId: projectId,
eventDatas: eventData,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
});
};
@@ -41,86 +33,103 @@ function use3DUndoHandler() {
const unDoData = peekUndo3D();
if (!unDoData) return;
if (unDoData.type === 'Scene') {
if (unDoData.type === "Scene") {
const { actions } = unDoData;
actions.forEach(action => {
actions.forEach((action) => {
const { actionType } = action;
if ('asset' in action) {
if ("asset" in action) {
const asset = action.asset;
if (actionType === 'Asset-Add') {
if (actionType === "Asset-Add") {
handleDelete(asset);
} else if (actionType === 'Asset-Delete') {
} else if (actionType === "Asset-Delete") {
handleAdd(asset);
} else if (actionType === 'Asset-Update') {
} else if (actionType === "Asset-Update") {
handleUpdate(asset);
} else if (actionType === 'Asset-Copied') {
} else if (actionType === "Asset-Copied") {
handleCopy(asset);
} else if (actionType === 'Asset-Duplicated') {
} else if (actionType === "Asset-Duplicated") {
handleDuplicate(asset);
}
} else if ('assets' in action) {
} else if ("assets" in action) {
const assets = action.assets;
if (actionType === 'Assets-Add') {
if (actionType === "Assets-Add") {
assets.forEach(handleDelete);
} else if (actionType === 'Assets-Delete') {
} else if (actionType === "Assets-Delete") {
assets.forEach(handleAdd);
} else if (actionType === 'Assets-Update') {
} else if (actionType === "Assets-Update") {
assets.forEach(handleUpdate);
} else if (actionType === 'Assets-Copied') {
} else if (actionType === "Assets-Copied") {
assets.forEach(handleCopy);
} else if (actionType === 'Assets-Duplicated') {
} else if (actionType === "Assets-Duplicated") {
assets.forEach(handleDuplicate);
}
}
});
} else if (unDoData.type === 'UI') {
} else if (unDoData.type === "UI") {
// Handle UI actions if needed
}
undo3D();
};
const handleAdd = (asset: AssetData) => {
switch (asset.type) {
case 'Asset': addAssetToBackend(asset.assetData); break;
case 'WallAsset': addWallAssetToBackend(asset.assetData); break;
case "Asset":
addAssetToBackend(asset.assetData);
break;
case "WallAsset":
addWallAssetToBackend(asset.assetData);
break;
}
};
const handleDelete = (asset: AssetData) => {
switch (asset.type) {
case 'Asset': deleteAssetToBackend(asset.assetData); break;
case 'WallAsset': deleteWallAssetToBackend(asset.assetData); break;
}
case "Asset":
deleteAssetToBackend(asset.assetData);
break;
case "WallAsset":
deleteWallAssetToBackend(asset.assetData);
break;
}
};
const handleUpdate = (asset: AssetData) => {
switch (asset.type) {
case 'Asset': updateAssetToBackend(asset.assetData.modelUuid, asset.assetData); break;
case 'WallAsset': updateWallAssetToBackend(asset.assetData.modelUuid, asset.assetData); break;
}
case "Asset":
updateAssetToBackend(asset.assetData.modelUuid, asset.assetData);
break;
case "WallAsset":
updateWallAssetToBackend(asset.assetData.modelUuid, asset.assetData);
break;
}
};
const handleCopy = (asset: AssetData) => {
switch (asset.type) {
case 'Asset': copyAssetToBackend(asset.assetData); break;
case 'WallAsset': copyWallAssetToBackend(asset.assetData); break;
}
case "Asset":
copyAssetToBackend(asset.assetData);
break;
case "WallAsset":
copyWallAssetToBackend(asset.assetData);
break;
}
};
const handleDuplicate = (asset: AssetData) => {
switch (asset.type) {
case 'Asset': duplicateAssetToBackend(asset.assetData); break;
case 'WallAsset': duplicateWallAssetToBackend(asset.assetData); break;
case "Asset":
duplicateAssetToBackend(asset.assetData);
break;
case "WallAsset":
duplicateWallAssetToBackend(asset.assetData);
break;
}
}
};
const addAssetToBackend = (assetData: Asset) => {
addAsset(assetData);
@@ -136,9 +145,9 @@ function use3DUndoHandler() {
isVisible: true,
eventData: {},
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId,
userId
userId,
};
if (assetData.eventData) {
@@ -158,17 +167,16 @@ function use3DUndoHandler() {
isLocked: false,
isVisible: true,
eventData: data.eventData,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId: projectId,
});
} else {
// SOCKET
socket.emit("v1:model-asset:add", data);
}
}
}
};
const deleteAssetToBackend = (assetData: Asset) => {
if (!socket?.connected) {
@@ -177,11 +185,10 @@ function use3DUndoHandler() {
deleteFloorAssetApi({
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
versionId: selectedVersion?.versionId || '',
projectId: projectId || ''
versionId: selectedVersion?.versionId || "",
projectId: projectId || "",
});
} else {
// SOCKET
const data = {
@@ -190,27 +197,22 @@ function use3DUndoHandler() {
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
}
versionId: selectedVersion?.versionId || "",
projectId,
};
socket.emit('v1:model-asset:delete', data)
socket.emit("v1:model-asset:delete", data);
}
removeEvent(assetData.modelUuid);
const updatedEvents = deleteEvent(assetData.modelUuid);
updatedEvents.forEach((event) => {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
})
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
});
removeAsset(assetData.modelUuid);
}
};
const updateAssetToBackend = (modelUuid: string, updatedData: Asset) => {
updateAsset(modelUuid, updatedData);
@@ -225,9 +227,9 @@ function use3DUndoHandler() {
isLocked: false,
isVisible: true,
socketId: socket?.id,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId,
userId
userId,
};
if (!socket?.connected) {
@@ -241,17 +243,16 @@ function use3DUndoHandler() {
rotation: { x: updatedData.rotation[0], y: updatedData.rotation[1], z: updatedData.rotation[2] },
isLocked: false,
isVisible: true,
versionId: selectedVersion?.versionId || '',
versionId: selectedVersion?.versionId || "",
projectId: projectId,
});
} else {
// SOCKET
socket.emit("v1:model-asset:add", data);
}
}
}
};
const copyAssetToBackend = (assetData: Asset) => {
if (!socket?.connected) {
@@ -260,11 +261,10 @@ function use3DUndoHandler() {
deleteFloorAssetApi({
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
versionId: selectedVersion?.versionId || '',
projectId: projectId || ''
versionId: selectedVersion?.versionId || "",
projectId: projectId || "",
});
} else {
// SOCKET
const data = {
@@ -273,27 +273,22 @@ function use3DUndoHandler() {
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
}
versionId: selectedVersion?.versionId || "",
projectId,
};
socket.emit('v1:model-asset:delete', data)
socket.emit("v1:model-asset:delete", data);
}
removeEvent(assetData.modelUuid);
const updatedEvents = deleteEvent(assetData.modelUuid);
updatedEvents.forEach((event) => {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
})
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
});
removeAsset(assetData.modelUuid);
}
};
const duplicateAssetToBackend = (assetData: Asset) => {
if (!socket?.connected) {
@@ -302,11 +297,10 @@ function use3DUndoHandler() {
deleteFloorAssetApi({
modelUuid: assetData.modelUuid,
modelName: assetData.modelName,
versionId: selectedVersion?.versionId || '',
projectId: projectId || ''
versionId: selectedVersion?.versionId || "",
projectId: projectId || "",
});
} else {
// SOCKET
const data = {
@@ -315,47 +309,32 @@ function use3DUndoHandler() {
modelName: assetData.modelName,
socketId: socket.id,
userId,
versionId: selectedVersion?.versionId || '',
projectId
}
versionId: selectedVersion?.versionId || "",
projectId,
};
socket.emit('v1:model-asset:delete', data)
socket.emit("v1:model-asset:delete", data);
}
removeEvent(assetData.modelUuid);
const updatedEvents = deleteEvent(assetData.modelUuid);
updatedEvents.forEach((event) => {
updateBackend(
selectedProduct.productName,
selectedProduct.productUuid,
projectId || '',
event
);
})
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
});
removeAsset(assetData.modelUuid);
}
};
const addWallAssetToBackend = (assetData: WallAsset) => {
const addWallAssetToBackend = (assetData: WallAsset) => {};
}
const deleteWallAssetToBackend = (assetData: WallAsset) => {};
const deleteWallAssetToBackend = (assetData: WallAsset) => {
const updateWallAssetToBackend = (modelUuid: string, updatedData: WallAsset) => {};
}
const copyWallAssetToBackend = (assetData: WallAsset) => {};
const updateWallAssetToBackend = (modelUuid: string, updatedData: WallAsset) => {
}
const copyWallAssetToBackend = (assetData: WallAsset) => {
}
const duplicateWallAssetToBackend = (assetData: WallAsset) => {
}
const duplicateWallAssetToBackend = (assetData: WallAsset) => {};
return { handleUndo };
}

View File

@@ -1,9 +1,8 @@
import { useCallback, useEffect, useState } from "react";
import * as THREE from 'three';
import * as THREE from "three";
import { useFrame } from "@react-three/fiber";
import { usePlayButtonStore, useAnimationPlaySpeed, usePauseButtonStore, useResetButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
interface SpawnInstance {
lastSpawnTime: number | null;
@@ -24,28 +23,32 @@ export function useSpawnHandler() {
const { materialStore, conveyorStore, productStore } = useSceneContext();
const { addMaterial } = materialStore();
const { getConveyorById } = conveyorStore();
const { getModelUuidByActionUuid, getPointUuidByActionUuid } = productStore();
const { getModelUuidByActionUuid, getPointUuidByActionUuid, selectedProduct } = productStore();
const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore();
const { speed } = useAnimationPlaySpeed();
const { isReset } = useResetButtonStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const [activeSpawns, setActiveSpawns] = useState<Map<string, SpawnInstance>>(new Map());
const getConveyorPausedState = useCallback((action: ConveyorAction) => {
const getConveyorPausedState = useCallback(
(action: ConveyorAction) => {
const modelUuid = getModelUuidByActionUuid(selectedProduct.productUuid, action.actionUuid);
if (!modelUuid) return false;
const conveyor = getConveyorById(modelUuid);
if (!conveyor) return false;
return conveyor.isPaused;
}, [getConveyorById, getModelUuidByActionUuid, selectedProduct.productUuid]);
},
[getConveyorById, getModelUuidByActionUuid, selectedProduct.productUuid]
);
const shouldPauseSpawn = useCallback((action: ConveyorAction) => {
const shouldPauseSpawn = useCallback(
(action: ConveyorAction) => {
return isPaused || getConveyorPausedState(action);
}, [isPaused, getConveyorPausedState]);
},
[isPaused, getConveyorPausedState]
);
const clearAllSpawns = useCallback(() => {
setActiveSpawns(new Map());
@@ -59,9 +62,10 @@ export function useSpawnHandler() {
const spawnLogStatus = (materialUuid: string, status: string) => {
echo.info(`${materialUuid}, ${status}`);
}
};
const createNewMaterial = useCallback((materialType: string, action: ConveyorAction) => {
const createNewMaterial = useCallback(
(materialType: string, action: ConveyorAction) => {
const modelUuid = getModelUuidByActionUuid(selectedProduct.productUuid, action.actionUuid);
const pointUuid = getPointUuidByActionUuid(selectedProduct.productUuid, action.actionUuid);
if (!modelUuid || !pointUuid) return;
@@ -79,37 +83,36 @@ export function useSpawnHandler() {
current: {
modelUuid: modelUuid,
pointUuid: pointUuid,
actionUuid: action.actionUuid
actionUuid: action.actionUuid,
},
};
if (action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid &&
action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid &&
action.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid
) {
if (action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid && action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid && action.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid) {
newMaterial.next = {
modelUuid: action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid,
pointUuid: action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid,
}
};
}
addMaterial(newMaterial);
return newMaterial;
}, [addMaterial, getModelUuidByActionUuid, getPointUuidByActionUuid, selectedProduct.productUuid]);
},
[addMaterial, getModelUuidByActionUuid, getPointUuidByActionUuid, selectedProduct.productUuid]
);
useFrame(() => {
const currentTime = performance.now();
const completedActions: string[] = [];
let hasChanges = false;
activeSpawns.forEach(spawn => {
activeSpawns.forEach((spawn) => {
const isPausedNow = shouldPauseSpawn(spawn.params.action);
if (isPausedNow && !spawn.isPaused) {
if (spawn.lastSpawnTime === null) {
spawn.remainingTime = Math.max(0, (spawn.params.intervalMs / speed) - (currentTime - spawn.startTime));
spawn.remainingTime = Math.max(0, spawn.params.intervalMs / speed - (currentTime - spawn.startTime));
} else {
spawn.remainingTime = Math.max(0, (spawn.params.intervalMs / speed) - (currentTime - spawn.lastSpawnTime));
spawn.remainingTime = Math.max(0, spawn.params.intervalMs / speed - (currentTime - spawn.lastSpawnTime));
}
spawn.pauseStartTime = currentTime;
spawn.isPaused = true;
@@ -177,10 +180,10 @@ export function useSpawnHandler() {
}
if (hasChanges || completedActions.length > 0) {
setActiveSpawns(prevSpawns => {
setActiveSpawns((prevSpawns) => {
const newSpawns = new Map(prevSpawns);
completedActions.forEach(actionUuid => {
completedActions.forEach((actionUuid) => {
newSpawns.delete(actionUuid);
});
@@ -190,12 +193,12 @@ export function useSpawnHandler() {
});
const handleSpawn = useCallback((action: ConveyorAction) => {
if (!action || action.actionType !== 'spawn') return;
if (!action || action.actionType !== "spawn") return;
const { material, spawnInterval = 0, spawnCount = 1, actionUuid } = action;
const intervalMs = spawnInterval * 1000;
setActiveSpawns(prevSpawns => {
setActiveSpawns((prevSpawns) => {
const newSpawns = new Map(prevSpawns);
if (newSpawns.has(actionUuid)) {
@@ -210,11 +213,11 @@ export function useSpawnHandler() {
material,
intervalMs,
totalCount: spawnCount,
action: action
action: action,
},
pauseStartTime: 0,
remainingTime: 0,
isPaused: false
isPaused: false,
});
return newSpawns;
@@ -229,6 +232,6 @@ export function useSpawnHandler() {
return {
handleSpawn,
clearAllSpawns
clearAllSpawns,
};
}

View File

@@ -1,21 +1,19 @@
import { useCallback } from "react";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function usePickAndDropHandler() {
const { materialStore, craneStore, productStore } = useSceneContext();
const { getMaterialById } = materialStore();
const { getModelUuidByActionUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getModelUuidByActionUuid, selectedProduct } = productStore();
const { incrementCraneLoad, addCurrentMaterial, addCurrentAction } = craneStore();
const pickAndDropLogStatus = (materialUuid: string, status: string) => {
echo.info(`${materialUuid}, ${status}`);
}
};
const handlePickAndDrop = useCallback((action: CraneAction, materialId?: string) => {
if (!action || action.actionType !== 'pickAndDrop' || !materialId) return;
const handlePickAndDrop = useCallback(
(action: CraneAction, materialId?: string) => {
if (!action || action.actionType !== "pickAndDrop" || !materialId) return;
const material = getMaterialById(materialId);
if (!material) return;
@@ -28,8 +26,9 @@ export function usePickAndDropHandler() {
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
pickAndDropLogStatus(material.materialName, `performing pickAndDrop action`);
}, [getMaterialById]);
},
[getMaterialById]
);
return {
handlePickAndDrop,

View File

@@ -1,21 +1,19 @@
import { useCallback } from "react";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function useManufacturerHandler() {
const { materialStore, humanStore, productStore } = useSceneContext();
const { getMaterialById } = materialStore();
const { getModelUuidByActionUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getModelUuidByActionUuid, selectedProduct } = productStore();
const { incrementHumanLoad, addCurrentMaterial, addCurrentAction } = humanStore();
const manufactureLogStatus = (materialUuid: string, status: string) => {
echo.info(`${materialUuid}, ${status}`);
}
};
const handleManufacturer = useCallback((action: HumanAction, materialId?: string) => {
if (!action || action.actionType !== 'manufacturer' || !materialId) return;
const handleManufacturer = useCallback(
(action: HumanAction, materialId?: string) => {
if (!action || action.actionType !== "manufacturer" || !materialId) return;
const material = getMaterialById(materialId);
if (!material) return;
@@ -28,8 +26,9 @@ export function useManufacturerHandler() {
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
manufactureLogStatus(material.materialName, `performing manufacturer action`);
}, [getMaterialById]);
},
[getMaterialById]
);
return {
handleManufacturer,

View File

@@ -1,21 +1,19 @@
import { useCallback } from "react";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function useWorkerHandler() {
const { materialStore, humanStore, productStore } = useSceneContext();
const { getMaterialById } = materialStore();
const { getModelUuidByActionUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getModelUuidByActionUuid, selectedProduct } = productStore();
const { incrementHumanLoad, addCurrentMaterial, addCurrentAction } = humanStore();
const workerLogStatus = (materialUuid: string, status: string) => {
echo.info(`${materialUuid}, ${status}`);
}
};
const handleWorker = useCallback((action: HumanAction, materialId?: string) => {
if (!action || action.actionType !== 'worker' || !materialId) return;
const handleWorker = useCallback(
(action: HumanAction, materialId?: string) => {
if (!action || action.actionType !== "worker" || !materialId) return;
const material = getMaterialById(materialId);
if (!material) return;
@@ -28,8 +26,9 @@ export function useWorkerHandler() {
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
workerLogStatus(material.materialName, `performing worker action`);
}, [getMaterialById]);
},
[getMaterialById]
);
return {
handleWorker,

View File

@@ -1,21 +1,19 @@
import { useCallback } from "react";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function useProcessHandler() {
const { materialStore, machineStore, productStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { getMaterialById, setMaterial } = materialStore();
const { addCurrentAction } = machineStore();
const { getModelUuidByActionUuid } = productStore();
const { selectedProduct } = selectedProductStore();
const { getModelUuidByActionUuid, selectedProduct } = productStore();
const processLogStatus = (materialUuid: string, status: string) => {
echo.log(`${materialUuid}, ${status}`);
}
};
const handleProcess = useCallback((action: MachineAction, materialId?: string) => {
if (!action || action.actionType !== 'process' || !materialId) return;
const handleProcess = useCallback(
(action: MachineAction, materialId?: string) => {
if (!action || action.actionType !== "process" || !materialId) return;
const { swapMaterial: newMaterialType } = action;
@@ -31,10 +29,11 @@ export function useProcessHandler() {
processLogStatus(material.materialName, `Swapped to ${newMaterialType}`);
processLogStatus(material.materialName, `starts Process action`);
}, [getMaterialById]);
},
[getMaterialById]
);
return {
handleProcess
handleProcess,
};
}

View File

@@ -1,21 +1,19 @@
import { useCallback } from "react";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function usePickAndPlaceHandler() {
const { materialStore, armBotStore, productStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { getMaterialById } = materialStore();
const { addCurrentAction } = armBotStore();
const { getModelUuidByActionUuid } = productStore();
const { selectedProduct } = selectedProductStore();
const { getModelUuidByActionUuid, selectedProduct } = productStore();
const pickAndPlaceLogStatus = (materialUuid: string, status: string) => {
echo.warn(`${materialUuid}, ${status}`);
}
};
const handlePickAndPlace = useCallback((action: RoboticArmAction, materialId?: string) => {
if (!action || action.actionType !== 'pickAndPlace' || !materialId) return;
const handlePickAndPlace = useCallback(
(action: RoboticArmAction, materialId?: string) => {
if (!action || action.actionType !== "pickAndPlace" || !materialId) return;
const material = getMaterialById(materialId);
if (!material) return;
@@ -24,16 +22,12 @@ export function usePickAndPlaceHandler() {
if (!modelUuid) return;
addCurrentAction(
modelUuid,
action.actionUuid,
material.materialType,
material.materialId
);
addCurrentAction(modelUuid, action.actionUuid, material.materialType, material.materialId);
pickAndPlaceLogStatus(material.materialName, `is going to be picked by armBot ${modelUuid}`);
}, [getMaterialById, getModelUuidByActionUuid, selectedProduct.productUuid, addCurrentAction]);
},
[getMaterialById, getModelUuidByActionUuid, selectedProduct.productUuid, addCurrentAction]
);
return {
handlePickAndPlace,

View File

@@ -2,21 +2,18 @@ import { useCallback, useState, useEffect, useRef } from "react";
import { useFrame } from "@react-three/fiber";
import { usePlayButtonStore, usePauseButtonStore, useResetButtonStore, useAnimationPlaySpeed } from "../../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
import { useHumanEventManager } from "../../../human/eventManager/useHumanEventManager";
export function useRetrieveHandler() {
const { materialStore, armBotStore, machineStore, vehicleStore, storageUnitStore, conveyorStore, craneStore, productStore, humanStore, assetStore, humanEventManagerRef } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { addMaterial } = materialStore();
const { getModelUuidByActionUuid, getPointUuidByActionUuid, getEventByModelUuid, getActionByUuid } = productStore();
const { getModelUuidByActionUuid, getPointUuidByActionUuid, getEventByModelUuid, getActionByUuid, selectedProduct } = productStore();
const { getStorageUnitById, getLastMaterial, updateCurrentLoad, removeLastMaterial } = storageUnitStore();
const { getVehicleById, incrementVehicleLoad, addCurrentMaterial } = vehicleStore();
const { getConveyorById } = conveyorStore();
const { getHumanById, incrementHumanLoad, addCurrentMaterial: addCurrentMaterialToHuman } = humanStore();
const { getCraneById, incrementCraneLoad, addCurrentMaterial: addCurrentMaterialToCrane, addCurrentAction: addCurrentActionToCrane } = craneStore();
const { getAssetById, setCurrentAnimation } = assetStore();
const { selectedProduct } = selectedProductStore();
const { getArmBotById, addCurrentAction } = armBotStore();
const { getMachineById } = machineStore();
const { isPlaying } = usePlayButtonStore();
@@ -25,7 +22,7 @@ export function useRetrieveHandler() {
const { isReset } = useResetButtonStore();
const { addHumanToMonitor } = useHumanEventManager();
const [activeRetrievals, setActiveRetrievals] = useState<Map<string, { action: StorageAction, isProcessing: boolean, lastCheckTime: number }>>(new Map());
const [activeRetrievals, setActiveRetrievals] = useState<Map<string, { action: StorageAction; isProcessing: boolean; lastCheckTime: number }>>(new Map());
const retrievalTimeRef = useRef<Map<string, number>>(new Map());
const retrievalCountRef = useRef<Map<string, number>>(new Map());
const monitoredHumansRef = useRef<Set<string>>(new Set());
@@ -36,9 +33,10 @@ export function useRetrieveHandler() {
const retrieveLogStatus = (materialUuid: string, status: string) => {
echo.info(`${materialUuid}, ${status}`);
}
};
const createNewMaterial = useCallback((materialId: string, materialType: string, action: StorageAction, visible: boolean = false) => {
const createNewMaterial = useCallback(
(materialId: string, materialType: string, action: StorageAction, visible: boolean = false) => {
const modelUuid = getModelUuidByActionUuid(selectedProduct.productUuid, action.actionUuid);
const pointUuid = getPointUuidByActionUuid(selectedProduct.productUuid, action.actionUuid);
if (!modelUuid || !pointUuid) return null;
@@ -56,18 +54,20 @@ export function useRetrieveHandler() {
previous: {
modelUuid: modelUuid,
pointUuid: pointUuid,
actionUuid: action.actionUuid
actionUuid: action.actionUuid,
},
current: {
modelUuid: modelUuid,
pointUuid: pointUuid,
actionUuid: action.actionUuid
actionUuid: action.actionUuid,
},
};
addMaterial(newMaterial);
return newMaterial;
}, [addMaterial, getModelUuidByActionUuid, getPointUuidByActionUuid, selectedProduct.productUuid]);
},
[addMaterial, getModelUuidByActionUuid, getPointUuidByActionUuid, selectedProduct.productUuid]
);
useEffect(() => {
if (isPlaying && !initialDelayComplete) {
@@ -102,9 +102,7 @@ export function useRetrieveHandler() {
activeRetrievals.forEach((retrieval, actionUuid) => {
if (retrieval.isProcessing) return;
const storageUnit = getStorageUnitById(
getModelUuidByActionUuid(selectedProduct.productUuid, retrieval.action.actionUuid) ?? ''
);
const storageUnit = getStorageUnitById(getModelUuidByActionUuid(selectedProduct.productUuid, retrieval.action.actionUuid) ?? "");
if (!storageUnit) {
completedActions.push(actionUuid);
@@ -120,18 +118,15 @@ export function useRetrieveHandler() {
return;
}
const triggeredModel = getEventByModelUuid(
selectedProduct.productUuid,
retrieval.action.triggers[0]?.triggeredAsset.triggeredModel.modelUuid
);
const triggeredModel = getEventByModelUuid(selectedProduct.productUuid, retrieval.action.triggers[0]?.triggeredAsset.triggeredModel.modelUuid);
if (!triggeredModel) return;
let isIdle = false;
if (triggeredModel.type === 'roboticArm') {
if (triggeredModel.type === "roboticArm") {
const armBot = getArmBotById(triggeredModel.modelUuid);
isIdle = (armBot && !armBot.isActive && armBot.state === 'idle' && !armBot.currentAction) || false;
isIdle = (armBot && !armBot.isActive && armBot.state === "idle" && !armBot.currentAction) || false;
if (!armBot) return;
if (!retrievalTimeRef.current.has(actionUuid) && isIdle) {
@@ -143,73 +138,49 @@ export function useRetrieveHandler() {
const minIdleTimeBeforeFirstRetrieval = 5000 / speed;
const minDelayBetweenRetrievals = 5000 / speed;
const canProceedFirstRetrieval = idleStartTime !== undefined &&
(currentTime - idleStartTime) >= minIdleTimeBeforeFirstRetrieval;
const canProceedFirstRetrieval = idleStartTime !== undefined && currentTime - idleStartTime >= minIdleTimeBeforeFirstRetrieval;
const lastRetrievalTime = retrievalTimeRef.current.get(`${actionUuid}_last`) ?? null;
const canProceedSubsequent = lastRetrievalTime === null ||
(currentTime - lastRetrievalTime) >= minDelayBetweenRetrievals;
const canProceedSubsequent = lastRetrievalTime === null || currentTime - lastRetrievalTime >= minDelayBetweenRetrievals;
const canProceed = lastRetrievalTime === null ? canProceedFirstRetrieval : canProceedSubsequent;
if (isIdle && canProceed) {
setActiveRetrievals(prev => {
setActiveRetrievals((prev) => {
const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, {
...retrieval,
isProcessing: true,
lastCheckTime: currentTime
lastCheckTime: currentTime,
});
return newRetrievals;
});
const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) {
if (retrieval.action.triggers[0]?.triggeredAsset.triggeredAction?.actionUuid) {
const action = getActionByUuid(selectedProduct.productUuid, retrieval.action.triggers[0]?.triggeredAsset.triggeredAction.actionUuid);
const storageAction = getActionByUuid(selectedProduct.productUuid, actionUuid);
if (action && action.triggers.length > 0 && action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid) {
const model = getEventByModelUuid(selectedProduct.productUuid, action?.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
const model = getEventByModelUuid(selectedProduct.productUuid, action?.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || "");
if (model && storageAction) {
if (model.type === 'vehicle') {
if (model.type === "vehicle") {
const vehicle = getVehicleById(model.modelUuid);
if (vehicle && !vehicle.isActive && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
storageAction as StorageAction
);
if (vehicle && !vehicle.isActive && vehicle.state === "idle" && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
const material = createNewMaterial(lastMaterial.materialId, lastMaterial.materialType, storageAction as StorageAction);
if (material) {
addCurrentAction(
triggeredModel.modelUuid,
retrieval.action.triggers[0]?.triggeredAsset.triggeredAction?.actionUuid ?? '',
material.materialType,
material.materialId
);
addCurrentAction(triggeredModel.modelUuid, retrieval.action.triggers[0]?.triggeredAsset.triggeredAction?.actionUuid ?? "", material.materialType, material.materialId);
retrieveLogStatus(material.materialName, `is being picked by ${armBot?.modelName}`);
}
}
} else {
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
storageAction as StorageAction
);
const material = createNewMaterial(lastMaterial.materialId, lastMaterial.materialType, storageAction as StorageAction);
if (material) {
addCurrentAction(
triggeredModel.modelUuid,
retrieval.action.triggers[0]?.triggeredAsset.triggeredAction?.actionUuid ?? '',
material.materialType,
material.materialId
);
addCurrentAction(triggeredModel.modelUuid, retrieval.action.triggers[0]?.triggeredAsset.triggeredAction?.actionUuid ?? "", material.materialType, material.materialId);
retrieveLogStatus(material.materialName, `is being picked by ${armBot?.modelName}`);
}
}
setActiveRetrievals(prev => {
setActiveRetrievals((prev) => {
const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, {
...retrieval,
@@ -220,19 +191,16 @@ export function useRetrieveHandler() {
});
retrievalTimeRef.current.set(actionUuid, currentTime);
}
}
}
}
} else if (!isIdle) {
retrievalTimeRef.current.delete(actionUuid);
}
} else if (triggeredModel.type === 'vehicle') {
} else if (triggeredModel.type === "vehicle") {
const vehicle = getVehicleById(triggeredModel.modelUuid);
isIdle = (vehicle && !vehicle.isActive && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) || false;
isIdle = (vehicle && !vehicle.isActive && vehicle.state === "idle" && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) || false;
if (!vehicle) return;
@@ -248,21 +216,19 @@ export function useRetrieveHandler() {
const idleStartTime = retrievalTimeRef.current.get(actionUuid);
const lastRetrievalTime = retrievalTimeRef.current.get(`${actionUuid}_last`) ?? null;
const canProceedFirstRetrieval = idleStartTime !== undefined &&
(currentTime - idleStartTime) >= minIdleTimeBeforeFirstRetrieval;
const canProceedFirstRetrieval = idleStartTime !== undefined && currentTime - idleStartTime >= minIdleTimeBeforeFirstRetrieval;
const canProceedSubsequent = lastRetrievalTime === null ||
(currentTime - lastRetrievalTime) >= minDelayBetweenRetrievals;
const canProceedSubsequent = lastRetrievalTime === null || currentTime - lastRetrievalTime >= minDelayBetweenRetrievals;
const canProceed = lastRetrievalTime === null ? canProceedFirstRetrieval : canProceedSubsequent;
if (isIdle && canProceed) {
setActiveRetrievals(prev => {
setActiveRetrievals((prev) => {
const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, {
...retrieval,
isProcessing: true,
lastCheckTime: currentTime
lastCheckTime: currentTime,
});
return newRetrievals;
});
@@ -270,16 +236,9 @@ export function useRetrieveHandler() {
const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) {
if (vehicle?.currentLoad < vehicle.point.action.loadCapacity) {
const triggeredAction = getActionByUuid(
selectedProduct.productUuid,
retrieval.action.triggers[0]?.triggeredAsset.triggeredAction?.actionUuid || ''
);
const triggeredAction = getActionByUuid(selectedProduct.productUuid, retrieval.action.triggers[0]?.triggeredAsset.triggeredAction?.actionUuid || "");
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
triggeredAction as StorageAction
);
const material = createNewMaterial(lastMaterial.materialId, lastMaterial.materialType, triggeredAction as StorageAction);
if (material) {
removeLastMaterial(storageUnit.modelUuid);
@@ -291,7 +250,7 @@ export function useRetrieveHandler() {
}
}
setActiveRetrievals(prev => {
setActiveRetrievals((prev) => {
const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, {
...retrieval,
@@ -307,12 +266,12 @@ export function useRetrieveHandler() {
retrievalTimeRef.current.delete(actionUuid);
retrievalTimeRef.current.delete(`${actionUuid}_last`);
}
} else if (triggeredModel.type === 'human') {
} else if (triggeredModel.type === "human") {
const human = getHumanById(triggeredModel.modelUuid);
const humanAsset = getAssetById(triggeredModel.modelUuid);
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || "");
if (!action || action.actionType !== 'worker') return;
if (!action || action.actionType !== "worker") return;
const currentCount = retrievalCountRef.current.get(actionUuid) ?? 0;
@@ -322,26 +281,20 @@ export function useRetrieveHandler() {
return;
}
if (human && !human.isScheduled && human.state === 'idle' && human.currentLoad < action.loadCapacity) {
const triggeredModel = action.triggers[0]?.triggeredAsset?.triggeredModel?.modelUuid
? getEventByModelUuid(selectedProduct.productUuid, action.triggers[0].triggeredAsset.triggeredModel.modelUuid)
: null;
if (human && !human.isScheduled && human.state === "idle" && human.currentLoad < action.loadCapacity) {
const triggeredModel = action.triggers[0]?.triggeredAsset?.triggeredModel?.modelUuid ? getEventByModelUuid(selectedProduct.productUuid, action.triggers[0].triggeredAsset.triggeredModel.modelUuid) : null;
const storageAction = getActionByUuid(selectedProduct.productUuid, actionUuid);
if (triggeredModel?.type === 'vehicle') {
if (triggeredModel?.type === "vehicle") {
const model = getVehicleById(triggeredModel.modelUuid);
if (model && !model.isActive && model.state === 'idle' && model.isPicking && model.currentLoad < model.point.action.loadCapacity) {
if (humanAsset?.animationState?.current === 'idle') {
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
} else if (humanAsset?.animationState?.current === 'pickup' && humanAsset.animationState.isCompleted) {
if (model && !model.isActive && model.state === "idle" && model.isPicking && model.currentLoad < model.point.action.loadCapacity) {
if (humanAsset?.animationState?.current === "idle") {
setCurrentAnimation(human.modelUuid, "pickup", true, false, false);
} else if (humanAsset?.animationState?.current === "pickup" && humanAsset.animationState.isCompleted) {
const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) {
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
storageAction as StorageAction
);
const material = createNewMaterial(lastMaterial.materialId, lastMaterial.materialType, storageAction as StorageAction);
if (material) {
removeLastMaterial(storageUnit.modelUuid);
updateCurrentLoad(storageUnit.modelUuid, -1);
@@ -355,19 +308,15 @@ export function useRetrieveHandler() {
}
return;
}
} else if (triggeredModel?.type === 'roboticArm') {
} else if (triggeredModel?.type === "roboticArm") {
const armBot = getArmBotById(triggeredModel.modelUuid);
if (armBot && !armBot.isActive && armBot.state === 'idle' && !armBot.currentAction) {
if (humanAsset?.animationState?.current === 'idle') {
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
} else if (humanAsset?.animationState?.current === 'pickup' && humanAsset.animationState.isCompleted) {
if (armBot && !armBot.isActive && armBot.state === "idle" && !armBot.currentAction) {
if (humanAsset?.animationState?.current === "idle") {
setCurrentAnimation(human.modelUuid, "pickup", true, false, false);
} else if (humanAsset?.animationState?.current === "pickup" && humanAsset.animationState.isCompleted) {
const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) {
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
storageAction as StorageAction
);
const material = createNewMaterial(lastMaterial.materialId, lastMaterial.materialType, storageAction as StorageAction);
if (material) {
removeLastMaterial(storageUnit.modelUuid);
updateCurrentLoad(storageUnit.modelUuid, -1);
@@ -381,19 +330,15 @@ export function useRetrieveHandler() {
}
return;
}
} else if (triggeredModel?.type === 'transfer') {
} else if (triggeredModel?.type === "transfer") {
const model = getConveyorById(triggeredModel.modelUuid);
if (model && !model.isPaused) {
if (humanAsset?.animationState?.current === 'idle') {
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
} else if (humanAsset?.animationState?.current === 'pickup' && humanAsset.animationState.isCompleted) {
if (humanAsset?.animationState?.current === "idle") {
setCurrentAnimation(human.modelUuid, "pickup", true, false, false);
} else if (humanAsset?.animationState?.current === "pickup" && humanAsset.animationState.isCompleted) {
const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) {
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
storageAction as StorageAction
);
const material = createNewMaterial(lastMaterial.materialId, lastMaterial.materialType, storageAction as StorageAction);
if (material) {
removeLastMaterial(storageUnit.modelUuid);
updateCurrentLoad(storageUnit.modelUuid, -1);
@@ -407,25 +352,25 @@ export function useRetrieveHandler() {
}
return;
}
} else if (triggeredModel?.type === 'machine') {
} else if (triggeredModel?.type === "machine") {
const machine = getMachineById(triggeredModel.modelUuid);
if (machine && !machine.isActive && machine.state === 'idle' && !machine.currentAction) {
if (machine && !machine.isActive && machine.state === "idle" && !machine.currentAction) {
if (!monitoredHumansRef.current.has(human.modelUuid)) {
addHumanToMonitor(human.modelUuid, () => {
if (humanAsset?.animationState?.current === 'idle') {
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
addHumanToMonitor(
human.modelUuid,
() => {
if (humanAsset?.animationState?.current === "idle") {
setCurrentAnimation(human.modelUuid, "pickup", true, false, false);
}
}, action.actionUuid);
},
action.actionUuid
);
}
monitoredHumansRef.current.add(human.modelUuid);
if (humanAsset?.animationState?.current === 'pickup' && humanAsset.animationState.isCompleted) {
if (humanAsset?.animationState?.current === "pickup" && humanAsset.animationState.isCompleted) {
const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) {
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
storageAction as StorageAction
);
const material = createNewMaterial(lastMaterial.materialId, lastMaterial.materialType, storageAction as StorageAction);
if (material) {
removeLastMaterial(storageUnit.modelUuid);
updateCurrentLoad(storageUnit.modelUuid, -1);
@@ -439,14 +384,10 @@ export function useRetrieveHandler() {
}
return;
}
} else if (triggeredModel?.type === 'storageUnit') {
} else if (triggeredModel?.type === "storageUnit") {
const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) {
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
storageAction as StorageAction
);
const material = createNewMaterial(lastMaterial.materialId, lastMaterial.materialType, storageAction as StorageAction);
if (material) {
removeLastMaterial(storageUnit.modelUuid);
updateCurrentLoad(storageUnit.modelUuid, -1);
@@ -459,49 +400,46 @@ export function useRetrieveHandler() {
}
}
}
} else if (triggeredModel?.type === 'crane') {
} else if (triggeredModel?.type === "crane") {
const crane = getCraneById(triggeredModel.modelUuid);
const action = getActionByUuid(selectedProduct.productUuid, crane?.currentAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, crane?.currentAction?.actionUuid || "");
const currentCount = retrievalCountRef.current.get(actionUuid) ?? 0;
if (!crane) return;
const hasLock = cranePickupLockRef.current.get(crane.modelUuid) || false;
if (action && action.actionType === 'pickAndDrop' && !hasLock && !crane.isCarrying && !crane.isActive && crane.currentLoad < (action?.maxPickUpCount || 0)) {
if (action && action.actionType === "pickAndDrop" && !hasLock && !crane.isCarrying && !crane.isActive && crane.currentLoad < (action?.maxPickUpCount || 0)) {
const material = getLastMaterial(storageUnit.modelUuid);
if (material) {
if (action.triggers[0].triggeredAsset?.triggeredModel.modelUuid && action.triggers[0].triggeredAsset.triggeredAction?.actionUuid) {
const human = getEventByModelUuid(selectedProduct.productUuid, action.triggers[0].triggeredAsset.triggeredModel.modelUuid);
if (human && human.type === 'human') {
if (human && human.type === "human") {
if (!monitoredHumansRef.current.has(human.modelUuid)) {
addHumanToMonitor(human.modelUuid, () => {
addHumanToMonitor(
human.modelUuid,
() => {
incrementCraneLoad(crane.modelUuid, 1);
addCurrentActionToCrane(crane.modelUuid, action.actionUuid, material.materialType, material.materialId);
addCurrentMaterialToCrane(crane.modelUuid, material.materialType, material.materialId);
cranePickupLockRef.current.set(crane.modelUuid, true);
monitoredHumansRef.current.delete(human.modelUuid);
}, action.triggers[0].triggeredAsset.triggeredAction?.actionUuid)
},
action.triggers[0].triggeredAsset.triggeredAction?.actionUuid
);
}
monitoredHumansRef.current.add(human.modelUuid);
}
}
}
} else if (crane.isCarrying && crane.currentPhase === 'pickup-drop' && hasLock) {
} else if (crane.isCarrying && crane.currentPhase === "pickup-drop" && hasLock) {
cranePickupLockRef.current.set(crane.modelUuid, false);
const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) {
const triggeredAction = getActionByUuid(
selectedProduct.productUuid,
action?.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid || ''
);
const triggeredAction = getActionByUuid(selectedProduct.productUuid, action?.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid || "");
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
triggeredAction as StorageAction
);
const material = createNewMaterial(lastMaterial.materialId, lastMaterial.materialType, triggeredAction as StorageAction);
if (material) {
removeLastMaterial(storageUnit.modelUuid);
updateCurrentLoad(storageUnit.modelUuid, -1);
@@ -509,28 +447,27 @@ export function useRetrieveHandler() {
}
}
} else if (!action) {
const action = getActionByUuid(selectedProduct.productUuid, retrieval.action.triggers[0]?.triggeredAsset.triggeredAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, retrieval.action.triggers[0]?.triggeredAsset.triggeredAction?.actionUuid || "");
if (action) {
addCurrentActionToCrane(crane.modelUuid, action.actionUuid, null, null);
}
}
}
});
if (hasChanges || completedActions.length > 0) {
setActiveRetrievals(prev => {
setActiveRetrievals((prev) => {
const newRetrievals = new Map(prev);
completedActions.forEach(actionUuid => newRetrievals.delete(actionUuid));
completedActions.forEach((actionUuid) => newRetrievals.delete(actionUuid));
return newRetrievals;
});
}
});
const handleRetrieve = useCallback((action: StorageAction) => {
if (!action || action.actionType !== 'retrieve') return;
if (!action || action.actionType !== "retrieve") return;
setActiveRetrievals(prev => {
setActiveRetrievals((prev) => {
const newRetrievals = new Map(prev);
newRetrievals.set(action.actionUuid, {
action,

View File

@@ -1,21 +1,19 @@
import { useCallback } from "react";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function useStoreHandler() {
const { materialStore, storageUnitStore, productStore } = useSceneContext();
const { getMaterialById, removeMaterial, setEndTime } = materialStore();
const { addCurrentMaterial, updateCurrentLoad } = storageUnitStore();
const { getModelUuidByActionUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getModelUuidByActionUuid, selectedProduct } = productStore();
const storeLogStatus = (materialUuid: string, status: string) => {
echo.info(`${materialUuid}, ${status}`);
}
};
const handleStore = useCallback((action: StorageAction, materialId?: string) => {
if (!action || action.actionType !== 'store' || !materialId) return;
const handleStore = useCallback(
(action: StorageAction, materialId?: string) => {
if (!action || action.actionType !== "store" || !materialId) return;
const material = getMaterialById(materialId);
if (!material) return;
@@ -29,8 +27,9 @@ export function useStoreHandler() {
updateCurrentLoad(modelUuid, 1);
storeLogStatus(material.materialName, `performed Store action`);
}, [getMaterialById]);
},
[getMaterialById]
);
return {
handleStore,

View File

@@ -1,21 +1,19 @@
import { useCallback } from "react";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useProductContext } from "../../../products/productContext";
export function useTravelHandler() {
const { materialStore, vehicleStore, productStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { getMaterialById } = materialStore();
const { getModelUuidByActionUuid } = productStore();
const { selectedProduct } = selectedProductStore();
const { getModelUuidByActionUuid, selectedProduct } = productStore();
const { incrementVehicleLoad, addCurrentMaterial } = vehicleStore();
const travelLogStatus = (materialUuid: string, status: string) => {
echo.info(`${materialUuid}, ${status}`);
}
};
const handleTravel = useCallback((action: VehicleAction, materialId?: string) => {
if (!action || action.actionType !== 'travel' || !materialId) return;
const handleTravel = useCallback(
(action: VehicleAction, materialId?: string) => {
if (!action || action.actionType !== "travel" || !materialId) return;
const material = getMaterialById(materialId);
if (!material) return;
@@ -28,8 +26,9 @@ export function useTravelHandler() {
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
travelLogStatus(material.materialName, `is triggering travel from ${modelUuid}`);
}, [addCurrentMaterial, getMaterialById, getModelUuidByActionUuid, incrementVehicleLoad, selectedProduct.productUuid]);
},
[addCurrentMaterial, getMaterialById, getModelUuidByActionUuid, incrementVehicleLoad, selectedProduct.productUuid]
);
return {
handleTravel,

View File

@@ -1,22 +1,19 @@
import React, { useEffect } from 'react'
import { CompareProduct, useCompareProductDataStore, useInputValues, useMachineDowntime, useMachineUptime, useProductionCapacityData, useROISummaryData, useThroughPutData } from '../../../../store/builder/store';
import { usePlayButtonStore } from '../../../../store/ui/usePlayButtonStore';
import { useProductContext } from '../../products/productContext';
import { useSceneContext } from '../../../scene/sceneContext';
import { useEffect } from "react";
import { CompareProduct, useCompareProductDataStore, useInputValues, useMachineDowntime, useMachineUptime, useProductionCapacityData, useROISummaryData, useThroughPutData } from "../../../../store/builder/store";
import { usePlayButtonStore } from "../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../scene/sceneContext";
export default function ROIData() {
const { selectedProductStore } = useProductContext();
const { inputValues } = useInputValues();
const { productionCapacityData } = useProductionCapacityData()
const { selectedProduct } = selectedProductStore();
const { productionCapacityData } = useProductionCapacityData();
const { isPlaying } = usePlayButtonStore();
const { setRoiSummaryData } = useROISummaryData();
const { productStore } = useSceneContext();
const { getProductById } = productStore();
const { getProductById, selectedProduct } = productStore();
const { compareProductsData, setCompareProductsData } = useCompareProductDataStore();
const { machineActiveTime } = useMachineUptime();
const { machineIdleTime } = useMachineDowntime();
const { throughputData } = useThroughPutData()
const { throughputData } = useThroughPutData();
useEffect(() => {
if (isPlaying) return;
@@ -47,10 +44,7 @@ export default function ROIData() {
const shiftsPerDay = parseFloat(inputValues["Shifts / day"]);
const workingDaysPerYear = parseFloat(inputValues["Working days / year"]);
if (!isNaN(electricityCost) && !isNaN(fixedCost) && !isNaN(laborCost) && !isNaN(maintenanceCost) &&
!isNaN(materialCost) && !isNaN(productionPeriod) && !isNaN(salvageValue) && !isNaN(sellingPrice) &&
!isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && productionCapacityData > 0) {
if (!isNaN(electricityCost) && !isNaN(fixedCost) && !isNaN(laborCost) && !isNaN(maintenanceCost) && !isNaN(materialCost) && !isNaN(productionPeriod) && !isNaN(salvageValue) && !isNaN(sellingPrice) && !isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && productionCapacityData > 0) {
// const totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear;
// const annualProductionUnits = productionCapacityData * totalHoursPerYear;
// const annualRevenue = annualProductionUnits * sellingPrice;
@@ -120,20 +114,20 @@ export default function ROIData() {
// setCompareProductsData([...prev, newData]);
// }
const Annual_units = throughputData * workingDaysPerYear
const Total_units = Annual_units * productionPeriod
const Annual_units = throughputData * workingDaysPerYear;
const Total_units = Annual_units * productionPeriod;
const Total_revenue = Total_units * sellingPrice
const Total_variable_cost = Total_units * (materialCost + (laborCost))
const Total_revenue = Total_units * sellingPrice;
const Total_variable_cost = Total_units * (materialCost + laborCost);
const Total_fixed_cost = (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear * productionPeriod
const Total_cost = Total_variable_cost + Total_fixed_cost
const Total_fixed_cost = (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear * productionPeriod;
const Total_cost = Total_variable_cost + Total_fixed_cost;
const Net_profit = Total_revenue - Total_cost + (salvageValue * workingDaysPerYear * productionPeriod)
const Net_profit = Total_revenue - Total_cost + salvageValue * workingDaysPerYear * productionPeriod;
const ROI = (Net_profit / initialInvestment) * 100
const ROI = (Net_profit / initialInvestment) * 100;
const Annual_net_profit = (Annual_units * (sellingPrice - materialCost - laborCost)) - (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear + (salvageValue * workingDaysPerYear)
const Annual_net_profit = Annual_units * (sellingPrice - materialCost - laborCost) - (maintenanceCost + electricityCost + fixedCost) * workingDaysPerYear + salvageValue * workingDaysPerYear;
const Payback_period_years = initialInvestment / Annual_net_profit;
setRoiSummaryData({
@@ -143,15 +137,14 @@ export default function ROIData() {
totalCost: Total_cost,
revenueGenerated: Total_revenue,
netProfit: Net_profit > 0 ? Net_profit : 0,
netLoss: Net_profit < 0 ? -Net_profit : 0
netLoss: Net_profit < 0 ? -Net_profit : 0,
});
const productData = getProductById(selectedProduct.productUuid);
const prev = useCompareProductDataStore.getState().compareProductsData;
const newData: CompareProduct = {
productUuid: productData?.productUuid ?? '',
productName: productData?.productName ?? '',
productUuid: productData?.productUuid ?? "",
productName: productData?.productName ?? "",
simulationData: {
// costPerUnit: costPerUnit,
// workingDaysPerYear: workingDaysPerYear,
@@ -168,12 +161,10 @@ export default function ROIData() {
machineIdleTime: machineIdleTime,
machineActiveTime: machineActiveTime,
throughputData: throughputData,
}
},
};
const existingIndex = prev.findIndex((item: CompareProduct) =>
item.productUuid === productData?.productUuid
);
const existingIndex = prev.findIndex((item: CompareProduct) => item.productUuid === productData?.productUuid);
if (existingIndex !== -1) {
const updated = [...prev];
@@ -183,12 +174,9 @@ export default function ROIData() {
setCompareProductsData([...prev, newData]);
}
}
}, [inputValues, productionCapacityData, throughputData, isPlaying]);
useEffect(() => {
}, [compareProductsData])
useEffect(() => {}, [compareProductsData]);
return null;
}

View File

@@ -1,15 +1,12 @@
import { useEffect } from 'react';
import { determineExecutionMachineSequences } from '../../simulator/functions/determineExecutionMachineSequences';
import { useInputValues, useMachineCount, useMachineDowntime, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from '../../../../store/builder/store';
import { usePlayButtonStore } from '../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../scene/sceneContext';
import { useProductContext } from '../../products/productContext';
import { useEffect } from "react";
import { determineExecutionMachineSequences } from "../../simulator/functions/determineExecutionMachineSequences";
import { useInputValues, useMachineCount, useMachineDowntime, useMachineUptime, useMaterialCycle, useProcessBar, useThroughPutData } from "../../../../store/builder/store";
import { usePlayButtonStore } from "../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../scene/sceneContext";
export default function ThroughPutData() {
const { materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, productStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { products, getProductById } = productStore();
const { products, getProductById, selectedProduct } = productStore();
const { armBots } = armBotStore();
const { vehicles } = vehicleStore();
const { machines } = machineStore();
@@ -21,14 +18,14 @@ export default function ThroughPutData() {
const { machineIdleTime, setMachineIdleTime } = useMachineDowntime();
const { materialCycleTime, setMaterialCycleTime } = useMaterialCycle();
const { setProcessBar } = useProcessBar();
const { setThroughputData } = useThroughPutData()
const { setThroughputData } = useThroughPutData();
const { isPlaying } = usePlayButtonStore();
const { inputValues } = useInputValues();
// Setting machine count
let totalItems = 0;
let totalActiveTime = 0;
let totalIdleTime = 0
let totalIdleTime = 0;
useEffect(() => {
if (!isPlaying) {
@@ -42,7 +39,7 @@ export default function ThroughPutData() {
setProcessBar([]);
setThroughputData(0);
}
}, [isPlaying])
}, [isPlaying]);
useEffect(() => {
if (isPlaying) {
@@ -50,15 +47,16 @@ export default function ThroughPutData() {
const fetchProductSequenceData = async () => {
const productData = getProductById(selectedProduct.productUuid);
if (productData) {
const productSequenceData = await determineExecutionMachineSequences([productData])
const productSequenceData = await determineExecutionMachineSequences([productData]);
if (productSequenceData?.length > 0) {
productSequenceData.forEach((sequence) => {
sequence.forEach((item) => {
if (item.type === "roboticArm") {
armBots.filter(arm => arm.modelUuid === item.modelUuid)
.forEach(arm => {
armBots
.filter((arm) => arm.modelUuid === item.modelUuid)
.forEach((arm) => {
if (arm.activeTime > 0) {
process.push({ modelid: arm.modelUuid, modelName: arm.modelName, activeTime: arm?.activeTime })
process.push({ modelid: arm.modelUuid, modelName: arm.modelName, activeTime: arm?.activeTime });
totalActiveTime += arm.activeTime;
}
if (arm.idleTime > 0) {
@@ -66,10 +64,11 @@ export default function ThroughPutData() {
}
});
} else if (item.type === "vehicle") {
vehicles.filter(vehicle => vehicle.modelUuid === item.modelUuid)
.forEach(vehicle => {
vehicles
.filter((vehicle) => vehicle.modelUuid === item.modelUuid)
.forEach((vehicle) => {
if (vehicle.activeTime > 0) {
process.push({ modelid: vehicle.modelUuid, modelName: vehicle.modelName, activeTime: vehicle?.activeTime })
process.push({ modelid: vehicle.modelUuid, modelName: vehicle.modelName, activeTime: vehicle?.activeTime });
totalActiveTime += vehicle.activeTime;
}
@@ -78,10 +77,11 @@ export default function ThroughPutData() {
}
});
} else if (item.type === "machine") {
machines.filter(machine => machine.modelUuid === item.modelUuid)
.forEach(machine => {
machines
.filter((machine) => machine.modelUuid === item.modelUuid)
.forEach((machine) => {
if (machine.activeTime > 0) {
process.push({ modelid: machine.modelUuid, modelName: machine.modelName, activeTime: machine?.activeTime })
process.push({ modelid: machine.modelUuid, modelName: machine.modelName, activeTime: machine?.activeTime });
totalActiveTime += machine.activeTime;
}
if (machine.idleTime > 0) {
@@ -89,15 +89,17 @@ export default function ThroughPutData() {
}
});
} else if (item.type === "transfer") {
conveyors.filter(conveyor => conveyor.modelUuid === item.modelUuid)
.forEach(conveyor => {
conveyors
.filter((conveyor) => conveyor.modelUuid === item.modelUuid)
.forEach((conveyor) => {
if (conveyor.activeTime > 0) {
// totalActiveTime += conveyor.activeTime;
}
});
} else if (item.type === "storageUnit") {
storageUnits.filter(storage => storage.modelUuid === item.modelUuid)
.forEach(storage => {
storageUnits
.filter((storage) => storage.modelUuid === item.modelUuid)
.forEach((storage) => {
if (storage.activeTime > 0) {
// totalActiveTime += storage.activeTime;
}
@@ -108,13 +110,12 @@ export default function ThroughPutData() {
totalItems += sequence.length;
});
setMachineCount(totalItems);
setMachineActiveTime(totalActiveTime);
setMachineIdleTime(totalIdleTime);
let arr = process.map((item: any) => ({
name: item.modelName,
completed: Math.round((item.activeTime / totalActiveTime) * 100)
completed: Math.round((item.activeTime / totalActiveTime) * 100),
}));
setProcessBar(arr);
}
@@ -136,12 +137,12 @@ export default function ThroughPutData() {
if (productData) {
const productSequenceData = await determineExecutionMachineSequences([productData]);
if (productSequenceData?.length > 0) {
productSequenceData.forEach(sequence => {
sequence.forEach(item => {
productSequenceData.forEach((sequence) => {
sequence.forEach((item) => {
if (item.type === "roboticArm") {
armBots
.filter(arm => arm.modelUuid === item.modelUuid)
.forEach(arm => {
.filter((arm) => arm.modelUuid === item.modelUuid)
.forEach((arm) => {
if (arm.isActive) {
anyArmActive = true;
} else {
@@ -151,8 +152,8 @@ export default function ThroughPutData() {
}
if (item.type === "vehicle") {
vehicles
.filter(vehicle => vehicle.modelUuid === item.modelUuid)
.forEach(vehicle => {
.filter((vehicle) => vehicle.modelUuid === item.modelUuid)
.forEach((vehicle) => {
if (vehicle.isActive) {
anyVehicleActive = true;
} else {
@@ -162,8 +163,8 @@ export default function ThroughPutData() {
}
if (item.type === "machine") {
machines
.filter(machine => machine.modelUuid === item.modelUuid)
.forEach(machine => {
.filter((machine) => machine.modelUuid === item.modelUuid)
.forEach((machine) => {
if (machine.isActive) {
anyMachineActive = true;
} else {
@@ -178,7 +179,6 @@ export default function ThroughPutData() {
const allInactive = !anyArmActive && !anyVehicleActive && !anyMachineActive;
if (materialHistory.length > 0) {
let totalCycleTimeSum = 0;
let cycleCount = 0;
@@ -207,7 +207,7 @@ export default function ThroughPutData() {
return () => {
if (timeoutId) clearTimeout(timeoutId);
};
}, [armBots, materials, materialHistory, machines, vehicles, selectedProduct?.productUuid])
}, [armBots, materials, materialHistory, machines, vehicles, selectedProduct?.productUuid]);
useEffect(() => {
const shiftLength = parseFloat(inputValues["Shift length"]);
@@ -222,8 +222,5 @@ export default function ThroughPutData() {
}
}, [materialCycleTime, machineCount, isPlaying, inputValues]);
return (
<>
</>
);
return <></>;
}

View File

@@ -1,15 +1,12 @@
import { useEffect } from 'react'
import { useFrame } from '@react-three/fiber'
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import { useEffect } from "react";
import { useFrame } from "@react-three/fiber";
import { useSceneContext } from "../../../../scene/sceneContext";
// import { findConveyorSubsequence } from '../../../simulator/functions/getConveyorSequencesInProduct';
function ConveyorInstance({ conveyor }: { readonly conveyor: ConveyorStatus }) {
const { materialStore, conveyorStore, productStore } = useSceneContext();
const { getProductById } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getProductById, selectedProduct } = productStore();
const { getMaterialsByCurrentModelUuid } = materialStore();
const { setConveyorPaused } = conveyorStore();
@@ -19,8 +16,7 @@ function ConveyorInstance({ conveyor }: { readonly conveyor: ConveyorStatus }) {
const conveyorMaterials = getMaterialsByCurrentModelUuid(conveyor.modelUuid);
if (conveyorMaterials && conveyorMaterials.length > 0) {
const hasPausedMaterials = conveyorMaterials.some(material => material.isPaused);
const hasPausedMaterials = conveyorMaterials.some((material) => material.isPaused);
if (hasPausedMaterials) {
setConveyorPaused(conveyor.modelUuid, true);
@@ -51,17 +47,13 @@ function ConveyorInstance({ conveyor }: { readonly conveyor: ConveyorStatus }) {
// setConveyorPaused(event.modelUuid, hasPausedMaterials);
// }
// });
});
useEffect(() => {
// console.log('conveyor: ', conveyor);
}, [conveyor])
}, [conveyor]);
return (
<>
</>
);
return <></>;
}
export default ConveyorInstance
export default ConveyorInstance;

View File

@@ -1,8 +1,7 @@
import { useEffect } from 'react';
import { useFrame } from '@react-three/fiber';
import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../scene/sceneContext';
import { useProductContext } from '../../products/productContext';
import { useEffect } from "react";
import { useFrame } from "@react-three/fiber";
import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../scene/sceneContext";
export function useCraneEventManager() {
const { craneStore, productStore, assetStore, vehicleStore, armBotStore, machineStore, craneEventManagerRef } = useSceneContext();
@@ -11,9 +10,7 @@ export function useCraneEventManager() {
const { getVehicleById } = vehicleStore();
const { getArmBotById } = armBotStore();
const { getMachineById } = machineStore();
const { getActionByUuid, getEventByModelUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, getEventByModelUuid, selectedProduct } = productStore();
const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore();
@@ -29,22 +26,22 @@ export function useCraneEventManager() {
const crane = getCraneById(craneId);
const action = getActionByUuid(selectedProduct.productUuid, actionUuid) as CraneAction | undefined;
if (!crane || !action || action.actionType !== 'pickAndDrop' || !craneEventManagerRef.current) return;
if (!crane || !action || action.actionType !== "pickAndDrop" || !craneEventManagerRef.current) return;
let state = craneEventManagerRef.current.craneStates.find(c => c.craneId === craneId);
let state = craneEventManagerRef.current.craneStates.find((c) => c.craneId === craneId);
if (!state) {
state = {
craneId,
pendingActions: [],
currentAction: null,
isProcessing: false
isProcessing: false,
};
craneEventManagerRef.current.craneStates.push(state);
}
state.pendingActions.push({
actionUuid,
callback
callback,
});
if (!state.isProcessing) {
@@ -75,19 +72,19 @@ export function useCraneEventManager() {
const { craneId, currentAction } = craneState;
const crane = getCraneById(craneId);
const craneAsset = getAssetById(craneId);
const currentCraneAction = getActionByUuid(selectedProduct.productUuid, crane?.currentAction?.actionUuid || '') as CraneAction | undefined;
const currentCraneAction = getActionByUuid(selectedProduct.productUuid, crane?.currentAction?.actionUuid || "") as CraneAction | undefined;
if (!crane || !craneAsset || !currentCraneAction) continue;
if (crane.isActive || crane.state !== "idle") continue;
if (currentCraneAction.actionType === 'pickAndDrop' && crane.currentLoad < currentCraneAction.maxPickUpCount) {
const humanAction = getActionByUuid(selectedProduct.productUuid, currentCraneAction.triggers[0].triggeredAsset?.triggeredAction?.actionUuid || '');
if (currentCraneAction.actionType === "pickAndDrop" && crane.currentLoad < currentCraneAction.maxPickUpCount) {
const humanAction = getActionByUuid(selectedProduct.productUuid, currentCraneAction.triggers[0].triggeredAsset?.triggeredAction?.actionUuid || "");
if (humanAction) {
const nextEvent = getEventByModelUuid(selectedProduct.productUuid, humanAction.triggers[0].triggeredAsset?.triggeredModel?.modelUuid || '')
const nextEvent = getEventByModelUuid(selectedProduct.productUuid, humanAction.triggers[0].triggeredAsset?.triggeredModel?.modelUuid || "");
if (nextEvent) {
if (nextEvent.type === 'transfer') {
if (nextEvent.type === "transfer") {
if (currentAction.actionUuid !== crane.currentAction?.actionUuid) {
setCurrentPhase(crane.modelUuid, 'init');
setCurrentPhase(crane.modelUuid, "init");
removeCurrentAction(crane.modelUuid);
}
@@ -97,12 +94,12 @@ export function useCraneEventManager() {
setTimeout(() => {
completeCurrentAction(craneState);
}, 1000);
} else if (nextEvent.type === 'vehicle') {
} else if (nextEvent.type === "vehicle") {
const vehicle = getVehicleById(nextEvent.modelUuid);
if (vehicle && !vehicle.isActive && vehicle.currentPhase === 'picking') {
if (vehicle && !vehicle.isActive && vehicle.currentPhase === "picking") {
if (currentAction.actionUuid !== crane.currentAction?.actionUuid) {
setCurrentPhase(crane.modelUuid, 'init');
setCurrentPhase(crane.modelUuid, "init");
removeCurrentAction(crane.modelUuid);
}
@@ -113,12 +110,12 @@ export function useCraneEventManager() {
completeCurrentAction(craneState);
}, 1000);
}
} else if (nextEvent.type === 'roboticArm') {
} else if (nextEvent.type === "roboticArm") {
const armBot = getArmBotById(nextEvent.modelUuid);
if (armBot && !armBot.isActive) {
if (currentAction.actionUuid !== crane.currentAction?.actionUuid) {
setCurrentPhase(crane.modelUuid, 'init');
setCurrentPhase(crane.modelUuid, "init");
removeCurrentAction(crane.modelUuid);
}
@@ -129,12 +126,12 @@ export function useCraneEventManager() {
completeCurrentAction(craneState);
}, 1000);
}
} else if (nextEvent.type === 'machine') {
} else if (nextEvent.type === "machine") {
const machine = getMachineById(nextEvent.modelUuid);
if (machine && !machine.isActive) {
if (currentAction.actionUuid !== crane.currentAction?.actionUuid) {
setCurrentPhase(crane.modelUuid, 'init');
setCurrentPhase(crane.modelUuid, "init");
removeCurrentAction(crane.modelUuid);
}
@@ -147,7 +144,7 @@ export function useCraneEventManager() {
}
} else {
if (currentAction.actionUuid !== crane.currentAction?.actionUuid) {
setCurrentPhase(crane.modelUuid, 'init');
setCurrentPhase(crane.modelUuid, "init");
removeCurrentAction(crane.modelUuid);
}
@@ -165,6 +162,6 @@ export function useCraneEventManager() {
}, 0);
return {
addCraneToMonitor
addCraneToMonitor,
};
}

View File

@@ -1,9 +1,8 @@
import { useEffect, useState } from 'react';
import * as THREE from 'three';
import { useFrame, useThree } from '@react-three/fiber';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import { useEffect, useState } from "react";
import * as THREE from "three";
import { useFrame, useThree } from "@react-three/fiber";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
function PillarJibAnimator({
crane,
@@ -11,7 +10,7 @@ function PillarJibAnimator({
setPoints,
animationPhase,
setAnimationPhase,
onAnimationComplete
onAnimationComplete,
}: Readonly<{
crane: CraneStatus;
points: [THREE.Vector3, THREE.Vector3] | null;
@@ -22,11 +21,9 @@ function PillarJibAnimator({
}>) {
const { scene } = useThree();
const { assetStore, productStore, materialStore } = useSceneContext();
const { getActionByUuid, getPointByUuid } = productStore();
const { getActionByUuid, getPointByUuid, selectedProduct } = productStore();
const { resetAsset } = assetStore();
const { setIsVisible } = materialStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { isPaused } = usePauseButtonStore();
const { isPlaying } = usePlayButtonStore();
const { isReset } = useResetButtonStore();
@@ -37,45 +34,40 @@ function PillarJibAnimator({
useEffect(() => {
if (!isPlaying || isReset) {
resetAsset(crane.modelUuid);
setAnimationPhase('idle');
setAnimationPhase("idle");
setPoints(null);
}
}, [isPlaying, scene, crane.modelUuid, isReset]);
useEffect(() => {
const model = scene.getObjectByProperty('uuid', crane.modelUuid);
const model = scene.getObjectByProperty("uuid", crane.modelUuid);
if (!model) return;
const hook = model.getObjectByName('hook');
const hook = model.getObjectByName("hook");
if (!hook) return;
const hookWorld = new THREE.Vector3();
hook.getWorldPosition(hookWorld);
if (crane.currentPhase === 'init-pickup') {
if (crane.currentPhase === "init-pickup") {
if (crane.currentMaterials.length > 0) {
const materials = scene.getObjectsByProperty('uuid', crane.currentMaterials[0].materialId);
const materials = scene.getObjectsByProperty("uuid", crane.currentMaterials[0].materialId);
const material = materials.find((material) => material.visible === true);
if (material) {
const materialWorld = new THREE.Vector3();
material.getWorldPosition(materialWorld);
setAnimationPhase('init-hook-adjust');
setPoints(
[
new THREE.Vector3(hookWorld.x, hookWorld.y, hookWorld.z),
new THREE.Vector3(materialWorld.x, materialWorld.y + 0.5, materialWorld.z)
]
);
setAnimationPhase("init-hook-adjust");
setPoints([new THREE.Vector3(hookWorld.x, hookWorld.y, hookWorld.z), new THREE.Vector3(materialWorld.x, materialWorld.y + 0.5, materialWorld.z)]);
}
}
} else if (crane.currentPhase === 'pickup-drop') {
} else if (crane.currentPhase === "pickup-drop") {
if (crane.currentMaterials.length > 0) {
const action = getActionByUuid(selectedProduct.productUuid, crane?.currentAction?.actionUuid || '');
const humanAction = getActionByUuid(selectedProduct.productUuid, action?.triggers[0].triggeredAsset?.triggeredAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, crane?.currentAction?.actionUuid || "");
const humanAction = getActionByUuid(selectedProduct.productUuid, action?.triggers[0].triggeredAsset?.triggeredAction?.actionUuid || "");
if (humanAction) {
const point = getPointByUuid(selectedProduct.productUuid, humanAction.triggers[0].triggeredAsset?.triggeredModel?.modelUuid || '', humanAction.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid || '');
const eventModel = scene.getObjectByProperty('uuid', humanAction.triggers[0].triggeredAsset?.triggeredModel?.modelUuid);
const point = getPointByUuid(selectedProduct.productUuid, humanAction.triggers[0].triggeredAsset?.triggeredModel?.modelUuid || "", humanAction.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid || "");
const eventModel = scene.getObjectByProperty("uuid", humanAction.triggers[0].triggeredAsset?.triggeredModel?.modelUuid);
if (point && eventModel) {
const pointLocal = new THREE.Vector3(...point.position);
const pointWorld = pointLocal.clone().applyMatrix4(eventModel.matrixWorld);
@@ -85,21 +77,21 @@ function PillarJibAnimator({
setIsVisible(crane.currentMaterials[0].materialId, false);
setAnimationPhase('init-hook-adjust');
setAnimationPhase("init-hook-adjust");
setPoints([startPoint, endPoint]);
}
}
}
}
}, [crane.currentPhase])
}, [crane.currentPhase]);
useEffect(() => {
const model = scene.getObjectByProperty('uuid', crane.modelUuid);
const model = scene.getObjectByProperty("uuid", crane.modelUuid);
if (!model?.userData.fieldData) return;
const base = model.getObjectByName('base');
const trolley = model.getObjectByName('trolley');
const hook = model.getObjectByName('hook');
const base = model.getObjectByName("base");
const trolley = model.getObjectByName("trolley");
const hook = model.getObjectByName("hook");
if (!base || !trolley || !hook || !points) return;
@@ -119,10 +111,7 @@ function PillarJibAnimator({
const distFromBase = new THREE.Vector2(trolleyWorld.x - baseWorld.x, trolleyWorld.z - baseWorld.z).length();
const innerRadius = Math.max(distFromBase + trolleyMinOffset, 0.05);
const outerRadius = Math.max(
new THREE.Vector2(trolleyWorld.x - baseWorld.x, trolleyWorld.z - baseWorld.z).length() + trolleyMaxOffset,
innerRadius
);
const outerRadius = Math.max(new THREE.Vector2(trolleyWorld.x - baseWorld.x, trolleyWorld.z - baseWorld.z).length() + trolleyMaxOffset, innerRadius);
const yMin = hookWorld.y + hookMaxOffset;
const yMax = hookWorld.y + hookMinOffset;
@@ -158,14 +147,14 @@ function PillarJibAnimator({
}, [crane.modelUuid, points]);
useFrame(() => {
if (!isPlaying || isPaused || !points || !clampedPoints || animationPhase === 'idle') return;
if (!isPlaying || isPaused || !points || !clampedPoints || animationPhase === "idle") return;
const model = scene.getObjectByProperty('uuid', crane.modelUuid);
const model = scene.getObjectByProperty("uuid", crane.modelUuid);
if (!model) return;
const base = model.getObjectByName('base');
const trolley = model.getObjectByName('trolley');
const hook = model.getObjectByName('hook');
const base = model.getObjectByName("base");
const trolley = model.getObjectByName("trolley");
const hook = model.getObjectByName("hook");
if (!base || !trolley || !hook || !trolley.parent || !hook.parent) return;
@@ -182,7 +171,7 @@ function PillarJibAnimator({
const threshold = Math.max(0.01, 0.05 / speed);
switch (animationPhase) {
case 'init-hook-adjust': {
case "init-hook-adjust": {
const hookWorld = new THREE.Vector3();
hook.getWorldPosition(hookWorld);
@@ -194,19 +183,19 @@ function PillarJibAnimator({
if (Math.abs(step) > Math.abs(diff)) {
const localTarget = hook.parent.worldToLocal(clampedPoints[0].clone());
hook.position.y = localTarget.y;
setAnimationPhase('init-rotate-base');
setAnimationPhase("init-rotate-base");
} else {
hook.position.y += step;
}
} else {
const localTarget = hook.parent.worldToLocal(clampedPoints[0].clone());
hook.position.y = localTarget.y;
setAnimationPhase('init-rotate-base');
setAnimationPhase("init-rotate-base");
}
break;
}
case 'init-rotate-base': {
case "init-rotate-base": {
const baseWorld = new THREE.Vector3();
base.getWorldPosition(baseWorld);
@@ -217,10 +206,7 @@ function PillarJibAnimator({
const currentDir = new THREE.Vector2(baseForward.x, baseForward.z).normalize();
const targetWorld = clampedPoints[0];
const targetDir = new THREE.Vector2(
targetWorld.x - baseWorld.x,
targetWorld.z - baseWorld.z
).normalize();
const targetDir = new THREE.Vector2(targetWorld.x - baseWorld.x, targetWorld.z - baseWorld.z).normalize();
const currentAngle = Math.atan2(currentDir.y, currentDir.x);
const targetAngle = Math.atan2(targetDir.y, targetDir.x);
@@ -233,18 +219,18 @@ function PillarJibAnimator({
if (Math.abs(step) > Math.abs(angleDiff)) {
base.rotation.y += angleDiff;
setAnimationPhase('init-move-trolley');
setAnimationPhase("init-move-trolley");
} else {
base.rotation.y += step;
}
} else {
base.rotation.y += angleDiff;
setAnimationPhase('init-move-trolley');
setAnimationPhase("init-move-trolley");
}
break;
}
case 'init-move-trolley': {
case "init-move-trolley": {
const baseWorld = new THREE.Vector3();
base.getWorldPosition(baseWorld);
@@ -257,18 +243,18 @@ function PillarJibAnimator({
const step = Math.sign(diff) * trolleySpeed;
if (Math.abs(step) > Math.abs(diff)) {
trolley.position.x = localTarget.x;
setAnimationPhase('init-final-hook-adjust');
setAnimationPhase("init-final-hook-adjust");
} else {
trolley.position.x += step;
}
} else {
trolley.position.x = localTarget.x;
setAnimationPhase('init-final-hook-adjust');
setAnimationPhase("init-final-hook-adjust");
}
break;
}
case 'init-final-hook-adjust': {
case "init-final-hook-adjust": {
const hookWorld = new THREE.Vector3();
hook.getWorldPosition(hookWorld);
@@ -280,19 +266,19 @@ function PillarJibAnimator({
if (Math.abs(step) > Math.abs(diff)) {
const localTarget = hook.parent.worldToLocal(clampedPoints[0].clone());
hook.position.y = localTarget.y;
setAnimationPhase('first-hook-adjust');
setAnimationPhase("first-hook-adjust");
} else {
hook.position.y += step;
}
} else {
const localTarget = hook.parent.worldToLocal(clampedPoints[0].clone());
hook.position.y = localTarget.y;
setAnimationPhase('first-hook-adjust');
setAnimationPhase("first-hook-adjust");
}
break;
}
case 'first-hook-adjust': {
case "first-hook-adjust": {
const hookWorld = new THREE.Vector3();
hook.getWorldPosition(hookWorld);
@@ -305,19 +291,19 @@ function PillarJibAnimator({
if (Math.abs(step) > Math.abs(diff)) {
const localTarget = hook.parent.worldToLocal(targetWorld.clone());
hook.position.y = localTarget.y;
setAnimationPhase('first-rotate-base');
setAnimationPhase("first-rotate-base");
} else {
hook.position.y += step;
}
} else {
const localTarget = hook.parent.worldToLocal(targetWorld.clone());
hook.position.y = localTarget.y;
setAnimationPhase('first-rotate-base');
setAnimationPhase("first-rotate-base");
}
break;
}
case 'first-rotate-base': {
case "first-rotate-base": {
const baseWorld = new THREE.Vector3();
base.getWorldPosition(baseWorld);
@@ -328,10 +314,7 @@ function PillarJibAnimator({
const currentDir = new THREE.Vector2(baseForward.x, baseForward.z).normalize();
const targetWorld = clampedPoints[1];
const targetDir = new THREE.Vector2(
targetWorld.x - baseWorld.x,
targetWorld.z - baseWorld.z
).normalize();
const targetDir = new THREE.Vector2(targetWorld.x - baseWorld.x, targetWorld.z - baseWorld.z).normalize();
const currentAngle = Math.atan2(currentDir.y, currentDir.x);
const targetAngle = Math.atan2(targetDir.y, targetDir.x);
@@ -344,18 +327,18 @@ function PillarJibAnimator({
if (Math.abs(step) > Math.abs(angleDiff)) {
base.rotation.y += angleDiff;
setAnimationPhase('first-move-trolley');
setAnimationPhase("first-move-trolley");
} else {
base.rotation.y += step;
}
} else {
base.rotation.y += angleDiff;
setAnimationPhase('first-move-trolley');
setAnimationPhase("first-move-trolley");
}
break;
}
case 'first-move-trolley': {
case "first-move-trolley": {
const baseWorld = new THREE.Vector3();
base.getWorldPosition(baseWorld);
@@ -368,18 +351,18 @@ function PillarJibAnimator({
const step = Math.sign(diff) * trolleySpeed;
if (Math.abs(step) > Math.abs(diff)) {
trolley.position.x = localTarget.x;
setAnimationPhase('first-final-hook-adjust');
setAnimationPhase("first-final-hook-adjust");
} else {
trolley.position.x += step;
}
} else {
trolley.position.x = localTarget.x;
setAnimationPhase('first-final-hook-adjust');
setAnimationPhase("first-final-hook-adjust");
}
break;
}
case 'first-final-hook-adjust': {
case "first-final-hook-adjust": {
const hookWorld = new THREE.Vector3();
hook.getWorldPosition(hookWorld);
@@ -391,12 +374,12 @@ function PillarJibAnimator({
if (Math.abs(step) > Math.abs(diff)) {
const localTarget = hook.parent.worldToLocal(clampedPoints[1].clone());
hook.position.y = localTarget.y;
if (crane.currentPhase === 'init-pickup') {
setAnimationPhase('picking');
onAnimationComplete('picking');
} else if (crane.currentPhase === 'pickup-drop') {
setAnimationPhase('dropping');
onAnimationComplete('dropping');
if (crane.currentPhase === "init-pickup") {
setAnimationPhase("picking");
onAnimationComplete("picking");
} else if (crane.currentPhase === "pickup-drop") {
setAnimationPhase("dropping");
onAnimationComplete("dropping");
}
} else {
hook.position.y += step;
@@ -404,12 +387,12 @@ function PillarJibAnimator({
} else {
const localTarget = hook.parent.worldToLocal(clampedPoints[1].clone());
hook.position.y = localTarget.y;
if (crane.currentPhase === 'init-pickup') {
setAnimationPhase('picking');
onAnimationComplete('picking');
} else if (crane.currentPhase === 'pickup-drop') {
setAnimationPhase('dropping');
onAnimationComplete('dropping');
if (crane.currentPhase === "init-pickup") {
setAnimationPhase("picking");
onAnimationComplete("picking");
} else if (crane.currentPhase === "pickup-drop") {
setAnimationPhase("dropping");
onAnimationComplete("dropping");
}
}
break;
@@ -417,10 +400,7 @@ function PillarJibAnimator({
}
});
return (
<>
</>
);
return <></>;
}
export default PillarJibAnimator;

View File

@@ -1,68 +1,65 @@
import { useEffect, useState } from 'react';
import * as THREE from 'three'
import { usePlayButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import { useEffect, useState } from "react";
import * as THREE from "three";
import { usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
import { useTriggerHandler } from "../../../triggers/triggerHandler/useTriggerHandler";
import PillarJibAnimator from '../animator/pillarJibAnimator'
import PillarJibHelper from '../helper/pillarJibHelper'
import MaterialAnimator from '../animator/materialAnimator';
import PillarJibAnimator from "../animator/pillarJibAnimator";
import PillarJibHelper from "../helper/pillarJibHelper";
import MaterialAnimator from "../animator/materialAnimator";
function PillarJibInstance({ crane }: { readonly crane: CraneStatus }) {
const { isPlaying } = usePlayButtonStore();
const { craneStore, productStore, humanStore, assetStore } = useSceneContext();
const { triggerPointActions } = useTriggerHandler();
const { getActionByUuid } = productStore();
const { getActionByUuid, selectedProduct } = productStore();
const { setCurrentPhase, setCraneActive, setIsCaryying, removeCurrentAction, removeLastMaterial, decrementCraneLoad } = craneStore();
const { setCurrentPhase: setCurrentPhaseHuman, setHumanActive, setHumanState, getHumanById } = humanStore();
const { setCurrentAnimation, getAssetById } = assetStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const [animationPhase, setAnimationPhase] = useState<string>('idle');
const [animationPhase, setAnimationPhase] = useState<string>("idle");
const [points, setPoints] = useState<[THREE.Vector3, THREE.Vector3] | null>(null);
const action = getActionByUuid(selectedProduct.productUuid, crane?.currentAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, crane?.currentAction?.actionUuid || "");
const actionTriggers = action?.triggers || [];
const humanId = actionTriggers?.[0]?.triggeredAsset?.triggeredModel?.modelUuid ?? null;
const humanAsset = getAssetById(humanId || '');
const humanAction = getActionByUuid(selectedProduct.productUuid, actionTriggers?.[0]?.triggeredAsset?.triggeredAction?.actionUuid ?? '');
const humanAsset = getAssetById(humanId || "");
const humanAction = getActionByUuid(selectedProduct.productUuid, actionTriggers?.[0]?.triggeredAsset?.triggeredAction?.actionUuid ?? "");
useEffect(() => {
if (isPlaying) {
const human = getHumanById(humanId || '');
if (!human || !humanAsset || !humanId || !action || action.actionType !== 'pickAndDrop') return;
const human = getHumanById(humanId || "");
if (!human || !humanAsset || !humanId || !action || action.actionType !== "pickAndDrop") return;
if (!crane.isActive && crane.currentPhase === 'init' && crane.currentMaterials.length > 0 && action.maxPickUpCount <= crane.currentMaterials.length) {
setCurrentPhase(crane.modelUuid, 'init-pickup');
} else if (crane.currentPhase === 'picking' && crane.currentMaterials.length > 0 && action.maxPickUpCount <= crane.currentMaterials.length && !crane.isCarrying) {
if (humanAsset?.animationState?.current === "working_standing" && humanAsset?.animationState?.isCompleted && humanId && humanAction && humanAction.actionType === 'operator') {
setCurrentAnimation(humanId, 'idle', true, true, true);
if (!crane.isActive && crane.currentPhase === "init" && crane.currentMaterials.length > 0 && action.maxPickUpCount <= crane.currentMaterials.length) {
setCurrentPhase(crane.modelUuid, "init-pickup");
} else if (crane.currentPhase === "picking" && crane.currentMaterials.length > 0 && action.maxPickUpCount <= crane.currentMaterials.length && !crane.isCarrying) {
if (humanAsset?.animationState?.current === "working_standing" && humanAsset?.animationState?.isCompleted && humanId && humanAction && humanAction.actionType === "operator") {
setCurrentAnimation(humanId, "idle", true, true, true);
setIsCaryying(crane.modelUuid, true);
setCurrentPhase(crane.modelUuid, 'pickup-drop');
setCurrentPhase(crane.modelUuid, "pickup-drop");
} else {
setCurrentPhaseHuman(humanId, 'hooking');
setCurrentPhaseHuman(humanId, "hooking");
setHumanActive(humanId, true);
setHumanState(humanId, 'running');
setCurrentAnimation(humanId, 'working_standing', true, false, false);
setHumanState(humanId, "running");
setCurrentAnimation(humanId, "working_standing", true, false, false);
}
} else if (crane.currentPhase === 'dropping' && crane.currentMaterials.length > 0 && action.maxPickUpCount <= crane.currentMaterials.length && crane.isCarrying && human.currentPhase === 'hooking') {
setCurrentPhaseHuman(humanId, 'loadPoint-unloadPoint');
} else if (human.state === 'running' && human.currentPhase === 'unhooking') {
} else if (crane.currentPhase === "dropping" && crane.currentMaterials.length > 0 && action.maxPickUpCount <= crane.currentMaterials.length && crane.isCarrying && human.currentPhase === "hooking") {
setCurrentPhaseHuman(humanId, "loadPoint-unloadPoint");
} else if (human.state === "running" && human.currentPhase === "unhooking") {
if (humanAsset?.animationState?.current === "working_standing" && humanAsset?.animationState?.isCompleted) {
setCurrentPhase(crane.modelUuid, 'init');
setCurrentPhase(crane.modelUuid, "init");
setCraneActive(crane.modelUuid, false);
setCurrentAnimation(humanId, 'idle', true, true, true);
setCurrentPhaseHuman(humanId, 'init');
setCurrentAnimation(humanId, "idle", true, true, true);
setCurrentPhaseHuman(humanId, "init");
setHumanActive(humanId, false);
setHumanState(humanId, 'idle');
setHumanState(humanId, "idle");
handleMaterialDrop();
}
}
}
}, [crane, humanAsset?.animationState?.isCompleted])
}, [crane, humanAsset?.animationState?.isCompleted]);
const handleMaterialDrop = () => {
if (humanAction && humanAction.actionType === 'operator') {
if (humanAction && humanAction.actionType === "operator") {
setIsCaryying(crane.modelUuid, false);
removeCurrentAction(crane.modelUuid);
const removedMaterial = removeLastMaterial(crane.modelUuid);
@@ -72,41 +69,27 @@ function PillarJibInstance({ crane }: { readonly crane: CraneStatus }) {
triggerPointActions(humanAction, removedMaterial.materialId);
}
}
}
};
const handleAnimationComplete = (action: string) => {
if (action === 'starting') {
setAnimationPhase('first-hook-adjust');
} else if (action === 'picking') {
setCurrentPhase(crane.modelUuid, 'picking');
} else if (action === 'dropping') {
setCurrentPhase(crane.modelUuid, 'dropping');
}
if (action === "starting") {
setAnimationPhase("first-hook-adjust");
} else if (action === "picking") {
setCurrentPhase(crane.modelUuid, "picking");
} else if (action === "dropping") {
setCurrentPhase(crane.modelUuid, "dropping");
}
};
return (
<>
<PillarJibAnimator
key={crane.modelUuid}
crane={crane}
points={points}
setPoints={setPoints}
animationPhase={animationPhase}
setAnimationPhase={setAnimationPhase}
onAnimationComplete={handleAnimationComplete}
/>
<PillarJibAnimator key={crane.modelUuid} crane={crane} points={points} setPoints={setPoints} animationPhase={animationPhase} setAnimationPhase={setAnimationPhase} onAnimationComplete={handleAnimationComplete} />
<MaterialAnimator crane={crane} />
<PillarJibHelper
crane={crane}
points={points}
isHelperNeeded={false}
/>
<PillarJibHelper crane={crane} points={points} isHelperNeeded={false} />
</>
)
);
}
export default PillarJibInstance;

View File

@@ -1,10 +1,9 @@
import { useParams } from "react-router-dom";
import * as THREE from "three";
import { useMemo, useRef, useState } from "react";
import { useThree } from "@react-three/fiber";
import { useToolMode } from "../../../../store/builder/store";
import { useSceneContext } from "../../../scene/sceneContext";
import { useProductContext } from "../../products/productContext";
import { useParams } from "react-router-dom";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
interface ConnectionLine {
@@ -20,10 +19,8 @@ export function Arrows({ connections }: { readonly connections: ConnectionLine[]
const { scene } = useThree();
const { toolMode } = useToolMode();
const { productStore, versionStore } = useSceneContext();
const { removeTrigger } = productStore();
const { removeTrigger, selectedProduct } = productStore();
const { selectedVersion } = versionStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { projectId } = useParams();
const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {

View File

@@ -8,7 +8,6 @@ import { useSelectedEventSphere, useSelectedEventData, useDeletableEventSphere }
import { useThree } from "@react-three/fiber";
import { usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { upsertProductOrEventApi } from "../../../../../services/simulation/products/UpsertProductOrEventApi";
import { useProductContext } from "../../../products/productContext";
import { useParams } from "react-router-dom";
import { useSceneContext } from "../../../../scene/sceneContext";
@@ -19,11 +18,9 @@ function PointsCreator() {
const { subModule } = useSubModuleStore();
const { toolMode } = useToolMode();
const { activeModule } = useModuleStore();
const { selectedProductStore } = useProductContext();
const { eventStore, productStore, versionStore } = useSceneContext();
const { getEventByModelUuid } = eventStore();
const { getEventByModelUuid: getEventByModelUuidFromProduct, updatePoint: updatePointFromProduct, getPointByUuid: getPointByUuidFromProduct, getTriggersByTriggeredPointUuid, removeTrigger, removePoint } = productStore();
const { selectedProduct } = selectedProductStore();
const { getEventByModelUuid: getEventByModelUuidFromProduct, updatePoint: updatePointFromProduct, getPointByUuid: getPointByUuidFromProduct, getTriggersByTriggeredPointUuid, removeTrigger, removePoint, selectedProduct } = productStore();
const transformRef = useRef<any>(null);
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
const { selectedEventSphere, clearSelectedEventSphere } = useSelectedEventSphere();

View File

@@ -1,11 +1,10 @@
import { useParams } from "react-router-dom";
import * as THREE from "three";
import { MeshProps } from "@react-three/fiber";
import { useRef } from "react";
import { useToolMode } from "../../../../../../store/builder/store";
import { useDeletableEventSphere, useSelectedEventSphere } from "../../../../../../store/simulation/useSimulationStore";
import { useSceneContext } from "../../../../../scene/sceneContext";
import { useProductContext } from "../../../../products/productContext";
import { useParams } from "react-router-dom";
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
interface PointInstanceProps extends Omit<MeshProps, "ref"> {
@@ -23,9 +22,7 @@ export default function PointInstance({ point, modelUuid, color, ...meshProps }:
const { deletableEventSphere, setDeletableEventSphere, clearDeletableEventSphere } = useDeletableEventSphere();
const { toolMode } = useToolMode();
const { productStore, versionStore } = useSceneContext();
const { getEventByModelUuid, getTriggersByTriggeredPointUuid, removeTrigger, removePoint } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getEventByModelUuid, getTriggersByTriggeredPointUuid, removeTrigger, removePoint, selectedProduct } = productStore();
const { selectedVersion } = versionStore();
const { projectId } = useParams();

View File

@@ -1,15 +1,11 @@
import { useProductContext } from "../../../products/productContext";
import { useSceneContext } from "../../../../scene/sceneContext";
import PointInstance from "./instance/pointInstance";
function PointInstances() {
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { eventStore, productStore } = useSceneContext();
const { events } = eventStore();
const { getEventByModelUuid } = productStore();
const { getEventByModelUuid, selectedProduct } = productStore();
const colorByType: Record<string, string> = {
transfer: "orange",
@@ -24,7 +20,7 @@ function PointInstances() {
return (
<>
{events.map((event, index) => {
const updatedEvent = selectedProduct.productUuid !== '' ? getEventByModelUuid(selectedProduct.productUuid, event.modelUuid) : null;
const updatedEvent = selectedProduct.productUuid !== "" ? getEventByModelUuid(selectedProduct.productUuid, event.modelUuid) : null;
const usedEvent = updatedEvent || event;
const color = colorByType[usedEvent.type];
@@ -34,18 +30,9 @@ function PointInstances() {
const points = usedEvent.type === "transfer" ? usedEvent.points : [usedEvent.point];
return (
<group
key={`${index}-${usedEvent.modelUuid}`}
position={usedEvent.position}
rotation={usedEvent.rotation}
>
<group key={`${index}-${usedEvent.modelUuid}`} position={usedEvent.position} rotation={usedEvent.rotation}>
{points.map((point) => (
<PointInstance
key={point.uuid}
point={point}
modelUuid={usedEvent.modelUuid}
color={color}
/>
<PointInstance key={point.uuid} point={point} modelUuid={usedEvent.modelUuid} color={color} />
))}
</group>
);

View File

@@ -1,6 +1,7 @@
import { useParams } from "react-router-dom";
import * as THREE from "three";
import { useEffect, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import * as THREE from "three";
import { useSubModuleStore } from "../../../../store/ui/useModuleStore";
import { useSelectedAction, useSelectedAsset, useSelectedEventData } from "../../../../store/simulation/useSimulationStore";
import { handleAddEventToProduct } from "../points/functions/handleAddEventToProduct";
@@ -8,8 +9,6 @@ import { QuadraticBezierLine } from "@react-three/drei";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
import { usePlayButtonStore } from "../../../../store/ui/usePlayButtonStore";
import { ArrowOnQuadraticBezier, Arrows } from "../arrows/arrows";
import { useProductContext } from "../../products/productContext";
import { useParams } from "react-router-dom";
import { useToolMode } from "../../../../store/builder/store";
import { useSceneContext } from "../../../scene/sceneContext";
@@ -23,11 +22,9 @@ interface ConnectionLine {
function TriggerConnector() {
const { gl, raycaster, scene, pointer, camera } = useThree();
const { subModule } = useSubModuleStore();
const { selectedProductStore } = useProductContext();
const { eventStore, productStore, versionStore } = useSceneContext();
const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, removeTrigger, addEvent, getEventByModelUuid, getPointUuidByActionUuid, getProductById } = productStore();
const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, removeTrigger, addEvent, getEventByModelUuid, getPointUuidByActionUuid, getProductById, selectedProduct } = productStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const { selectedProduct } = selectedProductStore();
const [hoveredLineKey, setHoveredLineKey] = useState<string | null>(null);
const groupRefs = useRef<Record<string, any>>({});
const [helperLineColor, setHelperLineColor] = useState<string>("red");

View File

@@ -1,16 +1,13 @@
import { useEffect } from 'react';
import { useFrame } from '@react-three/fiber';
import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../scene/sceneContext';
import { useProductContext } from '../../products/productContext';
import { useEffect } from "react";
import { useFrame } from "@react-three/fiber";
import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../scene/sceneContext";
export function useHumanEventManager() {
const { humanStore, productStore, assetStore, humanEventManagerRef } = useSceneContext();
const { getHumanById, setCurrentPhase, removeCurrentAction } = humanStore();
const { getAssetById } = assetStore();
const { getActionByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, selectedProduct } = productStore();
const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore();
@@ -25,24 +22,24 @@ export function useHumanEventManager() {
const addHumanToMonitor = (humanId: string, callback: () => void, actionUuid: string) => {
const human = getHumanById(humanId);
const action = getActionByUuid(selectedProduct.productUuid, actionUuid);
if (!human || !action || (action.actionType !== 'manufacturer' && action.actionType !== 'worker' && action.actionType !== 'operator') || !humanEventManagerRef.current) return;
if (!human || !action || (action.actionType !== "manufacturer" && action.actionType !== "worker" && action.actionType !== "operator") || !humanEventManagerRef.current) return;
let state = humanEventManagerRef.current.humanStates.find(h => h.humanId === humanId);
let state = humanEventManagerRef.current.humanStates.find((h) => h.humanId === humanId);
if (!state) {
state = { humanId, actionQueue: [], isCooldown: false };
humanEventManagerRef.current.humanStates.push(state);
}
const existingAction = state.actionQueue.find(a => a.actionUuid === actionUuid);
const existingAction = state.actionQueue.find((a) => a.actionUuid === actionUuid);
if (existingAction) {
const currentCount = existingAction.count ?? 0;
if (existingAction.actionType === 'worker' || existingAction.actionType === 'operator') {
if (existingAction.actionType === "worker" || existingAction.actionType === "operator") {
if (currentCount < existingAction.maxLoadCount) {
existingAction.callback = callback;
existingAction.isMonitored = true;
existingAction.isCompleted = false;
}
} else if (existingAction.actionType === 'manufacturer') {
} else if (existingAction.actionType === "manufacturer") {
if (currentCount < existingAction.maxManufactureCount) {
existingAction.callback = callback;
existingAction.isMonitored = true;
@@ -61,16 +58,16 @@ export function useHumanEventManager() {
count: 0,
isMonitored: true,
isCompleted: false,
callback
callback,
});
};
const removeHumanFromMonitor = (humanId: string, actionUuid: string) => {
if (!humanEventManagerRef.current) return;
const state = humanEventManagerRef.current.humanStates.find(h => h.humanId === humanId);
const state = humanEventManagerRef.current.humanStates.find((h) => h.humanId === humanId);
if (!state) return;
const action = state.actionQueue.find(a => a.actionUuid === actionUuid);
const action = state.actionQueue.find((a) => a.actionUuid === actionUuid);
if (action) {
action.callback = undefined;
action.isMonitored = false;
@@ -86,43 +83,42 @@ export function useHumanEventManager() {
const { humanId, actionQueue } = humanState;
if (!actionQueue || actionQueue.length === 0) continue;
const action = actionQueue.find(a => !a.isCompleted);
const action = actionQueue.find((a) => !a.isCompleted);
if (!action || !action.isMonitored || !action.callback) continue;
const human = getHumanById(humanId);
const humanAsset = getAssetById(humanId);
const currentAction = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '') as HumanAction | undefined;
const currentAction = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || "") as HumanAction | undefined;
if (!human || !humanAsset || !currentAction) continue;
if (human.isActive || human.state !== "idle" || humanAsset.animationState?.current !== 'idle') continue;
if (human.isActive || human.state !== "idle" || humanAsset.animationState?.current !== "idle") continue;
let conditionMet = false;
if (currentAction.actionType === 'worker' || currentAction.actionType === 'operator') {
if ((action.actionType === 'worker' || action.actionType === 'operator') && human.currentLoad < currentAction.loadCapacity) {
if (currentAction.actionType === "worker" || currentAction.actionType === "operator") {
if ((action.actionType === "worker" || action.actionType === "operator") && human.currentLoad < currentAction.loadCapacity) {
conditionMet = true;
} else if (action.actionType === 'manufacturer') {
} else if (action.actionType === "manufacturer") {
conditionMet = true;
}
} else if (currentAction.actionType === 'manufacturer') {
if (action.actionType === 'manufacturer') {
} else if (currentAction.actionType === "manufacturer") {
if (action.actionType === "manufacturer") {
conditionMet = true;
} else if ((action.actionType === 'worker' || action.actionType === 'operator') && human.currentLoad < currentAction.loadCapacity) {
} else if ((action.actionType === "worker" || action.actionType === "operator") && human.currentLoad < currentAction.loadCapacity) {
conditionMet = true;
}
}
if (conditionMet) {
if (action.actionUuid !== human.currentAction?.actionUuid) {
setCurrentPhase(human.modelUuid, 'init');
setCurrentPhase(human.modelUuid, "init");
removeCurrentAction(human.modelUuid);
}
action.callback();
action.count = (action.count ?? 0) + 1;
action.isMonitored = false;
if (((action.actionType === 'worker' || action.actionType === 'operator') && action.count >= action.maxLoadCount) ||
(action.actionType === 'manufacturer' && action.count >= action.maxManufactureCount)) {
if (((action.actionType === "worker" || action.actionType === "operator") && action.count >= action.maxLoadCount) || (action.actionType === "manufacturer" && action.count >= action.maxManufactureCount)) {
action.isCompleted = true;
}
humanState.isCooldown = true;
@@ -137,6 +133,6 @@ export function useHumanEventManager() {
return {
addHumanToMonitor,
removeHumanFromMonitor
removeHumanFromMonitor,
};
}

View File

@@ -1,10 +1,9 @@
import { useEffect, useRef, useState } from 'react';
import { useFrame, useThree } from '@react-three/fiber';
import * as THREE from 'three';
import { Line } from '@react-three/drei';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import { useEffect, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import * as THREE from "three";
import { Line } from "@react-three/drei";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
interface ManufacturerAnimatorProps {
path: [number, number, number][];
@@ -15,9 +14,7 @@ interface ManufacturerAnimatorProps {
function ManufacturerAnimator({ path, handleCallBack, human, reset }: Readonly<ManufacturerAnimatorProps>) {
const { humanStore, assetStore, productStore } = useSceneContext();
const { getActionByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, selectedProduct } = productStore();
const { getHumanById } = humanStore();
const { setCurrentAnimation } = assetStore();
const { isPaused } = usePauseButtonStore();
@@ -26,7 +23,7 @@ function ManufacturerAnimator({ path, handleCallBack, human, reset }: Readonly<M
const { isReset, setReset } = useResetButtonStore();
const progressRef = useRef<number>(0);
const completedRef = useRef<boolean>(false);
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || "");
const [objectRotation, setObjectRotation] = useState<[number, number, number] | null>((action as HumanAction)?.manufacturePoint?.rotation || [0, 0, 0]);
const [restingRotation, setRestingRotation] = useState<boolean>(true);
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
@@ -34,7 +31,7 @@ function ManufacturerAnimator({ path, handleCallBack, human, reset }: Readonly<M
useEffect(() => {
if (!human.currentAction?.actionUuid) return;
if (human.currentPhase === 'init-manufacture' && path.length > 0) {
if (human.currentPhase === "init-manufacture" && path.length > 0) {
setCurrentPath(path);
setObjectRotation((action as HumanAction)?.manufacturePoint?.rotation ?? null);
}
@@ -52,7 +49,7 @@ function ManufacturerAnimator({ path, handleCallBack, human, reset }: Readonly<M
progressRef.current = 0;
setReset(false);
setRestingRotation(true);
const object = scene.getObjectByProperty('uuid', human.modelUuid);
const object = scene.getObjectByProperty("uuid", human.modelUuid);
const humanData = getHumanById(human.modelUuid);
if (object && humanData) {
object.position.set(humanData.position[0], humanData.position[1], humanData.position[2]);
@@ -68,7 +65,7 @@ function ManufacturerAnimator({ path, handleCallBack, human, reset }: Readonly<M
const delta = (now - lastTimeRef.current) / 1000;
lastTimeRef.current = now;
const object = scene.getObjectByProperty('uuid', human.modelUuid);
const object = scene.getObjectByProperty("uuid", human.modelUuid);
if (!object || currentPath.length < 2) return;
if (isPaused || !isPlaying) return;
@@ -96,9 +93,7 @@ function ManufacturerAnimator({ path, handleCallBack, human, reset }: Readonly<M
const end = new THREE.Vector3(...currentPath[index + 1]);
const segmentDistance = distances[index];
const targetQuaternion = new THREE.Quaternion().setFromRotationMatrix(
new THREE.Matrix4().lookAt(start, end, new THREE.Vector3(0, 1, 0))
);
const targetQuaternion = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().lookAt(start, end, new THREE.Vector3(0, 1, 0)));
const y180 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
targetQuaternion.multiply(y180);
@@ -117,9 +112,9 @@ function ManufacturerAnimator({ path, handleCallBack, human, reset }: Readonly<M
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
const position = start.clone().lerp(end, t);
object.position.copy(position);
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
setCurrentAnimation(human.modelUuid, "walking", true, true, true);
} else {
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
}
}
@@ -139,7 +134,7 @@ function ManufacturerAnimator({ path, handleCallBack, human, reset }: Readonly<M
object.quaternion.rotateTowards(targetQuaternion, step);
}
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
return;
}
}

View File

@@ -1,19 +1,16 @@
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';
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";
const MaterialAnimator = ({ human }: { human: HumanStatus; }) => {
const MaterialAnimator = ({ human }: { human: HumanStatus }) => {
const { productStore } = useSceneContext();
const { getActionByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, selectedProduct } = productStore();
const meshRef = useRef<any>(null!);
const [hasLoad, setHasLoad] = useState(false);
const [isAttached, setIsAttached] = useState(false);
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || "");
const { scene } = useThree();
useEffect(() => {
@@ -31,7 +28,7 @@ const MaterialAnimator = ({ human }: { human: HumanStatus; }) => {
meshRef.current.visible = false;
const bone = humanModel.getObjectByName('PlaceObjectRefBone') as THREE.Bone;
const bone = humanModel.getObjectByName("PlaceObjectRefBone") as THREE.Bone;
if (bone) {
if (meshRef.current.parent) {
meshRef.current.parent.remove(meshRef.current);
@@ -48,18 +45,7 @@ const MaterialAnimator = ({ human }: { human: HumanStatus; }) => {
}
}, [hasLoad, human.modelUuid, scene, human.currentPhase]);
return (
<>
{hasLoad && action && (action as HumanAction).actionType === 'worker' && human.currentMaterials.length > 0 && (human.currentPhase !== 'init-pickup' && human.currentPhase !== 'init-manufacture' && human.currentPhase !== 'drop-pickup') && (
<MaterialModel
matRef={meshRef}
materialId={`human-${human.currentMaterials[0].materialId}` || ''}
materialType={human.currentMaterials[0].materialType || 'Default material'}
visible={isAttached}
/>
)}
</>
);
return <>{hasLoad && action && (action as HumanAction).actionType === "worker" && human.currentMaterials.length > 0 && human.currentPhase !== "init-pickup" && human.currentPhase !== "init-manufacture" && human.currentPhase !== "drop-pickup" && <MaterialModel matRef={meshRef} materialId={`human-${human.currentMaterials[0].materialId}` || ""} materialType={human.currentMaterials[0].materialType || "Default material"} visible={isAttached} />}</>;
};
export default MaterialAnimator;

View File

@@ -1,10 +1,9 @@
import { useEffect, useRef, useState } from 'react';
import { useFrame, useThree } from '@react-three/fiber';
import * as THREE from 'three';
import { Line } from '@react-three/drei';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import { useEffect, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import * as THREE from "three";
import { Line } from "@react-three/drei";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
interface WorkerAnimatorProps {
path: [number, number, number][];
@@ -15,9 +14,7 @@ interface WorkerAnimatorProps {
function OperatorAnimator({ path, handleCallBack, human, reset }: Readonly<WorkerAnimatorProps>) {
const { humanStore, assetStore, productStore } = useSceneContext();
const { getActionByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, selectedProduct } = productStore();
const { getHumanById } = humanStore();
const { setCurrentAnimation } = assetStore();
const { isPaused } = usePauseButtonStore();
@@ -27,7 +24,7 @@ function OperatorAnimator({ path, handleCallBack, human, reset }: Readonly<Worke
const progressRef = useRef<number>(0);
const movingForward = useRef<boolean>(true);
const completedRef = useRef<boolean>(false);
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
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 [restingRotation, setRestingRotation] = useState<boolean>(true);
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
@@ -35,14 +32,14 @@ function OperatorAnimator({ path, handleCallBack, human, reset }: Readonly<Worke
useEffect(() => {
if (!human.currentAction?.actionUuid) return;
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
if (human.currentPhase === 'init-loadPoint' && path.length > 0) {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || "");
if (human.currentPhase === "init-loadPoint" && path.length > 0) {
setCurrentPath(path);
setObjectRotation((action as HumanAction).pickUpPoint?.rotation ?? null);
} else if (human.currentPhase === 'loadPoint-unloadPoint' && path.length > 0) {
} else if (human.currentPhase === "loadPoint-unloadPoint" && path.length > 0) {
setObjectRotation((action as HumanAction)?.dropPoint?.rotation ?? null);
setCurrentPath(path);
} else if (human.currentPhase === 'unloadPoint-loadPoint' && path.length > 0) {
} else if (human.currentPhase === "unloadPoint-loadPoint" && path.length > 0) {
setObjectRotation((action as HumanAction)?.pickUpPoint?.rotation ?? null);
setCurrentPath(path);
}
@@ -61,7 +58,7 @@ function OperatorAnimator({ path, handleCallBack, human, reset }: Readonly<Worke
progressRef.current = 0;
setReset(false);
setRestingRotation(true);
const object = scene.getObjectByProperty('uuid', human.modelUuid);
const object = scene.getObjectByProperty("uuid", human.modelUuid);
const humanData = getHumanById(human.modelUuid);
if (object && humanData) {
object.position.set(humanData.position[0], humanData.position[1], humanData.position[2]);
@@ -77,7 +74,7 @@ function OperatorAnimator({ path, handleCallBack, human, reset }: Readonly<Worke
const delta = (now - lastTimeRef.current) / 1000;
lastTimeRef.current = now;
const object = scene.getObjectByProperty('uuid', human.modelUuid);
const object = scene.getObjectByProperty("uuid", human.modelUuid);
if (!object || currentPath.length < 2) return;
if (isPaused || !isPlaying) return;
@@ -105,9 +102,7 @@ function OperatorAnimator({ path, handleCallBack, human, reset }: Readonly<Worke
const end = new THREE.Vector3(...currentPath[index + 1]);
const segmentDistance = distances[index];
const targetQuaternion = new THREE.Quaternion().setFromRotationMatrix(
new THREE.Matrix4().lookAt(start, end, new THREE.Vector3(0, 1, 0))
);
const targetQuaternion = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().lookAt(start, end, new THREE.Vector3(0, 1, 0)));
const y180 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
targetQuaternion.multiply(y180);
@@ -126,9 +121,9 @@ function OperatorAnimator({ path, handleCallBack, human, reset }: Readonly<Worke
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
const position = start.clone().lerp(end, t);
object.position.copy(position);
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
setCurrentAnimation(human.modelUuid, "walking", true, true, true);
} else {
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
}
}
@@ -148,7 +143,7 @@ function OperatorAnimator({ path, handleCallBack, human, reset }: Readonly<Worke
object.quaternion.rotateTowards(targetQuaternion, step);
}
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
return;
}
}

View File

@@ -1,10 +1,9 @@
import { useEffect, useRef, useState } from 'react';
import { useFrame, useThree } from '@react-three/fiber';
import * as THREE from 'three';
import { Line } from '@react-three/drei';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import { useEffect, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import * as THREE from "three";
import { Line } from "@react-three/drei";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
interface WorkerAnimatorProps {
path: [number, number, number][];
@@ -16,9 +15,7 @@ interface WorkerAnimatorProps {
function WorkerAnimator({ path, handleCallBack, human, reset, startUnloadingProcess }: Readonly<WorkerAnimatorProps>) {
const { humanStore, assetStore, productStore } = useSceneContext();
const { getActionByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, selectedProduct } = productStore();
const { getHumanById } = humanStore();
const { setCurrentAnimation } = assetStore();
const { isPaused } = usePauseButtonStore();
@@ -28,7 +25,7 @@ function WorkerAnimator({ path, handleCallBack, human, reset, startUnloadingProc
const progressRef = useRef<number>(0);
const movingForward = useRef<boolean>(true);
const completedRef = useRef<boolean>(false);
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
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 [restingRotation, setRestingRotation] = useState<boolean>(true);
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
@@ -36,14 +33,14 @@ function WorkerAnimator({ path, handleCallBack, human, reset, startUnloadingProc
useEffect(() => {
if (!human.currentAction?.actionUuid) return;
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
if (human.currentPhase === 'init-pickup' && path.length > 0) {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || "");
if (human.currentPhase === "init-pickup" && path.length > 0) {
setCurrentPath(path);
setObjectRotation((action as HumanAction).pickUpPoint?.rotation ?? null);
} else if (human.currentPhase === 'pickup-drop' && path.length > 0) {
} else if (human.currentPhase === "pickup-drop" && path.length > 0) {
setObjectRotation((action as HumanAction)?.dropPoint?.rotation ?? null);
setCurrentPath(path);
} else if (human.currentPhase === 'drop-pickup' && path.length > 0) {
} else if (human.currentPhase === "drop-pickup" && path.length > 0) {
setObjectRotation((action as HumanAction)?.pickUpPoint?.rotation ?? null);
setCurrentPath(path);
}
@@ -62,7 +59,7 @@ function WorkerAnimator({ path, handleCallBack, human, reset, startUnloadingProc
progressRef.current = 0;
setReset(false);
setRestingRotation(true);
const object = scene.getObjectByProperty('uuid', human.modelUuid);
const object = scene.getObjectByProperty("uuid", human.modelUuid);
const humanData = getHumanById(human.modelUuid);
if (object && humanData) {
object.position.set(humanData.position[0], humanData.position[1], humanData.position[2]);
@@ -78,7 +75,7 @@ function WorkerAnimator({ path, handleCallBack, human, reset, startUnloadingProc
const delta = (now - lastTimeRef.current) / 1000;
lastTimeRef.current = now;
const object = scene.getObjectByProperty('uuid', human.modelUuid);
const object = scene.getObjectByProperty("uuid", human.modelUuid);
if (!object || currentPath.length < 2) return;
if (isPaused || !isPlaying) return;
@@ -106,9 +103,7 @@ function WorkerAnimator({ path, handleCallBack, human, reset, startUnloadingProc
const end = new THREE.Vector3(...currentPath[index + 1]);
const segmentDistance = distances[index];
const targetQuaternion = new THREE.Quaternion().setFromRotationMatrix(
new THREE.Matrix4().lookAt(start, end, new THREE.Vector3(0, 1, 0))
);
const targetQuaternion = new THREE.Quaternion().setFromRotationMatrix(new THREE.Matrix4().lookAt(start, end, new THREE.Vector3(0, 1, 0)));
const y180 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
targetQuaternion.multiply(y180);
@@ -127,16 +122,16 @@ function WorkerAnimator({ path, handleCallBack, human, reset, startUnloadingProc
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
const position = start.clone().lerp(end, t);
object.position.copy(position);
if (human.currentMaterials.length > 0 && (human.currentPhase !== 'init-pickup' && human.currentPhase !== 'init-manufacture' && human.currentPhase !== 'drop-pickup')) {
setCurrentAnimation(human.modelUuid, 'walk_with_box', true, true, true);
if (human.currentMaterials.length > 0 && human.currentPhase !== "init-pickup" && human.currentPhase !== "init-manufacture" && human.currentPhase !== "drop-pickup") {
setCurrentAnimation(human.modelUuid, "walk_with_box", true, true, true);
} else {
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
setCurrentAnimation(human.modelUuid, "walking", true, true, true);
}
} else if (!isAligned) {
if (human.currentMaterials.length > 0 && (human.currentPhase !== 'init-pickup' && human.currentPhase !== 'init-manufacture' && human.currentPhase !== 'drop-pickup')) {
setCurrentAnimation(human.modelUuid, 'idle_with_box', true, true, true);
if (human.currentMaterials.length > 0 && human.currentPhase !== "init-pickup" && human.currentPhase !== "init-manufacture" && human.currentPhase !== "drop-pickup") {
setCurrentAnimation(human.modelUuid, "idle_with_box", true, true, true);
} else {
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
}
}
}
@@ -157,11 +152,7 @@ function WorkerAnimator({ path, handleCallBack, human, reset, startUnloadingProc
object.quaternion.rotateTowards(targetQuaternion, step);
}
setCurrentAnimation(
human.modelUuid,
human.currentMaterials.length > 0 ? 'idle_with_box' : 'idle',
true, true, true
);
setCurrentAnimation(human.modelUuid, human.currentMaterials.length > 0 ? "idle_with_box" : "idle", true, true, true);
return;
}
}
@@ -172,7 +163,7 @@ function WorkerAnimator({ path, handleCallBack, human, reset, startUnloadingProc
movingForward.current = !movingForward.current;
setCurrentPath([]);
handleCallBack();
if (human.currentPhase === 'pickup-drop') {
if (human.currentPhase === "pickup-drop") {
requestAnimationFrame(startUnloadingProcess);
}
}

View File

@@ -1,14 +1,13 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { useThree } from '@react-three/fiber';
import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh } from '../../../../../../store/builder/store';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../../store/ui/usePlayButtonStore';
import { useTriggerHandler } from '../../../../triggers/triggerHandler/useTriggerHandler';
import { useSceneContext } from '../../../../../scene/sceneContext';
import { useProductContext } from '../../../../products/productContext';
import { useCallback, useEffect, useRef, useState } from "react";
import * as THREE from "three";
import { useThree } from "@react-three/fiber";
import { NavMeshQuery } from "@recast-navigation/core";
import { useNavMesh } from "../../../../../../store/builder/store";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from "../../../../../../store/ui/usePlayButtonStore";
import { useTriggerHandler } from "../../../../triggers/triggerHandler/useTriggerHandler";
import { useSceneContext } from "../../../../../scene/sceneContext";
import ManufacturerAnimator from '../../animator/manufacturerAnimator';
import ManufacturerAnimator from "../../animator/manufacturerAnimator";
function ManufacturerInstance({ human }: { readonly human: HumanStatus }) {
const { navMesh } = useNavMesh();
@@ -18,9 +17,7 @@ function ManufacturerInstance({ human }: { readonly human: HumanStatus }) {
const { setMaterial } = materialStore();
const { triggerPointActions } = useTriggerHandler();
const { setCurrentAnimation, resetAnimation, getAssetById } = assetStore();
const { getActionByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, selectedProduct } = productStore();
const { setHumanActive, setHumanState, decrementHumanLoad, removeLastMaterial, setCurrentPhase } = humanStore();
const [path, setPath] = useState<[number, number, number][]>([]);
@@ -45,20 +42,17 @@ function ManufacturerInstance({ human }: { readonly human: HumanStatus }) {
isSpeedRef.current = speed;
}, [speed]);
const computePath = useCallback((start: [number, number, number], end: [number, number, number]) => {
const computePath = useCallback(
(start: [number, number, number], end: [number, number, number]) => {
try {
const navMeshQuery = new NavMeshQuery(navMesh);
let startPoint = new THREE.Vector3(start[0], start[1], start[2]);
let endPoint = new THREE.Vector3(end[0], end[1], end[2]);
const { path: segmentPath } = navMeshQuery.computePath(startPoint, endPoint);
if (
segmentPath.length > 0 &&
Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(endPoint.x) &&
Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(endPoint.z)
) {
if (segmentPath.length > 0 && Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(endPoint.x) && Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(endPoint.z)) {
return segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
} else {
console.log("There is no path here...Choose valid path")
console.log("There is no path here...Choose valid path");
const { path: segmentPaths } = navMeshQuery.computePath(startPoint, startPoint);
return segmentPaths.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
}
@@ -66,16 +60,18 @@ function ManufacturerInstance({ human }: { readonly human: HumanStatus }) {
console.error("Failed to compute path");
return [];
}
}, [navMesh]);
},
[navMesh]
);
function humanStatus(modelId: string, status: string) {
// console.log(`${modelId} , ${status}`);
}
function reset() {
setCurrentPhase(human.modelUuid, 'init');
setCurrentPhase(human.modelUuid, "init");
setHumanActive(human.modelUuid, false);
setHumanState(human.modelUuid, 'idle');
setHumanState(human.modelUuid, "idle");
resetAnimation(human.modelUuid);
setPath([]);
if (processAnimationIdRef.current) {
@@ -88,7 +84,7 @@ function ManufacturerInstance({ human }: { readonly human: HumanStatus }) {
lastPauseTimeRef.current = null;
hasLoggedHalfway.current = false;
hasLoggedCompleted.current = false;
const object = scene.getObjectByProperty('uuid', human.modelUuid);
const object = scene.getObjectByProperty("uuid", human.modelUuid);
if (object && human) {
object.position.set(human.position[0], human.position[1], human.position[2]);
object.rotation.set(human.rotation[0], human.rotation[1], human.rotation[2]);
@@ -97,26 +93,26 @@ function ManufacturerInstance({ human }: { readonly human: HumanStatus }) {
useEffect(() => {
if (isPlaying) {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || "");
if (!action || !(action as HumanAction).manufacturePoint || (action as HumanAction).actionType === 'worker') return;
if (!action || !(action as HumanAction).manufacturePoint || (action as HumanAction).actionType === "worker") return;
if (!human.isActive && human.state === 'idle' && human.currentPhase === 'init') {
const humanMesh = scene.getObjectByProperty('uuid', human.modelUuid);
if (!human.isActive && human.state === "idle" && human.currentPhase === "init") {
const humanMesh = scene.getObjectByProperty("uuid", human.modelUuid);
if (!humanMesh) return;
const toPickupPath = computePath(humanMesh.position.toArray(), (action as HumanAction)?.manufacturePoint?.position || [0, 0, 0]);
setPath(toPickupPath);
setHumanState(human.modelUuid, 'idle');
setCurrentPhase(human.modelUuid, 'init-manufacture');
setHumanState(human.modelUuid, "idle");
setCurrentPhase(human.modelUuid, "init-manufacture");
setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Human is waiting for material in manufacture');
} else if (!human.isActive && human.state === 'idle' && human.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');
setCurrentPhase(human.modelUuid, 'manufacturing');
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
humanStatus(human.modelUuid, "Human is waiting for material in manufacture");
} else if (!human.isActive && human.state === "idle" && human.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");
setCurrentPhase(human.modelUuid, "manufacturing");
setHumanActive(human.modelUuid, true);
processStartTimeRef.current = performance.now();
@@ -130,28 +126,28 @@ function ManufacturerInstance({ human }: { readonly human: HumanStatus }) {
processAnimationIdRef.current = requestAnimationFrame(trackManufactureProcess);
}
}
} else if (human.isActive && human.state === 'running' && human.currentMaterials.length > 0 && humanAsset && humanAsset.animationState?.current === 'working_standing' && humanAsset.animationState?.isCompleted) {
if ((action as HumanAction).manufacturePoint && human.currentPhase === 'manufacturing') {
setHumanState(human.modelUuid, 'idle');
setCurrentPhase(human.modelUuid, 'waiting');
} else if (human.isActive && human.state === "running" && human.currentMaterials.length > 0 && humanAsset && humanAsset.animationState?.current === "working_standing" && humanAsset.animationState?.isCompleted) {
if ((action as HumanAction).manufacturePoint && human.currentPhase === "manufacturing") {
setHumanState(human.modelUuid, "idle");
setCurrentPhase(human.modelUuid, "waiting");
setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Human is waiting for material in manufacture');
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
humanStatus(human.modelUuid, "Human is waiting for material in manufacture");
decrementHumanLoad(human.modelUuid, 1);
const material = removeLastMaterial(human.modelUuid);
if (material) {
triggerPointActions((action as HumanAction), material.materialId);
triggerPointActions(action as HumanAction, material.materialId);
}
}
}
} else {
reset()
reset();
}
}, [human, human.currentPhase, path, isPlaying, humanAsset?.animationState?.isCompleted]);
const trackManufactureProcess = useCallback(() => {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || "");
const now = performance.now();
@@ -176,14 +172,14 @@ function ManufacturerInstance({ human }: { readonly human: HumanStatus }) {
if (elapsed >= totalProcessTimeMs / 2 && !hasLoggedHalfway.current) {
hasLoggedHalfway.current = true;
if (human.currentMaterials.length > 0) {
setMaterial(human.currentMaterials[0].materialId, (action as HumanAction).swapMaterial || 'Default Material');
setMaterial(human.currentMaterials[0].materialId, (action as HumanAction).swapMaterial || "Default Material");
}
humanStatus(human.modelUuid, `🟡 Human ${human.modelUuid} reached halfway in manufacture.`);
}
if (elapsed >= totalProcessTimeMs && !hasLoggedCompleted.current) {
hasLoggedCompleted.current = true;
setCurrentAnimation(human.modelUuid, 'working_standing', true, true, true);
setCurrentAnimation(human.modelUuid, "working_standing", true, true, true);
if (processAnimationIdRef.current) {
cancelAnimationFrame(processAnimationIdRef.current);
processAnimationIdRef.current = null;
@@ -196,24 +192,17 @@ function ManufacturerInstance({ human }: { readonly human: HumanStatus }) {
}, [human.modelUuid, human.currentMaterials]);
function handleCallBack() {
if (human.currentPhase === 'init-manufacture') {
setCurrentPhase(human.modelUuid, 'waiting');
setHumanState(human.modelUuid, 'idle');
if (human.currentPhase === "init-manufacture") {
setCurrentPhase(human.modelUuid, "waiting");
setHumanState(human.modelUuid, "idle");
setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Reached manufacture point, waiting for material');
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
humanStatus(human.modelUuid, "Reached manufacture point, waiting for material");
setPath([]);
}
}
return (
<ManufacturerAnimator
path={path}
handleCallBack={handleCallBack}
human={human}
reset={reset}
/>
)
return <ManufacturerAnimator path={path} handleCallBack={handleCallBack} human={human} reset={reset} />;
}
export default ManufacturerInstance;

View File

@@ -1,13 +1,12 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { useThree } from '@react-three/fiber';
import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh } from '../../../../../../store/builder/store';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../../../scene/sceneContext';
import { useProductContext } from '../../../../products/productContext';
import { useCallback, useEffect, useRef, useState } from "react";
import * as THREE from "three";
import { useThree } from "@react-three/fiber";
import { NavMeshQuery } from "@recast-navigation/core";
import { useNavMesh } from "../../../../../../store/builder/store";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from "../../../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../../../scene/sceneContext";
import OperatorAnimator from '../../animator/operatorAnimator';
import OperatorAnimator from "../../animator/operatorAnimator";
function OperatorInstance({ human }: { readonly human: HumanStatus }) {
const { navMesh } = useNavMesh();
@@ -15,9 +14,7 @@ function OperatorInstance({ human }: { readonly human: HumanStatus }) {
const { scene } = useThree();
const { assetStore, humanStore, productStore } = useSceneContext();
const { setCurrentAnimation, resetAnimation, getAssetById } = assetStore();
const { getActionByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, selectedProduct } = productStore();
const { setHumanActive, setHumanState, setHumanLoad, setHumanScheduled, resetTime, setCurrentPhase } = humanStore();
const [path, setPath] = useState<[number, number, number][]>([]);
@@ -40,20 +37,17 @@ function OperatorInstance({ human }: { readonly human: HumanStatus }) {
isSpeedRef.current = speed;
}, [speed]);
const computePath = useCallback((start: [number, number, number], end: [number, number, number]) => {
const computePath = useCallback(
(start: [number, number, number], end: [number, number, number]) => {
try {
const navMeshQuery = new NavMeshQuery(navMesh);
let startPoint = new THREE.Vector3(start[0], start[1], start[2]);
let endPoint = new THREE.Vector3(end[0], end[1], end[2]);
const { path: segmentPath } = navMeshQuery.computePath(startPoint, endPoint);
if (
segmentPath.length > 0 &&
Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(endPoint.x) &&
Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(endPoint.z)
) {
if (segmentPath.length > 0 && Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(endPoint.x) && Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(endPoint.z)) {
return segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
} else {
console.log("There is no path here...Choose valid path")
console.log("There is no path here...Choose valid path");
const { path: segmentPaths } = navMeshQuery.computePath(startPoint, startPoint);
return segmentPaths.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
}
@@ -61,31 +55,33 @@ function OperatorInstance({ human }: { readonly human: HumanStatus }) {
console.error("Failed to compute path");
return [];
}
}, [navMesh]);
},
[navMesh]
);
function humanStatus(modelId: string, status: string) {
// console.log(`${modelId} , ${status}`);
}
function reset() {
setCurrentPhase(human.modelUuid, 'init');
setCurrentPhase(human.modelUuid, "init");
setHumanActive(human.modelUuid, false);
setHumanState(human.modelUuid, 'idle');
setHumanState(human.modelUuid, "idle");
setHumanScheduled(human.modelUuid, false);
setHumanLoad(human.modelUuid, 0);
resetAnimation(human.modelUuid);
setPath([]);
isPausedRef.current = false;
pauseTimeRef.current = 0;
resetTime(human.modelUuid)
activeTimeRef.current = 0
idleTimeRef.current = 0
previousTimeRef.current = null
resetTime(human.modelUuid);
activeTimeRef.current = 0;
idleTimeRef.current = 0;
previousTimeRef.current = null;
if (animationFrameIdRef.current !== null) {
cancelAnimationFrame(animationFrameIdRef.current)
animationFrameIdRef.current = null
cancelAnimationFrame(animationFrameIdRef.current);
animationFrameIdRef.current = null;
}
const object = scene.getObjectByProperty('uuid', human.modelUuid);
const object = scene.getObjectByProperty("uuid", human.modelUuid);
if (object && human) {
object.position.set(human.position[0], human.position[1], human.position[2]);
object.rotation.set(human.rotation[0], human.rotation[1], human.rotation[2]);
@@ -94,66 +90,59 @@ function OperatorInstance({ human }: { readonly human: HumanStatus }) {
useEffect(() => {
if (isPlaying) {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
if (!action || action.actionType !== 'operator' || !action.pickUpPoint || !action.dropPoint) return;
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || "");
if (!action || action.actionType !== "operator" || !action.pickUpPoint || !action.dropPoint) return;
if (!human.isActive && human.state === 'idle' && human.currentPhase === 'init') {
const humanMesh = scene.getObjectByProperty('uuid', human.modelUuid);
if (!human.isActive && human.state === "idle" && human.currentPhase === "init") {
const humanMesh = scene.getObjectByProperty("uuid", human.modelUuid);
if (!humanMesh) return;
const toPickupPath = computePath(humanMesh.position.toArray(), action?.pickUpPoint?.position || [0, 0, 0]);
setPath(toPickupPath);
setCurrentPhase(human.modelUuid, 'init-loadPoint');
setHumanState(human.modelUuid, 'running');
setCurrentPhase(human.modelUuid, "init-loadPoint");
setHumanState(human.modelUuid, "running");
setHumanActive(human.modelUuid, true);
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
humanStatus(human.modelUuid, 'Started from init, heading to loadPoint');
} else if (human.isActive && human.currentPhase === 'loadPoint-unloadPoint') {
if (action.pickUpPoint && action.dropPoint && humanAsset?.animationState?.current === 'idle') {
setCurrentAnimation(human.modelUuid, "walking", true, true, true);
humanStatus(human.modelUuid, "Started from init, heading to loadPoint");
} else if (human.isActive && human.currentPhase === "loadPoint-unloadPoint") {
if (action.pickUpPoint && action.dropPoint && humanAsset?.animationState?.current === "idle") {
const toDrop = computePath(action.pickUpPoint.position || [0, 0, 0], action.dropPoint.position || [0, 0, 0]);
setPath(toDrop);
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
humanStatus(human.modelUuid, 'Started from loadPoint, heading to unloadPoint');
setCurrentAnimation(human.modelUuid, "walking", true, true, true);
humanStatus(human.modelUuid, "Started from loadPoint, heading to unloadPoint");
}
} else if (human.state === 'idle' && human.currentPhase === 'unhooking') {
} else if (human.state === "idle" && human.currentPhase === "unhooking") {
setTimeout(() => {
setHumanState(human.modelUuid, 'running');
setHumanState(human.modelUuid, "running");
setHumanActive(human.modelUuid, true);
setCurrentAnimation(human.modelUuid, 'working_standing', true, false, false);
}, 1)
setCurrentAnimation(human.modelUuid, "working_standing", true, false, false);
}, 1);
}
} else {
reset()
reset();
}
}, [human, human.currentAction, human.currentPhase, path, isPlaying, humanAsset?.animationState?.isCompleted]);
function handleCallBack() {
if (human.currentPhase === 'init-loadPoint') {
setCurrentPhase(human.modelUuid, 'waiting');
setHumanState(human.modelUuid, 'idle');
if (human.currentPhase === "init-loadPoint") {
setCurrentPhase(human.modelUuid, "waiting");
setHumanState(human.modelUuid, "idle");
setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Reached loadPoint point, waiting for material');
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
humanStatus(human.modelUuid, "Reached loadPoint point, waiting for material");
setPath([]);
} else if (human.currentPhase === 'loadPoint-unloadPoint') {
setCurrentPhase(human.modelUuid, 'unhooking');
setHumanState(human.modelUuid, 'idle');
} else if (human.currentPhase === "loadPoint-unloadPoint") {
setCurrentPhase(human.modelUuid, "unhooking");
setHumanState(human.modelUuid, "idle");
setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Reached loadPoint point, waiting for material');
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
humanStatus(human.modelUuid, "Reached loadPoint point, waiting for material");
setPath([]);
}
}
return (
<OperatorAnimator
path={path}
handleCallBack={handleCallBack}
human={human}
reset={reset}
/>
)
return <OperatorAnimator path={path} handleCallBack={handleCallBack} human={human} reset={reset} />;
}
export default OperatorInstance;

View File

@@ -1,14 +1,13 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { useThree } from '@react-three/fiber';
import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh } from '../../../../../../store/builder/store';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../../store/ui/usePlayButtonStore';
import { useTriggerHandler } from '../../../../triggers/triggerHandler/useTriggerHandler';
import { useSceneContext } from '../../../../../scene/sceneContext';
import { useProductContext } from '../../../../products/productContext';
import { useCallback, useEffect, useRef, useState } from "react";
import * as THREE from "three";
import { useThree } from "@react-three/fiber";
import { NavMeshQuery } from "@recast-navigation/core";
import { useNavMesh } from "../../../../../../store/builder/store";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from "../../../../../../store/ui/usePlayButtonStore";
import { useTriggerHandler } from "../../../../triggers/triggerHandler/useTriggerHandler";
import { useSceneContext } from "../../../../../scene/sceneContext";
import WorkerAnimator from '../../animator/workerAnimator';
import WorkerAnimator from "../../animator/workerAnimator";
function WorkerInstance({ human }: { readonly human: HumanStatus }) {
const { navMesh } = useNavMesh();
@@ -23,9 +22,7 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
const { getMachineById } = machineStore();
const { triggerPointActions } = useTriggerHandler();
const { setCurrentAnimation, resetAnimation, getAssetById } = assetStore();
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid, selectedProduct } = productStore();
const { setHumanActive, setHumanState, clearCurrentMaterials, setHumanLoad, setHumanScheduled, decrementHumanLoad, removeLastMaterial, incrementIdleTime, incrementActiveTime, resetTime, setCurrentPhase } = humanStore();
const [path, setPath] = useState<[number, number, number][]>([]);
@@ -48,20 +45,17 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
isSpeedRef.current = speed;
}, [speed]);
const computePath = useCallback((start: [number, number, number], end: [number, number, number]) => {
const computePath = useCallback(
(start: [number, number, number], end: [number, number, number]) => {
try {
const navMeshQuery = new NavMeshQuery(navMesh);
let startPoint = new THREE.Vector3(start[0], start[1], start[2]);
let endPoint = new THREE.Vector3(end[0], end[1], end[2]);
const { path: segmentPath } = navMeshQuery.computePath(startPoint, endPoint);
if (
segmentPath.length > 0 &&
Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(endPoint.x) &&
Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(endPoint.z)
) {
if (segmentPath.length > 0 && Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(endPoint.x) && Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(endPoint.z)) {
return segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
} else {
console.log("There is no path here...Choose valid path")
console.log("There is no path here...Choose valid path");
const { path: segmentPaths } = navMeshQuery.computePath(startPoint, startPoint);
return segmentPaths.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
}
@@ -69,31 +63,33 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
console.error("Failed to compute path");
return [];
}
}, [navMesh]);
},
[navMesh]
);
function humanStatus(modelId: string, status: string) {
// console.log(`${modelId} , ${status}`);
}
function reset() {
setCurrentPhase(human.modelUuid, 'init');
setCurrentPhase(human.modelUuid, "init");
setHumanActive(human.modelUuid, false);
setHumanState(human.modelUuid, 'idle');
setHumanState(human.modelUuid, "idle");
setHumanScheduled(human.modelUuid, false);
setHumanLoad(human.modelUuid, 0);
resetAnimation(human.modelUuid);
setPath([]);
isPausedRef.current = false;
pauseTimeRef.current = 0;
resetTime(human.modelUuid)
activeTimeRef.current = 0
idleTimeRef.current = 0
previousTimeRef.current = null
resetTime(human.modelUuid);
activeTimeRef.current = 0;
idleTimeRef.current = 0;
previousTimeRef.current = null;
if (animationFrameIdRef.current !== null) {
cancelAnimationFrame(animationFrameIdRef.current)
animationFrameIdRef.current = null
cancelAnimationFrame(animationFrameIdRef.current);
animationFrameIdRef.current = null;
}
const object = scene.getObjectByProperty('uuid', human.modelUuid);
const object = scene.getObjectByProperty("uuid", human.modelUuid);
if (object && human) {
object.position.set(human.position[0], human.position[1], human.position[2]);
object.rotation.set(human.rotation[0], human.rotation[1], human.rotation[2]);
@@ -102,42 +98,42 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
useEffect(() => {
if (isPlaying) {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
if (!action || action.actionType !== 'worker' || !action.pickUpPoint || !action.dropPoint) 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' && human.currentPhase === 'init') {
const humanMesh = scene.getObjectByProperty('uuid', human.modelUuid);
if (!human.isActive && human.state === "idle" && human.currentPhase === "init") {
const humanMesh = scene.getObjectByProperty("uuid", human.modelUuid);
if (!humanMesh) return;
const toPickupPath = computePath(humanMesh.position.toArray(), action?.pickUpPoint?.position || [0, 0, 0]);
setPath(toPickupPath);
setCurrentPhase(human.modelUuid, 'init-pickup');
setHumanState(human.modelUuid, 'running');
setCurrentPhase(human.modelUuid, "init-pickup");
setHumanState(human.modelUuid, "running");
setHumanActive(human.modelUuid, true);
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
humanStatus(human.modelUuid, 'Started from init, heading to pickup');
setCurrentAnimation(human.modelUuid, "walking", true, true, true);
humanStatus(human.modelUuid, "Started from init, heading to pickup");
return;
} else if (!human.isActive && human.state === 'idle' && human.currentPhase === 'picking') {
if (humanAsset && human.currentLoad === action.loadCapacity && human.currentMaterials.length > 0 && human.currentLoad > 0 && humanAsset.animationState?.current === 'pickup' && humanAsset.animationState?.isCompleted) {
} else if (!human.isActive && human.state === "idle" && human.currentPhase === "picking") {
if (humanAsset && human.currentLoad === action.loadCapacity && human.currentMaterials.length > 0 && human.currentLoad > 0 && humanAsset.animationState?.current === "pickup" && humanAsset.animationState?.isCompleted) {
if (action.pickUpPoint && action.dropPoint) {
const toDrop = computePath(action.pickUpPoint.position || [0, 0, 0], action.dropPoint.position || [0, 0, 0]);
setPath(toDrop);
setCurrentPhase(human.modelUuid, 'pickup-drop');
setHumanState(human.modelUuid, 'running');
setCurrentAnimation(human.modelUuid, 'walk_with_box', true, true, true);
humanStatus(human.modelUuid, 'Started from pickup point, heading to drop point');
setCurrentPhase(human.modelUuid, "pickup-drop");
setHumanState(human.modelUuid, "running");
setCurrentAnimation(human.modelUuid, "walk_with_box", true, true, true);
humanStatus(human.modelUuid, "Started from pickup point, heading to drop point");
}
} else if (human.currentMaterials.length > 0 && human.currentLoad > 0 && humanAsset?.animationState?.current !== 'pickup') {
} else if (human.currentMaterials.length > 0 && human.currentLoad > 0 && humanAsset?.animationState?.current !== "pickup") {
setTimeout(() => {
if (human.currentMaterials[0]?.materialId) {
setIsVisible(human.currentMaterials[0]?.materialId, false);
}
humanStatus(human.modelUuid, 'Started to pickup in pickup point');
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
}, 1)
humanStatus(human.modelUuid, "Started to pickup in pickup point");
setCurrentAnimation(human.modelUuid, "pickup", true, false, false);
}, 1);
}
} else if (!human.isActive && human.state === 'idle' && human.currentPhase === 'dropping' && human.currentLoad === 0) {
} else if (!human.isActive && human.state === "idle" && human.currentPhase === "dropping" && human.currentLoad === 0) {
if (action.pickUpPoint && action.dropPoint) {
// const dropToPickup = computePath(action.dropPoint.position || [0, 0, 0], action.pickUpPoint.position || [0, 0, 0]);
// setPath(dropToPickup);
@@ -146,25 +142,25 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
// setHumanActive(human.modelUuid, true);
// setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
if (humanEventManagerRef.current) {
let state = humanEventManagerRef.current.humanStates.find(h => h.humanId === human.modelUuid);
let state = humanEventManagerRef.current.humanStates.find((h) => h.humanId === human.modelUuid);
if (state) {
const existingAction = state.actionQueue.find(a => a.actionUuid === action.actionUuid);
const existingAction = state.actionQueue.find((a) => a.actionUuid === action.actionUuid);
if (existingAction) {
const currentCount = existingAction.count ?? 0;
if (existingAction.actionType === 'worker') {
if (existingAction.actionType === "worker") {
if (currentCount < existingAction.maxLoadCount) {
const dropToPickup = computePath(action.dropPoint.position || [0, 0, 0], action.pickUpPoint.position || [0, 0, 0]);
setPath(dropToPickup);
setCurrentPhase(human.modelUuid, 'drop-pickup');
setHumanState(human.modelUuid, 'running');
setCurrentPhase(human.modelUuid, "drop-pickup");
setHumanState(human.modelUuid, "running");
setHumanActive(human.modelUuid, true);
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
setCurrentAnimation(human.modelUuid, "walking", true, true, true);
} else {
setCurrentPhase(human.modelUuid, 'picking');
setHumanState(human.modelUuid, 'idle');
setCurrentPhase(human.modelUuid, "picking");
setHumanState(human.modelUuid, "idle");
setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Started from dropping point, heading to pickup point');
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
humanStatus(human.modelUuid, "Started from dropping point, heading to pickup point");
}
}
}
@@ -173,67 +169,67 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
}
}
} else {
reset()
reset();
}
}, [human, human.currentAction, human.currentPhase, path, isPlaying, humanAsset?.animationState?.isCompleted]);
function handleCallBack() {
if (human.currentPhase === 'init-pickup') {
setCurrentPhase(human.modelUuid, 'picking');
setHumanState(human.modelUuid, 'idle');
if (human.currentPhase === "init-pickup") {
setCurrentPhase(human.modelUuid, "picking");
setHumanState(human.modelUuid, "idle");
setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Reached pickup point, waiting for material');
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
humanStatus(human.modelUuid, "Reached pickup point, waiting for material");
setPath([]);
} else if (human.currentPhase === 'pickup-drop') {
setCurrentPhase(human.modelUuid, 'dropping');
setHumanState(human.modelUuid, 'idle');
} else if (human.currentPhase === "pickup-drop") {
setCurrentPhase(human.modelUuid, "dropping");
setHumanState(human.modelUuid, "idle");
setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
humanStatus(human.modelUuid, 'Reached drop point');
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
humanStatus(human.modelUuid, "Reached drop point");
setPath([]);
} else if (human.currentPhase === 'drop-pickup') {
setCurrentPhase(human.modelUuid, 'picking');
setHumanState(human.modelUuid, 'idle');
} else if (human.currentPhase === "drop-pickup") {
setCurrentPhase(human.modelUuid, "picking");
setHumanState(human.modelUuid, "idle");
setHumanActive(human.modelUuid, false);
setHumanScheduled(human.modelUuid, false);
setPath([]);
clearCurrentMaterials(human.modelUuid);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Reached pickup point again, cycle complete');
setCurrentAnimation(human.modelUuid, "idle", true, true, true);
humanStatus(human.modelUuid, "Reached pickup point again, cycle complete");
}
}
function startUnloadingProcess() {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
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") {
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
}
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
if (humanAsset?.animationState?.current === "drop" && humanAsset?.animationState?.isCompleted) {
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 || '');
const model = getEventByModelUuid(selectedProduct.productUuid, trigger?.triggeredAsset?.triggeredModel?.modelUuid || "");
if (trigger && model) {
if (model.type === 'transfer') {
if (model.type === "transfer") {
if (action) {
handleMaterialDropToConveyor(model);
}
} else if (model.type === 'machine') {
} else if (model.type === "machine") {
if (action) {
handleMaterialDropToMachine(model);
}
} else if (model.type === 'roboticArm') {
} else if (model.type === "roboticArm") {
if (action) {
handleMaterialDropToArmBot(model);
}
} else if (model.type === 'storageUnit') {
} else if (model.type === "storageUnit") {
if (action) {
handleMaterialDropToStorageUnit(model);
}
} else if (model.type === 'vehicle') {
} else if (model.type === "vehicle") {
if (action) {
handleMaterialDropToVehicle(model);
}
@@ -252,21 +248,15 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
}
function handleMaterialDropToStorageUnit(model: StorageEventSchema) {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
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);
if (model && humanAsset?.animationState?.current !== "drop") {
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
}
const checkAnimation = () => {
if (humanAsset?.animationState?.isCompleted) {
loopMaterialDropToStorage(
human.modelUuid,
human.currentLoad,
model.modelUuid,
model.storageCapacity,
(action as HumanAction)
);
loopMaterialDropToStorage(human.modelUuid, human.currentLoad, model.modelUuid, model.storageCapacity, action as HumanAction);
} else {
requestAnimationFrame(checkAnimation);
}
@@ -274,13 +264,7 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
checkAnimation();
}
function loopMaterialDropToStorage(
humanId: string,
humanCurrentLoad: number,
storageUnitId: string,
storageMaxCapacity: number,
action: HumanAction
) {
function loopMaterialDropToStorage(humanId: string, humanCurrentLoad: number, storageUnitId: string, storageMaxCapacity: number, action: HumanAction) {
const storageUnit = getStorageUnitById(storageUnitId);
const humanAsset = getAssetById(human.modelUuid);
@@ -298,17 +282,11 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
if (humanCurrentLoad > 0 && storageUnit.currentLoad < storageMaxCapacity) {
resetAnimation(human.modelUuid);
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
const waitForNextDrop = () => {
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
loopMaterialDropToStorage(
humanId,
humanCurrentLoad,
storageUnitId,
storageMaxCapacity,
action
);
if (humanAsset?.animationState?.current === "drop" && humanAsset?.animationState?.isCompleted) {
loopMaterialDropToStorage(humanId, humanCurrentLoad, storageUnitId, storageMaxCapacity, action);
} else {
requestAnimationFrame(waitForNextDrop);
}
@@ -318,22 +296,17 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
}
function handleMaterialDropToConveyor(model: ConveyorEventSchema) {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
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") {
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
}
const checkAnimation = () => {
if (humanAsset?.animationState?.isCompleted) {
const conveyor = getConveyorById(model.modelUuid);
if (conveyor) {
loopMaterialDropToConveyor(
human.modelUuid,
human.currentLoad,
conveyor.modelUuid,
(action as HumanAction)
);
loopMaterialDropToConveyor(human.modelUuid, human.currentLoad, conveyor.modelUuid, action as HumanAction);
}
} else {
requestAnimationFrame(checkAnimation);
@@ -342,12 +315,7 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
checkAnimation();
}
function loopMaterialDropToConveyor(
humanId: string,
humanCurrentLoad: number,
conveyorId: string,
action: HumanAction
) {
function loopMaterialDropToConveyor(humanId: string, humanCurrentLoad: number, conveyorId: string, action: HumanAction) {
const conveyor = getConveyorById(conveyorId);
const humanAsset = getAssetById(human.modelUuid);
@@ -365,16 +333,11 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
if (humanCurrentLoad > 0) {
resetAnimation(human.modelUuid);
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
const waitForNextDrop = () => {
if (humanAsset?.animationState?.isCompleted) {
loopMaterialDropToConveyor(
humanId,
humanCurrentLoad,
conveyorId,
action
);
loopMaterialDropToConveyor(humanId, humanCurrentLoad, conveyorId, action);
} else {
requestAnimationFrame(waitForNextDrop);
}
@@ -384,22 +347,17 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
}
function handleMaterialDropToArmBot(model: RoboticArmEventSchema) {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
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") {
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
}
const checkAnimation = () => {
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
if (humanAsset?.animationState?.current === "drop" && humanAsset?.animationState?.isCompleted) {
const armBot = getArmBotById(model.modelUuid);
if (armBot && armBot.state === 'idle' && !armBot.isActive) {
loopMaterialDropToArmBot(
human.modelUuid,
human.currentLoad,
model.modelUuid,
(action as HumanAction)
);
if (armBot && armBot.state === "idle" && !armBot.isActive) {
loopMaterialDropToArmBot(human.modelUuid, human.currentLoad, model.modelUuid, action as HumanAction);
}
} else {
requestAnimationFrame(checkAnimation);
@@ -408,16 +366,11 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
checkAnimation();
}
function loopMaterialDropToArmBot(
humanId: string,
humanCurrentLoad: number,
armBotId: string,
action: HumanAction
) {
function loopMaterialDropToArmBot(humanId: string, humanCurrentLoad: number, armBotId: string, action: HumanAction) {
const armBot = getArmBotById(armBotId);
const humanAsset = getAssetById(human.modelUuid);
if (!armBot || armBot.state !== 'idle' || armBot.isActive || humanCurrentLoad <= 0) {
if (!armBot || armBot.state !== "idle" || armBot.isActive || humanCurrentLoad <= 0) {
return;
}
@@ -431,18 +384,13 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
if (humanCurrentLoad > 0) {
resetAnimation(human.modelUuid);
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
const waitForNextTransfer = () => {
const currentArmBot = getArmBotById(armBotId);
if (currentArmBot && currentArmBot.state === 'idle' && !currentArmBot.isActive) {
if (currentArmBot && currentArmBot.state === "idle" && !currentArmBot.isActive) {
if (humanAsset?.animationState?.isCompleted) {
loopMaterialDropToArmBot(
humanId,
humanCurrentLoad,
armBotId,
action
);
loopMaterialDropToArmBot(humanId, humanCurrentLoad, armBotId, action);
} else {
requestAnimationFrame(waitForNextTransfer);
}
@@ -455,22 +403,17 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
}
function handleMaterialDropToVehicle(model: VehicleEventSchema) {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
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") {
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
}
const checkAnimation = () => {
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
if (humanAsset?.animationState?.current === "drop" && humanAsset?.animationState?.isCompleted) {
const vehicle = getVehicleById(model.modelUuid);
if (vehicle && vehicle.state === 'idle' && !vehicle.isActive) {
loopMaterialDropToVehicle(
human.modelUuid,
human.currentLoad,
model.modelUuid,
(action as HumanAction)
);
if (vehicle && vehicle.state === "idle" && !vehicle.isActive) {
loopMaterialDropToVehicle(human.modelUuid, human.currentLoad, model.modelUuid, action as HumanAction);
}
} else {
requestAnimationFrame(checkAnimation);
@@ -479,16 +422,11 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
checkAnimation();
}
function loopMaterialDropToVehicle(
humanId: string,
humanCurrentLoad: number,
vehicleId: string,
action: HumanAction
) {
function loopMaterialDropToVehicle(humanId: string, humanCurrentLoad: number, vehicleId: string, action: HumanAction) {
const vehicle = getVehicleById(vehicleId);
const humanAsset = getAssetById(human.modelUuid);
if (!vehicle || vehicle.state !== 'idle' || vehicle.isActive || humanCurrentLoad <= 0) {
if (!vehicle || vehicle.state !== "idle" || vehicle.isActive || humanCurrentLoad <= 0) {
return;
}
@@ -502,18 +440,13 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
if (humanCurrentLoad > 0) {
resetAnimation(human.modelUuid);
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
const waitForNextTransfer = () => {
const currentVehicle = getVehicleById(vehicleId);
if (currentVehicle && currentVehicle.state === 'idle' && !currentVehicle.isActive) {
if (currentVehicle && currentVehicle.state === "idle" && !currentVehicle.isActive) {
if (humanAsset?.animationState?.isCompleted) {
loopMaterialDropToVehicle(
humanId,
humanCurrentLoad,
vehicleId,
action
);
loopMaterialDropToVehicle(humanId, humanCurrentLoad, vehicleId, action);
} else {
requestAnimationFrame(waitForNextTransfer);
}
@@ -526,22 +459,17 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
}
function handleMaterialDropToMachine(model: MachineEventSchema) {
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
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") {
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
}
const checkAnimation = () => {
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
if (humanAsset?.animationState?.current === "drop" && humanAsset?.animationState?.isCompleted) {
const machine = getMachineById(model.modelUuid);
if (machine && machine.state === 'idle' && !machine.isActive) {
loopMaterialDropToMachine(
human.modelUuid,
human.currentLoad,
model.modelUuid,
(action as HumanAction)
);
if (machine && machine.state === "idle" && !machine.isActive) {
loopMaterialDropToMachine(human.modelUuid, human.currentLoad, model.modelUuid, action as HumanAction);
}
} else {
requestAnimationFrame(checkAnimation);
@@ -550,16 +478,11 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
checkAnimation();
}
function loopMaterialDropToMachine(
humanId: string,
humanCurrentLoad: number,
machineId: string,
action: HumanAction
) {
function loopMaterialDropToMachine(humanId: string, humanCurrentLoad: number, machineId: string, action: HumanAction) {
const machine = getMachineById(machineId);
const humanAsset = getAssetById(human.modelUuid);
if (!machine || machine.state !== 'idle' || machine.isActive || humanCurrentLoad <= 0) {
if (!machine || machine.state !== "idle" || machine.isActive || humanCurrentLoad <= 0) {
return;
}
@@ -573,18 +496,13 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
if (humanCurrentLoad > 0) {
resetAnimation(human.modelUuid);
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
const waitForNextTransfer = () => {
const currentMachine = getMachineById(machineId);
if (currentMachine && currentMachine.state === 'idle' && !currentMachine.isActive) {
if (currentMachine && currentMachine.state === "idle" && !currentMachine.isActive) {
if (humanAsset?.animationState?.isCompleted) {
loopMaterialDropToMachine(
humanId,
humanCurrentLoad,
machineId,
action
);
loopMaterialDropToMachine(humanId, humanCurrentLoad, machineId, action);
} else {
requestAnimationFrame(waitForNextTransfer);
}
@@ -598,8 +516,8 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
function handleMaterialDropByDefault(droppedMaterial: number) {
const humanAsset = getAssetById(human.modelUuid);
if (humanAsset?.animationState?.current !== 'drop') {
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
if (humanAsset?.animationState?.current !== "drop") {
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
}
if (humanAsset?.animationState?.isCompleted) {
@@ -614,7 +532,7 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
if (remainingMaterials > 0) {
resetAnimation(human.modelUuid);
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
setCurrentAnimation(human.modelUuid, "drop", true, false, false);
requestAnimationFrame(() => handleMaterialDropByDefault(remainingMaterials));
}
@@ -624,15 +542,7 @@ function WorkerInstance({ human }: { readonly human: HumanStatus }) {
requestAnimationFrame(() => handleMaterialDropByDefault(droppedMaterial));
}
return (
<WorkerAnimator
path={path}
handleCallBack={handleCallBack}
human={human}
reset={reset}
startUnloadingProcess={startUnloadingProcess}
/>
)
return <WorkerAnimator path={path} handleCallBack={handleCallBack} human={human} reset={reset} startUnloadingProcess={startUnloadingProcess} />;
}
export default WorkerInstance;

View File

@@ -1,19 +1,16 @@
import { useEffect, useRef } from 'react';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import { useEffect, useRef } from "react";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
import MaterialAnimator from '../animator/materialAnimator';
import ManufacturerInstance from './actions/manufacturerInstance';
import WorkerInstance from './actions/workerInstance';
import OperatorInstance from './actions/operatorInstance';
import MaterialAnimator from "../animator/materialAnimator";
import ManufacturerInstance from "./actions/manufacturerInstance";
import WorkerInstance from "./actions/workerInstance";
import OperatorInstance from "./actions/operatorInstance";
function HumanInstance({ human }: {readonly human: HumanStatus }) {
function HumanInstance({ human }: { readonly human: HumanStatus }) {
const { isPlaying } = usePlayButtonStore();
const { humanStore, productStore } = useSceneContext();
const { getActionByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, selectedProduct } = productStore();
const { incrementIdleTime, incrementActiveTime } = humanStore();
const idleTimeRef = useRef<number>(0);
@@ -24,7 +21,7 @@ function HumanInstance({ human }: {readonly human: HumanStatus }) {
const { isPaused } = usePauseButtonStore();
const previousTimeRef = useRef<number | null>(null);
const animationFrameIdRef = useRef<number | null>(null);
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, human?.currentAction?.actionUuid || "");
useEffect(() => {
isPausedRef.current = isPaused;
@@ -55,7 +52,7 @@ function HumanInstance({ human }: {readonly human: HumanStatus }) {
}
useEffect(() => {
if (!isPlaying) return
if (!isPlaying) return;
if (!human.isActive) {
const roundedActiveTime = Math.round(activeTimeRef.current);
incrementActiveTime(human.modelUuid, roundedActiveTime);
@@ -80,20 +77,13 @@ function HumanInstance({ human }: {readonly human: HumanStatus }) {
return (
<>
{action && action.actionType === 'worker' &&
<WorkerInstance human={human} />
}
{action && action.actionType === 'manufacturer' &&
<ManufacturerInstance human={human} />
}
{action && action.actionType === 'operator' &&
<OperatorInstance human={human} />
}
{action && action.actionType === "worker" && <WorkerInstance human={human} />}
{action && action.actionType === "manufacturer" && <ManufacturerInstance human={human} />}
{action && action.actionType === "operator" && <OperatorInstance human={human} />}
<MaterialAnimator human={human} />
</>
)
);
}
export default HumanInstance
export default HumanInstance;

View File

@@ -3,7 +3,6 @@ import * as THREE from "three";
import { Tube, useGLTF } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useIsDragging, useIsRotating, useSelectedAction, useSelectedEventSphere } from "../../../../../store/simulation/useSimulationStore";
import { useProductContext } from "../../../products/productContext";
import { useSceneContext } from "../../../../scene/sceneContext";
import { Group, Plane, Vector2, Vector3 } from "three";
import { useParams } from "react-router-dom";
@@ -23,11 +22,9 @@ function HumanUi() {
const prevMousePos = useRef({ x: 0, y: 0 });
const { controls, raycaster, camera } = useThree();
const { selectedEventSphere } = useSelectedEventSphere();
const { selectedProductStore } = useProductContext();
const { humanStore, productStore, versionStore } = useSceneContext();
const { selectedProduct } = selectedProductStore();
const { humans, getHumanById } = humanStore();
const { updateEvent, getActionByUuid } = productStore();
const { updateEvent, getActionByUuid, selectedProduct } = productStore();
const [startPosition, setStartPosition] = useState<[number, number, number]>([0, 1, 0]);
const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 1, 0]);
const [manufacturePosition, setManufacturePosition] = useState<[number, number, number]>([0, 1, 0]);

View File

@@ -1,12 +1,11 @@
import { useEffect, useRef, useState } from 'react'
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import MachineAnimator from '../animator/machineAnimator';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import { useEffect, useRef, useState } from "react";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import MachineAnimator from "../animator/machineAnimator";
import { useTriggerHandler } from "../../../triggers/triggerHandler/useTriggerHandler";
import { useSceneContext } from "../../../../scene/sceneContext";
function MachineInstance({ machineDetail }: { readonly machineDetail: MachineStatus }) {
const [currentPhase, setCurrentPhase] = useState<string>('idle');
const [currentPhase, setCurrentPhase] = useState<string>("idle");
let isIncrememtable = useRef<boolean>(true);
const idleTimeRef = useRef<number>(0);
const activeTimeRef = useRef<number>(0);
@@ -16,10 +15,8 @@ function MachineInstance({ machineDetail }: { readonly machineDetail: MachineSta
const isPausedRef = useRef<boolean>(false);
const { isPlaying } = usePlayButtonStore();
const { machineStore, productStore } = useSceneContext();
const { selectedProductStore } = useProductContext();
const { machines, setMachineState, setMachineActive, incrementIdleTime, incrementActiveTime, resetTime } = machineStore();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid } = productStore();
const { getActionByUuid, selectedProduct } = productStore();
const { triggerPointActions } = useTriggerHandler();
const { speed } = useAnimationPlaySpeed();
const { isPaused } = usePauseButtonStore();
@@ -34,19 +31,19 @@ function MachineInstance({ machineDetail }: { readonly machineDetail: MachineSta
const reset = () => {
setCurrentPhase("idle");
setMachineState(machineDetail.modelUuid, 'idle');
setMachineState(machineDetail.modelUuid, "idle");
setMachineActive(machineDetail.modelUuid, false);
isIncrememtable.current = true;
isPausedRef.current = false;
resetTime(machineDetail.modelUuid)
activeTimeRef.current = 0
idleTimeRef.current = 0
previousTimeRef.current = null
resetTime(machineDetail.modelUuid);
activeTimeRef.current = 0;
idleTimeRef.current = 0;
previousTimeRef.current = null;
if (animationFrameIdRef.current !== null) {
cancelAnimationFrame(animationFrameIdRef.current)
animationFrameIdRef.current = null
}
cancelAnimationFrame(animationFrameIdRef.current);
animationFrameIdRef.current = null;
}
};
function machineStatus(modelId: string, status: string) {
// console.log(`${modelId} , ${status}`);
@@ -75,7 +72,7 @@ function MachineInstance({ machineDetail }: { readonly machineDetail: MachineSta
}
useEffect(() => {
if (!isPlaying) return
if (!isPlaying) return;
if (!machineDetail.isActive) {
const roundedActiveTime = Math.round(activeTimeRef.current);
// console.log('Final Active Time:', roundedActiveTime, 'seconds');
@@ -103,38 +100,34 @@ function MachineInstance({ machineDetail }: { readonly machineDetail: MachineSta
useEffect(() => {
if (isPlaying) {
if (!machineDetail.isActive && machineDetail.state === "idle" && currentPhase == "idle" && !machineDetail.currentAction) {
machineStatus(machineDetail.modelUuid, 'Machine is idle and waiting for next instruction.')
machineStatus(machineDetail.modelUuid, "Machine is idle and waiting for next instruction.");
} else if (!machineDetail.isActive && machineDetail.state === "idle" && currentPhase == "idle" && machineDetail.currentAction) {
setCurrentPhase("processing");
setMachineState(machineDetail.modelUuid, 'running');
setMachineState(machineDetail.modelUuid, "running");
setMachineActive(machineDetail.modelUuid, true);
machineStatus(machineDetail.modelUuid, "Machine started processing")
machineStatus(machineDetail.modelUuid, "Machine started processing");
}
}
}, [currentPhase, isPlaying, machines])
}, [currentPhase, isPlaying, machines]);
function handleCallBack() {
if (currentPhase == "processing") {
setMachineState(machineDetail.modelUuid, 'idle');
setMachineState(machineDetail.modelUuid, "idle");
setMachineActive(machineDetail.modelUuid, false);
setCurrentPhase("idle")
setCurrentPhase("idle");
isIncrememtable.current = true;
machineStatus(machineDetail.modelUuid, "Machine has completed the processing")
machineStatus(machineDetail.modelUuid, "Machine has completed the processing");
if (machineDetail.currentAction) {
const action = getActionByUuid(selectedProduct.productUuid, machineDetail.currentAction.actionUuid);
if (action && machineDetail.currentAction.materialId) {
triggerPointActions(action, machineDetail.currentAction.materialId)
triggerPointActions(action, machineDetail.currentAction.materialId);
}
}
}
}
return (
<MachineAnimator processingTime={machineDetail.point.action.processTime} handleCallBack={handleCallBack} currentPhase={currentPhase} machineUuid={machineDetail.modelUuid} machineStatus={machineStatus} reset={reset} />
)
return <MachineAnimator processingTime={machineDetail.point.action.processTime} handleCallBack={handleCallBack} currentPhase={currentPhase} machineUuid={machineDetail.modelUuid} machineStatus={machineStatus} reset={reset} />;
}
export default MachineInstance
export default MachineInstance;

View File

@@ -1,21 +1,18 @@
import { useMemo, useRef } from 'react'
import * as THREE from 'three';
import MaterialAnimator from '../animator/materialAnimator';
import { MaterialModel } from '../material/materialModel';
import { useThree } from '@react-three/fiber';
import { useAnimationPlaySpeed } from '../../../../../store/ui/usePlayButtonStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import { useProductContext } from '../../../products/productContext';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useMemo, useRef } from "react";
import * as THREE from "three";
import MaterialAnimator from "../animator/materialAnimator";
import { MaterialModel } from "../material/materialModel";
import { useThree } from "@react-three/fiber";
import { useAnimationPlaySpeed } from "../../../../../store/ui/usePlayButtonStore";
import { useTriggerHandler } from "../../../triggers/triggerHandler/useTriggerHandler";
import { useSceneContext } from "../../../../scene/sceneContext";
function MaterialInstance({ material }: { readonly material: MaterialSchema }) {
const matRef: any = useRef();
const { scene } = useThree();
const { selectedProductStore } = useProductContext();
const { productStore, materialStore } = useSceneContext();
const { setIsPaused } = materialStore();
const { getModelUuidByPointUuid, getPointByUuid, getEventByModelUuid, getActionByPointUuid } = productStore();
const { selectedProduct } = selectedProductStore();
const { getModelUuidByPointUuid, getPointByUuid, getEventByModelUuid, getActionByPointUuid, selectedProduct } = productStore();
const { speed } = useAnimationPlaySpeed();
const { triggerPointActions } = useTriggerHandler();
@@ -53,18 +50,17 @@ function MaterialInstance({ material }: { readonly material: MaterialSchema }) {
return {
position: new THREE.Vector3(...point.position),
rotation: new THREE.Vector3(...point.rotation),
currentSpeed: currentSpeed || 1
currentSpeed: currentSpeed || 1,
};
}, [material, getPointByUuid]);
function getCurrentSpeed(productUuid: string, modelUuid: string) {
const event = getEventByModelUuid(productUuid, modelUuid)
const event = getEventByModelUuid(productUuid, modelUuid);
if (event) {
if (event.type === 'transfer' || event.type === 'machine' || event.type === 'storageUnit') {
if (event.type === "transfer" || event.type === "machine" || event.type === "storageUnit") {
return 1;
}
if (event.type === 'vehicle' || event.type === 'roboticArm' || event.type === 'human') {
if (event.type === "vehicle" || event.type === "roboticArm" || event.type === "human") {
return event.speed;
}
} else {
@@ -81,23 +77,22 @@ function MaterialInstance({ material }: { readonly material: MaterialSchema }) {
} else {
setIsPaused(material.materialId, true);
}
}
};
return (
<>
{material.isRendered &&
<MaterialModel materialId={material.materialId} matRef={matRef} materialType={material.materialType} visible={material.isVisible} position={position} rotation={[rotation.x, rotation.y, rotation.z]} />
}
{material.isRendered && <MaterialModel materialId={material.materialId} matRef={matRef} materialType={material.materialType} visible={material.isVisible} position={position} rotation={[rotation.x, rotation.y, rotation.z]} />}
<MaterialAnimator
matRef={matRef}
material={material}
currentSpeed={currentSpeed * speed}
onAnimationComplete={() => { callTrigger() }}
onAnimationComplete={() => {
callTrigger();
}}
/>
</>
)
);
}
export default MaterialInstance
export default MaterialInstance;

View File

@@ -1,37 +0,0 @@
import { createContext, useContext, useMemo } from 'react';
import { createSelectedProductStore, SelectedProductType } from '../../../store/simulation/useSimulationStore';
type ProductContextValue = {
selectedProductStore: SelectedProductType,
};
const ProductContext = createContext<ProductContextValue | null>(null);
export function ProductProvider({
children,
}: {
readonly children: React.ReactNode;
}) {
const selectedProductStore = useMemo(() => createSelectedProductStore(), []);
const contextValue = useMemo(() => (
{
selectedProductStore
}
), [selectedProductStore]);
return (
<ProductContext.Provider value={contextValue}>
{children}
</ProductContext.Provider>
);
}
// Base hook to get the context
export function useProductContext() {
const context = useContext(ProductContext);
if (!context) {
throw new Error('useProductContext must be used within a ProductProvider');
}
return context;
}

View File

@@ -1,19 +1,16 @@
import * as THREE from 'three';
import { useEffect } from 'react';
import { upsertProductOrEventApi } from '../../../services/simulation/products/UpsertProductOrEventApi';
import { getAllProductsApi } from '../../../services/simulation/products/getallProductsApi';
import { usePlayButtonStore, useResetButtonStore } from '../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../scene/sceneContext';
import { useProductContext } from './productContext';
import { useComparisonProduct, useMainProduct } from '../../../store/simulation/useSimulationStore';
import { useParams } from 'react-router-dom';
import * as THREE from "three";
import { useEffect } from "react";
import { upsertProductOrEventApi } from "../../../services/simulation/products/UpsertProductOrEventApi";
import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi";
import { usePlayButtonStore, useResetButtonStore } from "../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../scene/sceneContext";
import { useComparisonProduct, useMainProduct } from "../../../store/simulation/useSimulationStore";
import { useParams } from "react-router-dom";
function Products() {
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore, layout, productStore, versionStore } = useSceneContext();
const { products, getProductById, addProduct, setProducts } = productStore();
const { selectedProductStore } = useProductContext();
const { products, getProductById, addProduct, setProducts, selectedProduct, setSelectedProduct } = productStore();
const { setMainProduct } = useMainProduct();
const { selectedProduct, setSelectedProduct } = selectedProductStore();
const { addVehicle, clearVehicles } = vehicleStore();
const { addArmBot, clearArmBots } = armBotStore();
const { addMachine, clearMachines } = machineStore();
@@ -29,53 +26,55 @@ function Products() {
const { projectId } = useParams();
useEffect(() => {
if (layout === 'Main Layout' && mainProduct) {
if (layout === "Main Layout" && mainProduct) {
setSelectedProduct(mainProduct.productUuid, mainProduct.productName);
}
}, [mainProduct])
}, [mainProduct]);
useEffect(() => {
if (layout === 'Comparison Layout' && comparisonProduct) {
if (layout === "Comparison Layout" && comparisonProduct) {
setSelectedProduct(comparisonProduct.productUuid, comparisonProduct.productName);
}
}, [comparisonProduct])
}, [comparisonProduct]);
useEffect(() => {
if (!selectedVersion) return;
getAllProductsApi(projectId || '', selectedVersion?.versionId || '').then((data) => {
getAllProductsApi(projectId || "", selectedVersion?.versionId || "")
.then((data) => {
if (data && data.length === 0) {
const id = THREE.MathUtils.generateUUID();
const name = 'Product 1';
const name = "Product 1";
addProduct(name, id);
upsertProductOrEventApi({
productName: name,
productUuid: id,
projectId: projectId || '',
versionId: selectedVersion?.versionId || ''
})
if (layout === 'Main Layout') {
projectId: projectId || "",
versionId: selectedVersion?.versionId || "",
});
if (layout === "Main Layout") {
setSelectedProduct(id, name);
setMainProduct(id, name);
}
} else {
setProducts(data);
if (layout === 'Main Layout') {
if (layout === "Main Layout") {
setSelectedProduct(data[0].productUuid, data[0].productName);
setMainProduct(data[0].productUuid, data[0].productName);
}
}
}).catch((err) => {
console.error(err);
})
}, [selectedVersion?.versionId])
.catch((err) => {
console.error(err);
});
}, [selectedVersion?.versionId]);
useEffect(() => {
if (selectedProduct.productUuid) {
const product = getProductById(selectedProduct.productUuid);
if (product) {
clearVehicles();
product.eventDatas.forEach(events => {
if (events.type === 'vehicle') {
product.eventDatas.forEach((events) => {
if (events.type === "vehicle") {
addVehicle(selectedProduct.productUuid, events);
}
});
@@ -88,8 +87,8 @@ function Products() {
const product = getProductById(selectedProduct.productUuid);
if (product) {
clearArmBots();
product.eventDatas.forEach(events => {
if (events.type === 'roboticArm') {
product.eventDatas.forEach((events) => {
if (events.type === "roboticArm") {
addArmBot(selectedProduct.productUuid, events);
}
});
@@ -102,8 +101,8 @@ function Products() {
const product = getProductById(selectedProduct.productUuid);
if (product) {
clearConveyors();
product.eventDatas.forEach(events => {
if (events.type === 'transfer') {
product.eventDatas.forEach((events) => {
if (events.type === "transfer") {
addConveyor(selectedProduct.productUuid, events);
}
});
@@ -116,8 +115,8 @@ function Products() {
const product = getProductById(selectedProduct.productUuid);
if (product) {
clearMachines();
product.eventDatas.forEach(events => {
if (events.type === 'machine') {
product.eventDatas.forEach((events) => {
if (events.type === "machine") {
addMachine(selectedProduct.productUuid, events);
}
});
@@ -130,14 +129,14 @@ function Products() {
const product = getProductById(selectedProduct.productUuid);
if (product) {
clearStorageUnits();
product.eventDatas.forEach(event => {
if (event.type === 'storageUnit') {
product.eventDatas.forEach((event) => {
if (event.type === "storageUnit") {
addStorageUnit(selectedProduct.productUuid, event);
if (event.storageCount > 0) {
const materials = Array.from({ length: event.storageCount }, () => ({
materialType: event.materialType || 'Default material',
materialId: THREE.MathUtils.generateUUID()
materialType: event.materialType || "Default material",
materialId: THREE.MathUtils.generateUUID(),
}));
setCurrentMaterials(event.modelUuid, materials);
@@ -157,8 +156,8 @@ function Products() {
const product = getProductById(selectedProduct.productUuid);
if (product) {
clearHumans();
product.eventDatas.forEach(events => {
if (events.type === 'human') {
product.eventDatas.forEach((events) => {
if (events.type === "human") {
addHuman(selectedProduct.productUuid, events);
if (events.point.actions.length > 0) {
@@ -175,8 +174,8 @@ function Products() {
const product = getProductById(selectedProduct.productUuid);
if (product) {
clearCranes();
product.eventDatas.forEach(events => {
if (events.type === 'crane') {
product.eventDatas.forEach((events) => {
if (events.type === "crane") {
addCrane(selectedProduct.productUuid, events);
if (events.point.actions.length > 0) {
@@ -188,11 +187,7 @@ function Products() {
}
}, [selectedProduct, products, isReset, isPlaying]);
return (
<>
</>
)
return <></>;
}
export default Products
export default Products;

View File

@@ -1,10 +1,9 @@
import { useEffect, useRef, useState } from 'react';
import { useFrame, useThree } from '@react-three/fiber';
import * as THREE from 'three';
import { Line, Text } from '@react-three/drei';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import { useEffect, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import * as THREE from "three";
import { Line, Text } from "@react-three/drei";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useSceneContext } from "../../../../scene/sceneContext";
type PointWithDegree = {
position: [number, number, number];
@@ -34,13 +33,11 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
const { armBotStore, productStore, materialStore } = useSceneContext();
const { getArmBotById } = armBotStore();
const { getMaterialById, getMaterialPosition } = materialStore();
const { getEventByModelUuid, getActionByUuid, getPointByUuid, getTriggeringModels } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getEventByModelUuid, getActionByUuid, getPointByUuid, getTriggeringModels, selectedProduct } = productStore();
const { scene } = useThree();
let curveHeight = 1.75
const CIRCLE_RADIUS = 1.6
let curveHeight = 1.75;
const CIRCLE_RADIUS = 1.6;
// Zustand stores
const { isPlaying } = usePlayButtonStore();
@@ -55,7 +52,7 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
// Handle circle points based on armBot position
useEffect(() => {
const points = generateRingPoints(CIRCLE_RADIUS, 64)
const points = generateRingPoints(CIRCLE_RADIUS, 64);
setCirclePoints(points);
}, [armBot.position]);
@@ -69,13 +66,13 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
totalDistanceRef.current = 0;
startTimeRef.current = null;
segmentDistancesRef.current = [];
if (!ikSolver) return
if (!ikSolver) return;
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
if (!bone) return;
bone.position.copy(restPosition)
bone.position.copy(restPosition);
ikSolver.update();
}
}, [isReset, isPlaying])
}, [isReset, isPlaying]);
//Generate Circle Points
function generateRingPoints(radius: any, segments: any) {
@@ -110,18 +107,14 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
// Handle circle points based on armBot position
useEffect(() => {
const points = generateRingPointsWithDegrees(CIRCLE_RADIUS, 64, armBot.rotation);
setCirclePointsWithDegrees(points)
setCirclePointsWithDegrees(points);
}, [armBot.rotation]);
// Function for find nearest Circlepoints Index
const findNearestIndex = (nearestPoint: [number, number, number], points: [number, number, number][], epsilon = 1e-6) => {
for (let i = 0; i < points.length; i++) {
const [x, y, z] = points[i];
if (
Math.abs(x - nearestPoint[0]) < epsilon &&
Math.abs(y - nearestPoint[1]) < epsilon &&
Math.abs(z - nearestPoint[2]) < epsilon
) {
if (Math.abs(x - nearestPoint[0]) < epsilon && Math.abs(y - nearestPoint[1]) < epsilon && Math.abs(z - nearestPoint[2]) < epsilon) {
return i; // Found the matching index
}
}
@@ -154,7 +147,7 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
//Range to restrict angle
const hasForbiddenDegrees = (arc: [number, number, number][]) => {
return arc.some(p => {
return arc.some((p) => {
const idx = findNearestIndex(p, circlePoints);
const degree = circlePointsWithDegrees[idx]?.degree || 0;
return degree >= 271 && degree <= 300; // Forbidden range: 271° to 300°
@@ -164,24 +157,23 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
// Handle nearest points and final path (including arc points)
useEffect(() => {
if (circlePoints.length > 0 && currentPath.length > 0 && ikSolver.mesh) {
let start = currentPath[0];
let end = currentPath[currentPath.length - 1];
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
const armbotStatus = getArmBotById(armBot.modelUuid);
const currentMaterial = armbotStatus?.currentAction?.materialId;
const currentAction = getActionByUuid(selectedProduct.productUuid, armbotStatus?.currentAction?.actionUuid || '');
const currentAction = getActionByUuid(selectedProduct.productUuid, armbotStatus?.currentAction?.actionUuid || "");
if (armbotStatus && currentMaterial && currentAction && (currentPhase === 'rest-to-start' || currentPhase === 'start-to-end' || currentPhase === 'end-to-rest')) {
if (armbotStatus && currentMaterial && currentAction && (currentPhase === "rest-to-start" || currentPhase === "start-to-end" || currentPhase === "end-to-rest")) {
const materialData = getMaterialById(currentMaterial);
if (materialData) {
const triggeringModel = getTriggeringModels(selectedProduct.productUuid, currentAction.actionUuid);
const prevModel = triggeringModel[0] || null;
const nextModel = getEventByModelUuid(selectedProduct.productUuid, currentAction?.triggers[0]?.triggeredAsset?.triggeredModel?.modelUuid || '');
const nextPoint = getPointByUuid(selectedProduct.productUuid, currentAction?.triggers[0]?.triggeredAsset?.triggeredModel?.modelUuid || '', currentAction?.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid || '');
const nextModel = getEventByModelUuid(selectedProduct.productUuid, currentAction?.triggers[0]?.triggeredAsset?.triggeredModel?.modelUuid || "");
const nextPoint = getPointByUuid(selectedProduct.productUuid, currentAction?.triggers[0]?.triggeredAsset?.triggeredModel?.modelUuid || "", currentAction?.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid || "");
if (prevModel && prevModel.type === 'transfer') {
if (prevModel && prevModel.type === "transfer") {
const material = scene.getObjectByProperty("uuid", currentMaterial);
const armbotModel = scene.getObjectByProperty("uuid", armBot.modelUuid);
if (material && armbotModel) {
@@ -194,13 +186,13 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
const materialLocalPos = materialWorldPos.clone();
armbotModel.worldToLocal(materialLocalPos);
if (currentPhase === 'rest-to-start') {
if (currentPhase === "rest-to-start") {
end = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z];
} else if (currentPhase === 'start-to-end') {
} else if (currentPhase === "start-to-end") {
start = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z];
}
}
} else if (prevModel && prevModel.type === 'storageUnit') {
} else if (prevModel && prevModel.type === "storageUnit") {
const position = getMaterialPosition(prevModel.modelUuid, currentMaterial);
const armbotModel = scene.getObjectByProperty("uuid", armBot.modelUuid);
@@ -218,40 +210,35 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
const materialLocalPos = materialWorldPos.clone();
armbotModel.worldToLocal(materialLocalPos);
if (currentPhase === 'rest-to-start') {
if (currentPhase === "rest-to-start") {
end = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z];
} else if (currentPhase === 'start-to-end') {
} else if (currentPhase === "start-to-end") {
start = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z];
} else if (currentPhase === 'end-to-rest') {
} else if (currentPhase === "end-to-rest") {
start = [materialLocalPos.x, materialLocalPos.y + 0.35, materialLocalPos.z];
}
}
}
if (nextModel && nextPoint && nextModel.type === 'transfer') {
if (nextModel && nextPoint && nextModel.type === "transfer") {
const conveyorModel = scene.getObjectByProperty("uuid", nextModel.modelUuid);
const armbotModel = scene.getObjectByProperty("uuid", armBot.modelUuid);
if (conveyorModel && armbotModel) {
const localPoint = new THREE.Vector3(
nextPoint.position[0],
nextPoint.position[1],
nextPoint.position[2]
);
const localPoint = new THREE.Vector3(nextPoint.position[0], nextPoint.position[1], nextPoint.position[2]);
const worldPoint = conveyorModel.localToWorld(localPoint);
armbotModel.worldToLocal(worldPoint);
if (currentPhase === 'start-to-end') {
if (currentPhase === "start-to-end") {
end = [worldPoint.x, worldPoint.y + 0.35, worldPoint.z];
}
}
}
}
}
if (currentPhase === 'end-to-rest') {
if (currentPhase === "end-to-rest") {
const armbotModel = scene.getObjectByProperty("uuid", armBot.modelUuid);
const armbotWorldPos = new THREE.Vector3();
@@ -293,15 +280,7 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
arcPoints = arcCounterClockwise;
}
const pathVectors = [
new THREE.Vector3(start[0], start[1], start[2]),
new THREE.Vector3(start[0], curveHeight, start[2]),
new THREE.Vector3(nearestToStart[0], curveHeight, nearestToStart[2]),
...arcPoints.map(point => new THREE.Vector3(point[0], curveHeight, point[2])),
new THREE.Vector3(nearestToEnd[0], curveHeight, nearestToEnd[2]),
new THREE.Vector3(end[0], curveHeight, end[2]),
new THREE.Vector3(end[0], end[1], end[2])
];
const pathVectors = [new THREE.Vector3(start[0], start[1], start[2]), new THREE.Vector3(start[0], curveHeight, start[2]), new THREE.Vector3(nearestToStart[0], curveHeight, nearestToStart[2]), ...arcPoints.map((point) => new THREE.Vector3(point[0], curveHeight, point[2])), new THREE.Vector3(nearestToEnd[0], curveHeight, nearestToEnd[2]), new THREE.Vector3(end[0], curveHeight, end[2]), new THREE.Vector3(end[0], end[1], end[2])];
const pathSegments: [THREE.Vector3, THREE.Vector3][] = [];
for (let i = 0; i < pathVectors.length - 1; i++) {
@@ -426,7 +405,6 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
);
})}
</group> */}
</>
);
}

View File

@@ -1,15 +1,14 @@
import { useEffect, useRef, useState } from 'react'
import { useEffect, useRef, useState } from "react";
import * as THREE from "three";
import IKInstance from '../ikInstance/ikInstance';
import RoboticArmAnimator from '../animator/roboticArmAnimator';
import MaterialAnimator from '../animator/materialAnimator';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import IKInstance from "../ikInstance/ikInstance";
import RoboticArmAnimator from "../animator/roboticArmAnimator";
import MaterialAnimator from "../animator/materialAnimator";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useTriggerHandler } from "../../../triggers/triggerHandler/useTriggerHandler";
import { useSceneContext } from "../../../../scene/sceneContext";
function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
const [currentPhase, setCurrentPhase] = useState<(string)>("init");
const [currentPhase, setCurrentPhase] = useState<string>("init");
const [path, setPath] = useState<[number, number, number][]>([]);
const [ikSolver, setIkSolver] = useState<any>(null);
const restPosition = new THREE.Vector3(0, 1.75, -1.6);
@@ -18,15 +17,13 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
const isPausedRef = useRef<boolean>(false);
const isSpeedRef = useRef<any>(null);
const { selectedProductStore } = useProductContext();
const { materialStore, armBotStore, vehicleStore, storageUnitStore, productStore, assetStore } = useSceneContext();
const { resetAsset } = assetStore();
const { setArmBotActive, setArmBotState, removeCurrentAction, incrementActiveTime, incrementIdleTime } = armBotStore();
const { decrementVehicleLoad, removeLastMaterial } = vehicleStore();
const { removeLastMaterial: removeLastStorageMaterial, updateCurrentLoad } = storageUnitStore();
const { getMaterialById, setIsVisible } = materialStore();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, getEventByActionUuid, getEventByModelUuid } = productStore();
const { getActionByUuid, getEventByActionUuid, getEventByModelUuid, selectedProduct } = productStore();
const { triggerPointActions } = useTriggerHandler();
const { isPlaying } = usePlayButtonStore();
const { isReset } = useResetButtonStore();
@@ -39,9 +36,9 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
const animationFrameIdRef = useRef<number | null>(null);
const previousTimeRef = useRef<number | null>(null);
const lastRemoved = useRef<{ type: string, materialId: string, modelId: string } | null>(null);
const lastRemoved = useRef<{ type: string; materialId: string; modelId: string } | null>(null);
const action = getActionByUuid(selectedProduct.productUuid, armBot.currentAction?.actionUuid || '');
const action = getActionByUuid(selectedProduct.productUuid, armBot.currentAction?.actionUuid || "");
const handlePickUpTrigger = () => {
if (armBot?.currentAction?.materialId) {
@@ -49,17 +46,17 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
if (material?.previous?.modelUuid) {
const previousModel = getEventByActionUuid(selectedProduct.productUuid, material.previous.actionUuid);
if (previousModel) {
if (previousModel.type === 'transfer') {
if (previousModel.type === "transfer") {
setIsVisible(armBot.currentAction.materialId, false);
} else if (previousModel.type === 'machine') {
} else if (previousModel.type === "machine") {
// machine specific logic
} else if (previousModel.type === 'vehicle') {
} else if (previousModel.type === "vehicle") {
decrementVehicleLoad(previousModel.modelUuid, 1);
removeLastMaterial(previousModel.modelUuid);
} else if (previousModel.type === 'storageUnit') {
} else if (previousModel.type === "storageUnit") {
// storage unit logic
removeLastStorageMaterial(previousModel.modelUuid);
updateCurrentLoad(previousModel.modelUuid, -1)
updateCurrentLoad(previousModel.modelUuid, -1);
}
lastRemoved.current = { type: previousModel.type, materialId: armBot.currentAction.materialId, modelId: previousModel.modelUuid };
} else {
@@ -69,28 +66,27 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
setIsVisible(armBot.currentAction.materialId, false);
}
}
}
};
const handleDropTrigger = () => {
if (armBot.currentAction) {
const action = getActionByUuid(selectedProduct.productUuid, armBot.currentAction.actionUuid);
const model = getEventByModelUuid(selectedProduct.productUuid, action?.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
const model = getEventByModelUuid(selectedProduct.productUuid, action?.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || "");
if (action?.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid) {
if (!model) return;
if (model.type === 'transfer') {
setIsVisible(armBot.currentAction.materialId || '', true);
} else if (model.type === 'machine') {
if (model.type === "transfer") {
setIsVisible(armBot.currentAction.materialId || "", true);
} else if (model.type === "machine") {
//
} else if (model.type === 'vehicle') {
} else if (model.type === "vehicle") {
//
} else if (model.type === 'storageUnit') {
} else if (model.type === "storageUnit") {
//
}
}
if (action && armBot.currentAction.materialId) {
triggerPointActions(action, armBot.currentAction.materialId)
removeCurrentAction(armBot.modelUuid)
triggerPointActions(action, armBot.currentAction.materialId);
removeCurrentAction(armBot.modelUuid);
}
// if (lastRemoved.current) {
@@ -101,7 +97,7 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
// }
// }
}
}
};
useEffect(() => {
isPausedRef.current = isPaused;
@@ -113,16 +109,16 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
useEffect(() => {
if (isReset || !isPlaying) {
logStatus(armBot.modelUuid, "Simulation Play Reset Successfully")
setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "idle")
logStatus(armBot.modelUuid, "Simulation Play Reset Successfully");
setArmBotActive(armBot.modelUuid, false);
setArmBotState(armBot.modelUuid, "idle");
setCurrentPhase("init");
setPath([])
setPath([]);
setIkSolver(null);
removeCurrentAction(armBot.modelUuid);
resetAsset(armBot.modelUuid);
isPausedRef.current = false
pauseTimeRef.current = null
isPausedRef.current = false;
pauseTimeRef.current = null;
activeSecondsElapsed.current = 0;
idleSecondsElapsed.current = 0;
previousTimeRef.current = null;
@@ -131,17 +127,16 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
cancelAnimationFrame(animationFrameIdRef.current);
animationFrameIdRef.current = null;
}
const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone
);
const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
if (targetBones && isPlaying) {
let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition)
let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition);
if (curve) {
setPath(curve.points.map(point => [point.x, point.y, point.z]));
logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.")
setPath(curve.points.map((point) => [point.x, point.y, point.z]));
logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.");
}
}
}
}, [isReset, isPlaying])
}, [isReset, isPlaying]);
function animate(currentTime: number) {
if (previousTimeRef.current === null) {
@@ -164,7 +159,7 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
}
useEffect(() => {
if (!isPlaying) return
if (!isPlaying) return;
if (!armBot.isActive && armBot.state === "idle" && (currentPhase === "rest" || currentPhase === "init")) {
cancelAnimationFrame(animationFrameIdRef.current!);
@@ -173,7 +168,6 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
// console.log('🚨Final Active Time:',armBot.modelUuid, roundedActiveTime, 'seconds');
incrementActiveTime(armBot.modelUuid, roundedActiveTime);
activeSecondsElapsed.current = 0;
} else if (armBot.isActive && armBot.state !== "idle" && currentPhase !== "rest" && armBot.currentAction) {
cancelAnimationFrame(animationFrameIdRef.current!);
animationFrameIdRef.current = null;
@@ -181,7 +175,6 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
// console.log('🕒 Final Idle Time:', armBot.modelUuid,roundedIdleTime, 'seconds');
incrementIdleTime(armBot.modelUuid, roundedIdleTime);
idleSecondsElapsed.current = 0;
}
if (animationFrameIdRef.current === null) {
animationFrameIdRef.current = requestAnimationFrame(animate);
@@ -193,28 +186,26 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
animationFrameIdRef.current = null; // Reset the animation frame ID
}
};
}, [armBot, currentPhase, isPlaying])
}, [armBot, currentPhase, isPlaying]);
useEffect(() => {
const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
if (!isReset && isPlaying) {
if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "init") {
if (targetBones) {
setArmBotActive(armBot.modelUuid, true)
setArmBotState(armBot.modelUuid, "running")
setArmBotActive(armBot.modelUuid, true);
setArmBotState(armBot.modelUuid, "running");
setCurrentPhase("init-to-rest");
let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition)
let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition);
if (curve) {
setPath(curve.points.map(point => [point.x, point.y, point.z]));
setPath(curve.points.map((point) => [point.x, point.y, point.z]));
}
}
logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.")
logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.");
} else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "rest" && !armBot.currentAction) {
logStatus(armBot.modelUuid, "Waiting to trigger CurrentAction")
logStatus(armBot.modelUuid, "Waiting to trigger CurrentAction");
} else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "rest" && armBot.currentAction) {
if (armBot.currentAction) {
setArmBotActive(armBot.modelUuid, true);
setArmBotState(armBot.modelUuid, "running");
setCurrentPhase("rest-to-start");
@@ -223,11 +214,11 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
if (startPoint) {
let curve = createCurveBetweenTwoPoints(targetBones.position, new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]));
if (curve) {
setPath(curve.points.map(point => [point.x, point.y, point.z]));
setPath(curve.points.map((point) => [point.x, point.y, point.z]));
}
}
}
logStatus(armBot.modelUuid, "Moving armBot from rest point to start position.")
logStatus(armBot.modelUuid, "Moving armBot from rest point to start position.");
} else if (armBot && !armBot.isActive && armBot.state === "running" && currentPhase === "picking" && armBot.currentAction) {
setTimeout(() => {
setArmBotActive(armBot.modelUuid, true);
@@ -240,12 +231,12 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
let curve = createCurveBetweenTwoPoints(new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]), new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]));
if (curve) {
logStatus(armBot.modelUuid, "picking the object");
setPath(curve.points.map(point => [point.x, point.y, point.z]))
setPath(curve.points.map((point) => [point.x, point.y, point.z]));
handlePickUpTrigger();
}
}
logStatus(armBot.modelUuid, "Moving armBot from start point to end position.")
}, 100)
logStatus(armBot.modelUuid, "Moving armBot from start point to end position.");
}, 100);
} else if (armBot && !armBot.isActive && armBot.state === "running" && currentPhase === "dropping" && armBot.currentAction) {
setTimeout(() => {
setArmBotActive(armBot.modelUuid, true);
@@ -257,25 +248,24 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
let curve = createCurveBetweenTwoPoints(new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]), restPosition);
if (curve) {
logStatus(armBot.modelUuid, "dropping the object");
setPath(curve.points.map(point => [point.x, point.y, point.z]));
setPath(curve.points.map((point) => [point.x, point.y, point.z]));
handleDropTrigger();
}
}
logStatus(armBot.modelUuid, "Moving armBot from end point to rest position.")
}, 100)
logStatus(armBot.modelUuid, "Moving armBot from end point to rest position.");
}, 100);
}
} else {
logStatus(armBot.modelUuid, "Simulation Play Exited")
setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "idle")
logStatus(armBot.modelUuid, "Simulation Play Exited");
setArmBotActive(armBot.modelUuid, false);
setArmBotState(armBot.modelUuid, "idle");
setCurrentPhase("init");
setIkSolver(null);
setPath([])
isPausedRef.current = false
pauseTimeRef.current = null
isPausedRef.current = false
setPath([]);
isPausedRef.current = false;
pauseTimeRef.current = null;
isPausedRef.current = false;
activeSecondsElapsed.current = 0;
idleSecondsElapsed.current = 0;
previousTimeRef.current = null;
@@ -283,10 +273,9 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
cancelAnimationFrame(animationFrameIdRef.current);
animationFrameIdRef.current = null;
}
removeCurrentAction(armBot.modelUuid)
removeCurrentAction(armBot.modelUuid);
}
}, [currentPhase, armBot, isPlaying, isReset, ikSolver])
}, [currentPhase, armBot, isPlaying, isReset, ikSolver]);
function createCurveBetweenTwoPoints(p1: any, p2: any) {
const mid = new THREE.Vector3().addVectors(p1, p2).multiplyScalar(0.5);
@@ -297,57 +286,46 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
const HandleCallback = () => {
if (armBot.isActive && armBot.state == "running" && currentPhase == "init-to-rest") {
logStatus(armBot.modelUuid, "Callback triggered: rest");
setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "idle")
setArmBotActive(armBot.modelUuid, false);
setArmBotState(armBot.modelUuid, "idle");
setCurrentPhase("rest");
setPath([])
}
else if (armBot.state == "running" && currentPhase == "rest-to-start") {
setPath([]);
} else if (armBot.state == "running" && currentPhase == "rest-to-start") {
logStatus(armBot.modelUuid, "Callback triggered: pick.");
setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "running")
setArmBotActive(armBot.modelUuid, false);
setArmBotState(armBot.modelUuid, "running");
setCurrentPhase("picking");
setPath([])
}
else if (armBot.isActive && armBot.state == "running" && currentPhase == "start-to-end") {
setPath([]);
} else if (armBot.isActive && armBot.state == "running" && currentPhase == "start-to-end") {
logStatus(armBot.modelUuid, "Callback triggered: drop.");
setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "running")
setArmBotActive(armBot.modelUuid, false);
setArmBotState(armBot.modelUuid, "running");
setCurrentPhase("dropping");
setPath([])
}
else if (armBot.isActive && armBot.state == "running" && currentPhase == "end-to-rest") {
setPath([]);
} else if (armBot.isActive && armBot.state == "running" && currentPhase == "end-to-rest") {
logStatus(armBot.modelUuid, "Callback triggered: rest, cycle completed.");
setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "idle")
setArmBotActive(armBot.modelUuid, false);
setArmBotState(armBot.modelUuid, "idle");
setCurrentPhase("rest");
setPath([])
}
setPath([]);
}
};
const logStatus = (id: string, status: string) => {
// console.log('status: ', status);
}
};
return (
<>
{!isReset && isPlaying && (
<>
<IKInstance setIkSolver={setIkSolver} armBot={armBot} />
<RoboticArmAnimator
HandleCallback={HandleCallback}
restPosition={restPosition}
ikSolver={ikSolver}
targetBone={targetBone}
armBot={armBot}
path={path}
currentPhase={currentPhase}
/>
<RoboticArmAnimator HandleCallback={HandleCallback} restPosition={restPosition} ikSolver={ikSolver} targetBone={targetBone} armBot={armBot} path={path} currentPhase={currentPhase} />
</>
)}
<MaterialAnimator ikSolver={ikSolver} armBot={armBot} currentPhase={currentPhase} />
</>
)
);
}
export default RoboticArmInstance;

View File

@@ -1,16 +1,13 @@
import { useEffect } from 'react';
import { useActionHandler } from '../actions/useActionHandler';
import { usePlayButtonStore, useResetButtonStore } from '../../../store/ui/usePlayButtonStore';
import { determineExecutionOrder } from './functions/determineExecutionOrder';
import { useProductContext } from '../products/productContext';
import { useSceneContext } from '../../scene/sceneContext';
import { useEffect } from "react";
import { useActionHandler } from "../actions/useActionHandler";
import { usePlayButtonStore, useResetButtonStore } from "../../../store/ui/usePlayButtonStore";
import { determineExecutionOrder } from "./functions/determineExecutionOrder";
import { useSceneContext } from "../../scene/sceneContext";
function Simulator() {
const { selectedProductStore } = useProductContext();
const { productStore } = useSceneContext();
const { products, getProductById } = productStore();
const { products, getProductById, selectedProduct } = productStore();
const { handleAction } = useActionHandler();
const { selectedProduct } = selectedProductStore();
const { isPlaying } = usePlayButtonStore();
const { isReset } = useResetButtonStore();
@@ -22,19 +19,12 @@ function Simulator() {
const executionOrder = determineExecutionOrder([product]);
executionOrder.forEach(action => {
executionOrder.forEach((action) => {
handleAction(action);
});
}, [products, isPlaying, isReset, selectedProduct]);
return (
<>
</>
);
return <></>;
}
export default Simulator;

View File

@@ -10,7 +10,6 @@ import armPick from "../../../../assets/gltf-glb/ui/arm_ui_pick.glb";
import armDrop from "../../../../assets/gltf-glb/ui/arm_ui_drop.glb";
import { upsertProductOrEventApi } from "../../../../services/simulation/products/UpsertProductOrEventApi";
import { useSceneContext } from "../../../scene/sceneContext";
import { useProductContext } from "../../products/productContext";
import { useParams } from "react-router-dom";
type Positions = {
@@ -24,10 +23,8 @@ const ArmBotUI = () => {
const { armBotStore, productStore, versionStore } = useSceneContext();
const { armBots } = armBotStore();
const { selectedVersion } = versionStore();
const { getEventByModelUuid, updateAction, getActionByUuid } = productStore();
const { getEventByModelUuid, updateAction, getActionByUuid, selectedProduct } = productStore();
const { selectedEventSphere } = useSelectedEventSphere();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { selectedAction } = useSelectedAction();
const { projectId } = useParams();

View File

@@ -2,7 +2,6 @@ import { useRef, useState } from "react";
import * as THREE from "three";
import { ThreeEvent, useThree } from "@react-three/fiber";
import { useSelectedEventData } from "../../../../store/simulation/useSimulationStore";
import { useProductContext } from "../../products/productContext";
import { useSceneContext } from "../../../scene/sceneContext";
type OnUpdateCallback = (object: THREE.Object3D) => void;
@@ -18,14 +17,12 @@ export default function useDraggableGLTF(
minDistance: 1.2,
maxDistance: 2,
minheight: 0.6,
maxheight: 1.9
maxheight: 1.9,
}
) {
const { productStore } = useSceneContext();
const { getEventByModelUuid } = productStore();
const { getEventByModelUuid, selectedProduct } = productStore();
const { selectedEventData } = useSelectedEventData();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { camera, gl, controls } = useThree();
const activeObjRef = useRef<THREE.Object3D | null>(null);
const planeRef = useRef<THREE.Plane>(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0));
@@ -81,10 +78,7 @@ export default function useDraggableGLTF(
const handlePointerMove = (e: PointerEvent) => {
if (!activeObjRef.current) return;
if (selectedEventData?.data.type === "roboticArm") {
const selectedArmBot = getEventByModelUuid(
selectedProduct.productUuid,
selectedEventData.data.modelUuid
);
const selectedArmBot = getEventByModelUuid(selectedProduct.productUuid, selectedEventData.data.modelUuid);
if (!selectedArmBot) return;
// Check if Shift key is pressed
const isShiftKeyPressed = e.shiftKey;
@@ -99,10 +93,7 @@ export default function useDraggableGLTF(
// Create a vector to store intersection point
const intersection = new THREE.Vector3();
const intersects = raycaster.ray.intersectPlane(
planeRef.current,
intersection
);
const intersects = raycaster.ray.intersectPlane(planeRef.current, intersection);
if (!intersects) return;
// Add offset for dragging
@@ -170,11 +161,7 @@ export default function useDraggableGLTF(
const clampedDistance = Math.min(Math.max(distance, minDistance), maxDistance);
// Calculate local target
const finalLocal = new THREE.Vector3(
Math.cos(relativeAngle) * clampedDistance,
0,
Math.sin(relativeAngle) * clampedDistance
);
const finalLocal = new THREE.Vector3(Math.cos(relativeAngle) * clampedDistance, 0, Math.sin(relativeAngle) * clampedDistance);
// Rotate back to world space
finalLocal.applyQuaternion(robotQuaternion);
@@ -184,10 +171,7 @@ export default function useDraggableGLTF(
// Clamp Y axis using variables
targetPosition.y = Math.min(
Math.max(targetPosition.y, Math.min(minHeight, maxHeight)),
Math.max(minHeight, maxHeight)
);
targetPosition.y = Math.min(Math.max(targetPosition.y, Math.min(minHeight, maxHeight)), Math.max(minHeight, maxHeight));
// Convert to local if parent exists
if (parent) {

View File

@@ -10,7 +10,6 @@ import { DoubleSide, Group, Plane, Vector3 } from "three";
import startPoint from "../../../../assets/gltf-glb/ui/arrow_green.glb";
import startEnd from "../../../../assets/gltf-glb/ui/arrow_red.glb";
import { useSceneContext } from "../../../scene/sceneContext";
import { useProductContext } from "../../products/productContext";
import { useParams } from "react-router-dom";
const VehicleUI = () => {
@@ -18,11 +17,9 @@ const VehicleUI = () => {
const { scene: endScene } = useGLTF(startEnd) as any;
const prevMousePos = useRef({ x: 0, y: 0 });
const { selectedEventSphere } = useSelectedEventSphere();
const { selectedProductStore } = useProductContext();
const { vehicleStore, productStore, versionStore } = useSceneContext();
const { selectedProduct } = selectedProductStore();
const { vehicles, getVehicleById } = vehicleStore();
const { updateEvent } = productStore();
const { updateEvent, selectedProduct } = productStore();
const [startPosition, setStartPosition] = useState<[number, number, number]>([0, 1, 0]);
const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 1, 0]);

View File

@@ -1,18 +1,17 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh, useSelectedPath } from '../../../../../store/builder/store';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import InteractivePoints from '../animator/interactivePoint';
import { useCallback, useEffect, useRef, useState } from "react";
import * as THREE from "three";
import { NavMeshQuery } from "@recast-navigation/core";
import { useNavMesh, useSelectedPath } from "../../../../../store/builder/store";
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useTriggerHandler } from "../../../triggers/triggerHandler/useTriggerHandler";
import { useSceneContext } from "../../../../scene/sceneContext";
import InteractivePoints from "../animator/interactivePoint";
import MaterialAnimator from '../animator/materialAnimator';
import VehicleAnimator from '../animator/vehicleAnimator';
import MaterialAnimator from "../animator/materialAnimator";
import VehicleAnimator from "../animator/vehicleAnimator";
import { useHumanEventManager } from '../../../human/eventManager/useHumanEventManager';
import { useCraneEventManager } from '../../../crane/eventManager/useCraneEventManager';
import { useHumanEventManager } from "../../../human/eventManager/useHumanEventManager";
import { useCraneEventManager } from "../../../crane/eventManager/useCraneEventManager";
function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) {
const { navMesh } = useNavMesh();
@@ -28,9 +27,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const { setCurrentAnimation, getAssetById } = assetStore();
const { addHumanToMonitor } = useHumanEventManager();
const { addCraneToMonitor } = useCraneEventManager();
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid, selectedProduct } = productStore();
const { vehicles, setCurrentPhase, setVehicleActive, setVehicleState, setVehiclePicking, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial, getLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = vehicleStore();
const [path, setPath] = useState<[number, number, number][]>([]);
const pauseTimeRef = useRef<number | null>(null);
@@ -59,22 +56,19 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
try {
const navMeshQuery = new NavMeshQuery(navMesh);
const { path: segmentPath } = navMeshQuery.computePath(start, end);
if (
segmentPath.length > 0 &&
Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(end.x) &&
Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(end.z)
) {
if (segmentPath.length > 0 && Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(end.x) && Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(end.z)) {
return segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
} else {
const { path: segmentPaths } = navMeshQuery.computePath(start, start);
return segmentPaths.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
}
} catch {
console.error("Failed to compute path");
return [];
}
}, [navMesh]);
},
[navMesh]
);
function vehicleStatus(modelId: string, status: string) {
// console.log(`${modelId} , ${status}`);
@@ -82,22 +76,22 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
// Function to reset everything
function reset() {
setCurrentPhase(agvDetail.modelUuid, 'stationed');
setCurrentPhase(agvDetail.modelUuid, "stationed");
setVehicleActive(agvDetail.modelUuid, false);
setVehiclePicking(agvDetail.modelUuid, false);
setVehicleState(agvDetail.modelUuid, 'idle');
setVehicleState(agvDetail.modelUuid, "idle");
setVehicleLoad(agvDetail.modelUuid, 0);
setPath([]);
startTime = 0;
isPausedRef.current = false;
pauseTimeRef.current = 0;
resetTime(agvDetail.modelUuid)
activeTimeRef.current = 0
idleTimeRef.current = 0
previousTimeRef.current = null
resetTime(agvDetail.modelUuid);
activeTimeRef.current = 0;
idleTimeRef.current = 0;
previousTimeRef.current = null;
if (animationFrameIdRef.current !== null) {
cancelAnimationFrame(animationFrameIdRef.current)
animationFrameIdRef.current = null
cancelAnimationFrame(animationFrameIdRef.current);
animationFrameIdRef.current = null;
}
}
@@ -105,51 +99,41 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
if (isPlaying && selectedPath === "auto") {
if (!agvDetail.point.action.unLoadPoint || !agvDetail.point.action.pickUpPoint) return;
if (!agvDetail.isActive && agvDetail.state === 'idle' && agvDetail.currentPhase === 'stationed') {
const toPickupPath = computePath(
new THREE.Vector3(agvDetail?.position[0], agvDetail?.position[1], agvDetail?.position[2]),
agvDetail?.point?.action?.pickUpPoint?.position
);
if (!agvDetail.isActive && agvDetail.state === "idle" && agvDetail.currentPhase === "stationed") {
const toPickupPath = computePath(new THREE.Vector3(agvDetail?.position[0], agvDetail?.position[1], agvDetail?.position[2]), agvDetail?.point?.action?.pickUpPoint?.position);
setPath(toPickupPath);
setCurrentPhase(agvDetail.modelUuid, 'stationed-pickup');
setVehicleState(agvDetail.modelUuid, 'running');
setCurrentPhase(agvDetail.modelUuid, "stationed-pickup");
setVehicleState(agvDetail.modelUuid, "running");
setVehiclePicking(agvDetail.modelUuid, false);
setVehicleActive(agvDetail.modelUuid, true);
vehicleStatus(agvDetail.modelUuid, 'Started from station, heading to pickup');
vehicleStatus(agvDetail.modelUuid, "Started from station, heading to pickup");
return;
} else if (!agvDetail.isActive && agvDetail.state === 'idle' && agvDetail.currentPhase === 'picking') {
} else if (!agvDetail.isActive && agvDetail.state === "idle" && agvDetail.currentPhase === "picking") {
if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity && agvDetail.currentMaterials.length > 0) {
if (agvDetail.point.action.pickUpPoint && agvDetail.point.action.unLoadPoint) {
const toDrop = computePath(
agvDetail.point.action.pickUpPoint.position,
agvDetail.point.action.unLoadPoint.position
);
const toDrop = computePath(agvDetail.point.action.pickUpPoint.position, agvDetail.point.action.unLoadPoint.position);
setPath(toDrop);
setCurrentPhase(agvDetail.modelUuid, 'pickup-drop');
setVehicleState(agvDetail.modelUuid, 'running');
setCurrentPhase(agvDetail.modelUuid, "pickup-drop");
setVehicleState(agvDetail.modelUuid, "running");
setVehiclePicking(agvDetail.modelUuid, false);
setVehicleActive(agvDetail.modelUuid, true);
vehicleStatus(agvDetail.modelUuid, 'Started from pickup point, heading to drop point');
vehicleStatus(agvDetail.modelUuid, "Started from pickup point, heading to drop point");
}
}
} else if (!agvDetail.isActive && agvDetail.state === 'idle' && agvDetail.currentPhase === 'dropping' && agvDetail.currentLoad === 0) {
} else if (!agvDetail.isActive && agvDetail.state === "idle" && agvDetail.currentPhase === "dropping" && agvDetail.currentLoad === 0) {
if (agvDetail.point.action.pickUpPoint && agvDetail.point.action.unLoadPoint) {
const dropToPickup = computePath(
agvDetail.point.action.unLoadPoint.position,
agvDetail.point.action.pickUpPoint.position
);
const dropToPickup = computePath(agvDetail.point.action.unLoadPoint.position, agvDetail.point.action.pickUpPoint.position);
setPath(dropToPickup);
setCurrentPhase(agvDetail.modelUuid, 'drop-pickup');
setVehicleState(agvDetail.modelUuid, 'running');
setCurrentPhase(agvDetail.modelUuid, "drop-pickup");
setVehicleState(agvDetail.modelUuid, "running");
setVehiclePicking(agvDetail.modelUuid, false);
setVehicleActive(agvDetail.modelUuid, true);
vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point');
vehicleStatus(agvDetail.modelUuid, "Started from dropping point, heading to pickup point");
}
}
}
else {
reset()
} else {
reset();
}
}, [vehicles, agvDetail.currentPhase, path, isPlaying, selectedPath]);
@@ -174,7 +158,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}
useEffect(() => {
if (!isPlaying) return
if (!isPlaying) return;
if (!agvDetail.isActive) {
const roundedActiveTime = Math.round(activeTimeRef.current);
// console.log('Final Active Time:', roundedActiveTime, 'seconds');
@@ -200,63 +184,63 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}, [agvDetail, isPlaying]);
function handleCallBack() {
if (agvDetail.currentPhase === 'stationed-pickup') {
setCurrentPhase(agvDetail.modelUuid, 'picking');
setVehicleState(agvDetail.modelUuid, 'idle');
if (agvDetail.currentPhase === "stationed-pickup") {
setCurrentPhase(agvDetail.modelUuid, "picking");
setVehicleState(agvDetail.modelUuid, "idle");
setVehiclePicking(agvDetail.modelUuid, true);
setVehicleActive(agvDetail.modelUuid, false);
vehicleStatus(agvDetail.modelUuid, 'Reached pickup point, waiting for material');
vehicleStatus(agvDetail.modelUuid, "Reached pickup point, waiting for material");
setPath([]);
} else if (agvDetail.currentPhase === 'pickup-drop') {
setCurrentPhase(agvDetail.modelUuid, 'dropping');
setVehicleState(agvDetail.modelUuid, 'idle');
} else if (agvDetail.currentPhase === "pickup-drop") {
setCurrentPhase(agvDetail.modelUuid, "dropping");
setVehicleState(agvDetail.modelUuid, "idle");
setVehiclePicking(agvDetail.modelUuid, false);
setVehicleActive(agvDetail.modelUuid, false);
vehicleStatus(agvDetail.modelUuid, 'Reached drop point');
vehicleStatus(agvDetail.modelUuid, "Reached drop point");
setPath([]);
} else if (agvDetail.currentPhase === 'drop-pickup') {
setCurrentPhase(agvDetail.modelUuid, 'picking');
setVehicleState(agvDetail.modelUuid, 'idle');
} else if (agvDetail.currentPhase === "drop-pickup") {
setCurrentPhase(agvDetail.modelUuid, "picking");
setVehicleState(agvDetail.modelUuid, "idle");
setVehiclePicking(agvDetail.modelUuid, true);
setVehicleActive(agvDetail.modelUuid, false);
setPath([]);
clearCurrentMaterials(agvDetail.modelUuid)
vehicleStatus(agvDetail.modelUuid, 'Reached pickup point again, cycle complete');
clearCurrentMaterials(agvDetail.modelUuid);
vehicleStatus(agvDetail.modelUuid, "Reached pickup point again, cycle complete");
}
}
function startUnloadingProcess() {
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 || '');
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') {
if (model.type === "transfer") {
const action = getActionByUuid(selectedProduct.productUuid, agvDetail.point.action.actionUuid);
if (action) {
handleMaterialDropToConveyor(model);
}
} else if (model.type === 'machine') {
} else if (model.type === "machine") {
//
} else if (model.type === 'roboticArm') {
} else if (model.type === "roboticArm") {
const action = getActionByUuid(selectedProduct.productUuid, agvDetail.point.action.actionUuid);
if (action) {
handleMaterialDropToArmBot(model);
}
} else if (model.type === 'storageUnit') {
} else if (model.type === "storageUnit") {
const action = getActionByUuid(selectedProduct.productUuid, agvDetail.point.action.actionUuid);
if (action) {
handleMaterialDropToStorageUnit(model);
}
} else if (model.type === 'human') {
} else if (model.type === "human") {
const action = getActionByUuid(selectedProduct.productUuid, agvDetail.point.action.actionUuid);
if (action && (triggeredAction?.actionType === 'manufacturer' || triggeredAction?.actionType === 'worker')) {
if (action && (triggeredAction?.actionType === "manufacturer" || triggeredAction?.actionType === "worker")) {
handleMaterialDropToHuman(model, triggeredAction);
}
} else if (model.type === 'crane') {
} else if (model.type === "crane") {
const action = getActionByUuid(selectedProduct.productUuid, agvDetail.point.action.actionUuid);
if (action && (triggeredAction?.actionType === 'pickAndDrop')) {
if (action && triggeredAction?.actionType === "pickAndDrop") {
handleMaterialDropToCrane(model, triggeredAction);
addCraneAction(model.modelUuid, triggeredAction.actionUuid, null, null);
}
@@ -274,25 +258,20 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}
function handleMaterialDropToCrane(model: CraneEventSchema, action: CraneAction) {
if (model) {
if (action.actionType === 'pickAndDrop') {
addCraneToMonitor(model.modelUuid, () => {
loopMaterialDropToCrane(
agvDetail,
if (action.actionType === "pickAndDrop") {
addCraneToMonitor(
model.modelUuid,
action.actionUuid
() => {
loopMaterialDropToCrane(agvDetail, model.modelUuid, action.actionUuid);
},
action.actionUuid || ""
);
}, action.actionUuid || '')
}
}
}
function loopMaterialDropToCrane(
vehicle: VehicleStatus,
craneId: string,
craneActionId: string
) {
function loopMaterialDropToCrane(vehicle: VehicleStatus, craneId: string, craneActionId: string) {
let currentVehicleLoad = vehicle.currentLoad;
const unloadLoop = () => {
@@ -308,7 +287,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
setIsVisible(material.materialId, false);
}
return;
} else if (!crane.isCarrying && !crane.isActive && crane.currentLoad < (craneaction?.maxPickUpCount || 0) && craneaction?.actionType === 'pickAndDrop') {
} else if (!crane.isCarrying && !crane.isActive && crane.currentLoad < (craneaction?.maxPickUpCount || 0) && craneaction?.actionType === "pickAndDrop") {
const material = getLastMaterial(vehicle.modelUuid);
if (material) {
incrementCraneLoad(craneId, 1);
@@ -318,7 +297,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}
setTimeout(() => {
requestAnimationFrame(unloadLoop);
}, 500)
}, 500);
};
const crane = getCraneById(craneId);
@@ -326,31 +305,25 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
if (crane && crane.currentLoad < (craneaction?.maxPickUpCount || 0)) {
setTimeout(() => {
unloadLoop();
}, 500)
}, 500);
}
}
function handleMaterialDropToHuman(model: HumanEventSchema, action: HumanAction) {
if (model) {
if (action.actionType === 'worker') {
addHumanToMonitor(model.modelUuid, () => {
loopMaterialDropToHuman(
agvDetail,
if (action.actionType === "worker") {
addHumanToMonitor(
model.modelUuid,
action.actionUuid
() => {
loopMaterialDropToHuman(agvDetail, model.modelUuid, action.actionUuid);
},
action.actionUuid || ""
);
}, action.actionUuid || '')
}
}
}
function loopMaterialDropToHuman(
vehicle: VehicleStatus,
humanId: string,
humanActionId: string
) {
function loopMaterialDropToHuman(vehicle: VehicleStatus, humanId: string, humanActionId: string) {
let currentVehicleLoad = vehicle.currentLoad;
const unloadLoop = () => {
@@ -359,8 +332,8 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const humanAction = human?.point.actions.find((action) => action.actionUuid === humanActionId);
if (!human || human.currentAction?.actionUuid !== humanAction?.actionUuid) return;
if (!human.isActive && human.currentLoad < (humanAction?.loadCapacity || 0) && humanAsset?.animationState?.current === 'idle' && humanAction?.actionType === 'worker') {
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
if (!human.isActive && human.currentLoad < (humanAction?.loadCapacity || 0) && humanAsset?.animationState?.current === "idle" && humanAction?.actionType === "worker") {
setCurrentAnimation(human.modelUuid, "pickup", true, false, false);
decrementVehicleLoad(vehicle.modelUuid, 1);
currentVehicleLoad -= 1;
const material = removeLastMaterial(vehicle.modelUuid);
@@ -373,7 +346,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}
setTimeout(() => {
requestAnimationFrame(unloadLoop);
}, 500)
}, 500);
};
const human = getHumanById(humanId);
@@ -384,33 +357,19 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}
setTimeout(() => {
unloadLoop();
}, 500)
}, 500);
}
}
function handleMaterialDropToStorageUnit(model: StorageEventSchema) {
if (model) {
loopMaterialDropToStorage(
agvDetail.modelUuid,
agvDetail.currentLoad,
agvDetail.point.action.unLoadDuration,
model.modelUuid,
model.storageCapacity,
agvDetail.point.action
);
loopMaterialDropToStorage(agvDetail.modelUuid, agvDetail.currentLoad, agvDetail.point.action.unLoadDuration, model.modelUuid, model.storageCapacity, agvDetail.point.action);
}
}
function loopMaterialDropToStorage(
vehicleId: string,
vehicleCurrentLoad: number,
unLoadDuration: number,
storageUnitId: string,
storageMaxCapacity: number,
action: VehicleAction
) {
function loopMaterialDropToStorage(vehicleId: string, vehicleCurrentLoad: number, unLoadDuration: number, storageUnitId: string, storageMaxCapacity: number, action: VehicleAction) {
startTime = performance.now();
const fixedInterval = ((unLoadDuration / vehicleCurrentLoad) * (1000 / isSpeedRef.current));
const fixedInterval = (unLoadDuration / vehicleCurrentLoad) * (1000 / isSpeedRef.current);
const unloadLoop = () => {
if (isPausedRef.current) {
@@ -429,18 +388,13 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const storageUnit = getStorageUnitById(storageUnitId);
if (elapsedTime >= fixedInterval) {
if (storageUnit && agvDetail &&
storageUnit.currentLoad < storageMaxCapacity &&
vehicleCurrentLoad > 0) {
if (storageUnit && agvDetail && storageUnit.currentLoad < storageMaxCapacity && vehicleCurrentLoad > 0) {
decrementVehicleLoad(vehicleId, 1);
vehicleCurrentLoad -= 1;
const material = removeLastMaterial(vehicleId);
if (material) {
triggerPointActions(action, material.materialId);
}
if (vehicleCurrentLoad > 0 && storageUnit.currentLoad < storageMaxCapacity) {
@@ -462,23 +416,11 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
function handleMaterialDropToConveyor(model: ConveyorEventSchema) {
const conveyor = getConveyorById(model.modelUuid);
if (conveyor) {
loopMaterialDropToConveyor(
agvDetail.modelUuid,
agvDetail.currentLoad,
conveyor.modelUuid,
agvDetail.point.action.unLoadDuration,
agvDetail.point.action
);
loopMaterialDropToConveyor(agvDetail.modelUuid, agvDetail.currentLoad, conveyor.modelUuid, agvDetail.point.action.unLoadDuration, agvDetail.point.action);
}
}
function loopMaterialDropToConveyor(
vehicleId: string,
vehicleCurrentLoad: number,
conveyorId: string,
unLoadDuration: number,
action: VehicleAction
) {
function loopMaterialDropToConveyor(vehicleId: string, vehicleCurrentLoad: number, conveyorId: string, unLoadDuration: number, action: VehicleAction) {
let lastIncrementTime = performance.now();
let pauseStartTime: number | null = null;
let totalPausedDuration = 0;
@@ -487,7 +429,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const dropLoop = (currentTime: number) => {
const conveyor = getConveyorById(conveyorId);
if (isPausedRef.current || (conveyor?.isPaused)) {
if (isPausedRef.current || conveyor?.isPaused) {
if (pauseStartTime === null) {
pauseStartTime = currentTime;
}
@@ -531,28 +473,16 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
function handleMaterialDropToArmBot(model: RoboticArmEventSchema) {
const armBot = getArmBotById(model.modelUuid);
if (armBot && armBot.state === 'idle' && !armBot.isActive) {
loopMaterialDropToArmBot(
agvDetail.modelUuid,
agvDetail.currentLoad,
agvDetail.point.action.unLoadDuration,
model.modelUuid,
agvDetail.point.action
);
if (armBot && armBot.state === "idle" && !armBot.isActive) {
loopMaterialDropToArmBot(agvDetail.modelUuid, agvDetail.currentLoad, agvDetail.point.action.unLoadDuration, model.modelUuid, agvDetail.point.action);
}
}
function loopMaterialDropToArmBot(
vehicleId: string,
vehicleCurrentLoad: number,
unLoadDuration: number,
armBotId: string,
action: VehicleAction
) {
function loopMaterialDropToArmBot(vehicleId: string, vehicleCurrentLoad: number, unLoadDuration: number, armBotId: string, action: VehicleAction) {
startTime = performance.now();
const armBot = getArmBotById(armBotId);
if (!armBot || armBot.state !== 'idle' || armBot.isActive || vehicleCurrentLoad <= 0) {
if (!armBot || armBot.state !== "idle" || armBot.isActive || vehicleCurrentLoad <= 0) {
return;
}
@@ -582,7 +512,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
setTimeout(() => {
const waitForNextTransfer = () => {
const currentArmBot = getArmBotById(armBotId);
if (currentArmBot && currentArmBot.state === 'idle' && !currentArmBot.isActive) {
if (currentArmBot && currentArmBot.state === "idle" && !currentArmBot.isActive) {
startTime = performance.now();
loopMaterialDropToArmBot(vehicleId, vehicleCurrentLoad, unLoadDuration, armBotId, action);
} else {
@@ -590,7 +520,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}
};
waitForNextTransfer();
}, 0)
}, 0);
}
}
} else {
@@ -616,7 +546,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const elapsedTime = performance.now() - startTime;
const unLoadDuration = agvDetail.point.action.unLoadDuration;
fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / isSpeedRef.current));
fixedInterval = (unLoadDuration / agvDetail.currentLoad) * (1000 / isSpeedRef.current);
if (elapsedTime >= fixedInterval) {
let droppedMat = droppedMaterial - 1;
@@ -639,16 +569,8 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
return (
<>
<VehicleAnimator
path={path}
handleCallBack={handleCallBack}
currentPhase={agvDetail.currentPhase}
agvUuid={agvDetail?.modelUuid}
agvDetail={agvDetail}
reset={reset}
startUnloadingProcess={startUnloadingProcess}
/>
{selectedPath === "manual" && (<InteractivePoints agvUuid={agvDetail?.modelUuid} />)}
<VehicleAnimator path={path} handleCallBack={handleCallBack} currentPhase={agvDetail.currentPhase} agvUuid={agvDetail?.modelUuid} agvDetail={agvDetail} reset={reset} startUnloadingProcess={startUnloadingProcess} />
{selectedPath === "manual" && <InteractivePoints agvUuid={agvDetail?.modelUuid} />}
<MaterialAnimator agvDetail={agvDetail} />
</>
);

View File

@@ -13,7 +13,6 @@ import { getUserData } from "../functions/getUserData";
import { SceneProvider } from "../modules/scene/sceneContext";
import { sharedWithMeProjects } from "../services/dashboard/sharedWithMeProject";
import { handleCanvasCursors } from "../utils/mouseUtils/handleCanvasCursors";
import { ProductProvider } from "../modules/simulation/products/productContext";
import MainScene from "../components/layout/scenes/MainScene";
import ComparisonScene from "../components/layout/scenes/ComparisonScene";
@@ -84,14 +83,10 @@ const Project: React.FC = () => {
return (
<div className="project-main">
<SceneProvider layout="Main Layout">
<ProductProvider>
<MainScene />
</ProductProvider>
</SceneProvider>
<SceneProvider layout="Comparison Layout">
<ProductProvider>
<ComparisonScene />
</ProductProvider>
</SceneProvider>
{selectedUser && <FollowPerson />}
{isLogListVisible && (

View File

@@ -1,8 +1,12 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
type ProductsStore = {
products: productsSchema;
selectedProduct: { productUuid: string; productName: string };
setSelectedProduct: (productUuid: string, productName: string) => void;
clearSelectedProduct: () => void;
// Product-level actions
addProduct: (productName: string, productUuid: string) => void;
@@ -20,39 +24,17 @@ type ProductsStore = {
// Point-level actions
addPoint: (productUuid: string, modelUuid: string, point: PointsScheme) => EventsSchema | undefined;
removePoint: (productUuid: string, modelUuid: string, pointUuid: string) => EventsSchema | undefined;
updatePoint: (
productUuid: string,
modelUuid: string,
pointUuid: string,
updates: Partial<PointsScheme>
) => EventsSchema | undefined;
updatePoint: (productUuid: string, modelUuid: string, pointUuid: string, updates: Partial<PointsScheme>) => EventsSchema | undefined;
// Action-level actions
addAction: (
productUuid: string,
modelUuid: string,
pointUuid: string,
action: ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction
) => EventsSchema | undefined;
addAction: (productUuid: string, modelUuid: string, pointUuid: string, action: ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction) => EventsSchema | undefined;
removeAction: (productUuid: string, actionUuid: string) => EventsSchema | undefined;
updateAction: (
productUuid: string,
actionUuid: string,
updates: Partial<ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction>
) => EventsSchema | undefined;
updateAction: (productUuid: string, actionUuid: string, updates: Partial<ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction>) => EventsSchema | undefined;
// Trigger-level actionss
addTrigger: (
productUuid: string,
actionUuid: string,
trigger: TriggerSchema
) => EventsSchema | undefined;
addTrigger: (productUuid: string, actionUuid: string, trigger: TriggerSchema) => EventsSchema | undefined;
removeTrigger: (productUuid: string, triggerUuid: string) => EventsSchema | undefined;
updateTrigger: (
productUuid: string,
triggerUuid: string,
updates: Partial<TriggerSchema>
) => EventsSchema | undefined;
updateTrigger: (productUuid: string, triggerUuid: string, updates: Partial<TriggerSchema>) => EventsSchema | undefined;
// Renaming functions
renameProduct: (productUuid: string, newName: string) => void;
@@ -68,9 +50,9 @@ type ProductsStore = {
getPointByUuid: (productUuid: string, modelUuid: string, pointUuid: string) => PointsScheme | undefined;
getActionByUuid: (productUuid: string, actionUuid: string) => (ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction) | undefined;
getActionByPointUuid: (productUuid: string, pointUuid: string) => (ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction) | undefined;
getModelUuidByPointUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
getModelUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
getPointUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
getModelUuidByPointUuid: (productUuid: string, actionUuid: string) => string | undefined;
getModelUuidByActionUuid: (productUuid: string, actionUuid: string) => string | undefined;
getPointUuidByActionUuid: (productUuid: string, actionUuid: string) => string | undefined;
getTriggerByUuid: (productUuid: string, triggerUuid: string) => TriggerSchema | undefined;
getTriggersByTriggeredPointUuid: (productUuid: string, triggeredPointUuid: string) => TriggerSchema[];
getTriggeringModels: (productUuid: string, actionUUid: string) => EventsSchema[];
@@ -81,16 +63,30 @@ export const createProductStore = () => {
return create<ProductsStore>()(
immer((set, get) => ({
products: [],
selectedProduct: { productUuid: "", productName: "" },
setSelectedProduct: (productUuid, productName) => {
set((state) => {
state.selectedProduct.productUuid = productUuid;
state.selectedProduct.productName = productName;
});
},
clearSelectedProduct: () => {
set((state) => {
state.selectedProduct.productUuid = "";
state.selectedProduct.productName = "";
});
},
// Product-level actions
addProduct: (productName, productUuid) => {
set((state) => {
const existingProduct = state.products.find(p => p.productUuid === productUuid);
const existingProduct = state.products.find((p) => p.productUuid === productUuid);
if (!existingProduct) {
const newProduct = {
productName,
productUuid: productUuid,
eventDatas: []
eventDatas: [],
};
state.products.push(newProduct);
}
@@ -106,18 +102,20 @@ export const createProductStore = () => {
clearProducts: () => {
set((state) => {
state.products = [];
state.selectedProduct.productUuid = "";
state.selectedProduct.productName = "";
});
},
removeProduct: (productUuid) => {
set((state) => {
state.products = state.products.filter(p => p.productUuid !== productUuid);
state.products = state.products.filter((p) => p.productUuid !== productUuid);
});
},
updateProduct: (productUuid, updates) => {
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
Object.assign(product, updates);
}
@@ -127,9 +125,9 @@ export const createProductStore = () => {
// Event-level actions
addEvent: (productUuid, event) => {
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
const existingEvent = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === event.modelUuid);
const existingEvent = product.eventDatas.find((e) => "modelUuid" in e && e.modelUuid === event.modelUuid);
if (!existingEvent) {
product.eventDatas.push(event);
}
@@ -139,9 +137,9 @@ export const createProductStore = () => {
removeEvent: (productUuid, modelUuid) => {
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
product.eventDatas = product.eventDatas.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid);
product.eventDatas = product.eventDatas.filter((e) => "modelUuid" in e && e.modelUuid !== modelUuid);
}
});
},
@@ -152,21 +150,21 @@ export const createProductStore = () => {
const actionsToDelete = new Set<string>();
for (const product of state.products) {
const eventIndex = product.eventDatas.findIndex(e => 'modelUuid' in e && e.modelUuid === modelUuid);
const eventIndex = product.eventDatas.findIndex((e) => "modelUuid" in e && e.modelUuid === modelUuid);
if (eventIndex !== -1) {
const event = product.eventDatas[eventIndex];
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action) {
actionsToDelete.add(point.action.actionUuid);
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action) {
if ("action" in point && point.action) {
actionsToDelete.add(point.action.actionUuid);
} else if ('actions' in point) {
} else if ("actions" in point) {
for (const action of point.actions) {
actionsToDelete.add(action.actionUuid);
}
@@ -181,43 +179,34 @@ export const createProductStore = () => {
for (const event of product.eventDatas) {
let eventModified = false;
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action?.triggers) {
const originalLength = point.action.triggers.length;
point.action.triggers = point.action.triggers.filter(trigger => {
return !(
(trigger.triggeredAsset?.triggeredModel?.modelUuid === modelUuid) ||
(actionsToDelete.has(trigger.triggeredAsset?.triggeredAction?.actionUuid || ''))
);
point.action.triggers = point.action.triggers.filter((trigger) => {
return !(trigger.triggeredAsset?.triggeredModel?.modelUuid === modelUuid || actionsToDelete.has(trigger.triggeredAsset?.triggeredAction?.actionUuid || ""));
});
if (point.action.triggers.length !== originalLength) {
eventModified = true;
}
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action?.triggers) {
if ("action" in point && point.action?.triggers) {
const originalLength = point.action.triggers.length;
point.action.triggers = point.action.triggers.filter((trigger: TriggerSchema) => {
return !(
(trigger.triggeredAsset?.triggeredModel?.modelUuid === modelUuid) ||
(actionsToDelete.has(trigger.triggeredAsset?.triggeredAction?.actionUuid || ''))
);
return !(trigger.triggeredAsset?.triggeredModel?.modelUuid === modelUuid || actionsToDelete.has(trigger.triggeredAsset?.triggeredAction?.actionUuid || ""));
});
if (point.action.triggers.length !== originalLength) {
eventModified = true;
}
} else if ('actions' in point) {
} else if ("actions" in point) {
for (const action of point.actions) {
if (action.triggers) {
const originalLength = action.triggers.length;
action.triggers = action.triggers.filter((trigger: TriggerSchema) => {
return !(
(trigger.triggeredAsset?.triggeredModel?.modelUuid === modelUuid) ||
(actionsToDelete.has(trigger.triggeredAsset?.triggeredAction?.actionUuid || ''))
);
return !(trigger.triggeredAsset?.triggeredModel?.modelUuid === modelUuid || actionsToDelete.has(trigger.triggeredAsset?.triggeredAction?.actionUuid || ""));
});
if (action.triggers.length !== originalLength) {
eventModified = true;
@@ -239,9 +228,9 @@ export const createProductStore = () => {
updateEvent: (productUuid, modelUuid, updates) => {
let updatedEvent: EventsSchema | undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
const event = product.eventDatas.find((e) => "modelUuid" in e && e.modelUuid === modelUuid);
if (event) {
Object.assign(event, updates);
updatedEvent = JSON.parse(JSON.stringify(event));
@@ -255,16 +244,16 @@ export const createProductStore = () => {
addPoint: (productUuid, modelUuid, point) => {
let updatedEvent: EventsSchema | undefined = undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
if (event && 'points' in event) {
const existingPoint = (event as ConveyorEventSchema).points.find(p => p.uuid === point.uuid);
const event = product.eventDatas.find((e) => "modelUuid" in e && e.modelUuid === modelUuid);
if (event && "points" in event) {
const existingPoint = (event as ConveyorEventSchema).points.find((p) => p.uuid === point.uuid);
if (!existingPoint) {
(event as ConveyorEventSchema).points.push(point as ConveyorPointSchema);
updatedEvent = JSON.parse(JSON.stringify(event));
}
} else if (event && 'point' in event) {
} else if (event && "point" in event) {
const existingPoint = (event as any).point?.uuid === point.uuid;
if (!existingPoint) {
(event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any;
@@ -279,13 +268,13 @@ export const createProductStore = () => {
removePoint: (productUuid, modelUuid, pointUuid) => {
let updatedEvent: EventsSchema | undefined = undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
if (event && 'points' in event) {
(event as ConveyorEventSchema).points = (event as ConveyorEventSchema).points.filter(p => p.uuid !== pointUuid);
const event = product.eventDatas.find((e) => "modelUuid" in e && e.modelUuid === modelUuid);
if (event && "points" in event) {
(event as ConveyorEventSchema).points = (event as ConveyorEventSchema).points.filter((p) => p.uuid !== pointUuid);
updatedEvent = JSON.parse(JSON.stringify(event));
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
} else if (event && "point" in event && (event as any).point.uuid === pointUuid) {
// For events with single point, we can't remove it, only reset to empty
}
}
@@ -296,16 +285,16 @@ export const createProductStore = () => {
updatePoint: (productUuid, modelUuid, pointUuid, updates) => {
let updatedEvent: EventsSchema | undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
if (event && 'points' in event) {
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
const event = product.eventDatas.find((e) => "modelUuid" in e && e.modelUuid === modelUuid);
if (event && "points" in event) {
const point = (event as ConveyorEventSchema).points.find((p) => p.uuid === pointUuid);
if (point) {
Object.assign(point, updates);
updatedEvent = JSON.parse(JSON.stringify(event));
}
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
} else if (event && "point" in event && (event as any).point.uuid === pointUuid) {
Object.assign((event as any).point, updates);
updatedEvent = JSON.parse(JSON.stringify(event));
}
@@ -318,22 +307,22 @@ export const createProductStore = () => {
addAction: (productUuid, modelUuid, pointUuid, action) => {
let updatedEvent: EventsSchema | undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
if (event && 'points' in event) {
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
const event = product.eventDatas.find((e) => "modelUuid" in e && e.modelUuid === modelUuid);
if (event && "points" in event) {
const point = (event as ConveyorEventSchema).points.find((p) => p.uuid === pointUuid);
if (point && (!point.action || point.action.actionUuid !== action.actionUuid)) {
point.action = action as any;
updatedEvent = JSON.parse(JSON.stringify(event));
}
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
if ('action' in (event as any).point) {
} else if (event && "point" in event && (event as any).point.uuid === pointUuid) {
if ("action" in (event as any).point) {
if (!(event as any).point.action || (event as any).point.action.actionUuid !== action.actionUuid) {
(event as any).point.action = action;
updatedEvent = JSON.parse(JSON.stringify(event));
}
} else if ('actions' in (event as any).point) {
} else if ("actions" in (event as any).point) {
const existingAction = (event as any).point.actions.find((a: any) => a.actionUuid === action.actionUuid);
if (!existingAction) {
(event as any).point.actions.push(action);
@@ -349,17 +338,17 @@ export const createProductStore = () => {
removeAction: (productUuid, actionUuid) => {
let updatedEvent: EventsSchema | undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
// Handle ConveyorEventSchema
for (const point of (event as ConveyorEventSchema).points) {
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if (event.type === "roboticArm") {
if ('actions' in point) {
if ("actions" in point) {
const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid);
if (index !== -1) {
point.actions.splice(index, 1);
@@ -368,7 +357,7 @@ export const createProductStore = () => {
}
}
} else if (event.type === "human") {
if ('actions' in point) {
if ("actions" in point) {
const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid);
if (index !== -1) {
point.actions.splice(index, 1);
@@ -377,7 +366,7 @@ export const createProductStore = () => {
}
}
} else if (event.type === "crane") {
if ('actions' in point) {
if ("actions" in point) {
const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid);
if (index !== -1) {
point.actions.splice(index, 1);
@@ -385,7 +374,7 @@ export const createProductStore = () => {
return;
}
}
} else if ('action' in point && point.action?.actionUuid === actionUuid) {
} else if ("action" in point && point.action?.actionUuid === actionUuid) {
point.action = undefined;
updatedEvent = JSON.parse(JSON.stringify(event));
return;
@@ -400,10 +389,10 @@ export const createProductStore = () => {
updateAction: (productUuid, actionUuid, updates) => {
let updatedEvent: EventsSchema | undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && point.action.actionUuid === actionUuid) {
Object.assign(point.action, updates);
@@ -411,13 +400,13 @@ export const createProductStore = () => {
return;
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action.actionUuid === actionUuid) {
if ("action" in point && point.action.actionUuid === actionUuid) {
Object.assign(point.action, updates);
updatedEvent = JSON.parse(JSON.stringify(event));
return;
} else if ('actions' in point) {
} else if ("actions" in point) {
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
if (action) {
Object.assign(action, updates);
@@ -436,13 +425,13 @@ export const createProductStore = () => {
addTrigger: (productUuid, actionUuid, trigger) => {
let updatedEvent: EventsSchema | undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && point.action.actionUuid === actionUuid) {
const existingTrigger = point.action.triggers.find(t => t.triggerUuid === trigger.triggerUuid);
const existingTrigger = point.action.triggers.find((t) => t.triggerUuid === trigger.triggerUuid);
if (!existingTrigger) {
point.action.triggers.push(trigger);
updatedEvent = JSON.parse(JSON.stringify(event));
@@ -450,16 +439,16 @@ export const createProductStore = () => {
return;
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action.actionUuid === actionUuid) {
if ("action" in point && point.action.actionUuid === actionUuid) {
const existingTrigger = point.action.triggers.find((t: any) => t.triggerUuid === trigger.triggerUuid);
if (!existingTrigger) {
point.action.triggers.push(trigger);
updatedEvent = JSON.parse(JSON.stringify(event));
}
return;
} else if ('actions' in point) {
} else if ("actions" in point) {
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
if (action) {
const existingTrigger = action.triggers.find((t: any) => t.triggerUuid === trigger.triggerUuid);
@@ -480,30 +469,30 @@ export const createProductStore = () => {
removeTrigger: (productUuid, triggerUuid) => {
let updatedEvent: EventsSchema | undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && 'triggers' in point.action) {
const Trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
if (point.action && "triggers" in point.action) {
const Trigger = point.action.triggers.find((t) => t.triggerUuid === triggerUuid);
if (Trigger) {
point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid);
point.action.triggers = point.action.triggers.filter((t) => t.triggerUuid !== triggerUuid);
updatedEvent = JSON.parse(JSON.stringify(event));
}
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && 'triggers' in point.action) {
if ("action" in point && "triggers" in point.action) {
const Trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
if (Trigger) {
point.action.triggers = point.action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
updatedEvent = JSON.parse(JSON.stringify(event));
}
} else if ('actions' in point) {
} else if ("actions" in point) {
for (const action of point.actions) {
if ('triggers' in action) {
if ("triggers" in action) {
const Trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
if (Trigger) {
action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
@@ -522,13 +511,13 @@ export const createProductStore = () => {
updateTrigger: (productUuid, triggerUuid, updates) => {
let updatedEvent: EventsSchema | undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && 'triggers' in point.action) {
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
if (point.action && "triggers" in point.action) {
const trigger = point.action.triggers.find((t) => t.triggerUuid === triggerUuid);
if (trigger) {
Object.assign(trigger, updates);
updatedEvent = JSON.parse(JSON.stringify(event));
@@ -536,18 +525,18 @@ export const createProductStore = () => {
}
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && 'triggers' in point.action) {
if ("action" in point && "triggers" in point.action) {
const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
if (trigger) {
Object.assign(trigger, updates);
updatedEvent = JSON.parse(JSON.stringify(event));
return;
}
} else if ('actions' in point) {
} else if ("actions" in point) {
for (const action of point.actions) {
if ('triggers' in action) {
if ("triggers" in action) {
const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
if (trigger) {
Object.assign(trigger, updates);
@@ -567,7 +556,7 @@ export const createProductStore = () => {
// Renaming functions
renameProduct: (productUuid, newName) => {
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
product.productName = newName;
}
@@ -577,10 +566,10 @@ export const createProductStore = () => {
renameAction: (productUuid, actionUuid, newName) => {
let updatedEvent: EventsSchema | undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && point.action.actionUuid === actionUuid) {
point.action.actionName = newName;
@@ -588,13 +577,13 @@ export const createProductStore = () => {
return;
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action.actionUuid === actionUuid) {
if ("action" in point && point.action.actionUuid === actionUuid) {
point.action.actionName = newName;
updatedEvent = JSON.parse(JSON.stringify(event));
return;
} else if ('actions' in point) {
} else if ("actions" in point) {
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
if (action) {
action.actionName = newName;
@@ -612,13 +601,13 @@ export const createProductStore = () => {
renameTrigger: (productUuid, triggerUuid, newName) => {
let updatedEvent: EventsSchema | undefined;
set((state) => {
const product = state.products.find(p => p.productUuid === productUuid);
const product = state.products.find((p) => p.productUuid === productUuid);
if (product) {
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action && 'triggers' in point.action) {
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
if (point.action && "triggers" in point.action) {
const trigger = point.action.triggers.find((t) => t.triggerUuid === triggerUuid);
if (trigger) {
trigger.triggerName = newName;
updatedEvent = JSON.parse(JSON.stringify(event));
@@ -626,18 +615,18 @@ export const createProductStore = () => {
}
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && 'triggers' in point.action) {
if ("action" in point && "triggers" in point.action) {
const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
if (trigger) {
trigger.triggerName = newName;
updatedEvent = JSON.parse(JSON.stringify(event));
return;
}
} else if ('actions' in point) {
} else if ("actions" in point) {
for (const action of point.actions) {
if ('triggers' in action) {
if ("triggers" in action) {
const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
if (trigger) {
trigger.triggerName = newName;
@@ -656,13 +645,13 @@ export const createProductStore = () => {
// Helper functions
getProductById: (productUuid) => {
return get().products.find(p => p.productUuid === productUuid);
return get().products.find((p) => p.productUuid === productUuid);
},
getEventByModelUuid: (productUuid, modelUuid) => {
const product = get().getProductById(productUuid);
if (!product) return undefined;
return product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
return product.eventDatas.find((e) => "modelUuid" in e && e.modelUuid === modelUuid);
},
getEventByActionUuid: (productUuid, actionUuid) => {
@@ -670,17 +659,17 @@ export const createProductStore = () => {
if (!product) return undefined;
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action?.actionUuid === actionUuid) {
return event;
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action?.actionUuid === actionUuid) {
if ("action" in point && point.action?.actionUuid === actionUuid) {
return event;
} else if ('actions' in point) {
} else if ("actions" in point) {
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
if (action) {
return event;
@@ -696,19 +685,19 @@ export const createProductStore = () => {
if (!product) return undefined;
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action?.triggers?.some(t => t.triggerUuid === triggerUuid)) {
if (point.action?.triggers?.some((t) => t.triggerUuid === triggerUuid)) {
return event;
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point) {
if ("action" in point) {
if (point.action?.triggers?.some((t: any) => t.triggerUuid === triggerUuid)) {
return event;
}
} else if ('actions' in point) {
} else if ("actions" in point) {
for (const action of point.actions) {
if (action.triggers?.some((t: any) => t.triggerUuid === triggerUuid)) {
return event;
@@ -725,11 +714,11 @@ export const createProductStore = () => {
if (!product) return undefined;
for (const event of product.eventDatas) {
if ('points' in event) {
if ((event as ConveyorEventSchema).points.some(p => p.uuid === pointUuid)) {
if ("points" in event) {
if ((event as ConveyorEventSchema).points.some((p) => p.uuid === pointUuid)) {
return event;
}
} else if ('point' in event) {
} else if ("point" in event) {
if ((event as any).point?.uuid === pointUuid) {
return event;
}
@@ -742,30 +731,30 @@ export const createProductStore = () => {
const event = get().getEventByModelUuid(productUuid, modelUuid);
if (!event) return undefined;
if ('points' in event) {
return (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
} else if ('point' in event && (event as any).point.uuid === pointUuid) {
if ("points" in event) {
return (event as ConveyorEventSchema).points.find((p) => p.uuid === pointUuid);
} else if ("point" in event && (event as any).point.uuid === pointUuid) {
return (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point;
}
return undefined;
},
getActionByUuid: (productUuid, actionUuid) => {
const product = get().products.find(p => p.productUuid === productUuid);
const product = get().products.find((p) => p.productUuid === productUuid);
if (!product) return undefined;
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action?.actionUuid === actionUuid) {
return point.action;
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action?.actionUuid === actionUuid) {
if ("action" in point && point.action?.actionUuid === actionUuid) {
return point.action;
} else if ('actions' in point) {
} else if ("actions" in point) {
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
if (action) return action;
}
@@ -775,17 +764,17 @@ export const createProductStore = () => {
},
getActionByPointUuid: (productUuid, pointUuid) => {
const product = get().products.find(p => p.productUuid === productUuid);
const product = get().products.find((p) => p.productUuid === productUuid);
if (!product) return undefined;
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.uuid === pointUuid) {
return point.action;
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if (point.uuid === pointUuid) {
return point.action;
@@ -796,17 +785,17 @@ export const createProductStore = () => {
},
getModelUuidByPointUuid: (productUuid, pointUuid) => {
const product = get().products.find(p => p.productUuid === productUuid);
const product = get().products.find((p) => p.productUuid === productUuid);
if (!product) return undefined;
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.uuid === pointUuid) {
return event.modelUuid;
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if (point.uuid === pointUuid) {
return event.modelUuid;
@@ -817,21 +806,21 @@ export const createProductStore = () => {
},
getModelUuidByActionUuid: (productUuid, actionUuid) => {
const product = get().products.find(p => p.productUuid === productUuid);
const product = get().products.find((p) => p.productUuid === productUuid);
if (!product) return undefined;
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action?.actionUuid === actionUuid) {
return event.modelUuid;
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action?.actionUuid === actionUuid) {
if ("action" in point && point.action?.actionUuid === actionUuid) {
return event.modelUuid;
} else if ('actions' in point) {
} else if ("actions" in point) {
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
if (action) return event.modelUuid;
}
@@ -841,21 +830,21 @@ export const createProductStore = () => {
},
getPointUuidByActionUuid: (productUuid, actionUuid) => {
const product = get().products.find(p => p.productUuid === productUuid);
const product = get().products.find((p) => p.productUuid === productUuid);
if (!product) return undefined;
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action?.actionUuid === actionUuid) {
return point.uuid;
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action?.actionUuid === actionUuid) {
if ("action" in point && point.action?.actionUuid === actionUuid) {
return point.uuid;
} else if ('actions' in point) {
} else if ("actions" in point) {
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
if (action) return point.uuid;
}
@@ -865,11 +854,11 @@ export const createProductStore = () => {
},
getTriggerByUuid: (productUuid, triggerUuid) => {
const product = get().products.find(p => p.productUuid === productUuid);
const product = get().products.find((p) => p.productUuid === productUuid);
if (!product) return undefined;
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
for (const trigger of point.action?.triggers || []) {
if (trigger.triggerUuid === triggerUuid) {
@@ -877,15 +866,15 @@ export const createProductStore = () => {
}
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point) {
if ("action" in point) {
for (const trigger of point.action?.triggers || []) {
if (trigger.triggerUuid === triggerUuid) {
return trigger;
}
}
} else if ('actions' in point) {
} else if ("actions" in point) {
for (const action of point.actions) {
for (const trigger of action.triggers || []) {
if (trigger.triggerUuid === triggerUuid) {
@@ -900,7 +889,7 @@ export const createProductStore = () => {
},
getTriggeringModels: (productUuid: string, actionUuid: string) => {
const product = get().products.find(p => p.productUuid === productUuid);
const product = get().products.find((p) => p.productUuid === productUuid);
if (!product) return [];
const triggeringModels: EventsSchema[] = [];
@@ -909,35 +898,32 @@ export const createProductStore = () => {
if (!targetModelUuid) return [];
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action?.triggers) {
for (const trigger of point.action.triggers) {
if (trigger.triggeredAsset?.triggeredModel?.modelUuid === targetModelUuid &&
trigger.triggeredAsset?.triggeredAction?.actionUuid === actionUuid) {
if (trigger.triggeredAsset?.triggeredModel?.modelUuid === targetModelUuid && trigger.triggeredAsset?.triggeredAction?.actionUuid === actionUuid) {
triggeringModels.push(event);
break;
}
}
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action?.triggers) {
if ("action" in point && point.action?.triggers) {
for (const trigger of point.action.triggers) {
if (trigger.triggeredAsset?.triggeredModel?.modelUuid === targetModelUuid &&
trigger.triggeredAsset?.triggeredAction?.actionUuid === actionUuid) {
if (trigger.triggeredAsset?.triggeredModel?.modelUuid === targetModelUuid && trigger.triggeredAsset?.triggeredAction?.actionUuid === actionUuid) {
triggeringModels.push(event);
break;
}
}
} else if ('actions' in point) {
} else if ("actions" in point) {
for (const action of point.actions) {
if (action.triggers) {
for (const trigger of action.triggers) {
if (trigger.triggeredAsset?.triggeredModel?.modelUuid === targetModelUuid &&
trigger.triggeredAsset?.triggeredAction?.actionUuid === actionUuid) {
if (trigger.triggeredAsset?.triggeredModel?.modelUuid === targetModelUuid && trigger.triggeredAsset?.triggeredAction?.actionUuid === actionUuid) {
triggeringModels.push(event);
break;
}
@@ -952,13 +938,13 @@ export const createProductStore = () => {
},
getTriggersByTriggeredPointUuid: (productUuid, triggeredPointUuid) => {
const product = get().products.find(p => p.productUuid === productUuid);
const product = get().products.find((p) => p.productUuid === productUuid);
if (!product) return [];
const triggers: TriggerSchema[] = [];
for (const event of product.eventDatas) {
if ('points' in event) {
if ("points" in event) {
for (const point of (event as ConveyorEventSchema).points) {
if (point.action?.triggers) {
for (const trigger of point.action.triggers) {
@@ -968,15 +954,15 @@ export const createProductStore = () => {
}
}
}
} else if ('point' in event) {
} else if ("point" in event) {
const point = (event as any).point;
if ('action' in point && point.action?.triggers) {
if ("action" in point && point.action?.triggers) {
for (const trigger of point.action.triggers) {
if (trigger.triggeredAsset?.triggeredPoint?.pointUuid === triggeredPointUuid) {
triggers.push(trigger);
}
}
} else if ('actions' in point) {
} else if ("actions" in point) {
for (const action of point.actions) {
if (action.triggers) {
for (const trigger of action.triggers) {
@@ -996,10 +982,10 @@ export const createProductStore = () => {
getIsEventInProduct: (productUuid, modelUuid) => {
const product = get().getProductById(productUuid);
if (!product) return false;
return product.eventDatas.some(e => 'modelUuid' in e && e.modelUuid === modelUuid);
}
return product.eventDatas.some((e) => "modelUuid" in e && e.modelUuid === modelUuid);
},
}))
)
}
);
};
export type ProductStoreType = ReturnType<typeof createProductStore>;

View File

@@ -90,34 +90,6 @@ export const useSelectedAsset = create<SelectedAssetState>()(
}))
);
interface SelectedProductState {
selectedProduct: { productUuid: string; productName: string };
setSelectedProduct: (productUuid: string, productName: string) => void;
clearSelectedProduct: () => void;
}
export const createSelectedProductStore = () => {
return create<SelectedProductState>()(
immer((set) => ({
selectedProduct: { productUuid: '', productName: '' },
setSelectedProduct: (productUuid, productName) => {
set((state) => {
state.selectedProduct.productUuid = productUuid;
state.selectedProduct.productName = productName;
});
},
clearSelectedProduct: () => {
set((state) => {
state.selectedProduct.productUuid = '';
state.selectedProduct.productName = '';
});
},
}))
)
}
export type SelectedProductType = ReturnType<typeof createSelectedProductStore>;
interface SelectedActionState {
selectedAction: { actionId: string | null; actionName: string | null };
setSelectedAction: (actionId: string, actionName: string) => void;