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:
@@ -17,7 +17,7 @@ import type {
|
||||
ReportPlanet,
|
||||
ReportUnidentifiedShipGroup,
|
||||
} from "../src/api/game-state";
|
||||
import { BATTLE_MARKER_ID_PREFIX, BOMBING_MARKER_ID_PREFIX } from "../src/map/battle-markers";
|
||||
import { BATTLE_MARKER_ID_PREFIX } from "../src/map/battle-markers";
|
||||
import { SHIP_GROUP_ID_OFFSETS } from "../src/map/ship-groups";
|
||||
import { reportToWorld } from "../src/map/state-binding";
|
||||
import { EMPTY_SHIP_GROUPS } from "./helpers/empty-ship-groups";
|
||||
@@ -200,7 +200,7 @@ describe("reportToWorld — categories", () => {
|
||||
expect(categories.get(unidentifiedId)).toBe("unidentifiedGroup");
|
||||
});
|
||||
|
||||
test("battle markers and bombing markers each carry their own category", () => {
|
||||
test("battle markers carry the battleMarker category", () => {
|
||||
const { categories } = reportToWorld(
|
||||
makeReport({
|
||||
planets: [
|
||||
@@ -208,6 +208,9 @@ describe("reportToWorld — categories", () => {
|
||||
makePlanet({ number: 2, kind: "other", x: 200, y: 200 }),
|
||||
],
|
||||
battles: [makeBattle({ id: "b1", planet: 2 })],
|
||||
// F8-12 / #30: bombings no longer emit their own
|
||||
// primitives — the planet outline is drawn by
|
||||
// `setPlanetOutlines` from the map view.
|
||||
bombings: [makeBombing({ planetNumber: 2 })],
|
||||
}),
|
||||
);
|
||||
@@ -216,8 +219,6 @@ describe("reportToWorld — categories", () => {
|
||||
const battleB = BATTLE_MARKER_ID_PREFIX | (0 << 4) | 1;
|
||||
expect(categories.get(battleA)).toBe("battleMarker");
|
||||
expect(categories.get(battleB)).toBe("battleMarker");
|
||||
const bombingId = BOMBING_MARKER_ID_PREFIX | 0;
|
||||
expect(categories.get(bombingId)).toBe("bombingMarker");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -235,7 +236,7 @@ describe("reportToWorld — planetDependents", () => {
|
||||
expect(planetDependents.get(7)?.has(7)).toBe(true);
|
||||
});
|
||||
|
||||
test("battle / bombing markers cascade onto their anchor planet", () => {
|
||||
test("battle markers cascade onto their anchor planet", () => {
|
||||
const { planetDependents } = reportToWorld(
|
||||
makeReport({
|
||||
planets: [
|
||||
@@ -243,17 +244,18 @@ describe("reportToWorld — planetDependents", () => {
|
||||
makePlanet({ number: 2, kind: "other", x: 200, y: 200 }),
|
||||
],
|
||||
battles: [makeBattle({ planet: 2 })],
|
||||
// Bombings are still in the report but no primitive
|
||||
// rides the cascade now — they paint a planet outline
|
||||
// straight from `map.svelte`.
|
||||
bombings: [makeBombing({ planetNumber: 2 })],
|
||||
}),
|
||||
);
|
||||
const battleA = BATTLE_MARKER_ID_PREFIX | (0 << 4) | 0;
|
||||
const battleB = BATTLE_MARKER_ID_PREFIX | (0 << 4) | 1;
|
||||
const bombingId = BOMBING_MARKER_ID_PREFIX | 0;
|
||||
const deps = planetDependents.get(2) ?? new Set();
|
||||
expect(deps.has(2)).toBe(true);
|
||||
expect(deps.has(battleA)).toBe(true);
|
||||
expect(deps.has(battleB)).toBe(true);
|
||||
expect(deps.has(bombingId)).toBe(true);
|
||||
});
|
||||
|
||||
test("in-space groups cascade onto their destination planet", () => {
|
||||
|
||||
Reference in New Issue
Block a user