display menu bugfix

This commit is contained in:
Nalvazhuthi 2025-04-04 17:47:15 +05:30
parent 60b778ff3d
commit 46d4308f9a
5 changed files with 472 additions and 355 deletions

View File

@ -1,6 +1,10 @@
import { useThree } from "@react-three/fiber"; import { useThree } from "@react-three/fiber";
import React, { useEffect, useRef } from "react"; import React, { useEffect, useRef } from "react";
import { useAsset3dWidget, useSocketStore, useWidgetSubOption } from "../../../store/store"; import {
useAsset3dWidget,
useSocketStore,
useWidgetSubOption,
} from "../../../store/store";
import useModuleStore from "../../../store/useModuleStore"; import useModuleStore from "../../../store/useModuleStore";
import { ThreeState } from "../../../types/world/worldTypes"; import { ThreeState } from "../../../types/world/worldTypes";
import * as THREE from "three"; import * as THREE from "three";
@ -13,7 +17,14 @@ import { generateUniqueId } from "../../../functions/generateUniqueId";
import { adding3dWidgets } from "../../../services/realTimeVisulization/zoneData/add3dWidget"; import { adding3dWidgets } from "../../../services/realTimeVisulization/zoneData/add3dWidget";
import { get3dWidgetZoneData } from "../../../services/realTimeVisulization/zoneData/get3dWidgetData"; import { get3dWidgetZoneData } from "../../../services/realTimeVisulization/zoneData/get3dWidgetData";
import { use3DWidget } from "../../../store/useDroppedObjectsStore"; import { use3DWidget } from "../../../store/useDroppedObjectsStore";
import { useLeftData, useRightClickSelected, useRightSelected, useTopData, useZoneWidgetStore } from "../../../store/useZone3DWidgetStore"; import {
useEditWidgetOptionsStore,
useLeftData,
useRightClickSelected,
useRightSelected,
useTopData,
useZoneWidgetStore,
} from "../../../store/useZone3DWidgetStore";
import { useWidgetStore } from "../../../store/useWidgetStore"; import { useWidgetStore } from "../../../store/useWidgetStore";
import EditWidgetOption from "../menu/EditWidgetOption"; import EditWidgetOption from "../menu/EditWidgetOption";
type WidgetData = { type WidgetData = {
@ -24,7 +35,6 @@ type WidgetData = {
tempPosition?: [number, number, number]; tempPosition?: [number, number, number];
}; };
export default function Dropped3dWidgets() { export default function Dropped3dWidgets() {
const { widgetSelect } = useAsset3dWidget(); const { widgetSelect } = useAsset3dWidget();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
@ -34,8 +44,15 @@ export default function Dropped3dWidgets() {
const { top, setTop } = useTopData(); const { top, setTop } = useTopData();
const { left, setLeft } = useLeftData(); const { left, setLeft } = useLeftData();
const { rightSelect, setRightSelect } = useRightSelected(); const { rightSelect, setRightSelect } = useRightSelected();
const { setEditWidgetOptions } = useEditWidgetOptionsStore();
const { zoneWidgetData, setZoneWidgetData, addWidget, updateWidgetPosition, updateWidgetRotation } = useZoneWidgetStore(); const {
zoneWidgetData,
setZoneWidgetData,
addWidget,
updateWidgetPosition,
updateWidgetRotation,
} = useZoneWidgetStore();
const { setWidgets3D } = use3DWidget(); const { setWidgets3D } = use3DWidget();
const { visualizationSocket } = useSocketStore(); const { visualizationSocket } = useSocketStore();
const { rightClickSelected, setRightClickSelected } = useRightClickSelected(); const { rightClickSelected, setRightClickSelected } = useRightClickSelected();
@ -56,7 +73,10 @@ export default function Dropped3dWidgets() {
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
async function get3dWidgetData() { async function get3dWidgetData() {
const result = await get3dWidgetZoneData(selectedZone.zoneId, organization); const result = await get3dWidgetZoneData(
selectedZone.zoneId,
organization
);
setWidgets3D(result); setWidgets3D(result);
const formattedWidgets = result.map((widget: WidgetData) => ({ const formattedWidgets = result.map((widget: WidgetData) => ({
@ -88,7 +108,9 @@ export default function Dropped3dWidgets() {
const group1 = scene.getObjectByName("itemsGroup"); const group1 = scene.getObjectByName("itemsGroup");
if (!group1) return; if (!group1) return;
const intersects = raycaster.intersectObjects(scene.children, true).filter( const intersects = raycaster
.intersectObjects(scene.children, true)
.filter(
(intersect) => (intersect) =>
!intersect.object.name.includes("Roof") && !intersect.object.name.includes("Roof") &&
!intersect.object.name.includes("agv-collider") && !intersect.object.name.includes("agv-collider") &&
@ -109,7 +131,7 @@ export default function Dropped3dWidgets() {
const add3dWidget = { const add3dWidget = {
organization: organization, organization: organization,
widget: newWidget, widget: newWidget,
zoneId: selectedZone.zoneId zoneId: selectedZone.zoneId,
}; };
if (visualizationSocket) { if (visualizationSocket) {
@ -134,7 +156,9 @@ export default function Dropped3dWidgets() {
const organization = email?.split("@")[1]?.split(".")[0]; const organization = email?.split("@")[1]?.split(".")[0];
if (rightSelect === "Duplicate") { if (rightSelect === "Duplicate") {
const widgetToDuplicate = activeZoneWidgets.find((w: WidgetData) => w.id === rightClickSelected); const widgetToDuplicate = activeZoneWidgets.find(
(w: WidgetData) => w.id === rightClickSelected
);
if (!widgetToDuplicate) return; if (!widgetToDuplicate) return;
const newWidget: WidgetData = { const newWidget: WidgetData = {
id: generateUniqueId(), id: generateUniqueId(),
@ -150,7 +174,7 @@ export default function Dropped3dWidgets() {
const add3dWidget = { const add3dWidget = {
organization, organization,
widget: newWidget, widget: newWidget,
zoneId: selectedZone.zoneId zoneId: selectedZone.zoneId,
}; };
addWidget(selectedZone.zoneId, newWidget); addWidget(selectedZone.zoneId, newWidget);
@ -162,7 +186,7 @@ export default function Dropped3dWidgets() {
const deleteWidget = { const deleteWidget = {
organization, organization,
widgetId: rightClickSelected, widgetId: rightClickSelected,
zoneId: selectedZone.zoneId zoneId: selectedZone.zoneId,
}; };
setZoneWidgetData( setZoneWidgetData(
@ -181,13 +205,18 @@ export default function Dropped3dWidgets() {
if (rightSelect === "RotateX" || rightSelect === "RotateY") { if (rightSelect === "RotateX" || rightSelect === "RotateY") {
mouseStartRef.current = { x: event.clientX, y: event.clientY }; mouseStartRef.current = { x: event.clientX, y: event.clientY };
const selectedZone = Object.keys(zoneWidgetData).find((zoneId: string) => const selectedZone = Object.keys(zoneWidgetData).find(
zoneWidgetData[zoneId].some((widget: WidgetData) => widget.id === rightClickSelected) (zoneId: string) =>
zoneWidgetData[zoneId].some(
(widget: WidgetData) => widget.id === rightClickSelected
)
); );
if (!selectedZone) return; if (!selectedZone) return;
const selectedWidget = zoneWidgetData[selectedZone].find((widget: WidgetData) => widget.id === rightClickSelected); const selectedWidget = zoneWidgetData[selectedZone].find(
(widget: WidgetData) => widget.id === rightClickSelected
);
if (selectedWidget) { if (selectedWidget) {
rotationStartRef.current = selectedWidget.rotation || [0, 0, 0]; rotationStartRef.current = selectedWidget.rotation || [0, 0, 0];
} }
@ -197,11 +226,15 @@ export default function Dropped3dWidgets() {
const handleMouseMove = (event: MouseEvent) => { const handleMouseMove = (event: MouseEvent) => {
if (!rightClickSelected || !rightSelect) return; if (!rightClickSelected || !rightSelect) return;
const selectedZone = Object.keys(zoneWidgetData).find((zoneId: string) => const selectedZone = Object.keys(zoneWidgetData).find((zoneId: string) =>
zoneWidgetData[zoneId].some((widget: WidgetData) => widget.id === rightClickSelected) zoneWidgetData[zoneId].some(
(widget: WidgetData) => widget.id === rightClickSelected
)
); );
if (!selectedZone) return; if (!selectedZone) return;
const selectedWidget = zoneWidgetData[selectedZone].find((widget: WidgetData) => widget.id === rightClickSelected); const selectedWidget = zoneWidgetData[selectedZone].find(
(widget: WidgetData) => widget.id === rightClickSelected
);
if (!selectedWidget) return; if (!selectedWidget) return;
const rect = gl.domElement.getBoundingClientRect(); const rect = gl.domElement.getBoundingClientRect();
@ -210,22 +243,30 @@ export default function Dropped3dWidgets() {
raycaster.setFromCamera(mouse, camera); raycaster.setFromCamera(mouse, camera);
if (rightSelect === "Horizontal Move" && raycaster.ray.intersectPlane(plane.current, planeIntersect.current)) { if (
rightSelect === "Horizontal Move" &&
raycaster.ray.intersectPlane(plane.current, planeIntersect.current)
) {
const newPosition: [number, number, number] = [ const newPosition: [number, number, number] = [
planeIntersect.current.x, planeIntersect.current.x,
selectedWidget.position[1], selectedWidget.position[1],
planeIntersect.current.z planeIntersect.current.z,
]; ];
updateWidgetPosition(selectedZone, rightClickSelected, newPosition); updateWidgetPosition(selectedZone, rightClickSelected, newPosition);
console.log('Horizontal Move - Final Position:', newPosition); console.log("Horizontal Move - Final Position:", newPosition);
} }
if (rightSelect === "Vertical Move") { if (rightSelect === "Vertical Move") {
if (raycaster.ray.intersectPlane(verticalPlane.current, planeIntersect.current)) { if (
raycaster.ray.intersectPlane(
verticalPlane.current,
planeIntersect.current
)
) {
updateWidgetPosition(selectedZone, rightClickSelected, [ updateWidgetPosition(selectedZone, rightClickSelected, [
selectedWidget.position[0], selectedWidget.position[0],
planeIntersect.current.y, planeIntersect.current.y,
selectedWidget.position[2] selectedWidget.position[2],
]); ]);
} }
} }
@ -236,7 +277,7 @@ export default function Dropped3dWidgets() {
const newRotation: [number, number, number] = [ const newRotation: [number, number, number] = [
rotationStartRef.current[0] + deltaX * rotationSpeed, rotationStartRef.current[0] + deltaX * rotationSpeed,
rotationStartRef.current[1], rotationStartRef.current[1],
rotationStartRef.current[2] rotationStartRef.current[2],
]; ];
updateWidgetRotation(selectedZone, rightClickSelected, newRotation); updateWidgetRotation(selectedZone, rightClickSelected, newRotation);
} }
@ -247,7 +288,7 @@ export default function Dropped3dWidgets() {
const newRotation: [number, number, number] = [ const newRotation: [number, number, number] = [
rotationStartRef.current[0], rotationStartRef.current[0],
rotationStartRef.current[1] + deltaY * rotationSpeed, rotationStartRef.current[1] + deltaY * rotationSpeed,
rotationStartRef.current[2] rotationStartRef.current[2],
]; ];
updateWidgetRotation(selectedZone, rightClickSelected, newRotation); updateWidgetRotation(selectedZone, rightClickSelected, newRotation);
} }
@ -258,20 +299,21 @@ export default function Dropped3dWidgets() {
const newRotation: [number, number, number] = [ const newRotation: [number, number, number] = [
currentRotation[0], currentRotation[0],
currentRotation[1], currentRotation[1],
currentRotation[2] + deltaX * rotationSpeed currentRotation[2] + deltaX * rotationSpeed,
]; ];
updateWidgetRotation(selectedZone, rightClickSelected, newRotation); updateWidgetRotation(selectedZone, rightClickSelected, newRotation);
} }
}; };
const handleMouseUp = () => { const handleMouseUp = () => {
if (rightClickSelected && ( if (
rightSelect === "Horizontal Move" || rightClickSelected &&
(rightSelect === "Horizontal Move" ||
rightSelect === "Vertical Move" || rightSelect === "Vertical Move" ||
rightSelect === "RotateX" || rightSelect === "RotateX" ||
rightSelect === "RotateY" || rightSelect === "RotateZ" rightSelect === "RotateY" ||
)) { rightSelect === "RotateZ")
) {
setTimeout(() => { setTimeout(() => {
setRightClickSelected(null); setRightClickSelected(null);
setRightSelect(null); setRightSelect(null);
@ -292,15 +334,20 @@ export default function Dropped3dWidgets() {
return ( return (
<> <>
{activeZoneWidgets.map(({ id, type, position, rotation = [0, 0, 0] }: WidgetData) => { {activeZoneWidgets.map(
({ id, type, position, rotation = [0, 0, 0] }: WidgetData) => {
const handleRightClick = (event: React.MouseEvent, id: string) => { const handleRightClick = (event: React.MouseEvent, id: string) => {
event.preventDefault(); event.preventDefault();
const canvasElement = document.getElementById("real-time-vis-canvas"); const canvasElement = document.getElementById(
"real-time-vis-canvas"
);
if (!canvasElement) throw new Error("Canvas element not found"); if (!canvasElement) throw new Error("Canvas element not found");
const canvasRect = canvasElement.getBoundingClientRect(); const canvasRect = canvasElement.getBoundingClientRect();
const relativeX = event.clientX - canvasRect.left; const relativeX = event.clientX - canvasRect.left;
const relativeY = event.clientY - canvasRect.top; const relativeY = event.clientY - canvasRect.top;
setEditWidgetOptions(true);
setRightClickSelected(id); setRightClickSelected(id);
setTop(relativeY); setTop(relativeY);
setLeft(relativeX); setLeft(relativeX);
}; };
@ -353,7 +400,8 @@ export default function Dropped3dWidgets() {
default: default:
return null; return null;
} }
})} }
)}
</> </>
); );
} }

View File

@ -7,7 +7,6 @@ import DisplayZone from "./DisplayZone";
import Scene from "../../../modules/scene/scene"; import Scene from "../../../modules/scene/scene";
import useModuleStore from "../../../store/useModuleStore"; import useModuleStore from "../../../store/useModuleStore";
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore"; import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
import { import {
useAsset3dWidget, useAsset3dWidget,
@ -24,7 +23,11 @@ import RenderOverlay from "../../templates/Overlay";
import ConfirmationPopup from "../../layout/confirmationPopup/ConfirmationPopup"; import ConfirmationPopup from "../../layout/confirmationPopup/ConfirmationPopup";
import DroppedObjects from "./DroppedFloatingWidgets"; import DroppedObjects from "./DroppedFloatingWidgets";
import EditWidgetOption from "../menu/EditWidgetOption"; import EditWidgetOption from "../menu/EditWidgetOption";
import { useRightClickSelected } from "../../../store/useZone3DWidgetStore"; import {
useRightClickSelected,
useRightSelected,
useEditWidgetOptionsStore,
} from "../../../store/useZone3DWidgetStore";
type Side = "top" | "bottom" | "left" | "right"; type Side = "top" | "bottom" | "left" | "right";
@ -58,8 +61,8 @@ const RealTimeVisulization: React.FC = () => {
const [zonesData, setZonesData] = useState<FormattedZoneData>({}); const [zonesData, setZonesData] = useState<FormattedZoneData>({});
const { selectedZone, setSelectedZone } = useSelectedZoneStore(); const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { editWidgetOptions, setEditWidgetOptions } = useEditWidgetOptionsStore();
const { rightClickSelected, setRightClickSelected } = useRightClickSelected() const { rightClickSelected, setRightClickSelected } = useRightClickSelected();
const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false); const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false);
const [floatingWidgets, setFloatingWidgets] = useState< const [floatingWidgets, setFloatingWidgets] = useState<
@ -68,6 +71,7 @@ const RealTimeVisulization: React.FC = () => {
const { widgetSelect, setWidgetSelect } = useAsset3dWidget(); const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption(); const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore(); const { visualizationSocket } = useSocketStore();
const { setRightSelect } = useRightSelected();
useEffect(() => { useEffect(() => {
async function GetZoneData() { async function GetZoneData() {
@ -142,8 +146,8 @@ const RealTimeVisulization: React.FC = () => {
const relativeX = event.clientX - canvasRect.left; const relativeX = event.clientX - canvasRect.left;
const relativeY = event.clientY - canvasRect.top; const relativeY = event.clientY - canvasRect.top;
const newPosition = determinePosition(canvasRect, relativeX, relativeY) const newPosition = determinePosition(canvasRect, relativeX, relativeY);
console.log('newPosition: ', newPosition); console.log("newPosition: ", newPosition);
const newObject = { const newObject = {
...droppedData, ...droppedData,
id: generateUniqueId(), id: generateUniqueId(),
@ -162,12 +166,12 @@ const RealTimeVisulization: React.FC = () => {
let addFloatingWidget = { let addFloatingWidget = {
organization: organization, organization: organization,
widget: newObject, widget: newObject,
zoneId: selectedZone.zoneId zoneId: selectedZone.zoneId,
} };
console.log('newObject: ', newObject); console.log("newObject: ", newObject);
if (visualizationSocket) { if (visualizationSocket) {
visualizationSocket.emit("v2:viz-float:add", addFloatingWidget) visualizationSocket.emit("v2:viz-float:add", addFloatingWidget);
} }
// let response = await addingFloatingWidgets( // let response = await addingFloatingWidgets(
@ -197,6 +201,27 @@ const RealTimeVisulization: React.FC = () => {
} catch (error) {} } catch (error) {}
}; };
// Add this useEffect hook to your component
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
const editWidgetOptions = document.querySelector(
".editWidgetOptions-wrapper"
);
if (
editWidgetOptions &&
!editWidgetOptions.contains(event.target as Node)
) {
setRightClickSelected(null);
setRightSelect(null);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [setRightClickSelected]);
return ( return (
<div <div
ref={containerRef} ref={containerRef}
@ -230,12 +255,27 @@ const RealTimeVisulization: React.FC = () => {
> >
<Scene /> <Scene />
</div> </div>
{activeModule === "visualization" && selectedZone.zoneName !== "" && <DroppedObjects />} {activeModule === "visualization" && selectedZone.zoneName !== "" && (
<DroppedObjects />
)}
{activeModule === "visualization" && <SocketRealTimeViz />} {activeModule === "visualization" && <SocketRealTimeViz />}
{activeModule === "visualization" && rightClickSelected && <EditWidgetOption {activeModule === "visualization" &&
options={["Duplicate", "Vertical Move", "Horizontal Move", "RotateX", "RotateY", "RotateZ", "Delete"]} editWidgetOptions &&
/>} rightClickSelected && (
<EditWidgetOption
setWidgetSelect={setWidgetSelect}
options={[
"Duplicate",
"Vertical Move",
"Horizontal Move",
"RotateX",
"RotateY",
"RotateZ",
"Delete",
]}
/>
)}
{activeModule === "visualization" && ( {activeModule === "visualization" && (
<> <>

View File

@ -1,34 +1,51 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { useLeftData, useRightSelected, useTopData } from "../../../store/useZone3DWidgetStore"; import {
useEditWidgetOptionsStore,
useLeftData,
useRightClickSelected,
useRightSelected,
useTopData,
} from "../../../store/useZone3DWidgetStore";
interface EditWidgetOptionProps { interface EditWidgetOptionProps {
setWidgetSelect: any;
options: string[]; options: string[];
} }
const EditWidgetOption: React.FC<EditWidgetOptionProps> = ({ options }) => { const EditWidgetOption: React.FC<EditWidgetOptionProps> = ({
const { top, setTop } = useTopData() setWidgetSelect,
const { left, setLeft } = useLeftData() options,
const { rightSelect, setRightSelect } = useRightSelected() }) => {
const { top, setTop } = useTopData();
const { left, setLeft } = useLeftData();
const { rightSelect, setRightSelect } = useRightSelected();
const { setEditWidgetOptions } = useEditWidgetOptionsStore();
useEffect(() => { useEffect(() => {
console.log("left: ", left);
console.log('left: ', left); console.log("top: ", top);
console.log('top: ', top); }, [top, left]);
}, [top, left])
return ( return (
<div className="editWidgetOptions-wrapper" <div
className="editWidgetOptions-wrapper"
style={{ style={{
position: "absolute", position: "absolute",
top: `${top}px`, top: `${top}px`,
left: `${left}px`, left: `${left}px`,
zIndex: 10000, zIndex: 10000,
}} }}
> >
<div className="editWidgetOptions"> <div className="editWidgetOptions">
{options.map((option, index) => ( {options.map((option, index) => (
<div className="option" key={index} onClick={(e) => setRightSelect(option)}> <div
className="option"
key={index}
onClick={(e) => {
setRightSelect(option);
setEditWidgetOptions(false);
}}
>
{option} {option}
</div> </div>
))} ))}

View File

@ -96,3 +96,14 @@ export const useRightSelected = create<RightSelectStore>((set) => ({
rightSelect: null, // Default state is null rightSelect: null, // Default state is null
setRightSelect: (x) => set({ rightSelect: x }), setRightSelect: (x) => set({ rightSelect: x }),
})); }));
interface EditWidgetOptionsStore {
editWidgetOptions: boolean;
setEditWidgetOptions: (value: boolean) => void;
}
export const useEditWidgetOptionsStore = create<EditWidgetOptionsStore>((set) => ({
editWidgetOptions: false, // Initial state
setEditWidgetOptions: (value: boolean) => set({ editWidgetOptions: value }),
}));

View File

@ -719,9 +719,9 @@
.editWidgetOptions { .editWidgetOptions {
position: absolute; position: absolute;
top: 50%; // top: 50%;
left: 50%; // left: 50%;
transform: translate(-50%, -50%); // transform: translate(-50%, -50%);
background-color: var(--background-color); background-color: var(--background-color);
z-index: 3; z-index: 3;
display: flex; display: flex;
@ -729,6 +729,7 @@
border-radius: 6px; border-radius: 6px;
overflow: hidden; overflow: hidden;
min-width: 150px;
.option { .option {
padding: 8px 10px; padding: 8px 10px;
color: var(--text-color); color: var(--text-color);