Merge remote-tracking branch 'origin/v2' into simulation-armbot-v2
This commit is contained in:
commit
af891fae83
app/src
components
layout
sidebarLeft
sidebarRight
SideBarRight.tsx
properties/eventProperties
EventProperties.tsx
actions
DefaultAction.tsxDespawnAction.tsxPickAndPlaceAction.tsxProcessAction.tsxSpawnAction.tsxStorageAction.tsxSwapAction.tsxTravelAction.tsx
functions
mechanics
conveyorMechanics.tsxmachineMechanics.tsxroboticArmMechanics.tsxstorageMechanics.tsxvehicleMechanics.tsx
trigger
simulation
visualization/design
ui
modules
builder
scene/postProcessing
simulation
visualization
services/visulization/zone
store
simulation
useModuleStore.tsstyles
types
|
@ -73,7 +73,7 @@ const Assets: React.FC = () => {
|
||||||
try {
|
try {
|
||||||
const filt = await fetchAssets();
|
const filt = await fetchAssets();
|
||||||
setFiltereredAssets(filt);
|
setFiltereredAssets(filt);
|
||||||
} catch { }
|
} catch {}
|
||||||
};
|
};
|
||||||
filteredAssets();
|
filteredAssets();
|
||||||
}, [categoryAssets]);
|
}, [categoryAssets]);
|
||||||
|
@ -135,7 +135,7 @@ const Assets: React.FC = () => {
|
||||||
const res = await getCategoryAsset(asset);
|
const res = await getCategoryAsset(asset);
|
||||||
setCategoryAssets(res);
|
setCategoryAssets(res);
|
||||||
setFiltereredAssets(res);
|
setFiltereredAssets(res);
|
||||||
} catch (error) { }
|
} catch (error) {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
@ -151,7 +151,12 @@ const Assets: React.FC = () => {
|
||||||
<div className="assets-container">
|
<div className="assets-container">
|
||||||
{categoryAssets &&
|
{categoryAssets &&
|
||||||
categoryAssets?.map((asset: any, index: number) => (
|
categoryAssets?.map((asset: any, index: number) => (
|
||||||
<div key={index} className="assets" id={asset.filename}>
|
<div
|
||||||
|
key={index}
|
||||||
|
className="assets"
|
||||||
|
id={asset.filename}
|
||||||
|
title={asset.filename}
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
src={asset?.thumbnail}
|
src={asset?.thumbnail}
|
||||||
alt={asset.filename}
|
alt={asset.filename}
|
||||||
|
@ -187,7 +192,12 @@ const Assets: React.FC = () => {
|
||||||
<div className="assets-container">
|
<div className="assets-container">
|
||||||
{categoryAssets &&
|
{categoryAssets &&
|
||||||
categoryAssets?.map((asset: any, index: number) => (
|
categoryAssets?.map((asset: any, index: number) => (
|
||||||
<div key={index} className="assets" id={asset.filename}>
|
<div
|
||||||
|
key={index}
|
||||||
|
className="assets"
|
||||||
|
id={asset.filename}
|
||||||
|
title={asset.filename}
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
src={asset?.thumbnail}
|
src={asset?.thumbnail}
|
||||||
alt={asset.filename}
|
alt={asset.filename}
|
||||||
|
@ -196,8 +206,9 @@ const Assets: React.FC = () => {
|
||||||
setSelectedItem({
|
setSelectedItem({
|
||||||
name: asset.filename,
|
name: asset.filename,
|
||||||
id: asset.AssetID,
|
id: asset.AssetID,
|
||||||
type: asset.type === "undefined" ? undefined : asset.type
|
type:
|
||||||
})
|
asset.type === "undefined" ? undefined : asset.type,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ import Header from "./Header";
|
||||||
import useToggleStore from "../../../store/useUIToggleStore";
|
import useToggleStore from "../../../store/useUIToggleStore";
|
||||||
import Assets from "./Assets";
|
import Assets from "./Assets";
|
||||||
import useModuleStore from "../../../store/useModuleStore";
|
import useModuleStore from "../../../store/useModuleStore";
|
||||||
import Widgets from ".//visualization/widgets/Widgets";
|
import Widgets from "./visualization/widgets/Widgets";
|
||||||
import Templates from "../../../modules//visualization/template/Templates";
|
import Templates from "../../../modules/visualization/template/Templates";
|
||||||
import Search from "../../ui/inputs/Search";
|
import Search from "../../ui/inputs/Search";
|
||||||
|
|
||||||
const SideBarLeft: React.FC = () => {
|
const SideBarLeft: React.FC = () => {
|
||||||
|
|
|
@ -5,11 +5,11 @@ import {
|
||||||
GlobeIcon,
|
GlobeIcon,
|
||||||
WalletIcon,
|
WalletIcon,
|
||||||
} from "../../../../icons/3dChartIcons";
|
} from "../../../../icons/3dChartIcons";
|
||||||
import SimpleCard from "../../../../../modules//visualization/widgets/floating/cards/SimpleCard";
|
import SimpleCard from "../../../../../modules/visualization/widgets/floating/cards/SimpleCard";
|
||||||
|
|
||||||
import WarehouseThroughput from "../../../../../modules//visualization/widgets/floating/cards/WarehouseThroughput";
|
import WarehouseThroughput from "../../../../../modules/visualization/widgets/floating/cards/WarehouseThroughput";
|
||||||
import ProductivityDashboard from "../../../../../modules//visualization/widgets/floating/cards/ProductivityDashboard";
|
import ProductivityDashboard from "../../../../../modules/visualization/widgets/floating/cards/ProductivityDashboard";
|
||||||
import FleetEfficiency from "../../../../../modules//visualization/widgets/floating/cards/FleetEfficiency";
|
import FleetEfficiency from "../../../../../modules/visualization/widgets/floating/cards/FleetEfficiency";
|
||||||
|
|
||||||
interface Widget {
|
interface Widget {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -1,138 +1,148 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect } from "react";
|
||||||
import Header from "./Header";
|
import Header from "./Header";
|
||||||
import useModuleStore, {
|
import useModuleStore, {
|
||||||
useSubModuleStore,
|
useSubModuleStore,
|
||||||
} from "../../../store/useModuleStore";
|
} from "../../../store/useModuleStore";
|
||||||
import {
|
import {
|
||||||
AnalysisIcon,
|
AnalysisIcon,
|
||||||
MechanicsIcon,
|
MechanicsIcon,
|
||||||
PropertiesIcon,
|
PropertiesIcon,
|
||||||
SimulationIcon,
|
SimulationIcon,
|
||||||
} from "../../icons/SimulationIcons";
|
} from "../../icons/SimulationIcons";
|
||||||
import useToggleStore from "../../../store/useUIToggleStore";
|
import useToggleStore from "../../../store/useUIToggleStore";
|
||||||
import Visualization from "./visualization/Visualization";
|
import Visualization from "./visualization/Visualization";
|
||||||
import Analysis from "./analysis/Analysis";
|
import Analysis from "./analysis/Analysis";
|
||||||
import Simulations from "./simulation/Simulations";
|
import Simulations from "./simulation/Simulations";
|
||||||
import {
|
import { useSelectedFloorItem } from "../../../store/store";
|
||||||
useSelectedFloorItem,
|
import { useSelectedEventData, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
|
||||||
} from "../../../store/store";
|
|
||||||
import GlobalProperties from "./properties/GlobalProperties";
|
import GlobalProperties from "./properties/GlobalProperties";
|
||||||
import AsstePropertiies from "./properties/AssetProperties";
|
import AsstePropertiies from "./properties/AssetProperties";
|
||||||
import ZoneProperties from "./properties/ZoneProperties";
|
import ZoneProperties from "./properties/ZoneProperties";
|
||||||
|
import EventProperties from "./properties/eventProperties/EventProperties";
|
||||||
|
|
||||||
const SideBarRight: React.FC = () => {
|
const SideBarRight: React.FC = () => {
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const { toggleUI } = useToggleStore();
|
const { toggleUI } = useToggleStore();
|
||||||
const { subModule, setSubModule } = useSubModuleStore();
|
const { subModule, setSubModule } = useSubModuleStore();
|
||||||
const { selectedFloorItem } = useSelectedFloorItem();
|
const { selectedFloorItem } = useSelectedFloorItem();
|
||||||
// Reset activeList whenever activeModule changes
|
const { selectedEventData } = useSelectedEventData();
|
||||||
useEffect(() => {
|
const { selectedEventSphere } = useSelectedEventSphere();
|
||||||
if (activeModule !== "simulation") setSubModule("properties");
|
|
||||||
if (activeModule === "simulation") setSubModule("mechanics");
|
|
||||||
}, [activeModule]);
|
|
||||||
|
|
||||||
return (
|
// Reset activeList whenever activeModule changes
|
||||||
<div className="sidebar-right-wrapper">
|
useEffect(() => {
|
||||||
<Header />
|
if (activeModule !== "simulation") setSubModule("properties");
|
||||||
{toggleUI && (
|
if (activeModule === "simulation") setSubModule("simulations");
|
||||||
<div className="sidebar-actions-container">
|
}, [activeModule]);
|
||||||
{/* {activeModule === "builder" && ( */}
|
|
||||||
<div
|
useEffect(() => {
|
||||||
className={`sidebar-action-list ${subModule === "properties" ? "active" : ""
|
if (activeModule !== "mechanics" && selectedEventData && selectedEventSphere) {
|
||||||
}`}
|
setSubModule("mechanics");
|
||||||
onClick={() => setSubModule("properties")}
|
} else {
|
||||||
>
|
if (activeModule === 'simulation') {
|
||||||
<PropertiesIcon isActive={subModule === "properties"} />
|
setSubModule("simulations");
|
||||||
</div>
|
}
|
||||||
{/* )} */}
|
};
|
||||||
{activeModule === "simulation" && (
|
}, [activeModule, selectedEventData, selectedEventSphere])
|
||||||
<>
|
|
||||||
<div
|
return (
|
||||||
className={`sidebar-action-list ${subModule === "mechanics" ? "active" : ""
|
<div className="sidebar-right-wrapper">
|
||||||
}`}
|
<Header />
|
||||||
onClick={() => setSubModule("mechanics")}
|
{toggleUI && (
|
||||||
>
|
<div className="sidebar-actions-container">
|
||||||
<MechanicsIcon isActive={subModule === "mechanics"} />
|
<div
|
||||||
</div>
|
className={`sidebar-action-list ${subModule === "properties" ? "active" : ""
|
||||||
<div
|
}`}
|
||||||
className={`sidebar-action-list ${subModule === "simulations" ? "active" : ""
|
onClick={() => setSubModule("properties")}
|
||||||
}`}
|
>
|
||||||
onClick={() => setSubModule("simulations")}
|
<PropertiesIcon isActive={subModule === "properties"} />
|
||||||
>
|
</div>
|
||||||
<SimulationIcon isActive={subModule === "simulations"} />
|
{activeModule === "simulation" && (
|
||||||
</div>
|
<>
|
||||||
<div
|
<div
|
||||||
className={`sidebar-action-list ${subModule === "analysis" ? "active" : ""
|
className={`sidebar-action-list ${subModule === "mechanics" ? "active" : ""
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setSubModule("analysis")}
|
onClick={() => setSubModule("mechanics")}
|
||||||
>
|
>
|
||||||
<AnalysisIcon isActive={subModule === "analysis"} />
|
<MechanicsIcon isActive={subModule === "mechanics"} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
<div
|
||||||
)}
|
className={`sidebar-action-list ${subModule === "simulations" ? "active" : ""
|
||||||
|
}`}
|
||||||
|
onClick={() => setSubModule("simulations")}
|
||||||
|
>
|
||||||
|
<SimulationIcon isActive={subModule === "simulations"} />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={`sidebar-action-list ${subModule === "analysis" ? "active" : ""
|
||||||
|
}`}
|
||||||
|
onClick={() => setSubModule("analysis")}
|
||||||
|
>
|
||||||
|
<AnalysisIcon isActive={subModule === "analysis"} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{/* process builder */}
|
||||||
|
{toggleUI &&
|
||||||
|
subModule === "properties" &&
|
||||||
|
activeModule !== "visualization" &&
|
||||||
|
!selectedFloorItem && (
|
||||||
|
<div className="sidebar-right-container">
|
||||||
|
<div className="sidebar-right-content-container">
|
||||||
|
<GlobalProperties />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{toggleUI &&
|
||||||
|
subModule === "properties" &&
|
||||||
|
activeModule !== "visualization" &&
|
||||||
|
selectedFloorItem && (
|
||||||
|
<div className="sidebar-right-container">
|
||||||
|
<div className="sidebar-right-content-container">
|
||||||
|
<AsstePropertiies />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{toggleUI &&
|
||||||
|
subModule === "zoneProperties" &&
|
||||||
|
(activeModule === "builder" || activeModule === "simulation") && (
|
||||||
|
<div className="sidebar-right-container">
|
||||||
|
<div className="sidebar-right-content-container">
|
||||||
|
<ZoneProperties />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{/* simulation */}
|
||||||
|
{toggleUI && activeModule === "simulation" && (
|
||||||
|
<>
|
||||||
|
{subModule === "simulations" && (
|
||||||
|
<div className="sidebar-right-container">
|
||||||
|
<div className="sidebar-right-content-container">
|
||||||
|
<Simulations />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{subModule === "mechanics" && selectedEventData && selectedEventSphere && (
|
||||||
|
<div className="sidebar-right-container">
|
||||||
|
<div className="sidebar-right-content-container">
|
||||||
|
<EventProperties />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{subModule === "analysis" && (
|
||||||
|
<div className="sidebar-right-container">
|
||||||
|
<div className="sidebar-right-content-container">
|
||||||
|
<Analysis />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{/* realtime visualization */}
|
||||||
|
{toggleUI && activeModule === "visualization" && <Visualization />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
);
|
||||||
{/* process builder */}
|
|
||||||
{toggleUI &&
|
|
||||||
subModule === "properties" &&
|
|
||||||
activeModule !== "visualization" &&
|
|
||||||
!selectedFloorItem && (
|
|
||||||
<div className="sidebar-right-container">
|
|
||||||
<div className="sidebar-right-content-container">
|
|
||||||
<GlobalProperties />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{toggleUI &&
|
|
||||||
subModule === "properties" &&
|
|
||||||
activeModule !== "visualization" &&
|
|
||||||
selectedFloorItem && (
|
|
||||||
<div className="sidebar-right-container">
|
|
||||||
<div className="sidebar-right-content-container">
|
|
||||||
<AsstePropertiies />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{toggleUI &&
|
|
||||||
subModule === "zoneProperties" &&
|
|
||||||
(activeModule === "builder" || activeModule === "simulation") && (
|
|
||||||
<div className="sidebar-right-container">
|
|
||||||
<div className="sidebar-right-content-container">
|
|
||||||
<ZoneProperties />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{/* simulation */}
|
|
||||||
|
|
||||||
{toggleUI && activeModule === "simulation" && (
|
|
||||||
<>
|
|
||||||
{subModule === "mechanics" && (
|
|
||||||
<div className="sidebar-right-container">
|
|
||||||
<div className="sidebar-right-content-container">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{subModule === "analysis" && (
|
|
||||||
<div className="sidebar-right-container">
|
|
||||||
<div className="sidebar-right-content-container">
|
|
||||||
<Analysis />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{subModule === "simulations" && (
|
|
||||||
<div className="sidebar-right-container">
|
|
||||||
<div className="sidebar-right-content-container">
|
|
||||||
<Simulations />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* realtime visualization */}
|
|
||||||
{toggleUI && activeModule === "visualization" && <Visualization />}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SideBarRight;
|
export default SideBarRight;
|
|
@ -0,0 +1,279 @@
|
||||||
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
|
import InputWithDropDown from "../../../../ui/inputs/InputWithDropDown";
|
||||||
|
import LabledDropdown from "../../../../ui/inputs/LabledDropdown";
|
||||||
|
import {
|
||||||
|
AddIcon,
|
||||||
|
RemoveIcon,
|
||||||
|
ResizeHeightIcon,
|
||||||
|
} from "../../../../icons/ExportCommonIcons";
|
||||||
|
import RenameInput from "../../../../ui/inputs/RenameInput";
|
||||||
|
import { handleResize } from "../../../../../functions/handleResizePannel";
|
||||||
|
import { handleActionToggle } from "./functions/handleActionToggle";
|
||||||
|
import { handleDeleteAction } from "./functions/handleDeleteAction";
|
||||||
|
import DefaultAction from "./actions/DefaultAction";
|
||||||
|
import SpawnAction from "./actions/SpawnAction";
|
||||||
|
import SwapAction from "./actions/SwapAction";
|
||||||
|
import DespawnAction from "./actions/DespawnAction";
|
||||||
|
import TravelAction from "./actions/TravelAction";
|
||||||
|
import PickAndPlaceAction from "./actions/PickAndPlaceAction";
|
||||||
|
import ProcessAction from "./actions/ProcessAction";
|
||||||
|
import StorageAction from "./actions/StorageAction";
|
||||||
|
import Trigger from "./trigger/Trigger";
|
||||||
|
|
||||||
|
import { useSelectedEventData, useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
|
||||||
|
import { useProductStore } from "../../../../../store/simulation/useProductStore";
|
||||||
|
|
||||||
|
const EventProperties: React.FC = () => {
|
||||||
|
const actionsContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const [activeOption, setActiveOption] = useState("default");
|
||||||
|
const [selectedItem, setSelectedItem] = useState<{ item: { uuid: string; name: string } | null; }>({ item: null });
|
||||||
|
const { selectedEventData } = useSelectedEventData();
|
||||||
|
const { getEventByModelUuid } = useProductStore();
|
||||||
|
const { selectedProduct } = useSelectedProduct();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const actions = getActions();
|
||||||
|
if (actions.length > 0 && !selectedItem.item) {
|
||||||
|
setSelectedItem({ item: actions[0] });
|
||||||
|
}
|
||||||
|
}, [selectedEventData]);
|
||||||
|
|
||||||
|
const getCurrentEventData = () => {
|
||||||
|
if (!selectedEventData?.data || !selectedProduct) return null;
|
||||||
|
const event = getEventByModelUuid(selectedProduct.productId, selectedEventData.data.modelUuid);
|
||||||
|
return event || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAssetType = () => {
|
||||||
|
const event = getCurrentEventData();
|
||||||
|
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 getAvailableActions = () => {
|
||||||
|
switch (getAssetType()) {
|
||||||
|
case "conveyor":
|
||||||
|
return {
|
||||||
|
defaultOption: "default",
|
||||||
|
options: ["default", "spawn", "swap", "despawn"],
|
||||||
|
};
|
||||||
|
case "vehicle":
|
||||||
|
return {
|
||||||
|
defaultOption: "travel",
|
||||||
|
options: ["travel"],
|
||||||
|
};
|
||||||
|
case "roboticArm":
|
||||||
|
return {
|
||||||
|
defaultOption: "pickAndPlace",
|
||||||
|
options: ["pickAndPlace"],
|
||||||
|
};
|
||||||
|
case "machine":
|
||||||
|
return {
|
||||||
|
defaultOption: "process",
|
||||||
|
options: ["process"],
|
||||||
|
};
|
||||||
|
case "storageUnit":
|
||||||
|
return {
|
||||||
|
defaultOption: "store",
|
||||||
|
options: ["store", "spawn"],
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return {
|
||||||
|
defaultOption: "default",
|
||||||
|
options: ["default"],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get actions based on asset type
|
||||||
|
const getActions = () => {
|
||||||
|
if (!selectedEventData?.data) return [];
|
||||||
|
|
||||||
|
const event = selectedEventData.data;
|
||||||
|
switch (getAssetType()) {
|
||||||
|
case "conveyor":
|
||||||
|
return (event as ConveyorEventSchema).points
|
||||||
|
.find((point) => point.uuid === selectedEventData?.selectedPoint)
|
||||||
|
?.action?.triggers.map((trigger) => ({
|
||||||
|
uuid: trigger.triggerUuid,
|
||||||
|
name: trigger.triggerName,
|
||||||
|
})) || [];
|
||||||
|
case "vehicle":
|
||||||
|
return (event as VehicleEventSchema).point.action.triggers.map(
|
||||||
|
(trigger) => ({
|
||||||
|
uuid: trigger.triggerUuid,
|
||||||
|
name: trigger.triggerName,
|
||||||
|
})
|
||||||
|
) || [];
|
||||||
|
case "roboticArm":
|
||||||
|
return (event as RoboticArmEventSchema).point.actions.flatMap(
|
||||||
|
(action) =>
|
||||||
|
action.triggers.map((trigger) => ({
|
||||||
|
uuid: trigger.triggerUuid,
|
||||||
|
name: trigger.triggerName,
|
||||||
|
}))
|
||||||
|
) || [];
|
||||||
|
case "machine":
|
||||||
|
return (event as MachineEventSchema).point.action.triggers.map(
|
||||||
|
(trigger) => ({
|
||||||
|
uuid: trigger.triggerUuid,
|
||||||
|
name: trigger.triggerName,
|
||||||
|
})
|
||||||
|
) || [];
|
||||||
|
case "storageUnit":
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
uuid: (event as StorageEventSchema).point.action.actionUuid,
|
||||||
|
name: (event as StorageEventSchema).point.action.actionName,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleActionToggle = (actionUuid: string) => {
|
||||||
|
const actions = getActions();
|
||||||
|
const selected = actions.find(action => action.uuid === actionUuid);
|
||||||
|
if (selected) {
|
||||||
|
setSelectedItem({ item: selected });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteAction = (actionUuid: string) => {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const actions = getActions();
|
||||||
|
|
||||||
|
const getSpeed = () => {
|
||||||
|
if (!selectedEventData) return "0.5";
|
||||||
|
if ("speed" in selectedEventData.data) return selectedEventData.data.speed.toString();
|
||||||
|
return "0.5";
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{getCurrentEventData() &&
|
||||||
|
<div className="event-proprties-wrapper">
|
||||||
|
<div className="header">
|
||||||
|
<div className="header-value">{selectedEventData?.data.modelName}</div>
|
||||||
|
</div>
|
||||||
|
<div className="global-props">
|
||||||
|
<div className="property-list-container">
|
||||||
|
<div className="property-item">
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Speed"
|
||||||
|
value="0.5"
|
||||||
|
min={0}
|
||||||
|
step={0.1}
|
||||||
|
defaultValue={getSpeed()}
|
||||||
|
max={10}
|
||||||
|
activeOption="s"
|
||||||
|
onClick={() => { }}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="property-item">
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Delay"
|
||||||
|
value="0.5"
|
||||||
|
min={0}
|
||||||
|
step={0.1}
|
||||||
|
defaultValue="0.5"
|
||||||
|
max={10}
|
||||||
|
activeOption="s"
|
||||||
|
onClick={() => { }}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{getAssetType() === 'roboticArm' &&
|
||||||
|
<div className="actions-list-container">
|
||||||
|
<div className="actions">
|
||||||
|
<div className="header">
|
||||||
|
<div className="header-value">Actions</div>
|
||||||
|
<div className="add-button" onClick={() => { }}>
|
||||||
|
<AddIcon /> Add
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="lists-main-container"
|
||||||
|
ref={actionsContainerRef}
|
||||||
|
style={{ height: "120px" }}
|
||||||
|
>
|
||||||
|
<div className="list-container">
|
||||||
|
{actions.map((action) => (
|
||||||
|
<div
|
||||||
|
key={action.uuid}
|
||||||
|
className={`list-item ${selectedItem.item?.uuid === action.uuid ? "active" : ""}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="value"
|
||||||
|
onClick={() => handleActionToggle(action.uuid)}
|
||||||
|
>
|
||||||
|
<RenameInput value={action.name} />
|
||||||
|
</div>
|
||||||
|
{actions.length > 1 && (
|
||||||
|
<div
|
||||||
|
className="remove-button"
|
||||||
|
onClick={() => handleDeleteAction(action.uuid)}
|
||||||
|
>
|
||||||
|
<RemoveIcon />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="resize-icon"
|
||||||
|
id="action-resize"
|
||||||
|
onMouseDown={(e) => handleResize(e, actionsContainerRef)}
|
||||||
|
>
|
||||||
|
<ResizeHeightIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div className="selected-actions-details">
|
||||||
|
<div className="selected-actions-header">
|
||||||
|
<RenameInput value="Action Name" />
|
||||||
|
</div>
|
||||||
|
<div className="selected-actions-list">
|
||||||
|
<LabledDropdown
|
||||||
|
defaultOption={getAvailableActions().defaultOption}
|
||||||
|
options={getAvailableActions().options}
|
||||||
|
onSelect={(option) => setActiveOption(option)}
|
||||||
|
/>
|
||||||
|
{activeOption === "default" && <DefaultAction />}
|
||||||
|
{activeOption === "spawn" && <SpawnAction />}
|
||||||
|
{activeOption === "swap" && <SwapAction />}
|
||||||
|
{activeOption === "despawn" && <DespawnAction />}
|
||||||
|
{activeOption === "travel" && <TravelAction />}
|
||||||
|
{activeOption === "pickAndPlace" && <PickAndPlaceAction />}
|
||||||
|
{activeOption === "process" && <ProcessAction />}
|
||||||
|
{activeOption === "store" && <StorageAction />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="tirgger">
|
||||||
|
<Trigger />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EventProperties;
|
|
@ -0,0 +1,7 @@
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const DefaultAction:React.FC = () => {
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DefaultAction;
|
|
@ -0,0 +1,22 @@
|
||||||
|
import React from "react";
|
||||||
|
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
||||||
|
|
||||||
|
const DespawnAction: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Delay"
|
||||||
|
value=""
|
||||||
|
min={0}
|
||||||
|
step={0.1}
|
||||||
|
max={10}
|
||||||
|
defaultValue="0"
|
||||||
|
activeOption="s"
|
||||||
|
onClick={() => {}}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DespawnAction;
|
|
@ -0,0 +1,13 @@
|
||||||
|
import React from "react";
|
||||||
|
import EyeDropInput from "../../../../../ui/inputs/EyeDropInput";
|
||||||
|
|
||||||
|
const PickAndPlaceAction: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<EyeDropInput label="Pick Point" value="na" onChange={() => {}} />
|
||||||
|
<EyeDropInput label="Unload Point" value="na" onChange={() => {}} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PickAndPlaceAction;
|
|
@ -0,0 +1,24 @@
|
||||||
|
import React from "react";
|
||||||
|
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
||||||
|
import SwapAction from "./SwapAction";
|
||||||
|
|
||||||
|
const ProcessAction: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Process Time"
|
||||||
|
value="6"
|
||||||
|
min={0}
|
||||||
|
step={1}
|
||||||
|
max={10}
|
||||||
|
defaultValue="0"
|
||||||
|
activeOption="s"
|
||||||
|
onClick={() => {}}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
<SwapAction />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProcessAction;
|
|
@ -0,0 +1,35 @@
|
||||||
|
import React from "react";
|
||||||
|
import PreviewSelectionWithUpload from "../../../../../ui/inputs/PreviewSelectionWithUpload";
|
||||||
|
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
||||||
|
|
||||||
|
const SpawnAction: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Spawn interval"
|
||||||
|
value="0"
|
||||||
|
min={0}
|
||||||
|
step={1}
|
||||||
|
defaultValue="0"
|
||||||
|
max={10}
|
||||||
|
activeOption="s"
|
||||||
|
onClick={() => {}}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Spawn count"
|
||||||
|
value="0"
|
||||||
|
min={0}
|
||||||
|
step={1}
|
||||||
|
defaultValue="0"
|
||||||
|
max={10}
|
||||||
|
activeOption="s"
|
||||||
|
onClick={() => {}}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
<PreviewSelectionWithUpload />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SpawnAction;
|
|
@ -0,0 +1,20 @@
|
||||||
|
import React from "react";
|
||||||
|
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
||||||
|
|
||||||
|
const StorageAction: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Storage Capacity"
|
||||||
|
value=""
|
||||||
|
min={0}
|
||||||
|
step={0.1}
|
||||||
|
max={10}
|
||||||
|
defaultValue="0"
|
||||||
|
activeOption="s"
|
||||||
|
onClick={() => {}}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StorageAction;
|
|
@ -0,0 +1,12 @@
|
||||||
|
import React from "react";
|
||||||
|
import PreviewSelectionWithUpload from "../../../../../ui/inputs/PreviewSelectionWithUpload";
|
||||||
|
|
||||||
|
const SwapAction: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PreviewSelectionWithUpload />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SwapAction;
|
|
@ -0,0 +1,36 @@
|
||||||
|
import React from "react";
|
||||||
|
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
||||||
|
import EyeDropInput from "../../../../../ui/inputs/EyeDropInput";
|
||||||
|
|
||||||
|
const TravelAction: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Load Capacity"
|
||||||
|
value=""
|
||||||
|
min={0}
|
||||||
|
step={0.1}
|
||||||
|
max={10}
|
||||||
|
defaultValue="0"
|
||||||
|
activeOption="s"
|
||||||
|
onClick={() => {}}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Unload Duration"
|
||||||
|
value=""
|
||||||
|
min={0}
|
||||||
|
step={0.1}
|
||||||
|
max={10}
|
||||||
|
defaultValue="0"
|
||||||
|
activeOption="s"
|
||||||
|
onClick={() => {}}
|
||||||
|
onChange={(value) => console.log(value)}
|
||||||
|
/>
|
||||||
|
<EyeDropInput label="Pick Point" value="na" onChange={() => {}} />
|
||||||
|
<EyeDropInput label="Unload Point" value="na" onChange={() => {}} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TravelAction;
|
|
@ -0,0 +1,6 @@
|
||||||
|
export function handleActionToggle(uuid: string) {
|
||||||
|
// This function handles the action toggle for the event properties.
|
||||||
|
// It updates the selected action and its properties based on the provided UUID.
|
||||||
|
// The function is currently empty and needs to be implemented.
|
||||||
|
// You can add your logic here to handle the action toggle.
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
export function handleDeleteAction(uuid: string) {
|
||||||
|
// This function handles the action toggle for the event properties.
|
||||||
|
// It updates the selected action and its properties based on the provided UUID.
|
||||||
|
// The function is currently empty and needs to be implemented.
|
||||||
|
// You can add your logic here to handle the action toggle.
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function ConveyorMechanics() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConveyorMechanics
|
|
@ -0,0 +1,10 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function MachineMechanics() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MachineMechanics
|
|
@ -0,0 +1,10 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function RoboticArmMechanics() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RoboticArmMechanics
|
|
@ -0,0 +1,10 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function StorageMechanics() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StorageMechanics
|
|
@ -0,0 +1,10 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function VehicleMechanics() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VehicleMechanics
|
|
@ -0,0 +1,107 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { AddIcon, RemoveIcon } from "../../../../../icons/ExportCommonIcons";
|
||||||
|
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
|
||||||
|
|
||||||
|
const Trigger: React.FC = () => {
|
||||||
|
// State to hold the list of triggers
|
||||||
|
const [triggers, setTriggers] = useState<string[]>([]);
|
||||||
|
const [activeOption, setActiveOption] = useState("onComplete");
|
||||||
|
|
||||||
|
// States for dropdowns
|
||||||
|
const [triggeredModel, setTriggeredModel] = useState<string[]>([]);
|
||||||
|
const [triggeredPoint, setTriggeredPoint] = useState<string[]>([]);
|
||||||
|
const [triggeredAction, setTriggeredAction] = useState<string[]>([]);
|
||||||
|
|
||||||
|
// Function to handle adding a new trigger
|
||||||
|
const addTrigger = (): void => {
|
||||||
|
const newTrigger = `Trigger ${triggers.length + 1}`;
|
||||||
|
setTriggers([...triggers, newTrigger]); // Add new trigger to the state
|
||||||
|
|
||||||
|
// Initialize the states for the new trigger
|
||||||
|
setTriggeredModel([...triggeredModel, ""]);
|
||||||
|
setTriggeredPoint([...triggeredPoint, ""]);
|
||||||
|
setTriggeredAction([...triggeredAction, ""]);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to handle removing a trigger
|
||||||
|
const removeTrigger = (index: number): void => {
|
||||||
|
setTriggers(triggers.filter((_, i) => i !== index)); // Remove trigger by index
|
||||||
|
setTriggeredModel(triggeredModel.filter((_, i) => i !== index));
|
||||||
|
setTriggeredPoint(triggeredPoint.filter((_, i) => i !== index));
|
||||||
|
setTriggeredAction(triggeredAction.filter((_, i) => i !== index));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="trigger-wrapper">
|
||||||
|
<div className="header">
|
||||||
|
<div className="title">Trigger</div>
|
||||||
|
<div
|
||||||
|
className="add-button"
|
||||||
|
onClick={addTrigger}
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
<AddIcon /> Add
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="trigger-list">
|
||||||
|
{/* Map over triggers and render them */}
|
||||||
|
{triggers.map((trigger, index) => (
|
||||||
|
<div key={index} className="trigger-item">
|
||||||
|
<div className="trigger-name">
|
||||||
|
{trigger}
|
||||||
|
<div
|
||||||
|
className="remove-button"
|
||||||
|
onClick={() => removeTrigger(index)}
|
||||||
|
style={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
<RemoveIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<LabledDropdown
|
||||||
|
defaultOption={activeOption}
|
||||||
|
options={["onComplete", "onStart", "onStop", "delay"]}
|
||||||
|
onSelect={(option) => setActiveOption(option)}
|
||||||
|
/>
|
||||||
|
<div className="trigger-options">
|
||||||
|
<div>
|
||||||
|
<LabledDropdown
|
||||||
|
defaultOption={triggeredModel[index] || "Select Model"}
|
||||||
|
options={["Model 1", "Model 2", "Model 3"]}
|
||||||
|
onSelect={(option) => {
|
||||||
|
const newModel = [...triggeredModel];
|
||||||
|
newModel[index] = option;
|
||||||
|
setTriggeredModel(newModel);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<LabledDropdown
|
||||||
|
defaultOption={triggeredPoint[index] || "Select Point"}
|
||||||
|
options={["Point 1", "Point 2", "Point 3"]}
|
||||||
|
onSelect={(option) => {
|
||||||
|
const newPoint = [...triggeredPoint];
|
||||||
|
newPoint[index] = option;
|
||||||
|
setTriggeredPoint(newPoint);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<LabledDropdown
|
||||||
|
defaultOption={triggeredAction[index] || "Select Action"}
|
||||||
|
options={["Action 1", "Action 2", "Action 3"]}
|
||||||
|
onSelect={(option) => {
|
||||||
|
const newAction = [...triggeredAction];
|
||||||
|
newAction[index] = option;
|
||||||
|
setTriggeredAction(newAction);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Trigger;
|
|
@ -1,147 +1,198 @@
|
||||||
import React, { useRef, useState } from "react";
|
import React, { useEffect, 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 { useSelectedAsset, useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
|
||||||
|
import { useProductStore } from "../../../../store/simulation/useProductStore";
|
||||||
|
import { generateUUID } from "three/src/math/MathUtils";
|
||||||
|
import RenderOverlay from "../../../templates/Overlay";
|
||||||
|
import EditWidgetOption from "../../../ui/menu/EditWidgetOption";
|
||||||
|
|
||||||
interface Path {
|
interface Event {
|
||||||
pathName: string; // Represents the name of the path
|
pathName: string;
|
||||||
Children: string[]; // Represents the list of child points
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DropListProps {
|
interface ListProps {
|
||||||
val: Path; // Use the Path interface for the val prop
|
val: Event;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DropList: React.FC<DropListProps> = ({ val }) => {
|
const List: React.FC<ListProps> = ({ val }) => {
|
||||||
const [openDrop, setOpenDrop] = useState(false);
|
return (
|
||||||
return (
|
<div className="process-container">
|
||||||
<div className="process-container">
|
<div className="value">
|
||||||
<div
|
{val.pathName}
|
||||||
className="value"
|
|
||||||
onClick={() => {
|
|
||||||
setOpenDrop(!openDrop);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{val.pathName}
|
|
||||||
<div className={`arrow-container${openDrop ? " active" : ""}`}>
|
|
||||||
<ArrowIcon />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{val.Children && openDrop && (
|
|
||||||
<div className="children-drop">
|
|
||||||
{val.Children.map((child, index) => (
|
|
||||||
<div key={index} className="value">
|
|
||||||
{child}
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
);
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Simulations: React.FC = () => {
|
const Simulations: React.FC = () => {
|
||||||
const productsContainerRef = useRef<HTMLDivElement>(null);
|
const productsContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const [productsList, setProductsList] = useState<string[]>([]);
|
const { products, addProduct, removeProduct, renameProduct, addEvent, removeEvent } = useProductStore();
|
||||||
const [selectedItem, setSelectedItem] = useState<string>();
|
const { selectedProduct, setSelectedProduct } = useSelectedProduct();
|
||||||
|
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
|
||||||
|
|
||||||
const handleAddAction = () => {
|
const handleAddProduct = () => {
|
||||||
setProductsList([...productsList, `Product ${productsList.length + 1}`]);
|
addProduct(`Product ${products.length + 1}`, generateUUID());
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveAction = (index: number) => {
|
const handleRemoveProduct = (productId: string) => {
|
||||||
setProductsList(productsList.filter((_, i) => i !== index));
|
const currentIndex = products.findIndex(p => p.productId === productId);
|
||||||
if (selectedItem === productsList[index]) {
|
const isSelected = selectedProduct.productId === productId;
|
||||||
setSelectedItem("");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const Value = [
|
const updatedProducts = products.filter(p => p.productId !== productId);
|
||||||
{ pathName: "Path 1", Children: ["Point 1", "Point 2"] },
|
|
||||||
{ pathName: "Path 2", Children: ["Point 1", "Point 2"] },
|
|
||||||
{ pathName: "Path 3", Children: ["Point 1", "Point 2"] },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
if (isSelected) {
|
||||||
<div className="simulations-container">
|
if (updatedProducts.length > 0) {
|
||||||
<div className="header">Simulations</div>
|
let newSelectedIndex = currentIndex;
|
||||||
<div className="add-product-container">
|
if (currentIndex >= updatedProducts.length) {
|
||||||
<div className="actions">
|
newSelectedIndex = updatedProducts.length - 1;
|
||||||
<div className="header">
|
}
|
||||||
<div className="header-value">Products</div>
|
setSelectedProduct(
|
||||||
<div className="add-button" onClick={handleAddAction}>
|
updatedProducts[newSelectedIndex].productId,
|
||||||
<AddIcon /> Add
|
updatedProducts[newSelectedIndex].productName
|
||||||
</div>
|
);
|
||||||
</div>
|
} else {
|
||||||
<div
|
setSelectedProduct('', '');
|
||||||
className="lists-main-container"
|
}
|
||||||
ref={productsContainerRef}
|
}
|
||||||
style={{ height: "120px" }}
|
|
||||||
>
|
removeProduct(productId);
|
||||||
<div className="list-container">
|
};
|
||||||
{productsList.map((action, index) => (
|
|
||||||
<div
|
const handleRenameProduct = (productId: string, newName: string) => {
|
||||||
key={index}
|
renameProduct(productId, newName);
|
||||||
className={`list-item ${
|
if (selectedProduct.productId === productId) {
|
||||||
selectedItem === action ? "active" : ""
|
setSelectedProduct(productId, newName);
|
||||||
}`}
|
}
|
||||||
>
|
};
|
||||||
<div
|
|
||||||
className="value"
|
const handleAddEventToProduct = () => {
|
||||||
onClick={() => setSelectedItem(action)}
|
if (selectedAsset) {
|
||||||
>
|
addEvent(selectedProduct.productId, selectedAsset);
|
||||||
<input type="radio" name="products" id="products" />
|
clearSelectedAsset();
|
||||||
<RenameInput value={action} />
|
}
|
||||||
</div>
|
};
|
||||||
<div
|
|
||||||
className="remove-button"
|
const handleRemoveEventFromProduct = () => {
|
||||||
onClick={() => handleRemoveAction(index)}
|
if (selectedAsset) {
|
||||||
>
|
removeEvent(selectedProduct.productId, selectedAsset.modelUuid);
|
||||||
<RemoveIcon />
|
clearSelectedAsset();
|
||||||
</div>
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectedProductData = products.find(
|
||||||
|
(product) => product.productId === selectedProduct.productId
|
||||||
|
);
|
||||||
|
|
||||||
|
const events: Event[] = selectedProductData?.eventsData.map((event) => ({
|
||||||
|
pathName: event.modelName,
|
||||||
|
})) || [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="simulations-container">
|
||||||
|
<div className="header">Simulations</div>
|
||||||
|
<div className="add-product-container">
|
||||||
|
<div className="actions">
|
||||||
|
<div className="header">
|
||||||
|
<div className="header-value">Products</div>
|
||||||
|
<div className="add-button" onClick={handleAddProduct}>
|
||||||
|
<AddIcon /> Add
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="lists-main-container"
|
||||||
|
ref={productsContainerRef}
|
||||||
|
style={{ height: "120px" }}
|
||||||
|
>
|
||||||
|
<div className="list-container">
|
||||||
|
{products.map((product, index) => (
|
||||||
|
<div
|
||||||
|
key={product.productId}
|
||||||
|
className={`list-item ${selectedProduct.productId === product.productId ? "active" : ""}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="value"
|
||||||
|
onClick={() => setSelectedProduct(product.productId, product.productName)}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="products"
|
||||||
|
checked={selectedProduct.productId === product.productId}
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
<RenameInput
|
||||||
|
value={product.productName}
|
||||||
|
onRename={(newName) => handleRenameProduct(product.productId, newName)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{products.length > 1 && (
|
||||||
|
<div
|
||||||
|
className="remove-button"
|
||||||
|
onClick={() => handleRemoveProduct(product.productId)}
|
||||||
|
>
|
||||||
|
<RemoveIcon />
|
||||||
|
</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="collapse-header-container">
|
||||||
|
<div className="header">Events</div>
|
||||||
|
<div className="arrow-container">
|
||||||
|
<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>
|
||||||
<div
|
|
||||||
className="resize-icon"
|
{selectedAsset &&
|
||||||
id="action-resize"
|
<RenderOverlay>
|
||||||
onMouseDown={(e) => handleResize(e, productsContainerRef)}
|
<EditWidgetOption
|
||||||
>
|
options={['Add to Product', 'Remove from Product']}
|
||||||
<ResizeHeightIcon />
|
onClick={(option) => {
|
||||||
</div>
|
if (option === 'Add to Product') {
|
||||||
</div>
|
handleAddEventToProduct();
|
||||||
|
} else {
|
||||||
|
handleRemoveEventFromProduct();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</RenderOverlay>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className="simulation-process">
|
);
|
||||||
<div className="collapse-header-container">
|
|
||||||
<div className="header">Operations</div>
|
|
||||||
<div className="arrow-container">
|
|
||||||
<ArrowIcon />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{Value.map((val, index) => (
|
|
||||||
<DropList key={index} val={val} />
|
|
||||||
))}
|
|
||||||
</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>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Simulations;
|
export default Simulations;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect, useRef } from "react";
|
||||||
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
import { useWidgetStore } from "../../../../../store/useWidgetStore";
|
||||||
import ChartComponent from "../../../sidebarLeft//visualization/widgets/ChartComponent";
|
import ChartComponent from "../../../sidebarLeft/visualization/widgets/ChartComponent";
|
||||||
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../../ui/inputs/RegularDropDown";
|
||||||
import { WalletIcon } from "../../../../icons/3dChartIcons";
|
import { WalletIcon } from "../../../../icons/3dChartIcons";
|
||||||
import SimpleCard from "../../../../../modules//visualization/widgets/floating/cards/SimpleCard";
|
import SimpleCard from "../../../../../modules/visualization/widgets/floating/cards/SimpleCard";
|
||||||
|
|
||||||
interface Widget {
|
interface Widget {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
} from "../icons/ExportToolsIcons";
|
} from "../icons/ExportToolsIcons";
|
||||||
import { ArrowIcon, TickIcon } from "../icons/ExportCommonIcons";
|
import { ArrowIcon, TickIcon } from "../icons/ExportCommonIcons";
|
||||||
import useModuleStore, { useThreeDStore } from "../../store/useModuleStore";
|
import useModuleStore, { useThreeDStore } from "../../store/useModuleStore";
|
||||||
import { handleSaveTemplate } from "../../modules//visualization/functions/handleSaveTemplate";
|
import { handleSaveTemplate } from "../../modules/visualization/functions/handleSaveTemplate";
|
||||||
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
||||||
import useTemplateStore from "../../store/useTemplateStore";
|
import useTemplateStore from "../../store/useTemplateStore";
|
||||||
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
||||||
|
|
|
@ -5,6 +5,7 @@ type InputWithDropDownProps = {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
min?: number;
|
min?: number;
|
||||||
|
max?: number;
|
||||||
step?: number;
|
step?: number;
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
options?: string[]; // Array of dropdown options
|
options?: string[]; // Array of dropdown options
|
||||||
|
@ -19,6 +20,7 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
||||||
label,
|
label,
|
||||||
value,
|
value,
|
||||||
min,
|
min,
|
||||||
|
max,
|
||||||
step,
|
step,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
options,
|
options,
|
||||||
|
@ -47,6 +49,7 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
||||||
<div className="input default" id={separatedWords}>
|
<div className="input default" id={separatedWords}>
|
||||||
<input
|
<input
|
||||||
min={min}
|
min={min}
|
||||||
|
max={max}
|
||||||
step={step}
|
step={step}
|
||||||
type="number"
|
type="number"
|
||||||
defaultValue={value}
|
defaultValue={value}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import LabledDropdown from "./LabledDropdown";
|
||||||
|
import { ArrowIcon } from "../../icons/ExportCommonIcons";
|
||||||
|
|
||||||
|
const PreviewSelectionWithUpload: React.FC = () => {
|
||||||
|
const [showPreview, setSetshowPreview] = useState(false);
|
||||||
|
return (
|
||||||
|
<div className="preview-selection-with-upload-wrapper">
|
||||||
|
<div
|
||||||
|
className="input-header-container"
|
||||||
|
onClick={() => setSetshowPreview(!showPreview)}
|
||||||
|
>
|
||||||
|
<div className="input-header">Preview</div>
|
||||||
|
<div
|
||||||
|
className="arrow-container"
|
||||||
|
style={{ rotate: showPreview ? "0deg" : "90deg" }}
|
||||||
|
>
|
||||||
|
<ArrowIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{showPreview && (
|
||||||
|
<div className="canvas-wrapper">
|
||||||
|
<div className="canvas-container"></div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="asset-selection-container">
|
||||||
|
<div className="upload-custom-asset-button">
|
||||||
|
<div className="title">Upload Product</div>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept=".glb, .gltf"
|
||||||
|
id="simulation-product-upload"
|
||||||
|
/>
|
||||||
|
<label className="upload-button" htmlFor="simulation-product-upload">
|
||||||
|
Upload here
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<LabledDropdown
|
||||||
|
label="Presets"
|
||||||
|
defaultOption={"Default material"}
|
||||||
|
options={["Default material", "Product 1", "Product 2"]}
|
||||||
|
onSelect={(option) => console.log(option)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PreviewSelectionWithUpload;
|
|
@ -1,23 +1,20 @@
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import {
|
import {
|
||||||
useEditWidgetOptionsStore,
|
|
||||||
useLeftData,
|
useLeftData,
|
||||||
useRightClickSelected,
|
|
||||||
useRightSelected,
|
|
||||||
useTopData,
|
useTopData,
|
||||||
} from "../../../store/visualization/useZone3DWidgetStore";
|
} from "../../../store/visualization/useZone3DWidgetStore";
|
||||||
|
|
||||||
interface EditWidgetOptionProps {
|
interface EditWidgetOptionProps {
|
||||||
options: string[];
|
options: string[];
|
||||||
|
onClick: (option: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EditWidgetOption: React.FC<EditWidgetOptionProps> = ({
|
const EditWidgetOption: React.FC<EditWidgetOptionProps> = ({
|
||||||
options,
|
options,
|
||||||
|
onClick
|
||||||
}) => {
|
}) => {
|
||||||
const { top } = useTopData();
|
const { top } = useTopData();
|
||||||
const { left } = useLeftData();
|
const { left } = useLeftData();
|
||||||
const { setRightSelect } = useRightSelected();
|
|
||||||
const { setEditWidgetOptions } = useEditWidgetOptionsStore();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
@ -38,10 +35,7 @@ const EditWidgetOption: React.FC<EditWidgetOptionProps> = ({
|
||||||
<div
|
<div
|
||||||
className="option"
|
className="option"
|
||||||
key={index}
|
key={index}
|
||||||
onClick={(e) => {
|
onClick={() => onClick(option)}
|
||||||
setRightSelect(option);
|
|
||||||
setEditWidgetOptions(false);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{option}
|
{option}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,10 +8,12 @@ import * as Types from "../../../types/world/worldTypes";
|
||||||
import { initializeDB, retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils';
|
import { initializeDB, retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils';
|
||||||
import { getCamera } from '../../../services/factoryBuilder/camera/getCameraApi';
|
import { getCamera } from '../../../services/factoryBuilder/camera/getCameraApi';
|
||||||
import { getFloorAssets } from '../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
|
import { getFloorAssets } from '../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
|
||||||
|
import PointsCalculator from '../../simulation/events/points/functions/pointsCalculator';
|
||||||
|
|
||||||
async function loadInitialFloorItems(
|
async function loadInitialFloorItems(
|
||||||
itemsGroup: Types.RefGroup,
|
itemsGroup: Types.RefGroup,
|
||||||
setFloorItems: Types.setFloorItemSetState,
|
setFloorItems: Types.setFloorItemSetState,
|
||||||
|
addEvent: (event: EventsSchema) => void,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!itemsGroup.current) return;
|
if (!itemsGroup.current) return;
|
||||||
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||||
|
@ -70,7 +72,7 @@ async function loadInitialFloorItems(
|
||||||
const cachedModel = THREE.Cache.get(item.modelfileID!);
|
const cachedModel = THREE.Cache.get(item.modelfileID!);
|
||||||
if (cachedModel) {
|
if (cachedModel) {
|
||||||
// console.log(`[Cache] Fetching ${item.modelname}`);
|
// console.log(`[Cache] Fetching ${item.modelname}`);
|
||||||
processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems);
|
processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems, addEvent);
|
||||||
modelsLoaded++;
|
modelsLoaded++;
|
||||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
||||||
return;
|
return;
|
||||||
|
@ -85,7 +87,7 @@ async function loadInitialFloorItems(
|
||||||
URL.revokeObjectURL(blobUrl);
|
URL.revokeObjectURL(blobUrl);
|
||||||
THREE.Cache.remove(blobUrl);
|
THREE.Cache.remove(blobUrl);
|
||||||
THREE.Cache.add(item.modelfileID!, gltf);
|
THREE.Cache.add(item.modelfileID!, gltf);
|
||||||
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems);
|
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, addEvent);
|
||||||
modelsLoaded++;
|
modelsLoaded++;
|
||||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
||||||
},
|
},
|
||||||
|
@ -106,7 +108,7 @@ async function loadInitialFloorItems(
|
||||||
const modelBlob = await fetch(modelUrl).then((res) => res.blob());
|
const modelBlob = await fetch(modelUrl).then((res) => res.blob());
|
||||||
await storeGLTF(item.modelfileID!, modelBlob);
|
await storeGLTF(item.modelfileID!, modelBlob);
|
||||||
THREE.Cache.add(item.modelfileID!, gltf);
|
THREE.Cache.add(item.modelfileID!, gltf);
|
||||||
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems);
|
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, addEvent);
|
||||||
modelsLoaded++;
|
modelsLoaded++;
|
||||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
||||||
},
|
},
|
||||||
|
@ -148,8 +150,9 @@ function processLoadedModel(
|
||||||
item: Types.FloorItemType,
|
item: Types.FloorItemType,
|
||||||
itemsGroup: Types.RefGroup,
|
itemsGroup: Types.RefGroup,
|
||||||
setFloorItems: Types.setFloorItemSetState,
|
setFloorItems: Types.setFloorItemSetState,
|
||||||
|
addEvent: (event: EventsSchema) => void,
|
||||||
) {
|
) {
|
||||||
const model = gltf;
|
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 };
|
||||||
|
@ -182,6 +185,243 @@ function processLoadedModel(
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (item.modelfileID === "a1ee92554935007b10b3eb05") {
|
||||||
|
const data = PointsCalculator(
|
||||||
|
'Vehicle',
|
||||||
|
gltf.clone(),
|
||||||
|
new THREE.Vector3(...model.rotation)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!data || !data.points) return;
|
||||||
|
|
||||||
|
const vehicleEvent: VehicleEventSchema = {
|
||||||
|
modelUuid: item.modeluuid,
|
||||||
|
modelName: item.modelname,
|
||||||
|
position: item.position,
|
||||||
|
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
||||||
|
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",
|
||||||
|
material: null,
|
||||||
|
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}`,
|
||||||
|
actionType: 'default',
|
||||||
|
material: 'inherit',
|
||||||
|
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(),
|
||||||
|
actionName: "Pick and Place",
|
||||||
|
actionType: "pickAndPlace",
|
||||||
|
process: {
|
||||||
|
startPoint: [0, 0, 0],
|
||||||
|
endPoint: [0, 0, 0]
|
||||||
|
},
|
||||||
|
triggers: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addEvent(roboticArmEvent);
|
||||||
|
}
|
||||||
|
|
||||||
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' });
|
||||||
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out' });
|
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out' });
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ import Ground from "../scene/environment/ground";
|
||||||
// import ZoneGroup from "../groups/zoneGroup1";
|
// import ZoneGroup from "../groups/zoneGroup1";
|
||||||
import { findEnvironment } from "../../services/factoryBuilder/environment/findEnvironment";
|
import { findEnvironment } from "../../services/factoryBuilder/environment/findEnvironment";
|
||||||
import Layer2DVisibility from "./geomentries/layers/layer2DVisibility";
|
import Layer2DVisibility from "./geomentries/layers/layer2DVisibility";
|
||||||
import DrieHtmlTemp from "..//visualization/mqttTemp/drieHtmlTemp";
|
import DrieHtmlTemp from "../visualization/mqttTemp/drieHtmlTemp";
|
||||||
import ZoneGroup from "./groups/zoneGroup";
|
import ZoneGroup from "./groups/zoneGroup";
|
||||||
import useModuleStore from "../../store/useModuleStore";
|
import useModuleStore from "../../store/useModuleStore";
|
||||||
import MeasurementTool from "../scene/tools/measurementTool";
|
import MeasurementTool from "../scene/tools/measurementTool";
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { retrieveGLTF, storeGLTF } from '../../../../utils/indexDB/idbUtils';
|
||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
import * as CONSTANTS from '../../../../types/world/worldConstants';
|
import * as CONSTANTS from '../../../../types/world/worldConstants';
|
||||||
import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||||
import PointsCalculator from '../../../simulation/events/points/pointsCalculator';
|
import PointsCalculator from '../../../simulation/events/points/functions/pointsCalculator';
|
||||||
|
|
||||||
async function addAssetModel(
|
async function addAssetModel(
|
||||||
raycaster: THREE.Raycaster,
|
raycaster: THREE.Raycaster,
|
||||||
|
@ -266,7 +266,7 @@ async function handleModelLoad(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
addEvent(roboticArmEvent);
|
addEvent(roboticArmEvent);
|
||||||
} else if (selectedItem.type === "Machine") {
|
} else if (selectedItem.type === "StaticMachine") {
|
||||||
const machineEvent: MachineEventSchema = {
|
const machineEvent: MachineEventSchema = {
|
||||||
modelUuid: newFloorItem.modeluuid,
|
modelUuid: newFloorItem.modeluuid,
|
||||||
modelName: newFloorItem.modelname,
|
modelName: newFloorItem.modelname,
|
||||||
|
|
|
@ -75,7 +75,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
||||||
gltfLoaderWorker.postMessage({ floorItems: data });
|
gltfLoaderWorker.postMessage({ floorItems: data });
|
||||||
} else {
|
} else {
|
||||||
gltfLoaderWorker.postMessage({ floorItems: [] });
|
gltfLoaderWorker.postMessage({ floorItems: [] });
|
||||||
loadInitialFloorItems(itemsGroup, setFloorItems);
|
loadInitialFloorItems(itemsGroup, setFloorItems, addEvent);
|
||||||
updateLoadingProgress(100);
|
updateLoadingProgress(100);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -94,7 +94,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
|
||||||
updateLoadingProgress(progress);
|
updateLoadingProgress(progress);
|
||||||
|
|
||||||
if (loadedAssets === totalAssets) {
|
if (loadedAssets === totalAssets) {
|
||||||
loadInitialFloorItems(itemsGroup, setFloorItems);
|
loadInitialFloorItems(itemsGroup, setFloorItems, addEvent);
|
||||||
updateLoadingProgress(100);
|
updateLoadingProgress(100);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,90 +2,107 @@ import * as THREE from "three";
|
||||||
import { EffectComposer, N8AO, Outline } from "@react-three/postprocessing";
|
import { EffectComposer, N8AO, Outline } from "@react-three/postprocessing";
|
||||||
import { BlendFunction } from "postprocessing";
|
import { BlendFunction } from "postprocessing";
|
||||||
import {
|
import {
|
||||||
useDeletableFloorItem,
|
useDeletableFloorItem,
|
||||||
useSelectedWallItem,
|
useSelectedWallItem,
|
||||||
useSelectedFloorItem,
|
useSelectedFloorItem,
|
||||||
} from "../../../store/store";
|
} from "../../../store/store";
|
||||||
import * as Types from "../../../types/world/worldTypes";
|
import * as Types from "../../../types/world/worldTypes";
|
||||||
import * as CONSTANTS from "../../../types/world/worldConstants";
|
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
|
||||||
|
|
||||||
export default function PostProcessing() {
|
export default function PostProcessing() {
|
||||||
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
|
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
|
||||||
const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
|
const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
|
||||||
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
|
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
|
||||||
|
const { selectedEventSphere } = useSelectedEventSphere();
|
||||||
|
|
||||||
function flattenChildren(children: any[]) {
|
function flattenChildren(children: any[]) {
|
||||||
const allChildren: any[] = [];
|
const allChildren: any[] = [];
|
||||||
children.forEach((child) => {
|
children.forEach((child) => {
|
||||||
allChildren.push(child);
|
allChildren.push(child);
|
||||||
if (child.children && child.children.length > 0) {
|
if (child.children && child.children.length > 0) {
|
||||||
allChildren.push(...flattenChildren(child.children));
|
allChildren.push(...flattenChildren(child.children));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return allChildren;
|
return allChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EffectComposer autoClear={false}>
|
<EffectComposer autoClear={false}>
|
||||||
<N8AO
|
<N8AO
|
||||||
color="black"
|
color="black"
|
||||||
aoRadius={20}
|
aoRadius={20}
|
||||||
intensity={7}
|
intensity={7}
|
||||||
distanceFalloff={4}
|
distanceFalloff={4}
|
||||||
aoSamples={32}
|
aoSamples={32}
|
||||||
denoiseRadius={6}
|
denoiseRadius={6}
|
||||||
denoiseSamples={16}
|
denoiseSamples={16}
|
||||||
/>
|
/>
|
||||||
{deletableFloorItem && (
|
{deletableFloorItem && (
|
||||||
<Outline
|
<Outline
|
||||||
selection={flattenChildren(deletableFloorItem.children)}
|
selection={flattenChildren(deletableFloorItem.children)}
|
||||||
selectionLayer={10}
|
selectionLayer={10}
|
||||||
width={3000}
|
width={3000}
|
||||||
blendFunction={BlendFunction.ALPHA}
|
blendFunction={BlendFunction.ALPHA}
|
||||||
edgeStrength={5}
|
edgeStrength={5}
|
||||||
resolutionScale={2}
|
resolutionScale={2}
|
||||||
pulseSpeed={0}
|
pulseSpeed={0}
|
||||||
visibleEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
|
visibleEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
|
||||||
hiddenEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
|
hiddenEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
|
||||||
blur={true}
|
blur={true}
|
||||||
xRay={true}
|
xRay={true}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{selectedWallItem && (
|
{selectedWallItem && (
|
||||||
<Outline
|
<Outline
|
||||||
selection={selectedWallItem.children[1].children[0].children.filter(
|
selection={selectedWallItem.children[1].children[0].children.filter(
|
||||||
(child: Types.Mesh) => child.name !== "CSG_REF"
|
(child: Types.Mesh) => child.name !== "CSG_REF"
|
||||||
)}
|
)}
|
||||||
selectionLayer={10}
|
selectionLayer={10}
|
||||||
width={3000}
|
width={3000}
|
||||||
blendFunction={BlendFunction.ALPHA}
|
blendFunction={BlendFunction.ALPHA}
|
||||||
edgeStrength={5}
|
edgeStrength={5}
|
||||||
resolutionScale={2}
|
resolutionScale={2}
|
||||||
pulseSpeed={0}
|
pulseSpeed={0}
|
||||||
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
|
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
|
||||||
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
|
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
|
||||||
blur={true}
|
blur={true}
|
||||||
xRay={true}
|
xRay={true}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{selectedFloorItem && (
|
{selectedFloorItem && (
|
||||||
<Outline
|
<Outline
|
||||||
selection={flattenChildren(selectedFloorItem.children)}
|
selection={flattenChildren(selectedFloorItem.children)}
|
||||||
selectionLayer={10}
|
selectionLayer={10}
|
||||||
width={3000}
|
width={3000}
|
||||||
blendFunction={BlendFunction.ALPHA}
|
blendFunction={BlendFunction.ALPHA}
|
||||||
edgeStrength={5}
|
edgeStrength={5}
|
||||||
resolutionScale={2}
|
resolutionScale={2}
|
||||||
pulseSpeed={0}
|
pulseSpeed={0}
|
||||||
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
|
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
|
||||||
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
|
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
|
||||||
blur={true}
|
blur={true}
|
||||||
xRay={true}
|
xRay={true}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</EffectComposer>
|
{selectedEventSphere && (
|
||||||
</>
|
<Outline
|
||||||
);
|
selection={[selectedEventSphere]}
|
||||||
|
selectionLayer={10}
|
||||||
|
width={1000}
|
||||||
|
blendFunction={BlendFunction.ALPHA}
|
||||||
|
edgeStrength={10}
|
||||||
|
resolutionScale={2}
|
||||||
|
pulseSpeed={0}
|
||||||
|
visibleEdgeColor={0x6f42c1}
|
||||||
|
hiddenEdgeColor={0x6f42c1}
|
||||||
|
blur={true}
|
||||||
|
xRay={true}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</EffectComposer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react'
|
||||||
|
import ConveyorInstances from './instances/conveyorInstances'
|
||||||
|
|
||||||
|
function Conveyor() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<ConveyorInstances />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Conveyor
|
|
@ -0,0 +1,10 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function ConveyorInstance() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConveyorInstance
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react'
|
||||||
|
import ConveyorInstance from './conveyorInstance/conveyorInstance'
|
||||||
|
|
||||||
|
function ConveyorInstances() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<ConveyorInstance />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ConveyorInstances
|
|
@ -4,20 +4,37 @@ import { useEventsStore } from '../../../../../store/simulation/useEventsStore';
|
||||||
import useModuleStore from '../../../../../store/useModuleStore';
|
import useModuleStore from '../../../../../store/useModuleStore';
|
||||||
import { TransformControls } from '@react-three/drei';
|
import { TransformControls } from '@react-three/drei';
|
||||||
import { detectModifierKeys } from '../../../../../utils/shortcutkeys/detectModifierKeys';
|
import { detectModifierKeys } from '../../../../../utils/shortcutkeys/detectModifierKeys';
|
||||||
|
import { useSelectedEventSphere, useSelectedEventData } from '../../../../../store/simulation/useSimulationStore';
|
||||||
|
|
||||||
function PointsCreator() {
|
function PointsCreator() {
|
||||||
const { events, updatePoint, getPointByUuid } = useEventsStore();
|
const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const transformRef = useRef<any>(null);
|
const transformRef = useRef<any>(null);
|
||||||
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null);
|
||||||
const [selectedPoint, setSelectedPoint] = useState<THREE.Mesh | null>(null);
|
|
||||||
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({});
|
||||||
|
const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere } = useSelectedEventSphere();
|
||||||
|
const { setSelectedEventData, clearSelectedEventData } = useSelectedEventData();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedEventSphere) {
|
||||||
|
const eventData = getEventByModelUuid(selectedEventSphere.userData.modelUuid);
|
||||||
|
if (eventData) {
|
||||||
|
setSelectedEventData(
|
||||||
|
eventData,
|
||||||
|
selectedEventSphere.userData.pointUuid
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
clearSelectedEventData();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearSelectedEventData();
|
||||||
|
}
|
||||||
|
}, [selectedEventSphere]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTransformMode(null);
|
|
||||||
const handleKeyDown = (e: KeyboardEvent) => {
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
const keyCombination = detectModifierKeys(e);
|
const keyCombination = detectModifierKeys(e);
|
||||||
if (!selectedPoint) return;
|
if (!selectedEventSphere) return;
|
||||||
if (keyCombination === "G") {
|
if (keyCombination === "G") {
|
||||||
setTransformMode((prev) => (prev === "translate" ? null : "translate"));
|
setTransformMode((prev) => (prev === "translate" ? null : "translate"));
|
||||||
}
|
}
|
||||||
|
@ -28,13 +45,13 @@ function PointsCreator() {
|
||||||
|
|
||||||
window.addEventListener("keydown", handleKeyDown);
|
window.addEventListener("keydown", handleKeyDown);
|
||||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||||
}, [selectedPoint]);
|
}, [selectedEventSphere]);
|
||||||
|
|
||||||
const updatePointToState = (selectedPoint: THREE.Mesh) => {
|
const updatePointToState = (selectedEventSphere: THREE.Mesh) => {
|
||||||
let point = JSON.parse(JSON.stringify(getPointByUuid(selectedPoint.userData.modelUuid, selectedPoint.userData.pointUuid)));
|
let point = JSON.parse(JSON.stringify(getPointByUuid(selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid)));
|
||||||
if (point) {
|
if (point) {
|
||||||
point.position = [selectedPoint.position.x, selectedPoint.position.y, selectedPoint.position.z];
|
point.position = [selectedEventSphere.position.x, selectedEventSphere.position.y, selectedEventSphere.position.z];
|
||||||
updatePoint(selectedPoint.userData.modelUuid, selectedPoint.userData.pointUuid, point)
|
updatePoint(selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid, point)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,10 +70,11 @@ function PointsCreator() {
|
||||||
ref={(el) => (sphereRefs.current[point.uuid] = el!)}
|
ref={(el) => (sphereRefs.current[point.uuid] = el!)}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setSelectedPoint(sphereRefs.current[point.uuid]);
|
setSelectedEventSphere(sphereRefs.current[point.uuid]);
|
||||||
}}
|
}}
|
||||||
onPointerMissed={() => {
|
onPointerMissed={() => {
|
||||||
setSelectedPoint(null);
|
clearSelectedEventSphere();
|
||||||
|
setTransformMode(null);
|
||||||
}}
|
}}
|
||||||
key={`${i}-${j}`}
|
key={`${i}-${j}`}
|
||||||
position={new THREE.Vector3(...point.position)}
|
position={new THREE.Vector3(...point.position)}
|
||||||
|
@ -76,10 +94,11 @@ function PointsCreator() {
|
||||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setSelectedPoint(sphereRefs.current[event.point.uuid]);
|
setSelectedEventSphere(sphereRefs.current[event.point.uuid]);
|
||||||
}}
|
}}
|
||||||
onPointerMissed={() => {
|
onPointerMissed={() => {
|
||||||
setSelectedPoint(null);
|
clearSelectedEventSphere();
|
||||||
|
setTransformMode(null);
|
||||||
}}
|
}}
|
||||||
position={new THREE.Vector3(...event.point.position)}
|
position={new THREE.Vector3(...event.point.position)}
|
||||||
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
||||||
|
@ -97,10 +116,11 @@ function PointsCreator() {
|
||||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setSelectedPoint(sphereRefs.current[event.point.uuid]);
|
setSelectedEventSphere(sphereRefs.current[event.point.uuid]);
|
||||||
}}
|
}}
|
||||||
onPointerMissed={() => {
|
onPointerMissed={() => {
|
||||||
setSelectedPoint(null);
|
clearSelectedEventSphere();
|
||||||
|
setTransformMode(null);
|
||||||
}}
|
}}
|
||||||
position={new THREE.Vector3(...event.point.position)}
|
position={new THREE.Vector3(...event.point.position)}
|
||||||
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
||||||
|
@ -118,10 +138,11 @@ function PointsCreator() {
|
||||||
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
ref={(el) => (sphereRefs.current[event.point.uuid] = el!)}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setSelectedPoint(sphereRefs.current[event.point.uuid]);
|
setSelectedEventSphere(sphereRefs.current[event.point.uuid]);
|
||||||
}}
|
}}
|
||||||
onPointerMissed={() => {
|
onPointerMissed={() => {
|
||||||
setSelectedPoint(null);
|
clearSelectedEventSphere();
|
||||||
|
setTransformMode(null);
|
||||||
}}
|
}}
|
||||||
position={new THREE.Vector3(...event.point.position)}
|
position={new THREE.Vector3(...event.point.position)}
|
||||||
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
|
||||||
|
@ -136,8 +157,8 @@ function PointsCreator() {
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
</group>
|
</group>
|
||||||
{(selectedPoint && transformMode) &&
|
{(selectedEventSphere && transformMode) &&
|
||||||
<TransformControls ref={transformRef} object={selectedPoint} mode={transformMode} onMouseUp={(e) => { updatePointToState(selectedPoint) }} />
|
<TransformControls ref={transformRef} object={selectedEventSphere} mode={transformMode} onMouseUp={(e) => { updatePointToState(selectedEventSphere) }} />
|
||||||
}
|
}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import { Group } from '../../../../types/world/worldTypes';
|
import { Group } from '../../../../../types/world/worldTypes';
|
||||||
|
|
||||||
function PointsCalculator(
|
function PointsCalculator(
|
||||||
type: string,
|
type: string,
|
|
@ -0,0 +1,10 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function MachineInstance() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MachineInstance
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react'
|
||||||
|
import MachineInstance from './machineInstance/machineInstance'
|
||||||
|
|
||||||
|
function MachineInstances() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<MachineInstance />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MachineInstances
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react'
|
||||||
|
import MachineInstances from './instances/machineInstances'
|
||||||
|
|
||||||
|
function Machine() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<MachineInstances />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Machine
|
|
@ -0,0 +1,9 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function MaterialAnimator() {
|
||||||
|
return (
|
||||||
|
<></>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MaterialAnimator
|
|
@ -0,0 +1,9 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function MaterialInstance() {
|
||||||
|
return (
|
||||||
|
<></>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MaterialInstance
|
|
@ -0,0 +1,17 @@
|
||||||
|
import React from 'react'
|
||||||
|
import MaterialInstance from './instance/materialInstance'
|
||||||
|
import MaterialAnimator from './animator/materialAnimator'
|
||||||
|
|
||||||
|
function MaterialInstances() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<MaterialInstance />
|
||||||
|
|
||||||
|
<MaterialAnimator />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MaterialInstances
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react'
|
||||||
|
import MaterialInstances from './instances/materialInstances'
|
||||||
|
|
||||||
|
function Materials() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<MaterialInstances />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Materials
|
|
@ -0,0 +1,25 @@
|
||||||
|
import React, { useEffect } from 'react'
|
||||||
|
import { useProductStore } from '../../../store/simulation/useProductStore'
|
||||||
|
import * as THREE from 'three';
|
||||||
|
import { useSelectedProduct } from '../../../store/simulation/useSimulationStore';
|
||||||
|
|
||||||
|
function Products() {
|
||||||
|
const { products, addProduct } = useProductStore();
|
||||||
|
const { setSelectedProduct } = useSelectedProduct();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (products.length === 0) {
|
||||||
|
const id = THREE.MathUtils.generateUUID();
|
||||||
|
const name = 'Product 1';
|
||||||
|
addProduct(name, id);
|
||||||
|
setSelectedProduct(id, name);
|
||||||
|
}
|
||||||
|
}, [products])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Products
|
|
@ -1,28 +1,62 @@
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from 'react';
|
||||||
import { useEventsStore } from "../../store/simulation/useEventsStore";
|
import { useEventsStore } from '../../store/simulation/useEventsStore';
|
||||||
import { useProductStore } from "../../store/simulation/useProductStore";
|
import { useProductStore } from '../../store/simulation/useProductStore';
|
||||||
import Vehicles from "./vehicle/vehicles";
|
import Vehicles from './vehicle/vehicles';
|
||||||
import Points from "./events/points/points";
|
import Points from './events/points/points';
|
||||||
import RoboticArm from "./roboticArm/roboticArm";
|
import Conveyor from './conveyor/conveyor';
|
||||||
|
import RoboticArm from './roboticArm/roboticArm';
|
||||||
|
import Materials from './materials/materials';
|
||||||
|
import Machine from './machine/machine';
|
||||||
|
import StorageUnit from './storageUnit/storageUnit';
|
||||||
|
import Simulator from './simulator/simulator';
|
||||||
|
import Products from './products/products';
|
||||||
|
import Trigger from './triggers/trigger';
|
||||||
|
import useModuleStore from '../../store/useModuleStore';
|
||||||
|
|
||||||
function Simulation() {
|
function Simulation() {
|
||||||
|
const { activeModule } = useModuleStore();
|
||||||
const { events } = useEventsStore();
|
const { events } = useEventsStore();
|
||||||
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 (
|
||||||
<>
|
<>
|
||||||
<Points />
|
|
||||||
|
|
||||||
<Vehicles />
|
{activeModule === 'simulation' &&
|
||||||
<RoboticArm />
|
|
||||||
|
<>
|
||||||
|
|
||||||
|
<Points />
|
||||||
|
|
||||||
|
<Products />
|
||||||
|
|
||||||
|
<Materials />
|
||||||
|
|
||||||
|
<Trigger />
|
||||||
|
|
||||||
|
<Conveyor />
|
||||||
|
|
||||||
|
<Vehicles />
|
||||||
|
|
||||||
|
<RoboticArm />
|
||||||
|
|
||||||
|
<Machine />
|
||||||
|
|
||||||
|
<StorageUnit />
|
||||||
|
|
||||||
|
<Simulator />
|
||||||
|
|
||||||
|
</>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function Simulator() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Simulator
|
|
@ -0,0 +1,10 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function storageUnitInstance() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default storageUnitInstance
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react'
|
||||||
|
import StorageUnitInstance from './storageUnitInstance/storageUnitInstance'
|
||||||
|
|
||||||
|
function StorageUnitInstances() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<StorageUnitInstance />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StorageUnitInstances
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react'
|
||||||
|
import StorageUnitInstances from './instances/storageUnitInstances'
|
||||||
|
|
||||||
|
function StorageUnit() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<StorageUnitInstances />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StorageUnit
|
|
@ -0,0 +1,126 @@
|
||||||
|
import { useThree } from '@react-three/fiber'
|
||||||
|
import React, { useEffect } from 'react'
|
||||||
|
import { Object3D } from 'three';
|
||||||
|
import { useSubModuleStore } from '../../../../store/useModuleStore';
|
||||||
|
import { useLeftData, useTopData } from '../../../../store/visualization/useZone3DWidgetStore';
|
||||||
|
import { useEventsStore } from '../../../../store/simulation/useEventsStore';
|
||||||
|
import { useProductStore } from '../../../../store/simulation/useProductStore';
|
||||||
|
import { useSelectedProduct } from '../../../../store/simulation/useSimulationStore';
|
||||||
|
import { useSelectedAsset } from '../../../../store/simulation/useSimulationStore';
|
||||||
|
|
||||||
|
function TriggerConnector() {
|
||||||
|
const { gl, raycaster, scene } = useThree();
|
||||||
|
const { subModule } = useSubModuleStore();
|
||||||
|
const { setTop } = useTopData();
|
||||||
|
const { setLeft } = useLeftData();
|
||||||
|
const { getIsEventInProduct } = useProductStore();
|
||||||
|
const { getEventByModelUuid } = useEventsStore();
|
||||||
|
const { selectedProduct } = useSelectedProduct();
|
||||||
|
const { selectedAsset, setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
const canvasElement = gl.domElement;
|
||||||
|
|
||||||
|
let drag = false;
|
||||||
|
let isRightMouseDown = false;
|
||||||
|
|
||||||
|
const onMouseDown = (evt: MouseEvent) => {
|
||||||
|
if (selectedAsset) {
|
||||||
|
clearSelectedAsset();
|
||||||
|
}
|
||||||
|
if (evt.button === 2) {
|
||||||
|
isRightMouseDown = true;
|
||||||
|
drag = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMouseUp = (evt: MouseEvent) => {
|
||||||
|
if (evt.button === 2) {
|
||||||
|
isRightMouseDown = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onMouseMove = () => {
|
||||||
|
if (isRightMouseDown) {
|
||||||
|
drag = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRightClick = (evt: MouseEvent) => {
|
||||||
|
if (drag) return;
|
||||||
|
evt.preventDefault();
|
||||||
|
const canvasElement = gl.domElement;
|
||||||
|
if (!canvasElement) return;
|
||||||
|
|
||||||
|
let 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) {
|
||||||
|
let currentObject = intersects[0].object;
|
||||||
|
|
||||||
|
while (currentObject) {
|
||||||
|
if (currentObject.name === "Scene") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentObject = currentObject.parent as Object3D;
|
||||||
|
}
|
||||||
|
if (currentObject) {
|
||||||
|
const isInProduct = getIsEventInProduct(selectedProduct.productId, currentObject.uuid);
|
||||||
|
|
||||||
|
if (isInProduct) {
|
||||||
|
const event = getEventByModelUuid(currentObject.uuid);
|
||||||
|
if (event) {
|
||||||
|
setSelectedAsset(event)
|
||||||
|
const canvasRect = canvasElement.getBoundingClientRect();
|
||||||
|
const relativeX = evt.clientX - canvasRect.left;
|
||||||
|
const relativeY = evt.clientY - canvasRect.top;
|
||||||
|
|
||||||
|
setTop(relativeY);
|
||||||
|
setLeft(relativeX);
|
||||||
|
} else {
|
||||||
|
clearSelectedAsset()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const event = getEventByModelUuid(currentObject.uuid);
|
||||||
|
if (event) {
|
||||||
|
setSelectedAsset(event)
|
||||||
|
const canvasRect = canvasElement.getBoundingClientRect();
|
||||||
|
const relativeX = evt.clientX - canvasRect.left;
|
||||||
|
const relativeY = evt.clientY - canvasRect.top;
|
||||||
|
|
||||||
|
setTop(relativeY);
|
||||||
|
setLeft(relativeX);
|
||||||
|
} else {
|
||||||
|
clearSelectedAsset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearSelectedAsset()
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
if (subModule === 'simulations') {
|
||||||
|
canvasElement.addEventListener("mousedown", onMouseDown);
|
||||||
|
canvasElement.addEventListener("mouseup", onMouseUp);
|
||||||
|
canvasElement.addEventListener("mousemove", onMouseMove);
|
||||||
|
canvasElement.addEventListener('contextmenu', handleRightClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
canvasElement.removeEventListener("mousedown", onMouseDown);
|
||||||
|
canvasElement.removeEventListener("mouseup", onMouseUp);
|
||||||
|
canvasElement.removeEventListener("mousemove", onMouseMove);
|
||||||
|
canvasElement.removeEventListener('contextmenu', handleRightClick);
|
||||||
|
};
|
||||||
|
|
||||||
|
}, [gl, subModule, selectedProduct, selectedAsset]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TriggerConnector
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react'
|
||||||
|
import TriggerConnector from './connector/triggerConnector'
|
||||||
|
|
||||||
|
function Trigger() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<TriggerConnector />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Trigger
|
|
@ -125,7 +125,7 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
setZonesData(formattedData);
|
setZonesData(formattedData);
|
||||||
} catch (error) {}
|
} catch (error) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
GetZoneData();
|
GetZoneData();
|
||||||
|
@ -362,6 +362,10 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
"RotateY",
|
"RotateY",
|
||||||
"Delete",
|
"Delete",
|
||||||
]}
|
]}
|
||||||
|
onClick={(e) => {
|
||||||
|
setRightSelect(e);
|
||||||
|
setEditWidgetOptions(false);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ export const getSelect2dZoneData = async (
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${url_Backend_dwinzo}/api/v2/Zone/visualization/${ZoneId}?organization=${organization}`,
|
`${url_Backend_dwinzo}/api/v2/ZoneVisualization/${ZoneId}?organization=${organization}`,
|
||||||
{
|
{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
@ -1,170 +1,187 @@
|
||||||
import { create } from "zustand";
|
import { create } from 'zustand';
|
||||||
import { immer } from "zustand/middleware/immer";
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
interface ArmBotStore {
|
interface ArmBotStore {
|
||||||
armBots: ArmBotStatus[];
|
armBots: ArmBotStatus[];
|
||||||
|
|
||||||
addArmBot: (productId: string, event: RoboticArmEventSchema) => void;
|
addArmBot: (productId: string, event: RoboticArmEventSchema) => void;
|
||||||
removeArmBot: (modelUuid: string) => void;
|
removeArmBot: (modelUuid: string) => void;
|
||||||
|
updateArmBot: (
|
||||||
|
modelUuid: string,
|
||||||
|
updates: Partial<Omit<ArmBotStatus, 'modelUuid' | 'productId'>>
|
||||||
|
) => void;
|
||||||
|
|
||||||
updateArmBot: (
|
addCurrentAction: (modelUuid: string, actionUuid: string) => void;
|
||||||
modelUuid: string,
|
removeCurrentAction: (modelUuid: string) => void;
|
||||||
updates: Partial<Omit<ArmBotStatus, "modelUuid" | "productId">>
|
|
||||||
) => void;
|
|
||||||
|
|
||||||
addCurrentAction: (modelUuid: string, actionUuid: string) => void;
|
addAction: (modelUuid: string, action: RoboticArmPointSchema['actions'][number]) => void;
|
||||||
removeCurrentAction: (modelUuid: string) => void;
|
removeAction: (modelUuid: string, actionUuid: string) => void;
|
||||||
|
|
||||||
addAction: (
|
updateStartPoint: (modelUuid: string, actionUuid: string, startPoint: [number, number, number] | null) => void;
|
||||||
modelUuid: string,
|
updateEndPoint: (modelUuid: string, actionUuid: string, endPoint: [number, number, number] | null) => void;
|
||||||
action: RoboticArmPointSchema["actions"][number]
|
|
||||||
) => void;
|
|
||||||
removeAction: (modelUuid: string, actionUuid: string) => void;
|
|
||||||
|
|
||||||
setArmBotActive: (modelUuid: string, isActive: boolean) => void;
|
setArmBotActive: (modelUuid: string, isActive: boolean) => void;
|
||||||
|
|
||||||
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
|
||||||
getArmBotById: (modelUuid: string) => ArmBotStatus | undefined;
|
getArmBotById: (modelUuid: string) => ArmBotStatus | undefined;
|
||||||
getArmBotsByProduct: (productId: string) => ArmBotStatus[];
|
getArmBotsByProduct: (productId: string) => ArmBotStatus[];
|
||||||
getArmBotsByState: (state: string) => ArmBotStatus[];
|
getArmBotsByState: (state: string) => ArmBotStatus[];
|
||||||
getActiveArmBots: () => ArmBotStatus[];
|
getActiveArmBots: () => ArmBotStatus[];
|
||||||
getIdleArmBots: () => ArmBotStatus[];
|
getIdleArmBots: () => ArmBotStatus[];
|
||||||
getArmBotsByCurrentAction: (actionUuid: string) => ArmBotStatus[];
|
getArmBotsByCurrentAction: (actionUuid: string) => ArmBotStatus[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useArmBotStore = create<ArmBotStore>()(
|
export const useArmBotStore = create<ArmBotStore>()(
|
||||||
immer((set, get) => ({
|
immer((set, get) => ({
|
||||||
armBots: [],
|
armBots: [],
|
||||||
|
|
||||||
addArmBot: (productId, event) => {
|
addArmBot: (productId, event) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.armBots.push({
|
state.armBots.push({
|
||||||
...event,
|
...event,
|
||||||
productId,
|
productId,
|
||||||
isActive: false,
|
isActive: false,
|
||||||
idleTime: 0,
|
idleTime: 0,
|
||||||
activeTime: 0,
|
activeTime: 0,
|
||||||
state: "idle",
|
state: 'idle',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
removeArmBot: (modelUuid) => {
|
removeArmBot: (modelUuid) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.armBots = state.armBots.filter((a) => a.modelUuid !== modelUuid);
|
state.armBots = state.armBots.filter(a => a.modelUuid !== modelUuid);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateArmBot: (modelUuid, updates) => {
|
updateArmBot: (modelUuid, updates) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const armBot = state.armBots.find((a) => a.modelUuid === modelUuid);
|
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||||
if (armBot) {
|
if (armBot) {
|
||||||
Object.assign(armBot, updates);
|
Object.assign(armBot, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addCurrentAction: (modelUuid, actionUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||||
|
if (armBot) {
|
||||||
|
const action = armBot.point.actions.find(a => a.actionUuid === actionUuid);
|
||||||
|
if (action) {
|
||||||
|
armBot.currentAction = {
|
||||||
|
actionUuid: action.actionUuid,
|
||||||
|
actionName: action.actionName,
|
||||||
|
};
|
||||||
|
armBot.isActive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeCurrentAction: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||||
|
if (armBot) {
|
||||||
|
armBot.currentAction = undefined;
|
||||||
|
armBot.isActive = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addAction: (modelUuid, action) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||||
|
if (armBot) {
|
||||||
|
armBot.point.actions.push(action);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeAction: (modelUuid, actionUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||||
|
if (armBot) {
|
||||||
|
armBot.point.actions = armBot.point.actions.filter(a => a.actionUuid !== actionUuid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateStartPoint: (modelUuid, actionUuid, startPoint) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||||
|
if (armBot) {
|
||||||
|
const action = armBot.point.actions.find(a => a.actionUuid === actionUuid);
|
||||||
|
if (action) {
|
||||||
|
action.process.startPoint = startPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateEndPoint: (modelUuid, actionUuid, endPoint) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||||
|
if (armBot) {
|
||||||
|
const action = armBot.point.actions.find(a => a.actionUuid === actionUuid);
|
||||||
|
if (action) {
|
||||||
|
action.process.endPoint = endPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setArmBotActive: (modelUuid, isActive) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||||
|
if (armBot) {
|
||||||
|
armBot.isActive = isActive;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||||
|
if (armBot) {
|
||||||
|
armBot.activeTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||||
|
if (armBot) {
|
||||||
|
armBot.idleTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getArmBotById: (modelUuid) => {
|
||||||
|
return get().armBots.find(a => a.modelUuid === modelUuid);
|
||||||
|
},
|
||||||
|
|
||||||
|
getArmBotsByProduct: (productId) => {
|
||||||
|
return get().armBots.filter(a => a.productId === productId);
|
||||||
|
},
|
||||||
|
|
||||||
|
getArmBotsByState: (state) => {
|
||||||
|
return get().armBots.filter(a => a.state === state);
|
||||||
|
},
|
||||||
|
|
||||||
|
getActiveArmBots: () => {
|
||||||
|
return get().armBots.filter(a => a.isActive);
|
||||||
|
},
|
||||||
|
|
||||||
|
getIdleArmBots: () => {
|
||||||
|
return get().armBots.filter(a => !a.isActive && a.state === 'idle');
|
||||||
|
},
|
||||||
|
|
||||||
|
getArmBotsByCurrentAction: (actionUuid) => {
|
||||||
|
return get().armBots.filter(a => a.currentAction?.actionUuid === actionUuid);
|
||||||
}
|
}
|
||||||
});
|
}))
|
||||||
},
|
|
||||||
|
|
||||||
addCurrentAction: (modelUuid, actionUuid) => {
|
|
||||||
set((state) => {
|
|
||||||
const armBot = state.armBots.find((a) => a.modelUuid === modelUuid);
|
|
||||||
if (armBot) {
|
|
||||||
const action = armBot.point.actions.find(
|
|
||||||
(a) => a.actionUuid === actionUuid
|
|
||||||
);
|
|
||||||
if (action) {
|
|
||||||
armBot.currentAction = {
|
|
||||||
actionUuid: action.actionUuid,
|
|
||||||
actionName: action.actionName,
|
|
||||||
};
|
|
||||||
armBot.isActive = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
removeCurrentAction: (modelUuid) => {
|
|
||||||
set((state) => {
|
|
||||||
const armBot = state.armBots.find((a) => a.modelUuid === modelUuid);
|
|
||||||
if (armBot) {
|
|
||||||
armBot.currentAction = undefined;
|
|
||||||
armBot.isActive = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
addAction: (modelUuid, action) => {
|
|
||||||
set((state) => {
|
|
||||||
const armBot = state.armBots.find((a) => a.modelUuid === modelUuid);
|
|
||||||
if (armBot) {
|
|
||||||
armBot.point.actions.push(action);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
removeAction: (modelUuid, actionUuid) => {
|
|
||||||
set((state) => {
|
|
||||||
const armBot = state.armBots.find((a) => a.modelUuid === modelUuid);
|
|
||||||
if (armBot) {
|
|
||||||
armBot.point.actions = armBot.point.actions.filter(
|
|
||||||
(a) => a.actionUuid !== actionUuid
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
setArmBotActive: (modelUuid, isActive) => {
|
|
||||||
set((state) => {
|
|
||||||
const armBot = state.armBots.find((a) => a.modelUuid === modelUuid);
|
|
||||||
if (armBot) {
|
|
||||||
armBot.isActive = isActive;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
incrementActiveTime: (modelUuid, incrementBy) => {
|
|
||||||
set((state) => {
|
|
||||||
const armBot = state.armBots.find((a) => a.modelUuid === modelUuid);
|
|
||||||
if (armBot) {
|
|
||||||
armBot.activeTime += incrementBy;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
incrementIdleTime: (modelUuid, incrementBy) => {
|
|
||||||
set((state) => {
|
|
||||||
const armBot = state.armBots.find((a) => a.modelUuid === modelUuid);
|
|
||||||
if (armBot) {
|
|
||||||
armBot.idleTime += incrementBy;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
getArmBotById: (modelUuid) => {
|
|
||||||
return get().armBots.find((a) => a.modelUuid === modelUuid);
|
|
||||||
},
|
|
||||||
|
|
||||||
getArmBotsByProduct: (productId) => {
|
|
||||||
return get().armBots.filter((a) => a.productId === productId);
|
|
||||||
},
|
|
||||||
|
|
||||||
getArmBotsByState: (state) => {
|
|
||||||
return get().armBots.filter((a) => a.state === state);
|
|
||||||
},
|
|
||||||
|
|
||||||
getActiveArmBots: () => {
|
|
||||||
return get().armBots.filter((a) => a.isActive);
|
|
||||||
},
|
|
||||||
|
|
||||||
getIdleArmBots: () => {
|
|
||||||
return get().armBots.filter((a) => !a.isActive && a.state === "idle");
|
|
||||||
},
|
|
||||||
|
|
||||||
getArmBotsByCurrentAction: (actionUuid) => {
|
|
||||||
return get().armBots.filter(
|
|
||||||
(a) => a.currentAction?.actionUuid === actionUuid
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
import { create } from 'zustand';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
|
type MaterialsStore = {
|
||||||
|
materials: MaterialsSchema;
|
||||||
|
|
||||||
|
addMaterial: (material: MaterialSchema) => void;
|
||||||
|
removeMaterial: (materialId: string) => void;
|
||||||
|
updateMaterial: (materialId: string, updates: Partial<MaterialSchema>) => void;
|
||||||
|
|
||||||
|
setStartTime: (materialId: string, startTime: string) => void;
|
||||||
|
setEndTime: (materialId: string, endTime: string) => void;
|
||||||
|
setCost: (materialId: string, cost: number) => void;
|
||||||
|
setWeight: (materialId: string, weight: number) => void;
|
||||||
|
|
||||||
|
getMaterialById: (materialId: string) => MaterialSchema | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useMaterialStore = create<MaterialsStore>()(
|
||||||
|
immer((set, get) => ({
|
||||||
|
materials: [],
|
||||||
|
|
||||||
|
addMaterial: (material) => {
|
||||||
|
set((state) => {
|
||||||
|
state.materials.push(material);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeMaterial: (materialId) => {
|
||||||
|
set((state) => {
|
||||||
|
state.materials = state.materials.filter(m => m.materialId !== materialId);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateMaterial: (materialId, updates) => {
|
||||||
|
set((state) => {
|
||||||
|
const material = state.materials.find(m => m.materialId === materialId);
|
||||||
|
if (material) {
|
||||||
|
Object.assign(material, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setStartTime: (materialId, startTime) => {
|
||||||
|
set((state) => {
|
||||||
|
const material = state.materials.find(m => m.materialId === materialId);
|
||||||
|
if (material) material.startTime = startTime;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setEndTime: (materialId, endTime) => {
|
||||||
|
set((state) => {
|
||||||
|
const material = state.materials.find(m => m.materialId === materialId);
|
||||||
|
if (material) material.endTime = endTime;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setCost: (materialId, cost) => {
|
||||||
|
set((state) => {
|
||||||
|
const material = state.materials.find(m => m.materialId === materialId);
|
||||||
|
if (material) material.cost = cost;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setWeight: (materialId, weight) => {
|
||||||
|
set((state) => {
|
||||||
|
const material = state.materials.find(m => m.materialId === materialId);
|
||||||
|
if (material) material.weight = weight;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getMaterialById: (materialId) => {
|
||||||
|
return get().materials.find(m => m.materialId === materialId);
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
|
@ -48,8 +48,18 @@ type ProductsStore = {
|
||||||
updates: Partial<TriggerSchema>
|
updates: Partial<TriggerSchema>
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
|
// Renaming functions
|
||||||
|
renameProduct: (productId: string, newName: string) => void;
|
||||||
|
renameAction: (actionUuid: string, newName: string) => void;
|
||||||
|
renameTrigger: (triggerUuid: string, newName: string) => void;
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
getProductById: (productId: string) => { productName: string; productId: string; eventsData: EventsSchema[] } | undefined;
|
getProductById: (productId: string) => { productName: string; productId: string; eventsData: EventsSchema[] } | undefined;
|
||||||
|
getEventByModelUuid: (productId: string, modelUuid: string) => EventsSchema | undefined;
|
||||||
|
getPointByUuid: (productId: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
|
||||||
|
getActionByUuid: (productId: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
|
||||||
|
getTriggerByUuid: (productId: string, triggerUuid: string) => TriggerSchema | undefined;
|
||||||
|
getIsEventInProduct: (productId: string, modelUuid: string) => boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useProductStore = create<ProductsStore>()(
|
export const useProductStore = create<ProductsStore>()(
|
||||||
|
@ -331,9 +341,170 @@ export const useProductStore = create<ProductsStore>()(
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Renaming functions
|
||||||
|
renameProduct: (productId, newName) => {
|
||||||
|
set((state) => {
|
||||||
|
const product = state.products.find(p => p.productId === productId);
|
||||||
|
if (product) {
|
||||||
|
product.productName = newName;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
renameAction: (actionUuid, newName) => {
|
||||||
|
set((state) => {
|
||||||
|
for (const product of state.products) {
|
||||||
|
for (const event of product.eventsData) {
|
||||||
|
if ('points' in event) {
|
||||||
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
|
if (point.action && point.action.actionUuid === actionUuid) {
|
||||||
|
point.action.actionName = newName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ('point' in event) {
|
||||||
|
const point = (event as any).point;
|
||||||
|
if ('action' in point && point.action.actionUuid === actionUuid) {
|
||||||
|
point.action.actionName = newName;
|
||||||
|
return;
|
||||||
|
} else if ('actions' in point) {
|
||||||
|
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||||
|
if (action) {
|
||||||
|
action.actionName = newName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
renameTrigger: (triggerUuid, newName) => {
|
||||||
|
set((state) => {
|
||||||
|
for (const product of state.products) {
|
||||||
|
for (const event of product.eventsData) {
|
||||||
|
if ('points' in event) {
|
||||||
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
|
if (point.action && 'triggers' in point.action) {
|
||||||
|
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
||||||
|
if (trigger) {
|
||||||
|
trigger.triggerName = newName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ('point' in event) {
|
||||||
|
const point = (event as any).point;
|
||||||
|
if ('action' in point && 'triggers' in point.action) {
|
||||||
|
const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||||
|
if (trigger) {
|
||||||
|
trigger.triggerName = newName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if ('actions' in point) {
|
||||||
|
for (const action of point.actions) {
|
||||||
|
if ('triggers' in action) {
|
||||||
|
const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||||
|
if (trigger) {
|
||||||
|
trigger.triggerName = newName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
getProductById: (productId) => {
|
getProductById: (productId) => {
|
||||||
return get().products.find(p => p.productId === productId);
|
return get().products.find(p => p.productId === productId);
|
||||||
|
},
|
||||||
|
|
||||||
|
getEventByModelUuid: (productId, modelUuid) => {
|
||||||
|
const product = get().getProductById(productId);
|
||||||
|
if (!product) return undefined;
|
||||||
|
return product.eventsData.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
|
},
|
||||||
|
|
||||||
|
getPointByUuid: (productId, modelUuid, pointUuid) => {
|
||||||
|
const event = get().getEventByModelUuid(productId, modelUuid);
|
||||||
|
if (!event) return undefined;
|
||||||
|
|
||||||
|
if ('points' in event) {
|
||||||
|
return (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||||
|
} else if ('point' in event && (event as any).point.uuid === pointUuid) {
|
||||||
|
return (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
getActionByUuid: (productId, actionUuid) => {
|
||||||
|
const product = get().products.find(p => p.productId === productId);
|
||||||
|
if (!product) return undefined;
|
||||||
|
|
||||||
|
for (const event of product.eventsData) {
|
||||||
|
if ('points' in event) {
|
||||||
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
|
if (point.action?.actionUuid === actionUuid) {
|
||||||
|
return point.action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ('point' in event) {
|
||||||
|
const point = (event as any).point;
|
||||||
|
if ('action' in point && point.action?.actionUuid === actionUuid) {
|
||||||
|
return point.action;
|
||||||
|
} else if ('actions' in point) {
|
||||||
|
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||||
|
if (action) return action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
getTriggerByUuid: (productId, triggerUuid) => {
|
||||||
|
const product = get().products.find(p => p.productId === productId);
|
||||||
|
if (!product) return undefined;
|
||||||
|
|
||||||
|
for (const event of product.eventsData) {
|
||||||
|
if ('points' in event) {
|
||||||
|
for (const point of (event as ConveyorEventSchema).points) {
|
||||||
|
for (const trigger of point.action?.triggers || []) {
|
||||||
|
if (trigger.triggerUuid === triggerUuid) {
|
||||||
|
return trigger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ('point' in event) {
|
||||||
|
const point = (event as any).point;
|
||||||
|
if ('action' in point) {
|
||||||
|
for (const trigger of point.action?.triggers || []) {
|
||||||
|
if (trigger.triggerUuid === triggerUuid) {
|
||||||
|
return trigger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ('actions' in point) {
|
||||||
|
for (const action of point.actions) {
|
||||||
|
for (const trigger of action.triggers || []) {
|
||||||
|
if (trigger.triggerUuid === triggerUuid) {
|
||||||
|
return trigger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
getIsEventInProduct: (productId, modelUuid) => {
|
||||||
|
const product = get().getProductById(productId);
|
||||||
|
if (!product) return false;
|
||||||
|
return product.eventsData.some(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
import { create } from 'zustand';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
import * as THREE from 'three';
|
||||||
|
|
||||||
|
interface SelectedEventSphereState {
|
||||||
|
selectedEventSphere: THREE.Mesh | null;
|
||||||
|
setSelectedEventSphere: (mesh: THREE.Mesh | null) => void;
|
||||||
|
clearSelectedEventSphere: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSelectedEventSphere = create<SelectedEventSphereState>()(
|
||||||
|
immer((set) => ({
|
||||||
|
selectedEventSphere: null,
|
||||||
|
setSelectedEventSphere: (mesh) => {
|
||||||
|
set((state) => {
|
||||||
|
state.selectedEventSphere = mesh;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
clearSelectedEventSphere: () => {
|
||||||
|
set((state) => {
|
||||||
|
state.selectedEventSphere = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
interface SelectedEventDataState {
|
||||||
|
selectedEventData: { data: EventsSchema; selectedPoint: string } | undefined;
|
||||||
|
setSelectedEventData: (data: EventsSchema, selectedPoint: string) => void;
|
||||||
|
clearSelectedEventData: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSelectedEventData = create<SelectedEventDataState>()(
|
||||||
|
immer((set) => ({
|
||||||
|
selectedEventData: undefined,
|
||||||
|
setSelectedEventData: (data, selectedPoint) => {
|
||||||
|
set((state) => {
|
||||||
|
state.selectedEventData = { data, selectedPoint };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
clearSelectedEventData: () => {
|
||||||
|
set((state) => {
|
||||||
|
state.selectedEventData = undefined;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
interface SelectedAssetState {
|
||||||
|
selectedAsset: EventsSchema | undefined;
|
||||||
|
setSelectedAsset: (EventData: EventsSchema) => void;
|
||||||
|
clearSelectedAsset: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSelectedAsset = create<SelectedAssetState>()(
|
||||||
|
immer((set) => ({
|
||||||
|
selectedAsset: undefined,
|
||||||
|
setSelectedAsset: (EventData) => {
|
||||||
|
set((state) => {
|
||||||
|
state.selectedAsset = EventData;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
clearSelectedAsset: () => {
|
||||||
|
set((state) => {
|
||||||
|
state.selectedAsset = undefined;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
interface SelectedProductState {
|
||||||
|
selectedProduct: { productId: string; productName: string };
|
||||||
|
setSelectedProduct: (productId: string, productName: string) => void;
|
||||||
|
clearSelectedProduct: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSelectedProduct = create<SelectedProductState>()(
|
||||||
|
immer((set) => ({
|
||||||
|
selectedProduct: { productId: '', productName: '' },
|
||||||
|
setSelectedProduct: (productId, productName) => {
|
||||||
|
set((state) => {
|
||||||
|
state.selectedProduct.productId = productId;
|
||||||
|
state.selectedProduct.productName = productName;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
clearSelectedProduct: () => {
|
||||||
|
set((state) => {
|
||||||
|
state.selectedProduct.productId = '';
|
||||||
|
state.selectedProduct.productName = '';
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
|
@ -13,14 +13,17 @@ const useModuleStore = create<ModuleStore>((set) => ({
|
||||||
export default useModuleStore;
|
export default useModuleStore;
|
||||||
|
|
||||||
// New store for subModule
|
// New store for subModule
|
||||||
|
|
||||||
|
type SubModule = 'properties' | 'simulations' | 'mechanics' | 'analysis' | 'zoneProperties';
|
||||||
|
|
||||||
interface SubModuleStore {
|
interface SubModuleStore {
|
||||||
subModule: string;
|
subModule: SubModule;
|
||||||
setSubModule: (subModule: string) => void;
|
setSubModule: (subModule: SubModule) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useSubModuleStore = create<SubModuleStore>((set) => ({
|
const useSubModuleStore = create<SubModuleStore>((set) => ({
|
||||||
subModule: "properties", // Initial subModule state
|
subModule: "properties", // Initial subModule state
|
||||||
setSubModule: (subModule) => set({ subModule }), // Update subModule state
|
setSubModule: (value) => set({ subModule: value }), // Update subModule state
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export { useSubModuleStore };
|
export { useSubModuleStore };
|
||||||
|
|
|
@ -7,8 +7,8 @@ input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
border-radius: #{$border-radius-small};
|
border-radius: #{$border-radius-small};
|
||||||
outline: 2px solid var(--border-color);
|
outline: 1px solid var(--border-color);
|
||||||
outline-offset: -2px;
|
outline-offset: -1px;
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--input-text-color);
|
color: var(--input-text-color);
|
||||||
|
@ -30,6 +30,24 @@ input {
|
||||||
background-color: var(--background-color) !important;
|
background-color: var(--background-color) !important;
|
||||||
-webkit-box-shadow: 0 0 0px 1000px var(--background-color) inset !important;
|
-webkit-box-shadow: 0 0 0px 1000px var(--background-color) inset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File input specific style adjustments
|
||||||
|
&::file-selector-button {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--accent-color);
|
||||||
|
background-color: var(--background-color-secondary);
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
border-radius: #{$border-radius-small};
|
||||||
|
padding: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
// Hover effect for the file button
|
||||||
|
&:hover {
|
||||||
|
color: var(--primary-color);
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-value {
|
.input-value {
|
||||||
|
@ -712,3 +730,47 @@ input {
|
||||||
border: 1px solid var(--accent-color);
|
border: 1px solid var(--accent-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview-selection-with-upload-wrapper {
|
||||||
|
.input-header-container {
|
||||||
|
padding: 6px 12px;
|
||||||
|
@include flex-space-between;
|
||||||
|
.arrow-container {
|
||||||
|
transition: all 0.2s;
|
||||||
|
@include flex-center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.upload-custom-asset-button{
|
||||||
|
padding: 6px 12px;
|
||||||
|
@include flex-space-between;
|
||||||
|
.title{
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
input{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.upload-button{
|
||||||
|
width: 60%;
|
||||||
|
background: var(--highlight-accent-color);
|
||||||
|
color: var(--accent-color);
|
||||||
|
padding: 3px 6px;
|
||||||
|
border-radius: #{$border-radius-small};
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.canvas-wrapper {
|
||||||
|
height: 150px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
padding-right: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
.canvas-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: #{$border-radius-small};
|
||||||
|
background-color: var(--background-color-gray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
top: 32px;
|
top: 32px;
|
||||||
left: 8px;
|
left: 8px;
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
|
backdrop-filter: blur(150px);
|
||||||
border-radius: #{$border-radius-extra-large};
|
border-radius: #{$border-radius-extra-large};
|
||||||
box-shadow: #{$box-shadow-medium};
|
box-shadow: #{$box-shadow-medium};
|
||||||
z-index: #{$z-index-tools};
|
z-index: #{$z-index-tools};
|
||||||
|
@ -131,15 +132,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.widgets-wrapper {
|
.widgets-wrapper {
|
||||||
|
|
||||||
min-height: 50vh;
|
min-height: 50vh;
|
||||||
max-height: 60vh;
|
max-height: 60vh;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.widget-left-sideBar {
|
.widget-left-sideBar {
|
||||||
|
|
||||||
|
|
||||||
.widget2D {
|
.widget2D {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
|
@ -246,6 +244,7 @@
|
||||||
top: 32px;
|
top: 32px;
|
||||||
right: 8px;
|
right: 8px;
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
|
backdrop-filter: blur(150px);
|
||||||
border-radius: #{$border-radius-extra-large};
|
border-radius: #{$border-radius-extra-large};
|
||||||
box-shadow: #{$box-shadow-medium};
|
box-shadow: #{$box-shadow-medium};
|
||||||
z-index: #{$z-index-tools};
|
z-index: #{$z-index-tools};
|
||||||
|
@ -643,7 +642,7 @@
|
||||||
|
|
||||||
path {
|
path {
|
||||||
stroke: var(--accent-color);
|
stroke: var(--accent-color);
|
||||||
strokewidth: 1.5px;
|
stroke-width: 1.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -658,7 +657,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.machine-mechanics-content-container,
|
.machine-mechanics-content-container,
|
||||||
.simulations-container {
|
.simulations-container,
|
||||||
|
.event-proprties-wrapper {
|
||||||
max-height: calc(60vh - (47px - 35px));
|
max-height: calc(60vh - (47px - 35px));
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
@ -682,6 +682,52 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.global-props {
|
||||||
|
.property-list-container {
|
||||||
|
.property-item {
|
||||||
|
.value-field-container {
|
||||||
|
margin: 0;
|
||||||
|
input {
|
||||||
|
padding: 5px 4px;
|
||||||
|
}
|
||||||
|
.dropdown {
|
||||||
|
top: 4px;
|
||||||
|
right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-actions-details {
|
||||||
|
.selected-actions-header .input-value {
|
||||||
|
padding: 8px 12px;
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
.selected-actions-list {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
.eye-dropper-input-container{
|
||||||
|
padding: 6px 12px;
|
||||||
|
.regularDropdown-container {
|
||||||
|
padding: 5px 8px;
|
||||||
|
outline: 2px solid var(--border-color);
|
||||||
|
outline-offset: -2px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.value-field-container {
|
||||||
|
margin: 0;
|
||||||
|
input {
|
||||||
|
padding: 5px 4px;
|
||||||
|
}
|
||||||
|
.dropdown {
|
||||||
|
top: 4px;
|
||||||
|
right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.lists-main-container {
|
.lists-main-container {
|
||||||
margin: 2px 8px;
|
margin: 2px 8px;
|
||||||
width: calc(100% - 12px);
|
width: calc(100% - 12px);
|
||||||
|
@ -712,6 +758,7 @@
|
||||||
|
|
||||||
input {
|
input {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
outline: none;
|
||||||
accent-color: var(--accent-color);
|
accent-color: var(--accent-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1183,25 +1230,21 @@
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
max-height: 38px;
|
||||||
font-size: var(--font-size-regular);
|
font-size: var(--font-size-regular);
|
||||||
background: color-mix(in srgb,
|
background: color-mix(
|
||||||
var(--background-color) 40%,
|
in srgb,
|
||||||
transparent);
|
var(--background-color) 40%,
|
||||||
|
transparent
|
||||||
|
);
|
||||||
backdrop-filter: blur(5px);
|
backdrop-filter: blur(5px);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.3s ease;
|
transition: opacity 0.3s ease;
|
||||||
|
|
||||||
/* Added properties for ellipsis */
|
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
/* Necessary for multiline truncation */
|
|
||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 2;
|
||||||
/* Number of lines to show */
|
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
/* Box orientation for the ellipsis */
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
/* Hide overflowing content */
|
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
/* Add ellipsis for truncated content */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.asset-image {
|
.asset-image {
|
||||||
|
|
|
@ -25,7 +25,7 @@ interface ConveyorPointSchema {
|
||||||
action: {
|
action: {
|
||||||
actionUuid: string;
|
actionUuid: string;
|
||||||
actionName: string;
|
actionName: string;
|
||||||
actionType: "default" | "spawn" | "swap" | "despawn";
|
actionType: "default" | "spawn" | "swap" | "delay" | "despawn";
|
||||||
material: string;
|
material: string;
|
||||||
delay: number | "inherit";
|
delay: number | "inherit";
|
||||||
spawnInterval: number | "inherit";
|
spawnInterval: number | "inherit";
|
||||||
|
@ -59,7 +59,7 @@ interface RoboticArmPointSchema {
|
||||||
actionUuid: string;
|
actionUuid: string;
|
||||||
actionName: string;
|
actionName: string;
|
||||||
actionType: "pickAndPlace";
|
actionType: "pickAndPlace";
|
||||||
process: { startPoint: [number, number, number]; endPoint: [number, number, number] };
|
process: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; };
|
||||||
triggers: TriggerSchema[];
|
triggers: TriggerSchema[];
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ interface StoragePointSchema {
|
||||||
action: {
|
action: {
|
||||||
actionUuid: string;
|
actionUuid: string;
|
||||||
actionName: string;
|
actionName: string;
|
||||||
actionType: "storage";
|
actionType: "store";
|
||||||
materials: { materialName: string; materialId: string; }[];
|
materials: { materialName: string; materialId: string; }[];
|
||||||
storageCapacity: number;
|
storageCapacity: number;
|
||||||
};
|
};
|
||||||
|
@ -119,6 +119,8 @@ interface StorageEventSchema extends AssetEventSchema {
|
||||||
point: StoragePointSchema;
|
point: StoragePointSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PointsScheme = ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema;
|
||||||
|
|
||||||
type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema;
|
type EventsSchema = ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema;
|
||||||
|
|
||||||
type productsSchema = {
|
type productsSchema = {
|
||||||
|
@ -169,3 +171,16 @@ interface StorageUnitStatus extends StorageEventSchema {
|
||||||
activeTime: number;
|
activeTime: number;
|
||||||
currentLoad: number;
|
currentLoad: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MaterialSchema {
|
||||||
|
materialId: string;
|
||||||
|
materialName: string;
|
||||||
|
materialType: string;
|
||||||
|
isActive: boolean;
|
||||||
|
startTime?: string;
|
||||||
|
endTime?: string;
|
||||||
|
cost?: number;
|
||||||
|
weight?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type MaterialsSchema = MaterialSchema[];
|
Loading…
Reference in New Issue