mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:30:45 +00:00
add subtle player-tile highlight on nation hover
The hover wiring already pushed setHighlightOwner into the border pass, but the WebGL canvas has pointer-events: none (post-migration to the inputOverlay div) so MapInteraction's pointermove listener never fired. Forward pointermove from the input overlay to view.handlePointerMove so hover actually triggers. While there, brighten every tile owned by the hovered player — the territory frag shader now reads uHighlightOwner / uHighlightBrighten and mixes toward white when the tile owner matches. Wired through territory-pass.ts; renderer.setHighlightOwner forwards to both border and territory passes. New highlightFillBrighten setting (0.15) keeps the fill tint tunable independently of the existing highlightBrighten border setting, which is dropped from 0.6 → 0.25 so neither effect blows out.
This commit is contained in:
@@ -445,6 +445,13 @@ async function createClientGame(
|
||||
(e) => applyDayNightMode((e as CustomEvent<string>).detail === "true"),
|
||||
);
|
||||
|
||||
// The WebGL canvas has pointer-events: none so input flows through the
|
||||
// overlay div. Forward pointermove to the WebGL view's MapInteraction so
|
||||
// hover-driven features (highlight owner, etc.) still work.
|
||||
inputOverlay.addEventListener("pointermove", (e) =>
|
||||
view.handlePointerMove(e),
|
||||
);
|
||||
|
||||
const gameRenderer = createRenderer(
|
||||
inputOverlay,
|
||||
gameView,
|
||||
|
||||
@@ -19,6 +19,10 @@ const PALETTE_SIZE = 4096;
|
||||
export class WebGLFrameBuilder {
|
||||
private readonly palette: Float32Array;
|
||||
private readonly knownSmallIDs = new Set<number>();
|
||||
// The renderer needs to know which player is "me" so affiliation tint,
|
||||
// unit colors, and SAM-radius perspective work. Push it once the local
|
||||
// player's update arrives (may take several ticks during join).
|
||||
private localPlayerSmallID = 0;
|
||||
|
||||
constructor(private readonly view: WebGLGameView) {
|
||||
this.palette = new Float32Array(PALETTE_SIZE * 2 * 4);
|
||||
@@ -26,9 +30,17 @@ export class WebGLFrameBuilder {
|
||||
|
||||
update(gameView: GameView): void {
|
||||
this.syncPlayers(gameView);
|
||||
this.syncLocalPlayer(gameView);
|
||||
uploadFrameData(this.view, gameView.frameData());
|
||||
}
|
||||
|
||||
private syncLocalPlayer(gameView: GameView): void {
|
||||
const sid = gameView.myPlayer()?.smallID() ?? 0;
|
||||
if (sid === this.localPlayerSmallID) return;
|
||||
this.localPlayerSmallID = sid;
|
||||
this.view.setLocalPlayerID(sid);
|
||||
}
|
||||
|
||||
private syncPlayers(gameView: GameView): void {
|
||||
const newPlayers: PlayerStatic[] = [];
|
||||
for (const p of gameView.players()) {
|
||||
|
||||
@@ -116,7 +116,16 @@ export function buildTree(s: RenderSettings, d: RenderSettings): DebugNode[] {
|
||||
0,
|
||||
1,
|
||||
0.01,
|
||||
"Highlight Brighten",
|
||||
"Highlight Brighten (border)",
|
||||
),
|
||||
slider(
|
||||
s.mapOverlay,
|
||||
"highlightFillBrighten",
|
||||
d.mapOverlay,
|
||||
0,
|
||||
1,
|
||||
0.01,
|
||||
"Highlight Brighten (fill)",
|
||||
),
|
||||
slider(
|
||||
s.mapOverlay,
|
||||
|
||||
@@ -110,6 +110,18 @@ export class GameView {
|
||||
if (rect.width > 0) this.renderer.resize(rect.width, rect.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward a pointermove event into the MapInteraction handler. The WebGL
|
||||
* canvas itself has pointer-events: none (input flows through a separate
|
||||
* overlay div in the main client), so the listener bound to `canvas` in
|
||||
* the constructor never actually fires for game-mode input. Callers that
|
||||
* own the active input element forward pointermove events here so hover
|
||||
* tracking + setHighlightOwner still work.
|
||||
*/
|
||||
handlePointerMove(e: PointerEvent): void {
|
||||
this.interaction.handlePointerMove(e);
|
||||
}
|
||||
|
||||
// ---- Event system ----
|
||||
|
||||
on<K extends GameViewEventType>(
|
||||
|
||||
@@ -34,6 +34,9 @@ export class TerritoryPass {
|
||||
private uCharcoalBase: WebGLUniformLocation;
|
||||
private uCharcoalVariation: WebGLUniformLocation;
|
||||
private uCharcoalAlpha: WebGLUniformLocation;
|
||||
private uHighlightOwner: WebGLUniformLocation;
|
||||
private uHighlightBrighten: WebGLUniformLocation;
|
||||
private highlightOwner = 0;
|
||||
|
||||
private vao: WebGLVertexArrayObject;
|
||||
private tileTex: WebGLTexture;
|
||||
@@ -101,6 +104,14 @@ export class TerritoryPass {
|
||||
this.program,
|
||||
"uCharcoalAlpha",
|
||||
)!;
|
||||
this.uHighlightOwner = gl.getUniformLocation(
|
||||
this.program,
|
||||
"uHighlightOwner",
|
||||
)!;
|
||||
this.uHighlightBrighten = gl.getUniformLocation(
|
||||
this.program,
|
||||
"uHighlightBrighten",
|
||||
)!;
|
||||
|
||||
gl.useProgram(this.program);
|
||||
gl.uniform1i(gl.getUniformLocation(this.program, "uTileTex"), 0);
|
||||
@@ -319,6 +330,11 @@ export class TerritoryPass {
|
||||
this.altView = active;
|
||||
}
|
||||
|
||||
/** Set the hovered player's smallID for territory-fill brightening (0 = off). */
|
||||
setHighlightOwner(ownerID: number): void {
|
||||
this.highlightOwner = ownerID;
|
||||
}
|
||||
|
||||
/** Draw territory fill + fallout charcoal. Blending must be enabled by caller. */
|
||||
draw(cameraMatrix: Float32Array): void {
|
||||
this.flushTileTexture();
|
||||
@@ -334,6 +350,8 @@ export class TerritoryPass {
|
||||
gl.uniform1f(this.uCharcoalBase, mo.charcoalBase);
|
||||
gl.uniform1f(this.uCharcoalVariation, mo.charcoalVariation);
|
||||
gl.uniform1f(this.uCharcoalAlpha, mo.charcoalAlpha);
|
||||
gl.uniform1ui(this.uHighlightOwner, this.highlightOwner);
|
||||
gl.uniform1f(this.uHighlightBrighten, mo.highlightFillBrighten);
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.tileTex);
|
||||
|
||||
@@ -65,7 +65,8 @@
|
||||
"emberColorBrightG": 0.5,
|
||||
"emberColorBrightB": 0.05,
|
||||
"emberStrengthUnowned": 0.5,
|
||||
"highlightBrighten": 0.6,
|
||||
"highlightBrighten": 0.25,
|
||||
"highlightFillBrighten": 0.15,
|
||||
"highlightThicken": 2,
|
||||
"defensePostRange": 30,
|
||||
"embargoTintRatio": 0.35,
|
||||
|
||||
@@ -68,6 +68,7 @@ export interface RenderSettings {
|
||||
emberColorBrightB: number;
|
||||
emberStrengthUnowned: number;
|
||||
highlightBrighten: number;
|
||||
highlightFillBrighten: number;
|
||||
highlightThicken: number;
|
||||
defensePostRange: number;
|
||||
embargoTintRatio: number;
|
||||
|
||||
@@ -694,10 +694,6 @@ export class GPURenderer {
|
||||
this.railroadPass.updateGhostPreview(data);
|
||||
this.rangeCirclePass.updateGhostPreview(data);
|
||||
this.crosshairPass.updateGhostPreview(data);
|
||||
if (data) this.localPlayerID = data.ownerID;
|
||||
this.samRadiusPass.setLocalPlayer(this.localPlayerID);
|
||||
this.affiliationPalette.setLocalPlayer(this.localPlayerID);
|
||||
this.unitPass.setLocalPlayer(this.localPlayerID);
|
||||
this.samGhostVisible =
|
||||
data !== null && SAM_RADIUS_GHOST_TYPES.has(data.ghostType);
|
||||
this.samRadiusPass.setVisible(
|
||||
@@ -723,6 +719,7 @@ export class GPURenderer {
|
||||
|
||||
setHighlightOwner(ownerID: number): void {
|
||||
this.borderPass.setHighlightOwner(ownerID);
|
||||
this.territoryPass.setHighlightOwner(ownerID);
|
||||
}
|
||||
setHighlightStructureTypes(unitTypes: string[] | null): void {
|
||||
this.structurePass.setHighlightTypes(unitTypes);
|
||||
|
||||
@@ -10,6 +10,8 @@ uniform int uAltView;
|
||||
uniform float uCharcoalBase;
|
||||
uniform float uCharcoalVariation;
|
||||
uniform float uCharcoalAlpha;
|
||||
uniform uint uHighlightOwner; // 0 = no highlight; otherwise smallID of hovered owner
|
||||
uniform float uHighlightBrighten; // mix amount toward white for highlighted tiles
|
||||
|
||||
in vec2 vWorldPos;
|
||||
out vec4 fragColor;
|
||||
@@ -38,5 +40,12 @@ void main() {
|
||||
|
||||
// --- Territory fill (owned) ---
|
||||
float u = (float(owner) + 0.5) / float(PALETTE_SIZE);
|
||||
fragColor = texture(uPalette, vec2(u, 0.25));
|
||||
vec4 color = texture(uPalette, vec2(u, 0.25));
|
||||
|
||||
// Hover highlight: brighten every tile owned by the hovered player.
|
||||
if (uHighlightOwner != 0u && owner == uHighlightOwner) {
|
||||
color.rgb = mix(color.rgb, vec3(1.0), uHighlightBrighten);
|
||||
}
|
||||
|
||||
fragColor = color;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user