mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-23 18:43:07 +00:00
Feature/Move theme system from core to client-side ThemeProvider (#4108)
**Add approved & assigned issue number here:** Resolves #2549 ## Description: Themes are purely for the client's rendering, and the server doesn't need context on them. This PR moves `Theme.ts` from `src/core/configuration` to `src/client/theme` and moves affiliation colors to `render-settings.json`. This is to support the ability to add additional themes more quickly, such as colorblind-friendly themes. No visible changes occur from this refactor. ## 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: jetaviz --------- Co-authored-by: Josh Harris <josh@wickedsick.com>
This commit is contained in:
@@ -79,6 +79,27 @@ export interface RenderSettings {
|
||||
defensePostRange: number;
|
||||
embargoTintRatio: number;
|
||||
friendlyTintRatio: number;
|
||||
embargoTintR: number;
|
||||
embargoTintG: number;
|
||||
embargoTintB: number;
|
||||
friendlyTintR: number;
|
||||
friendlyTintG: number;
|
||||
friendlyTintB: number;
|
||||
};
|
||||
/** Alt-view affiliation colors (0–1 RGB). */
|
||||
affiliation: {
|
||||
selfR: number;
|
||||
selfG: number;
|
||||
selfB: number;
|
||||
allyR: number;
|
||||
allyG: number;
|
||||
allyB: number;
|
||||
neutralR: number;
|
||||
neutralG: number;
|
||||
neutralB: number;
|
||||
enemyR: number;
|
||||
enemyG: number;
|
||||
enemyB: number;
|
||||
};
|
||||
railroad: {
|
||||
railMinZoom: number;
|
||||
|
||||
@@ -478,7 +478,7 @@ export class GPURenderer {
|
||||
this.sceneTarget = { fbo: sceneFbo, tex: sceneTex, w: 1, h: 1 };
|
||||
|
||||
// --- Alt-view passes ---
|
||||
this.affiliationPalette = new AffiliationPalette(gl);
|
||||
this.affiliationPalette = new AffiliationPalette(gl, this.settings);
|
||||
const affTex = this.affiliationPalette.getTexture();
|
||||
this.borderStampPass.setAffiliationTex(affTex);
|
||||
this.unitPass.setAffiliationTex(affTex);
|
||||
|
||||
@@ -27,6 +27,8 @@ export class BorderStampPass {
|
||||
private uDefenseCheckerDarken: WebGLUniformLocation;
|
||||
private uEmbargoTintRatio: WebGLUniformLocation;
|
||||
private uFriendlyTintRatio: WebGLUniformLocation;
|
||||
private uEmbargoTint: WebGLUniformLocation;
|
||||
private uFriendlyTint: WebGLUniformLocation;
|
||||
private uAltView: WebGLUniformLocation;
|
||||
|
||||
private vao: WebGLVertexArrayObject;
|
||||
@@ -79,6 +81,8 @@ export class BorderStampPass {
|
||||
this.program,
|
||||
"uFriendlyTintRatio",
|
||||
)!;
|
||||
this.uEmbargoTint = gl.getUniformLocation(this.program, "uEmbargoTint")!;
|
||||
this.uFriendlyTint = gl.getUniformLocation(this.program, "uFriendlyTint")!;
|
||||
this.uAltView = gl.getUniformLocation(this.program, "uAltView")!;
|
||||
|
||||
gl.useProgram(this.program);
|
||||
@@ -109,6 +113,18 @@ export class BorderStampPass {
|
||||
gl.uniform1f(this.uDefenseCheckerDarken, mo.defenseCheckerDarken);
|
||||
gl.uniform1f(this.uEmbargoTintRatio, mo.embargoTintRatio);
|
||||
gl.uniform1f(this.uFriendlyTintRatio, mo.friendlyTintRatio);
|
||||
gl.uniform3f(
|
||||
this.uEmbargoTint,
|
||||
mo.embargoTintR,
|
||||
mo.embargoTintG,
|
||||
mo.embargoTintB,
|
||||
);
|
||||
gl.uniform3f(
|
||||
this.uFriendlyTint,
|
||||
mo.friendlyTintR,
|
||||
mo.friendlyTintG,
|
||||
mo.friendlyTintB,
|
||||
);
|
||||
gl.uniform1i(this.uAltView, this.altView ? 1 : 0);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
|
||||
@@ -75,7 +75,27 @@
|
||||
"highlightThicken": 2,
|
||||
"defensePostRange": 30,
|
||||
"embargoTintRatio": 0.35,
|
||||
"friendlyTintRatio": 0.35
|
||||
"friendlyTintRatio": 0.35,
|
||||
"embargoTintR": 1,
|
||||
"embargoTintG": 0,
|
||||
"embargoTintB": 0,
|
||||
"friendlyTintR": 0,
|
||||
"friendlyTintG": 1,
|
||||
"friendlyTintB": 0
|
||||
},
|
||||
"affiliation": {
|
||||
"selfR": 0,
|
||||
"selfG": 1,
|
||||
"selfB": 0,
|
||||
"allyR": 1,
|
||||
"allyG": 1,
|
||||
"allyB": 0,
|
||||
"neutralR": 0.502,
|
||||
"neutralG": 0.502,
|
||||
"neutralB": 0.502,
|
||||
"enemyR": 1,
|
||||
"enemyG": 0,
|
||||
"enemyB": 0
|
||||
},
|
||||
"railroad": {
|
||||
"railMinZoom": 4,
|
||||
|
||||
@@ -12,6 +12,8 @@ uniform float uHighlightBrighten;
|
||||
uniform float uDefenseCheckerDarken;
|
||||
uniform float uEmbargoTintRatio;
|
||||
uniform float uFriendlyTintRatio;
|
||||
uniform vec3 uEmbargoTint;
|
||||
uniform vec3 uFriendlyTint;
|
||||
|
||||
in vec2 vWorldPos;
|
||||
out vec4 fragColor;
|
||||
@@ -46,9 +48,9 @@ void main() {
|
||||
}
|
||||
// Relationship tint (applied BEFORE defense checkerboard, matching game)
|
||||
if (relation > 0.75) {
|
||||
bc = mix(bc, vec3(1.0, 0.0, 0.0), uEmbargoTintRatio);
|
||||
bc = mix(bc, uEmbargoTint, uEmbargoTintRatio);
|
||||
} else if (relation > 0.25) {
|
||||
bc = mix(bc, vec3(0.0, 1.0, 0.0), uFriendlyTintRatio);
|
||||
bc = mix(bc, uFriendlyTint, uFriendlyTintRatio);
|
||||
}
|
||||
// Defense bonus: checkerboard darken (applied AFTER tint, matching game)
|
||||
if (defense) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* Rebuilt when localPlayerID or relationship data changes.
|
||||
*/
|
||||
|
||||
import type { RenderSettings } from "../RenderSettings";
|
||||
import { getPaletteSize } from "./ColorUtils";
|
||||
import { createTexture2D } from "./GlUtils";
|
||||
|
||||
@@ -16,20 +17,6 @@ const RELATION_NEUTRAL = 0;
|
||||
const RELATION_FRIENDLY = 1;
|
||||
const RELATION_EMBARGO = 2;
|
||||
|
||||
// Affiliation RGB values (upstream PastelTheme)
|
||||
const SELF_R = 0,
|
||||
SELF_G = 255,
|
||||
SELF_B = 0;
|
||||
const ALLY_R = 255,
|
||||
ALLY_G = 255,
|
||||
ALLY_B = 0;
|
||||
const NEUTRAL_R = 128,
|
||||
NEUTRAL_G = 128,
|
||||
NEUTRAL_B = 128;
|
||||
const ENEMY_R = 255,
|
||||
ENEMY_G = 0,
|
||||
ENEMY_B = 0;
|
||||
|
||||
const TEX_W = getPaletteSize(); // 4096 — covers full 12-bit smallID range
|
||||
const TEX_H = 2;
|
||||
|
||||
@@ -44,7 +31,10 @@ export class AffiliationPalette {
|
||||
private relationData: Uint8Array | null = null;
|
||||
private relationSize = 0;
|
||||
|
||||
constructor(gl: WebGL2RenderingContext) {
|
||||
constructor(
|
||||
gl: WebGL2RenderingContext,
|
||||
private settings: RenderSettings,
|
||||
) {
|
||||
this.gl = gl;
|
||||
this.rebuild(); // initialize to spectator-mode defaults (gray borders, red units)
|
||||
this.tex = createTexture2D(gl, {
|
||||
@@ -100,6 +90,22 @@ export class AffiliationPalette {
|
||||
const rel = this.relationData;
|
||||
const rs = this.relationSize;
|
||||
|
||||
// Affiliation RGB values (0–1) from render-settings, expanded to 0–255.
|
||||
const a = this.settings.affiliation;
|
||||
const to255 = (v: number) => Math.round(v * 255);
|
||||
const SELF_R = to255(a.selfR),
|
||||
SELF_G = to255(a.selfG),
|
||||
SELF_B = to255(a.selfB);
|
||||
const ALLY_R = to255(a.allyR),
|
||||
ALLY_G = to255(a.allyG),
|
||||
ALLY_B = to255(a.allyB);
|
||||
const NEUTRAL_R = to255(a.neutralR),
|
||||
NEUTRAL_G = to255(a.neutralG),
|
||||
NEUTRAL_B = to255(a.neutralB);
|
||||
const ENEMY_R = to255(a.enemyR),
|
||||
ENEMY_G = to255(a.enemyG),
|
||||
ENEMY_B = to255(a.enemyB);
|
||||
|
||||
for (let owner = 0; owner < TEX_W; owner++) {
|
||||
// Determine relationship
|
||||
let relation = RELATION_NEUTRAL;
|
||||
|
||||
Reference in New Issue
Block a user