refactor: Enhance ControlsPlayer and CamMode for improved camera mode handling and UI responsiveness
This commit is contained in:
parent
8facad31bc
commit
9cd08f75e3
|
@ -1,23 +1,44 @@
|
||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
import useCameraModeStore, {
|
||||||
|
usePlayButtonStore,
|
||||||
|
} from "../../../store/usePlayButtonStore";
|
||||||
import useModuleStore from "../../../store/useModuleStore";
|
import useModuleStore from "../../../store/useModuleStore";
|
||||||
import { PlayIcon } from "../../icons/ShortcutIcons";
|
import { PlayIcon } from "../../icons/ShortcutIcons";
|
||||||
import InputToggle from "../../ui/inputs/InputToggle";
|
import InputToggle from "../../ui/inputs/InputToggle";
|
||||||
import { EyeCloseIcon, WalkIcon } from "../../icons/ExportCommonIcons";
|
import { EyeCloseIcon, WalkIcon } from "../../icons/ExportCommonIcons";
|
||||||
import { ExitIcon } from "../../icons/SimulationIcons";
|
import { ExitIcon } from "../../icons/SimulationIcons";
|
||||||
|
import { useCamMode } from "../../../store/builder/store";
|
||||||
|
|
||||||
const ControlsPlayer = () => {
|
const ControlsPlayer: React.FC = () => {
|
||||||
const { setIsPlaying } = usePlayButtonStore();
|
const { setIsPlaying } = usePlayButtonStore();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const [walkMode, setWalkMode] = useState(false);
|
const { walkMode, toggleWalkMode } = useCameraModeStore();
|
||||||
const [hidePlayer, setHidePlayer] = useState(false);
|
const [hidePlayer, setHidePlayer] = useState(false);
|
||||||
|
const { camMode } = useCamMode();
|
||||||
|
|
||||||
const changeCamMode = () => {
|
const changeCamMode = () => {
|
||||||
setWalkMode(!walkMode);
|
toggleWalkMode();
|
||||||
console.log("switch camera mode to first person");
|
echo.log("switch camera mode to first person");
|
||||||
|
// Simulate "/" keypress
|
||||||
|
const slashKeyEvent = new KeyboardEvent("keydown", {
|
||||||
|
key: "/",
|
||||||
|
code: "Slash",
|
||||||
|
keyCode: 191, // for compatibility
|
||||||
|
which: 191,
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
});
|
||||||
|
document.dispatchEvent(slashKeyEvent);
|
||||||
};
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (camMode === "ThirdPerson") {
|
||||||
|
toggleWalkMode();
|
||||||
|
} else return;
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [camMode]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="controls-player-container">
|
<div className={`controls-player-container${hidePlayer ? " hide" : ""}`}>
|
||||||
{!hidePlayer && (
|
{!hidePlayer && (
|
||||||
<div className="controls-left">
|
<div className="controls-left">
|
||||||
<PlayIcon />
|
<PlayIcon />
|
||||||
|
@ -26,7 +47,7 @@ const ControlsPlayer = () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="controls-right">
|
<div className="controls-right">
|
||||||
{!hidePlayer && (
|
{!hidePlayer && activeModule === "builder" && (
|
||||||
<div className="walkMode-wrapper">
|
<div className="walkMode-wrapper">
|
||||||
<WalkIcon />
|
<WalkIcon />
|
||||||
<InputToggle
|
<InputToggle
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { useKeyboardControls } from "@react-three/drei";
|
||||||
import switchToThirdPerson from "./switchToThirdPerson";
|
import switchToThirdPerson from "./switchToThirdPerson";
|
||||||
import switchToFirstPerson from "./switchToFirstPerson";
|
import switchToFirstPerson from "./switchToFirstPerson";
|
||||||
import { detectModifierKeys } from "../../../utils/shortcutkeys/detectModifierKeys";
|
import { detectModifierKeys } from "../../../utils/shortcutkeys/detectModifierKeys";
|
||||||
|
import { firstPersonCamera } from "./firstPersonCamera";
|
||||||
|
|
||||||
const CamMode: React.FC = () => {
|
const CamMode: React.FC = () => {
|
||||||
const { camMode, setCamMode } = useCamMode();
|
const { camMode, setCamMode } = useCamMode();
|
||||||
|
@ -65,26 +66,14 @@ const CamMode: React.FC = () => {
|
||||||
const keyCombination = detectModifierKeys(event);
|
const keyCombination = detectModifierKeys(event);
|
||||||
|
|
||||||
if (keyCombination === "/" && !isTransitioning && !toggleView) {
|
if (keyCombination === "/" && !isTransitioning && !toggleView) {
|
||||||
setIsTransitioning(true);
|
firstPersonCamera({
|
||||||
|
setIsTransitioning,
|
||||||
state.controls.mouseButtons.left =
|
state,
|
||||||
CONSTANTS.controlsTransition.leftMouse;
|
camMode,
|
||||||
state.controls.mouseButtons.right =
|
setCamMode,
|
||||||
CONSTANTS.controlsTransition.rightMouse;
|
switchToFirstPerson,
|
||||||
state.controls.mouseButtons.wheel =
|
switchToThirdPerson,
|
||||||
CONSTANTS.controlsTransition.wheelMouse;
|
});
|
||||||
state.controls.mouseButtons.middle =
|
|
||||||
CONSTANTS.controlsTransition.middleMouse;
|
|
||||||
|
|
||||||
if (camMode === "ThirdPerson") {
|
|
||||||
setCamMode("FirstPerson");
|
|
||||||
await switchToFirstPerson(state.controls, state.camera);
|
|
||||||
} else if (camMode === "FirstPerson") {
|
|
||||||
setCamMode("ThirdPerson");
|
|
||||||
await switchToThirdPerson(state.controls, state.camera);
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsTransitioning(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,6 +81,7 @@ const CamMode: React.FC = () => {
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("keydown", handleKeyPress);
|
window.removeEventListener("keydown", handleKeyPress);
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [
|
}, [
|
||||||
camMode,
|
camMode,
|
||||||
isTransitioning,
|
isTransitioning,
|
||||||
|
@ -140,6 +130,3 @@ const CamMode: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CamMode;
|
export default CamMode;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import * as CONSTANTS from "../../../types/world/worldConstants";
|
||||||
|
|
||||||
|
interface FirstPersonCameraProps {
|
||||||
|
setIsTransitioning?: (value: boolean) => void;
|
||||||
|
state: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FirstPersonCameraParams extends FirstPersonCameraProps {
|
||||||
|
camMode: string;
|
||||||
|
setCamMode: (mode: string) => void;
|
||||||
|
switchToFirstPerson: (controls: any, camera: any) => Promise<void>;
|
||||||
|
switchToThirdPerson: (controls: any, camera: any) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function firstPersonCamera({
|
||||||
|
setIsTransitioning,
|
||||||
|
state,
|
||||||
|
camMode,
|
||||||
|
setCamMode,
|
||||||
|
switchToFirstPerson,
|
||||||
|
switchToThirdPerson
|
||||||
|
}: FirstPersonCameraParams): Promise<void> {
|
||||||
|
setIsTransitioning && setIsTransitioning(true);
|
||||||
|
|
||||||
|
state.controls.mouseButtons.left = CONSTANTS.controlsTransition.leftMouse;
|
||||||
|
state.controls.mouseButtons.right = CONSTANTS.controlsTransition.rightMouse;
|
||||||
|
state.controls.mouseButtons.wheel = CONSTANTS.controlsTransition.wheelMouse;
|
||||||
|
state.controls.mouseButtons.middle = CONSTANTS.controlsTransition.middleMouse;
|
||||||
|
|
||||||
|
if (camMode === "ThirdPerson") {
|
||||||
|
setCamMode("FirstPerson");
|
||||||
|
await switchToFirstPerson(state.controls, state.camera);
|
||||||
|
} else if (camMode === "FirstPerson") {
|
||||||
|
setCamMode("ThirdPerson");
|
||||||
|
await switchToThirdPerson(state.controls, state.camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsTransitioning && setIsTransitioning(false);
|
||||||
|
}
|
|
@ -33,3 +33,17 @@ export const useAnimationPlaySpeed = create<AnimationSpeedState>((set) => ({
|
||||||
speed: 1,
|
speed: 1,
|
||||||
setSpeed: (value) => set({ speed: value }),
|
setSpeed: (value) => set({ speed: value }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
interface CameraModeState {
|
||||||
|
walkMode: boolean;
|
||||||
|
setWalkMode: (enabled: boolean) => void;
|
||||||
|
toggleWalkMode: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useCameraModeStore = create<CameraModeState>((set) => ({
|
||||||
|
walkMode: false,
|
||||||
|
setWalkMode: (enabled) => set({ walkMode: enabled }),
|
||||||
|
toggleWalkMode: () => set((state) => ({ walkMode: !state.walkMode })),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default useCameraModeStore;
|
||||||
|
|
|
@ -358,7 +358,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.controls-player-container {
|
.controls-player-container {
|
||||||
max-width: 50vw;
|
min-width: 26vw;
|
||||||
|
max-width: 80vw;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
gap: 40px;
|
gap: 40px;
|
||||||
background: var(--background-color);
|
background: var(--background-color);
|
||||||
|
@ -375,6 +376,12 @@
|
||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
&.hide {
|
||||||
|
min-width: none;
|
||||||
|
width: 92px;
|
||||||
|
}
|
||||||
|
|
||||||
.controls-left,
|
.controls-left,
|
||||||
.controls-right {
|
.controls-right {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
useToggleView,
|
useToggleView,
|
||||||
useToolMode,
|
useToolMode,
|
||||||
} from "../../store/builder/store";
|
} from "../../store/builder/store";
|
||||||
import { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
import useCameraModeStore, { usePlayButtonStore } from "../../store/usePlayButtonStore";
|
||||||
import { detectModifierKeys } from "./detectModifierKeys";
|
import { detectModifierKeys } from "./detectModifierKeys";
|
||||||
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ const KeyPressListener: React.FC = () => {
|
||||||
const { setActiveTool } = useActiveTool();
|
const { setActiveTool } = useActiveTool();
|
||||||
const { clearSelectedZone } = useSelectedZoneStore();
|
const { clearSelectedZone } = useSelectedZoneStore();
|
||||||
const { showShortcuts, setShowShortcuts } = useShortcutStore();
|
const { showShortcuts, setShowShortcuts } = useShortcutStore();
|
||||||
|
const { setWalkMode } = useCameraModeStore();
|
||||||
|
|
||||||
const isTextInput = (element: Element | null): boolean =>
|
const isTextInput = (element: Element | null): boolean =>
|
||||||
element instanceof HTMLInputElement ||
|
element instanceof HTMLInputElement ||
|
||||||
|
@ -168,6 +169,7 @@ const KeyPressListener: React.FC = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyCombination === "ESCAPE") {
|
if (keyCombination === "ESCAPE") {
|
||||||
|
setWalkMode(false);
|
||||||
setActiveTool("cursor");
|
setActiveTool("cursor");
|
||||||
setActiveSubTool("cursor");
|
setActiveSubTool("cursor");
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
|
|
Loading…
Reference in New Issue