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
+20
View File
@@ -12,6 +12,7 @@ import {
distSqPointToSegment,
screenToWorld,
torusShortestDelta,
torusShortestDistance,
worldToScreen,
} from "../src/map/math";
@@ -104,3 +105,22 @@ describe("screenToWorld and worldToScreen", () => {
expect(w1.x - w0.x).toBeCloseTo(1, 12);
});
});
describe("torusShortestDistance", () => {
test("returns plain Euclidean distance when no wrap is shorter", () => {
const d = torusShortestDistance(0, 0, 3, 4, 1000, 1000);
expect(d).toBeCloseTo(5, 12);
});
test("respects torus wrap on both axes", () => {
// Wrap on x: 50 → 950 across the seam is 100 units.
// Wrap on y: 100 → 900 across the seam is 200 units.
// Hypot(100, 200) ≈ 223.606.
const d = torusShortestDistance(50, 100, 950, 900, 1000, 1000);
expect(d).toBeCloseTo(Math.hypot(100, 200), 9);
});
test("zero when both points coincide", () => {
expect(torusShortestDistance(123, 456, 123, 456, 1000, 1000)).toBe(0);
});
});