mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-17 17:41:43 +00:00
rename render/ files to UpperCamelCase to match client convention
The render/ tree was the only place in the client still using kebab-case filenames. Brings ~80 files in line with the rest of src/client/ (BuildPreviewController, TransformHandler, etc.). Directories kept as they were (name-pass/, fx-pass/, passes/, utils/, debug/) since the codebase already mixes those. Two collisions surfaced and got resolved: render/types/ is a directory, not a file, so its imports kept the lowercase form; and the sed pass incidentally normalized core/pathfinding imports, which had to be reverted since that file is actually lowercase on disk despite some imports having referenced it as ./Types under macOS case-insensitive resolution.
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* StatusIconProgram — instanced status icons above player names.
|
||||
*
|
||||
* Renders up to 8 status icons per player (crown, traitor, disconnected,
|
||||
* alliance, alliance request, target, embargo, nuke). Each instance reads
|
||||
* individual float flags from pd5/pd6 to decide whether to draw.
|
||||
*
|
||||
* Owns: shader program, uniform locations, status atlas texture.
|
||||
* The shared playerDataTex is passed in but not owned/deleted.
|
||||
*/
|
||||
|
||||
import statusAtlasMeta from "resources/atlases/status-atlas-meta.json";
|
||||
import { assetUrl } from "src/core/AssetUrls";
|
||||
import type { RenderSettings } from "../../RenderSettings";
|
||||
import statusFragSrc from "../../shaders/name/status-icon.frag.glsl?raw";
|
||||
import statusVertSrc from "../../shaders/name/status-icon.vert.glsl?raw";
|
||||
import { createProgram } from "../../utils/GlUtils";
|
||||
import type { ParsedAtlas } from "./Types";
|
||||
|
||||
const statusAtlasUrl = assetUrl("atlases/status-atlas.png");
|
||||
|
||||
const MAX_STATUS_ICONS = 8;
|
||||
|
||||
export class StatusIconProgram {
|
||||
private gl: WebGL2RenderingContext;
|
||||
private program: WebGLProgram;
|
||||
private playerDataTex: WebGLTexture;
|
||||
private maxPlayers: number;
|
||||
|
||||
private statusAtlasTex: WebGLTexture | null = null;
|
||||
private atlasReady = false;
|
||||
|
||||
// Dynamic uniform locations
|
||||
private uCamera: WebGLUniformLocation;
|
||||
private uTime: WebGLUniformLocation;
|
||||
private uLerpSpeed: WebGLUniformLocation;
|
||||
private uCullThreshold: WebGLUniformLocation;
|
||||
private uNameScaleFactor: WebGLUniformLocation;
|
||||
private uNameScaleCap: WebGLUniformLocation;
|
||||
private uStatusRowOffset: WebGLUniformLocation;
|
||||
|
||||
constructor(
|
||||
gl: WebGL2RenderingContext,
|
||||
atlas: ParsedAtlas,
|
||||
playerDataTex: WebGLTexture,
|
||||
maxPlayers: number,
|
||||
) {
|
||||
this.gl = gl;
|
||||
this.playerDataTex = playerDataTex;
|
||||
this.maxPlayers = maxPlayers;
|
||||
|
||||
this.program = createProgram(gl, statusVertSrc, statusFragSrc);
|
||||
gl.useProgram(this.program);
|
||||
|
||||
// Texture unit bindings
|
||||
gl.uniform1i(gl.getUniformLocation(this.program, "uPlayerData"), 0);
|
||||
gl.uniform1i(gl.getUniformLocation(this.program, "uStatusAtlas"), 1);
|
||||
|
||||
// Static uniforms from atlas metadata
|
||||
const sm = statusAtlasMeta as any;
|
||||
gl.uniform1f(
|
||||
gl.getUniformLocation(this.program, "uFontSize")!,
|
||||
atlas.fontSize,
|
||||
);
|
||||
gl.uniform1f(gl.getUniformLocation(this.program, "uFontBase")!, atlas.base);
|
||||
gl.uniform1f(
|
||||
gl.getUniformLocation(this.program, "uStatusCell")!,
|
||||
sm.cellSize,
|
||||
);
|
||||
gl.uniform1f(gl.getUniformLocation(this.program, "uStatusCols")!, sm.cols);
|
||||
gl.uniform1f(
|
||||
gl.getUniformLocation(this.program, "uStatusAtlasW")!,
|
||||
sm.width,
|
||||
);
|
||||
gl.uniform1f(
|
||||
gl.getUniformLocation(this.program, "uStatusAtlasH")!,
|
||||
sm.height,
|
||||
);
|
||||
gl.uniform1f(
|
||||
gl.getUniformLocation(this.program, "uStatusPad")!,
|
||||
sm.pad ?? 0,
|
||||
);
|
||||
|
||||
// Dynamic uniform locations
|
||||
this.uCamera = gl.getUniformLocation(this.program, "uCamera")!;
|
||||
this.uTime = gl.getUniformLocation(this.program, "uTime")!;
|
||||
this.uLerpSpeed = gl.getUniformLocation(this.program, "uLerpSpeed")!;
|
||||
this.uCullThreshold = gl.getUniformLocation(
|
||||
this.program,
|
||||
"uCullThreshold",
|
||||
)!;
|
||||
this.uNameScaleFactor = gl.getUniformLocation(
|
||||
this.program,
|
||||
"uNameScaleFactor",
|
||||
)!;
|
||||
this.uNameScaleCap = gl.getUniformLocation(this.program, "uNameScaleCap")!;
|
||||
this.uStatusRowOffset = gl.getUniformLocation(
|
||||
this.program,
|
||||
"uStatusRowOffset",
|
||||
)!;
|
||||
|
||||
this.loadAtlas();
|
||||
}
|
||||
|
||||
private loadAtlas(): void {
|
||||
const gl = this.gl;
|
||||
const img = new Image();
|
||||
img.crossOrigin = "anonymous";
|
||||
img.onload = () => {
|
||||
const tex = gl.createTexture()!;
|
||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
||||
gl.texParameteri(
|
||||
gl.TEXTURE_2D,
|
||||
gl.TEXTURE_MIN_FILTER,
|
||||
gl.LINEAR_MIPMAP_LINEAR,
|
||||
);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
|
||||
gl.generateMipmap(gl.TEXTURE_2D);
|
||||
this.statusAtlasTex = tex;
|
||||
this.atlasReady = true;
|
||||
};
|
||||
img.src = statusAtlasUrl;
|
||||
}
|
||||
|
||||
draw(
|
||||
cameraMatrix: Float32Array,
|
||||
settings: RenderSettings,
|
||||
vao: WebGLVertexArrayObject,
|
||||
): void {
|
||||
if (!this.atlasReady) return;
|
||||
|
||||
const gl = this.gl;
|
||||
const ns = settings.name;
|
||||
gl.useProgram(this.program);
|
||||
|
||||
gl.uniformMatrix3fv(this.uCamera, false, cameraMatrix);
|
||||
gl.uniform1f(this.uTime, performance.now() / 1000);
|
||||
gl.uniform1f(this.uLerpSpeed, ns.lerpSpeed);
|
||||
gl.uniform1f(this.uCullThreshold, ns.cullThreshold);
|
||||
gl.uniform1f(this.uNameScaleFactor, ns.nameScaleFactor);
|
||||
gl.uniform1f(this.uNameScaleCap, ns.nameScaleCap);
|
||||
gl.uniform1f(this.uStatusRowOffset, ns.statusRowOffset);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.playerDataTex);
|
||||
gl.activeTexture(gl.TEXTURE1);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.statusAtlasTex!);
|
||||
|
||||
gl.bindVertexArray(vao);
|
||||
gl.drawArraysInstanced(
|
||||
gl.TRIANGLES,
|
||||
0,
|
||||
6,
|
||||
this.maxPlayers * MAX_STATUS_ICONS,
|
||||
);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
const gl = this.gl;
|
||||
gl.deleteProgram(this.program);
|
||||
if (this.statusAtlasTex) gl.deleteTexture(this.statusAtlasTex);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user