added ortho cam toggle

This commit is contained in:
2025-09-11 17:00:21 +05:30
parent f3302d3f33
commit f47b55333b
9 changed files with 77 additions and 89 deletions

View File

@@ -1,7 +1,7 @@
import { useEffect } from "react";
import { useParams } from "react-router-dom";
import { useLoadingProgress, useRenameModeStore, useIsComparing, useSelectedComment, useSocketStore, useWidgetSubOption } from "../../../store/builder/store";
import useModuleStore, { useThreeDStore } from "../../../store/ui/useModuleStore";
import { useLoadingProgress, useRenameModeStore, useIsComparing, useSelectedComment, useSocketStore, useWidgetSubOption, useToggleView } from "../../../store/builder/store";
import useModuleStore from "../../../store/ui/useModuleStore";
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore";
import { useFloatingWidget } from "../../../store/visualization/useDroppedObjectsStore";
@@ -39,7 +39,7 @@ function MainScene() {
const { activeModule } = useModuleStore();
const { selectedUser } = useSelectedUserStore();
const { loadingProgress } = useLoadingProgress();
const { toggleThreeD } = useThreeDStore();
const { toggleView } = useToggleView();
const { isPlaying } = usePlayButtonStore();
const { widgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore();
@@ -166,7 +166,7 @@ function MainScene() {
{loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
{!isPlaying && (
<>
{toggleThreeD && !isComparing && <ModuleToggle />}
{!toggleView && !isComparing && <ModuleToggle />}
<SideBarLeft />
<SideBarRight />
</>
@@ -181,7 +181,7 @@ function MainScene() {
<RenameTooltip name={selectedFloorAsset?.userData.modelName || selectedAssets[0].userData.modelName} onSubmit={handleObjectRename} />
)}
{/* remove this later */}
{activeModule === "builder" && !toggleThreeD && <SelectFloorPlan />}
{activeModule === "builder" && toggleView && <SelectFloorPlan />}
</>
)}
<div

View File

@@ -1,7 +1,7 @@
import React, { useEffect, useRef, useState } from "react";
import { AsileIcon, CommentIcon, CursorIcon, DeleteIcon, FloorIcon, FreeMoveIcon, MeasureToolIcon, PenIcon, PlayIcon, SaveTemplateIcon, WallIcon, ZoneIcon } from "../icons/ExportToolsIcons";
import { ArrowIcon, TickIcon } from "../icons/ExportCommonIcons";
import useModuleStore, { useThreeDStore } from "../../store/ui/useModuleStore";
import useModuleStore from "../../store/ui/useModuleStore";
import { handleSaveTemplate } from "../../modules/visualization/functions/handleSaveTemplate";
import { usePlayButtonStore } from "../../store/ui/usePlayButtonStore";
import useTemplateStore from "../../store/ui/useTemplateStore";
@@ -31,7 +31,6 @@ const ToolButton = ({ toolKey, toolId, icon: Icon, active, onClick, tooltip }: a
const Tools: React.FC = () => {
const { activeModule } = useModuleStore();
const { toggleThreeD, setToggleThreeD } = useThreeDStore();
const { isPlaying, setIsPlaying } = usePlayButtonStore();
const { showShortcuts } = useShortcutStore();
const { activeTool, setActiveTool, setToolMode } = useStoreHooks();
@@ -126,7 +125,6 @@ const Tools: React.FC = () => {
const toggle2D3D = () => {
const toggleTo2D = toggleView;
setToggleView(!toggleTo2D);
setToggleThreeD(toggleTo2D);
setToggleUI(toggleTo2D, toggleTo2D);
if (toggleTo2D) {
setSelectedWallAsset(null);
@@ -138,7 +136,7 @@ const Tools: React.FC = () => {
const renderBuilderTools = () => (
<>
{!toggleThreeD && (
{toggleView && (
<div className="draw-tools">
<ToolButton toolId="drawWall" icon={WallIcon} tooltip="draw wall (q)" active={activeTool === "draw-wall"} onClick={() => setActiveTool("draw-wall")} />
<ToolButton toolId="drawZone" icon={ZoneIcon} tooltip="draw zone (e)" active={activeTool === "draw-zone"} onClick={() => setActiveTool("draw-zone")} />
@@ -182,10 +180,10 @@ const Tools: React.FC = () => {
);
const renderModeSwitcher = () => (
<button id="toggle-threed-button" className={`toggle-threed-button${toggleThreeD ? " toggled" : ""}`} onClick={toggle2D3D}>
<button id="toggle-threed-button" className={`toggle-threed-button${!toggleView ? " toggled" : ""}`} onClick={toggle2D3D}>
<div className="tooltip">toggle view (tab)</div>
<div className={`toggle-option${!toggleThreeD ? " active" : ""}`}>2d</div>
<div className={`toggle-option${toggleThreeD ? " active" : ""}`}>3d</div>
<div className={`toggle-option${toggleView ? " active" : ""}`}>2d</div>
<div className={`toggle-option${!toggleView ? " active" : ""}`}>3d</div>
</button>
);
@@ -281,7 +279,7 @@ const Tools: React.FC = () => {
)}
</div>
{toggleThreeD && activeModule !== "visualization" && (
{!toggleView && activeModule !== "visualization" && (
<>
<div className="split"></div>
<div className="transform-tools">
@@ -300,7 +298,7 @@ const Tools: React.FC = () => {
<div className="split"></div>
<div className="general-options">
<ToolButton toolId="comment" icon={CommentIcon} tooltip="comment" active={activeTool === "comment"} onClick={() => setActiveTool("comment")} />
{toggleThreeD && <ToolButton toolId="play" icon={PlayIcon} tooltip="play (ctrl + p)" active={activeTool === "play"} onClick={() => setIsPlaying(!isPlaying)} />}
{!toggleView && <ToolButton toolId="play" icon={PlayIcon} tooltip="play (ctrl + p)" active={activeTool === "play"} onClick={() => setIsPlaying(!isPlaying)} />}
</div>
{activeModule === "builder" && (

View File

@@ -1,12 +1,17 @@
import { Vector3 } from "three";
import { useEffect } from "react";
import { useThree } from "@react-three/fiber";
import type { CameraControls } from "@react-three/drei";
import { useThreeDStore } from "../../../../store/ui/useModuleStore";
import { CameraControls } from "@react-three/drei";
import { useToggleView } from "../../../../store/builder/store";
import useModuleStore from "../../../../store/ui/useModuleStore";
import { useSceneStore } from "../../../../store/scene/useSceneStore";
import * as CONSTANTS from "../../../../types/world/worldConstants";
const CameraShortcutsControls = () => {
const { camera, controls } = useThree();
const { toggleThreeD, setToggleThreeD } = useThreeDStore();
const { toggleView } = useToggleView();
const { camType, setCamType } = useSceneStore();
const { activeModule } = useModuleStore();
const isTextInput = (element: Element | null): boolean => element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element?.getAttribute("contenteditable") === "true";
@@ -54,12 +59,16 @@ const CameraShortcutsControls = () => {
break;
}
case "Numpad5": {
if (!toggleThreeD) {
setToggleThreeD(true);
} else {
cc.setLookAt(0, distance, 0, target.x, target.y, target.z, false).then(() => {
setToggleThreeD(false);
});
if (!toggleView) {
if (camType === "perspective") {
setCamType("orthographic");
(controls as any).mouseButtons.left = CONSTANTS.twoDimension.leftMouse;
(controls as any).mouseButtons.right = CONSTANTS.twoDimension.rightMouse;
} else {
setCamType("perspective");
(controls as any).mouseButtons.left = CONSTANTS.threeDimension.leftMouse;
(controls as any).mouseButtons.right = CONSTANTS.threeDimension.rightMouse;
}
}
break;
}
@@ -72,7 +81,7 @@ const CameraShortcutsControls = () => {
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [controls, camera, toggleThreeD, setToggleThreeD]);
}, [controls, camera, camType, setCamType, toggleView, activeModule]);
return null;
};

View File

@@ -1,24 +1,24 @@
import { useEffect } from "react";
import { useThree } from "@react-three/fiber";
import * as THREE from "three";
import { PerspectiveCamera, OrthographicCamera, CameraControls } from "@react-three/drei";
import { useEffect } from "react";
import { useParams } from "react-router-dom";
import { useThree } from "@react-three/fiber";
import { PerspectiveCamera, OrthographicCamera, CameraControls } from "@react-three/drei";
import * as CONSTANTS from "../../../types/world/worldConstants";
import { getCameraApi } from "../../../services/factoryBuilder/camera/getCameraApi";
import { useToggleView } from "../../../store/builder/store";
import { useThreeDStore } from "../../../store/ui/useModuleStore";
import { useSceneStore } from "../../../store/scene/useSceneStore";
export default function SwitchView() {
const { toggleView } = useToggleView();
const { controls } = useThree();
const { camType } = useSceneStore();
const { projectId } = useParams();
const { toggleThreeD } = useThreeDStore();
useEffect(() => {
if (toggleView && controls) {
if ((toggleView || camType === "orthographic") && controls) {
(controls as any).mouseButtons.left = CONSTANTS.twoDimension.leftMouse;
(controls as any).mouseButtons.right = CONSTANTS.twoDimension.rightMouse;
} else {
} else if (!toggleView && camType === "perspective") {
if (!projectId) return;
getCameraApi(projectId)
.then((data) => {
@@ -41,11 +41,11 @@ export default function SwitchView() {
(controls as any).mouseButtons.right = CONSTANTS.threeDimension.rightMouse;
}
}
}, [toggleView, controls, projectId]);
}, [toggleView, controls, projectId, camType]);
return (
<>
{toggleView || !toggleThreeD ? (
{toggleView || camType === "orthographic" ? (
<OrthographicCamera
makeDefault
position={CONSTANTS.twoDimension.defaultPosition}

View File

@@ -4,6 +4,7 @@ import { useThree } from "@react-three/fiber";
import * as THREE from "three";
import * as CONSTANTS from "../../../types/world/worldConstants";
import { useSocketStore, useToggleView, useResetCamera } from "../../../store/builder/store";
import { useSceneStore } from "../../../store/scene/useSceneStore";
import CamMode from "../camera/camMode";
import SwitchView from "../camera/switchView";
@@ -24,10 +25,10 @@ import updateCamPosition from "../camera/functions/updateCameraPosition";
export default function Controls() {
const controlsRef = useRef<CameraControls>(null);
const state = useThree();
const { toggleView } = useToggleView();
const { resetCamera, setResetCamera } = useResetCamera();
const { camType } = useSceneStore();
const { socket } = useSocketStore();
const { projectId } = useParams();
const { userId, organization } = getUserData();
@@ -89,7 +90,7 @@ export default function Controls() {
let intervalId: NodeJS.Timeout | null = null;
const handleRest = () => {
if (hasInteracted && controlsRef.current && state.camera.position && !toggleView && socket) {
if (hasInteracted && controlsRef.current && state.camera.position && !toggleView && socket && camType === "perspective") {
const position = state.camera.position;
if (position.x === 0 && position.y === 0 && position.z === 0) return;
updateCamPosition(controlsRef, socket, position, state.camera.rotation, projectId);
@@ -101,7 +102,7 @@ export default function Controls() {
hasInteracted = true;
if (!intervalId) {
intervalId = setInterval(() => {
if (controlsRef.current && !toggleView) {
if (controlsRef.current && !toggleView && camType === "perspective") {
handleRest();
}
}, CONSTANTS.camPositionUpdateInterval);
@@ -116,7 +117,7 @@ export default function Controls() {
};
const controls = controlsRef.current;
if (controls) {
if (controls && !toggleView && camType === "perspective") {
controls.addEventListener("sleep", handleRest);
controls.addEventListener("control", startInterval);
controls.addEventListener("controlend", stopInterval);
@@ -130,20 +131,20 @@ export default function Controls() {
}
stopInterval();
};
}, [toggleView, state, socket]);
}, [toggleView, state, socket, camType]);
return (
<>
<CameraControls
makeDefault
ref={controlsRef}
minDistance={toggleView ? CONSTANTS.twoDimension.minDistance : CONSTANTS.threeDimension.minDistance}
minDistance={toggleView || camType === "orthographic" ? CONSTANTS.twoDimension.minDistance : CONSTANTS.threeDimension.minDistance}
maxDistance={CONSTANTS.thirdPersonControls.maxDistance}
minZoom={CONSTANTS.thirdPersonControls.minZoom}
maxZoom={CONSTANTS.thirdPersonControls.maxZoom}
maxPolarAngle={CONSTANTS.thirdPersonControls.maxPolarAngle}
camera={state.camera}
dollyToCursor={toggleView}
dollyToCursor={toggleView || camType === "orthographic"}
verticalDragToForward={true}
boundaryEnclosesCamera={true}
dollyDragInverted

View File

@@ -108,9 +108,7 @@ const MeasurementTool = () => {
!intersect.object.name.includes("zonePlane") &&
!intersect.object.name.includes("SelectionGroup") &&
!intersect.object.name.includes("selectionAssetGroup") &&
!intersect.object.name.includes(
"SelectionGroupBoundingBoxLine"
) &&
!intersect.object.name.includes("SelectionGroupBoundingBoxLine") &&
!intersect.object.name.includes("SelectionGroupBoundingBox") &&
!intersect.object.name.includes("SelectionGroupBoundingLine") &&
intersect.object.type !== "GridHelper"
@@ -119,10 +117,7 @@ const MeasurementTool = () => {
if (intersects.length > 0) {
let intersectionPoint = intersects[0].point.clone();
if (axisLock && points.length > 0) {
intersectionPoint = applyAxisLock(
intersectionPoint,
points[points.length - 1]
);
intersectionPoint = applyAxisLock(intersectionPoint, points[points.length - 1]);
}
if (points.length < 2) {
setPoints([...points, intersectionPoint]);
@@ -232,27 +227,14 @@ const MeasurementTool = () => {
)}
{points.map((point, index) => (
<Html
key={index}
position={point}
scale={0.5}
wrapperClass="measurement-label-wrapper"
className="measurement-label"
zIndexRange={[1, 0]}
prepend
sprite
>
<Html key={index} position={point} scale={0.5} wrapperClass="measurement-label-wrapper" className="measurement-label" zIndexRange={[1, 0]} prepend sprite>
<div className="measurement-point"></div>
</Html>
))}
{linePoints && linePoints.length === 2 && (
<Html
position={[
(linePoints[0].x + linePoints[1].x) / 2,
(linePoints[0].y + linePoints[1].y) / 2,
(linePoints[0].z + linePoints[1].z) / 2,
]}
position={[(linePoints[0].x + linePoints[1].x) / 2, (linePoints[0].y + linePoints[1].y) / 2, (linePoints[0].z + linePoints[1].z) / 2]}
scale={0.5}
wrapperClass="distance-text-wrapper"
className="distance-text"

View File

@@ -10,9 +10,13 @@ type SceneStore = {
target: THREE.Vector3;
};
camType: "orthographic" | "perspective";
setLimitFps: (limitFps: boolean) => void;
setFps: (fps: number) => void;
setCamera: (pos: THREE.Vector3, target: THREE.Vector3) => void;
setCamType: (type: "orthographic" | "perspective") => void;
};
export const useSceneStore = create<SceneStore>()(
@@ -24,6 +28,8 @@ export const useSceneStore = create<SceneStore>()(
target: new THREE.Vector3(0, 0, 0),
},
camType: "perspective",
setLimitFps: (limitFps) => {
set((state) => {
state.limitFps = limitFps;
@@ -36,11 +42,18 @@ export const useSceneStore = create<SceneStore>()(
});
},
setCamera: (pos, target) =>
setCamera: (pos, target) => {
set((state) => {
state.camState.position.copy(pos);
state.camState.target.copy(target);
}),
});
},
setCamType: (type) => {
set((state) => {
state.camType = type;
});
},
}))
);

View File

@@ -1,42 +1,29 @@
import { create } from "zustand";
interface ModuleStore {
activeModule: string;
setActiveModule: (module: string) => void;
activeModule: string;
setActiveModule: (module: string) => void;
}
const useModuleStore = create<ModuleStore>((set) => ({
activeModule: "builder", // Initial state
setActiveModule: (module) => set({ activeModule: module }), // Update state
activeModule: "builder", // Initial state
setActiveModule: (module) => set({ activeModule: module }), // Update state
}));
export default useModuleStore;
// New store for subModule
type SubModule = 'properties' | 'simulations' | 'mechanics' | 'analysis' | 'zoneProperties'|"resourceManagement";
type SubModule = "properties" | "simulations" | "mechanics" | "analysis" | "zoneProperties" | "resourceManagement";
interface SubModuleStore {
subModule: SubModule;
setSubModule: (subModule: SubModule) => void;
subModule: SubModule;
setSubModule: (subModule: SubModule) => void;
}
const useSubModuleStore = create<SubModuleStore>((set) => ({
subModule: "properties", // Initial subModule state
setSubModule: (value) => set({ subModule: value }), // Update subModule state
subModule: "properties", // Initial subModule state
setSubModule: (value) => set({ subModule: value }), // Update subModule state
}));
export { useSubModuleStore };
interface ThreeDState {
toggleThreeD: boolean;
setToggleThreeD: (value: boolean) => void;
}
// Create the Zustand store
const useThreeDStore = create<ThreeDState>((set) => ({
toggleThreeD: true, // Initial state
setToggleThreeD: (value) => set({ toggleThreeD: value }), // Action to update the state
}));
export { useThreeDStore };

View File

@@ -1,5 +1,5 @@
import React, { useEffect } from "react";
import useModuleStore, { useSubModuleStore, useThreeDStore } from "../../store/ui/useModuleStore";
import useModuleStore, { useSubModuleStore } from "../../store/ui/useModuleStore";
import { usePlayerStore, useToggleStore } from "../../store/ui/useUIToggleStore";
import {
useActiveSubTool,
@@ -29,7 +29,6 @@ const KeyPressListener: React.FC = () => {
const { setSubModule } = useSubModuleStore();
const { setActiveSubTool } = useActiveSubTool();
const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore();
const { setToggleThreeD } = useThreeDStore();
const { setToolMode } = useToolMode();
const { isPlaying, setIsPlaying } = usePlayButtonStore();
const { toggleView, setToggleView } = useToggleView();
@@ -83,7 +82,6 @@ const KeyPressListener: React.FC = () => {
if (key === "TAB") {
const toggleTo2D = toggleView;
setToggleView(!toggleTo2D);
setToggleThreeD(toggleTo2D);
if (toggleTo2D) {
setSelectedWallAsset(null);
setToggleUI(localStorage.getItem("navBarUiLeft") !== "false", localStorage.getItem("navBarUiRight") !== "false");