Refactor asset model handling and event data management

- Removed redundant data structure in handleModelLoad function.
- Introduced eventData object to encapsulate event-related information for different asset types (Conveyor, Vehicle, ArmBot, StaticMachine).
- Updated socket emission to include complete data with eventData.
- Enhanced copy-paste and duplication controls to maintain eventData integrity during object duplication.
- Integrated event data updates in move and rotate controls to reflect changes in the simulation state.
- Improved PointsCreator component to handle rotation for event groups.
- Updated handleAddEventToProduct function to support event data management.
- Enhanced product management to fetch existing products from the server and handle new product creation.
- Added new types for eventData in worldTypes and simulationTypes for better type safety.
- Refactored IndexedDB utility functions for cleaner code.
This commit is contained in:
Jerald-Golden-B 2025-04-29 19:15:17 +05:30
parent ea53af62c4
commit 882c81a385
22 changed files with 1379 additions and 1209 deletions

View File

@ -1,9 +1,8 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { import {
useSelectedAsset, useSelectedEventData,
useSelectedEventData, useSelectedEventSphere,
useSelectedEventSphere, useSelectedProduct,
useSelectedProduct,
} from "../../../../../store/simulation/useSimulationStore"; } from "../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../store/simulation/useProductStore"; import { useProductStore } from "../../../../../store/simulation/useProductStore";
import ConveyorMechanics from "./mechanics/conveyorMechanics"; import ConveyorMechanics from "./mechanics/conveyorMechanics";
@ -13,120 +12,117 @@ import MachineMechanics from "./mechanics/machineMechanics";
import StorageMechanics from "./mechanics/storageMechanics"; import StorageMechanics from "./mechanics/storageMechanics";
import { AddIcon } from "../../../../icons/ExportCommonIcons"; import { AddIcon } from "../../../../icons/ExportCommonIcons";
import { handleAddEventToProduct } from "../../../../../modules/simulation/events/points/functions/handleAddEventToProduct"; import { handleAddEventToProduct } from "../../../../../modules/simulation/events/points/functions/handleAddEventToProduct";
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
const EventProperties: React.FC = () => { const EventProperties: React.FC = () => {
const { selectedEventData } = useSelectedEventData(); const { selectedEventData } = useSelectedEventData();
const { getEventByModelUuid } = useProductStore(); const { getEventByModelUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct(); const { selectedProduct } = useSelectedProduct();
const [currentEventData, setCurrentEventData] = useState<EventsSchema | null>( const [currentEventData, setCurrentEventData] = useState<EventsSchema | null>(null);
null const [assetType, setAssetType] = useState<string | null>(null);
); const { products, addEvent } = useProductStore();
const [assetType, setAssetType] = useState<string | null>(null); const { selectedEventSphere } = useSelectedEventSphere();
const { products, addEvent } = useProductStore();
const { selectedEventSphere } = useSelectedEventSphere();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset(); useEffect(() => {
useEffect(() => { const event = getCurrentEventData();
const event = getCurrentEventData(); setCurrentEventData(event);
setCurrentEventData(event);
const type = determineAssetType(event); const type = determineAssetType(event);
setAssetType(type); setAssetType(type);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedEventData, selectedProduct]); }, [selectedEventData, selectedProduct]);
const getCurrentEventData = () => {
if (!selectedEventData?.data || !selectedProduct) return null;
return (
getEventByModelUuid(
selectedProduct.productId,
selectedEventData.data.modelUuid
) ?? null
);
};
const determineAssetType = (event: EventsSchema | null) => {
if (!event) return null;
switch (event.type) {
case "transfer":
return "conveyor";
case "vehicle":
return "vehicle";
case "roboticArm":
return "roboticArm";
case "machine":
return "machine";
case "storageUnit":
return "storageUnit";
default:
return null;
}
};
const getCurrentEventData = () => {
if (!selectedEventData?.data || !selectedProduct) return null;
return ( return (
getEventByModelUuid( <div className="event-proprties-wrapper">
selectedProduct.productId, {currentEventData && (
selectedEventData.data.modelUuid <>
) ?? null <div className="header">
<div className="header-value">
{selectedEventData?.data.modelName}
</div>
</div>
{assetType === "conveyor" && <ConveyorMechanics />}
{assetType === "vehicle" && <VehicleMechanics />}
{assetType === "roboticArm" && <RoboticArmMechanics />}
{assetType === "machine" && <MachineMechanics />}
{assetType === "storageUnit" && <StorageMechanics />}
</>
)}
{!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.
</p>
<div className="products-list">
<p>
<strong>Here are some products you can add it to:</strong>
</p>
<ul>
{products.map((product) => (
<li key={product.productId}>
<button
onClick={() => {
if (selectedEventData) {
handleAddEventToProduct({
event: useEventsStore.getState().getEventByModelUuid(selectedEventData?.data.modelUuid),
addEvent,
selectedProduct,
})
}
}}
>
<AddIcon />
{product.productName}
</button>
</li>
))}
</ul>
</div>
</div>
)
}
{!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.
</p>
</div>
)}
</div >
); );
};
const determineAssetType = (event: EventsSchema | null) => {
if (!event) return null;
switch (event.type) {
case "transfer":
return "conveyor";
case "vehicle":
return "vehicle";
case "roboticArm":
return "roboticArm";
case "machine":
return "machine";
case "storageUnit":
return "storageUnit";
default:
return null;
}
};
return (
<div className="event-proprties-wrapper">
{currentEventData && (
<>
<div className="header">
<div className="header-value">
{selectedEventData?.data.modelName}
</div>
</div>
{assetType === "conveyor" && <ConveyorMechanics />}
{assetType === "vehicle" && <VehicleMechanics />}
{assetType === "roboticArm" && <RoboticArmMechanics />}
{assetType === "machine" && <MachineMechanics />}
{assetType === "storageUnit" && <StorageMechanics />}
</>
)}
{!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.
</p>
<div className="products-list">
<p>
<strong>Here are some products you can add it to:</strong>
</p>
<ul>
{products.map((product) => (
<li key={product.productId}>
<button
onClick={() =>
handleAddEventToProduct({
selectedAsset,
addEvent,
selectedProduct: {
productId: product.productId,
productName: product.productName,
},
clearSelectedAsset,
})
}
>
<AddIcon />
{product.productName}
</button>
</li>
))}
</ul>
</div>
</div>
)}
{!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.
</p>
</div>
)}
</div>
);
}; };
export default EventProperties; export default EventProperties;

View File

