feat(ui): Phase 29 map visibility toggles
Tests · Go / test (push) Successful in 2m31s
Tests · UI / test (push) Failing after 8m7s

Adds the gear-icon popover on the map view with per-game persistence
of every category toggle plus the wrap-mode radio. Hide-by-id and
visibility-fog facilities land on the renderer so every flip applies
within one frame without a Pixi remount; the wrap-mode toggle keeps
its existing remount + camera-preserve path. A new server-side turn
force-resets every flag to defaults so a hidden category never makes
the player miss the next turn's news.

Also fixes the FligthDistance → FlightDistance typo in pkg/calc/race.go
(plus the single Go caller); the TS side keeps duplicating the formula
until a race-level WASM bridge lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-19 21:33:53 +02:00
parent 65c0fbb87d
commit 2bd1b54936
32 changed files with 3046 additions and 63 deletions
+34 -1
View File
@@ -60,9 +60,26 @@ export interface BombingMarkerTarget {
export type MarkerTarget = BattleMarkerTarget | BombingMarkerTarget;
/**
* MarkerCategory tags every emitted primitive with the toggleable
* surface it belongs to so the Phase 29 hide-set machinery can flip
* each independently. Battles and bombings have their own toggles —
* a player can hide the bombing rings while keeping the battle
* crosses visible.
*/
export type MarkerCategory = "battleMarker" | "bombingMarker";
export interface BuildMarkersResult {
primitives: Primitive[];
lookup: Map<PrimitiveID, MarkerTarget>;
categories: Map<PrimitiveID, MarkerCategory>;
/**
* planetDependents maps the anchor planet number to the ids of
* markers drawn on it; the Phase 29 cascade hides the markers
* together with the planet when the planet itself is filtered out
* (kind toggle off or unreachable filter on).
*/
planetDependents: Map<number, Set<PrimitiveID>>;
}
/**
@@ -93,6 +110,16 @@ export function buildBattleAndBombingMarkers(
const primitives: Primitive[] = [];
const lookup = new Map<PrimitiveID, MarkerTarget>();
const categories = new Map<PrimitiveID, MarkerCategory>();
const planetDependents = new Map<number, Set<PrimitiveID>>();
const addDependent = (planetNumber: number, id: PrimitiveID): void => {
let set = planetDependents.get(planetNumber);
if (set === undefined) {
set = new Set();
planetDependents.set(planetNumber, set);
}
set.add(id);
};
for (let i = 0; i < report.battles.length; i++) {
const battle = report.battles[i];
@@ -135,6 +162,10 @@ export function buildBattleAndBombingMarkers(
primitives.push(lineA, lineB);
lookup.set(lineA.id, target);
lookup.set(lineB.id, target);
categories.set(lineA.id, "battleMarker");
categories.set(lineB.id, "battleMarker");
addDependent(battle.planet, lineA.id);
addDependent(battle.planet, lineB.id);
}
for (let i = 0; i < report.bombings.length; i++) {
@@ -162,7 +193,9 @@ export function buildBattleAndBombingMarkers(
};
primitives.push(ring);
lookup.set(id, { kind: "bombing", planet: bombing.planetNumber });
categories.set(id, "bombingMarker");
addDependent(bombing.planetNumber, id);
}
return { primitives, lookup };
return { primitives, lookup, categories, planetDependents };
}