Update & refactor dark mode (#4114)

## Description:

- The renderer no longer knows what "dark mode" is.
`RenderSettings.dayNight.mode` (`"light" | "dark"`) is gone — passes
read neutral values (`lighting.ambient: number`, `lighting.enabled:
boolean`).
- `render-settings.json` holds the light-mode baseline. Dark mode is
just another override layer, applied the same way as graphics settings
(`darkNames`, `classicIcons`, etc.).
- New `src/client/render/gl/RenderOverrides.ts` exposes two in-place
mutators with matching shapes:
- `applyGraphicsOverrides(settings, overrides)` — replaces the old
`generateRenderSettings`
  - `applyDarkModeOverride(settings, isDark)`
- `ClientGameRunner` regenerates the live settings each time the user
setting changes via `deepAssign(live, createRenderSettings())` + the
override chain. No per-slice copy list, no intermediate object — adding
a new override that touches a new section just works.
- Renamed `dayNight` → `lighting`; collapsed `nightAmbient`/`dayAmbient`
into single `ambient`; renamed `enableLightCompositing` → `enabled`.
- Bumped dark-mode ambient from 0.15 → 0.35 so terrain stays readable.

<img width="1250" height="846" alt="Screenshot 2026-06-02 at 11 47
28 AM"
src="https://github.com/user-attachments/assets/b41e8ffb-6011-4ba0-9e1f-c2a21ff90794"
/>

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
This commit is contained in:
Evan
2026-06-02 11:48:52 -07:00
committed by GitHub
parent 2386b4b38a
commit f1045a2022
12 changed files with 125 additions and 125 deletions
+15 -21
View File
@@ -69,8 +69,11 @@ import { createCanvas } from "./Utils";
import { WebGLFrameBuilder } from "./WebGLFrameBuilder"; import { WebGLFrameBuilder } from "./WebGLFrameBuilder";
import { createRenderer, GameRenderer } from "./hud/GameRenderer"; import { createRenderer, GameRenderer } from "./hud/GameRenderer";
import { import {
applyDarkModeOverride,
applyGraphicsOverrides,
createDebugGui, createDebugGui,
generateRenderSettings, createRenderSettings,
deepAssign,
GameView as WebGLGameView, GameView as WebGLGameView,
} from "./render/gl"; } from "./render/gl";
import { ALL_UNIT_TYPES, UnitState } from "./render/types"; import { ALL_UNIT_TYPES, UnitState } from "./render/types";
@@ -474,18 +477,6 @@ async function createClientGame(
config, config,
); );
// Bind the WebGL renderer's day/night mode to the existing darkMode
// UserSetting so the in-game map matches the rest of the UI. Initial
// apply + live updates via the per-key settings-changed event.
const applyDayNightMode = (isDark: boolean): void => {
view.getSettings().dayNight.mode = isDark ? "dark" : "light";
};
applyDayNightMode(userSettings.darkMode());
globalThis.addEventListener(
`${USER_SETTINGS_CHANGED_EVENT}:${DARK_MODE_KEY}`,
(e) => applyDayNightMode((e as CustomEvent<string>).detail === "true"),
);
view.setShowPatterns(userSettings.territoryPatterns()); view.setShowPatterns(userSettings.territoryPatterns());
globalThis.addEventListener( globalThis.addEventListener(
`${USER_SETTINGS_CHANGED_EVENT}:settings.territoryPatterns`, `${USER_SETTINGS_CHANGED_EVENT}:settings.territoryPatterns`,
@@ -493,18 +484,21 @@ async function createClientGame(
); );
const graphicsListenerAbort = new AbortController(); const graphicsListenerAbort = new AbortController();
const applyGraphicsOverrides = (): void => { const regenerateRenderSettings = (): void => {
const generated = generateRenderSettings(
userSettings.graphicsOverrides(),
);
const live = view.getSettings(); const live = view.getSettings();
Object.assign(live.name, generated.name); deepAssign(live, createRenderSettings());
Object.assign(live.structure, generated.structure); applyGraphicsOverrides(live, userSettings.graphicsOverrides());
applyDarkModeOverride(live, userSettings.darkMode());
}; };
applyGraphicsOverrides(); regenerateRenderSettings();
globalThis.addEventListener( globalThis.addEventListener(
`${USER_SETTINGS_CHANGED_EVENT}:${GRAPHICS_KEY}`, `${USER_SETTINGS_CHANGED_EVENT}:${GRAPHICS_KEY}`,
applyGraphicsOverrides, regenerateRenderSettings,
{ signal: graphicsListenerAbort.signal },
);
globalThis.addEventListener(
`${USER_SETTINGS_CHANGED_EVENT}:${DARK_MODE_KEY}`,
regenerateRenderSettings,
{ signal: graphicsListenerAbort.signal }, { signal: graphicsListenerAbort.signal },
); );
+48
View File
@@ -0,0 +1,48 @@
import type { GraphicsOverrides } from "./GraphicsOverrides";
import type { RenderSettings } from "./RenderSettings";
const DARK_AMBIENT = 0.35;
export function applyGraphicsOverrides(
settings: RenderSettings,
overrides: GraphicsOverrides,
): void {
if (overrides.name?.nameScaleFactor !== undefined) {
settings.name.nameScaleFactor = overrides.name.nameScaleFactor;
}
if (overrides.name?.cullThreshold !== undefined) {
settings.name.cullThreshold = overrides.name.cullThreshold;
}
if (overrides.structure?.classicIcons === true) {
// Classic look: lighter player-colored shape behind a dark icon glyph,
// with a touch of translucency.
settings.structure.borderDarken = 0.7;
settings.structure.fillDarken = 1.0;
settings.structure.iconR = 0;
settings.structure.iconG = 0;
settings.structure.iconB = 0;
settings.structure.iconAlpha = 0.75;
}
if (overrides.name?.darkNames !== undefined) {
const dark = overrides.name.darkNames;
// Dark: black fill + player-colored outline. Force outline RGB to black
// so the shader's defaultFill ramp (mix(uOutlineColor, black, fillT))
// collapses to pure black regardless of ambient.
// Colored: player-colored fill + white outline (defaults from JSON).
settings.name.fillUsePlayerColor = !dark;
settings.name.outlineUsePlayerColor = dark;
const channel = dark ? 0 : 1;
settings.name.outlineR = channel;
settings.name.outlineG = channel;
settings.name.outlineB = channel;
}
}
export function applyDarkModeOverride(
settings: RenderSettings,
isDark: boolean,
): void {
if (!isDark) return;
settings.lighting.ambient = DARK_AMBIENT;
settings.lighting.enabled = true;
}
+3 -45
View File
@@ -1,4 +1,3 @@
import { GraphicsOverrides } from "./GraphicsOverrides";
import defaults from "./render-settings.json"; import defaults from "./render-settings.json";
export interface RenderSettings { export interface RenderSettings {
@@ -47,10 +46,9 @@ export interface RenderSettings {
particleStrength: number; particleStrength: number;
particleFreshScale: number; particleFreshScale: number;
}; };
dayNight: { lighting: {
mode: "light" | "dark"; ambient: number;
nightAmbient: number; enabled: boolean;
dayAmbient: number;
falloffPower: number; falloffPower: number;
falloutLightR: number; falloutLightR: number;
falloutLightG: number; falloutLightG: number;
@@ -296,46 +294,6 @@ export function createRenderSettings(): RenderSettings {
return JSON.parse(JSON.stringify(defaults)) as RenderSettings; return JSON.parse(JSON.stringify(defaults)) as RenderSettings;
} }
/**
* Generate a fresh RenderSettings by layering user overrides on top of the
* render-settings.json defaults. Pure — does not mutate any input.
*/
export function generateRenderSettings(
overrides: GraphicsOverrides,
): RenderSettings {
const settings = createRenderSettings();
if (overrides.name?.nameScaleFactor !== undefined) {
settings.name.nameScaleFactor = overrides.name.nameScaleFactor;
}
if (overrides.name?.cullThreshold !== undefined) {
settings.name.cullThreshold = overrides.name.cullThreshold;
}
if (overrides.structure?.classicIcons === true) {
// Classic look: lighter player-colored shape behind a dark icon glyph,
// with a touch of translucency.
settings.structure.borderDarken = 0.7;
settings.structure.fillDarken = 1.0;
settings.structure.iconR = 0;
settings.structure.iconG = 0;
settings.structure.iconB = 0;
settings.structure.iconAlpha = 0.75;
}
if (overrides.name?.darkNames !== undefined) {
const dark = overrides.name.darkNames;
// Dark: black fill + player-colored outline. Force outline RGB to black
// so the shader's defaultFill ramp (mix(uOutlineColor, black, fillT))
// collapses to pure black regardless of ambient.
// Colored: player-colored fill + white outline (defaults from JSON).
settings.name.fillUsePlayerColor = !dark;
settings.name.outlineUsePlayerColor = dark;
const channel = dark ? 0 : 1;
settings.name.outlineR = channel;
settings.name.outlineG = channel;
settings.name.outlineB = channel;
}
return settings;
}
/** Dump current settings to a downloadable JSON file. */ /** Dump current settings to a downloadable JSON file. */
export function dumpSettings(settings: RenderSettings): void { export function dumpSettings(settings: RenderSettings): void {
const json = JSON.stringify(settings, null, 2); const json = JSON.stringify(settings, null, 2);
+4 -4
View File
@@ -1208,9 +1208,9 @@ export class GPURenderer {
const zoom = this.camera.zoom; const zoom = this.camera.zoom;
const cw = this.canvas.width; const cw = this.canvas.width;
const ch = this.canvas.height; const ch = this.canvas.height;
const nightActive = this.isNightActive(); const compositingActive = this.isLightCompositingActive();
if (nightActive) { if (compositingActive) {
this.resizeSceneTargetIfNeeded(cw, ch); this.resizeSceneTargetIfNeeded(cw, ch);
const sceneTex = toTarget(this.gl, this.sceneTarget, () => const sceneTex = toTarget(this.gl, this.sceneTarget, () =>
this.drawBaseLayer(cam), this.drawBaseLayer(cam),
@@ -1226,8 +1226,8 @@ export class GPURenderer {
this.renderOverlays(cam, zoom); this.renderOverlays(cam, zoom);
} }
private isNightActive(): boolean { private isLightCompositingActive(): boolean {
return this.settings.dayNight.mode === "dark"; return this.settings.lighting.enabled;
} }
private resizeSceneTargetIfNeeded(cw: number, ch: number): void { private resizeSceneTargetIfNeeded(cw: number, ch: number): void {
+13 -15
View File
@@ -2,7 +2,6 @@ import type { RenderSettings } from "../RenderSettings";
import type { DebugNode } from "./Folder"; import type { DebugNode } from "./Folder";
import { folder } from "./Folder"; import { folder } from "./Folder";
import { color } from "./props/Color"; import { color } from "./props/Color";
import { select } from "./props/Select";
import { slider } from "./props/Slider"; import { slider } from "./props/Slider";
import { toggle } from "./props/Toggle"; import { toggle } from "./props/Toggle";
@@ -90,30 +89,29 @@ export function buildTree(s: RenderSettings, d: RenderSettings): DebugNode[] {
slider(s.falloutBloom, "particleFreshScale", d.falloutBloom, 0, 1, 0.01), slider(s.falloutBloom, "particleFreshScale", d.falloutBloom, 0, 1, 0.01),
]), ]),
folder("Day / Night", [ folder("Lighting", [
select(s.dayNight, "mode", d.dayNight, ["light", "dark"], "Mode"), toggle(s.lighting, "enabled", d.lighting),
slider(s.dayNight, "nightAmbient", d.dayNight, 0, 1, 0.01), slider(s.lighting, "ambient", d.lighting, 0, 1, 0.01),
slider(s.dayNight, "dayAmbient", d.dayNight, 0, 1, 0.01), slider(s.lighting, "falloffPower", d.lighting, 0.5, 5, 0.1),
slider(s.dayNight, "falloffPower", d.dayNight, 0.5, 5, 0.1), slider(s.lighting, "falloutLightIntensity", d.lighting, 0, 20, 0.1),
slider(s.dayNight, "falloutLightIntensity", d.dayNight, 0, 20, 0.1), slider(s.lighting, "falloutLightThreshold", d.lighting, 0, 0.5, 0.001),
slider(s.dayNight, "falloutLightThreshold", d.dayNight, 0, 0.5, 0.001), slider(s.lighting, "blurZoomDivisor", d.lighting, 1, 20, 0.5),
slider(s.dayNight, "blurZoomDivisor", d.dayNight, 1, 20, 0.5), slider(s.lighting, "lightRadiusMultiplier", d.lighting, 0.1, 5, 0.1),
slider(s.dayNight, "lightRadiusMultiplier", d.dayNight, 0.1, 5, 0.1),
color( color(
s.dayNight, s.lighting,
"falloutLightR", "falloutLightR",
"falloutLightG", "falloutLightG",
"falloutLightB", "falloutLightB",
d.dayNight, d.lighting,
"Fallout Light Color", "Fallout Light Color",
), ),
slider(s.dayNight, "emberLightIntensity", d.dayNight, 0, 20, 0.1), slider(s.lighting, "emberLightIntensity", d.lighting, 0, 20, 0.1),
color( color(
s.dayNight, s.lighting,
"emberLightR", "emberLightR",
"emberLightG", "emberLightG",
"emberLightB", "emberLightB",
d.dayNight, d.lighting,
"Ember Light Color", "Ember Light Color",
), ),
]), ]),
+4 -4
View File
@@ -13,10 +13,10 @@ export { GraphicsOverridesSchema } from "./GraphicsOverrides";
export type { GraphicsOverrides } from "./GraphicsOverrides"; export type { GraphicsOverrides } from "./GraphicsOverrides";
export type { SpawnCenter } from "./passes/SpawnOverlayPass"; export type { SpawnCenter } from "./passes/SpawnOverlayPass";
export { export {
createRenderSettings, applyDarkModeOverride,
dumpSettings, applyGraphicsOverrides,
generateRenderSettings, } from "./RenderOverrides";
} from "./RenderSettings"; export { createRenderSettings, dumpSettings } from "./RenderSettings";
export type { RenderSettings } from "./RenderSettings"; export type { RenderSettings } from "./RenderSettings";
export { deepAssign, deepDiff } from "./SettingsUtils"; export { deepAssign, deepDiff } from "./SettingsUtils";
export { buildTerrainRGBA, getPaletteSize } from "./utils/ColorUtils"; export { buildTerrainRGBA, getPaletteSize } from "./utils/ColorUtils";
@@ -192,7 +192,7 @@ export class FalloutLightPass {
tick: number, tick: number,
): void { ): void {
const gl = this.gl; const gl = this.gl;
const dn = this.settings.dayNight; const dn = this.settings.lighting;
const fb = this.settings.falloutBloom; const fb = this.settings.falloutBloom;
// Step 1: Extract fallout light in tile space // Step 1: Extract fallout light in tile space
+1 -1
View File
@@ -166,7 +166,7 @@ export class LightmapPass {
const zoom = Math.abs(cameraMatrix[0]); const zoom = Math.abs(cameraMatrix[0]);
const mapSize = Math.max(this.mapW, this.mapH); const mapSize = Math.max(this.mapW, this.mapH);
const blurScale = Math.min( const blurScale = Math.min(
(zoom * mapSize) / this.settings.dayNight.blurZoomDivisor, (zoom * mapSize) / this.settings.lighting.blurZoomDivisor,
1.0, 1.0,
); );
@@ -47,8 +47,7 @@ export class NightCompositePass {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
getAmbient(): number { getAmbient(): number {
const dn = this.settings.dayNight; return this.settings.lighting.ambient;
return dn.mode === "dark" ? dn.nightAmbient : dn.dayAmbient;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
@@ -207,7 +207,7 @@ export class PointLightPass {
if (this.lightCount === 0) return; if (this.lightCount === 0) return;
const gl = this.gl; const gl = this.gl;
const dn = this.settings.dayNight; const dn = this.settings.lighting;
gl.useProgram(this.lightProg); gl.useProgram(this.lightProg);
gl.uniformMatrix3fv(this.uLightCam, false, cameraMatrix); gl.uniformMatrix3fv(this.uLightCam, false, cameraMatrix);
+3 -4
View File
@@ -44,10 +44,9 @@
"particleStrength": 1, "particleStrength": 1,
"particleFreshScale": 0.2 "particleFreshScale": 0.2
}, },
"dayNight": { "lighting": {
"mode": "light", "ambient": 1,
"nightAmbient": 0.15, "enabled": false,
"dayAmbient": 1,
"falloffPower": 2, "falloffPower": 2,
"falloutLightR": 0.15, "falloutLightR": 0.15,
"falloutLightG": 0.95, "falloutLightG": 0.95,
+31 -27
View File
@@ -1,9 +1,16 @@
import { describe, expect, test } from "vitest"; import { describe, expect, test } from "vitest";
import { GraphicsOverridesSchema } from "../src/client/render/gl/GraphicsOverrides";
import { import {
createRenderSettings, GraphicsOverrides,
generateRenderSettings, GraphicsOverridesSchema,
} from "../src/client/render/gl/RenderSettings"; } from "../src/client/render/gl/GraphicsOverrides";
import { applyGraphicsOverrides } from "../src/client/render/gl/RenderOverrides";
import { createRenderSettings } from "../src/client/render/gl/RenderSettings";
function gen(overrides: GraphicsOverrides) {
const settings = createRenderSettings();
applyGraphicsOverrides(settings, overrides);
return settings;
}
describe("GraphicsOverridesSchema", () => { describe("GraphicsOverridesSchema", () => {
test("accepts empty object", () => { test("accepts empty object", () => {
@@ -51,16 +58,16 @@ describe("GraphicsOverridesSchema", () => {
}); });
}); });
describe("generateRenderSettings", () => { describe("applyGraphicsOverrides", () => {
test("with empty overrides matches createRenderSettings defaults", () => { test("with empty overrides matches createRenderSettings defaults", () => {
const fromGen = generateRenderSettings({}); const fromGen = gen({});
const fromCreate = createRenderSettings(); const fromCreate = createRenderSettings();
expect(fromGen).toEqual(fromCreate); expect(fromGen).toEqual(fromCreate);
}); });
test("returns a fresh object each call (no shared mutation)", () => { test("returns a fresh object each call (no shared mutation)", () => {
const a = generateRenderSettings({}); const a = gen({});
const b = generateRenderSettings({}); const b = gen({});
expect(a).not.toBe(b); expect(a).not.toBe(b);
expect(a.name).not.toBe(b.name); expect(a.name).not.toBe(b.name);
a.name.nameScaleFactor = 999; a.name.nameScaleFactor = 999;
@@ -70,27 +77,24 @@ describe("generateRenderSettings", () => {
test("does not mutate the overrides input", () => { test("does not mutate the overrides input", () => {
const overrides = { name: { darkNames: true as const } }; const overrides = { name: { darkNames: true as const } };
const snapshot = JSON.parse(JSON.stringify(overrides)); const snapshot = JSON.parse(JSON.stringify(overrides));
generateRenderSettings(overrides); gen(overrides);
expect(overrides).toEqual(snapshot); expect(overrides).toEqual(snapshot);
}); });
test("applies nameScaleFactor override", () => { test("applies nameScaleFactor override", () => {
const settings = generateRenderSettings({ name: { nameScaleFactor: 1.3 } }); const settings = gen({ name: { nameScaleFactor: 1.3 } });
expect(settings.name.nameScaleFactor).toBe(1.3); expect(settings.name.nameScaleFactor).toBe(1.3);
}); });
test("applies cullThreshold override (including 0)", () => { test("applies cullThreshold override (including 0)", () => {
expect( expect(gen({ name: { cullThreshold: 0.03 } }).name.cullThreshold).toBe(
generateRenderSettings({ name: { cullThreshold: 0.03 } }).name 0.03,
.cullThreshold, );
).toBe(0.03); expect(gen({ name: { cullThreshold: 0 } }).name.cullThreshold).toBe(0);
expect(
generateRenderSettings({ name: { cullThreshold: 0 } }).name.cullThreshold,
).toBe(0);
}); });
test("darkNames=true → black fill + player-colored outline + outline RGB 0", () => { test("darkNames=true → black fill + player-colored outline + outline RGB 0", () => {
const s = generateRenderSettings({ name: { darkNames: true } }).name; const s = gen({ name: { darkNames: true } }).name;
expect(s.fillUsePlayerColor).toBe(false); expect(s.fillUsePlayerColor).toBe(false);
expect(s.outlineUsePlayerColor).toBe(true); expect(s.outlineUsePlayerColor).toBe(true);
expect(s.outlineR).toBe(0); expect(s.outlineR).toBe(0);
@@ -99,7 +103,7 @@ describe("generateRenderSettings", () => {
}); });
test("darkNames=false → player-colored fill + white outline + outline RGB 1", () => { test("darkNames=false → player-colored fill + white outline + outline RGB 1", () => {
const s = generateRenderSettings({ name: { darkNames: false } }).name; const s = gen({ name: { darkNames: false } }).name;
expect(s.fillUsePlayerColor).toBe(true); expect(s.fillUsePlayerColor).toBe(true);
expect(s.outlineUsePlayerColor).toBe(false); expect(s.outlineUsePlayerColor).toBe(false);
expect(s.outlineR).toBe(1); expect(s.outlineR).toBe(1);
@@ -109,13 +113,13 @@ describe("generateRenderSettings", () => {
test("only-darkNames override leaves nameScale/cull at defaults", () => { test("only-darkNames override leaves nameScale/cull at defaults", () => {
const defaults = createRenderSettings().name; const defaults = createRenderSettings().name;
const s = generateRenderSettings({ name: { darkNames: true } }).name; const s = gen({ name: { darkNames: true } }).name;
expect(s.nameScaleFactor).toBe(defaults.nameScaleFactor); expect(s.nameScaleFactor).toBe(defaults.nameScaleFactor);
expect(s.cullThreshold).toBe(defaults.cullThreshold); expect(s.cullThreshold).toBe(defaults.cullThreshold);
}); });
test("combined overrides all apply together", () => { test("combined overrides all apply together", () => {
const s = generateRenderSettings({ const s = gen({
name: { nameScaleFactor: 0.9, cullThreshold: 0.01, darkNames: true }, name: { nameScaleFactor: 0.9, cullThreshold: 0.01, darkNames: true },
}).name; }).name;
expect(s.nameScaleFactor).toBe(0.9); expect(s.nameScaleFactor).toBe(0.9);
@@ -127,16 +131,16 @@ describe("generateRenderSettings", () => {
test("settings outside the name slice are untouched by name overrides", () => { test("settings outside the name slice are untouched by name overrides", () => {
const defaults = createRenderSettings(); const defaults = createRenderSettings();
const s = generateRenderSettings({ const s = gen({
name: { nameScaleFactor: 0.6, darkNames: true }, name: { nameScaleFactor: 0.6, darkNames: true },
}); });
expect(s.passEnabled).toEqual(defaults.passEnabled); expect(s.passEnabled).toEqual(defaults.passEnabled);
expect(s.dayNight).toEqual(defaults.dayNight); expect(s.lighting).toEqual(defaults.lighting);
expect(s.structure).toEqual(defaults.structure); expect(s.structure).toEqual(defaults.structure);
}); });
test("classicIcons=true → light shape + dark icon + 0.75 alpha", () => { test("classicIcons=true → light shape + dark icon + 0.75 alpha", () => {
const s = generateRenderSettings({ const s = gen({
structure: { classicIcons: true }, structure: { classicIcons: true },
}).structure; }).structure;
// Shape (circle behind) is mostly player color, lightly darkened. // Shape (circle behind) is mostly player color, lightly darkened.
@@ -152,14 +156,14 @@ describe("generateRenderSettings", () => {
test("classicIcons=false or absent → keeps render-settings.json defaults (fully opaque)", () => { test("classicIcons=false or absent → keeps render-settings.json defaults (fully opaque)", () => {
const defaults = createRenderSettings().structure; const defaults = createRenderSettings().structure;
const off = generateRenderSettings({ const off = gen({
structure: { classicIcons: false }, structure: { classicIcons: false },
}).structure; }).structure;
expect(off.borderDarken).toBe(defaults.borderDarken); expect(off.borderDarken).toBe(defaults.borderDarken);
expect(off.fillDarken).toBe(defaults.fillDarken); expect(off.fillDarken).toBe(defaults.fillDarken);
expect(off.iconR).toBe(defaults.iconR); expect(off.iconR).toBe(defaults.iconR);
expect(off.iconAlpha).toBe(1); expect(off.iconAlpha).toBe(1);
const absent = generateRenderSettings({ structure: {} }).structure; const absent = gen({ structure: {} }).structure;
expect(absent.borderDarken).toBe(defaults.borderDarken); expect(absent.borderDarken).toBe(defaults.borderDarken);
expect(absent.fillDarken).toBe(defaults.fillDarken); expect(absent.fillDarken).toBe(defaults.fillDarken);
expect(absent.iconR).toBe(defaults.iconR); expect(absent.iconR).toBe(defaults.iconR);
@@ -167,7 +171,7 @@ describe("generateRenderSettings", () => {
}); });
test("classicIcons + name overrides compose independently", () => { test("classicIcons + name overrides compose independently", () => {
const s = generateRenderSettings({ const s = gen({
name: { darkNames: true, nameScaleFactor: 0.9 }, name: { darkNames: true, nameScaleFactor: 0.9 },
structure: { classicIcons: true }, structure: { classicIcons: true },
}); });