Phase 7: cockpit overlay generator, region extraction, and profile editor
Overlay generator (pure, tested) — RioJoy.Core/Overlay:
- FontFitter ports the legacy calc-fontsize auto-fit search (validated against a
brute-force oracle); OverlayLayoutEngine ports create-data-layer's fit + h/v
justification and adds per-region 90 deg CCW rotation; OverlayTemplate/Region +
OverlayTemplateStore hold cell geometry/colour/rotation (regions.json).
- GoobieDataImporter parses the legacy .data label sheet into label rows.
- src/RioJoy.Overlay: SkiaSharp rasterizer (SkiaTextMeasurer shared with the engine
so measured layout == drawn output; SkiaOverlayRenderer -> PNG;
ProfileWallpaperGenerator). Verified end-to-end on the real cockpit art
(regions.json + riojoy.png + TEST.data) by OverlayRenderIntegrationTests.
- RioJoy.Tray/WallpaperApplier applies via SystemParametersInfo; RioCoordinator
generates+applies on profile activation (opt-in via AppConfig.OverlayTemplatePath).
Region geometry — tools/XcfRegionExtract parses riojoy.xcf (a GIMP-format binary
reader, no GIMP needed) into the 119-cell regions.json: per-layer offsets/size/
font/colour, with 90 deg CCW rotation on a-00 + b-10..b-1F. Base image riojoy.png.
NOTE: the wallpaper positions are a VGA chroma-split display artifact (6 displays),
not the cockpit's logical layout.
Mapping editor (first cut) — RioJoy.Tray/Editor/ProfileEditorForm renders the
config sheet's logical grid (SheetLayout parses the sheet CSV export). The iRIO
word is edited via ButtonBinding <-> RioMapEntry.Create (no hex bit-twiddling), with
a context-sensitive picker: keyboard keys by name (KeyCatalog VK names), joystick
Button N, hat direction, mouse/RIO-command enum names; modifiers only for keyboard.
Opened from the tray ("Edit profile..."). The sheet-grid layout is a starting point
that needs rework from a better-formatted source.
~220 xUnit tests green. Docs (PLAN.md, README) updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+47
-13
@@ -100,7 +100,7 @@ tray menu is always available.
|
||||
## Phases
|
||||
|
||||
### Phase 0 — Repo & scaffold ✅ (this commit)
|
||||
- `git init`, remote `https://gitea.mysticmachines.com/VWE/riovjoy2.git`.
|
||||
- `git init`, remote `https://gitea.mysticmachines.com/VWE/RIOJoy.git`.
|
||||
- Legacy C++ moved to `legacy/`; cockpit art to `docs/reference/`.
|
||||
- Solution `RioJoy.sln` with `src/RioJoy.Core` (lib) + `src/RioJoy.Tray`
|
||||
(tray app); `driver/` placeholder for the WDK project.
|
||||
@@ -183,7 +183,7 @@ Implemented in `src/RioJoy.Core/Calibration` + `Plasma` (105 xUnit tests total):
|
||||
|
||||
### Phase 5 — Tray app + profiles — code-complete ✅
|
||||
Core logic in `src/RioJoy.Core/Profiles` + `RioRuntime`; UI/OS in `src/RioJoy.Tray`
|
||||
(123 xUnit tests total):
|
||||
(136 xUnit tests total across the suite):
|
||||
- `RioProfile` + `AppConfig` model; `ConfigStore` JSON persistence (round-trip
|
||||
tested); `RioIniImporter` ports the legacy `RIO.ini` (buttons/inverts/greeting).
|
||||
- `AutoSwitchResolver` + `AutoSwitchWatcher`: the three-state decision
|
||||
@@ -205,20 +205,54 @@ Core logic in `src/RioJoy.Core/Profiles` + `RioRuntime`; UI/OS in `src/RioJoy.Tr
|
||||
acquire/release lifecycle against real RIO hardware.
|
||||
|
||||
### Phase 6 — Packaging / signing / deploy
|
||||
- Driver install via `pnputil`; app installer; test-signing script.
|
||||
- Cabinet deployment doc. (Production option: attestation signing.)
|
||||
- Driver test-signing + `pnputil` install already scripted (`driver/sign.ps1`,
|
||||
`driver/install.ps1`, `driver/uninstall.ps1`, [`driver/README.md`](../driver/README.md));
|
||||
proven on the cabinet. ⏳ Still to do: app installer, a single bundled deploy,
|
||||
and a cabinet deployment doc. (Production option: attestation signing.)
|
||||
|
||||
### Phase 7 — Profile/mapping editor + cockpit overlay generator
|
||||
### Phase 7 — Profile/mapping editor + cockpit overlay generator — in progress
|
||||
Replaces the legacy Google-Sheet → `.data` → GIMP → Script-Fu pipeline
|
||||
(see [`docs/reference/customBackground/`](reference/customBackground/)).
|
||||
- **Mapping editor:** per-button UI to set action + label + lamp, no hex
|
||||
bit-twiddling; clone-from-existing profile.
|
||||
- **Overlay generator:** render labels into named regions over a base cockpit
|
||||
image using **SkiaSharp**, porting the auto-fit/justification logic from
|
||||
`sg-goobie-MFD.scm`; export the per-profile wallpaper and re-apply via
|
||||
`SystemParametersInfo`.
|
||||
- **Region authoring:** extract the label rectangles from `riojoy.xcf` into a
|
||||
`regions.json`; in-app box editor for future tweaks.
|
||||
- **Overlay generator — done ✅, verified on real assets.** `RioJoy.Core/Overlay`
|
||||
is the pure, unit-tested layout engine: `FontFitter` is a faithful port of the
|
||||
`calc-fontsize` auto-fit search (validated against a brute-force oracle),
|
||||
`OverlayLayoutEngine` ports `create-data-layer`'s fit + horizontal/vertical
|
||||
justification, and `OverlayTemplate`/`OverlayRegion` (a `regions.json` via
|
||||
`OverlayTemplateStore`) hold the cell geometry/color. Label text is per-profile
|
||||
(`RioProfile.OverlayLabels`); `GoobieDataImporter` reads the legacy `.data`
|
||||
sheet into label rows. The rasterizer lives in `src/RioJoy.Overlay`
|
||||
(**SkiaSharp**): `SkiaTextMeasurer` (shared with the engine so measured layout
|
||||
== drawn output) + `SkiaOverlayRenderer` (draw labels → PNG). The full chain is
|
||||
exercised end-to-end on the real cockpit art (`regions.json` + `riojoy.png` +
|
||||
`TEST.data`) by `OverlayRenderIntegrationTests`. `RioJoy.Tray/WallpaperApplier`
|
||||
applies the result via `SystemParametersInfo`.
|
||||
- **Region authoring — extraction done ✅.** `tools/XcfRegionExtract` parses the
|
||||
GIMP source (`riojoy.xcf`) and writes the 119-cell
|
||||
`docs/reference/customBackground/regions.json` (per-layer offsets/size/font/color,
|
||||
`BaseImagePath` → exported `riojoy.png`), anchored by `CockpitRegionsTests`.
|
||||
⏳ Still to do: an in-app box editor for tweaks.
|
||||
- **Runtime wiring — done ✅ (opt-in).** `RioJoy.Overlay/ProfileWallpaperGenerator`
|
||||
renders a profile's labels onto the template base image; `RioCoordinator`
|
||||
generates + applies the wallpaper on profile activation when
|
||||
`AppConfig.OverlayTemplatePath` is set (best-effort, off by default, never breaks
|
||||
activation). The live `SystemParametersInfo` apply changes a user setting, so it
|
||||
is gated behind config and not exercised by tests. ⏳ Optional: restore the prior
|
||||
wallpaper when going dormant.
|
||||
- **Mapping editor — first cut done ✅.** `RioJoy.Tray/Editor/ProfileEditorForm`
|
||||
shows the cockpit as a scrollable, clickable grid that mirrors the legacy
|
||||
authoring spreadsheet's **logical** layout — parsed from the sheet's CSV export
|
||||
(`docs/reference/customBackground/config-sheet.csv`) by `SheetLayout`, coloured
|
||||
by section. (The layout deliberately follows the sheet, **not** the wallpaper
|
||||
region positions: the wallpaper drives 6 displays via VGA chroma-channel
|
||||
splitting, so its label positions stack and don't reflect the physical cockpit.)
|
||||
Clicking an address cell edits its label and action/modifiers/lamp; the `iRIO`
|
||||
word is read/written through `ButtonBinding` ↔ `RioMapEntry.Create` (round-trip
|
||||
tested) — no hex bit-twiddling. The value field is a **context-sensitive picker**:
|
||||
keyboard actions pick a key by name (`KeyCatalog` VK names), joystick a Button N,
|
||||
hat a direction, mouse/RIO-command the enum name; modifiers enable only for
|
||||
keyboard. Opened from the tray ("Edit profile…"); Save persists the profile.
|
||||
⏳ Still to refine: grouping a button's two bank addresses (edit once → both),
|
||||
and clone-from-existing.
|
||||
- The unified profile JSON supersedes both `RIO.ini` and the Google Sheet, with
|
||||
importers for each.
|
||||
- To confirm at Phase 7: target wallpaper resolution(s); static wallpaper vs.
|
||||
|
||||
Reference in New Issue
Block a user