mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-24 04:53:45 +00:00
Add Graphics Settings modal with live name-label tuning (#4065)
## Description:
- Add a user-facing **Graphics Settings** modal accessible from the
in-game Settings menu, with live preview as sliders change.
- First two knobs: **Name Scale** and **Minimum Name Size** (the
name-cull threshold).
- Overrides stored as a single JSON blob in `localStorage` under
`settings.graphics`, validated by a Zod schema
(`GraphicsOverridesSchema`). Future graphics knobs just extend the
schema + slider list.
## How it fits together
- `generateRenderSettings(overrides)` (`RenderSettings.ts`) — pure
function: clones `render-settings.json` defaults, layers overrides on
top, returns a fresh `RenderSettings`.
- `UserSettings.graphicsOverrides()` / `setGraphicsOverrides()` —
read/write the blob; falls back to `{}` on a missing/corrupt entry.
- `ClientGameRunner` listens for
`USER_SETTINGS_CHANGED_EVENT:settings.graphics`, regenerates, and
`Object.assign`s each category into the live `view.getSettings()` slice
so passes pick up the new values on the next frame (no renderer
reconstruction).
- Modal reads defaults straight from `render-settings.json` so there's
no duplication.
<img width="599" height="515" alt="Screenshot 2026-05-28 at 11 18 43 AM"
src="https://github.com/user-attachments/assets/263d7d91-10d8-4a66-a069-10015c735d60"
/>
## 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
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
## Please put your Discord username so you can be contacted if a bug or
regression is found:
evan
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
import {
|
||||
GraphicsOverrides,
|
||||
GraphicsOverridesSchema,
|
||||
} from "../../client/render/gl/GraphicsOverrides";
|
||||
import { Cosmetics } from "../CosmeticSchemas";
|
||||
import { PlayerPattern } from "../Schemas";
|
||||
|
||||
@@ -53,6 +57,7 @@ export const COLOR_KEY = "settings.territoryColor";
|
||||
export const DARK_MODE_KEY = "settings.darkMode";
|
||||
export const PERFORMANCE_OVERLAY_KEY = "settings.performanceOverlay";
|
||||
export const KEYBINDS_KEY = "settings.keybinds";
|
||||
export const GRAPHICS_KEY = "settings.graphics";
|
||||
|
||||
export class UserSettings {
|
||||
private static cache = new Map<string, string | null>();
|
||||
@@ -354,6 +359,23 @@ export class UserSettings {
|
||||
this.setFloat("settings.attackRatio", value);
|
||||
}
|
||||
|
||||
// Returns {} if missing, unparseable, or fails schema validation.
|
||||
graphicsOverrides(): GraphicsOverrides {
|
||||
const raw = this.getString(GRAPHICS_KEY, "");
|
||||
if (!raw) return {};
|
||||
try {
|
||||
const parsed = GraphicsOverridesSchema.safeParse(JSON.parse(raw));
|
||||
if (parsed.success) return parsed.data;
|
||||
} catch {
|
||||
// fall through
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
setGraphicsOverrides(value: GraphicsOverrides): void {
|
||||
this.setString(GRAPHICS_KEY, JSON.stringify(value));
|
||||
}
|
||||
|
||||
// In case localStorage was manually edited to be invalid, return an empty object
|
||||
parsedUserKeybinds(): Record<string, any> {
|
||||
const raw = this.getString(KEYBINDS_KEY, "{}");
|
||||
|
||||
Reference in New Issue
Block a user