mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-15 14:46:03 +00:00
unit price (#3989)
## Description: # Ghost structure cost label Renders the gold cost of the currently-selected build under the ghost structure cursor, with color-coded affordability/placement state. Honors the existing `cursorCostLabel` user setting (legacy name `ghostPricePill`, already shipping ON by default). ## Behavior | State | Color | |---|---| | Can afford + valid placement | white | | Can afford + can't place here (port on land, overlap, …) | gray | | Can't afford | red | The number is formatted via `renderNumber` (project-wide convention — `1.5K`, `1.23M`, etc.) and rendered as MSDF text at a fixed world-space scale, centered under the ghost icon. ## Implementation The cost was already plumbed end-to-end on [`GhostPreviewData.cost`](src/client/render/types/Renderer.ts) but never visualized. This PR: - Extends [`GhostPreviewData`](src/client/render/types/Renderer.ts) with `showCost` (from setting) and `canAfford` (gold vs. cost check, computed in [BuildPreviewController](src/client/controllers/BuildPreviewController.ts)). - Adds a `setGhostCostLabel(...)` channel to the MSDF text pass — one persistent, non-animated text instance alongside the existing ephemeral popups. No new pass, no new shader. - Wires [`Renderer.updateGhostPreview`](src/client/render/gl/Renderer.ts) to push the label whenever a ghost is active. - Renames `ConquestPopupPass` → [`WorldTextPass`](src/client/render/gl/passes/WorldTextPass.ts) (and its shader dir `conquest-popup/` → `world-text/`) since it now handles conquest popups, bonus popups, and the ghost cost label. Done with `git mv` so history is preserved. https://github.com/user-attachments/assets/c5b21bf3-f440-4c28-9b94-843df9bf6a37 ## 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 - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: evan
This commit is contained in:
@@ -30,7 +30,6 @@ import type { RadialMenuItem } from "./Events";
|
||||
import { BarPass } from "./passes/BarPass";
|
||||
import { BorderComputePass } from "./passes/BorderComputePass";
|
||||
import { BorderStampPass } from "./passes/BorderStampPass";
|
||||
import { ConquestPopupPass } from "./passes/ConquestPopupPass";
|
||||
import { CoordinateGridPass } from "./passes/CoordinateGridPass";
|
||||
import { CrosshairPass } from "./passes/CrosshairPass";
|
||||
import { FalloutBloomPass } from "./passes/FalloutBloomPass";
|
||||
@@ -56,6 +55,7 @@ import { TerrainPass } from "./passes/TerrainPass";
|
||||
import { TerritoryPass } from "./passes/TerritoryPass";
|
||||
import { TrailPass } from "./passes/TrailPass";
|
||||
import { UnitPass } from "./passes/UnitPass";
|
||||
import { WorldTextPass } from "./passes/WorldTextPass";
|
||||
import { createRenderSettings, type RenderSettings } from "./RenderSettings";
|
||||
import { AffiliationPalette } from "./utils/Affiliation";
|
||||
import { buildTerrainRGBA, getPaletteSize } from "./utils/ColorUtils";
|
||||
@@ -114,7 +114,7 @@ export class GPURenderer {
|
||||
private crosshairPass: CrosshairPass;
|
||||
private railroadPass: RailroadPass;
|
||||
private barPass: BarPass;
|
||||
private conquestPopupPass: ConquestPopupPass;
|
||||
private worldTextPass: WorldTextPass;
|
||||
private radialMenuPass: RadialMenuPass;
|
||||
private selectionBoxPass: SelectionBoxPass;
|
||||
private moveIndicatorPass: MoveIndicatorPass;
|
||||
@@ -399,8 +399,8 @@ export class GPURenderer {
|
||||
this.namePass = new NamePass(gl, header, paletteData, this.settings);
|
||||
this.fxPass = new FxPass(gl, header, this.settings);
|
||||
this.barPass = new BarPass(gl, header, this.settings);
|
||||
this.conquestPopupPass = new ConquestPopupPass(gl, this.settings);
|
||||
this.conquestPopupPass.setMapWidth(this.mapW);
|
||||
this.worldTextPass = new WorldTextPass(gl, this.settings);
|
||||
this.worldTextPass.setMapWidth(this.mapW);
|
||||
this.radialMenuPass = new RadialMenuPass(gl);
|
||||
this.selectionBoxPass = new SelectionBoxPass(gl);
|
||||
this.moveIndicatorPass = new MoveIndicatorPass(gl, this.settings);
|
||||
@@ -730,7 +730,7 @@ export class GPURenderer {
|
||||
applyConquestEvents(events: ConquestFx[]): void {
|
||||
if (events.length > 0) {
|
||||
this.fxPass.applyConquestEvents(events);
|
||||
this.conquestPopupPass.applyConquestEvents(events);
|
||||
this.worldTextPass.applyConquestEvents(events);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,7 +741,7 @@ export class GPURenderer {
|
||||
this.localPlayerID > 0
|
||||
? events.filter((e) => e.smallID === this.localPlayerID)
|
||||
: events;
|
||||
if (filtered.length > 0) this.conquestPopupPass.applyBonusEvents(filtered);
|
||||
if (filtered.length > 0) this.worldTextPass.applyBonusEvents(filtered);
|
||||
}
|
||||
|
||||
updateAttackRings(rings: AttackRingInput[]): void {
|
||||
@@ -750,11 +750,11 @@ export class GPURenderer {
|
||||
|
||||
clearFx(): void {
|
||||
this.fxPass.clear();
|
||||
this.conquestPopupPass.clear();
|
||||
this.worldTextPass.clear();
|
||||
}
|
||||
setFxTimeFn(fn: () => number): void {
|
||||
this.fxPass.setTimeFn(fn);
|
||||
this.conquestPopupPass.setTimeFn(fn);
|
||||
this.worldTextPass.setTimeFn(fn);
|
||||
}
|
||||
|
||||
updateGhostPreview(data: GhostPreviewData | null): void {
|
||||
@@ -762,6 +762,17 @@ export class GPURenderer {
|
||||
this.railroadPass.updateGhostPreview(data);
|
||||
this.rangeCirclePass.updateGhostPreview(data);
|
||||
this.crosshairPass.updateGhostPreview(data);
|
||||
this.worldTextPass.setGhostCostLabel(
|
||||
data && data.showCost && data.cost > 0
|
||||
? {
|
||||
tileX: data.tileX,
|
||||
tileY: data.tileY,
|
||||
cost: data.cost,
|
||||
canAfford: data.canAfford,
|
||||
canPlace: data.canBuild || data.canUpgrade,
|
||||
}
|
||||
: null,
|
||||
);
|
||||
this.samGhostVisible =
|
||||
data !== null && SAM_RADIUS_GHOST_TYPES.has(data.ghostType);
|
||||
this.samRadiusPass.setVisible(
|
||||
@@ -1162,8 +1173,8 @@ export class GPURenderer {
|
||||
this.fxPass.draw(cam, zoom);
|
||||
}
|
||||
|
||||
this.conquestPopupPass.tick();
|
||||
this.conquestPopupPass.draw(cam, zoom);
|
||||
this.worldTextPass.tick();
|
||||
this.worldTextPass.draw(cam, zoom);
|
||||
|
||||
if (this.gridView) this.coordinateGridPass.draw(cam, zoom);
|
||||
if (pe.name && !this.gridView)
|
||||
@@ -1203,7 +1214,7 @@ export class GPURenderer {
|
||||
this.unitPass.dispose();
|
||||
this.namePass.dispose();
|
||||
this.fxPass.dispose();
|
||||
this.conquestPopupPass.dispose();
|
||||
this.worldTextPass.dispose();
|
||||
this.radialMenuPass.dispose();
|
||||
this.selectionBoxPass.dispose();
|
||||
this.moveIndicatorPass.dispose();
|
||||
|
||||
Reference in New Issue
Block a user