feat(scoreboard): scroll speed is a property (20-400 px/s, persisted)

The marquee now has the dial it needs. `ScoreboardPresenter.PixelsPerSecond` is the single owner of
the range (20-400, default 120), the layer's properties expose it with a live px/s readout, and the
value is persisted as Scoreboard.ScrollSpeed because it is a READABILITY choice — re-dialling it
every launch would be a tax on the creator who needs the strip to be readable.

Advance() still takes an optional override so tests can drive exact distances.

Guard: the presenter test proves speed is real (same elapsed time, twice the speed, different
window) — not a value that is stored and ignored — and the panel test pins the control, its range
and the persistence key.
This commit is contained in:
2026-10-30 15:19:28 -07:00
parent 460b36204d
commit 28525c90aa
7 changed files with 61 additions and 3 deletions
+10
View File
@@ -48,6 +48,16 @@ public class ScoreboardPresenterTests
Assert.NotNull(ticked);
Assert.NotEqual(first.BgraPixels, ticked!.BgraPixels);
// SPEED is a real dial: the same elapsed time at twice the speed moves twice as far,
// so the window lands somewhere else.
var slow = new ScoreboardPresenter(recorder, new ScoreboardStyle()) { PixelsPerSecond = 60 };
var fast = new ScoreboardPresenter(recorder, new ScoreboardStyle()) { PixelsPerSecond = 120 };
slow.SetTiles(tiles);
fast.SetTiles(tiles);
slow.Advance(1.0);
fast.Advance(1.0);
Assert.NotEqual(slow.Frame!.BgraPixels, fast.Frame!.BgraPixels);
// A visible change re-rasterises the run.
recorder.Record(Member("Second"));
var second = presenter.Frame;