mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-17 20:39:13 +00:00
Resolve render settings before renderer construction (#4271)
## What
The client now resolves render settings (defaults + user overrides) **up
front** and passes the result into the renderer, instead of the renderer
constructing defaults itself and the client re-applying overrides
afterward.
```
before: new GPURenderer(...) // this.settings = createRenderSettings() (defaults)
view.getSettings() → deepAssign(defaults) → applyGraphicsOverrides(...) // patch after the fact
after: const settings = createRenderSettings(); applyGraphicsOverrides(settings, ...); applyDarkModeOverride(settings, ...)
new GPURenderer(..., settings) // built with the final values
```
## Why
- **Removes the construct-with-defaults / re-apply-overrides dance.**
Every pass — including texture-baking ones like terrain that read their
settings *once* at build time rather than every frame — is now built
with the final values on the first try. (This is the cleanup that
motivated the change, surfaced while adding a terrain color override in
a separate PR.)
- **Fixes a latent context-restore bug.** On WebGL context loss/restore
the renderer was rebuilt via `createRenderSettings()` → fresh
**defaults**, silently dropping any user overrides until the next
settings change. `MapRenderer` now holds the resolved settings object
and hands the same one to the recreated `GPURenderer`, so overrides
survive a restore.
Live setting changes still work exactly as before:
`regenerateRenderSettings()` re-resolves and `deepAssign`s onto the
renderer's live settings object in place (passes hold a reference, so
they pick it up next frame).
## Changes
- `Renderer.ts` (`GPURenderer`) — constructor takes a `settings:
RenderSettings`; drops the internal `createRenderSettings()` call.
- `MapRenderer.ts` — holds the resolved settings and passes it through
on construction and on context-restore re-init.
- `ClientGameRunner.ts` — new `resolveRenderSettings()` helper used both
at construction and by `regenerateRenderSettings()`; `createWebGLView`
takes the resolved settings; the now-redundant initial
`regenerateRenderSettings()` call is removed.
## Testing
Verified live in a headless singleplayer game:
- A saved `nameScaleFactor` override is present in `getSettings()`
immediately after game start, with no settings-change event fired
(construction path).
- A mid-game override change is reflected in the live settings
(regenerate/in-place path).
- The map renders correctly through spawn phase.
`tsc` and ESLint clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,10 @@ export class MapRenderer {
|
||||
private terrainBytes: Uint8Array,
|
||||
private paletteData: Float32Array,
|
||||
private config: Config,
|
||||
// Resolved render settings (defaults + overrides). Held so the same object
|
||||
// is re-used when a GPURenderer is recreated after a context restore,
|
||||
// preserving any user overrides that were applied to it.
|
||||
private settings: RenderSettings,
|
||||
private raf?: typeof requestAnimationFrame,
|
||||
private caf?: typeof cancelAnimationFrame,
|
||||
) {
|
||||
@@ -78,6 +82,7 @@ export class MapRenderer {
|
||||
this.terrainBytes,
|
||||
this.paletteData,
|
||||
this.config,
|
||||
this.settings,
|
||||
this.raf,
|
||||
this.caf,
|
||||
);
|
||||
|
||||
@@ -57,7 +57,7 @@ import { TerritoryPass } from "./passes/TerritoryPass";
|
||||
import { TrailPass } from "./passes/TrailPass";
|
||||
import { UnitPass } from "./passes/UnitPass";
|
||||
import { WorldTextPass } from "./passes/WorldTextPass";
|
||||
import { createRenderSettings, type RenderSettings } from "./RenderSettings";
|
||||
import type { RenderSettings } from "./RenderSettings";
|
||||
import { AffiliationPalette } from "./utils/Affiliation";
|
||||
import { buildTerrainRGBA, getPaletteSize } from "./utils/ColorUtils";
|
||||
import {
|
||||
@@ -180,11 +180,15 @@ export class GPURenderer {
|
||||
terrainBytes: Uint8Array,
|
||||
paletteData: Float32Array,
|
||||
config: Config,
|
||||
settings: RenderSettings,
|
||||
raf: typeof requestAnimationFrame = requestAnimationFrame.bind(window),
|
||||
caf: typeof cancelAnimationFrame = cancelAnimationFrame.bind(window),
|
||||
) {
|
||||
this.canvas = canvas;
|
||||
this.settings = createRenderSettings();
|
||||
// Settings are resolved (defaults + user overrides) by the caller and
|
||||
// passed in, so every pass — including texture-baking ones like terrain —
|
||||
// is built with the final values. Live changes mutate this object in place.
|
||||
this.settings = settings;
|
||||
this.raf = raf;
|
||||
this.caf = caf;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user