@ -8,217 +8,193 @@ import SwapAction from "../actions/SwapAction";
import SpawnAction from "../actions/SpawnAction"; import SpawnAction from "../actions/SpawnAction";
import DefaultAction from "../actions/DefaultAction"; import DefaultAction from "../actions/DefaultAction";
import Trigger from "../trigger/Trigger"; import Trigger from "../trigger/Trigger";
import { import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
useSelectedEventData,
useSelectedProduct,
} from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import ActionsList from "../components/ActionsList"; import ActionsList from "../components/ActionsList";
function ConveyorMechanics() { function ConveyorMechanics() {
const [activeOption, setActiveOption] = useState< const [activeOption, setActiveOption] = useState<"default" | "spawn" | "swap" | "delay" | "despawn">("default");
"default" | "spawn" | "swap" | "delay" | "despawn" const [selectedPointData, setSelectedPointData] = useState<ConveyorPointSchema | undefined>();
>("default"); const { selectedEventData } = useSelectedEventData();
const [selectedPointData, setSelectedPointData] = useState< const { getPointByUuid, updateEvent, updateAction } = useProductStore();
ConveyorPointSchema | undefined const { selectedProduct } = useSelectedProduct();
>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, updateEvent, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
useEffect(() => { useEffect(() => {
if (selectedEventData) { if (selectedEventData) {
const point = getPointByUuid( const point = getPointByUuid(
selectedProduct.productId, selectedProduct.productId,
selectedEventData?.data.modelUuid, selectedEventData?.data.modelUuid,
selectedEventData?.selectedPoint selectedEventData?.selectedPoint
) as ConveyorPointSchema | undefined; ) as ConveyorPointSchema | undefined;
if (point && "action" in point) { if (point && "action" in point) {
setSelectedPointData(point); setSelectedPointData(point);
setActiveOption( setActiveOption(point.action.actionType as | "default" | "spawn" | "swap" | "delay" | "despawn");
point.action.actionType as }
| "default" }
| "spawn" }, [selectedProduct, selectedEventData, getPointByUuid]);
| "swap"
| "delay"
| "despawn"
);
}
}
}, [selectedProduct, selectedEventData, getPointByUuid]);
const handleSpeedChange = (value: string) => { const handleSpeedChange = (value: string) => {
if (!selectedEventData) return; if (!selectedEventData) return;
updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, {
speed: parseFloat(value), speed: parseFloat(value),
}); });
}; };
const handleActionTypeChange = (option: string) => { const handleActionTypeChange = (option: string) => {
if (!selectedEventData || !selectedPointData) return; if (!selectedEventData || !selectedPointData) return;
const validOption = option as const validOption = option as | "default" | "spawn" | "swap" | "delay" | "despawn";
| "default" setActiveOption(validOption);
| "spawn"
| "swap"
| "delay"
| "despawn";
setActiveOption(validOption);
updateAction(selectedPointData.action.actionUuid, { updateAction(selectedPointData.action.actionUuid, {
actionType: validOption, actionType: validOption,
}); });
}; };
const handleRenameAction = (newName: string) => { const handleRenameAction = (newName: string) => {
if (!selectedPointData) return; if (!selectedPointData) return;
updateAction(selectedPointData.action.actionUuid, { actionName: newName }); updateAction(selectedPointData.action.actionUuid, { actionName: newName });
}; };
const handleSpawnCountChange = (value: string) => { const handleSpawnCountChange = (value: string) => {
if (!selectedPointData) return; if (!selectedPointData) return;
updateAction(selectedPointData.action.actionUuid, { updateAction(selectedPointData.action.actionUuid, {
spawnCount: value === "inherit" ? "inherit" : parseFloat(value), spawnCount: value === "inherit" ? "inherit" : parseFloat(value),
}); });
}; };
const handleSpawnIntervalChange = (value: string) => { const handleSpawnIntervalChange = (value: string) => {
if (!selectedPointData) return; if (!selectedPointData) return;
updateAction(selectedPointData.action.actionUuid, { updateAction(selectedPointData.action.actionUuid, {
spawnInterval: value === "inherit" ? "inherit" : parseFloat(value), spawnInterval: value === "inherit" ? "inherit" : parseFloat(value),
}); });
}; };
const handleMaterialSelect = (material: string) => { const handleMaterialSelect = (material: string) => {
if (!selectedPointData) return; if (!selectedPointData) return;
updateAction(selectedPointData.action.actionUuid, { material }); updateAction(selectedPointData.action.actionUuid, { material });
}; };
const handleDelayChange = (value: string) => { const handleDelayChange = (value: string) => {
if (!selectedPointData) return; if (!selectedPointData) return;
updateAction(selectedPointData.action.actionUuid, { updateAction(selectedPointData.action.actionUuid, {
delay: value === "inherit" ? "inherit" : parseFloat(value), delay: value === "inherit" ? "inherit" : parseFloat(value),
}); });
}; };
const availableActions = { const availableActions = {
defaultOption: "default", defaultOption: "default",
options: ["default", "spawn", "swap", "delay", "despawn"], options: ["default", "spawn", "swap", "delay", "despawn"],
}; };
// Get current values from store // Get current values from store
const currentSpeed = const currentSpeed = selectedEventData?.data.type === "transfer"
selectedEventData?.data.type === "transfer" ? selectedEventData.data.speed.toString()
? selectedEventData.data.speed.toString() : "0.5";
: "0.5";
const currentActionName = selectedPointData const currentActionName = selectedPointData
? selectedPointData.action.actionName ? selectedPointData.action.actionName
: "Action Name"; : "Action Name";
const currentMaterial = selectedPointData const currentMaterial = selectedPointData
? selectedPointData.action.material ? selectedPointData.action.material
: "Default material"; : "Default material";
const currentSpawnCount = selectedPointData const currentSpawnCount = selectedPointData
? selectedPointData.action.spawnCount?.toString() || "1" ? selectedPointData.action.spawnCount?.toString() || "1"
: "1"; : "1";
const currentSpawnInterval = selectedPointData const currentSpawnInterval = selectedPointData
? selectedPointData.action.spawnInterval?.toString() || "1" ? selectedPointData.action.spawnInterval?.toString() || "1"
: "1"; : "1";
const currentDelay = selectedPointData const currentDelay = selectedPointData
? selectedPointData.action.delay?.toString() || "0" ? selectedPointData.action.delay?.toString() || "0"
: "0"; : "0";
return ( return (
<>
{selectedEventData && (
<> <>
<div key={selectedPointData?.uuid} className="global-props"> {selectedEventData && (
<div className="property-list-container"> <>
<div className="property-item"> <div key={selectedPointData?.uuid} className="global-props">
<InputWithDropDown <div className="property-list-container">
label="Speed" <div className="property-item">
value={currentSpeed} <InputWithDropDown
min={0} label="Speed"
step={0.1} value={currentSpeed}
defaultValue={"0.5"} min={0}
max={10} step={0.1}
activeOption="m/s" defaultValue={"0.5"}
onClick={() => {}} max={10}
onChange={handleSpeedChange} activeOption="m/s"
/> onClick={() => { }}
</div> onChange={handleSpeedChange}
</div> />
</div> </div>
</div>
</div>
<ActionsList <ActionsList
setSelectedPointData={setSelectedPointData} setSelectedPointData={setSelectedPointData}
selectedPointData={selectedPointData} selectedPointData={selectedPointData}
/> />
<div className="selected-actions-details"> <div className="selected-actions-details">
<div className="selected-actions-header"> <div className="selected-actions-header">
<RenameInput <RenameInput
value={currentActionName} value={currentActionName}
onRename={handleRenameAction} onRename={handleRenameAction}
/> />
</div> </div>
<div className="selected-actions-list"> <div className="selected-actions-list">
<LabledDropdown <LabledDropdown
defaultOption={ defaultOption={selectedPointData ? selectedPointData.action.actionType : "default"}
selectedPointData options={availableActions.options}
? selectedPointData.action.actionType onSelect={handleActionTypeChange}
: "default" />
} {activeOption === "default" && <DefaultAction />}
options={availableActions.options} {activeOption === "spawn" && (
onSelect={handleActionTypeChange} <SpawnAction
/> onChangeCount={handleSpawnCountChange}
{activeOption === "default" && <DefaultAction />} options={["Default material", "Material 1", "Material 2"]}
{activeOption === "spawn" && ( defaultOption={currentMaterial}
<SpawnAction onSelect={handleMaterialSelect}
onChangeCount={handleSpawnCountChange} onChangeInterval={handleSpawnIntervalChange}
options={["Default material", "Material 1", "Material 2"]} intervalValue={currentSpawnInterval}
defaultOption={currentMaterial} countValue={currentSpawnCount}
onSelect={handleMaterialSelect} intervalMin={1}
onChangeInterval={handleSpawnIntervalChange} intervalMax={60}
intervalValue={currentSpawnInterval} intervalDefaultValue="1"
countValue={currentSpawnCount} countMin={1}
intervalMin={1} countMax={100}
intervalMax={60} countDefaultValue="1"
intervalDefaultValue="1" />
countMin={1} )}
countMax={100} {activeOption === "swap" && (
countDefaultValue="1" <SwapAction
/> options={["Default material", "Material 1", "Material 2"]}
)} defaultOption={currentMaterial}
{activeOption === "swap" && ( onSelect={handleMaterialSelect}
<SwapAction />
options={["Default material", "Material 1", "Material 2"]} )}
defaultOption={currentMaterial} {activeOption === "despawn" && <DespawnAction />}
onSelect={handleMaterialSelect} {activeOption === "delay" && (
/> <DelayAction
)} value={currentDelay}
{activeOption === "despawn" && <DespawnAction />} defaultValue="0"
{activeOption === "delay" && ( min={0}
<DelayAction max={60}
value={currentDelay} onChange={handleDelayChange}
defaultValue="0" />
min={0} )}
max={60} </div>
onChange={handleDelayChange} </div>
/> <div className="tirgger">
)} <Trigger />
</div> </div>
</div> </>
<div className="tirgger"> )}
<Trigger />
</div>
</> </>
)} );
</>
);
} }
export default ConveyorMechanics; export default ConveyorMechanics;

View File

@ -2,128 +2,121 @@ import { useEffect, useState } from "react";
import RenameInput from "../../../../../ui/inputs/RenameInput"; import RenameInput from "../../../../../ui/inputs/RenameInput";
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
import Trigger from "../trigger/Trigger"; import Trigger from "../trigger/Trigger";
import { import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
useSelectedEventData,
useSelectedProduct,
} from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import ProcessAction from "../actions/ProcessAction"; import ProcessAction from "../actions/ProcessAction";
import ActionsList from "../components/ActionsList"; import ActionsList from "../components/ActionsList";
function MachineMechanics() { function MachineMechanics() {
const [activeOption, setActiveOption] = useState<"default" | "process">( const [activeOption, setActiveOption] = useState<"default" | "process">("default");
"default" const [selectedPointData, setSelectedPointData] = useState<MachinePointSchema | undefined>();
); const { selectedEventData } = useSelectedEventData();
const [selectedPointData, setSelectedPointData] = useState< const { getPointByUuid, updateAction } = useProductStore();
MachinePointSchema | undefined const { selectedProduct } = useSelectedProduct();
>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
useEffect(() => { useEffect(() => {
if (selectedEventData) { if (selectedEventData) {
const point = getPointByUuid( const point = getPointByUuid(
selectedProduct.productId, selectedProduct.productId,
selectedEventData?.data.modelUuid, selectedEventData?.data.modelUuid,
selectedEventData?.selectedPoint selectedEventData?.selectedPoint
) as MachinePointSchema | undefined; ) as MachinePointSchema | undefined;
if (point && "action" in point) { if (point && "action" in point) {
setSelectedPointData(point); setSelectedPointData(point);
setActiveOption(point.action.actionType as "process"); setActiveOption(point.action.actionType as "process");
} }
} }
}, [selectedProduct, selectedEventData, getPointByUuid]); }, [selectedProduct, selectedEventData, getPointByUuid]);
const handleActionTypeChange = (option: string) => { const handleActionTypeChange = (option: string) => {
if (!selectedEventData || !selectedPointData) return; if (!selectedEventData || !selectedPointData) return;
const validOption = option as "process"; const validOption = option as "process";
setActiveOption(validOption); setActiveOption(validOption);
updateAction(selectedPointData.action.actionUuid, { updateAction(selectedPointData.action.actionUuid, {
actionType: validOption, actionType: validOption,
}); });
}; };
const handleRenameAction = (newName: string) => { const handleRenameAction = (newName: string) => {
if (!selectedPointData) return; if (!selectedPointData) return;
updateAction(selectedPointData.action.actionUuid, { actionName: newName }); updateAction(selectedPointData.action.actionUuid, { actionName: newName });
}; };
const handleProcessTimeChange = (value: string) => { const handleProcessTimeChange = (value: string) => {
if (!selectedPointData) return; if (!selectedPointData) return;
updateAction(selectedPointData.action.actionUuid, { updateAction(selectedPointData.action.actionUuid, {
processTime: parseFloat(value), processTime: parseFloat(value),
}); });
}; };
const handleMaterialSelect = (material: string) => { const handleMaterialSelect = (material: string) => {
if (!selectedPointData) return; if (!selectedPointData) return;
updateAction(selectedPointData.action.actionUuid, { updateAction(selectedPointData.action.actionUuid, {
swapMaterial: material, swapMaterial: material,
}); });
}; };
// Get current values from store // Get current values from store
const currentActionName = selectedPointData const currentActionName = selectedPointData
? selectedPointData.action.actionName ? selectedPointData.action.actionName
: "Action Name"; : "Action Name";
const currentProcessTime = selectedPointData const currentProcessTime = selectedPointData
? selectedPointData.action.processTime.toString() ? selectedPointData.action.processTime.toString()
: "1"; : "1";
const currentMaterial = selectedPointData const currentMaterial = selectedPointData
? selectedPointData.action.swapMaterial ? selectedPointData.action.swapMaterial
: "Default material"; : "Default material";
const availableActions = { const availableActions = {
defaultOption: "process", defaultOption: "process",
options: ["process"], options: ["process"],
}; };
return ( return (
<>
{selectedEventData && (
<> <>
<div className="selected-actions-details"> {selectedEventData && (
<div className="selected-actions-header"> <>
<RenameInput <div className="selected-actions-details">
value={currentActionName} <div className="selected-actions-header">
onRename={handleRenameAction} <RenameInput
/> value={currentActionName}
</div> onRename={handleRenameAction}
<ActionsList />
setSelectedPointData={setSelectedPointData} </div>
selectedPointData={selectedPointData} <ActionsList
/> setSelectedPointData={setSelectedPointData}
<div className="selected-actions-list"> selectedPointData={selectedPointData}
<LabledDropdown />
defaultOption="process" <div className="selected-actions-list">
options={availableActions.options} <LabledDropdown
onSelect={handleActionTypeChange} defaultOption="process"
/> options={availableActions.options}
{activeOption === "process" && ( onSelect={handleActionTypeChange}
<ProcessAction />
value={currentProcessTime} {activeOption === "process" && (
min={0.1} <ProcessAction
max={60} value={currentProcessTime}
defaultValue="1" min={0.1}
onChange={handleProcessTimeChange} max={60}
swapOptions={["Default material", "Material 1", "Material 2"]} defaultValue="1"
swapDefaultOption={currentMaterial} onChange={handleProcessTimeChange}
onSwapSelect={handleMaterialSelect} swapOptions={["Default material", "Material 1", "Material 2"]}
/> swapDefaultOption={currentMaterial}
)} onSwapSelect={handleMaterialSelect}
</div> />
</div> )}
<div className="tirgger"> </div>
<Trigger /> </div>
</div> <div className="tirgger">
<Trigger />
</div>
</>
)}
</> </>
)} );
</>
);
} }
export default MachineMechanics; export default MachineMechanics;

