Control Surface UX: pill toggle, background rename, per-scene properties

- Sliding pill toggle (green ON / red OFF) replaces checkbox
- Geometry mismatch error for custom backgrounds
- Backdrop -> Background: C# rename, SQL column rename with migration
- Source.IsBackground: new -> override (fixes WPF binding)
- Legacy 'Backdrop' display name migrated to 'Background'
- Per-scene UseDefaultBackground + CustomBackgroundPath
- Asset files renamed backdrop -> background
- StagedScene/LiveScene split, thumbnail strip, edit gating
- TransitionService (Cut/Fade/Move)
- Context menu: Capture Desktop, Refresh Desktop
- Resolution badge removed, ON-AIR status light added
This commit is contained in:
2026-08-22 18:10:59 -07:00
parent e06bfa42a8
commit 4b9a8e515f
35 changed files with 1406 additions and 717 deletions
+7 -7
View File
@@ -59,10 +59,10 @@ public class FramePumpTests
public void RaiseHealth(StreamHealth health) => HealthUpdated?.Invoke(this, health);
}
private static Scene BackdropScene()
private static Scene BackgroundScene()
{
var scene = new Scene { Name = "Live" };
scene.Elements.Add(new Source { Type = SourceType.DisplayCapture, IsBackdrop = true, CaptureKey = "monitor:0" });
scene.Elements.Add(new Source { Type = SourceType.DisplayCapture, IsBackground = true, CaptureKey = "monitor:0" });
return scene;
}
@@ -72,7 +72,7 @@ public class FramePumpTests
Func<(VideoFrame? Frame, SocialBarPosition Position)>? socialBar = null)
{
return new FramePump(
sceneProvider: scene ?? (() => BackdropScene()),
sceneProvider: scene ?? (() => BackgroundScene()),
frameResolver: resolve ?? (_ => null),
compositorOptions: () => new CompositorOptions
{
@@ -166,7 +166,7 @@ public class FramePumpTests
var red = SceneCompositorTests.Solid(64, 48, 255, 0, 0);
var encoder = new FakeEncoder();
using var pump = NewPump(encoder,
resolve: e => e is Source { IsBackdrop: true } ? red : null);
resolve: e => e is Source { IsBackground: true } ? red : null);
await pump.StartAsync();
Assert.True(pump.IsRunning);
@@ -177,7 +177,7 @@ public class FramePumpTests
var frame = encoder.Frames[0];
Assert.Equal(64, frame.Width);
Assert.Equal(48, frame.Height);
AssertColor(frame, 0, 0, 255, 0, 0); // the backdrop really was composited in
AssertColor(frame, 0, 0, 255, 0, 0); // the background really was composited in
await pump.StopAsync();
Assert.False(pump.IsRunning);
@@ -236,7 +236,7 @@ public class FramePumpTests
var encoder = new FakeEncoder();
var position = SocialBarPosition.Top;
using var pump = NewPump(encoder,
resolve: e => e is Source { IsBackdrop: true } ? red : null,
resolve: e => e is Source { IsBackground: true } ? red : null,
socialBar: () => (bar, position));
await pump.StartAsync();
@@ -246,7 +246,7 @@ public class FramePumpTests
// Flip to Bottom: the pump re-reads the seam each frame, so a later frame
// lands the bar at the bottom edge (SourceRectHeight - bar height) and the
// top corner clears back to backdrop.
// top corner clears back to background.
position = SocialBarPosition.Bottom;
VideoFrame? flipped = null;
var deadline = DateTime.UtcNow.AddSeconds(5);