diff --git a/app/src/components/footer/Footer.tsx b/app/src/components/footer/Footer.tsx
index 737ee26..fc16956 100644
--- a/app/src/components/footer/Footer.tsx
+++ b/app/src/components/footer/Footer.tsx
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useEffect, useState } from "react";
import { HelpIcon } from "../icons/DashboardIcon";
import { useLogger } from "../ui/log/LoggerContext";
import { GetLogIcon } from "./getLogIcons";
@@ -8,10 +8,13 @@ import {
CurserRightIcon,
} from "../icons/LogIcons";
import ShortcutHelper from "./shortcutHelper";
-import useVersionHistoryVisibleStore, { useShortcutStore } from "../../store/builder/store";
+import useVersionHistoryVisibleStore, {
+ useShortcutStore,
+} from "../../store/builder/store";
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
import useModuleStore, { useSubModuleStore } from "../../store/useModuleStore";
import { useVersionContext } from "../../modules/builder/version/versionContext";
+import { mouseActionHelper } from "../../utils/mouseUtils/mouseHelper";
const Footer: React.FC = () => {
const { logs, setIsLogListVisible } = useLogger();
@@ -25,28 +28,45 @@ const Footer: React.FC = () => {
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
+ const [notes, setNotes] = useState({
+ Leftnote: "",
+ Middlenote: "",
+ Rightnote: "",
+ });
+
+ useEffect(() => {
+ const cleanup = mouseActionHelper(setNotes);
+ return () => cleanup();
+ }, []);
+
+ const mouseButtons = [
+ {
+ icon: ,
+ label: notes.Leftnote !== "" ? notes.Leftnote : "Pan",
+ mouse: "left",
+ },
+ {
+ icon: ,
+ label: notes.Middlenote !== "" ? notes.Middlenote : "Scroll Zoom",
+ mouse: "middle",
+ },
+ {
+ icon: ,
+ label: notes.Rightnote !== "" ? notes.Rightnote : "Orbit / Cancel action",
+ mouse: "right",
+ },
+ ];
+
return (
-
-
-
+ {mouseButtons.map(({ icon, label, mouse }) => (
+
-
Selection
-
-
-
-
-
-
-
Pan/Context Menu
-
+ ))}
@@ -68,12 +88,15 @@ const Footer: React.FC = () => {
)}
-
{
- setVersionHistoryVisible(true);
- setSubModule("properties");
- setActiveModule('builder');
- }}>
- {(selectedVersion?.version) ?? 'v 0.0.0'}
+
{
+ setVersionHistoryVisible(true);
+ setSubModule("properties");
+ setActiveModule("builder");
+ }}
+ >
+ {selectedVersion?.version ?? "v 0.0.0"}
@@ -83,8 +106,9 @@ const Footer: React.FC = () => {
{!isPlaying && (
diff --git a/app/src/modules/builder/line/line.tsx b/app/src/modules/builder/line/line.tsx
index cc53b9d..2eb05dc 100644
--- a/app/src/modules/builder/line/line.tsx
+++ b/app/src/modules/builder/line/line.tsx
@@ -9,6 +9,7 @@ import * as Constants from '../../../types/world/worldConstants';
import { useVersionContext } from '../version/versionContext';
import { useParams } from 'react-router-dom';
import { getUserData } from '../../../functions/getUserData';
+import { handleCanvasCursors } from '../../../utils/mouseUtils/handleCanvasCursors';
// import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
// import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
@@ -23,7 +24,7 @@ interface LineProps {
function Line({ points }: Readonly
) {
const [isHovered, setIsHovered] = useState(false);
- const { raycaster, camera, pointer, gl } = useThree();
+ const { raycaster, camera, pointer } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const [isDeletable, setIsDeletable] = useState(false);
const { socket } = useSocketStore();
@@ -213,7 +214,7 @@ function Line({ points }: Readonly) {
});
}
}
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
}
}
@@ -224,7 +225,7 @@ function Line({ points }: Readonly) {
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
- gl.domElement.style.cursor = 'move';
+ handleCanvasCursors('grabbing');
const positionWithOffset = new THREE.Vector3().addVectors(hit, dragOffset);
const start = new THREE.Vector3(...points[0].position);
@@ -269,7 +270,7 @@ function Line({ points }: Readonly) {
const handleDragEnd = (points: [Point, Point]) => {
if (toolMode !== 'move' || !dragOffset) return;
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
setDragOffset(null);
if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
const updatedWalls1 = getWallsByPointId(points[0].pointUuid);
@@ -377,14 +378,14 @@ function Line({ points }: Readonly) {
setHoveredLine(points);
setIsHovered(true)
if (toolMode === 'move' && !hoveredPoint) {
- gl.domElement.style.cursor = 'pointer';
+ handleCanvasCursors('grab');
}
}
}}
onPointerOut={() => {
if (hoveredLine) {
setHoveredLine(null);
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
}
setIsHovered(false)
}}
diff --git a/app/src/modules/builder/point/point.tsx b/app/src/modules/builder/point/point.tsx
index 73dec77..c6ed85a 100644
--- a/app/src/modules/builder/point/point.tsx
+++ b/app/src/modules/builder/point/point.tsx
@@ -20,10 +20,11 @@ import { useSceneContext } from '../../scene/sceneContext';
// import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
import { getUserData } from '../../../functions/getUserData';
+import { handleCanvasCursors } from '../../../utils/mouseUtils/handleCanvasCursors';
function Point({ point }: { readonly point: Point }) {
const materialRef = useRef(null);
- const { raycaster, camera, pointer, gl } = useThree();
+ const { raycaster, camera, pointer } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const [isHovered, setIsHovered] = useState(false);
const [dragOffset, setDragOffset] = useState(null);
@@ -44,7 +45,7 @@ function Point({ point }: { readonly point: Point }) {
const colors = getColor(point);
useEffect(() => {
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
}, [toolMode])
function getColor(point: Point) {
@@ -114,7 +115,7 @@ function Point({ point }: { readonly point: Point }) {
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
- gl.domElement.style.cursor = 'move';
+ handleCanvasCursors('grabbing');
const positionWithOffset = new THREE.Vector3().addVectors(hit, dragOffset);
const newPosition: [number, number, number] = [positionWithOffset.x, positionWithOffset.y, positionWithOffset.z];
@@ -152,7 +153,7 @@ function Point({ point }: { readonly point: Point }) {
};
const handleDragEnd = (point: Point) => {
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
setDragOffset(null);
if (toolMode !== 'move') return;
if (point.pointType === 'Aisle') {
@@ -396,7 +397,7 @@ function Point({ point }: { readonly point: Point }) {
});
}
}
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
}
}
@@ -431,14 +432,14 @@ function Point({ point }: { readonly point: Point }) {
setHoveredPoint(point);
setIsHovered(true);
if (toolMode === 'move') {
- gl.domElement.style.cursor = 'pointer';
+ handleCanvasCursors('grab');
}
}
}}
onPointerOut={() => {
if (hoveredPoint) {
setHoveredPoint(null);
- gl.domElement.style.cursor = 'default';
+ handleCanvasCursors('default');
}
setIsHovered(false)
}}
diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx
index bd4e2bc..b257521 100644
--- a/app/src/pages/Project.tsx
+++ b/app/src/pages/Project.tsx
@@ -27,7 +27,7 @@ import { getVersionHistoryApi } from "../services/factoryBuilder/versionControl/
import { useVersionHistoryStore } from "../store/builder/useVersionHistoryStore";
import { VersionProvider } from "../modules/builder/version/versionContext";
import { sharedWithMeProjects } from "../services/dashboard/sharedWithMeProject";
-import { handleCanvasCursors } from "../utils/handleCanvasCursors";
+import { handleCanvasCursors } from "../utils/mouseUtils/handleCanvasCursors";
const Project: React.FC = () => {
let navigate = useNavigate();
@@ -134,7 +134,6 @@ const Project: React.FC = () => {
useEffect(() => {
handleCanvasCursors(activeTool);
- console.log('activeTool: ', activeTool);
}, [activeTool]);
return (
diff --git a/app/src/styles/scene/cursors.scss b/app/src/styles/scene/cursors.scss
index cef9b92..43f3078 100644
--- a/app/src/styles/scene/cursors.scss
+++ b/app/src/styles/scene/cursors.scss
@@ -45,3 +45,9 @@ $cursor-grabing: url("../../assets/cursors/close.svg") 8 8, default;
}
}
+.scene-container.hand-closed {
+ canvas {
+ cursor: $cursor-grabing !important;
+ }
+}
+
diff --git a/app/src/utils/handleCanvasCursors.ts b/app/src/utils/mouseUtils/handleCanvasCursors.ts
similarity index 85%
rename from app/src/utils/handleCanvasCursors.ts
rename to app/src/utils/mouseUtils/handleCanvasCursors.ts
index 72e2bd6..5bad3ae 100644
--- a/app/src/utils/handleCanvasCursors.ts
+++ b/app/src/utils/mouseUtils/handleCanvasCursors.ts
@@ -3,14 +3,19 @@ export const handleCanvasCursors = (name: string) => {
if (!canvas) return;
const cursorMap: Record = {
+ default: '',
'draw-wall': 'draw',
'draw-aisle': 'draw',
'draw-zone': 'draw',
'draw-floor': 'draw',
measure: 'measure',
delete: 'pointer',
+ pointer: 'pointer',
+ grab: 'hand',
+ grabbing: 'hand-closed',
pen: 'pen',
'free-hand': 'hand',
+ move: 'move',
// Add more mappings as needed
};
diff --git a/app/src/utils/mouseUtils/mouseHelper.ts b/app/src/utils/mouseUtils/mouseHelper.ts
new file mode 100644
index 0000000..94be50e
--- /dev/null
+++ b/app/src/utils/mouseUtils/mouseHelper.ts
@@ -0,0 +1,46 @@
+const actionNotes: Record = {
+ 'left+CONTROL': 'Box Select',
+ 'left+SHIFT': 'Multi Select',
+ 'middle+CONTROL': 'Zoom In',
+};
+
+export function mouseActionHelper(
+ onUpdate: (notes: {
+ Leftnote: string;
+ Middlenote: string;
+ Rightnote: string;
+ }) => void
+) {
+ const activeKeys = new Set();
+
+ function updateNotesFromKeys() {
+ const sortedKeys = Array.from(activeKeys).sort();
+ const leftKey = ['left', ...sortedKeys].join('+');
+ const middleKey = ['middle', ...sortedKeys].join('+');
+ const rightKey = ['right', ...sortedKeys].join('+');
+
+ onUpdate({
+ Leftnote: actionNotes[leftKey] || '',
+ Middlenote: actionNotes[middleKey] || '',
+ Rightnote: actionNotes[rightKey] || '',
+ });
+ }
+
+ function handleKeyDown(event: KeyboardEvent) {
+ activeKeys.add(event.key.toUpperCase());
+ updateNotesFromKeys();
+ }
+
+ function handleKeyUp(event: KeyboardEvent) {
+ activeKeys.delete(event.key.toUpperCase());
+ updateNotesFromKeys();
+ }
+
+ window.addEventListener('keydown', handleKeyDown);
+ window.addEventListener('keyup', handleKeyUp);
+
+ return () => {
+ window.removeEventListener('keydown', handleKeyDown);
+ window.removeEventListener('keyup', handleKeyUp);
+ };
+}