import { useControls, useDebug, useSettings, type TouchMode, } from "./SettingsProvider"; import { MissionSelect } from "./MissionSelect"; import { useEffect, useState, useRef, RefObject } from "react"; import { CopyCoordinatesButton } from "./CopyCoordinatesButton"; import { LoadDemoButton } from "./LoadDemoButton"; import { JoinServerButton } from "./JoinServerButton"; import { useRecording } from "./RecordingProvider"; import { useLiveConnectionOptional } from "./LiveConnection"; import { FiInfo, FiSettings } from "react-icons/fi"; import { Camera } from "three"; import styles from "./InspectorControls.module.css"; export function InspectorControls({ missionName, missionType, onChangeMission, onOpenMapInfo, onOpenServerBrowser, isTouch, cameraRef, }: { missionName: string; missionType: string; onChangeMission: ({ missionName, missionType, }: { missionName: string; missionType: string; }) => void; onOpenMapInfo: () => void; onOpenServerBrowser?: () => void; isTouch: boolean | null; cameraRef: RefObject; }) { const { fogEnabled, setFogEnabled, fov, setFov, audioEnabled, setAudioEnabled, animationEnabled, setAnimationEnabled, } = useSettings(); const { speedMultiplier, setSpeedMultiplier, touchMode, setTouchMode } = useControls(); const { debugMode, setDebugMode } = useDebug(); const demoRecording = useRecording(); const live = useLiveConnectionOptional(); const isLive = live?.adapter != null; const isStreaming = demoRecording != null || isLive; // Hide FOV/speed controls during .rec playback (faithfully replaying), // but show them in .mis browsing and live observer mode. const hideViewControls = isStreaming && !isLive; const [settingsOpen, setSettingsOpen] = useState(false); const dropdownRef = useRef(null); const buttonRef = useRef(null); const focusAreaRef = useRef(null); // Focus the panel when it opens. useEffect(() => { if (settingsOpen) { dropdownRef.current?.focus(); } }, [settingsOpen]); const handleDropdownBlur = (e: React.FocusEvent) => { const relatedTarget = e.relatedTarget as Node | null; if (relatedTarget && focusAreaRef.current?.contains(relatedTarget)) { return; } setSettingsOpen(false); }; // Close on Escape and return focus to the gear button. const handlePanelKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Escape") { setSettingsOpen(false); buttonRef.current?.focus(); } }; return (
e.stopPropagation()} onPointerDown={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()} >
{onOpenServerBrowser && ( )}
{ setFogEnabled(event.target.checked); }} />
{ setAudioEnabled(event.target.checked); }} />
{ setAnimationEnabled(event.target.checked); }} />
{ setDebugMode(event.target.checked); }} />
{hideViewControls ? null : (
setFov(parseInt(event.target.value))} /> {fov}
)} {hideViewControls ? null : (
setSpeedMultiplier(parseFloat(event.target.value)) } />
)}
{isTouch && (
{" "}
)}
); }