View File

@ -3,192 +3,164 @@ import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
import RenameInput from "../../../../../ui/inputs/RenameInput"; import RenameInput from "../../../../../ui/inputs/RenameInput";
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
import Trigger from "../trigger/Trigger"; import Trigger from "../trigger/Trigger";
import { import { useSelectedEventData, useSelectedProduct, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
useSelectedEventData,
useSelectedProduct,
useSelectedAction,
} from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import PickAndPlaceAction from "../actions/PickAndPlaceAction"; import PickAndPlaceAction from "../actions/PickAndPlaceAction";
import ActionsList from "../components/ActionsList"; import ActionsList from "../components/ActionsList";
function RoboticArmMechanics() { function RoboticArmMechanics() {
const [activeOption, setActiveOption] = useState<"default" | "pickAndPlace">( const [activeOption, setActiveOption] = useState<"default" | "pickAndPlace">("default");
"default" const [selectedPointData, setSelectedPointData] = useState<RoboticArmPointSchema | undefined>();
); const { selectedEventData } = useSelectedEventData();
const [selectedPointData, setSelectedPointData] = useState< const { getPointByUuid, updateEvent, updateAction } = useProductStore();
RoboticArmPointSchema | undefined const { selectedProduct } = useSelectedProduct();
>(); const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, updateEvent, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedAction, setSelectedAction, clearSelectedAction } =
useSelectedAction();
useEffect(() => { useEffect(() => {
if (selectedEventData) { if (selectedEventData) {
const point = getPointByUuid( const point = getPointByUuid(
selectedProduct.productId, selectedProduct.productId,
selectedEventData.data.modelUuid, selectedEventData.data.modelUuid,
selectedEventData.selectedPoint selectedEventData.selectedPoint
) as RoboticArmPointSchema | undefined; ) as RoboticArmPointSchema | undefined;
if (point?.actions) { if (point?.actions) {
setSelectedPointData(point); setSelectedPointData(point);
setActiveOption( setActiveOption(point.actions[0].actionType as "default" | "pickAndPlace");
point.actions[0].actionType as "default" | "pickAndPlace" if (point.actions.length > 0 && !selectedAction.actionId) {
); setSelectedAction(
if (point.actions.length > 0 && !selectedAction.actionId) { point.actions[0].actionUuid,
setSelectedAction( point.actions[0].actionName
point.actions[0].actionUuid, );
point.actions[0].actionName }
); }
} else {
clearSelectedAction();
} }
} }, [clearSelectedAction, getPointByUuid, selectedAction.actionId, selectedEventData, selectedProduct, setSelectedAction,]);
} else {
clearSelectedAction();
}
}, [
clearSelectedAction,
getPointByUuid,
selectedAction.actionId,
selectedEventData,
selectedProduct,
setSelectedAction,
]);
const handleRenameAction = (newName: string) => { const handleRenameAction = (newName: string) => {
if (!selectedAction.actionId) return; if (!selectedAction.actionId) return;
updateAction(selectedAction.actionId, { actionName: newName }); updateAction(selectedAction.actionId, { actionName: newName });
if (selectedPointData) { if (selectedPointData) {
const updatedActions = selectedPointData.actions.map((action) => const updatedActions = selectedPointData.actions.map((action) =>
action.actionUuid === selectedAction.actionId action.actionUuid === selectedAction.actionId ? { ...action, actionName: newName } : action
? { ...action, actionName: newName } );
: action setSelectedPointData({
); ...selectedPointData,
setSelectedPointData({ actions: updatedActions,
...selectedPointData, });
actions: updatedActions, }
}); };
}
};
const handleSpeedChange = (value: string) => { const handleSpeedChange = (value: string) => {
if (!selectedEventData) return; if (!selectedEventData) return;
updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, { updateEvent(selectedProduct.productId, selectedEventData.data.modelUuid, {
speed: parseFloat(value), speed: parseFloat(value),
}); });
}; };
const handlePickPointChange = (value: string) => { const handlePickPointChange = (value: string) => {
if (!selectedAction.actionId || !selectedPointData) return; if (!selectedAction.actionId || !selectedPointData) return;
const [x, y, z] = value.split(",").map(Number); const [x, y, z] = value.split(",").map(Number);
updateAction(selectedAction.actionId, { updateAction(selectedAction.actionId, {
process: { process: {
startPoint: [x, y, z] as [number, number, number], startPoint: [x, y, z] as [number, number, number],
endPoint: endPoint: selectedPointData.actions.find((a) => a.actionUuid === selectedAction.actionId)?.process.endPoint || null,
selectedPointData.actions.find( },
(a) => a.actionUuid === selectedAction.actionId });
)?.process.endPoint || null, };
},
});
};
const handlePlacePointChange = (value: string) => { const handlePlacePointChange = (value: string) => {
if (!selectedAction.actionId || !selectedPointData) return; if (!selectedAction.actionId || !selectedPointData) return;
const [x, y, z] = value.split(",").map(Number); const [x, y, z] = value.split(",").map(Number);
updateAction(selectedAction.actionId, { updateAction(selectedAction.actionId, {
process: { process: {
startPoint: startPoint: selectedPointData.actions.find((a) => a.actionUuid === selectedAction.actionId)?.process.startPoint || null,
selectedPointData.actions.find( endPoint: [x, y, z] as [number, number, number],
(a) => a.actionUuid === selectedAction.actionId },
)?.process.startPoint || null, });
endPoint: [x, y, z] as [number, number, number], };
},
});
};
const availableActions = { const availableActions = {
defaultOption: "pickAndPlace", defaultOption: "pickAndPlace",
options: ["pickAndPlace"], options: ["pickAndPlace"],
}; };
const currentSpeed = const currentSpeed = selectedEventData?.data.type === "roboticArm"
selectedEventData?.data.type === "roboticArm" ? selectedEventData.data.speed.toString()
? selectedEventData.data.speed.toString() : "0.5";
: "0.5";
const currentAction = selectedPointData?.actions.find( const currentAction = selectedPointData?.actions.find((a) => a.actionUuid === selectedAction.actionId);
(a) => a.actionUuid === selectedAction.actionId
);
const currentPickPoint = currentAction?.process.startPoint
? `${currentAction.process.startPoint[0]},${currentAction.process.startPoint[1]},${currentAction.process.startPoint[2]}`
: "";
const currentPlacePoint = currentAction?.process.endPoint
? `${currentAction.process.endPoint[0]},${currentAction.process.endPoint[1]},${currentAction.process.endPoint[2]}`
: "";
return ( const currentPickPoint = currentAction?.process.startPoint
<> ? `${currentAction.process.startPoint[0]},${currentAction.process.startPoint[1]},${currentAction.process.startPoint[2]}`
{selectedEventData && selectedPointData && ( : "";
const currentPlacePoint = currentAction?.process.endPoint
? `${currentAction.process.endPoint[0]},${currentAction.process.endPoint[1]},${currentAction.process.endPoint[2]}`
: "";
return (
<> <>
<div className="global-props"> {selectedEventData && selectedPointData && (
<div className="property-list-container"> <>
<div className="property-item"> <div className="global-props">
<InputWithDropDown <div className="property-list-container">
label="Speed" <div className="property-item">
value={currentSpeed} <InputWithDropDown
min={0} label="Speed"
step={0.1} value={currentSpeed}
defaultValue={"0.5"} min={0}
max={10} step={0.1}
activeOption="m/s" defaultValue={"0.5"}
onClick={() => {}} max={10}
onChange={handleSpeedChange} activeOption="m/s"
/> onClick={() => { }}
</div> onChange={handleSpeedChange}
</div> />
</div> </div>
</div>
</div>
<ActionsList <ActionsList
setSelectedPointData={setSelectedPointData} setSelectedPointData={setSelectedPointData}
selectedPointData={selectedPointData} selectedPointData={selectedPointData}
multipleAction multipleAction
/> />
{selectedAction.actionId && currentAction && ( {selectedAction.actionId && currentAction && (
<div className="selected-actions-details"> <div className="selected-actions-details">
<div className="selected-actions-header"> <div className="selected-actions-header">
<RenameInput <RenameInput
value={selectedAction.actionName} value={selectedAction.actionName}
onRename={handleRenameAction} onRename={handleRenameAction}
/> />
</div> </div>
<div className="selected-actions-list"> <div className="selected-actions-list">
<LabledDropdown <LabledDropdown
defaultOption={activeOption} defaultOption={activeOption}
options={availableActions.options} options={availableActions.options}
onSelect={() => {}} onSelect={() => { }}
disabled={true} disabled={true}
/> />
<PickAndPlaceAction <PickAndPlaceAction
pickPointValue={currentPickPoint} pickPointValue={currentPickPoint}
pickPointOnChange={handlePickPointChange} pickPointOnChange={handlePickPointChange}
placePointValue={currentPlacePoint} placePointValue={currentPlacePoint}
placePointOnChange={handlePlacePointChange} placePointOnChange={handlePlacePointChange}
/> />
</div> </div>
<div className="tirgger"> <div className="tirgger">
<Trigger /> <Trigger />
</div> </div>
</div> </div>
)} )}
</>
)}
</> </>
)} );
</>
);
} }
export default RoboticArmMechanics; export default RoboticArmMechanics;

View File

