Mesh Studio: Raylib Preview + Git Graph UX
Policies that keep the org coherent
name: Mesh Studio Raylib Git overview: Fix black Raylib Preview by starting the embedded host when entering Preview mode, and upgrade the History panel to a readable git-style graph with branch-colored lanes and a prominent HEAD "you are here" dot. todos:
- id: raylib-host-lifecycle
content: Call SetHostActive in ViewportModeCoordinator + auto-start on RaylibHostControl attach; publish Novolis.Avalonia.Raylib status: completed
- id: git-graph-model
content: Extend GitGraphTimelineRow + GitGraphPalette (branch/kind colors, HEAD marker) status: completed
- id: git-graph-ui
content: Redesign row template with colored dot, branch lanes, fix GitHistoryPanel layout + node fallback status: completed
- id: verify-mesh-studio
content: Manual test Preview/Quality toggle + Save/Branch graph; build MeshBench status: completed isProject: false
Diagnosis
Raylib Preview is black (Quality works)
Path trace uses `ViewportSurface` and works. Preview uses `RaylibHostControl` via `ViewportModeCoordinator`.
sequenceDiagram
participant MW as MainWindow
participant Coord as ViewportModeCoordinator
participant Ray as RaylibHostControl
MW->>Coord: EnterFast / StartInFastMode
Coord->>Ray: AttachRaylibHost (re-add to Grid)
Note over Ray: OnAttached starts present timer only
Note over Ray: StartHost never called
Ray-->>MW: Black viewport (_session is null)`RaylibHostControl.OnAttachedToVisualTree` only starts the present timer; the render loop starts in StartHost(), which is only reached via `SetHostActive(true)`. The coordinator never calls that API (grep shows zero usage in MeshBench).
After Quality mode, DetachRaylibHost triggers OnDetachedFromVisualTree → SetHostActive(false) → host stopped. Returning to Preview re-attaches the control but does not restart the host.
Git graph panel looks empty / unusable
Current stack: `GitHistoryPanel` → `GitGraphTimelineBuilder` → `GitGraphTimelineList`.
Gaps vs your request:
| Request | Current state |
|---|---|
| Visible git graph | Empty until first **Save** (timeline nodes only created in `SavePointAsync`); overlapping Grid can hide empty hint behind ScrollViewer |
| Branch color-coding | Single blue graph color; branch name only in refs column |
| Clear "you are here" dot | `HEAD` text in refs column; graph uses `*` for all commits |
| Save-point type colors | `Presentation.Kind` (`manual`, `safety`, etc. from [`SnapshotKinds`](d:\novolis\novolis-workspaces\src\Novolis.Snapshots.Abstractions\SnapshotKinds.cs)) not used in UI |
Part 1 — Fix Raylib Preview
1.1 Wire host lifecycle in coordinator
In `ViewportModeCoordinator.cs`:
- `EnterFast` / `StartInFastMode`: after
AttachRaylibHost(), call_raylibHost.SetHostActive(true). - `EnterQuality`: call
_raylibHost.SetHostActive(false)beforeDetachRaylibHost()(belt-and-suspenders withOnDetached). - `EnsureViewportSized` path (via `MainWindow`): keep setting
FrameWidth/FrameHeightfrom_viewportHost.Boundsso restarts pick up size (already done).
1.2 Safety net in `RaylibHostControl` (novolis-avalonia)
OnAttachedToVisualTree: callSetHostActive(true)when attached (so first launch works even if coordinator forgets).- Keep
OnDetachedFromVisualTree→SetHostActive(false)(GLFW single-host rule from `RaylibGlfwProcessSync`).
1.3 GPR package
MeshBench consumes Novolis.Avalonia.Raylib via GPR (`MeshBench.csproj`). After avalonia changes, publish Novolis.Avalonia.Raylib so SetHostActive is available to dogfooding (per nuget-only policy).
1.4 Verify
- Open app → Preview shows meshes immediately (Raylib grid + objects).
- Switch Quality → path trace (already works).
- Switch back Preview → Raylib returns (not black).
Part 2 — Git graph with branch colors + HEAD dot
2.1 Enrich row model
Extend `GitGraphTimelineRow`:
BranchName(string)SnapshotKind(fromnode.Presentation.Kind)BranchColor/KindColor(AvaloniaColoror ARGB int)IsHere(maps tonode.IsHead— workspace HEAD / "you are here")Marker(●for HEAD,○for normal,◉optional for branch-point)
Add small palettes in new GitGraphPalette.cs:
- Branches: stable hash of
BranchName→ 6–8 distinct hues (mainalways one fixed color). - Snapshot kinds:
manual= green tint,safety= amber,autosave= gray,quick= cyan, etc. (fromSnapshotKindsconstants).
2.2 Improve graph builder
In GitGraphTimelineBuilder:
- Pass
BranchName,Kind,IsHeadinto each row. - Colorize graph prefix characters (
│,├,└) conceptually via row metadata (UI applies brush). - Fallback: if
TimelineTreeView.Rootsis empty butGetNodesAsync()has nodes, build a simple lineargit log --onelinelist (newest first) so saves always appear even if tree projection edge case fails.
2.3 Row template redesign
In `GitGraphTimelineList.cs` (or new GitGraphRowControl.cs):
[ colored ● ] │─┬─* Subject label branch refs
12px dot graph (kind badge optional)- HEAD / you are here: large filled dot (10–12px), white ring or glow,
ToolTip: "You are here (HEAD)". - Other commits: smaller dot filled with branch color.
- Graph column: monospace lanes tinted with branch color (lower opacity).
- Subject: white; optional small pill for snapshot kind (e.g.
manual) using kind color. - Refs column: branch name only (drop redundant
HEADtext when dot conveys it).
2.4 Fix History panel layout
- Replace overlapping
GridwithDockPanel: header area N/A (header stays inMainWindow),ScrollViewerfills center, empty hint only whenrows.Count == 0(no overlapping black ListBox). - Ensure
MinHeightand visible border so panel never looks like a void.
2.5 Session refresh
In `MeshBenchSession.RefreshTimelineAsync`: pass head into builder so IsHead is accurate after save/restore/branch.
After Save in MainWindow.OnSavePoint, RefreshUi() already runs — graph should populate immediately.
2.6 Optional polish
- Auto-select HEAD row on refresh.
- Legend line under "History (git graph)": colored swatches for
main+ active branches (only if ≥2 branches).
Files to touch
| File | Change |
|---|---|
| [`ViewportModeCoordinator.cs`](d:\novolis\novolis-dogfooding\apps\rendering\MeshBench\Services\ViewportModeCoordinator.cs) | `SetHostActive(true/false)` on mode switch |
| [`RaylibHostControl.cs`](d:\novolis\novolis-avalonia\src\Novolis.Avalonia.Raylib\RaylibHostControl.cs) | Auto-start on attach |
| [`GitGraphTimelineBuilder.cs`](d:\novolis\novolis-dogfooding\apps\rendering\MeshBench\Services\GitGraphTimelineBuilder.cs) | Colors, markers, fallback list |
| New `GitGraphPalette.cs` | Branch/kind color maps |
| [`GitGraphTimelineList.cs`](d:\novolis\novolis-dogfooding\apps\rendering\MeshBench\Ui\GitGraphTimelineList.cs) | Dot + colored row template |
| [`GitHistoryPanel.cs`](d:\novolis\novolis-dogfooding\apps\rendering\MeshBench\Ui\GitHistoryPanel.cs) | Dock layout, empty state |
| [`MainWindow.cs`](d:\novolis\novolis-dogfooding\apps\rendering\MeshBench\MainWindow.cs) | Select HEAD after refresh (minor) |
| GPR publish | `Novolis.Avalonia.Raylib` after avalonia fix |
Verification
- Preview: meshes visible on open; survives Preview ↔ Quality toggles.
- Ctrl+S: History shows ≥1 row with colored branch dot; HEAD row has prominent ●.
- Branch: create branch, save — second branch color differs from
main. dotnet buildMeshBench;verify-nuget-only.ps1after GPR publish.