diff --git a/app/src/components/layout/controls/ControlsPlayer.tsx b/app/src/components/layout/controls/ControlsPlayer.tsx index 4f897d2..724c3bb 100644 --- a/app/src/components/layout/controls/ControlsPlayer.tsx +++ b/app/src/components/layout/controls/ControlsPlayer.tsx @@ -1,23 +1,44 @@ -import React, { useState } from "react"; -import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; +import React, { useEffect, useState } from "react"; +import useCameraModeStore, { + usePlayButtonStore, +} from "../../../store/usePlayButtonStore"; import useModuleStore from "../../../store/useModuleStore"; import { PlayIcon } from "../../icons/ShortcutIcons"; import InputToggle from "../../ui/inputs/InputToggle"; import { EyeCloseIcon, WalkIcon } from "../../icons/ExportCommonIcons"; import { ExitIcon } from "../../icons/SimulationIcons"; +import { useCamMode } from "../../../store/builder/store"; -const ControlsPlayer = () => { +const ControlsPlayer: React.FC = () => { const { setIsPlaying } = usePlayButtonStore(); const { activeModule } = useModuleStore(); - const [walkMode, setWalkMode] = useState(false); + const { walkMode, toggleWalkMode } = useCameraModeStore(); const [hidePlayer, setHidePlayer] = useState(false); + const { camMode } = useCamMode(); const changeCamMode = () => { - setWalkMode(!walkMode); - console.log("switch camera mode to first person"); + toggleWalkMode(); + 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 ( -
+
{!hidePlayer && (
@@ -26,7 +47,7 @@ const ControlsPlayer = () => { )}
- {!hidePlayer && ( + {!hidePlayer && activeModule === "builder" && (
{ const { camMode, setCamMode } = useCamMode(); @@ -65,26 +66,14 @@ const CamMode: React.FC = () => { const keyCombination = detectModifierKeys(event); if (keyCombination === "/" && !isTransitioning && !toggleView) { - 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(false); + firstPersonCamera({ + setIsTransitioning, + state, + camMode, + setCamMode, + switchToFirstPerson, + switchToThirdPerson, + }); } }; @@ -92,6 +81,7 @@ const CamMode: React.FC = () => { return () => { window.removeEventListener("keydown", handleKeyPress); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ camMode, isTransitioning, @@ -140,6 +130,3 @@ const CamMode: React.FC = () => { }; export default CamMode; - - - diff --git a/app/src/modules/scene/camera/firstPersonCamera.ts b/app/src/modules/scene/camera/firstPersonCamera.ts new file mode 100644 index 0000000..85aacb3 --- /dev/null +++ b/app/src/modules/scene/camera/firstPersonCamera.ts @@ -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; + switchToThirdPerson: (controls: any, camera: any) => Promise; +} + +export async function firstPersonCamera({ + setIsTransitioning, + state, + camMode, + setCamMode, + switchToFirstPerson, + switchToThirdPerson +}: FirstPersonCameraParams): Promise { + 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); +} diff --git a/app/src/store/usePlayButtonStore.ts b/app/src/store/usePlayButtonStore.ts index bed2bd7..fe85d6a 100644 --- a/app/src/store/usePlayButtonStore.ts +++ b/app/src/store/usePlayButtonStore.ts @@ -33,3 +33,17 @@ export const useAnimationPlaySpeed = create((set) => ({ speed: 1, setSpeed: (value) => set({ speed: value }), })); + +interface CameraModeState { + walkMode: boolean; + setWalkMode: (enabled: boolean) => void; + toggleWalkMode: () => void; +} + +const useCameraModeStore = create((set) => ({ + walkMode: false, + setWalkMode: (enabled) => set({ walkMode: enabled }), + toggleWalkMode: () => set((state) => ({ walkMode: !state.walkMode })), +})); + +export default useCameraModeStore; diff --git a/app/src/styles/components/simulation/simulation.scss b/app/src/styles/components/simulation/simulation.scss index f95518e..28c28f4 100644 --- a/app/src/styles/components/simulation/simulation.scss +++ b/app/src/styles/components/simulation/simulation.scss @@ -358,7 +358,8 @@ } .controls-player-container { - max-width: 50vw; + min-width: 26vw; + max-width: 80vw; border-radius: 15px; gap: 40px; background: var(--background-color); @@ -375,6 +376,12 @@ isolation: isolate; font-weight: 700; padding: 8px; + transition: all 0.2s; + + &.hide { + min-width: none; + width: 92px; + } .controls-left, .controls-right { @@ -418,7 +425,7 @@ outline: 1px solid var(--border-color); color: var(--accent-color); } - &.hide{ + &.hide { width: 32px; } .icon { diff --git a/app/src/utils/shortcutkeys/handleShortcutKeys.ts b/app/src/utils/shortcutkeys/handleShortcutKeys.ts index 813d2cb..c4d8aa1 100644 --- a/app/src/utils/shortcutkeys/handleShortcutKeys.ts +++ b/app/src/utils/shortcutkeys/handleShortcutKeys.ts @@ -11,7 +11,7 @@ import { useToggleView, useToolMode, } from "../../store/builder/store"; -import { usePlayButtonStore } from "../../store/usePlayButtonStore"; +import useCameraModeStore, { usePlayButtonStore } from "../../store/usePlayButtonStore"; import { detectModifierKeys } from "./detectModifierKeys"; import { useSelectedZoneStore } from "../../store/visualization/useZoneStore"; @@ -29,6 +29,7 @@ const KeyPressListener: React.FC = () => { const { setActiveTool } = useActiveTool(); const { clearSelectedZone } = useSelectedZoneStore(); const { showShortcuts, setShowShortcuts } = useShortcutStore(); + const { setWalkMode } = useCameraModeStore(); const isTextInput = (element: Element | null): boolean => element instanceof HTMLInputElement || @@ -168,6 +169,7 @@ const KeyPressListener: React.FC = () => { } if (keyCombination === "ESCAPE") { + setWalkMode(false); setActiveTool("cursor"); setActiveSubTool("cursor"); setIsPlaying(false);