@ -2,119 +2,112 @@ import { useEffect, useState } from "react";
import RenameInput from "../../../../../ui/inputs/RenameInput"; import RenameInput from "../../../../../ui/inputs/RenameInput";
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown"; import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
import Trigger from "../trigger/Trigger"; import Trigger from "../trigger/Trigger";
import { import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
useSelectedEventData,
useSelectedProduct,
} from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore"; import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import StorageAction from "../actions/StorageAction"; import StorageAction from "../actions/StorageAction";
import ActionsList from "../components/ActionsList"; import ActionsList from "../components/ActionsList";
function StorageMechanics() { function StorageMechanics() {
const [activeOption, setActiveOption] = useState< const [activeOption, setActiveOption] = useState<"default" | "store" | "spawn">("default");
"default" | "store" | "spawn" const [selectedPointData, setSelectedPointData] = useState<StoragePointSchema | undefined>();
>("default"); const { selectedEventData } = useSelectedEventData();
const [selectedPointData, setSelectedPointData] = useState< const { getPointByUuid, updateAction } = useProductStore();
StoragePointSchema | undefined const { selectedProduct } = useSelectedProduct();
>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
useEffect(() => { useEffect(() => {
if (selectedEventData) { if (selectedEventData) {
const point = getPointByUuid( const point = getPointByUuid(
selectedProduct.productId, selectedProduct.productId,
selectedEventData?.data.modelUuid, selectedEventData?.data.modelUuid,
selectedEventData?.selectedPoint selectedEventData?.selectedPoint
) as StoragePointSchema | undefined; ) as StoragePointSchema | undefined;
if (point && "action" in point) { if (point && "action" in point) {
setSelectedPointData(point); setSelectedPointData(point);
setActiveOption(point.action.actionType as "store" | "spawn"); setActiveOption(point.action.actionType as "store" | "spawn");
} }
} }
}, [selectedProduct, selectedEventData, getPointByUuid]); }, [selectedProduct, selectedEventData, getPointByUuid]);
const handleActionTypeChange = (option: string) => { const handleActionTypeChange = (option: string) => {
if (!selectedEventData || !selectedPointData) return; if (!selectedEventData || !selectedPointData) return;
const validOption = option as "store" | "spawn"; const validOption = option as "store" | "spawn";
setActiveOption(validOption); setActiveOption(validOption);
updateAction(selectedPointData.action.actionUuid, { updateAction(selectedPointData.action.actionUuid, {
actionType: validOption, actionType: validOption,
}); });
}; };
const handleRenameAction = (newName: string) => { const handleRenameAction = (newName: string) => {
if (!selectedPointData) return; if (!selectedPointData) return;
updateAction(selectedPointData.action.actionUuid, { actionName: newName }); updateAction(selectedPointData.action.actionUuid, { actionName: newName });
}; };
const handleCapacityChange = (value: string) => { const handleCapacityChange = (value: string) => {
if (!selectedPointData) return; if (!selectedPointData) return;
updateAction(selectedPointData.action.actionUuid, { updateAction(selectedPointData.action.actionUuid, {
storageCapacity: parseInt(value), storageCapacity: parseInt(value),
}); });
}; };
// Get current values from store // Get current values from store
const currentActionName = selectedPointData const currentActionName = selectedPointData
? selectedPointData.action.actionName ? selectedPointData.action.actionName
: "Action Name"; : "Action Name";
const currentCapacity = selectedPointData const currentCapacity = selectedPointData
? selectedPointData.action.storageCapacity.toString() ? selectedPointData.action.storageCapacity.toString()
: "0"; : "0";
const availableActions = { const availableActions = {
defaultOption: "store", defaultOption: "store",
options: ["store", "spawn"], options: ["store", "spawn"],
}; };
return ( return (
<>
{selectedEventData && (
<> <>
<ActionsList {selectedEventData && (
setSelectedPointData={setSelectedPointData} <>
selectedPointData={selectedPointData} <ActionsList
/> setSelectedPointData={setSelectedPointData}
<div className="selected-actions-details"> selectedPointData={selectedPointData}
<div className="selected-actions-header"> />
<RenameInput <div className="selected-actions-details">
value={currentActionName} <div className="selected-actions-header">
onRename={handleRenameAction} <RenameInput
/> value={currentActionName}
</div> onRename={handleRenameAction}
<div className="selected-actions-list"> />
<LabledDropdown </div>
defaultOption={activeOption} <div className="selected-actions-list">
options={availableActions.options} <LabledDropdown
onSelect={handleActionTypeChange} defaultOption={activeOption}
/> options={availableActions.options}
{activeOption === "store" && ( onSelect={handleActionTypeChange}
<StorageAction />
value={currentCapacity} {activeOption === "store" && (
defaultValue="0" <StorageAction
min={0} value={currentCapacity}
max={20} defaultValue="0"
onChange={handleCapacityChange} min={0}
/> max={20}
)} onChange={handleCapacityChange}
{activeOption === "spawn" && ( />
<div className="spawn-options"> )}
<p>Spawn configuration options would go here</p> {activeOption === "spawn" && (
</div> <div className="spawn-options">
)} <p>Spawn configuration options would go here</p>
</div> </div>
</div> )}
<div className="tirgger"> </div>
<Trigger /> </div>
</div> <div className="tirgger">
<Trigger />
</div>
</>
)}
</> </>
)} );
</>
);
} }
export default StorageMechanics; export default StorageMechanics;

View File

@ -1,216 +1,216 @@
import React, { useEffect, useRef } from "react"; import React, { useRef } from "react";
import { import {
AddIcon, AddIcon,
ArrowIcon, ArrowIcon,
RemoveIcon, RemoveIcon,
ResizeHeightIcon, ResizeHeightIcon,
} from "../../../icons/ExportCommonIcons"; } from "../../../icons/ExportCommonIcons";
import RenameInput from "../../../ui/inputs/RenameInput"; import RenameInput from "../../../ui/inputs/RenameInput";
import { handleResize } from "../../../../functions/handleResizePannel"; import { handleResize } from "../../../../functions/handleResizePannel";
import { import {
useSelectedAsset, useSelectedAsset,
useSelectedProduct, useSelectedProduct,
} from "../../../../store/simulation/useSimulationStore"; } from "../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../store/simulation/useProductStore"; import { useProductStore } from "../../../../store/simulation/useProductStore";
import { generateUUID } from "three/src/math/MathUtils"; import { generateUUID } from "three/src/math/MathUtils";
import RenderOverlay from "../../../templates/Overlay"; import RenderOverlay from "../../../templates/Overlay";
import EditWidgetOption from "../../../ui/menu/EditWidgetOption"; import EditWidgetOption from "../../../ui/menu/EditWidgetOption";
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
import { handleAddEventToProduct } from "../../../../modules/simulation/events/points/functions/handleAddEventToProduct"; import { handleAddEventToProduct } from "../../../../modules/simulation/events/points/functions/handleAddEventToProduct";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { deleteEventDataApi } from "../../../../services/simulation/deleteEventDataApi";
interface Event { interface Event {
pathName: string; pathName: string;
} }
interface ListProps { interface ListProps {
val: Event; val: Event;
} }
const List: React.FC<ListProps> = ({ val }) => { const List: React.FC<ListProps> = ({ val }) => {
return ( return (
<div className="process-container"> <div className="process-container">
<div className="value">{val.pathName}</div> <div className="value">{val.pathName}</div>
</div> </div>
); );
}; };
const Simulations: React.FC = () => { const Simulations: React.FC = () => {
const productsContainerRef = useRef<HTMLDivElement>(null); const productsContainerRef = useRef<HTMLDivElement>(null);
const { const { products, addProduct, removeProduct, renameProduct, addEvent, removeEvent, } = useProductStore();
products, const { selectedProduct, setSelectedProduct } = useSelectedProduct();
addProduct, const { getEventByModelUuid } = useEventsStore();
removeProduct, const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
renameProduct,
addEvent,
removeEvent,
} = useProductStore();
const { selectedProduct, setSelectedProduct } = useSelectedProduct();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const handleAddProduct = () => { const handleAddProduct = () => {
addProduct(`Product ${products.length + 1}`, generateUUID()); addProduct(`Product ${products.length + 1}`, generateUUID());
}; };
const handleRemoveProduct = (productId: string) => { const handleRemoveProduct = (productId: string) => {
const currentIndex = products.findIndex((p) => p.productId === productId); const currentIndex = products.findIndex((p) => p.productId === productId);
const isSelected = selectedProduct.productId === productId; const isSelected = selectedProduct.productId === productId;
const updatedProducts = products.filter((p) => p.productId !== productId); const updatedProducts = products.filter((p) => p.productId !== productId);
if (isSelected) { if (isSelected) {
if (updatedProducts.length > 0) { if (updatedProducts.length > 0) {
let newSelectedIndex = currentIndex; let newSelectedIndex = currentIndex;
if (currentIndex >= updatedProducts.length) { if (currentIndex >= updatedProducts.length) {
newSelectedIndex = updatedProducts.length - 1; newSelectedIndex = updatedProducts.length - 1;
}
setSelectedProduct(
updatedProducts[newSelectedIndex].productId,
updatedProducts[newSelectedIndex].productName
);
} else {
setSelectedProduct("", "");
}
} }
setSelectedProduct(
updatedProducts[newSelectedIndex].productId,
updatedProducts[newSelectedIndex].productName
);
} else {
setSelectedProduct("", "");
}
}
removeProduct(productId); removeProduct(productId);
}; };
const handleRenameProduct = (productId: string, newName: string) => { const handleRenameProduct = (productId: string, newName: string) => {
renameProduct(productId, newName); renameProduct(productId, newName);
if (selectedProduct.productId === productId) { if (selectedProduct.productId === productId) {
setSelectedProduct(productId, newName); setSelectedProduct(productId, newName);
} }
}; };
const handleRemoveEventFromProduct = () => { const handleRemoveEventFromProduct = () => {
if (selectedAsset) { if (selectedAsset) {
removeEvent(selectedProduct.productId, selectedAsset.modelUuid); const email = localStorage.getItem('email')
clearSelectedAsset(); const organization = (email!.split("@")[1]).split(".")[0];
} deleteEventDataApi({
}; productId: selectedProduct.productId,
modelUuid: selectedAsset.modelUuid,
organization: organization
});
removeEvent(selectedProduct.productId, selectedAsset.modelUuid);
clearSelectedAsset();
}
};
const selectedProductData = products.find( const selectedProductData = products.find(
(product) => product.productId === selectedProduct.productId (product) => product.productId === selectedProduct.productId
); );
const events: Event[] = const events: Event[] = selectedProductData?.eventDatas.map((event) => ({
selectedProductData?.eventDatas.map((event) => ({ pathName: event.modelName,
pathName: event.modelName,
})) || []; })) || [];
return ( return (
<div className="simulations-container"> <div className="simulations-container">
<div className="header">Simulations</div> <div className="header">Simulations</div>
<div className="add-product-container"> <div className="add-product-container">
<div className="actions"> <div className="actions">
<div className="header"> <div className="header">
<div className="header-value">Products</div> <div className="header-value">Products</div>
<div className="add-button" onClick={handleAddProduct}> <div className="add-button" onClick={handleAddProduct}>
<AddIcon /> Add <AddIcon /> Add
</div> </div>
</div> </div>
<div <div
className="lists-main-container" className="lists-main-container"
ref={productsContainerRef} ref={productsContainerRef}
style={{ height: "120px" }} style={{ height: "120px" }}
> >
<div className="list-container"> <div className="list-container">
{products.map((product, index) => ( {products.map((product, index) => (
<div <div
key={product.productId} key={product.productId}
className={`list-item ${ className={`list-item ${selectedProduct.productId === product.productId
selectedProduct.productId === product.productId ? "active"
? "active" : ""
: "" }`}
}`} >
> <div
<div className="value"
className="value" onClick={() =>
onClick={() => setSelectedProduct(product.productId, product.productName)
setSelectedProduct(product.productId, product.productName) }
} >
> <input
<input type="radio"
type="radio" name="products"
name="products" checked={selectedProduct.productId === product.productId}
checked={selectedProduct.productId === product.productId} readOnly
readOnly />
/> <RenameInput
<RenameInput value={product.productName}
value={product.productName} onRename={(newName) =>
onRename={(newName) => handleRenameProduct(product.productId, newName)
handleRenameProduct(product.productId, newName) }
} />
/> </div>
</div> {products.length > 1 && (
{products.length > 1 && ( <div
<div className="remove-button"
className="remove-button" onClick={() => handleRemoveProduct(product.productId)}
onClick={() => handleRemoveProduct(product.productId)} >
> <RemoveIcon />
<RemoveIcon /> </div>
)}
</div>
))}
</div>
<div
className="resize-icon"
id="action-resize"
onMouseDown={(e) => handleResize(e, productsContainerRef)}
>
<ResizeHeightIcon />
</div>
</div> </div>
)}
</div> </div>
))}
</div>
<div
className="resize-icon"
id="action-resize"
onMouseDown={(e) => handleResize(e, productsContainerRef)}
>
<ResizeHeightIcon />
</div>
</div>
</div>
<div className="simulation-process"> <div className="simulation-process">
<div className="collapse-header-container"> <div className="collapse-header-container">
<div className="header">Events</div> <div className="header">Events</div>
<div className="arrow-container"> <div className="arrow-container">
<ArrowIcon /> <ArrowIcon />
</div>
</div>
{events.map((event, index) => (
<List key={index} val={event} />
))}
</div>
<div className="compare-simulations-container">
<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.
</div>
<div className="input">
<input type="button" value={"Compare"} className="submit" />
</div>
</div>
</div> </div>
</div>
{events.map((event, index) => (
<List key={index} val={event} />
))}
</div>
<div className="compare-simulations-container"> {selectedAsset && (
<div className="compare-simulations-header"> <RenderOverlay>
Need to Compare Layout? <EditWidgetOption
</div> options={["Add to Product", "Remove from Product"]}
<div className="content"> onClick={(option) => {
Click <span>'Compare'</span> to review and analyze the layout if (option === "Add to Product") {
differences between them. handleAddEventToProduct({
</div> event: getEventByModelUuid(selectedAsset.modelUuid),
<div className="input"> addEvent,
<input type="button" value={"Compare"} className="submit" /> selectedProduct,
</div> clearSelectedAsset
});
} else {
handleRemoveEventFromProduct();
}
}}
/>
</RenderOverlay>
)}
</div> </div>
</div> );
{selectedAsset && (
<RenderOverlay>
<EditWidgetOption
options={["Add to Product", "Remove from Product"]}
onClick={(option) => {
if (option === "Add to Product") {
handleAddEventToProduct({
selectedAsset,
addEvent,
selectedProduct,
clearSelectedAsset,
});
} else {
handleRemoveEventFromProduct();
}
}}
/>
</RenderOverlay>
)}
</div>
);
}; };
export default Simulations; export default Simulations;

