feat(ui): F8-12 — map polish (zoom invariance, labels, selection, soft radius) (#55)
* Honest pixel-space sizing for `pointRadiusPx` / `strokeWidthPx`: the renderer divides by the current camera scale on every `viewport.zoomed` so thin lines / small markers stay the same on-screen size at any zoom. * Known-size planets switch to `pointRadiusWorld`, softened against the reference scale by `PLANET_SIZE_ZOOM_ALPHA = 0.33`; unidentified planets pin to a 3-px disc. * New planet label layer renders a two-line `name / #N` legend under each planet (`#N` only for unidentified or when the new `planetNames` toggle is off). Selection now paints an inverse-fill frame around the selected planet's label plus an outline on the disc; the old selection-ring primitive is retired. * Bombing markers swap the separate CirclePrim for a planet-outline overlay (damaged / wiped colour); the report deep-link moves to a "view bombing report" link in the planet inspector. * Docs + tests follow: `renderer.md` reflects the new sizing contract + label / outline layers, vitest covers the sizing math, label formatting, and the new toggle, and the map-toggles e2e adds a persistence case for `planetNames`. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -82,10 +82,10 @@ describe("isCategoryVisible", () => {
|
||||
expect(isCategoryVisible("planet-unidentified", t)).toBe(false);
|
||||
});
|
||||
|
||||
test("battle and bombing markers have independent toggles", () => {
|
||||
const t = toggles({ battleMarkers: false, bombingMarkers: true });
|
||||
test("battleMarker toggle hides battle X-crosses without touching other layers", () => {
|
||||
const t = toggles({ battleMarkers: false });
|
||||
expect(isCategoryVisible("battleMarker", t)).toBe(false);
|
||||
expect(isCategoryVisible("bombingMarker", t)).toBe(true);
|
||||
expect(isCategoryVisible("planet-foreign", t)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -202,6 +202,9 @@ describe("computeHiddenPlanetNumbers", () => {
|
||||
});
|
||||
|
||||
describe("computeHiddenIds", () => {
|
||||
// F8-12 / #30: bombings no longer ride the cascade as their own
|
||||
// primitive — they paint a planet outline directly. The fixture
|
||||
// here mirrors what `reportToWorld` currently emits.
|
||||
const categories: Map<PrimitiveID, MapCategory> = new Map<
|
||||
PrimitiveID,
|
||||
MapCategory
|
||||
@@ -212,11 +215,10 @@ describe("computeHiddenIds", () => {
|
||||
[150, "hyperspaceGroup"],
|
||||
[200, "incomingGroup"],
|
||||
[300, "battleMarker"],
|
||||
[400, "bombingMarker"],
|
||||
]);
|
||||
const planetDependents = new Map<number, ReadonlySet<PrimitiveID>>([
|
||||
[1, new Set([1])],
|
||||
[2, new Set([2, 100, 150, 200, 300, 400])],
|
||||
[2, new Set([2, 100, 150, 200, 300])],
|
||||
]);
|
||||
|
||||
test("category-toggle off hides every primitive in that category", () => {
|
||||
@@ -239,10 +241,10 @@ describe("computeHiddenIds", () => {
|
||||
new Set([2]),
|
||||
toggles(),
|
||||
);
|
||||
expect(hidden).toEqual(new Set([2, 100, 150, 200, 300, 400]));
|
||||
expect(hidden).toEqual(new Set([2, 100, 150, 200, 300]));
|
||||
});
|
||||
|
||||
test("battle / bombing markers have independent toggles", () => {
|
||||
test("battle markers honour the battleMarkers toggle independently", () => {
|
||||
const hidden = computeHiddenIds(
|
||||
categories,
|
||||
planetDependents,
|
||||
@@ -250,7 +252,7 @@ describe("computeHiddenIds", () => {
|
||||
toggles({ battleMarkers: false }),
|
||||
);
|
||||
expect(hidden.has(300)).toBe(true);
|
||||
expect(hidden.has(400)).toBe(false);
|
||||
expect(hidden.has(150)).toBe(false);
|
||||
});
|
||||
|
||||
test("planet cascade and category toggle compose without duplicates", () => {
|
||||
@@ -262,7 +264,7 @@ describe("computeHiddenIds", () => {
|
||||
);
|
||||
// 300 is already present from the cascade; the category toggle
|
||||
// re-adds it but Set semantics dedupe.
|
||||
expect(hidden).toEqual(new Set([2, 100, 150, 200, 300, 400]));
|
||||
expect(hidden).toEqual(new Set([2, 100, 150, 200, 300]));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user