TASK 31: SceneGraph component + baked-crust compositor optimization
- Add ElementKind (Static/Dynamic) to SceneElement base; Source/WebcamSceneConfig classify - Services/SceneGraph.cs: owns the Scenes collection (ViewModel's Scenes delegates to it), the element mutation surface (Add/Insert/Remove/Move, each invalidating the bake), and the queries that were scattered LINQ (GetBackground/GetWebcam/GetChatBoxes/GetSplitPoint/IsStatic) - SceneCompositor: split-aware BakeStaticBase + CompositeLayers + Render(.., staticBase, split); builds/caches the static base below the split point in source-rect space - FramePump: optional SceneGraph -> optimized bake+composite path; falls back to full render - MainViewModel: routes element mutations through the graph; invalidates the bake on static layout/opacity/visibility/useDefaultBackground changes and after background heal/Ensure - Integration test SceneGraphTests.BakedStaticBase_WithDynamicLayer_CompositesCorrectly Derivative survey (mandated): tried before writing — OBS does per-source opacity/visibility caching and static-scene baking; this mirrors OBS's 'cached static source' optimization. 3 documented defensive deviations from the spec (ChatOverlayLayer stays decoupled; background helpers stay VM-static for direct testability; full facade peel deferred post-1.0) in TASKS.md + ai.md. Scope check passed; clean build 0 warnings.
This commit is contained in:
@@ -1227,7 +1227,40 @@ and a full layout restructure moving all live controls into the preview pane.
|
||||
`SceneGraph` component. Classify elements as static or dynamic. Enable the compositor to bake
|
||||
static layers once and only recompose dynamic layers per frame.
|
||||
|
||||
### Status: ☐ Not started
|
||||
### Status: ✅ Done (2026-08-31)
|
||||
|
||||
What landed — core optimization + SceneGraph component, all in one commit:
|
||||
|
||||
- `ElementKind` (Static/Dynamic) on `SceneElement` base, overridden in `Source` and `WebcamSceneConfig`
|
||||
- `Services/SceneGraph.cs`: owns `Scenes` collection (ViewModel's `Scenes` property delegates to it);
|
||||
mutation surface `AddElement`/`InsertElement`/`RemoveElement`/`MoveElement` (each invalidates the bake);
|
||||
queries `GetBackground`/`GetWebcam`/`GetChatBoxes`/`GetSplitPoint`/`IsStatic`; and the
|
||||
`GetBakedBase` bake-cache (keyed by scene id + static element identities below the split)
|
||||
- `SceneCompositor.BakeStaticBase`/`CompositeLayers` + `Render(.., staticBase, split)` overload —
|
||||
split-aware, builds the cached base in source-rect space, composites dynamic/above-split per frame
|
||||
- `FramePump` takes an optional `SceneGraph` and uses the optimized path when wired (falls back to full render)
|
||||
- `MainViewModel`: routes element mutations through the graph; invalidates the bake on static
|
||||
layout/opacity/visibility/useDefaultBackground changes and after background heal / EnsureBackground
|
||||
- Integration test `SceneGraphTests.BakedStaticBase_WithDynamicLayer_CompositesCorrectly` (audio-free,
|
||||
verifies bake-once + cache hit + dynamic-on-top pixels + static-mutation invalidation +
|
||||
dynamic-only non-invalidation)
|
||||
|
||||
**Defensive deviations from this spec (decision 2026-08-31):**
|
||||
1. `ChatOverlayLayer` keeps taking `IEnumerable<Scene>` rather than `SceneGraph.GetChatBoxes()` — it is
|
||||
deliberately decoupled from the graph (`// without owning the scene graph`). Forcing the graph in would
|
||||
couple a WPF-bound layer to it and violate that documented seam.
|
||||
2. Background static helpers (`EnsureBackground`/`CreateBackground`/`NormalizeBackgrounds`) stay on the
|
||||
ViewModel because `BackgroundTests.cs` unit-tests `MainViewModel.EnsureBackground` directly. Queries
|
||||
moved to SceneGraph; helpers + their invalidation wiring stayed on the VM.
|
||||
3. The full ViewModel-as-facade extraction (moving the ~all-binding-surface off Scenes/StagedScene/
|
||||
LiveScene) was deliberately NOT done in this unsupervised pass — it is the "touch 11 files across 4
|
||||
layers" regression risk the handoff flagged. SceneGraph owns the collection + mutation surface now;
|
||||
the remaining VM call sites binding to those still work because `Scenes` delegates. Revisit after 1.0.
|
||||
|
||||
**Verification:** SceneCompositorTests 4, StretchMathTests 4, BackgroundTests 16, SceneCatalogTests 18,
|
||||
LayoutStorePersistenceTests 12, FramePumpTests 9, SceneGraphTests 1 all green. RealAppHost GUI/collection
|
||||
tests (SourceNaming, RoundClip, BackgroundHeal, ...) construct a real `MainWindow` and cannot run in a
|
||||
headless WSL session (pre-existing limitation, not caused by this change).
|
||||
|
||||
### Design
|
||||
|
||||
|
||||
Reference in New Issue
Block a user