View File

@ -156,7 +156,7 @@ function processLoadedModel(
const model = gltf.clone(); const model = gltf.clone();
model.uuid = item.modeluuid; model.uuid = item.modeluuid;
model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap); model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid }; model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid, eventData: item.eventData };
model.position.set(...item.position); model.position.set(...item.position);
model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z); model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z);
@ -170,256 +170,141 @@ function processLoadedModel(
} }
}); });
itemsGroup?.current?.add(model); itemsGroup?.current?.add(model);
setFloorItems((prevItems) => [ if (item.eventData) {
...(prevItems || []), setFloorItems((prevItems) => [
{ ...(prevItems || []),
modeluuid: item.modeluuid, {
modelname: item.modelname, modeluuid: item.modeluuid,
position: item.position, modelname: item.modelname,
rotation: item.rotation, position: item.position,
modelfileID: item.modelfileID, rotation: item.rotation,
isLocked: item.isLocked, modelfileID: item.modelfileID,
isVisible: item.isVisible, isLocked: item.isLocked,
}, isVisible: item.isVisible,
]); eventData: item.eventData,
},
]);
if (item.modelfileID === "a1ee92554935007b10b3eb05") { if (item.eventData.type === "vehicle") {
const data = PointsCalculator( const vehicleEvent: VehicleEventSchema = {
'Vehicle', modelUuid: item.modeluuid,
gltf.clone(), modelName: item.modelname,
new THREE.Vector3(...model.rotation) position: item.position,
); rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
if (!data || !data.points) return; type: "vehicle",
speed: 1,
const vehicleEvent: VehicleEventSchema = { point: {
modelUuid: item.modeluuid, uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
modelName: item.modelname, position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
position: item.position, rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0],
rotation: [item.rotation.x, item.rotation.y, item.rotation.z], action: {
state: "idle",
type: "vehicle",
speed: 1,
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [data.points[0].x, data.points[0].y, data.points[0].z],
rotation: [0, 0, 0],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Vehicle Action",
actionType: "travel",
unLoadDuration: 5,
loadCapacity: 10,
pickUpPoint: null,
unLoadPoint: null,
triggers: []
}
}
};
addEvent(vehicleEvent);
} else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") {
const data = PointsCalculator(
'Conveyor',
gltf.clone(),
new THREE.Vector3(...model.rotation)
);
if (!data || !data.points) return;
const ConveyorEvent: ConveyorEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
position: item.position,
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "transfer",
speed: 1,
points: data.points.map((point: THREE.Vector3, index: number) => ({
uuid: THREE.MathUtils.generateUUID(),
position: [point.x, point.y, point.z],
rotation: [0, 0, 0],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: `Action ${index + 1}`,
actionType: 'default',
material: 'Default material',
delay: 0,
spawnInterval: 5,
spawnCount: 1,
triggers: []
}
}))
};
addEvent(ConveyorEvent);
} else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") {
// const data = PointsCalculator(
// 'Conveyor',
// gltf.clone(),
// new THREE.Vector3(...model.rotation)
// );
// if (!data || !data.points) return;
// const points: ConveyorPointSchema[] = data.points.map((point: THREE.Vector3, index: number) => {
// const actionUuid = THREE.MathUtils.generateUUID();
// return {
// uuid: THREE.MathUtils.generateUUID(),
// position: [point.x, point.y, point.z],
// rotation: [0, 0, 0],
// action: {
// actionUuid,
// actionName: `Action ${index}`,
// actionType: 'default',
// material: 'inherit',
// delay: 0,
// spawnInterval: 5,
// spawnCount: 1,
// triggers: []
// }
// };
// });
// points.forEach((point, index) => {
// if (index < points.length - 1) {
// const nextPoint = points[index + 1];
// point.action.triggers.push({
// triggerUuid: THREE.MathUtils.generateUUID(),
// triggerName: `Trigger 1`,
// triggerType: "onComplete",
// delay: 0,
// triggeredAsset: {
// triggeredModel: {
// modelName: item.modelname,
// modelUuid: item.modeluuid
// },
// triggeredPoint: {
// pointName: `Point ${index + 1}`,
// pointUuid: nextPoint.uuid
// },
// triggeredAction: {
// actionName: nextPoint.action.actionName,
// actionUuid: nextPoint.action.actionUuid
// }
// }
// });
// }
// });
// const ConveyorEvent: ConveyorEventSchema = {
// modelUuid: item.modeluuid,
// modelName: item.modelname,
// position: item.position,
// rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
// state: "idle",
// type: "transfer",
// speed: 1,
// points
// };
// addEvent(ConveyorEvent);
} else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") {
const data = PointsCalculator(
'Conveyor',
gltf.clone(),
new THREE.Vector3(...model.rotation)
);
if (!data || !data.points) return;
const ConveyorEvent: ConveyorEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
position: item.position,
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "transfer",
speed: 1,
points: data.points.map((point: THREE.Vector3, index: number) => ({
uuid: THREE.MathUtils.generateUUID(),
position: [point.x, point.y, point.z],
rotation: [0, 0, 0],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: `Action ${index}`,
actionType: 'default',
material: 'inherit',
delay: 0,
spawnInterval: 5,
spawnCount: 1,
triggers: []
}
}))
};
addEvent(ConveyorEvent);
} else if (item.modelfileID === "29dee78715ad5b853f5c346d") {
const data = PointsCalculator(
'StaticMachine',
gltf.clone(),
new THREE.Vector3(...model.rotation)
);
if (!data || !data.points) return;
const machineEvent: MachineEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
position: item.position,
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "machine",
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [data.points[0].x, data.points[0].y, data.points[0].z],
rotation: [0, 0, 0],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Process Action",
actionType: "process",
processTime: 10,
swapMaterial: "material-id",
triggers: []
}
}
};
addEvent(machineEvent);
} else if (item.modelfileID === "52e6681fbb743a890d96c914") {
const data = PointsCalculator(
'ArmBot',
gltf.clone(),
new THREE.Vector3(...model.rotation)
);
if (!data || !data.points) return;
const roboticArmEvent: RoboticArmEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
position: item.position,
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "roboticArm",
speed: 1,
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [data.points[0].x, data.points[0].y, data.points[0].z],
rotation: [0, 0, 0],
actions: [
{
actionUuid: THREE.MathUtils.generateUUID(), actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Pick and Place", actionName: "Vehicle Action",
actionType: "pickAndPlace", actionType: "travel",
process: { unLoadDuration: 5,
startPoint: [0, 0, 0], loadCapacity: 10,
endPoint: [0, 0, 0] pickUpPoint: null,
}, unLoadPoint: null,
triggers: [] triggers: []
} }
] }
} };
}; addEvent(vehicleEvent);
addEvent(roboticArmEvent); } else if (item.eventData.type === "Conveyor") {
const ConveyorEvent: ConveyorEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
position: item.position,
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "transfer",
speed: 1,
points: item.eventData.points?.map((point: any, index: number) => ({
uuid: point.uuid || THREE.MathUtils.generateUUID(),
position: [point.position[0], point.position[1], point.position[2]],
rotation: [point.rotation[0], point.rotation[1], point.rotation[2]],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: `Action ${index + 1}`,
actionType: 'default',
material: 'Default material',
delay: 0,
spawnInterval: 5,
spawnCount: 1,
triggers: []
}
})) || [],
};
addEvent(ConveyorEvent);
} else if (item.eventData.type === "StaticMachine") {
const machineEvent: MachineEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
position: item.position,
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "machine",
point: {
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Process Action",
actionType: "process",
processTime: 10,
swapMaterial: "material-id",
triggers: []
}
}
};
addEvent(machineEvent);
} else if (item.eventData.type === "ArmBot") {
const roboticArmEvent: RoboticArmEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
position: item.position,
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "roboticArm",
speed: 1,
point: {
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0],
actions: [
{
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Pick and Place",
actionType: "pickAndPlace",
process: {
startPoint: [0, 0, 0],
endPoint: [0, 0, 0]
},
triggers: []
}
]
}
};
addEvent(roboticArmEvent);
}
} else {
setFloorItems((prevItems) => [
...(prevItems || []),
{
modeluuid: item.modeluuid,
modelname: item.modelname,
position: item.position,
rotation: item.rotation,
modelfileID: item.modelfileID,
isLocked: item.isLocked,
isVisible: item.isVisible,
},
]);
} }
gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: 'power2.out' }); gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: 'power2.out' });

