mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-07-13 07:25:07 +00:00
allow selecting different game types
This commit is contained in:
parent
7f75ed84da
commit
049566cdbb
56 changed files with 436 additions and 207 deletions
40
app/page.tsx
40
app/page.tsx
|
|
@ -1,5 +1,5 @@
|
|||
"use client";
|
||||
import { useState, useEffect, useCallback, Suspense } from "react";
|
||||
import { useState, useEffect, useCallback, Suspense, useMemo } from "react";
|
||||
import { useSearchParams, useRouter } from "next/navigation";
|
||||
import { Canvas, GLProps } from "@react-three/fiber";
|
||||
import { NoToneMapping, SRGBColorSpace, PCFShadowMap } from "three";
|
||||
|
|
@ -30,10 +30,19 @@ function MapInspector() {
|
|||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
|
||||
// Initialize state from query params
|
||||
const [missionName, setMissionName] = useState(
|
||||
searchParams.get("mission") || "TWL2_WoodyMyrk",
|
||||
const [initialMissionName, initialMissionType] = useMemo(
|
||||
() => (searchParams.get("mission") || "RiverDance:CTF").split("~"),
|
||||
[],
|
||||
);
|
||||
const [missionName, setMissionName] = useState(initialMissionName);
|
||||
const availableMissionTypes = getMissionInfo(missionName).missionTypes;
|
||||
const [missionType, setMissionType] = useState(() =>
|
||||
initialMissionType && availableMissionTypes.includes(initialMissionType)
|
||||
? initialMissionType
|
||||
: availableMissionTypes[0],
|
||||
);
|
||||
const isOnlyMissionType = availableMissionTypes.length === 1;
|
||||
|
||||
const [loadingProgress, setLoadingProgress] = useState(0);
|
||||
const [showLoadingIndicator, setShowLoadingIndicator] = useState(true);
|
||||
const isLoading = loadingProgress < 1;
|
||||
|
|
@ -64,9 +73,12 @@ function MapInspector() {
|
|||
// Update query params when state changes
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams();
|
||||
params.set("mission", missionName);
|
||||
const value = isOnlyMissionType
|
||||
? missionName
|
||||
: `${missionName}~${missionType}`;
|
||||
params.set("mission", value);
|
||||
router.replace(`?${params.toString()}`, { scroll: false });
|
||||
}, [missionName, router]);
|
||||
}, [missionName, missionType, isOnlyMissionType, router]);
|
||||
|
||||
const handleLoadingChange = useCallback(
|
||||
(_loading: boolean, progress: number = 0) => {
|
||||
|
|
@ -94,13 +106,19 @@ function MapInspector() {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
<Canvas frameloop="always" gl={glSettings} shadows={{ type: PCFShadowMap }}>
|
||||
<Canvas
|
||||
frameloop="always"
|
||||
gl={glSettings}
|
||||
shadows={{ type: PCFShadowMap }}
|
||||
>
|
||||
<CamerasProvider>
|
||||
<AudioProvider>
|
||||
<Mission
|
||||
key={missionName}
|
||||
key={`${missionName}~${missionType}`}
|
||||
name={missionName}
|
||||
missionType={missionType}
|
||||
onLoadingChange={handleLoadingChange}
|
||||
setMissionType={setMissionType}
|
||||
/>
|
||||
<ObserverCamera />
|
||||
<DebugElements />
|
||||
|
|
@ -111,7 +129,11 @@ function MapInspector() {
|
|||
</div>
|
||||
<InspectorControls
|
||||
missionName={missionName}
|
||||
onChangeMission={setMissionName}
|
||||
missionType={missionType}
|
||||
onChangeMission={({ missionName, missionType }) => {
|
||||
setMissionName(missionName);
|
||||
setMissionType(missionType);
|
||||
}}
|
||||
/>
|
||||
</SettingsProvider>
|
||||
</main>
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ main {
|
|||
z-index: 1;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
max-width: 80px;
|
||||
}
|
||||
|
||||
.CheckboxField {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -73,11 +77,6 @@ main {
|
|||
gap: 6px;
|
||||
}
|
||||
|
||||
#fovInput,
|
||||
#speedInput {
|
||||
max-width: 80px;
|
||||
}
|
||||
|
||||
.StaticShapeLabel {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
color: #fff;
|
||||
|
|
@ -85,6 +84,7 @@ main {
|
|||
white-space: nowrap;
|
||||
padding: 1px 3px;
|
||||
border-radius: 1px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.StatsPanel {
|
||||
|
|
@ -133,7 +133,7 @@ main {
|
|||
}
|
||||
|
||||
.MissionSelect-input {
|
||||
width: 240px;
|
||||
width: 280px;
|
||||
padding: 6px 36px 6px 8px;
|
||||
font-size: 14px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
|
|
@ -152,8 +152,37 @@ main {
|
|||
}
|
||||
|
||||
.MissionSelect-input::placeholder {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.MissionSelect-selectedValue {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
right: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.MissionSelect-input[aria-expanded="true"] ~ .MissionSelect-selectedValue {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.MissionSelect-selectedName {
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
flex-shrink: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.MissionSelect-selectedValue > .MissionSelect-itemType {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.MissionSelect-popover {
|
||||
|
|
@ -246,6 +275,10 @@ main {
|
|||
color: #fff;
|
||||
}
|
||||
|
||||
.MissionSelect-itemType:hover {
|
||||
background: rgba(255, 157, 0, 0.7);
|
||||
}
|
||||
|
||||
.MissionSelect-itemMissionName {
|
||||
font-size: 12px;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue