feat: enhance camera controls and switch view functionality with 3D toggle integration

This commit is contained in:
2025-09-11 10:14:17 +05:30
parent 767e301776
commit 0f478e8e1a
2 changed files with 57 additions and 29 deletions

View File

@@ -1,10 +1,13 @@
import { Vector3 } from "three";
import { useEffect } from "react";
import { useThree } from "@react-three/fiber";
import * as THREE from "three";
import type { CameraControls } from "@react-three/drei";
import { useThreeDStore } from "../../../../store/ui/useModuleStore";
import * as CONSTANTS from "../../../../types/world/worldConstants";
const CameraShortcutsControls = () => {
const { camera, controls } = useThree();
const { toggleThreeD, setToggleThreeD } = useThreeDStore();
const isTextInput = (element: Element | null): boolean =>
element instanceof HTMLInputElement ||
@@ -18,54 +21,77 @@ const CameraShortcutsControls = () => {
const cc = controls as CameraControls;
// get current target
const target = new THREE.Vector3();
const target = new Vector3();
cc.getTarget(target);
const distance = camera.position.distanceTo(target);
let pos: THREE.Vector3 | null = null;
let pos: Vector3 | null = null;
const dir = new THREE.Vector3().subVectors(camera.position, target).normalize();
const dir = new Vector3().subVectors(camera.position, target).normalize();
if (isTextInput(document.activeElement)) return;
switch (e.key) {
case "1": // Front
pos = new THREE.Vector3(0, 0, distance).add(target);
switch (e.code) {
case "Numpad1": // Front
pos = new Vector3(0, 0, distance).add(target);
LookAt(pos);
break;
case "3": // Right
pos = new THREE.Vector3(distance, 0, 0).add(target);
case "Numpad3": // Right
pos = new Vector3(distance, 0, 0).add(target);
LookAt(pos);
break;
case "7": // Top
pos = new THREE.Vector3(0, distance, 0).add(target);
case "Numpad7": // Top
pos = new Vector3(0, distance, 0).add(target);
LookAt(pos);
break;
case "9": {
case "Numpad9": {
// Opposite view logic
if (Math.abs(dir.z) > Math.abs(dir.x) && Math.abs(dir.z) > Math.abs(dir.y)) {
// Currently looking Front/Back → flip Z
pos = new THREE.Vector3(0, 0, -Math.sign(dir.z) * distance).add(target);
} else if (Math.abs(dir.x) > Math.abs(dir.z) && Math.abs(dir.x) > Math.abs(dir.y)) {
// Currently looking Right/Left → flip X
pos = new THREE.Vector3(-Math.sign(dir.x) * distance, 0, 0).add(target);
pos = new Vector3(0, 0, -Math.sign(dir.z) * distance).add(target);
LookAt(pos);
} else if (
Math.abs(dir.x) > Math.abs(dir.z) &&
Math.abs(dir.x) > Math.abs(dir.y)
) {
pos = new Vector3(-Math.sign(dir.x) * distance, 0, 0).add(target);
LookAt(pos);
} else {
// Currently looking Top/Bottom → stay Top
pos = new THREE.Vector3(0, distance, 0).add(target);
pos = new Vector3(0, distance, 0).add(target);
LookAt(pos);
}
break;
}
case "Numpad5": {
// Only apply when on Top view
if (!toggleThreeD) {
console.log("cc: ", cc.camera);
setToggleThreeD(true);
(cc as any).mouseButtons.left = CONSTANTS.threeDimension.leftMouse;
(cc as any).mouseButtons.right = CONSTANTS.threeDimension.rightMouse;
} else {
console.log("cc: ", cc.camera);
cc.setLookAt(0, distance, 0, target.x, target.y, target.z, false).then(
() => {
setToggleThreeD(false);
(cc as any).mouseButtons.left = CONSTANTS.twoDimension.leftMouse;
(cc as any).mouseButtons.right = CONSTANTS.twoDimension.rightMouse;
}
);
}
break;
}
}
if (pos) {
cc.setLookAt(
pos.x, pos.y, pos.z, // camera position
target.x, target.y, target.z, // keep same target
true // smooth transition
);
function LookAt(pos: Vector3) {
console.log('hi lookat');
cc.setLookAt(pos.x, pos.y, pos.z, target.x, target.y, target.z, true);
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [controls, camera]);
}, [controls, camera, toggleThreeD, setToggleThreeD]);
return null;
};

View File

@@ -6,11 +6,13 @@ import { useParams } from "react-router-dom";
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";
export default function SwitchView() {
const { toggleView } = useToggleView();
const { controls } = useThree();
const { projectId } = useParams();
const { toggleThreeD } = useThreeDStore();
useEffect(() => {
if (toggleView && controls) {
@@ -39,11 +41,11 @@ export default function SwitchView() {
(controls as any).mouseButtons.right = CONSTANTS.threeDimension.rightMouse;
}
}
}, [toggleView, controls]);
}, [toggleView, controls, projectId]);
return (
<>
{toggleView ? (
{(toggleView || !toggleThreeD) ? (
<OrthographicCamera
makeDefault
position={CONSTANTS.twoDimension.defaultPosition}