fix(ui-map): repaint fog as layered overpaint; rename to visibleHyperspace
Tests · UI / test (push) Waiting to run

The Phase 29 fog overlay rendered as a handful of random arc
segments instead of a clean union of holes around LOCAL planets
— Pixi v8's `Graphics.cut()` does not reliably subtract multiple
overlapping circles from a base path.

Replaced the cut-based approach with a layered overpaint: a
fog-tinted rectangle fills the world, then opaque background-
coloured circles are painted on top for every visibility circle.
The natural rendering order unions overlapping circles for free —
no geometry, no `cut()` quirks, one extra fill per circle.

Renamed the toggle from `visibilityFog` to `visibleHyperspace`
across the store, i18n strings, popover, tests, and docs. The
overlay still implements the visual "fog" effect at the renderer
level (FOG_COLOR, setVisibilityFog, getMapFog); the toggle is
named after the player-facing concept it controls — the portion
of the map that is visible (intelligence/scan coverage) — rather
than the obscured part.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-19 23:39:39 +02:00
parent 2f4dc01d54
commit 37580b7699
16 changed files with 86 additions and 65 deletions
+4 -4
View File
@@ -113,7 +113,7 @@ describe("GameStateStore.mapToggles persistence", () => {
await a.init({ client: makeFakeClient(3), cache, gameId: GAME_ID });
await a.setMapToggle("hyperspaceGroups", false);
await a.setMapToggle("battleMarkers", false);
await a.setMapToggle("visibilityFog", false);
await a.setMapToggle("visibleHyperspace", false);
a.dispose();
listMyGamesSpy.mockResolvedValue([makeGameSummary(3)]);
@@ -121,7 +121,7 @@ describe("GameStateStore.mapToggles persistence", () => {
await b.init({ client: makeFakeClient(3), cache, gameId: GAME_ID });
expect(b.mapToggles.hyperspaceGroups).toBe(false);
expect(b.mapToggles.battleMarkers).toBe(false);
expect(b.mapToggles.visibilityFog).toBe(false);
expect(b.mapToggles.visibleHyperspace).toBe(false);
// Untouched flags retain defaults.
expect(b.mapToggles.bombingMarkers).toBe(true);
b.dispose();
@@ -141,7 +141,7 @@ describe("GameStateStore.mapToggles persistence", () => {
expect(store.mapToggles.hyperspaceGroups).toBe(false);
expect(store.mapToggles.battleMarkers).toBe(true);
expect(store.mapToggles.bombingMarkers).toBe(true);
expect(store.mapToggles.visibilityFog).toBe(true);
expect(store.mapToggles.visibleHyperspace).toBe(true);
store.dispose();
});
});
@@ -153,7 +153,7 @@ describe("GameStateStore.mapToggles new-turn reset", () => {
...DEFAULT_MAP_TOGGLES,
hyperspaceGroups: false,
battleMarkers: false,
visibilityFog: false,
visibleHyperspace: false,
},
lastResetTurn: 4,
});