Phase 29 — Map Toggles #20
Reference in New Issue
Block a user
Delete Branch "feature/ui-map-toggles"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Phase 29 of
ui/PLAN.md— the gear-icon popover that controls per-game mapvisibility plus the wrap-mode toggle.
MapTogglesrune inGameStateStorewith persistence in the newgame-map-togglescache namespace; a new server-side turn force-resets everyflag to defaults.
setHiddenPrimitiveIds(hide-by-id without remount,hit-test-aware) +
setVisibilityFog(layered overpaint on a viewport-levelfog layer that sits below every primitive copy).
reportToWorldnow also returnscategoriesandplanetDependentsso the map view can cascade planet hiding onto themarkers / in-space / incoming groups anchored on it; cargo routes and
pending-Send overlay filter the same way.
map-toggles.sveltepopover (≥ 44 px tap target, popover on desktop/ bottom-sheet on mobile) with three fieldsets — Objects, Planets, View.
hide-by-id contract, the popover lifecycle, persistence + reset, the
fog-paint-ops contract, the categories + cascade map, plus a Playwright e2e
across the four projects.
ui/docs/renderer.md,ui/docs/storage.md,ui/docs/game-state.md,docs/FUNCTIONAL.md(§6.7) + RU mirror,ui/PLAN.mddecisions block.pkg/calc/race.gotypoFligth → Flightand the one Gocaller.
Test plan
cd ui/frontend && pnpm test(707 / 707 green)pnpm exec playwright testonchromium-desktop,webkit-desktop,chromium-mobile-iphone-13,chromium-mobile-pixel-5(all green ongitea ui-test run #220)
dev-deploy:- Zero-turn map: visibility fog ON shows planets inside the unfogged
circles, fog OFF shows the regular dark canvas.
- Legacy report with maxed-out drive tech: visibility fog covers the
whole map (correct — visibility radius exceeds map size), planets
stay visible on top.
- Torus seam: visibility circles wrap continuously across the world
edge, no "sector" artifact.
- Wrap-mode flip: camera centre preserved, no Pixi remount.
The previous logic re-mounted the renderer whenever `store.wrapMode` flipped, because the `sameSnapshot` gate included `handle.getMode() === mode`. Pixi 8 does not reliably re-initialise an `Application` on the same canvas — the symptom showed up as the chromium tab silently closing during the Phase 29 wrap-mode e2e ("Target page, context or browser has been closed"). The renderer already exposes an in-place `setMode` that swaps the wrap-clamp / torus-copy visibility synchronously while preserving the camera; the playground-map.spec.ts wrap toggle has been driving it for several phases without issue. Drop mode from the snapshot gate and route the change through `handle.setMode(mode)` instead. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Two visible regressions in the in-game map's fog overlay surfaced on dev-deploy: 1. With three LOCAL planets close together, only the last planet glyph stayed visible inside the bg holes — the other two were obscured. The previous implementation stacked the fog rectangle plus every bg circle onto a single `Graphics` via repeated `g.rect(...).fill(...).circle(...).fill(...)...`. Pixi v8's multi-shape Graphics is supported in theory, but in practice only the last shape's fill seems to land, dropping the earlier bg holes (and the planet glyphs on top look like they vanished along with their hole). Splitting each op onto its own `Graphics` inside a per-copy `Container` removes the ambiguity — one shape, one fill, one render pass. 2. A planet near the right world edge produced a "sector" — the bg circle painted into the area past the seam, but the neighbouring tile's fog rectangle then overpainted that bleed, leaving a quarter-circle hole. In torus mode each visibility circle is now drawn at the nine wrapped positions (`(dx, dy) ∈ {-1, 0, 1}²`); the wrapped copies in the neighbour-tile-aligned positions keep the hole continuous across the seam. No-wrap mode keeps a single emission per circle, because wrapped circles would leak into the visible world rectangle as unwanted holes. The `fogPaintOps` helper now takes the wrap mode as a parameter; `tests/fog-paint-ops.test.ts` covers the torus expansion (nine-wrap product per circle, the seam-fix case at x = 950) and re-asserts the no-wrap path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Two regressions surfaced once visible-hyperspace toggled on a real dev-deploy map: 1. On the zero-turn map the bg holes painted ON TOP of the planet glyphs — every LOCAL planet looked like a hollow circle of background colour instead of the planet pixel inside an unfogged area. 2. On a legacy report with a drive tech that pushes the visibility radius well past the world dimensions the bg circles overlapped to cover the entire viewport. Combined with the wrong z-order the result was a uniformly black canvas with every primitive hidden. The per-copy implementation added the fog container via `copy.addChildAt(container, 0)` and trusted Pixi v8 to insert the container at the start of the copy's children. Whether by a Pixi quirk or by some interaction with how `populatePrimitives` orders its `c.addChild(g)` calls, the fog ended up rendering after every primitive in practice — the symptoms above are a perfect match for that ordering. Restructured the fog rendering so the z-order is structural rather than relying on `addChildAt`: - A single `fogLayer: Container` is added to the viewport BEFORE the nine torus copies. Pixi renders viewport children in order, so the layer is guaranteed to paint first; every copy renders on top. - `fogPaintOps` now emits world-space coordinates with wrap offsets baked in (9 fog rects + 9 bg circles per visibility entry in torus mode, 1 + N in no-wrap mode). The renderer populates `fogLayer` with one `Graphics` per op — no per-copy iteration on the fog side. - The previous `fogGraphics: Container[]` closure state is gone. Each `setVisibilityFog` flip drops every child of `fogLayer` and rebuilds it. The dispose path drops the children eagerly before `app.destroy({children: true})` walks the tree. The fog-paint-ops test exercises the new contract: the no-wrap path keeps one rect + N circles, the torus path expands to nine rects + nine wrapped circles per entry (including the seam-fix case at x = 950). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>