From 492985a19c9f9310f5850b36f95dc85f55690273 Mon Sep 17 00:00:00 2001 From: Gomathi9520 Date: Fri, 11 Apr 2025 17:26:03 +0530 Subject: [PATCH] vertical move updated --- app/package-lock.json | 60 +++- app/package.json | 1 + .../sidebarLeft/visualization/Templates.tsx | 4 +- .../ui/componets/Dropped3dWidget.tsx | 319 +++++++++++------- .../ui/componets/RealTimeVisulization.tsx | 1 - 5 files changed, 248 insertions(+), 137 deletions(-) diff --git a/app/package-lock.json b/app/package-lock.json index 8be748e..5d92f68 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -48,6 +48,7 @@ "zustand": "^5.0.0-rc.2" }, "devDependencies": { + "@types/html2canvas": "^1.0.0", "@types/node": "^22.9.1", "@types/three": "^0.169.0", "axios": "^1.8.4", @@ -2020,7 +2021,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -2032,7 +2033,7 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -4135,6 +4136,26 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@testing-library/jest-dom": { "version": "5.17.0", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", @@ -4246,25 +4267,25 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true + "devOptional": true }, "node_modules/@turf/along": { "version": "7.2.0", @@ -6470,6 +6491,17 @@ "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" }, + "node_modules/@types/html2canvas": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/html2canvas/-/html2canvas-1.0.0.tgz", + "integrity": "sha512-BJpVf+FIN9UERmzhbtUgpXj6XBZpG67FMgBLLoj9HZKd9XifcCpSV+UnFcwTZfEyun4U/KmCrrVOG7829L589w==", + "deprecated": "This is a stub types definition. html2canvas provides its own type definitions, so you do not need this installed.", + "dev": true, + "license": "MIT", + "dependencies": { + "html2canvas": "*" + } + }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", @@ -9007,7 +9039,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "node_modules/cross-env": { "version": "7.0.3", @@ -9884,7 +9916,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.3.1" } @@ -15247,7 +15279,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true }, "node_modules/makeerror": { "version": "1.0.12", @@ -20715,7 +20747,7 @@ "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, + "devOptional": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -20758,7 +20790,7 @@ "version": "8.3.4", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, + "devOptional": true, "dependencies": { "acorn": "^8.11.0" }, @@ -20770,7 +20802,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true }, "node_modules/tsconfig-paths": { "version": "3.15.0", @@ -21266,7 +21298,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "devOptional": true }, "node_modules/v8-to-istanbul": { "version": "8.1.1", @@ -22325,7 +22357,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } diff --git a/app/package.json b/app/package.json index ce5c7d3..e555d5f 100644 --- a/app/package.json +++ b/app/package.json @@ -70,6 +70,7 @@ ] }, "devDependencies": { + "@types/html2canvas": "^1.0.0", "@types/node": "^22.9.1", "@types/three": "^0.169.0", "axios": "^1.8.4", diff --git a/app/src/components/layout/sidebarLeft/visualization/Templates.tsx b/app/src/components/layout/sidebarLeft/visualization/Templates.tsx index efcbcaf..f8f91e4 100644 --- a/app/src/components/layout/sidebarLeft/visualization/Templates.tsx +++ b/app/src/components/layout/sidebarLeft/visualization/Templates.tsx @@ -91,10 +91,10 @@ const Templates = () => {
handleLoadTemplate(template)} + > {template?.snapshot && ( -
+
handleLoadTemplate(template)}> {`${template.name}(); + const [horizontalX, setHorizontalX] = useState(); + const [horizontalZ, setHorizontalZ] = useState(); const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || []; useEffect(() => { @@ -177,26 +179,30 @@ export default function Dropped3dWidgets() { }; const onDrop = (event: any) => { - event.preventDefault(); event.stopPropagation(); - + hasEntered.current = false; - + const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; - + const newWidget = createdWidgetRef.current; if (!newWidget || !widgetSelect.startsWith("ui")) return; - + // ✅ Extract 2D drop position - const [x, , z] = newWidget.position; - + let [x, y, z] = newWidget.position; + + // ✅ Clamp Y to at least 0 + y = Math.max(y, 0); + newWidget.position = [x, y, z]; + // ✅ Prepare polygon from selectedZone.points const points3D = selectedZone.points as Array<[number, number, number]>; const zonePolygonXZ = points3D.map(([x, , z]) => [x, z] as [number, number]); - + const isInside = isPointInPolygon([x, z], zonePolygonXZ); + // ✅ Remove temp widget const prevWidgets = useZoneWidgetStore.getState().zoneWidgetData[selectedZone.zoneId] || []; const cleanedWidgets = prevWidgets.filter(w => w.id !== newWidget.id); @@ -206,26 +212,29 @@ export default function Dropped3dWidgets() { [selectedZone.zoneId]: cleanedWidgets, }, })); + + // (Optional) Prevent adding if dropped outside zone // if (!isInside) { - // createdWidgetRef.current = null; - // return; // Stop here + // return; // } - // ✅ Add widget if inside polygon + + // ✅ Add widget addWidget(selectedZone.zoneId, newWidget); - + const add3dWidget = { organization, widget: newWidget, zoneId: selectedZone.zoneId, }; - + if (visualizationSocket) { visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget); } - + createdWidgetRef.current = null; }; + canvasElement.addEventListener("dragenter", handleDragEnter); @@ -331,28 +340,40 @@ export default function Dropped3dWidgets() { return inside; } const [prevX, setPrevX] = useState(0); - + useEffect(() => { const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; const handleMouseDown = (event: MouseEvent) => { if (!rightClickSelected || !rightSelect) return; + const selectedZoneId = Object.keys(zoneWidgetData).find( + (zoneId: string) => + zoneWidgetData[zoneId].some( + (widget: WidgetData) => widget.id === rightClickSelected + ) + ); + if (!selectedZoneId) return; + const selectedWidget = zoneWidgetData[selectedZoneId].find( + (widget: WidgetData) => widget.id === rightClickSelected + ); + if (!selectedWidget) return + // let points = []; + // points.push(new THREE.Vector3(0, 0, 0)); + // points.push(new THREE.Vector3(0, selectedWidget.position[1], 0)); + // const newgeometry = new THREE.BufferGeometry().setFromPoints(points); + // let vector = new THREE.Vector3(); + // camera.getWorldDirection(vector); + // let cameraDirection = vector; + // let newPlane = new THREE.Plane(cameraDirection); + // floorPlanesVertical = newPlane; + // setFloorPlanesVertical(newPlane); + // const intersect1 = raycaster?.ray?.intersectPlane( + // floorPlanesVertical, + // planeIntersect.current + // ); + + // setintersectcontextmenu(intersect1.y); - const cameraDirection = new THREE.Vector3(); - camera.getWorldDirection(cameraDirection); - - // Plane normal should be perpendicular to screen (XZ move), so use screen right direction - const right = new THREE.Vector3(); - camera.getWorldDirection(cameraDirection); - cameraDirection.y = 0; - cameraDirection.normalize(); - - right.crossVectors(new THREE.Vector3(0, 1, 0), cameraDirection).normalize(); - - // Create a plane that allows vertical movement - const verticalPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(right, new THREE.Vector3(0, 0, 0)); - - setFloorPlanesVertical(verticalPlane); if (rightSelect === "RotateX" || rightSelect === "RotateY") { mouseStartRef.current = { x: event.clientX, y: event.clientY }; @@ -370,6 +391,7 @@ export default function Dropped3dWidgets() { rotationStartRef.current = selectedWidget.rotation || [0, 0, 0]; } } + }; const handleMouseMove = (event: MouseEvent) => { @@ -392,90 +414,110 @@ export default function Dropped3dWidgets() { raycaster.setFromCamera(mouse, camera); - if (rightSelect === "Horizontal Move" &&raycaster.ray.intersectPlane(plane.current, planeIntersect.current)) { - const points3D = selectedZone.points as Array<[number, number, number]>; - const zonePolygonXZ = points3D.map(([x, , z]) => [x, z] as [number, number]); - const newPosition: [number, number, number] = [ - planeIntersect.current.x, - selectedWidget.position[1], - planeIntersect.current.z, - ]; - const isInside = isPointInPolygon( - [newPosition[0], newPosition[2]], - zonePolygonXZ - ); - // if (isInside) { + if (rightSelect === "Horizontal Move") { + const intersect = raycaster.ray.intersectPlane(plane.current, planeIntersect.current); + if ( + intersect && + typeof horizontalX === "number" && + typeof horizontalZ === "number" + ) { + const selectedZoneId = Object.keys(zoneWidgetData).find(zoneId => + zoneWidgetData[zoneId].some(widget => widget.id === rightClickSelected) + ); + if (!selectedZoneId) return; + + const selectedWidget = zoneWidgetData[selectedZoneId].find(widget => widget.id === rightClickSelected); + if (!selectedWidget) return; + + const newPosition: [number, number, number] = [ + intersect.x + horizontalX, + selectedWidget.position[1], + intersect.z + horizontalZ, + ]; + + updateWidgetPosition(selectedZoneId, rightClickSelected, newPosition); - // } + } } + if (rightSelect === "Vertical Move") { - if (raycaster.ray.intersectPlane(floorPlanesVertical, planeIntersect.current)) { - const currentY = selectedWidget.position[1]; - const newY = planeIntersect.current.y; - console.log('planeIntersect.current: ', planeIntersect.current); - - const deltaY = newY - currentY; - - // Reject if jump is too large (safety check) - if (Math.abs(deltaY) > 200) return; - - // Clamp jump or apply smoothing - const clampedY = currentY + THREE.MathUtils.clamp(deltaY, -10, 10); - - if (clampedY > 0) { - updateWidgetPosition(selectedZoneId, rightClickSelected, [ - selectedWidget.position[0], - clampedY, - selectedWidget.position[2], - ]); - } + const intersect = raycaster.ray.intersectPlane(floorPlanesVertical, planeIntersect.current); + + if (intersect && typeof intersectcontextmenu === "number") { + const diff = intersect.y - intersectcontextmenu; + const unclampedY = selectedWidget.position[1] + diff; + const newY = Math.max(0, unclampedY); // Prevent going below floor (y=0) + + setintersectcontextmenu(intersect.y); + + const newPosition: [number, number, number] = [ + selectedWidget.position[0], + newY, + selectedWidget.position[2], + ]; + + updateWidgetPosition(selectedZoneId, rightClickSelected, newPosition); } } + + if (rightSelect?.startsWith("Rotate")) { + const axis = rightSelect.slice(-1).toLowerCase(); // "x", "y", or "z" + const currentX = event.pageX; + const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; + setPrevX(currentX); + if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { + const index = axis === "x" ? 0 : axis === "y" ? 1 : 2; + const currentRotation = selectedWidget.rotation as [number, number, number]; // assert type + const newRotation: [number, number, number] = [...currentRotation]; + newRotation[index] += 0.05 * sign; + updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); + } + } + // if (rightSelect === "RotateX") { + // + // const currentX = event.pageX; + // const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; + // + // setPrevX(currentX); + // if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { + // + // const newRotation: [number, number, number] = [ + // selectedWidget.rotation[0] + 0.05 * sign, + // selectedWidget.rotation[1], + // selectedWidget.rotation[2], + // ]; + // updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); + // } + // } + // if (rightSelect === "RotateY") { + // const currentX = event.pageX; + // const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; + // setPrevX(currentX); + // if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { + // const newRotation: [number, number, number] = [ + // selectedWidget.rotation[0], + // selectedWidget.rotation[1] + 0.05 * sign, + // selectedWidget.rotation[2], + // ]; - if (rightSelect === "RotateX") { - const currentX = event.pageX; - const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; - setPrevX(currentX); - if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { - const newRotation: [number, number, number] = [ - selectedWidget.rotation[0] + 0.05 * sign, - selectedWidget.rotation[1], - selectedWidget.rotation[2], - ]; - - updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); - } - } + // updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); + // } + // } + // if (rightSelect === "RotateZ") { + // const currentX = event.pageX; + // const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; + // setPrevX(currentX); + // if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { + // const newRotation: [number, number, number] = [ + // selectedWidget.rotation[0], + // selectedWidget.rotation[1], + // selectedWidget.rotation[2] + 0.05 * sign, + // ]; - if (rightSelect === "RotateY") { - const currentX = event.pageX; - const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; - setPrevX(currentX); - if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { - const newRotation: [number, number, number] = [ - selectedWidget.rotation[0] , - selectedWidget.rotation[1]+ 0.05 * sign, - selectedWidget.rotation[2], - ]; - - updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); - } - } - if (rightSelect === "RotateZ") { - const currentX = event.pageX; - const sign = currentX > prevX ? 1 : currentX < prevX ? -1 : 0; - setPrevX(currentX); - if (selectedWidget?.rotation && selectedWidget.rotation.length >= 3) { - const newRotation: [number, number, number] = [ - selectedWidget.rotation[0] , - selectedWidget.rotation[1], - selectedWidget.rotation[2]+ 0.05 * sign, - ]; - - updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); - } - } + // updateWidgetRotation(selectedZoneId, rightClickSelected, newRotation); + // } + // } }; const handleMouseUp = () => { if (!rightClickSelected || !rightSelect) return; @@ -525,7 +567,7 @@ export default function Dropped3dWidgets() { const rotation = selectedWidget.rotation || [0, 0, 0]; let lastRotation = formatValues(rotation) as [number, number, number]; - + // (async () => { // let response = await update3dWidgetRotation(selectedZoneId, organization, rightClickSelected, lastRotation); // @@ -564,23 +606,60 @@ export default function Dropped3dWidgets() { }; }, [rightClickSelected, rightSelect, zoneWidgetData, gl]); + const handleRightClick3d = (event: React.MouseEvent, id: string) => { + event.preventDefault(); + + const canvasElement = document.getElementById("real-time-vis-canvas"); + if (!canvasElement) throw new Error("Canvas element not found"); + + const canvasRect = canvasElement.getBoundingClientRect(); + const relativeX = event.clientX - canvasRect.left; + const relativeY = event.clientY - canvasRect.top; + + setEditWidgetOptions(true); + setRightClickSelected(id); + setTop(relativeY); + setLeft(relativeX); + + const selectedZoneId = Object.keys(zoneWidgetData).find(zoneId => + zoneWidgetData[zoneId].some(widget => widget.id === id) + ); + if (!selectedZoneId) return; + + const selectedWidget = zoneWidgetData[selectedZoneId].find(widget => widget.id === id); + if (!selectedWidget) return; + + const { top, left, width, height } = canvasElement.getBoundingClientRect(); + mouse.x = ((event.clientX - left) / width) * 2 - 1; + mouse.y = -((event.clientY - top) / height) * 2 + 1; + + raycaster.setFromCamera(mouse, camera); + + const cameraDirection = new THREE.Vector3(); + camera.getWorldDirection(cameraDirection); + const verticalPlane = new THREE.Plane(cameraDirection); + setFloorPlanesVertical(verticalPlane); + + const intersectPoint = raycaster.ray.intersectPlane(verticalPlane, planeIntersect.current); + if (intersectPoint) { + setintersectcontextmenu(intersectPoint.y); + } + const intersect2 = raycaster.ray.intersectPlane(plane.current, planeIntersect.current); + if (intersect2) { + const xDiff = -intersect2.x + selectedWidget.position[0]; + const zDiff = -intersect2.z + selectedWidget.position[2]; + setHorizontalX(xDiff); + setHorizontalZ(zDiff); + } + }; + + return ( <> {activeZoneWidgets.map( ({ id, type, position, rotation = [0, 0, 0] }: WidgetData) => { const handleRightClick = (event: React.MouseEvent, id: string) => { - event.preventDefault(); - const canvasElement = document.getElementById( - "real-time-vis-canvas" - ); - if (!canvasElement) throw new Error("Canvas element not found"); - const canvasRect = canvasElement.getBoundingClientRect(); - const relativeX = event.clientX - canvasRect.left; - const relativeY = event.clientY - canvasRect.top; - setEditWidgetOptions(true); - setRightClickSelected(id); - setTop(relativeY); - setLeft(relativeX); + handleRightClick3d(event, id) }; switch (type) { diff --git a/app/src/components/ui/componets/RealTimeVisulization.tsx b/app/src/components/ui/componets/RealTimeVisulization.tsx index d70bfc3..0950536 100644 --- a/app/src/components/ui/componets/RealTimeVisulization.tsx +++ b/app/src/components/ui/componets/RealTimeVisulization.tsx @@ -286,7 +286,6 @@ const RealTimeVisulization: React.FC = () => { "Horizontal Move", "RotateX", "RotateY", - "RotateZ", "Delete", ]} />