mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 12:10:46 +00:00
4cd22a9b5c
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.
116 lines
3.9 KiB
TypeScript
116 lines
3.9 KiB
TypeScript
/**
|
|
* MoveIndicatorPass — converging chevron animation at a warship's
|
|
* move-target location. Matches the upstream game's MoveIndicatorUI
|
|
* but rendered via SDF in a fragment shader.
|
|
*/
|
|
|
|
import type { RenderSettings } from "../RenderSettings";
|
|
import { createProgram } from "../utils/GlUtils";
|
|
|
|
import fragSrc from "../shaders/move-indicator/move-indicator.frag.glsl?raw";
|
|
import vertSrc from "../shaders/move-indicator/move-indicator.vert.glsl?raw";
|
|
|
|
export class MoveIndicatorPass {
|
|
private gl: WebGL2RenderingContext;
|
|
private settings: RenderSettings;
|
|
private program: WebGLProgram;
|
|
private vao: WebGLVertexArrayObject;
|
|
|
|
private uCamera: WebGLUniformLocation;
|
|
private uCenter: WebGLUniformLocation;
|
|
private uElapsed: WebGLUniformLocation;
|
|
private uColor: WebGLUniformLocation;
|
|
private uPxPerTile: WebGLUniformLocation;
|
|
private uStartRadius: WebGLUniformLocation;
|
|
private uChevronSize: WebGLUniformLocation;
|
|
private uLineWidth: WebGLUniformLocation;
|
|
private uDuration: WebGLUniformLocation;
|
|
private uConverge: WebGLUniformLocation;
|
|
|
|
private active = false;
|
|
private centerX = 0;
|
|
private centerY = 0;
|
|
private colorR = 1;
|
|
private colorG = 0;
|
|
private colorB = 0;
|
|
private startTime = 0;
|
|
|
|
constructor(gl: WebGL2RenderingContext, settings: RenderSettings) {
|
|
this.gl = gl;
|
|
this.settings = settings;
|
|
this.program = createProgram(gl, vertSrc, fragSrc);
|
|
|
|
this.uCamera = gl.getUniformLocation(this.program, "uCamera")!;
|
|
this.uCenter = gl.getUniformLocation(this.program, "uCenter")!;
|
|
this.uElapsed = gl.getUniformLocation(this.program, "uElapsed")!;
|
|
this.uColor = gl.getUniformLocation(this.program, "uColor")!;
|
|
this.uPxPerTile = gl.getUniformLocation(this.program, "uPxPerTile")!;
|
|
this.uStartRadius = gl.getUniformLocation(this.program, "uStartRadius")!;
|
|
this.uChevronSize = gl.getUniformLocation(this.program, "uChevronSize")!;
|
|
this.uLineWidth = gl.getUniformLocation(this.program, "uLineWidth")!;
|
|
this.uDuration = gl.getUniformLocation(this.program, "uDuration")!;
|
|
this.uConverge = gl.getUniformLocation(this.program, "uConverge")!;
|
|
|
|
// Unit quad [0,1]
|
|
this.vao = gl.createVertexArray()!;
|
|
gl.bindVertexArray(this.vao);
|
|
const buf = gl.createBuffer()!;
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
gl.bufferData(
|
|
gl.ARRAY_BUFFER,
|
|
new Float32Array([0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1]),
|
|
gl.STATIC_DRAW,
|
|
);
|
|
gl.enableVertexAttribArray(0);
|
|
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
|
|
gl.bindVertexArray(null);
|
|
}
|
|
|
|
/**
|
|
* Trigger the move indicator at world tile (x, y) with player color.
|
|
* Each call replaces the previous indicator.
|
|
*/
|
|
show(x: number, y: number, r: number, g: number, b: number): void {
|
|
this.active = true;
|
|
this.centerX = x;
|
|
this.centerY = y;
|
|
this.colorR = r;
|
|
this.colorG = g;
|
|
this.colorB = b;
|
|
this.startTime = performance.now();
|
|
}
|
|
|
|
draw(cameraMatrix: Float32Array, zoom: number): void {
|
|
if (!this.active) return;
|
|
|
|
const s = this.settings.moveIndicator;
|
|
const elapsed = performance.now() - this.startTime;
|
|
if (elapsed >= s.duration) {
|
|
this.active = false;
|
|
return;
|
|
}
|
|
|
|
const gl = this.gl;
|
|
gl.useProgram(this.program);
|
|
gl.uniformMatrix3fv(this.uCamera, false, cameraMatrix);
|
|
gl.uniform2f(this.uCenter, this.centerX, this.centerY);
|
|
gl.uniform1f(this.uElapsed, elapsed);
|
|
gl.uniform3f(this.uColor, this.colorR, this.colorG, this.colorB);
|
|
gl.uniform1f(this.uPxPerTile, zoom);
|
|
gl.uniform1f(this.uStartRadius, s.startRadius);
|
|
gl.uniform1f(this.uChevronSize, s.chevronSize);
|
|
gl.uniform1f(this.uLineWidth, s.lineWidth);
|
|
gl.uniform1f(this.uDuration, s.duration);
|
|
gl.uniform1f(this.uConverge, s.converge);
|
|
|
|
gl.bindVertexArray(this.vao);
|
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
}
|
|
|
|
dispose(): void {
|
|
const gl = this.gl;
|
|
gl.deleteProgram(this.program);
|
|
gl.deleteVertexArray(this.vao);
|
|
}
|
|
}
|