feat: enhance camera controls and switch view functionality with 3D toggle integration
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user