Reapply graphics overrides on debug render GUI reset (#4287)

## Problem

The debug render GUI's **"Reset to Defaults"** restored bare
`createRenderSettings()` defaults, wiping the user's graphics overrides
(colorblind theme, ocean color, lighting, name scaling, etc.) from the
live render settings. The per-prop right-click "reset to default" and
the modified-indicators had the same flaw — their captured defaults were
raw, ignoring overrides.

## Fix

Thread the existing `resolveRenderSettings` (`createRenderSettings()` +
`applyGraphicsOverrides()`) into the debug GUI as the defaults provider,
so reset restores the same settings the renderer was actually built
with.

- **`debug/index.ts`** — added a `resolveDefaults` param (defaults to
`createRenderSettings` to keep the module decoupled). The captured
`defaults` now include overrides, fixing the per-prop reset and modified
indicators too.
- **`debug/Wiring.ts`** — `wireActions` takes `resolveDefaults`; the
reset handler `deepAssign`s `resolveDefaults()` instead of
`createRenderSettings()`.
- **`ClientGameRunner.ts`** — passes `resolveRenderSettings` into
`createDebugGui`, and extracts a `refreshDerivedGraphics` helper
(terrain rebuild + re-theme/palette) from `onGraphicsChanged`, wired as
the GUI's `onSettingsChanged` so the reapplied terrain/colorblind
overrides become *visible* after reset (they're baked into GPU textures
and aren't picked up per-frame).

Side benefit: editing terrain/theme settings in the debug GUI now
refreshes those textures live too (that callback was previously never
wired).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Evan
2026-06-14 19:44:20 -07:00
committed by GitHub
parent 094aa766ce
commit 5be72db060
3 changed files with 23 additions and 9 deletions
+14 -5
View File
@@ -514,10 +514,9 @@ async function createClientGame(
const regenerateRenderSettings = (): void => { const regenerateRenderSettings = (): void => {
deepAssign(view.getSettings(), resolveRenderSettings()); deepAssign(view.getSettings(), resolveRenderSettings());
}; };
// Re-apply render settings, then re-theme and recolor players, on a // Rebuild the GPU-derived graphics state that the per-frame passes don't
// graphics-override change (covers a theme switch such as colorblind mode). // pick up from the live settings object on their own.
const onGraphicsChanged = (): void => { const refreshDerivedGraphics = (): void => {
regenerateRenderSettings();
// Terrain is baked into a GPU texture rather than read per-frame, so a // Terrain is baked into a GPU texture rather than read per-frame, so a
// terrain-color override (e.g. ocean) needs an explicit texture rebuild. // terrain-color override (e.g. ocean) needs an explicit texture rebuild.
view.rebuildTerrain(); view.rebuildTerrain();
@@ -527,6 +526,12 @@ async function createClientGame(
gameView.refreshPlayerColors(); gameView.refreshPlayerColors();
webglBuilder.refreshPalette(gameView); webglBuilder.refreshPalette(gameView);
}; };
// Re-apply render settings, then re-theme and recolor players, on a
// graphics-override change (covers a theme switch such as colorblind mode).
const onGraphicsChanged = (): void => {
regenerateRenderSettings();
refreshDerivedGraphics();
};
// No initial regenerate or terrain rebuild needed — the renderer was // No initial regenerate or terrain rebuild needed — the renderer was
// constructed with the resolved settings above, so the terrain texture // constructed with the resolved settings above, so the terrain texture
// already bakes any saved ocean-color override. // already bakes any saved ocean-color override.
@@ -545,7 +550,11 @@ async function createClientGame(
debugGuiLoading = true; debugGuiLoading = true;
import("./render/gl/debug/index") import("./render/gl/debug/index")
.then(({ createDebugGui }) => { .then(({ createDebugGui }) => {
debugGui = createDebugGui(view.getSettings()); debugGui = createDebugGui(
view.getSettings(),
resolveRenderSettings,
refreshDerivedGraphics,
);
debugGui.open(); debugGui.open();
}) })
.finally(() => { .finally(() => {
+3 -2
View File
@@ -1,6 +1,6 @@
import GUI, { FunctionController } from "lil-gui"; import GUI, { FunctionController } from "lil-gui";
import type { RenderSettings } from "../RenderSettings"; import type { RenderSettings } from "../RenderSettings";
import { createRenderSettings, dumpSettings } from "../RenderSettings"; import { dumpSettings } from "../RenderSettings";
import { deepAssign } from "../SettingsUtils"; import { deepAssign } from "../SettingsUtils";
import type { ConfigProp } from "./ConfigProp"; import type { ConfigProp } from "./ConfigProp";
@@ -66,6 +66,7 @@ export function wireActions(
gui: GUI, gui: GUI,
settings: RenderSettings, settings: RenderSettings,
props: ConfigProp[], props: ConfigProp[],
resolveDefaults: () => RenderSettings,
onSettingsChanged?: () => void, onSettingsChanged?: () => void,
): void { ): void {
gui.add({ dump: () => dumpSettings(settings) }, "dump").name("Download JSON"); gui.add({ dump: () => dumpSettings(settings) }, "dump").name("Download JSON");
@@ -99,7 +100,7 @@ export function wireActions(
.add( .add(
{ {
reset: () => { reset: () => {
deepAssign(settings, createRenderSettings()); deepAssign(settings, resolveDefaults());
props.forEach((p) => p.resetToDefault()); props.forEach((p) => p.resetToDefault());
onSettingsChanged?.(); onSettingsChanged?.();
}, },
+6 -2
View File
@@ -7,6 +7,7 @@ import { makeDraggable, wireActions, wireModifiedIndicators } from "./Wiring";
export function createDebugGui( export function createDebugGui(
settings: RenderSettings, settings: RenderSettings,
resolveDefaults: () => RenderSettings = createRenderSettings,
onSettingsChanged?: () => void, onSettingsChanged?: () => void,
): GUI { ): GUI {
const gui = new GUI({ title: "Render Settings", width: 320 }); const gui = new GUI({ title: "Render Settings", width: 320 });
@@ -17,10 +18,13 @@ export function createDebugGui(
makeDraggable(gui); makeDraggable(gui);
const defaults = createRenderSettings(); // Defaults include the user's graphics overrides so "Reset to Defaults"
// (and the per-prop reset / modified indicators) restore the same settings
// the renderer was built with — not bare defaults that drop the overrides.
const defaults = resolveDefaults();
const props = walkTree(buildTree(settings, defaults), gui); const props = walkTree(buildTree(settings, defaults), gui);
wireActions(gui, settings, props, onSettingsChanged); wireActions(gui, settings, props, resolveDefaults, onSettingsChanged);
wireModifiedIndicators(gui, props, onSettingsChanged); wireModifiedIndicators(gui, props, onSettingsChanged);
gui.close(); gui.close();