2025-03-25 06:17:41 +00:00
|
|
|
import React, { useEffect, useRef, useState } from "react";
|
|
|
|
import {
|
|
|
|
AsileIcon,
|
|
|
|
CommentIcon,
|
|
|
|
CursorIcon,
|
2025-03-29 07:27:16 +00:00
|
|
|
DeleteIcon,
|
2025-03-25 06:17:41 +00:00
|
|
|
FloorIcon,
|
|
|
|
FreeMoveIcon,
|
2025-03-29 07:27:16 +00:00
|
|
|
MeasureToolIcon,
|
2025-03-25 06:17:41 +00:00
|
|
|
PenIcon,
|
|
|
|
PlayIcon,
|
|
|
|
SaveTemplateIcon,
|
|
|
|
WallIcon,
|
|
|
|
ZoneIcon,
|
|
|
|
} from "../icons/ExportToolsIcons";
|
|
|
|
import { ArrowIcon, TickIcon } from "../icons/ExportCommonIcons";
|
2025-03-31 05:41:44 +00:00
|
|
|
import useModuleStore, { useThreeDStore } from "../../store/useModuleStore";
|
2025-04-24 11:08:42 +00:00
|
|
|
import { handleSaveTemplate } from "../../modules/visualization/functions/handleSaveTemplate";
|
2025-03-25 06:17:41 +00:00
|
|
|
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
|
|
|
import useTemplateStore from "../../store/useTemplateStore";
|
feat: Implement Zustand stores for machine, simulation, storage unit, vehicle, and visualization management
- Added `useMachineStore` for managing machine statuses, including actions for adding, removing, and updating machines.
- Introduced `useSimulationStore` to handle product and event management with actions for adding, removing, and updating products and events.
- Created `useStorageUnitStore` for managing storage unit statuses, including load tracking and state updates.
- Developed `useVehicleStore` for vehicle management, including load and state updates.
- Implemented `useChartStore` for managing measurement data and visualization settings.
- Added `useDroppedObjectsStore` for handling dropped objects in visualization zones, including object manipulation actions.
- Created `useZone3DWidgetStore` for managing 3D widget data in zones, including position and rotation updates.
- Introduced `useZoneStore` for managing selected zone states and widget configurations.
2025-04-22 08:58:29 +00:00
|
|
|
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
2025-03-26 06:00:17 +00:00
|
|
|
import {
|
2025-03-29 04:54:47 +00:00
|
|
|
useActiveTool,
|
2025-03-26 06:00:17 +00:00
|
|
|
useAddAction,
|
2025-04-08 09:26:45 +00:00
|
|
|
useDeleteTool,
|
2025-03-29 04:54:47 +00:00
|
|
|
useDeletePointOrLine,
|
2025-03-29 07:28:54 +00:00
|
|
|
useRefTextUpdate,
|
2025-03-26 06:00:17 +00:00
|
|
|
useSelectedWallItem,
|
2025-04-02 13:19:18 +00:00
|
|
|
useSocketStore,
|
2025-03-26 06:00:17 +00:00
|
|
|
useToggleView,
|
2025-03-29 04:54:47 +00:00
|
|
|
useToolMode,
|
2025-04-09 12:13:44 +00:00
|
|
|
useActiveSubTool,
|
2025-05-13 11:20:50 +00:00
|
|
|
useShortcutStore,
|
2025-05-13 12:23:00 +00:00
|
|
|
} from "../../store/builder/store";
|
2025-03-29 07:27:16 +00:00
|
|
|
import useToggleStore from "../../store/useUIToggleStore";
|
2025-04-02 13:42:14 +00:00
|
|
|
import {
|
|
|
|
use3DWidget,
|
|
|
|
useFloatingWidget,
|
feat: Implement Zustand stores for machine, simulation, storage unit, vehicle, and visualization management
- Added `useMachineStore` for managing machine statuses, including actions for adding, removing, and updating machines.
- Introduced `useSimulationStore` to handle product and event management with actions for adding, removing, and updating products and events.
- Created `useStorageUnitStore` for managing storage unit statuses, including load tracking and state updates.
- Developed `useVehicleStore` for vehicle management, including load and state updates.
- Implemented `useChartStore` for managing measurement data and visualization settings.
- Added `useDroppedObjectsStore` for handling dropped objects in visualization zones, including object manipulation actions.
- Created `useZone3DWidgetStore` for managing 3D widget data in zones, including position and rotation updates.
- Introduced `useZoneStore` for managing selected zone states and widget configurations.
2025-04-22 08:58:29 +00:00
|
|
|
} from "../../store/visualization/useDroppedObjectsStore";
|
2025-03-25 06:17:41 +00:00
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
// Utility component
|
2025-05-14 13:09:47 +00:00
|
|
|
const ToolButton = ({
|
|
|
|
toolKey,
|
|
|
|
toolId,
|
|
|
|
icon: Icon,
|
|
|
|
active,
|
|
|
|
onClick,
|
|
|
|
tooltip,
|
|
|
|
}: any) => (
|
|
|
|
<button
|
|
|
|
key={toolKey} // used in rendering list
|
|
|
|
id={toolId}
|
|
|
|
className={`tool-button ${active ? "active" : ""}`}
|
|
|
|
onClick={onClick}
|
|
|
|
>
|
2025-05-13 10:07:06 +00:00
|
|
|
<div className="tooltip">{tooltip}</div>
|
2025-05-14 13:09:47 +00:00
|
|
|
<div className="tool" id={toolId}>
|
|
|
|
<Icon isActive={active} />
|
|
|
|
</div>
|
2025-05-13 10:07:06 +00:00
|
|
|
</button>
|
|
|
|
);
|
|
|
|
|
2025-03-25 06:17:41 +00:00
|
|
|
const Tools: React.FC = () => {
|
2025-05-13 10:07:06 +00:00
|
|
|
const { activeModule } = useModuleStore();
|
2025-03-31 05:41:44 +00:00
|
|
|
const { toggleThreeD, setToggleThreeD } = useThreeDStore();
|
2025-05-13 10:07:06 +00:00
|
|
|
const { isPlaying, setIsPlaying } = usePlayButtonStore();
|
2025-05-13 11:32:11 +00:00
|
|
|
const { showShortcuts } = useShortcutStore();
|
2025-05-13 10:07:06 +00:00
|
|
|
|
|
|
|
const {
|
|
|
|
activeTool,
|
|
|
|
setActiveTool,
|
|
|
|
setToolMode,
|
|
|
|
setAddAction,
|
|
|
|
setDeleteTool,
|
|
|
|
setDeletePointOrLine,
|
|
|
|
} = useStoreHooks();
|
|
|
|
|
|
|
|
const { setActiveSubTool, activeSubTool } = useActiveSubTool();
|
|
|
|
const { setSelectedWallItem } = useSelectedWallItem();
|
|
|
|
const { setRefTextUpdate } = useRefTextUpdate();
|
2025-03-31 05:41:44 +00:00
|
|
|
const { setToggleUI } = useToggleStore();
|
2025-05-13 10:07:06 +00:00
|
|
|
const { setToggleView, toggleView } = useToggleView();
|
2025-03-25 06:17:41 +00:00
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
const { addTemplate, templates } = useTemplateStore();
|
2025-03-25 06:17:41 +00:00
|
|
|
const { selectedZone } = useSelectedZoneStore();
|
2025-04-02 13:42:14 +00:00
|
|
|
const { floatingWidget } = useFloatingWidget();
|
|
|
|
const { widgets3D } = use3DWidget();
|
2025-05-13 10:07:06 +00:00
|
|
|
const { visualizationSocket } = useSocketStore();
|
2025-03-25 06:17:41 +00:00
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
const dropdownRef = useRef<HTMLButtonElement>(null);
|
|
|
|
const [openDrop, setOpenDrop] = useState(false);
|
2025-03-29 04:54:47 +00:00
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
// 1. Set UI toggles on initial render
|
2025-03-29 07:27:16 +00:00
|
|
|
useEffect(() => {
|
2025-03-31 05:41:44 +00:00
|
|
|
setToggleUI(
|
2025-05-13 10:07:06 +00:00
|
|
|
localStorage.getItem("navBarUiLeft") !== "false",
|
|
|
|
localStorage.getItem("navBarUiRight") !== "false"
|
2025-03-31 05:41:44 +00:00
|
|
|
);
|
2025-05-13 10:07:06 +00:00
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
2025-03-29 07:27:16 +00:00
|
|
|
}, []);
|
2025-05-09 05:16:18 +00:00
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
// 2. Update tool based on subtool and module
|
2025-03-25 06:17:41 +00:00
|
|
|
useEffect(() => {
|
|
|
|
setActiveTool(activeSubTool);
|
|
|
|
setActiveSubTool(activeSubTool);
|
2025-05-13 10:07:06 +00:00
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
2025-03-25 06:17:41 +00:00
|
|
|
}, [activeModule]);
|
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
// 3. Update tools behavior based on selected tool and view mode
|
|
|
|
useEffect(() => {
|
|
|
|
resetTools();
|
|
|
|
updateToolBehavior(activeTool, toggleView);
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, [activeTool, toggleView]);
|
2025-03-25 08:30:03 +00:00
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
// 4. Dropdown auto-close
|
2025-03-25 06:17:41 +00:00
|
|
|
useEffect(() => {
|
2025-05-13 10:07:06 +00:00
|
|
|
const handleClickOutside = (e: MouseEvent) => {
|
2025-03-25 06:17:41 +00:00
|
|
|
if (
|
|
|
|
dropdownRef.current &&
|
2025-05-13 10:07:06 +00:00
|
|
|
!dropdownRef.current.contains(e.target as Node)
|
2025-03-25 06:17:41 +00:00
|
|
|
) {
|
2025-05-13 10:07:06 +00:00
|
|
|
setOpenDrop(false);
|
2025-03-25 06:17:41 +00:00
|
|
|
}
|
|
|
|
};
|
2025-05-13 10:07:06 +00:00
|
|
|
document.addEventListener("mousedown", handleClickOutside);
|
|
|
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
2025-03-25 06:17:41 +00:00
|
|
|
}, []);
|
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
const resetTools = () => {
|
2025-03-29 04:54:47 +00:00
|
|
|
setToolMode(null);
|
2025-04-08 09:26:45 +00:00
|
|
|
setDeleteTool(false);
|
2025-03-29 04:54:47 +00:00
|
|
|
setAddAction(null);
|
|
|
|
setDeletePointOrLine(false);
|
2025-05-13 10:07:06 +00:00
|
|
|
setRefTextUpdate((prev) => prev - 1);
|
|
|
|
};
|
2025-03-29 04:54:47 +00:00
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
const updateToolBehavior = (tool: string, is2D: boolean) => {
|
|
|
|
switch (tool) {
|
2025-05-09 05:16:18 +00:00
|
|
|
case "cursor":
|
2025-03-29 04:54:47 +00:00
|
|
|
if (toggleView) {
|
2025-05-14 13:09:47 +00:00
|
|
|
setToolMode("move");
|
2025-03-29 04:54:47 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "draw-wall":
|
2025-05-13 10:07:06 +00:00
|
|
|
is2D && setToolMode("Wall");
|
2025-03-29 04:54:47 +00:00
|
|
|
break;
|
2025-03-29 07:27:16 +00:00
|
|
|
case "draw-aisle":
|
2025-05-13 10:07:06 +00:00
|
|
|
is2D && setToolMode("Aisle");
|
2025-03-29 04:54:47 +00:00
|
|
|
break;
|
2025-03-29 07:27:16 +00:00
|
|
|
case "draw-zone":
|
2025-05-13 10:07:06 +00:00
|
|
|
is2D && setToolMode("Zone");
|
2025-03-29 04:54:47 +00:00
|
|
|
break;
|
2025-03-29 07:27:16 +00:00
|
|
|
case "draw-floor":
|
2025-05-13 10:07:06 +00:00
|
|
|
is2D && setToolMode("Floor");
|
2025-03-29 04:54:47 +00:00
|
|
|
break;
|
2025-03-29 07:27:16 +00:00
|
|
|
case "measure":
|
2025-03-29 04:54:47 +00:00
|
|
|
setToolMode("MeasurementScale");
|
|
|
|
break;
|
|
|
|
case "Add pillar":
|
2025-05-13 10:07:06 +00:00
|
|
|
if (!is2D) setAddAction("pillar");
|
2025-03-29 04:54:47 +00:00
|
|
|
break;
|
2025-03-29 07:27:16 +00:00
|
|
|
case "delete":
|
2025-05-13 10:07:06 +00:00
|
|
|
is2D ? setDeletePointOrLine(true) : setDeleteTool(true);
|
2025-03-29 04:54:47 +00:00
|
|
|
break;
|
2025-05-13 10:07:06 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const toggle2D3D = () => {
|
2025-05-13 11:51:17 +00:00
|
|
|
const toggleTo2D = toggleView;
|
|
|
|
setToggleView(!toggleTo2D);
|
|
|
|
setToggleThreeD(toggleTo2D);
|
|
|
|
setToggleUI(toggleTo2D, toggleTo2D);
|
|
|
|
if (toggleTo2D) {
|
|
|
|
setSelectedWallItem(null);
|
|
|
|
setDeleteTool(false);
|
|
|
|
setAddAction(null);
|
|
|
|
}
|
|
|
|
setActiveTool("cursor");
|
|
|
|
setActiveSubTool("cursor");
|
2025-05-13 10:07:06 +00:00
|
|
|
setToggleUI(
|
|
|
|
localStorage.getItem("navBarUiLeft") !== "false",
|
|
|
|
localStorage.getItem("navBarUiRight") !== "false"
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const renderBuilderTools = () => (
|
|
|
|
<>
|
|
|
|
{!toggleThreeD && (
|
|
|
|
<div className="draw-tools">
|
|
|
|
<ToolButton
|
2025-05-14 13:09:47 +00:00
|
|
|
toolId="drawWall"
|
2025-05-13 10:07:06 +00:00
|
|
|
icon={WallIcon}
|
|
|
|
tooltip="draw wall (q)"
|
|
|
|
active={activeTool === "draw-wall"}
|
|
|
|
onClick={() => setActiveTool("draw-wall")}
|
|
|
|
/>
|
|
|
|
<ToolButton
|
2025-05-14 13:09:47 +00:00
|
|
|
toolId="drawZone"
|
2025-05-13 10:07:06 +00:00
|
|
|
icon={ZoneIcon}
|
|
|
|
tooltip="draw zone (e)"
|
|
|
|
active={activeTool === "draw-zone"}
|
|
|
|
onClick={() => setActiveTool("draw-zone")}
|
|
|
|
/>
|
|
|
|
<ToolButton
|
2025-05-14 13:09:47 +00:00
|
|
|
toolId="drawAisle"
|
2025-05-13 10:07:06 +00:00
|
|
|
icon={AsileIcon}
|
|
|
|
tooltip="draw aisle (r)"
|
|
|
|
active={activeTool === "draw-aisle"}
|
|
|
|
onClick={() => setActiveTool("draw-aisle")}
|
|
|
|
/>
|
|
|
|
<ToolButton
|
2025-05-14 13:09:47 +00:00
|
|
|
toolId="drawFloor"
|
2025-05-13 10:07:06 +00:00
|
|
|
icon={FloorIcon}
|
|
|
|
tooltip="draw floor (t)"
|
|
|
|
active={activeTool === "draw-floor"}
|
|
|
|
onClick={() => setActiveTool("draw-floor")}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
<div className="draw-tools">
|
|
|
|
<ToolButton
|
2025-05-14 13:09:47 +00:00
|
|
|
toolId="measureScale"
|
2025-05-13 10:07:06 +00:00
|
|
|
icon={MeasureToolIcon}
|
|
|
|
tooltip="measure scale (m)"
|
|
|
|
active={activeTool === "measure"}
|
|
|
|
onClick={() => setActiveTool("measure")}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
);
|
2025-03-29 04:54:47 +00:00
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
const renderSimulationTools = () => (
|
|
|
|
<div className="draw-tools">
|
|
|
|
<ToolButton
|
2025-05-14 13:09:47 +00:00
|
|
|
toolId="pen"
|
2025-05-13 10:07:06 +00:00
|
|
|
icon={PenIcon}
|
|
|
|
tooltip="pen"
|
|
|
|
active={activeTool === "pen"}
|
|
|
|
onClick={() => setActiveTool("pen")}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
|
|
|
const renderVisualizationTools = () => (
|
|
|
|
<div className="draw-tools">
|
|
|
|
<ToolButton
|
2025-05-14 13:09:47 +00:00
|
|
|
toolId="saveTemplate"
|
2025-05-13 10:07:06 +00:00
|
|
|
icon={SaveTemplateIcon}
|
|
|
|
tooltip="save template"
|
|
|
|
active={false}
|
|
|
|
onClick={() =>
|
|
|
|
handleSaveTemplate({
|
|
|
|
addTemplate,
|
|
|
|
floatingWidget,
|
|
|
|
widgets3D,
|
|
|
|
selectedZone,
|
|
|
|
templates,
|
|
|
|
visualizationSocket,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
|
|
|
|
const renderModeSwitcher = () => (
|
|
|
|
<button
|
2025-05-14 13:09:47 +00:00
|
|
|
id="toggle-threed-button"
|
2025-05-13 10:07:06 +00:00
|
|
|
className={`toggle-threed-button${toggleThreeD ? " toggled" : ""}`}
|
|
|
|
onClick={toggle2D3D}
|
|
|
|
>
|
|
|
|
<div className="tooltip">toggle view (tab)</div>
|
|
|
|
<div className={`toggle-option${!toggleThreeD ? " active" : ""}`}>2d</div>
|
|
|
|
<div className={`toggle-option${toggleThreeD ? " active" : ""}`}>3d</div>
|
|
|
|
</button>
|
|
|
|
);
|
|
|
|
|
|
|
|
const getIconByTool = (tool: string) => {
|
|
|
|
switch (tool) {
|
|
|
|
case "cursor":
|
|
|
|
return CursorIcon;
|
|
|
|
case "free-hand":
|
|
|
|
return FreeMoveIcon;
|
|
|
|
case "delete":
|
|
|
|
return DeleteIcon;
|
2025-03-29 04:54:47 +00:00
|
|
|
default:
|
2025-05-13 10:07:06 +00:00
|
|
|
return CursorIcon;
|
2025-03-29 04:54:47 +00:00
|
|
|
}
|
2025-05-13 10:07:06 +00:00
|
|
|
};
|
2025-03-29 04:54:47 +00:00
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
const getTooltipShortcut = (tool: string) => {
|
|
|
|
switch (tool) {
|
|
|
|
case "cursor":
|
|
|
|
return "v";
|
|
|
|
case "free-hand":
|
|
|
|
return "h";
|
|
|
|
case "delete":
|
|
|
|
return "x";
|
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const getIconComponent = (option: string) => {
|
|
|
|
switch (option) {
|
|
|
|
case "cursor":
|
|
|
|
return <CursorIcon isActive={false} />;
|
|
|
|
case "free-hand":
|
|
|
|
return <FreeMoveIcon isActive={false} />;
|
|
|
|
case "delete":
|
|
|
|
return <DeleteIcon isActive={false} />;
|
|
|
|
default:
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
2025-03-29 04:54:47 +00:00
|
|
|
|
2025-03-25 06:17:41 +00:00
|
|
|
return (
|
2025-05-13 11:32:11 +00:00
|
|
|
<div className={`tools-container ${showShortcuts ? "visible" : ""}`}>
|
2025-05-13 10:07:06 +00:00
|
|
|
<div className="activeDropicon">
|
|
|
|
{/* Tool Picker (cursor, delete, etc.) */}
|
|
|
|
{["cursor", "free-hand", "delete"].map(
|
|
|
|
(tool) =>
|
|
|
|
activeSubTool === tool && (
|
|
|
|
<ToolButton
|
|
|
|
key={tool}
|
2025-05-14 13:09:47 +00:00
|
|
|
toolId={tool}
|
2025-05-13 10:07:06 +00:00
|
|
|
icon={getIconByTool(tool)}
|
|
|
|
tooltip={`${tool} (${getTooltipShortcut(tool)})`}
|
|
|
|
active={activeTool === tool}
|
|
|
|
onClick={() => setActiveTool(tool)}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
)}
|
|
|
|
{/* Dropdown Menu */}
|
|
|
|
{activeModule !== "visualization" && (
|
|
|
|
<button
|
2025-05-14 13:09:47 +00:00
|
|
|
id="drop-down-button"
|
2025-05-13 10:07:06 +00:00
|
|
|
className="drop-down-option-button"
|
|
|
|
ref={dropdownRef}
|
|
|
|
onClick={() => setOpenDrop(!openDrop)}
|
|
|
|
>
|
|
|
|
<ArrowIcon />
|
|
|
|
{openDrop && (
|
|
|
|
<div className="drop-down-container">
|
|
|
|
{["cursor", "free-hand", "delete"].map((option) => (
|
|
|
|
<button
|
|
|
|
key={option}
|
2025-05-15 05:00:37 +00:00
|
|
|
id={`${option}-tool`}
|
2025-05-13 10:07:06 +00:00
|
|
|
className="option-list"
|
|
|
|
onClick={() => {
|
|
|
|
setActiveTool(option);
|
|
|
|
setActiveSubTool(option);
|
|
|
|
setOpenDrop(false);
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<div className="active-option">
|
|
|
|
{activeSubTool === option && <TickIcon />}
|
2025-05-02 12:09:11 +00:00
|
|
|
</div>
|
2025-05-13 10:07:06 +00:00
|
|
|
{getIconComponent(option)}
|
|
|
|
<div className="option">{option}</div>
|
|
|
|
</button>
|
|
|
|
))}
|
2025-05-02 12:09:11 +00:00
|
|
|
</div>
|
2025-03-31 09:22:06 +00:00
|
|
|
)}
|
2025-05-13 10:07:06 +00:00
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="split"></div>
|
|
|
|
{activeModule === "builder" && renderBuilderTools()}
|
|
|
|
{activeModule === "simulation" && renderSimulationTools()}
|
|
|
|
{activeModule === "visualization" && renderVisualizationTools()}
|
|
|
|
|
|
|
|
<div className="split"></div>
|
|
|
|
<div className="general-options">
|
|
|
|
<ToolButton
|
2025-05-14 13:09:47 +00:00
|
|
|
toolId="comment"
|
2025-05-13 10:07:06 +00:00
|
|
|
icon={CommentIcon}
|
|
|
|
tooltip="comment"
|
|
|
|
active={activeTool === "comment"}
|
|
|
|
onClick={() => setActiveTool("comment")}
|
|
|
|
/>
|
|
|
|
{toggleThreeD && (
|
|
|
|
<ToolButton
|
2025-05-14 13:09:47 +00:00
|
|
|
toolId="play"
|
2025-05-13 10:07:06 +00:00
|
|
|
icon={PlayIcon}
|
|
|
|
tooltip="play (ctrl + p)"
|
|
|
|
active={activeTool === "play"}
|
|
|
|
onClick={() => setIsPlaying(!isPlaying)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{activeModule === "builder" && (
|
2025-03-27 05:25:44 +00:00
|
|
|
<>
|
2025-05-13 10:07:06 +00:00
|
|
|
<div className="split"></div>
|
|
|
|
{renderModeSwitcher()}
|
2025-03-27 05:25:44 +00:00
|
|
|
</>
|
2025-03-26 06:00:17 +00:00
|
|
|
)}
|
2025-05-13 10:07:06 +00:00
|
|
|
</div>
|
2025-03-25 06:17:41 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2025-05-13 10:07:06 +00:00
|
|
|
// Extracted common store logic
|
|
|
|
const useStoreHooks = () => {
|
|
|
|
return {
|
|
|
|
...useActiveTool(),
|
|
|
|
...useToolMode(),
|
|
|
|
...useDeleteTool(),
|
|
|
|
...useAddAction(),
|
|
|
|
...useDeletePointOrLine(),
|
|
|
|
...useRefTextUpdate(),
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2025-03-25 06:17:41 +00:00
|
|
|
export default Tools;
|