From e037ba027bf49458a9ca1b9f7267f83e16c34952 Mon Sep 17 00:00:00 2001 From: gramps Date: Fri, 7 Aug 2026 08:24:18 -0700 Subject: [PATCH] Multi-scene webcam (schema v3/v4): singleton Webcam + per-scene WebcamSceneConfig, right-click OBS-style border/context menu, persisted round-to-rect restore + legacy-square 16:9 heal, dark MenuItem template, tests (25 passing) --- AGENTS.md | 8 +- Helpers/EnumToBoolConverter.cs | 14 + MainWindow.xaml | 162 +++++++++- MainWindow.xaml.cs | 91 ++++-- Models/Scene.cs | 10 +- Models/SceneElement.cs | 239 +++++++++++++++ Models/Source.cs | 98 +----- Models/Webcam.cs | 13 + Models/WebcamSceneConfig.cs | 16 + Models/index.md | 7 +- Services/CameraManager.cs | 22 ++ Services/LayoutStore.cs | 316 ++++++++++++++++++- Services/index.md | 4 +- TASKS.md | 8 +- Themes/Controls.xaml | 54 +++- ViewModels/MainViewModel.cs | 321 ++++++++++++++------ ViewModels/index.md | 2 +- ai.md | 82 +++-- run.bat | 3 + run.sh | 4 + ytLive.Tests/LayoutStorePersistenceTests.cs | 66 +++- ytLive.Tests/RoundClipInteractionTests.cs | 15 +- ytLive.Tests/WebcamSafeguardTests.cs | 137 +++++++++ 23 files changed, 1405 insertions(+), 287 deletions(-) create mode 100644 Helpers/EnumToBoolConverter.cs create mode 100644 Models/SceneElement.cs create mode 100644 Models/Webcam.cs create mode 100644 Models/WebcamSceneConfig.cs create mode 100644 run.bat create mode 100644 run.sh create mode 100644 ytLive.Tests/WebcamSafeguardTests.cs diff --git a/AGENTS.md b/AGENTS.md index 1c05a21..a2bca3c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -51,8 +51,14 @@ conventions live here and in `ai.md`. ## Build +From WSL, ALWAYS use the Windows dotnet host — Linux `dotnet` re-downloads the +`windowsdesktop.app.*` packs over the slow 9p bridge and re-restores twice (WPF +`_wpftmp`), and `--no-restore` right after an interrupted restore produces bogus +`NETSDK1064` errors. See `ai.md` → Run for the exact commands and why. + ```bash -dotnet build # Windows-only WPF; builds from WSL via EnableWindowsTargeting +"/mnt/c/Program Files/dotnet/dotnet.exe" build "C:\Users\gramp\Documents\Code\projects\ytLive\ytLive.csproj" +"/mnt/c/Program Files/dotnet/dotnet.exe" vstest "C:\Users\gramp\Documents\Code\projects\ytLive\ytLive.Tests\bin\Debug\net8.0-windows10.0.19041.0\ytLive.Tests.dll" ``` Keep it at **0 warnings**. Running requires Windows. On a silent startup crash, diff --git a/Helpers/EnumToBoolConverter.cs b/Helpers/EnumToBoolConverter.cs new file mode 100644 index 0000000..aee9f0d --- /dev/null +++ b/Helpers/EnumToBoolConverter.cs @@ -0,0 +1,14 @@ +using System.Globalization; +using System.Windows.Data; + +namespace ytLive.Helpers; + +/// True when the bound value's ToString() equals the ConverterParameter string. +public class EnumToBoolConverter : IValueConverter +{ + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + => value?.ToString() == parameter?.ToString(); + + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + => Binding.DoNothing; +} diff --git a/MainWindow.xaml b/MainWindow.xaml index cae6c48..815e55b 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -30,6 +30,8 @@ xmlns:Helpers="clr-namespace:ytLive.Helpers"/> + @@ -230,7 +232,7 @@ @@ -244,8 +246,8 @@ - + + + + + + - @@ -325,6 +332,16 @@ Opacity="{Binding Opacity}" Background="Transparent" RenderTransformOrigin="0.5,0.5"> + + + @@ -335,12 +352,12 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Canvas.Left="{Binding SelectedElement.X}" Canvas.Top="{Binding SelectedElement.Y}" + Width="{Binding SelectedElement.Width}" Height="{Binding SelectedElement.Height}"> @@ -475,17 +611,17 @@ -