View File

@ -164,18 +164,6 @@ async function handleModelLoad(
// SOCKET // SOCKET
const data = {
organization,
modeluuid: newFloorItem.modeluuid,
modelname: newFloorItem.modelname,
modelfileID: newFloorItem.modelfileID,
position: newFloorItem.position,
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id
};
if (selectedItem.type) { if (selectedItem.type) {
const data = PointsCalculator( const data = PointsCalculator(
selectedItem.type, selectedItem.type,
@ -185,6 +173,10 @@ async function handleModelLoad(
if (!data || !data.points) return; if (!data || !data.points) return;
const eventData: any = {
type: selectedItem.type,
};
if (selectedItem.type === "Conveyor") { if (selectedItem.type === "Conveyor") {
const ConveyorEvent: ConveyorEventSchema = { const ConveyorEvent: ConveyorEventSchema = {
modelUuid: newFloorItem.modeluuid, modelUuid: newFloorItem.modeluuid,
@ -209,8 +201,14 @@ async function handleModelLoad(
triggers: [] triggers: []
} }
})) }))
} };
addEvent(ConveyorEvent); addEvent(ConveyorEvent);
eventData.points = ConveyorEvent.points.map(point => ({
uuid: point.uuid,
position: point.position,
rotation: point.rotation
}));
} else if (selectedItem.type === "Vehicle") { } else if (selectedItem.type === "Vehicle") {
const vehicleEvent: VehicleEventSchema = { const vehicleEvent: VehicleEventSchema = {
modelUuid: newFloorItem.modeluuid, modelUuid: newFloorItem.modeluuid,
@ -237,6 +235,12 @@ async function handleModelLoad(
} }
}; };
addEvent(vehicleEvent); addEvent(vehicleEvent);
eventData.point = {
uuid: vehicleEvent.point.uuid,
position: vehicleEvent.point.position,
rotation: vehicleEvent.point.rotation
};
} else if (selectedItem.type === "ArmBot") { } else if (selectedItem.type === "ArmBot") {
const roboticArmEvent: RoboticArmEventSchema = { const roboticArmEvent: RoboticArmEventSchema = {
modelUuid: newFloorItem.modeluuid, modelUuid: newFloorItem.modeluuid,
@ -265,6 +269,13 @@ async function handleModelLoad(
} }
}; };
addEvent(roboticArmEvent); addEvent(roboticArmEvent);
console.log('roboticArmEvent: ', roboticArmEvent);
eventData.point = {
uuid: roboticArmEvent.point.uuid,
position: roboticArmEvent.point.position,
rotation: roboticArmEvent.point.rotation
};
} else if (selectedItem.type === "StaticMachine") { } else if (selectedItem.type === "StaticMachine") {
const machineEvent: MachineEventSchema = { const machineEvent: MachineEventSchema = {
modelUuid: newFloorItem.modeluuid, modelUuid: newFloorItem.modeluuid,
@ -288,19 +299,65 @@ async function handleModelLoad(
} }
}; };
addEvent(machineEvent); addEvent(machineEvent);
eventData.point = {
uuid: machineEvent.point.uuid,
position: machineEvent.point.position,
rotation: machineEvent.point.rotation
};
} }
const completeData = {
organization,
modeluuid: newFloorItem.modeluuid,
modelname: newFloorItem.modelname,
modelfileID: newFloorItem.modelfileID,
position: newFloorItem.position,
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id,
eventData: eventData
};
model.userData.eventData = eventData;
newFloorItem.eventData = eventData;
setFloorItems((prevItems) => {
const updatedItems = [...(prevItems || []), newFloorItem];
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
return updatedItems;
});
socket.emit("v2:model-asset:add", completeData);
gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } });
} else {
const data = {
organization,
modeluuid: newFloorItem.modeluuid,
modelname: newFloorItem.modelname,
modelfileID: newFloorItem.modelfileID,
position: newFloorItem.position,
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
isLocked: false,
isVisible: true,
socketId: socket.id
};
setFloorItems((prevItems) => {
const updatedItems = [...(prevItems || []), newFloorItem];
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
return updatedItems;
});
socket.emit("v2:model-asset:add", data);
gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } });
} }
setFloorItems((prevItems) => {
const updatedItems = [...(prevItems || []), newFloorItem];
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
return updatedItems;
});
socket.emit("v2:model-asset:add", data);
gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } });
} }
export default addAssetModel; export default addAssetModel;

View File

@ -65,6 +65,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
}; };
getFloorAssets(organization).then((data) => { getFloorAssets(organization).then((data) => {
console.log('data: ', data);
if (data.length > 0) { if (data.length > 0) {
const uniqueItems = (data as Types.FloorItems).filter((item, index, self) => index === self.findIndex((t) => t.modelfileID === item.modelfileID)); const uniqueItems = (data as Types.FloorItems).filter((item, index, self) => index === self.findIndex((t) => t.modelfileID === item.modelfileID));
totalAssets = uniqueItems.length; totalAssets = uniqueItems.length;

View File

@ -137,6 +137,38 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
if (itemsGroupRef.current) { if (itemsGroupRef.current) {
let updatedEventData = null;
if (obj.userData.eventData) {
updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData));
updatedEventData.modelUuid = THREE.MathUtils.generateUUID();
if (updatedEventData.type === "Conveyor" && updatedEventData.points) {
updatedEventData.points = updatedEventData.points.map((point: any) => ({
...point,
uuid: THREE.MathUtils.generateUUID()
}));
}
else if (updatedEventData.type === "Vehicle" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
else if (updatedEventData.type === "ArmBot" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
else if (updatedEventData.type === "StaticMachine" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
}
const newFloorItem: Types.FloorItemType = { const newFloorItem: Types.FloorItemType = {
modeluuid: obj.uuid, modeluuid: obj.uuid,
modelname: obj.userData.name, modelname: obj.userData.name,
@ -144,7 +176,8 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
position: [worldPosition.x, worldPosition.y, worldPosition.z], position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
isLocked: false, isLocked: false,
isVisible: true isVisible: true,
eventData: updatedEventData
}; };
setFloorItems((prevItems: Types.FloorItems) => { setFloorItems((prevItems: Types.FloorItems) => {
@ -181,11 +214,18 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
isLocked: false, isLocked: false,
isVisible: true, isVisible: true,
socketId: socket.id, socketId: socket.id,
eventData: updatedEventData
}; };
socket.emit("v2:model-asset:add", data); socket.emit("v2:model-asset:add", data);
obj.userData.modeluuid = newFloorItem.modeluuid; obj.userData = {
name: newFloorItem.modelname,
modelId: newFloorItem.modelfileID,
modeluuid: newFloorItem.modeluuid,
eventData: updatedEventData
};
itemsGroupRef.current.add(obj); itemsGroupRef.current.add(obj);
} }
}); });
@ -205,7 +245,7 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
setSelectedAssets([]); setSelectedAssets([]);
} }
return null; // No visible output, but the component handles copy-paste functionality return null;
}; };
export default CopyPasteControls; export default CopyPasteControls;

View File

@ -115,6 +115,38 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
if (itemsGroupRef.current) { if (itemsGroupRef.current) {
let updatedEventData = null;
if (obj.userData.eventData) {
updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData));
updatedEventData.modelUuid = THREE.MathUtils.generateUUID();
if (updatedEventData.type === "Conveyor" && updatedEventData.points) {
updatedEventData.points = updatedEventData.points.map((point: any) => ({
...point,
uuid: THREE.MathUtils.generateUUID()
}));
}
else if (updatedEventData.type === "Vehicle" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
else if (updatedEventData.type === "ArmBot" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
else if (updatedEventData.type === "StaticMachine" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
}
const newFloorItem: Types.FloorItemType = { const newFloorItem: Types.FloorItemType = {
modeluuid: obj.uuid, modeluuid: obj.uuid,
modelname: obj.userData.name, modelname: obj.userData.name,
@ -122,7 +154,8 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
position: [worldPosition.x, worldPosition.y, worldPosition.z], position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, }, rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
isLocked: false, isLocked: false,
isVisible: true isVisible: true,
eventData: updatedEventData
}; };
setFloorItems((prevItems: Types.FloorItems) => { setFloorItems((prevItems: Types.FloorItems) => {
@ -159,11 +192,18 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
isLocked: false, isLocked: false,
isVisible: true, isVisible: true,
socketId: socket.id, socketId: socket.id,
eventData: updatedEventData
}; };
socket.emit("v2:model-asset:add", data); socket.emit("v2:model-asset:add", data);
obj.userData.modeluuid = newFloorItem.modeluuid; obj.userData = {
name: newFloorItem.modelname,
modelId: newFloorItem.modelfileID,
modeluuid: newFloorItem.modeluuid,
eventData: updatedEventData
};
itemsGroupRef.current.add(obj); itemsGroupRef.current.add(obj);
} }
}); });
@ -183,7 +223,7 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
setSelectedAssets([]); setSelectedAssets([]);
} }
return null; // This component does not render any UI return null;
}; };
export default DuplicationControls; export default DuplicationControls;

