TASK 3 milestone 1: webcam capture (MediaCapture CPU-first, CameraManager refcount, picker, clip/mirror, schema v2, tests)

This commit is contained in:
2026-08-06 14:35:34 -07:00
parent d97b5d375c
commit 98cdc4b3f4
23 changed files with 1099 additions and 40 deletions
+20 -4
View File
@@ -115,13 +115,29 @@ public partial class MainWindow : Window
private void UpdateSelectionOverlay()
{
var selected = _viewModel.SelectedSource is { Type: SourceType.Image };
var selected = _viewModel.SelectedSource is { } s && IsDraggableSource(s);
SelectionOverlay.Visibility = selected ? Visibility.Visible : Visibility.Collapsed;
OpacityChip.Visibility = selected ? Visibility.Visible : Visibility.Collapsed;
if (selected)
OpacityValueText.Text = $"{Math.Round(_viewModel.SelectedSource!.Opacity * 100)}%";
}
// Static images and the webcam share the move/resize/selection behavior.
private static bool IsDraggableSource(Source source)
=> source.Type is SourceType.Image or SourceType.Webcam;
private void MirrorButton_Click(object sender, RoutedEventArgs e)
{
if (_viewModel.SelectedSource is { Type: SourceType.Webcam } source)
source.IsMirrored = !source.IsMirrored;
}
private void ShapeButton_Click(object sender, RoutedEventArgs e)
{
if (_viewModel.SelectedSource is { Type: SourceType.Webcam } source)
source.ClipShape = source.ClipShape == ClipShape.Traditional ? ClipShape.Round : ClipShape.Traditional;
}
private void OpacitySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
=> OpacityValueText.Text = $"{Math.Round(e.NewValue * 100)}%";
@@ -134,10 +150,10 @@ public partial class MainWindow : Window
var p = toCanvas.Transform(e.GetPosition(grid));
var selected = _viewModel.SelectedSource;
if (selected is { Type: SourceType.Image } && HitHandle(e.GetPosition(grid), selected))
if (selected is { } sel && IsDraggableSource(sel) && HitHandle(e.GetPosition(grid), sel))
{
_isResizing = true;
_resizeAspect = selected.Width / Math.Max(1, selected.Height);
_resizeAspect = sel.Width / Math.Max(1, sel.Height);
grid.CaptureMouse();
e.Handled = true;
return;
@@ -218,7 +234,7 @@ public partial class MainWindow : Window
for (var i = scene.Sources.Count - 1; i >= 0; i--)
{
var source = scene.Sources[i];
if (source.Type != SourceType.Image || !source.IsEnabled) continue;
if (!IsDraggableSource(source) || !source.IsEnabled) continue;
if (p.X >= source.X && p.X <= source.X + source.Width &&
p.Y >= source.Y && p.Y <= source.Y + source.Height)
return source;