mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:50:43 +00:00
fix(render): keep build-cost chip a fixed screen size
Chip used a world-space scale and y-offset, so it shrank as the camera zoomed out and slid under the cursor. Now both the scale and the downward offset are divided by zoom each frame, mirroring the existing attack-troop-label pattern. Tunable via ghostCost in render-settings.
This commit is contained in:
@@ -229,6 +229,10 @@ export interface RenderSettings {
|
||||
minScreenScale: number; // minimum world-scale when zoomed out (prevents vanishing)
|
||||
cullZoom: number; // popups hidden below this zoom level
|
||||
};
|
||||
ghostCost: {
|
||||
screenScale: number; // screen-relative em scale; divided by zoom each frame for fixed on-screen size
|
||||
screenYOffset: number; // screen-relative downward offset from icon center; divided by zoom each frame for fixed on-screen gap
|
||||
};
|
||||
spawnOverlay: {
|
||||
highlightRadius: number; // tile highlight radius (squared internally)
|
||||
highlightAlpha: number; // tile highlight opacity (0–1)
|
||||
|
||||
@@ -38,10 +38,6 @@ const CONQUEST_Y_OFFSET = 8;
|
||||
/** World-space font size for conquest popups. */
|
||||
const CONQUEST_SCALE = 6;
|
||||
const CONQUEST_OUTLINE_WIDTH = 2.0;
|
||||
/** Tiles below the ghost icon center for the cost label. */
|
||||
const GHOST_COST_Y_OFFSET = 3;
|
||||
/** World-space font size — smaller than popups so it sits unobtrusively under the icon. */
|
||||
const GHOST_COST_SCALE = 4;
|
||||
/** Matches player-name outline width for a consistent UI look. */
|
||||
const GHOST_COST_OUTLINE_WIDTH = 1.4;
|
||||
/**
|
||||
@@ -351,9 +347,10 @@ export class WorldTextPass {
|
||||
}
|
||||
// The vertex shader adds +0.5 to (x, y) for tile-center alignment, so we
|
||||
// pass raw tile coords here — same convention as the other popup entries.
|
||||
// Y offset is applied in rebuildInstances (zoom-relative).
|
||||
this.ghostCostLabel = {
|
||||
x: label.tileX,
|
||||
y: label.tileY + GHOST_COST_Y_OFFSET,
|
||||
y: label.tileY,
|
||||
text: renderNumber(label.cost),
|
||||
colorR: r,
|
||||
colorG: g,
|
||||
@@ -474,8 +471,12 @@ export class WorldTextPass {
|
||||
// Ghost cost label — persistent, no fade or rise. layoutString already
|
||||
// centers cursors around 0, so passing the tile coord places the text
|
||||
// centered on the tile (vertex shader adds the +0.5 tile-center offset).
|
||||
// Scale is divided by zoom so the chip keeps a constant on-screen size.
|
||||
const label = this.ghostCostLabel;
|
||||
if (label) {
|
||||
const invZoom = 1 / Math.max(zoom, 0.0001);
|
||||
const ghostScale = this.settings.ghostCost.screenScale * invZoom;
|
||||
const ghostY = label.y + this.settings.ghostCost.screenYOffset * invZoom;
|
||||
layoutString(
|
||||
label.text,
|
||||
this.glyph,
|
||||
@@ -490,14 +491,14 @@ export class WorldTextPass {
|
||||
|
||||
const off = count * FLOATS_PER_INSTANCE;
|
||||
this.instanceData[off + 0] = label.x;
|
||||
this.instanceData[off + 1] = label.y;
|
||||
this.instanceData[off + 1] = ghostY;
|
||||
this.instanceData[off + 2] = this.cursors[i];
|
||||
this.instanceData[off + 3] = this.charCodes[i];
|
||||
this.instanceData[off + 4] = 1;
|
||||
this.instanceData[off + 5] = label.colorR;
|
||||
this.instanceData[off + 6] = label.colorG;
|
||||
this.instanceData[off + 7] = label.colorB;
|
||||
this.instanceData[off + 8] = GHOST_COST_SCALE;
|
||||
this.instanceData[off + 8] = ghostScale;
|
||||
this.instanceData[off + 9] = GHOST_COST_OUTLINE_WIDTH;
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -244,6 +244,10 @@
|
||||
"minScreenScale": 0.15,
|
||||
"cullZoom": 0.3
|
||||
},
|
||||
"ghostCost": {
|
||||
"screenScale": 30,
|
||||
"screenYOffset": 50
|
||||
},
|
||||
"spawnOverlay": {
|
||||
"highlightRadius": 9,
|
||||
"highlightAlpha": 1.0,
|
||||
|
||||
Reference in New Issue
Block a user