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:
@@ -19,6 +19,17 @@ public enum BorderAnimation
|
||||
Sparkles
|
||||
}
|
||||
|
||||
/// <summary>Whether an element's pixel content is fixed (bake once into the
|
||||
/// compositor's cached base) or changes every frame (composite each tick).
|
||||
/// See ai.md "SceneGraph component + baked-crust compositor" (TASK 31).</summary>
|
||||
public enum ElementKind
|
||||
{
|
||||
/// <summary>Pixels never change at runtime (images, background art).</summary>
|
||||
Static,
|
||||
/// <summary>Pixels change every frame (webcam, live capture, chat, web source).</summary>
|
||||
Dynamic
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A thing rendered in a scene: a multi-instance Source (image/background/text)
|
||||
/// or a singleton resource's per-scene config (webcam). Carries the shared
|
||||
@@ -44,6 +55,11 @@ public abstract class SceneElement : INotifyPropertyChanged
|
||||
private string _name = string.Empty;
|
||||
public string Name { get => _name; set => Set(ref _name, value); }
|
||||
|
||||
/// <summary>Whether this element's pixels are fixed (Static) or change every
|
||||
/// frame (Dynamic). The compositor bakes all Static layers below the first
|
||||
/// Dynamic layer once (see <c>SceneGraph.GetSplitPoint</c>).</summary>
|
||||
public virtual ElementKind Kind => ElementKind.Static;
|
||||
|
||||
/// <summary>True only for singleton resources (webcam). Gates webcam-only UI.</summary>
|
||||
public virtual bool IsWebcam => false;
|
||||
|
||||
|
||||
@@ -63,6 +63,11 @@ public class Source : SceneElement
|
||||
|
||||
public override bool IsDraggable => Type is SourceType.Image or SourceType.WebSource or SourceType.ChatBox;
|
||||
|
||||
/// <summary>Live captures, chat, web sources and media are dynamic; static art is fixed.</summary>
|
||||
public override ElementKind Kind => Type is SourceType.DisplayCapture or SourceType.WindowCapture
|
||||
or SourceType.ChatBox or SourceType.WebSource or SourceType.MediaSource
|
||||
? ElementKind.Dynamic : ElementKind.Static;
|
||||
|
||||
public override bool IsWebSource => Type == SourceType.WebSource;
|
||||
|
||||
/// <summary>The permanent scene background (live desktop/game capture). Never removable/reorderable.</summary>
|
||||
|
||||
@@ -13,5 +13,6 @@ public class WebcamSceneConfig : SceneElement
|
||||
public string WebcamId { get; init; } = string.Empty;
|
||||
public override bool IsWebcam => true;
|
||||
public override bool IsDraggable => true;
|
||||
public override ElementKind Kind => ElementKind.Dynamic;
|
||||
public override ImageSource? DisplaySource => VideoImageSource;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user