mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-03-22 13:50:56 +00:00
split up components more
This commit is contained in:
parent
d336c20098
commit
539dbba677
71 changed files with 1064 additions and 990 deletions
95
src/components/GameView.tsx
Normal file
95
src/components/GameView.tsx
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import { lazy, memo, Suspense } from "react";
|
||||
import { type RootState } from "@react-three/fiber";
|
||||
import { useDataSource } from "../state/gameEntityStore";
|
||||
import { useRecording } from "./RecordingProvider";
|
||||
import { AudioProvider } from "./AudioContext";
|
||||
import { CamerasProvider } from "./CamerasProvider";
|
||||
import { InputProducers } from "./InputHandlers";
|
||||
import { SceneLighting } from "./SceneLighting";
|
||||
import { ThreeCanvas } from "./ThreeCanvas";
|
||||
import { TickProvider } from "./TickProvider";
|
||||
import { EntityScene } from "./EntityScene";
|
||||
import { ObserverCamera } from "./ObserverCamera";
|
||||
import { AudioEnabled } from "./AudioEnabled";
|
||||
import { DebugEnabled } from "./DebugEnabled";
|
||||
import { InputConsumer } from "./InputConsumer";
|
||||
|
||||
function createLazy(
|
||||
name: string,
|
||||
loader: () => Promise<{
|
||||
[name]: React.ComponentType<any>;
|
||||
}>,
|
||||
) {
|
||||
return lazy(() => loader().then((mod) => ({ default: mod[name] })));
|
||||
}
|
||||
|
||||
const StreamingController = createLazy(
|
||||
"StreamingController",
|
||||
() => import("@/src/components/StreamingController"),
|
||||
);
|
||||
const DebugElements = createLazy(
|
||||
"DebugElements",
|
||||
() => import("@/src/components/DebugElements"),
|
||||
);
|
||||
const Mission = createLazy("Mission", () => import("@/src/components/Mission"));
|
||||
const ChatSoundPlayer = createLazy(
|
||||
"ChatSoundPlayer",
|
||||
() => import("@/src/components/ChatSoundPlayer"),
|
||||
);
|
||||
|
||||
export const GameView = memo(function GameView({
|
||||
dpr,
|
||||
onCreated,
|
||||
missionName,
|
||||
missionType,
|
||||
onLoadingChange,
|
||||
}: {
|
||||
dpr?: number;
|
||||
onCreated?: (state: RootState) => void;
|
||||
missionName: string;
|
||||
missionType?: string;
|
||||
onLoadingChange?: (isLoading: boolean, progress?: number) => void;
|
||||
}) {
|
||||
const recording = useRecording();
|
||||
const dataSource = useDataSource();
|
||||
const hasStreamData = dataSource === "demo" || dataSource === "live";
|
||||
|
||||
return (
|
||||
<ThreeCanvas dpr={dpr} onCreated={onCreated}>
|
||||
<TickProvider>
|
||||
<CamerasProvider>
|
||||
<InputProducers />
|
||||
<AudioProvider>
|
||||
<SceneLighting />
|
||||
<Suspense>
|
||||
<EntityScene />
|
||||
</Suspense>
|
||||
<ObserverCamera />
|
||||
<AudioEnabled>
|
||||
<ChatSoundPlayer />
|
||||
</AudioEnabled>
|
||||
<DebugEnabled>
|
||||
<DebugElements />
|
||||
</DebugEnabled>
|
||||
{recording ? (
|
||||
<Suspense>
|
||||
<StreamingController recording={recording} />
|
||||
</Suspense>
|
||||
) : null}
|
||||
{!hasStreamData ? (
|
||||
<Suspense>
|
||||
<Mission
|
||||
key={`${missionName}~${missionType}`}
|
||||
name={missionName}
|
||||
missionType={missionType}
|
||||
onLoadingChange={onLoadingChange}
|
||||
/>
|
||||
</Suspense>
|
||||
) : null}
|
||||
<InputConsumer />
|
||||
</AudioProvider>
|
||||
</CamerasProvider>
|
||||
</TickProvider>
|
||||
</ThreeCanvas>
|
||||
);
|
||||
});
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useState, useRef, RefObject } from "react";
|
||||
import { useEffect, useState, useRef, RefObject, memo } from "react";
|
||||
import { RiLandscapeFill } from "react-icons/ri";
|
||||
import { FaRotateRight } from "react-icons/fa6";
|
||||
import { LuClipboardList, LuUsers } from "react-icons/lu";
|
||||
|
|
@ -22,7 +22,7 @@ import { hasMission } from "../manifest";
|
|||
|
||||
const DEFAULT_PANELS = ["controls", "preferences", "audio"];
|
||||
|
||||
export function InspectorControls({
|
||||
export const InspectorControls = memo(function InspectorControls({
|
||||
missionName,
|
||||
missionType,
|
||||
onOpenMapInfo,
|
||||
|
|
@ -422,4 +422,4 @@ export function InspectorControls({
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,22 +11,17 @@ import {
|
|||
ReactNode,
|
||||
// ViewTransition,
|
||||
} from "react";
|
||||
import { Camera } from "three";
|
||||
import { type Camera } from "three";
|
||||
import { type RootState } from "@react-three/fiber";
|
||||
import { type InvalidateFunction } from "@/src/components/ThreeCanvas";
|
||||
import { InspectorControls } from "@/src/components/InspectorControls";
|
||||
import { MissionSelect } from "@/src/components/MissionSelect";
|
||||
import { StreamingMissionInfo } from "@/src/components/StreamingMissionInfo";
|
||||
import { useSettings } from "@/src/components/SettingsProvider";
|
||||
import { ObserverCamera } from "@/src/components/ObserverCamera";
|
||||
import { AudioProvider } from "@/src/components/AudioContext";
|
||||
import { CamerasProvider } from "@/src/components/CamerasProvider";
|
||||
import { InputConsumer } from "./InputConsumer";
|
||||
import {
|
||||
RecordingProvider,
|
||||
useRecording,
|
||||
} from "@/src/components/RecordingProvider";
|
||||
import { EntityScene } from "@/src/components/EntityScene";
|
||||
import { TickProvider } from "@/src/components/TickProvider";
|
||||
import { SceneLighting } from "@/src/components/SceneLighting";
|
||||
import { useFeatures } from "@/src/components/FeaturesProvider";
|
||||
import {
|
||||
liveConnectionStore,
|
||||
|
|
@ -37,12 +32,9 @@ import {
|
|||
CurrentMission,
|
||||
useMissionQueryState,
|
||||
} from "@/src/components/useQueryParams";
|
||||
import { ThreeCanvas, InvalidateFunction } from "@/src/components/ThreeCanvas";
|
||||
import { InputProducers, InputProvider } from "./InputHandlers";
|
||||
import { InputProvider } from "./InputHandlers";
|
||||
import { VisualInput } from "./VisualInput";
|
||||
import { LoadingIndicator } from "./LoadingIndicator";
|
||||
import { AudioEnabled } from "./AudioEnabled";
|
||||
import { DebugEnabled } from "./DebugEnabled";
|
||||
import { engineStore } from "../state/engineStore";
|
||||
import {
|
||||
gameEntityStore,
|
||||
|
|
@ -57,8 +49,8 @@ import {
|
|||
LuPanelTopClose,
|
||||
LuPanelTopOpen,
|
||||
} from "react-icons/lu";
|
||||
import styles from "./MapInspector.module.css";
|
||||
import { useTouchDevice } from "./useTouchDevice";
|
||||
import styles from "./MapInspector.module.css";
|
||||
|
||||
function ViewTransition({ children }: { children: ReactNode }) {
|
||||
return children;
|
||||
|
|
@ -73,23 +65,14 @@ function createLazy(
|
|||
return lazy(() => loader().then((mod) => ({ default: mod[name] })));
|
||||
}
|
||||
|
||||
const StreamingController = createLazy(
|
||||
"StreamingController",
|
||||
() => import("@/src/components/StreamingController"),
|
||||
const GameView = createLazy(
|
||||
"GameView",
|
||||
() => import("@/src/components/GameView"),
|
||||
);
|
||||
const DemoPlaybackControls = createLazy(
|
||||
"DemoPlaybackControls",
|
||||
() => import("@/src/components/DemoPlaybackControls"),
|
||||
);
|
||||
const DebugElements = createLazy(
|
||||
"DebugElements",
|
||||
() => import("@/src/components/DebugElements"),
|
||||
);
|
||||
const Mission = createLazy("Mission", () => import("@/src/components/Mission"));
|
||||
const ChatSoundPlayer = createLazy(
|
||||
"ChatSoundPlayer",
|
||||
() => import("@/src/components/ChatSoundPlayer"),
|
||||
);
|
||||
const PlayerHUD = createLazy(
|
||||
"PlayerHUD",
|
||||
() => import("@/src/components/PlayerHUD"),
|
||||
|
|
@ -148,6 +131,7 @@ export function MapInspector() {
|
|||
// Sync the mission query param when streaming data provides a mission name.
|
||||
const streamMissionName = useMissionName();
|
||||
const streamMissionType = useMissionType();
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasStreamData || !streamMissionName) return;
|
||||
try {
|
||||
|
|
@ -210,6 +194,30 @@ export function MapInspector() {
|
|||
const cameraRef = useRef<Camera | null>(null);
|
||||
const invalidateRef = useRef<InvalidateFunction | null>(null);
|
||||
|
||||
const handleOpenMapInfo = useCallback(() => setMapInfoOpen(true), []);
|
||||
const handleOpenScoreScreen = useCallback(() => {
|
||||
if (hasStreamData) {
|
||||
setScoreScreenOpen(true);
|
||||
}
|
||||
}, [hasStreamData]);
|
||||
const handleOpenServerBrowser = useCallback(() => {
|
||||
if (features.live) {
|
||||
setServerBrowserOpen(true);
|
||||
}
|
||||
}, [features.live]);
|
||||
const handleChooseMap = useCallback(() => {
|
||||
if (hasStreamData) {
|
||||
setChoosingMap(true);
|
||||
}
|
||||
}, [hasStreamData]);
|
||||
const handleCancelChoosingMap = useCallback(() => {
|
||||
setChoosingMap(false);
|
||||
}, []);
|
||||
const handleCanvasCreated = useCallback((state: RootState) => {
|
||||
cameraRef.current = state.camera;
|
||||
invalidateRef.current = state.invalidate;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<main className={styles.Frame}>
|
||||
<RecordingProvider>
|
||||
|
|
@ -279,26 +287,14 @@ export function MapInspector() {
|
|||
<InspectorControls
|
||||
missionName={missionName}
|
||||
missionType={missionType}
|
||||
onOpenMapInfo={() => setMapInfoOpen(true)}
|
||||
onOpenScoreScreen={
|
||||
hasStreamData ? () => setScoreScreenOpen(true) : undefined
|
||||
}
|
||||
onOpenServerBrowser={
|
||||
features.live ? () => setServerBrowserOpen(true) : undefined
|
||||
}
|
||||
onChooseMap={
|
||||
hasStreamData
|
||||
? () => {
|
||||
setChoosingMap(true);
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
onCancelChoosingMap={() => {
|
||||
setChoosingMap(false);
|
||||
}}
|
||||
choosingMap={choosingMap}
|
||||
cameraRef={cameraRef}
|
||||
invalidateRef={invalidateRef}
|
||||
onOpenMapInfo={handleOpenMapInfo}
|
||||
onOpenScoreScreen={handleOpenScoreScreen}
|
||||
onOpenServerBrowser={handleOpenServerBrowser}
|
||||
onChooseMap={handleChooseMap}
|
||||
onCancelChoosingMap={handleCancelChoosingMap}
|
||||
/>
|
||||
</div>
|
||||
</ViewTransition>
|
||||
|
|
@ -306,52 +302,19 @@ export function MapInspector() {
|
|||
<InputProvider>
|
||||
<div className={styles.Content}>
|
||||
<div className={styles.ThreeView}>
|
||||
<ThreeCanvas
|
||||
dpr={
|
||||
mapInfoOpen || serverBrowserOpen || scoreScreenOpen
|
||||
? 0.25
|
||||
: undefined
|
||||
}
|
||||
onCreated={(state) => {
|
||||
cameraRef.current = state.camera;
|
||||
invalidateRef.current = state.invalidate;
|
||||
}}
|
||||
>
|
||||
<TickProvider>
|
||||
<CamerasProvider>
|
||||
<InputProducers />
|
||||
<AudioProvider>
|
||||
<SceneLighting />
|
||||
<Suspense>
|
||||
<EntityScene />
|
||||
</Suspense>
|
||||
<ObserverCamera />
|
||||
<AudioEnabled>
|
||||
<ChatSoundPlayer />
|
||||
</AudioEnabled>
|
||||
<DebugEnabled>
|
||||
<DebugElements />
|
||||
</DebugEnabled>
|
||||
{recording ? (
|
||||
<Suspense>
|
||||
<StreamingController recording={recording} />
|
||||
</Suspense>
|
||||
) : null}
|
||||
{!hasStreamData ? (
|
||||
<Suspense>
|
||||
<Mission
|
||||
key={`${missionName}~${missionType}`}
|
||||
name={missionName}
|
||||
missionType={missionType}
|
||||
onLoadingChange={handleLoadingChange}
|
||||
/>
|
||||
</Suspense>
|
||||
) : null}
|
||||
<InputConsumer />
|
||||
</AudioProvider>
|
||||
</CamerasProvider>
|
||||
</TickProvider>
|
||||
</ThreeCanvas>
|
||||
<Suspense>
|
||||
<GameView
|
||||
missionName={missionName}
|
||||
missionType={missionType}
|
||||
dpr={
|
||||
mapInfoOpen || serverBrowserOpen || scoreScreenOpen
|
||||
? 0.25
|
||||
: undefined
|
||||
}
|
||||
onCreated={handleCanvasCreated}
|
||||
onLoadingChange={handleLoadingChange}
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
{hasStreamData && !scoreScreenOpen ? (
|
||||
<Suspense>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ReactNode } from "react";
|
||||
import { ReactNode, Suspense } from "react";
|
||||
import { Canvas, GLProps, RootState } from "@react-three/fiber";
|
||||
import { NoToneMapping, PCFShadowMap, SRGBColorSpace } from "three";
|
||||
import { useDebug } from "./SettingsProvider";
|
||||
|
|
@ -35,7 +35,7 @@ export function ThreeCanvas({
|
|||
shadows={{ type: PCFShadowMap }}
|
||||
onCreated={onCreated}
|
||||
>
|
||||
{children}
|
||||
<Suspense>{children}</Suspense>
|
||||
</Canvas>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue