import { useFrame, useThree } from "@react-three/fiber"; import React, { useEffect, useState } from "react"; import * as CONSTANTS from "../../../types/world/worldConstants"; import { useCamMode, useToggleView } from "../../../store/builder/store"; import { useKeyboardControls } from "@react-three/drei"; import switchToThirdPerson from "./switchToThirdPerson"; import switchToFirstPerson from "./switchToFirstPerson"; import { detectModifierKeys } from "../../../utils/shortcutkeys/detectModifierKeys"; import { firstPersonCamera } from "./firstPersonCamera"; const CamMode: React.FC = () => { const { camMode, setCamMode } = useCamMode(); const [, get] = useKeyboardControls(); const [isTransitioning, setIsTransitioning] = useState(false); const state: any = useThree(); const { toggleView } = useToggleView(); const [isShiftActive, setIsShiftActive] = useState(false); useEffect(() => { const handlePointerLockChange = async () => { if (document.pointerLockElement && !toggleView) { // Pointer is locked } else if (camMode === "FirstPerson" && !toggleView) { // Pointer is unlocked setCamMode("ThirdPerson"); await switchToThirdPerson(state.controls, state.camera); } }; document.addEventListener("pointerlockchange", handlePointerLockChange); return () => { document.removeEventListener( "pointerlockchange", handlePointerLockChange ); }; }, [camMode, toggleView, setCamMode, state.controls, state.camera]); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (event.key === "Shift") { setIsShiftActive(true); } }; const handleKeyUp = (event: KeyboardEvent) => { if (event.key === "Shift") { setIsShiftActive(false); } }; window.addEventListener("keydown", handleKeyDown); window.addEventListener("keyup", handleKeyUp); return () => { window.removeEventListener("keydown", handleKeyDown); window.removeEventListener("keyup", handleKeyUp); }; }, []); useEffect(() => { const handleKeyPress = async (event: KeyboardEvent) => { if (!state.controls) return; const keyCombination = detectModifierKeys(event); if (keyCombination === "/" && !isTransitioning && !toggleView) { firstPersonCamera({ setIsTransitioning, state, camMode, setCamMode, switchToFirstPerson, switchToThirdPerson, }); } }; window.addEventListener("keydown", handleKeyPress); return () => { window.removeEventListener("keydown", handleKeyPress); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [ camMode, isTransitioning, toggleView, state.controls, state.camera, setCamMode, ]); useFrame(() => { const { forward, backward, left, right } = get(); if (!state.controls) return; if (camMode === "ThirdPerson" || !document.pointerLockElement) return; const speedMultiplier = isShiftActive ? 4 : 1; if (forward) { state.controls.forward( CONSTANTS.firstPersonControls.forwardSpeed * speedMultiplier, true ); } if (backward) { state.controls.forward( CONSTANTS.firstPersonControls.backwardSpeed * speedMultiplier, true ); } if (left) { state.controls.truck( CONSTANTS.firstPersonControls.leftSpeed * speedMultiplier, 0, true ); } if (right) { state.controls.truck( CONSTANTS.firstPersonControls.rightSpeed * speedMultiplier, 0, true ); } }); return null; // This component does not render any UI }; export default CamMode;