Move special effects toggle to graphics settings, wire to renderer

The special effects toggle wrote settings.specialEffects but nothing in
the WebGL pipeline read it — the FX pass is gated on passEnabled.fx. The
setting was orphaned when the old canvas renderer was removed, so the
toggle had no visual effect.

Move the toggle into the graphics settings modal (under a new Effects
section) and remove it from the in-game settings modal and the homepage
user settings modal. Rewire it to a passEnabled.fx graphics override so
it actually toggles the FX pass, applied live via the existing graphics
override listener.

Delete the now-dead fxLayer()/toggleFxLayer() from UserSettings.

Note: users who previously disabled special effects will reset to on,
since the old settings.specialEffects key is no longer read.
This commit is contained in:
evanpelle
2026-06-08 14:15:07 -07:00
parent 1c1728f6fa
commit ea95069604
7 changed files with 54 additions and 57 deletions
+1
View File
@@ -946,6 +946,7 @@
"highlight_thicken_desc": "How much the border thickens on hover",
"rail_distance_label": "Train track draw distance",
"rail_distance_desc": "How far zoomed out train tracks remain visible",
"section_effects": "Effects",
"reset_label": "Reset to defaults",
"reset_desc": "Clear all graphics overrides"
},
-18
View File
@@ -221,15 +221,6 @@ export class UserSettingModal extends BaseModal {
);
}
private toggleFxLayer() {
this.userSettings.toggleFxLayer();
console.log(
"💥 Special effects:",
this.userSettings.fxLayer() ? "ON" : "OFF",
);
}
private toggleCursorCostLabel() {
this.userSettings.toggleCursorCostLabel();
@@ -769,15 +760,6 @@ export class UserSettingModal extends BaseModal {
@change=${this.toggleAlertFrame}
></setting-toggle>
<!-- 💥 Special effects -->
<setting-toggle
label="${translateText("user_setting.special_effects_label")}"
description="${translateText("user_setting.special_effects_desc")}"
id="special-effect-toggle"
.checked=${this.userSettings.fxLayer()}
@change=${this.toggleFxLayer}
></setting-toggle>
<!-- 💰 Cursor Price Pill -->
<setting-toggle
label="${translateText("user_setting.cursor_cost_label_label")}"
@@ -231,6 +231,26 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
this.patchStructure({ classicIcons: !this.currentClassicIcons() });
}
private patchPassEnabled(patch: Partial<GraphicsOverrides["passEnabled"]>) {
const current = this.userSettings.graphicsOverrides();
this.userSettings.setGraphicsOverrides({
...current,
passEnabled: { ...current.passEnabled, ...patch },
});
this.requestUpdate();
}
private currentSpecialEffects(): boolean {
return (
this.userSettings.graphicsOverrides().passEnabled?.fx ??
renderDefaults.passEnabled.fx
);
}
private onToggleSpecialEffects() {
this.patchPassEnabled({ fx: !this.currentSpecialEffects() });
}
private onNameScaleChange(event: Event) {
const value = parseFloat((event.target as HTMLInputElement).value);
this.patchName({ nameScaleFactor: value });
@@ -504,6 +524,31 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
</div>
</div>
<div
class="px-3 py-1 text-xs font-semibold text-slate-400 uppercase tracking-wider mt-2"
>
${translateText("graphics_setting.section_effects")}
</div>
<button
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
@click=${this.onToggleSpecialEffects}
>
<div class="flex-1">
<div class="font-medium">
${translateText("user_setting.special_effects_label")}
</div>
<div class="text-sm text-slate-400">
${translateText("user_setting.special_effects_desc")}
</div>
</div>
<div class="text-sm text-slate-400">
${this.currentSpecialEffects()
? translateText("user_setting.on")
: translateText("user_setting.off")}
</div>
</button>
<div class="border-t border-slate-600 pt-3 mt-4">
<button
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
-31
View File
@@ -21,7 +21,6 @@ const cursorPriceIcon = assetUrl("images/CursorPriceIconWhite.svg");
const darkModeIcon = assetUrl("images/DarkModeIconWhite.svg");
const emojiIcon = assetUrl("images/EmojiIconWhite.svg");
const exitIcon = assetUrl("images/ExitIconWhite.svg");
const explosionIcon = assetUrl("images/ExplosionIconWhite.svg");
const mouseIcon = assetUrl("images/MouseIconWhite.svg");
const ninjaIcon = assetUrl("images/NinjaIconWhite.svg");
const settingsIcon = assetUrl("images/SettingIconWhite.svg");
@@ -132,11 +131,6 @@ export class SettingsModal extends LitElement implements Controller {
this.requestUpdate();
}
private onToggleSpecialEffectsButtonClick() {
this.userSettings.toggleFxLayer();
this.requestUpdate();
}
private onToggleAlertFrameButtonClick() {
this.userSettings.toggleAlertFrame();
this.requestUpdate();
@@ -379,31 +373,6 @@ export class SettingsModal extends LitElement implements Controller {
</div>
</button>
<button
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
@click="${this.onToggleSpecialEffectsButtonClick}"
>
<img
src=${explosionIcon}
alt="specialEffects"
width="20"
height="20"
/>
<div class="flex-1">
<div class="font-medium">
${translateText("user_setting.special_effects_label")}
</div>
<div class="text-sm text-slate-400">
${translateText("user_setting.special_effects_desc")}
</div>
</div>
<div class="text-sm text-slate-400">
${this.userSettings.fxLayer()
? translateText("user_setting.on")
: translateText("user_setting.off")}
</div>
</button>
<button
class="flex gap-3 items-center w-full text-left p-3 hover:bg-slate-700 rounded-sm text-white transition-colors"
@click="${this.onToggleAlertFrameButtonClick}"
@@ -26,6 +26,11 @@ export const GraphicsOverridesSchema = z
railMinZoom: z.number(),
})
.partial(),
passEnabled: z
.object({
fx: z.boolean(),
})
.partial(),
})
.partial();
+3
View File
@@ -38,6 +38,9 @@ export function applyGraphicsOverrides(
if (overrides.railroad?.railMinZoom !== undefined) {
settings.railroad.railMinZoom = overrides.railroad.railMinZoom;
}
if (overrides.passEnabled?.fx !== undefined) {
settings.passEnabled.fx = overrides.passEnabled.fx;
}
if (overrides.name?.darkNames !== undefined) {
const dark = overrides.name.darkNames;
// Dark: black fill + player-colored outline. Force outline RGB to black
-8
View File
@@ -154,10 +154,6 @@ export class UserSettings {
return this.getBool("settings.lobbyIdVisibility", true);
}
fxLayer() {
return this.getBool("settings.specialEffects", true);
}
darkMode() {
return this.getBool(DARK_MODE_KEY, false);
}
@@ -219,10 +215,6 @@ export class UserSettings {
this.setBool("settings.lobbyIdVisibility", !this.lobbyIdVisibility());
}
toggleFxLayer() {
this.setBool("settings.specialEffects", !this.fxLayer());
}
toggleCursorCostLabel() {
this.setBool("settings.cursorCostLabel", !this.cursorCostLabel());
}