diff --git a/Controls/LeftPanel.xaml b/Controls/LeftPanel.xaml
index 3de42fd..1ef1ba3 100644
--- a/Controls/LeftPanel.xaml
+++ b/Controls/LeftPanel.xaml
@@ -502,9 +502,8 @@
IsChecked="{Binding ScoreboardBackgroundEnabled, Mode=TwoWay}"/>
-
+ SelectedValuePath="Hex" SelectedValue="{Binding ScoreboardBackgroundColor, Mode=TwoWay}"/>
+ Gap between the strip and the frame edge.
+ private const double ScoreboardEdgeMargin = 8;
private Source? _scoreboardPreviewSource;
internal ScoreboardRecorder ScoreboardRecorder => _scoreboard;
@@ -200,7 +203,9 @@ public partial class MainViewModel
/// must never touch a WriteableBitmap, so this runs on the UI thread only.
private void RefreshScoreboardPreviews()
{
- var frame = _scoreboardEnabled ? _scoreboardPresenter?.Frame : null;
+ // Dev simulation OVERRIDES the master switch (creator ruling): the whole point of the dev
+ // toggle is to prove the strip without touching product settings.
+ var frame = (_scoreboardEnabled || _scoreboardSimulate) ? _scoreboardPresenter?.Frame : null;
foreach (var scene in Scenes)
foreach (var source in scene.Elements.OfType().Where(s => s.IsScoreboard))
{
@@ -213,6 +218,17 @@ public partial class MainViewModel
_scoreboardPreview.WritePixels(new System.Windows.Int32Rect(0, 0, frame.Width, frame.Height),
frame.BgraPixels, frame.Width * 4, 0);
source.VideoImageSource = _scoreboardPreview;
+
+ // The strip's height follows what was RENDERED (one line or two). A fixed 56px box
+ // squashed a wrapped strip instead of showing it, and its Y follows from the edge.
+ if (Math.Abs(source.Height - frame.Height) > 0.5)
+ {
+ source.Width = frame.Width;
+ source.Height = frame.Height;
+ source.Y = _scoreboardStyle is var _ && source.Y > 540
+ ? 1080 - frame.Height - ScoreboardEdgeMargin
+ : ScoreboardEdgeMargin;
+ }
_scoreboardPreviewSource = source;
}
}
diff --git a/ytLive.Tests/ScoreboardRendererTests.cs b/ytLive.Tests/ScoreboardRendererTests.cs
index 5c63460..9f397bb 100644
--- a/ytLive.Tests/ScoreboardRendererTests.cs
+++ b/ytLive.Tests/ScoreboardRendererTests.cs
@@ -44,6 +44,27 @@ public class ScoreboardRendererTests
var red = ScoreboardRenderer.Render(Tiles, new ScoreboardStyle("#FF0000", false, "#000000", 0.5));
Assert.True(Count(red!, (r, g, b, a) => r > 180 && g < 80 && b < 80 && a > 200) > 20);
+ // The PLATE TOGGLE itself: same text, plate off vs on, different pixels. This is the
+ // check that answers "the checkbox has no code behind it".
+ var off = ScoreboardRenderer.Render(Tiles, new ScoreboardStyle("#FFFFFF", false, "#0000FF", 0.5));
+ var on = ScoreboardRenderer.Render(Tiles, new ScoreboardStyle("#FFFFFF", true, "#0000FF", 0.5));
+ Assert.True(Count(on!, (r, g, b, a) => b > 150 && r < 60 && g < 60 && a > 100)
+ > Count(off!, (r, g, b, a) => b > 150 && r < 60 && g < 60 && a > 100) + 500,
+ "turning the plate on must add plate pixels");
+
+ // Opacity: 20% and 80% must produce visibly different plate transparency.
+ var faint = ScoreboardRenderer.Render(Tiles, new ScoreboardStyle("#FFFFFF", true, "#0000FF", 0.2));
+ var solid = ScoreboardRenderer.Render(Tiles, new ScoreboardStyle("#FFFFFF", true, "#0000FF", 0.8));
+ int AlphaOf(VideoFrame f)
+ {
+ for (var i = 3; i < f.BgraPixels.Length; i += 4)
+ if (f.BgraPixels[i] is > 10 and < 245) return f.BgraPixels[i];
+ return 0;
+ }
+ Assert.InRange(AlphaOf(faint!), 35, 70); // ~20% of 255
+ Assert.InRange(AlphaOf(solid!), 190, 220); // ~80% of 255
+ Assert.True(AlphaOf(solid!) > AlphaOf(faint!) + 100, "the opacity slider must move the alpha");
+
// Nothing enabled: no frame at all (the layer draws nothing).
Assert.Null(ScoreboardRenderer.Render(Array.Empty(), new ScoreboardStyle()));
}
diff --git a/ytLive.Tests/ScoreboardSimulationTests.cs b/ytLive.Tests/ScoreboardSimulationTests.cs
index 9a521a6..c76cae7 100644
--- a/ytLive.Tests/ScoreboardSimulationTests.cs
+++ b/ytLive.Tests/ScoreboardSimulationTests.cs
@@ -29,6 +29,11 @@ public class ScoreboardSimulationTests
recorder.StartSession();
Assert.Equal(0, recorder.State.NewMembers);
+ // Simulate OVERRIDES the master "show" switch: the dev toggle must work even when the
+ // product setting is off.
+ var vmSource = SourceAssert.Text("ViewModels", "MainViewModel.Scoreboard.cs");
+ Assert.Contains("_scoreboardEnabled || _scoreboardSimulate", vmSource);
+
// The control exists and is gated on the build, not on a runtime flag.
var panel = SourceAssert.Text("Controls", "LeftPanel.xaml");
Assert.Contains("ScoreboardSimulate", panel);