From 9b9f61369c543fbffde14200202518d091162dba Mon Sep 17 00:00:00 2001 From: Gomathi9520 <gomathi@hexrfactory.com> Date: Thu, 24 Apr 2025 16:58:15 +0530 Subject: [PATCH] code structure updated --- app/src/components/ui/list/List.tsx | 4 +- .../builder/groups/floorItemsGroup.tsx | 20 +- .../collaboration/socketResponses.dev.tsx | 2 +- app/src/modules/visualization/DisplayZone.tsx | 159 +++---------- .../visualization/RealTimeVisulization.tsx | 133 +++-------- .../widgets/panel/AddButtons.tsx | 219 +++--------------- .../visualization/widgets/panel/Panel.tsx | 152 +++--------- app/src/modules/visualization/zoneAssets.tsx | 88 +++---- 8 files changed, 169 insertions(+), 608 deletions(-) diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx index 49e86f4..2fb9a96 100644 --- a/app/src/components/ui/list/List.tsx +++ b/app/src/components/ui/list/List.tsx @@ -45,7 +45,8 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => { const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>( {} ); - const { floorItems, setFloorItems } = useFloorItems(); + const { setFloorItems } = useFloorItems(); + useEffect(() => { useSelectedZoneStore.getState().setSelectedZone({ @@ -143,6 +144,7 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => { ); } + console.log('newName: ', newName); } diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx index acc284f..84eb27e 100644 --- a/app/src/modules/builder/groups/floorItemsGroup.tsx +++ b/app/src/modules/builder/groups/floorItemsGroup.tsx @@ -1,5 +1,5 @@ import { useFrame, useThree } from "@react-three/fiber"; -import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteTool, useFloorItems, useLoadingProgress, useRenderDistance, useSelectedFloorItem, useSelectedItem, useSimulationStates, useSocketStore, useToggleView, useTransformMode, } from "../../../store/store"; +import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteTool, useFloorItems, useLoadingProgress, useRenderDistance, useSelectedFloorItem, useSelectedItem, useSimulationStates, useSocketStore, useToggleView, useTransformMode, useZoneAssetId, } from "../../../store/store"; import assetVisibility from "../geomentries/assets/assetVisibility"; import { useEffect } from "react"; import * as THREE from "three"; @@ -32,12 +32,13 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject const { setSelectedFloorItem } = useSelectedFloorItem(); const { activeTool } = useActiveTool(); const { selectedItem, setSelectedItem } = useSelectedItem(); - const { simulationStates, setSimulationStates } = useSimulationStates(); + const { setSimulationStates } = useSimulationStates(); const { setLoadingProgress } = useLoadingProgress(); const { activeModule } = useModuleStore(); const { socket } = useSocketStore(); const loader = new GLTFLoader(); const dracoLoader = new DRACOLoader(); + const { setZoneAssetId } = useZoneAssetId(); dracoLoader.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/"); loader.setDRACOLoader(dracoLoader); @@ -220,6 +221,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject const target = controls.getTarget(new THREE.Vector3()); await controls.setTarget(target.x, 0, target.z, true); setSelectedFloorItem(null); + setZoneAssetId(null) } } } @@ -314,14 +316,14 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject useFrame(() => { if (controls) // assetVisibility(itemsGroup, state.camera.position, renderDistance); - if (deleteTool && activeModule === "builder") { - DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem); - } else if (!deleteTool) { - if (hoveredDeletableFloorItem.current) { - hoveredDeletableFloorItem.current = undefined; - setDeletableFloorItem(null); + if (deleteTool && activeModule === "builder") { + DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem); + } else if (!deleteTool) { + if (hoveredDeletableFloorItem.current) { + hoveredDeletableFloorItem.current = undefined; + setDeletableFloorItem(null); + } } - } }); return <group ref={itemsGroup} name="itemsGroup"></group>; diff --git a/app/src/modules/collaboration/socketResponses.dev.tsx b/app/src/modules/collaboration/socketResponses.dev.tsx index 6e578a1..7688155 100644 --- a/app/src/modules/collaboration/socketResponses.dev.tsx +++ b/app/src/modules/collaboration/socketResponses.dev.tsx @@ -795,7 +795,7 @@ export default function SocketResponses({ return } if (data.message === "zone deleted") { - const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId); + const updatedZones = zones?.filter((zone: any) => zone.zoneId !== data.data.zoneId); setZones(updatedZones); const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === data.data.zoneId); diff --git a/app/src/modules/visualization/DisplayZone.tsx b/app/src/modules/visualization/DisplayZone.tsx index e2f3b2f..6f18c20 100644 --- a/app/src/modules/visualization/DisplayZone.tsx +++ b/app/src/modules/visualization/DisplayZone.tsx @@ -1,18 +1,11 @@ import React, { useEffect, useRef, useState, useCallback } from "react"; -import { useWidgetStore, Widget } from "../../store/useWidgetStore"; - -import { - useDroppedObjectsStore, - useFloatingWidget, -} from "../../store/useDroppedObjectsStore"; +import { Widget } from "../../store/useWidgetStore"; +import {useDroppedObjectsStore, useFloatingWidget,} from "../../store/useDroppedObjectsStore"; import { getSelect2dZoneData } from "../../services/realTimeVisulization/zoneData/getSelect2dZoneData"; import { getFloatingZoneData } from "../../services/realTimeVisulization/zoneData/getFloatingData"; -import { get3dWidgetZoneData } from "../../services/realTimeVisulization/zoneData/get3dWidgetData"; -import { - MoveArrowLeft, - MoveArrowRight, -} from "../../components/icons/SimulationIcons"; +import {MoveArrowLeft, MoveArrowRight,} from "../../components/icons/SimulationIcons"; import { InfoIcon } from "../../components/icons/ExportCommonIcons"; +import { useSelectedZoneStore } from "../../store/useZoneStore"; // Define the type for `Side` type Side = "top" | "bottom" | "left" | "right"; @@ -34,62 +27,20 @@ interface DisplayZoneProps { zoneViewPortPosition: number[]; }; }; - selectedZone: { - zoneName: string; - activeSides: Side[]; - panelOrder: Side[]; - lockedPanels: Side[]; - zoneId: string; - points: []; - zoneViewPortTarget: number[]; - zoneViewPortPosition: number[]; - widgets: { - id: string; - type: string; - title: string; - panel: Side; - data: any; - }[]; - }; - setSelectedZone: React.Dispatch< - React.SetStateAction<{ - zoneName: string; - activeSides: Side[]; - panelOrder: Side[]; - lockedPanels: Side[]; - points: []; - zoneId: string; - zoneViewPortTarget: number[]; - zoneViewPortPosition: number[]; - widgets: { - id: string; - type: string; - title: string; - panel: Side; - data: any; - }[]; - }> - >; hiddenPanels: HiddenPanels; // Updated prop type setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type } -const DisplayZone: React.FC<DisplayZoneProps> = ({ - zonesData, - selectedZone, - setSelectedZone, - hiddenPanels, -}) => { +const DisplayZone: React.FC<DisplayZoneProps> = ({ zonesData, hiddenPanels }) => { + + const [showLeftArrow, setShowLeftArrow] = useState(false); + const [showRightArrow, setShowRightArrow] = useState(false); // Ref for the container element const containerRef = useRef<HTMLDivElement | null>(null); const scrollContainerRef = useRef<HTMLDivElement | null>(null); - - // State to track overflow visibility - const [showLeftArrow, setShowLeftArrow] = useState(false); - const [showRightArrow, setShowRightArrow] = useState(false); - const { floatingWidget, setFloatingWidget } = useFloatingWidget(); - - const { setSelectedChartId } = useWidgetStore(); + //zustand + const { setFloatingWidget } = useFloatingWidget(); + const { selectedZone, setSelectedZone } = useSelectedZoneStore(); // Function to calculate overflow state const updateOverflowState = useCallback(() => { @@ -97,16 +48,9 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({ if (container) { const isOverflowing = container.scrollWidth > container.clientWidth; const canScrollLeft = container.scrollLeft > 0; - - const canScrollRight = - container.scrollLeft + container.clientWidth + 1 < - container.scrollWidth; + const canScrollRight = container.scrollLeft + container.clientWidth + 1 < container.scrollWidth; setShowLeftArrow(isOverflowing && canScrollLeft); setShowRightArrow(isOverflowing && canScrollRight); - - // console.log('canScrollRight: ', canScrollRight); - // console.log('isOverflowing: ', isOverflowing); - } }, []); @@ -126,10 +70,7 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({ const handleWheel = (event: WheelEvent) => { if (Math.abs(event.deltaY) > Math.abs(event.deltaX)) { event.preventDefault(); - container.scrollBy({ - left: event.deltaY * 2, - behavior: "smooth", - }); + container.scrollBy({ left: event.deltaY * 2, behavior: "smooth", }); } }; @@ -171,23 +112,11 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({ if (selectedZone?.zoneId === zoneId) { return; } - // setSelectedChartId(null); const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; + + //api for getting 2d widget Data let response = await getSelect2dZoneData(zoneId, organization); - console.log("response: ", response); - let res = await getFloatingZoneData(zoneId, organization); - console.log("res: ", res); - - setFloatingWidget(res); - // Set the selected zone in the store - useDroppedObjectsStore.getState().setZone(zoneName, zoneId); - if (Array.isArray(res)) { - res.forEach((val) => { - useDroppedObjectsStore.getState().addObject(zoneName, val); - }); - } - setSelectedZone({ zoneName, activeSides: response.activeSides || [], @@ -199,62 +128,42 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({ zoneViewPortTarget: response.viewPortCenter || {}, zoneViewPortPosition: response.viewPortposition || {}, }); - } catch (error) {} + + //api for getting floating widget Data + let res = await getFloatingZoneData(zoneId, organization); + setFloatingWidget(res); + useDroppedObjectsStore.getState().setZone(zoneName, zoneId); + if (Array.isArray(res)) { + res.forEach((val) => { + useDroppedObjectsStore.getState().addObject(zoneName, val); + }); + } + + } catch (error) { } } return ( - <div - ref={containerRef} - className={`zone-wrapper ${ - selectedZone?.activeSides?.includes("bottom") && - !hiddenPanels[selectedZone.zoneId]?.includes("bottom") - ? "bottom" - : "" - }`} - > + <div ref={containerRef} className={`zone-wrapper ${selectedZone?.activeSides?.includes("bottom") && !hiddenPanels[selectedZone.zoneId]?.includes("bottom") ? "bottom" : ""}`}> {/* Left Arrow */} - {showLeftArrow && ( - <button className="arrow left-arrow" onClick={handleScrollLeft}> - <MoveArrowLeft /> - </button> - )} - + {showLeftArrow && (<button className="arrow left-arrow" onClick={handleScrollLeft}><MoveArrowLeft /></button>)} {/* Scrollable Zones Container */} - <div - ref={scrollContainerRef} - className="zones-wrapper" - style={{ overflowX: "auto", whiteSpace: "nowrap" }} - > + <div ref={scrollContainerRef} className="zones-wrapper" style={{ overflowX: "auto", whiteSpace: "nowrap" }}> {Object.keys(zonesData).length !== 0 ? ( <> {Object.keys(zonesData).map((zoneName, index) => ( - <div - key={index} - className={`zone ${ - selectedZone.zoneName === zoneName ? "active" : "" - }`} - onClick={() => - handleSelect2dZoneData(zonesData[zoneName]?.zoneId, zoneName) - } + <div key={index} className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""}`} + onClick={() => handleSelect2dZoneData(zonesData[zoneName]?.zoneId, zoneName)} > {zoneName} </div> ))} </> ) : ( - <div className="no-zone"> - <InfoIcon /> - No zones? Create one! - </div> + <div className="no-zone"><InfoIcon />No zones? Create one!</div> )} </div> - {/* Right Arrow */} - {showRightArrow && ( - <button className="arrow right-arrow" onClick={handleScrollRight}> - <MoveArrowRight /> - </button> - )} + {showRightArrow && (<button className="arrow right-arrow" onClick={handleScrollRight}><MoveArrowRight /></button>)} </div> ); }; diff --git a/app/src/modules/visualization/RealTimeVisulization.tsx b/app/src/modules/visualization/RealTimeVisulization.tsx index e039592..e82dce3 100644 --- a/app/src/modules/visualization/RealTimeVisulization.tsx +++ b/app/src/modules/visualization/RealTimeVisulization.tsx @@ -6,32 +6,17 @@ import { useSelectedZoneStore } from "../../store/useZoneStore"; import DisplayZone from "./DisplayZone"; import Scene from "../scene/scene"; import useModuleStore from "../../store/useModuleStore"; - -import { - useDroppedObjectsStore, - useFloatingWidget, -} from "../../store/useDroppedObjectsStore"; -import { - useAsset3dWidget, - useSocketStore, - useWidgetSubOption, - useZones, -} from "../../store/store"; +import { useDroppedObjectsStore, useFloatingWidget, } from "../../store/useDroppedObjectsStore"; +import { useAsset3dWidget, useSocketStore, useWidgetSubOption } from "../../store/store"; import { getZone2dData } from "../../services/realTimeVisulization/zoneData/getZoneData"; import { generateUniqueId } from "../../functions/generateUniqueId"; import { determinePosition } from "./functions/determinePosition"; -import { addingFloatingWidgets } from "../../services/realTimeVisulization/zoneData/addFloatingWidgets"; import SocketRealTimeViz from "./socket/realTimeVizSocket.dev"; import RenderOverlay from "../../components/templates/Overlay"; import ConfirmationPopup from "../../components/layout/confirmationPopup/ConfirmationPopup"; import DroppedObjects from "./widgets/floating/DroppedFloatingWidgets"; import EditWidgetOption from "../../components/ui/menu/EditWidgetOption"; -import { - useEditWidgetOptionsStore, - useRightClickSelected, - useRightSelected, -} from "../../store/useZone3DWidgetStore"; -import Dropped3dWidgets from "./widgets/3d/Dropped3dWidget"; +import { useEditWidgetOptionsStore, useRightClickSelected, useRightSelected, } from "../../store/useZone3DWidgetStore"; import OuterClick from "../../utils/outerClick"; import { useWidgetStore } from "../../store/useWidgetStore"; import { getActiveProperties } from "./functions/getActiveProperties"; @@ -65,36 +50,26 @@ interface HiddenPanels { } const RealTimeVisulization: React.FC = () => { - const [hiddenPanels, setHiddenPanels] = React.useState<HiddenPanels>({}); - const containerRef = useRef<HTMLDivElement>(null); + //zustand const { isPlaying } = usePlayButtonStore(); const { activeModule } = useModuleStore(); - const [droppedObjects, setDroppedObjects] = useState<any[]>([]); - const [zonesData, setZonesData] = useState<FormattedZoneData>({}); const { selectedZone, setSelectedZone } = useSelectedZoneStore(); - - const { rightSelect, setRightSelect } = useRightSelected(); - const { editWidgetOptions, setEditWidgetOptions } = - useEditWidgetOptionsStore(); + const { setRightSelect } = useRightSelected(); + const { editWidgetOptions } = useEditWidgetOptionsStore(); const { rightClickSelected, setRightClickSelected } = useRightClickSelected(); - const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false); - - // const [floatingWidgets, setFloatingWidgets] = useState<Record<string, { zoneName: string; zoneId: string; objects: any[] }>>({}); - const { floatingWidget, setFloatingWidget } = useFloatingWidget(); - const { widgetSelect, setWidgetSelect } = useAsset3dWidget(); - const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption(); + const { setFloatingWidget } = useFloatingWidget(); + const { widgetSubOption } = useWidgetSubOption(); const { visualizationSocket } = useSocketStore(); const { setSelectedChartId } = useWidgetStore(); + const [hiddenPanels, setHiddenPanels] = React.useState<HiddenPanels>({}); + const containerRef = useRef<HTMLDivElement>(null); + const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false); + const [zonesData, setZonesData] = useState<FormattedZoneData>({}); + const [canvasDimensions, setCanvasDimensions] = useState({ width: 0, height: 0, }); + OuterClick({ - contextClassName: [ - "chart-container", - "floating", - "sidebar-right-wrapper", - "card", - "dropdown-menu", - "dropdown-options", - ], + contextClassName: ["chart-container","floating","sidebar-right-wrapper","card","dropdown-menu","dropdown-options",], setMenuVisible: () => setSelectedChartId(null), }); @@ -104,7 +79,6 @@ const RealTimeVisulization: React.FC = () => { const organization = email?.split("@")[1]?.split(".")[0]; try { const response = await getZone2dData(organization); - // console.log('response: ', response); if (!Array.isArray(response)) { return; @@ -126,11 +100,11 @@ const RealTimeVisulization: React.FC = () => { {} ); setZonesData(formattedData); - } catch (error) {} + } catch (error) { } } GetZoneData(); - }, [activeModule]); // Removed `zones` from dependencies + }, [activeModule]); useEffect(() => { setZonesData((prev) => { @@ -152,7 +126,6 @@ const RealTimeVisulization: React.FC = () => { }); }, [selectedZone]); - // useEffect(() => {}, [floatingWidgets]); const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => { event.preventDefault(); @@ -251,10 +224,10 @@ const RealTimeVisulization: React.FC = () => { ); setFloatingWidget(currentZone.objects); } else { - console.warn("Zone not found or zoneId mismatch"); + } } catch (error) { - console.error("Error in handleDrop:", error); + } }; @@ -278,10 +251,7 @@ const RealTimeVisulization: React.FC = () => { }; }, [setRightClickSelected]); - const [canvasDimensions, setCanvasDimensions] = useState({ - width: 0, - height: 0, - }); + useEffect(() => { const canvas = document.getElementById("real-time-vis-canvas"); if (!canvas) return; @@ -304,14 +274,7 @@ const RealTimeVisulization: React.FC = () => { return ( <> <style> - {` - :root { - --realTimeViz-container-width: ${canvasDimensions.width}px; - - --realTimeViz-container-height: ${canvasDimensions.height}px; - - } - `} + {`:root {--realTimeViz-container-width: ${canvasDimensions.width}px;--realTimeViz-container-height: ${canvasDimensions.height}px; }`} </style> <div ref={containerRef} @@ -326,11 +289,7 @@ const RealTimeVisulization: React.FC = () => { <div className="realTime-viz-wrapper"> {openConfirmationPopup && ( <RenderOverlay> - <ConfirmationPopup - message={"Are you sure want to delete?"} - onConfirm={() => console.log("Confirmed")} - onCancel={() => setOpenConfirmationPopup(false)} - /> + <ConfirmationPopup message={"Are you sure want to delete?"} onConfirm={() => { }} onCancel={() => setOpenConfirmationPopup(false)} /> </RenderOverlay> )} <div @@ -346,51 +305,15 @@ const RealTimeVisulization: React.FC = () => { > <Scene /> </div> - {activeModule === "visualization" && selectedZone.zoneName !== "" && ( - <DroppedObjects /> - )} + {activeModule === "visualization" && selectedZone.zoneName !== "" && (<DroppedObjects />)} {activeModule === "visualization" && <SocketRealTimeViz />} - - {activeModule === "visualization" && - editWidgetOptions && - rightClickSelected && ( - <EditWidgetOption - options={[ - "Duplicate", - "Vertical Move", - "Horizontal Move", - "RotateX", - "RotateY", - "Delete", - ]} - /> - )} - + {activeModule === "visualization" && editWidgetOptions && rightClickSelected && (<EditWidgetOption options={["Duplicate", "Vertical Move", "Horizontal Move", "RotateX", "RotateY", "Delete",]} />)} {activeModule === "visualization" && ( <> - <DisplayZone - zonesData={zonesData} - selectedZone={selectedZone} - setSelectedZone={setSelectedZone} - hiddenPanels={hiddenPanels} - setHiddenPanels={setHiddenPanels} - /> - - {!isPlaying && selectedZone?.zoneName !== "" && ( - <AddButtons - hiddenPanels={hiddenPanels} - setHiddenPanels={setHiddenPanels} - selectedZone={selectedZone} - setSelectedZone={setSelectedZone} - /> - )} - - <Panel - selectedZone={selectedZone} - setSelectedZone={setSelectedZone} - hiddenPanels={hiddenPanels} - setZonesData={setZonesData} - /> + <DisplayZone zonesData={zonesData} hiddenPanels={hiddenPanels} setHiddenPanels={setHiddenPanels} /> + {!isPlaying && selectedZone?.zoneName !== "" && + (<AddButtons hiddenPanels={hiddenPanels} setHiddenPanels={setHiddenPanels} />)} + <Panel hiddenPanels={hiddenPanels} setZonesData={setZonesData} /> </> )} </div> diff --git a/app/src/modules/visualization/widgets/panel/AddButtons.tsx b/app/src/modules/visualization/widgets/panel/AddButtons.tsx index 5d45d3f..8474629 100644 --- a/app/src/modules/visualization/widgets/panel/AddButtons.tsx +++ b/app/src/modules/visualization/widgets/panel/AddButtons.tsx @@ -6,100 +6,48 @@ import { } from "../../../../components/icons/RealTimeVisulationIcons"; import { AddIcon } from "../../../../components/icons/ExportCommonIcons"; import { useSocketStore } from "../../../../store/store"; -import { clearPanel } from "../../../../services/realTimeVisulization/zoneData/clearPanel"; -import { lockPanel } from "../../../../services/realTimeVisulization/zoneData/lockPanel"; - +import { useSelectedZoneStore } from "../../../../store/useZoneStore"; // Define the type for `Side` type Side = "top" | "bottom" | "left" | "right"; -// Define the type for HiddenPanels, where keys are zone IDs and values are arrays of hidden sides interface HiddenPanels { [zoneId: string]: Side[]; } -// Define the type for the props passed to the Buttons component interface ButtonsProps { - selectedZone: { - zoneName: string; - activeSides: Side[]; - panelOrder: Side[]; - lockedPanels: Side[]; - points: []; - zoneId: string; - zoneViewPortTarget: number[]; - zoneViewPortPosition: number[]; - widgets: { - id: string; - type: string; - title: string; - panel: Side; - data: any; - }[]; - }; - setSelectedZone: React.Dispatch< - React.SetStateAction<{ - zoneName: string; - activeSides: Side[]; - panelOrder: Side[]; - lockedPanels: Side[]; - points: []; - zoneId: string; - zoneViewPortTarget: number[]; - zoneViewPortPosition: number[]; - widgets: { - id: string; - type: string; - title: string; - panel: Side; - data: any; - }[]; - }> - >; hiddenPanels: HiddenPanels; // Updated prop type setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type } -const AddButtons: React.FC<ButtonsProps> = ({ - selectedZone, - setSelectedZone, - setHiddenPanels, - hiddenPanels, -}) => { +const AddButtons: React.FC<ButtonsProps> = ({ setHiddenPanels, hiddenPanels, }) => { + + const { selectedZone, setSelectedZone } = useSelectedZoneStore(); const { visualizationSocket } = useSocketStore(); // Function to toggle visibility of a panel const toggleVisibility = (side: Side) => { const isHidden = hiddenPanels[selectedZone.zoneId]?.includes(side) ?? false; - if (isHidden) { // If the panel is already hidden, remove it from the hiddenPanels array for this zone setHiddenPanels((prevHiddenPanels) => ({ ...prevHiddenPanels, - [selectedZone.zoneId]: prevHiddenPanels[selectedZone.zoneId].filter( - (panel) => panel !== side - ), + [selectedZone.zoneId]: prevHiddenPanels[selectedZone.zoneId].filter((panel) => panel !== side), })); } else { // If the panel is visible, add it to the hiddenPanels array for this zone setHiddenPanels((prevHiddenPanels) => ({ ...prevHiddenPanels, - [selectedZone.zoneId]: [ - ...(prevHiddenPanels[selectedZone.zoneId] || []), - side, - ], + [selectedZone.zoneId]: [...(prevHiddenPanels[selectedZone.zoneId] || []), side,], })); } }; // Function to toggle lock/unlock a panel const toggleLockPanel = async (side: Side) => { - // console.log('side: ', side); const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value - //add api - const newLockedPanels = selectedZone.lockedPanels.includes(side) - ? selectedZone.lockedPanels.filter((panel) => panel !== side) - : [...selectedZone.lockedPanels, side]; + + const newLockedPanels = selectedZone.lockedPanels.includes(side) ? selectedZone.lockedPanels.filter((panel) => panel !== side) : [...selectedZone.lockedPanels, side]; const updatedZone = { ...selectedZone, @@ -114,10 +62,9 @@ const AddButtons: React.FC<ButtonsProps> = ({ if (visualizationSocket) { visualizationSocket.emit("v2:viz-panel:locked", lockedPanel); } - setSelectedZone(updatedZone); // let response = await lockPanel(selectedZone.zoneId, organization, newLockedPanels) - // console.log('response: ', response); + // // if (response.message === 'locked panel updated successfully') { // // Update the selectedZone state // setSelectedZone(updatedZone); @@ -126,17 +73,9 @@ const AddButtons: React.FC<ButtonsProps> = ({ // Function to clean all widgets from a panel const cleanPanel = async (side: Side) => { - //add api - // console.log('side: ', side); - if ( - hiddenPanels[selectedZone.zoneId]?.includes(side) || - selectedZone.lockedPanels.includes(side) - ) - return; - + if (hiddenPanels[selectedZone.zoneId]?.includes(side) || selectedZone.lockedPanels.includes(side)) return; const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value - let clearPanel = { organization: organization, panelName: side, @@ -145,54 +84,33 @@ const AddButtons: React.FC<ButtonsProps> = ({ if (visualizationSocket) { visualizationSocket.emit("v2:viz-panel:clear", clearPanel); } - const cleanedWidgets = selectedZone.widgets.filter( - (widget) => widget.panel !== side - ); + const cleanedWidgets = selectedZone.widgets.filter((widget) => widget.panel !== side); const updatedZone = { ...selectedZone, widgets: cleanedWidgets, }; // Update the selectedZone state - // console.log('updatedZone: ', updatedZone); setSelectedZone(updatedZone); - - // let response = await clearPanel(selectedZone.zoneId, organization, side) - // console.log('response: ', response); - // if (response.message === 'PanelWidgets cleared successfully') { - - // const cleanedWidgets = selectedZone.widgets.filter( - // (widget) => widget.panel !== side - // ); - // const updatedZone = { - // ...selectedZone, - // widgets: cleanedWidgets, - // }; - // // Update the selectedZone state - // setSelectedZone(updatedZone); - // } }; // Function to handle "+" button click const handlePlusButtonClick = async (side: Side) => { + + // Get email and organization safely with a default fallback + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; + if (selectedZone.activeSides.includes(side)) { - console.log("open"); // Panel already exists: Remove widgets from that side and update activeSides - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value - // Remove all widgets associated with the side and update active sides - const cleanedWidgets = selectedZone.widgets.filter( - (widget) => widget.panel !== side - ); + const cleanedWidgets = selectedZone.widgets.filter((widget) => widget.panel !== side); const newActiveSides = selectedZone.activeSides.filter((s) => s !== side); - const updatedZone = { ...selectedZone, widgets: cleanedWidgets, activeSides: newActiveSides, panelOrder: newActiveSides, }; - let deletePanel = { organization: organization, panelName: side, @@ -202,41 +120,17 @@ const AddButtons: React.FC<ButtonsProps> = ({ visualizationSocket.emit("v2:viz-panel:delete", deletePanel); } setSelectedZone(updatedZone); - if (hiddenPanels[selectedZone.zoneId]?.includes(side)) { setHiddenPanels((prev) => ({ ...prev, - [selectedZone.zoneId]: prev[selectedZone.zoneId].filter( - (s) => s !== side - ), + [selectedZone.zoneId]: prev[selectedZone.zoneId].filter((s) => s !== side), })); } - - // if(hiddenPanels[selectedZone.zoneId].includes(side)) - - // API call to delete the panel - // try { - // const response = await deletePanelApi(selectedZone.zoneId, side, organization); - // - // if (response.message === "Panel deleted successfully") { - // } else { - // - // } - // } catch (error) { - // - // } } else { // Panel does not exist: Create panel try { - // Get email and organization safely with a default fallback - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0]; - // Prevent duplicate side entries - const newActiveSides = selectedZone.activeSides.includes(side) - ? [...selectedZone.activeSides] - : [...selectedZone.activeSides, side]; - + const newActiveSides = selectedZone.activeSides.includes(side)? [...selectedZone.activeSides]: [...selectedZone.activeSides, side]; const updatedZone = { ...selectedZone, activeSides: newActiveSides, @@ -251,15 +145,7 @@ const AddButtons: React.FC<ButtonsProps> = ({ visualizationSocket.emit("v2:viz-panel:add", addPanel); } setSelectedZone(updatedZone); - // API call to create panels - // const response = await panelData(organization, selectedZone.zoneId, newActiveSides); - // - - // if (response.message === "Panels created successfully") { - // } else { - // - // } - } catch (error) {} + } catch (error) { } } }; return ( @@ -268,20 +154,11 @@ const AddButtons: React.FC<ButtonsProps> = ({ {(["top", "right", "bottom", "left"] as Side[]).map((side) => ( <div key={side} className={`side-button-container ${side}`}> {/* "+" Button */} - <button - className={`side-button ${side}${ - selectedZone.activeSides.includes(side) ? " active" : "" - }`} + <button className={`side-button ${side}${selectedZone.activeSides.includes(side) ? " active" : ""}`} onClick={() => handlePlusButtonClick(side)} - title={ - selectedZone.activeSides.includes(side) - ? `Remove all items and close ${side} panel` - : `Activate ${side} panel` - } + title={selectedZone.activeSides.includes(side) ? `Remove all items and close ${side} panel` : `Activate ${side} panel`} > - <div className="add-icon"> - <AddIcon /> - </div> + <div className="add-icon"><AddIcon /></div> </button> {/* Extra Buttons */} @@ -289,62 +166,28 @@ const AddButtons: React.FC<ButtonsProps> = ({ <div className="extra-Bs"> {/* Hide Panel */} <div - className={`icon ${ - hiddenPanels[selectedZone.zoneId]?.includes(side) - ? "active" - : "" - }`} - title={ - hiddenPanels[selectedZone.zoneId]?.includes(side) - ? "Show Panel" - : "Hide Panel" - } + className={`icon ${hiddenPanels[selectedZone.zoneId]?.includes(side) ? "active" : ""}`} + title={hiddenPanels[selectedZone.zoneId]?.includes(side) ? "Show Panel" : "Hide Panel"} onClick={() => toggleVisibility(side)} > - <EyeIcon - fill={ - hiddenPanels[selectedZone.zoneId]?.includes(side) - ? "var(--primary-color)" - : "var(--text-color)" - } - /> + <EyeIcon fill={hiddenPanels[selectedZone.zoneId]?.includes(side) ? "var(--primary-color)" : "var(--text-color)"} /> </div> {/* Clean Panel */} - <div - className="icon" - title="Clean Panel" + <div className="icon" title="Clean Panel" onClick={() => cleanPanel(side)} - style={{ - cursor: - hiddenPanels[selectedZone.zoneId]?.includes(side) || - selectedZone.lockedPanels.includes(side) - ? "not-allowed" - : "pointer", - }} + style={{ cursor: hiddenPanels[selectedZone.zoneId]?.includes(side) || selectedZone.lockedPanels.includes(side) ? "not-allowed" : "pointer", }} > <CleanPannel /> </div> {/* Lock/Unlock Panel */} <div - className={`icon ${ - selectedZone.lockedPanels.includes(side) ? "active" : "" - }`} - title={ - selectedZone.lockedPanels.includes(side) - ? "Unlock Panel" - : "Lock Panel" - } + className={`icon ${selectedZone.lockedPanels.includes(side) ? "active" : ""}`} + title={selectedZone.lockedPanels.includes(side) ? "Unlock Panel" : "Lock Panel"} onClick={() => toggleLockPanel(side)} > - <LockIcon - fill={ - selectedZone.lockedPanels.includes(side) - ? "var(--primary-color)" - : "var(--text-color)" - } - /> + <LockIcon fill={selectedZone.lockedPanels.includes(side) ? "var(--primary-color)" : "var(--text-color)"} /> </div> </div> )} diff --git a/app/src/modules/visualization/widgets/panel/Panel.tsx b/app/src/modules/visualization/widgets/panel/Panel.tsx index f53b0ea..c2ddefa 100644 --- a/app/src/modules/visualization/widgets/panel/Panel.tsx +++ b/app/src/modules/visualization/widgets/panel/Panel.tsx @@ -5,94 +5,46 @@ import { useAsset3dWidget, useSocketStore } from "../../../../store/store"; import { usePlayButtonStore } from "../../../../store/usePlayButtonStore"; import { useWidgetStore } from "../../../../store/useWidgetStore"; import { DraggableWidget } from "../2d/DraggableWidget"; +import { useSelectedZoneStore } from "../../../../store/useZoneStore"; type Side = "top" | "bottom" | "left" | "right"; -interface Widget { - id: string; - type: string; - title: string; - panel: Side; - data: any; -} - interface PanelProps { - selectedZone: { - zoneName: string; - activeSides: Side[]; - panelOrder: Side[]; - lockedPanels: Side[]; - points: []; - zoneId: string; - zoneViewPortTarget: number[]; - zoneViewPortPosition: number[]; - widgets: Widget[]; - }; - setSelectedZone: React.Dispatch< - React.SetStateAction<{ - zoneName: string; - activeSides: Side[]; - panelOrder: Side[]; - lockedPanels: Side[]; - points: []; - zoneId: string; - zoneViewPortTarget: number[]; - zoneViewPortPosition: number[]; - widgets: Widget[]; - }> - >; hiddenPanels: any; setZonesData: React.Dispatch<React.SetStateAction<any>>; } +const generateUniqueId = () =>`${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; -const generateUniqueId = () => - `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; - -const Panel: React.FC<PanelProps> = ({ - selectedZone, - setSelectedZone, - hiddenPanels, - setZonesData, -}) => { - const { widgetSelect, setWidgetSelect } = useAsset3dWidget(); - const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({}); - const [panelDimensions, setPanelDimensions] = useState<{ - [side in Side]?: { width: number; height: number }; - }>({}); - const [openKebabId, setOpenKebabId] = useState<string | null>(null); +const Panel: React.FC<PanelProps> = ({hiddenPanels,setZonesData,}) => { + //zustand state + const { selectedZone, setSelectedZone } = useSelectedZoneStore(); const { isPlaying } = usePlayButtonStore(); const { visualizationSocket } = useSocketStore(); - const [canvasDimensions, setCanvasDimensions] = useState({ - width: 0, - height: 0, - }); + + const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({}); + const [panelDimensions, setPanelDimensions] = useState<{ [side in Side]?: { width: number; height: number }; }>({}); + const [openKebabId, setOpenKebabId] = useState<string | null>(null); + const [canvasDimensions, setCanvasDimensions] = useState({ width: 0, height: 0, }); // Track canvas dimensions useEffect(() => { const canvas = document.getElementById("real-time-vis-canvas"); if (!canvas) return; - const updateCanvasDimensions = () => { const rect = canvas.getBoundingClientRect(); - setCanvasDimensions({ - width: rect.width, - height: rect.height, - }); + setCanvasDimensions({ width: rect.width, height: rect.height, }); }; - updateCanvasDimensions(); const resizeObserver = new ResizeObserver(updateCanvasDimensions); resizeObserver.observe(canvas); - return () => resizeObserver.unobserve(canvas); }, []); - - // Calculate panel size - const panelSize = Math.max( - Math.min(canvasDimensions.width * 0.25, canvasDimensions.height * 0.25), - 170 // Min 170px - ); - + // Calculate panel size // Min 170px + const panelSize = Math.max(Math.min(canvasDimensions.width * 0.25, canvasDimensions.height * 0.25), 170); + // Check if panel is locked + const isPanelLocked = (panel: Side) => selectedZone.lockedPanels.includes(panel); + // Get current widget count in a panel + const getCurrentWidgetCount = (panel: Side) => selectedZone.widgets.filter((w) => w.panel === panel).length; // Define getPanelStyle const getPanelStyle = useMemo( () => (side: Side) => { @@ -108,8 +60,7 @@ const Panel: React.FC<PanelProps> = ({ case "bottom": return { minWidth: "170px", - width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0) - }px)`, + width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)}px)`, minHeight: "170px", height: `${panelSize}px`, left: leftActive ? `${panelSize}px` : "0", @@ -122,8 +73,7 @@ const Panel: React.FC<PanelProps> = ({ minWidth: "170px", width: `${panelSize}px`, minHeight: "170px", - height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0) - }px)`, + height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)}px)`, top: topActive ? `${panelSize}px` : "0", bottom: bottomActive ? `${panelSize}px` : "0", [side]: "0", @@ -134,82 +84,54 @@ const Panel: React.FC<PanelProps> = ({ }, [selectedZone.panelOrder, panelSize] ); - // Handle drop event const handleDrop = (e: React.DragEvent, panel: Side) => { e.preventDefault(); const { draggedAsset } = useWidgetStore.getState(); - if ( - !draggedAsset || - isPanelLocked(panel) || - hiddenPanels[selectedZone.zoneId]?.includes(panel) - ) - return; + if (!draggedAsset || isPanelLocked(panel) || hiddenPanels[selectedZone.zoneId]?.includes(panel)) return; const currentWidgetsCount = getCurrentWidgetCount(panel); const maxCapacity = calculatePanelCapacity(panel); - - if (currentWidgetsCount < maxCapacity) { addWidgetToPanel(draggedAsset, panel); } }; - - // Check if panel is locked - const isPanelLocked = (panel: Side) => - selectedZone.lockedPanels.includes(panel); - - // Get current widget count in a panel - const getCurrentWidgetCount = (panel: Side) => - selectedZone.widgets.filter((w) => w.panel === panel).length; - // Calculate panel capacity const calculatePanelCapacity = (panel: Side) => { const CHART_WIDTH = panelSize - 10; const CHART_HEIGHT = panelSize - 10; - const dimensions = panelDimensions[panel]; if (!dimensions) { return panel === "top" || panel === "bottom" ? 5 : 3; // Fallback capacities } - - return panel === "top" || panel === "bottom" - ? Math.max(1, Math.floor(dimensions.width / CHART_WIDTH)) - : Math.max(1, Math.floor(dimensions.height / CHART_HEIGHT)); + return panel === "top" || panel === "bottom" ? Math.max(1, Math.floor(dimensions.width / CHART_WIDTH)) : Math.max(1, Math.floor(dimensions.height / CHART_HEIGHT)); }; - // Add widget to panel const addWidgetToPanel = async (asset: any, panel: Side) => { const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; - const newWidget = { ...asset, id: generateUniqueId(), panel, }; - let addWidget = { organization: organization, zoneId: selectedZone.zoneId, widget: newWidget, }; - if (visualizationSocket) { visualizationSocket.emit("v2:viz-widget:add", addWidget); } - setSelectedZone((prev) => ({ ...prev, widgets: [...prev.widgets, newWidget], })); }; - // Observe panel dimensions useEffect(() => { const observers: ResizeObserver[] = []; const currentPanelRefs = panelRefs.current; - selectedZone.activeSides.forEach((side) => { const element = currentPanelRefs[side]; if (element) { @@ -232,24 +154,18 @@ const Panel: React.FC<PanelProps> = ({ observers.forEach((observer) => observer.disconnect()); }; }, [selectedZone.activeSides]); - // Handle widget reordering const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => { setSelectedZone((prev) => { const widgetsInPanel = prev.widgets.filter((w) => w.panel === panel); const reorderedWidgets = arrayMove(widgetsInPanel, fromIndex, toIndex); - - const updatedWidgets = prev.widgets - .filter((widget) => widget.panel !== panel) - .concat(reorderedWidgets); - + const updatedWidgets = prev.widgets.filter((widget) => widget.panel !== panel).concat(reorderedWidgets); return { ...prev, widgets: updatedWidgets, }; }); }; - // Calculate capacities and dimensions const topWidth = getPanelStyle("top").width; const bottomWidth = getPanelStyle("bottom").height; @@ -283,41 +199,29 @@ const Panel: React.FC<PanelProps> = ({ <div key={side} id="panel-wrapper" - className={`panel ${side}-panel absolute ${hiddenPanels[selectedZone.zoneId]?.includes(side) ? "hidePanel" : "" - }`} + className={`panel ${side}-panel absolute ${hiddenPanels[selectedZone.zoneId]?.includes(side) ? "hidePanel" : ""}`} style={getPanelStyle(side)} onDrop={(e) => handleDrop(e, side)} onDragOver={(e) => e.preventDefault()} ref={(el) => { - if (el) { - panelRefs.current[side] = el; - } else { - delete panelRefs.current[side]; - } + if (el) { panelRefs.current[side] = el; } + else { delete panelRefs.current[side]; } }} > <div className={`panel-content ${isPlaying && "fullScreen"}`} style={{ - pointerEvents: - selectedZone.lockedPanels.includes(side) || - hiddenPanels[selectedZone.zoneId]?.includes(side) - ? "none" - : "auto", + pointerEvents:selectedZone.lockedPanels.includes(side) || hiddenPanels[selectedZone.zoneId]?.includes(side)? "none": "auto", opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1", }} > - {selectedZone.widgets - .filter((w) => w.panel === side) - .map((widget, index) => ( + {selectedZone.widgets.filter((w) => w.panel === side).map((widget, index) => ( <DraggableWidget hiddenPanels={hiddenPanels} widget={widget} key={widget.id} index={index} - onReorder={(fromIndex, toIndex) => - handleReorder(fromIndex, toIndex, side) - } + onReorder={(fromIndex, toIndex) =>handleReorder(fromIndex, toIndex, side)} openKebabId={openKebabId} setOpenKebabId={setOpenKebabId} selectedZone={selectedZone} diff --git a/app/src/modules/visualization/zoneAssets.tsx b/app/src/modules/visualization/zoneAssets.tsx index 7a48196..c36d8b6 100644 --- a/app/src/modules/visualization/zoneAssets.tsx +++ b/app/src/modules/visualization/zoneAssets.tsx @@ -1,81 +1,59 @@ import React, { useEffect, useRef } from 'react' -import { useSelectedFloorItem, useZoneAssetId } from '../../store/store'; +import { useSelectedFloorItem, useZoneAssetId, useToggleView } from '../../store/store'; import * as THREE from "three"; import { useThree } from '@react-three/fiber'; -import * as Types from "../../types/world/worldTypes"; export default function ZoneAssets() { - const { zoneAssetId, setZoneAssetId } = useZoneAssetId(); + const { zoneAssetId } = useZoneAssetId(); const { setSelectedFloorItem } = useSelectedFloorItem(); - const { raycaster, controls, scene }: any = useThree(); + const { toggleView } = useToggleView(); + const { controls, scene }: any = useThree(); + + function focusAsset(AssetMesh: any) { + console.log('AssetMesh: ', AssetMesh); + if (toggleView) return; + const bbox = new THREE.Box3().setFromObject(AssetMesh); + const size = bbox.getSize(new THREE.Vector3()); + const center = bbox.getCenter(new THREE.Vector3()); + + const front = new THREE.Vector3(0, 0, 1); + AssetMesh.localToWorld(front); + front.sub(AssetMesh.position).normalize(); + + const distance = Math.max(size.x, size.y, size.z) * 2; + const newPosition = center.clone().addScaledVector(front, distance); + + controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true); + controls.setTarget(center.x, center.y, center.z, true); + controls.fitToBox(AssetMesh, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, }); + + setSelectedFloorItem(AssetMesh); + } + useEffect(() => { - // console.log('zoneAssetId: ', zoneAssetId); if (!zoneAssetId) return - console.log('zoneAssetId: ', zoneAssetId); let AssetMesh = scene.getObjectByProperty("uuid", zoneAssetId.id); + if (AssetMesh) { - const bbox = new THREE.Box3().setFromObject(AssetMesh); - const size = bbox.getSize(new THREE.Vector3()); - const center = bbox.getCenter(new THREE.Vector3()); - - const front = new THREE.Vector3(0, 0, 1); - AssetMesh.localToWorld(front); - front.sub(AssetMesh.position).normalize(); - - const distance = Math.max(size.x, size.y, size.z) * 2; - const newPosition = center.clone().addScaledVector(front, distance); - - controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true); - controls.setTarget(center.x, center.y, center.z, true); - controls.fitToBox(AssetMesh, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, }); - - setSelectedFloorItem(AssetMesh); + focusAsset(AssetMesh) } else { - console.log('zoneAssetId: ', zoneAssetId) if (Array.isArray(zoneAssetId.position) && zoneAssetId.position.length >= 3) { - let selectedAssetPosition = [ - zoneAssetId.position[0], - 10, - zoneAssetId.position[2] - ]; - console.log('selectedAssetPosition: ', selectedAssetPosition); - let selectedAssetTarget = [ - zoneAssetId.position[0], - zoneAssetId.position[1], - zoneAssetId.position[2] - ]; - console.log('selectedAssetTarget: ', selectedAssetTarget); - const setCam = async () => { + let selectedAssetPosition = [zoneAssetId.position[0], 10, zoneAssetId.position[2]]; + let selectedAssetTarget = [zoneAssetId.position[0], zoneAssetId.position[1], zoneAssetId.position[2]]; + const setCamera = async () => { await controls?.setLookAt(...selectedAssetPosition, ...selectedAssetTarget, true); setTimeout(() => { let AssetMesh = scene.getObjectByProperty("uuid", zoneAssetId.id); if (AssetMesh) { - const bbox = new THREE.Box3().setFromObject(AssetMesh); - const size = bbox.getSize(new THREE.Vector3()); - const center = bbox.getCenter(new THREE.Vector3()); - - const front = new THREE.Vector3(0, 0, 1); - AssetMesh.localToWorld(front); - front.sub(AssetMesh.position).normalize(); - - const distance = Math.max(size.x, size.y, size.z) * 2; - const newPosition = center.clone().addScaledVector(front, distance); - - controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true); - controls.setTarget(center.x, center.y, center.z, true); - controls.fitToBox(AssetMesh, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, }); - - setSelectedFloorItem(AssetMesh); + focusAsset(AssetMesh) } }, 500) }; - setCam(); + setCamera(); } } }, [zoneAssetId, scene, controls]) - - return ( <> </>