2025-09-11 23:48:23 +00:00
|
|
|
"use client";
|
2025-11-15 20:55:08 +00:00
|
|
|
import { useState, useEffect, Suspense } from "react";
|
2025-11-15 01:23:16 +00:00
|
|
|
import { useSearchParams, useRouter } from "next/navigation";
|
2025-11-14 06:55:58 +00:00
|
|
|
import { Canvas } from "@react-three/fiber";
|
2025-11-14 11:10:26 +00:00
|
|
|
import { EffectComposer, N8AO } from "@react-three/postprocessing";
|
2025-11-15 01:23:16 +00:00
|
|
|
import { Mission } from "@/src/components/Mission";
|
|
|
|
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
|
|
|
import { ObserverControls } from "@/src/components/ObserverControls";
|
|
|
|
|
import { InspectorControls } from "@/src/components/InspectorControls";
|
|
|
|
|
import { SettingsProvider } from "@/src/components/SettingsProvider";
|
|
|
|
|
import { ObserverCamera } from "@/src/components/ObserverCamera";
|
2025-11-16 00:33:18 +00:00
|
|
|
import { AudioProvider } from "@/src/components/AudioContext";
|
2025-11-24 05:47:49 +00:00
|
|
|
import { DebugElements } from "@/src/components/DebugElements";
|
2025-11-26 22:37:49 +00:00
|
|
|
import { CamerasProvider } from "@/src/components/CamerasProvider";
|
2025-11-14 06:55:58 +00:00
|
|
|
|
|
|
|
|
// three.js has its own loaders for textures and models, but we need to load other
|
|
|
|
|
// stuff too, e.g. missions, terrains, and more. This client is used for those.
|
|
|
|
|
const queryClient = new QueryClient();
|
2025-09-11 23:48:23 +00:00
|
|
|
|
2025-11-15 20:55:08 +00:00
|
|
|
function MapInspector() {
|
2025-11-14 11:30:33 +00:00
|
|
|
const searchParams = useSearchParams();
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
|
|
|
|
// Initialize state from query params
|
|
|
|
|
const [missionName, setMissionName] = useState(
|
2025-11-29 17:08:20 +00:00
|
|
|
searchParams.get("mission") || "TWL2_WoodyMyrk",
|
2025-11-14 11:30:33 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Update query params when state changes
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const params = new URLSearchParams();
|
|
|
|
|
params.set("mission", missionName);
|
|
|
|
|
router.replace(`?${params.toString()}`, { scroll: false });
|
2025-11-14 07:41:10 +00:00
|
|
|
}, [missionName, router]);
|
2025-09-12 17:30:40 +00:00
|
|
|
|
2025-09-11 23:48:23 +00:00
|
|
|
return (
|
2025-11-14 07:41:10 +00:00
|
|
|
<QueryClientProvider client={queryClient}>
|
|
|
|
|
<main>
|
|
|
|
|
<SettingsProvider>
|
2025-11-24 05:47:49 +00:00
|
|
|
<Canvas shadows frameloop="always">
|
2025-11-26 22:37:49 +00:00
|
|
|
<CamerasProvider>
|
|
|
|
|
<AudioProvider>
|
|
|
|
|
<Mission key={missionName} name={missionName} />
|
|
|
|
|
<ObserverCamera />
|
|
|
|
|
<DebugElements />
|
|
|
|
|
<ObserverControls />
|
|
|
|
|
</AudioProvider>
|
|
|
|
|
</CamerasProvider>
|
2025-11-14 11:10:26 +00:00
|
|
|
<EffectComposer>
|
|
|
|
|
<N8AO intensity={3} aoRadius={3} quality="performance" />
|
|
|
|
|
</EffectComposer>
|
2025-11-14 06:55:58 +00:00
|
|
|
</Canvas>
|
|
|
|
|
<InspectorControls
|
|
|
|
|
missionName={missionName}
|
|
|
|
|
onChangeMission={setMissionName}
|
2025-09-12 17:30:40 +00:00
|
|
|
/>
|
2025-11-14 07:41:10 +00:00
|
|
|
</SettingsProvider>
|
|
|
|
|
</main>
|
|
|
|
|
</QueryClientProvider>
|
2025-09-11 23:48:23 +00:00
|
|
|
);
|
|
|
|
|
}
|
2025-11-15 20:55:08 +00:00
|
|
|
|
|
|
|
|
export default function HomePage() {
|
|
|
|
|
return (
|
|
|
|
|
<Suspense>
|
|
|
|
|
<MapInspector />
|
|
|
|
|
</Suspense>
|
|
|
|
|
);
|
|
|
|
|
}
|