View File

@ -1,11 +1,14 @@
import * as THREE from "three"; import * as THREE from "three";
import { useEffect, useMemo, useRef, useState } from "react"; import { useEffect, useMemo, useRef } from "react";
import { useFrame, useThree } from "@react-three/fiber"; import { useFrame, useThree } from "@react-three/fiber";
import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; // import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import * as Types from "../../../../types/world/worldTypes"; import * as Types from "../../../../types/world/worldTypes";
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys"; import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) { function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {
const { camera, controls, gl, scene, pointer, raycaster } = useThree(); const { camera, controls, gl, scene, pointer, raycaster } = useThree();
@ -176,6 +179,24 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
isVisible: true isVisible: true
}; };
if (obj.userData.eventData) {
const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modeluuid);
const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid);
if (eventData) {
useEventsStore.getState().updateEvent(obj.userData.modeluuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
}
if (productData) {
useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
}
}
setFloorItems((prevItems: Types.FloorItems) => { setFloorItems((prevItems: Types.FloorItems) => {
const updatedItems = [...(prevItems || []), newFloorItem]; const updatedItems = [...(prevItems || []), newFloorItem];
localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
@ -234,7 +255,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
setSelectedAssets([]); setSelectedAssets([]);
} }
return null; // No need to return anything, as this component is used for its side effects return null;
} }
export default MoveControls export default MoveControls

View File

@ -1,11 +1,13 @@
import * as THREE from "three"; import * as THREE from "three";
import { useEffect, useMemo, useRef, useState } from "react"; import { useEffect, useMemo, useRef } from "react";
import { useFrame, useThree } from "@react-three/fiber"; import { useFrame, useThree } from "@react-three/fiber";
import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store"; import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi'; // import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import * as Types from "../../../../types/world/worldTypes"; import * as Types from "../../../../types/world/worldTypes";
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi"; import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) { function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {
const { camera, controls, gl, scene, pointer, raycaster } = useThree(); const { camera, controls, gl, scene, pointer, raycaster } = useThree();
@ -177,6 +179,24 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
isVisible: true isVisible: true
}; };
if (obj.userData.eventData) {
const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modeluuid);
const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid);
if (eventData) {
useEventsStore.getState().updateEvent(obj.userData.modeluuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
}
if (productData) {
useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
}
}
setFloorItems((prevItems: Types.FloorItems) => { setFloorItems((prevItems: Types.FloorItems) => {
const updatedItems = [...(prevItems || []), newFloorItem]; const updatedItems = [...(prevItems || []), newFloorItem];
localStorage.setItem("FloorItems", JSON.stringify(updatedItems)); localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
@ -235,7 +255,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
setSelectedAssets([]); setSelectedAssets([]);
} }
return null; // No need to return anything, as this component is used for its side effects return null;
} }
export default RotateControls export default RotateControls

View File

@ -62,7 +62,7 @@ function PointsCreator() {
{events.map((event, i) => { {events.map((event, i) => {
if (event.type === 'transfer') { if (event.type === 'transfer') {
return ( return (
<group key={i} position={new THREE.Vector3(...event.position)}> <group key={i} position={[...event.position]} rotation={[...event.rotation]} >
{event.points.map((point, j) => ( {event.points.map((point, j) => (
<mesh <mesh
name='Event-Sphere' name='Event-Sphere'
@ -78,6 +78,7 @@ function PointsCreator() {
}} }}
key={`${i}-${j}`} key={`${i}-${j}`}
position={new THREE.Vector3(...point.position)} position={new THREE.Vector3(...point.position)}
// rotation={new THREE.Euler(...point.rotation)}
userData={{ modelUuid: event.modelUuid, pointUuid: point.uuid }} userData={{ modelUuid: event.modelUuid, pointUuid: point.uuid }}
> >
<sphereGeometry args={[0.1, 16, 16]} /> <sphereGeometry args={[0.1, 16, 16]} />
@ -88,7 +89,7 @@ function PointsCreator() {
); );
} else if (event.type === 'vehicle') { } else if (event.type === 'vehicle') {
return ( return (
<group key={i} position={new THREE.Vector3(...event.position)}> <group key={i} position={[...event.position]} rotation={[...event.rotation]} >
<mesh <mesh
name='Event-Sphere' name='Event-Sphere'
uuid={event.point.uuid} uuid={event.point.uuid}
@ -102,6 +103,7 @@ function PointsCreator() {
setTransformMode(null); setTransformMode(null);
}} }}
position={new THREE.Vector3(...event.point.position)} position={new THREE.Vector3(...event.point.position)}
// rotation={new THREE.Euler(...event.point.rotation)}
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }} userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
> >
<sphereGeometry args={[0.1, 16, 16]} /> <sphereGeometry args={[0.1, 16, 16]} />
@ -111,7 +113,7 @@ function PointsCreator() {
); );
} else if (event.type === 'roboticArm') { } else if (event.type === 'roboticArm') {
return ( return (
<group key={i} position={new THREE.Vector3(...event.position)}> <group key={i} position={[...event.position]} rotation={[...event.rotation]} >
<mesh <mesh
name='Event-Sphere' name='Event-Sphere'
uuid={event.point.uuid} uuid={event.point.uuid}
@ -125,6 +127,7 @@ function PointsCreator() {
setTransformMode(null); setTransformMode(null);
}} }}
position={new THREE.Vector3(...event.point.position)} position={new THREE.Vector3(...event.point.position)}
// rotation={new THREE.Euler(...event.point.rotation)}
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }} userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
> >
<sphereGeometry args={[0.1, 16, 16]} /> <sphereGeometry args={[0.1, 16, 16]} />
@ -134,7 +137,7 @@ function PointsCreator() {
); );
} else if (event.type === 'machine') { } else if (event.type === 'machine') {
return ( return (
<group key={i} position={new THREE.Vector3(...event.position)}> <group key={i} position={[...event.position]} rotation={[...event.rotation]} >
<mesh <mesh
name='Event-Sphere' name='Event-Sphere'
uuid={event.point.uuid} uuid={event.point.uuid}
@ -148,6 +151,7 @@ function PointsCreator() {
setTransformMode(null); setTransformMode(null);
}} }}
position={new THREE.Vector3(...event.point.position)} position={new THREE.Vector3(...event.point.position)}
// rotation={new THREE.Euler(...event.point.rotation)}
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }} userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
> >
<sphereGeometry args={[0.1, 16, 16]} /> <sphereGeometry args={[0.1, 16, 16]} />

View File

@ -1,28 +1,38 @@
import { upsertProductOrEventApi } from "../../../../../services/simulation/UpsertProductOrEventApi";
interface HandleAddEventToProductParams { interface HandleAddEventToProductParams {
selectedAsset: any; // Replace `any` with specific type if you have it event: EventsSchema | undefined;
addEvent: (productId: string, asset: any) => void; addEvent: (productId: string, event: EventsSchema) => void;
selectedProduct: { selectedProduct: {
productId: string; productId: string;
productName: string; productName: string;
// Add other fields if needed }
}; clearSelectedAsset?: () => void;
clearSelectedAsset: () => void;
} }
export const handleAddEventToProduct = ({ export const handleAddEventToProduct = ({
selectedAsset, event,
addEvent, addEvent,
selectedProduct, selectedProduct,
clearSelectedAsset, clearSelectedAsset
}: HandleAddEventToProductParams) => { }: HandleAddEventToProductParams) => {
console.log('selectedProduct: ', selectedProduct); if (event && selectedProduct.productId) {
if (selectedAsset) { addEvent(selectedProduct.productId, event);
addEvent(selectedProduct.productId, selectedAsset);
// upsertProductOrEventApi({ const email = localStorage.getItem('email')
// productName: selectedProduct.productName, const organization = (email!.split("@")[1]).split(".")[0];
// productId: selectedProduct.productId,
// eventDatas: selectedAsset upsertProductOrEventApi({
// }); productName: selectedProduct.productName,
clearSelectedAsset(); productId: selectedProduct.productId,
organization: organization,
eventDatas: event
}).then((data) => {
// console.log(data);
})
if (clearSelectedAsset) {
clearSelectedAsset();
}
} }
}; };

View File

@ -7,28 +7,27 @@ import { upsertProductOrEventApi } from '../../../services/simulation/UpsertProd
import { getAllProductsApi } from '../../../services/simulation/getallProductsApi'; import { getAllProductsApi } from '../../../services/simulation/getallProductsApi';
function Products() { function Products() {
const { products, addProduct } = useProductStore(); const { products, addProduct, setProducts } = useProductStore();
const { setSelectedProduct } = useSelectedProduct(); const { setSelectedProduct } = useSelectedProduct();
useEffect(() => { useEffect(() => {
if (products.length === 0) { const email = localStorage.getItem('email')
const id = THREE.MathUtils.generateUUID(); const organization = (email!.split("@")[1]).split(".")[0];
const name = 'Product 1'; getAllProductsApi(organization).then((data) => {
addProduct(name, id); if (data.length === 0) {
// upsertProductOrEventApi({ productName: name, productId: id }).then((data) => { const id = THREE.MathUtils.generateUUID();
// console.log('data: ', data); const name = 'Product 1';
// }); addProduct(name, id);
setSelectedProduct(id, name); upsertProductOrEventApi({ productName: name, productId: id, organization: organization })
} setSelectedProduct(id, name);
}, [products]) } else {
setProducts(data);
setSelectedProduct(data[0].productId, data[0].productName);
}
})
}, [])
useEffect(() => { useEffect(() => {
// const email = localStorage.getItem('email')
// const organization = (email!.split("@")[1]).split(".")[0];
// console.log(organization);
// getAllProductsApi(organization).then((data) => {
// console.log('data: ', data);
// })
}, []) }, [])
return ( return (

View File

@ -19,11 +19,11 @@ function Simulation() {
const { products } = useProductStore(); const { products } = useProductStore();
useEffect(() => { useEffect(() => {
// console.log('events: ', events); console.log('events: ', events);
}, [events]) }, [events])
useEffect(() => { useEffect(() => {
// console.log('products: ', products); console.log('products: ', products);
}, [products]) }, [products])
return ( return (

View File

@ -1,19 +1,85 @@
import { useEffect } from "react"; import { useEffect, useRef, useState } from "react";
import { useThree } from "@react-three/fiber"; import { useThree } from "@react-three/fiber";
import * as THREE from "three";
import { useSubModuleStore } from "../../../../store/useModuleStore"; import { useSubModuleStore } from "../../../../store/useModuleStore";
import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore"; import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../store/simulation/useProductStore"; import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore"; import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
import { handleAddEventToProduct } from "../../events/points/functions/handleAddEventToProduct";
interface ConnectionLine {
id: string;
start: THREE.Vector3;
end: THREE.Vector3;
mid: THREE.Vector3;
trigger: TriggerSchema;
}
function TriggerConnector() { function TriggerConnector() {
const { gl, raycaster, scene } = useThree(); const { gl, raycaster, scene } = useThree();
const { subModule } = useSubModuleStore(); const { subModule } = useSubModuleStore();
const { getPointByUuid, getIsEventInProduct } = useProductStore(); const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, addEvent, getEventByModelUuid } = useProductStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset(); const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const { selectedProduct } = useSelectedProduct(); const { selectedProduct } = useSelectedProduct();
useEffect(() => { const [firstSelectedPoint, setFirstSelectedPoint] = useState<{
productId: string;
modelUuid: string;
pointUuid: string;
actionUuid?: string;
} | null>(null);
const [connections, setConnections] = useState<ConnectionLine[]>([]);
useEffect(() => {
const newConnections: ConnectionLine[] = [];
products.forEach(product => {
product.eventDatas.forEach(event => {
if ('points' in event) {
event.points.forEach(point => {
if ('action' in point && point.action?.triggers) {
point.action.triggers.forEach(trigger => {
if (trigger.triggeredAsset) {
const targetPoint = getPointByUuid(
product.productId,
trigger.triggeredAsset.triggeredModel.modelUuid,
trigger.triggeredAsset.triggeredPoint.pointUuid
);
if (targetPoint) {
const startPos = new THREE.Vector3(...point.position);
const endPos = new THREE.Vector3(...targetPoint.position);
const midPos = new THREE.Vector3()
.addVectors(startPos, endPos)
.multiplyScalar(0.5)
.add(new THREE.Vector3(0, 2, 0));
newConnections.push({
id: `${point.uuid}-${targetPoint.uuid}-${trigger.triggerUuid}`,
start: startPos,
end: endPos,
mid: midPos,
trigger
});
}
}
});
}
});
}
});
});
setConnections(newConnections);
}, [products]);
useEffect(() => {
console.log('connections: ', connections);
}, connections)
useEffect(() => {
const canvasElement = gl.domElement; const canvasElement = gl.domElement;
let drag = false; let drag = false;
@ -44,37 +110,114 @@ function TriggerConnector() {
const handleRightClick = (evt: MouseEvent) => { const handleRightClick = (evt: MouseEvent) => {
if (drag) return; if (drag) return;
evt.preventDefault(); evt.preventDefault();
const canvasElement = gl.domElement;
if (!canvasElement) return;
let intersects = raycaster.intersectObjects(scene.children, true); const intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) { if (intersects.length === 0) return;
let currentObject = intersects[0].object;
if (currentObject && currentObject.name === 'Event-Sphere') { const currentObject = intersects[0].object;
if (!currentObject || currentObject.name !== 'Event-Sphere') return;
const isInProduct = getIsEventInProduct( const modelUuid = currentObject.userData.modelUuid;
selectedProduct.productId, const pointUuid = currentObject.userData.pointUuid;
currentObject.userData.modelUuid
);
// You left Here if (selectedProduct && getIsEventInProduct(selectedProduct.productId, modelUuid)) {
if (isInProduct) { const point = getPointByUuid(
selectedProduct.productId,
modelUuid,
pointUuid
);
const event = getPointByUuid( if (!point) return;
selectedProduct.productId,
currentObject.userData.modelUuid,
currentObject.userData.pointUuid
);
console.log('event: ', event);
} else {
} let actionUuid: string | undefined;
if ('action' in point && point.action) {
actionUuid = point.action.actionUuid;
} else if ('actions' in point && point.actions.length === 1) {
actionUuid = point.actions[0].actionUuid;
} }
} else { if (!firstSelectedPoint) {
setFirstSelectedPoint({
productId: selectedProduct.productId,
modelUuid,
pointUuid,
actionUuid
});
} else {
const trigger: TriggerSchema = {
triggerUuid: THREE.MathUtils.generateUUID(),
triggerName: `Trigger ${firstSelectedPoint.pointUuid.slice(0, 4)}${pointUuid.slice(0, 4)}`,
triggerType: "onComplete",
delay: 0,
triggeredAsset: {
triggeredModel: {
modelName: currentObject.parent?.parent?.name || 'Unknown',
modelUuid: modelUuid
},
triggeredPoint: {
pointName: currentObject.name,
pointUuid: pointUuid
},
triggeredAction: actionUuid ? {
actionName: getActionByUuid(selectedProduct.productId, actionUuid)?.actionName || 'Action',
actionUuid: actionUuid
} : null
}
};
if (firstSelectedPoint.actionUuid) {
addTrigger(firstSelectedPoint.actionUuid, trigger);
}
setFirstSelectedPoint(null);
}
} else if (!getIsEventInProduct(selectedProduct.productId, modelUuid) && firstSelectedPoint) {
handleAddEventToProduct({
event: useEventsStore.getState().getEventByModelUuid(modelUuid),
addEvent,
selectedProduct,
})
const point = getPointByUuid(
selectedProduct.productId,
modelUuid,
pointUuid
);
if (!point) return;
let actionUuid: string | undefined;
if ('action' in point && point.action) {
actionUuid = point.action.actionUuid;
} else if ('actions' in point && point.actions.length === 1) {
actionUuid = point.actions[0].actionUuid;
}
const trigger: TriggerSchema = {
triggerUuid: THREE.MathUtils.generateUUID(),
triggerName: `Trigger ${firstSelectedPoint.pointUuid.slice(0, 4)}${pointUuid.slice(0, 4)}`,
triggerType: "onComplete",
delay: 0,
triggeredAsset: {
triggeredModel: {
modelName: currentObject.parent?.parent?.name || 'Unknown',
modelUuid: modelUuid
},
triggeredPoint: {
pointName: currentObject.name,
pointUuid: pointUuid
},
triggeredAction: actionUuid ? {
actionName: getActionByUuid(selectedProduct.productId, actionUuid)?.actionName || 'Action',
actionUuid: actionUuid
} : null
}
};
if (firstSelectedPoint.actionUuid) {
addTrigger(firstSelectedPoint.actionUuid, trigger);
}
setFirstSelectedPoint(null);
} }
}; };
@ -92,12 +235,12 @@ function TriggerConnector() {
canvasElement.removeEventListener('contextmenu', handleRightClick); canvasElement.removeEventListener('contextmenu', handleRightClick);
}; };
}, [gl, subModule]); }, [gl, subModule, selectedProduct, firstSelectedPoint]);
return ( return (
<> <>
</> </>
) );
} }
export default TriggerConnector export default TriggerConnector;

View File

@ -6,6 +6,7 @@ type ProductsStore = {
// Product-level actions // Product-level actions
addProduct: (productName: string, productId: string) => void; addProduct: (productName: string, productId: string) => void;
setProducts: (products: productsSchema) => void;
removeProduct: (productId: string) => void; removeProduct: (productId: string) => void;
updateProduct: (productId: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void; updateProduct: (productId: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void;
@ -78,6 +79,12 @@ export const useProductStore = create<ProductsStore>()(
}); });
}, },
setProducts: (products) => {
set((state) => {
state.products = products;
});
},
removeProduct: (productId) => { removeProduct: (productId) => {
set((state) => { set((state) => {
state.products = state.products.filter(p => p.productId !== productId); state.products = state.products.filter(p => p.productId !== productId);

View File

@ -14,7 +14,7 @@ interface TriggerSchema {
triggeredAsset: { triggeredAsset: {
triggeredModel: { modelName: string, modelUuid: string }; triggeredModel: { modelName: string, modelUuid: string };
triggeredPoint: { pointName: string, pointUuid: string }; triggeredPoint: { pointName: string, pointUuid: string };
triggeredAction: { actionName: string, actionUuid: string }; triggeredAction: { actionName: string, actionUuid: string } | null;
} | null; } | null;
} }

View File

@ -196,6 +196,19 @@ export type FloorItemType = {
modelfileID: string; modelfileID: string;
isLocked: boolean; isLocked: boolean;
isVisible: boolean; isVisible: boolean;
eventData?: {
type: string;
point?: {
uuid: string;
position: [number, number, number];
rotation: [number, number, number];
}
points?: {
uuid: string;
position: [number, number, number];
rotation: [number, number, number];
}[];
}
}; };
// Array of floor items for managing multiple objects on the floor // Array of floor items for managing multiple objects on the floor

View File

@ -3,43 +3,43 @@ const STORE_NAME = 'models';
const DB_VERSION = 1; const DB_VERSION = 1;
export function initializeDB(): Promise<IDBDatabase> { export function initializeDB(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const request = indexedDB.open(DB_NAME, DB_VERSION); const request = indexedDB.open(DB_NAME, DB_VERSION);
request.onupgradeneeded = () => { request.onupgradeneeded = () => {
const db = request.result; const db = request.result;
if (!db.objectStoreNames.contains(STORE_NAME)) { if (!db.objectStoreNames.contains(STORE_NAME)) {
db.createObjectStore(STORE_NAME); db.createObjectStore(STORE_NAME);
} }
}; };
request.onsuccess = () => resolve(request.result); request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error); request.onerror = () => reject(request.error);
}); });
} }
export async function storeGLTF(key: string, file: Blob): Promise<void> { export async function storeGLTF(key: string, file: Blob): Promise<void> {
const db = await initializeDB(); const db = await initializeDB();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const transaction = db.transaction(STORE_NAME, 'readwrite'); const transaction = db.transaction(STORE_NAME, 'readwrite');
const store = transaction.objectStore(STORE_NAME); const store = transaction.objectStore(STORE_NAME);
const request = store.put(file, key); const request = store.put(file, key);
request.onsuccess = () => resolve(); request.onsuccess = () => resolve();
request.onerror = () => reject(request.error); request.onerror = () => reject(request.error);
}); });
} }
export async function retrieveGLTF(key: string): Promise<Blob | undefined> { export async function retrieveGLTF(key: string): Promise<Blob | undefined> {
const db = await initializeDB(); const db = await initializeDB();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const transaction = db.transaction(STORE_NAME, 'readonly'); const transaction = db.transaction(STORE_NAME, 'readonly');
const store = transaction.objectStore(STORE_NAME); const store = transaction.objectStore(STORE_NAME);
const request = store.get(key); const request = store.get(key);
request.onsuccess = () => resolve(request.result as Blob | undefined); request.onsuccess = () => resolve(request.result as Blob | undefined);
request.onerror = () => reject(request.error); request.onerror = () => reject(request.error);
}); });
} }