diff --git a/Controls/OverlayHost.xaml b/Controls/OverlayHost.xaml
index a66718d..50ec09d 100644
--- a/Controls/OverlayHost.xaml
+++ b/Controls/OverlayHost.xaml
@@ -61,6 +61,7 @@
+
diff --git a/Services/TransitionService.cs b/Services/TransitionService.cs
index df2e0d7..06089f0 100644
--- a/Services/TransitionService.cs
+++ b/Services/TransitionService.cs
@@ -10,7 +10,8 @@ public enum TransitionType
{
Cut,
Fade,
- Move
+ Move,
+ Wipe
}
///
@@ -102,10 +103,33 @@ public sealed class TransitionService
{
TransitionType.Fade => BlendFade(FromFrame, toFrame, t),
TransitionType.Move => BlendMove(FromFrame, toFrame, t),
+ TransitionType.Wipe => BlendWipe(FromFrame, toFrame, t),
_ => toFrame
};
}
+ /// Left-to-right reveal: the new scene sweeps in across the frame.
+ private static VideoFrame BlendWipe(VideoFrame from, VideoFrame to, float t)
+ {
+ var w = from.Width;
+ var h = from.Height;
+ var output = new byte[w * h * 4];
+ var edge = (int)Math.Round(Math.Clamp(t, 0f, 1f) * w);
+ for (var y = 0; y < h; y++)
+ {
+ for (var x = 0; x < w; x++)
+ {
+ var src = x < edge ? to.BgraPixels : from.BgraPixels;
+ var i = (y * w + x) * 4;
+ output[i] = src[i];
+ output[i + 1] = src[i + 1];
+ output[i + 2] = src[i + 2];
+ output[i + 3] = src[i + 3];
+ }
+ }
+ return new VideoFrame(w, h, output);
+ }
+
private static VideoFrame BlendFade(VideoFrame from, VideoFrame to, float t)
{
var w = from.Width;
diff --git a/TASKS.md b/TASKS.md
index c8edc59..eb74c5c 100644
--- a/TASKS.md
+++ b/TASKS.md
@@ -456,7 +456,7 @@ These were explicitly ruled out:
- ✅ **Fade fix** — swaps fade from the outgoing picture (`TransitionFadeTests`). On-screen check pending.
- ✅ **Transition picker** in App Settings (type + duration), saved with the layout (`TransitionPickerTests`).
-- ☐ **Wipe** — CPU blend, direction setting.
+- ✅ **Wipe** — CPU blend, left-to-right reveal (`WipeTransitionTests`). Direction setting not yet added.
- ☐ **Move** — persistent layers (per-layer "carry across scenes" flag), per-scene placement, fixed z band.
- ☐ **Brand logo** — permanent "Brand logo" layer above background in every scene; file in App Settings
(imported to the asset table); per-scene eye toggle; top-left default.
diff --git a/ytLive.Tests/WipeTransitionTests.cs b/ytLive.Tests/WipeTransitionTests.cs
new file mode 100644
index 0000000..e0d4669
--- /dev/null
+++ b/ytLive.Tests/WipeTransitionTests.cs
@@ -0,0 +1,25 @@
+using System.Linq;
+using Xunit;
+using ytLive.Services;
+
+namespace ytLive.Tests;
+
+public class WipeTransitionTests
+{
+ [Fact]
+ public void Wipe_At_Half_Reveals_The_New_Scene_On_The_Left_Half()
+ {
+ var transition = new TransitionService();
+ var to = new VideoFrame(4, 1, Enumerable.Repeat((byte)255, 16).ToArray());
+ var from = new VideoFrame(4, 1, new byte[16]);
+
+ transition.Start(TransitionType.Wipe, 300, from);
+ transition.Tick(150);
+ var blended = transition.BlendFrame(to);
+
+ Assert.Equal((byte)255, blended.BgraPixels[0]);
+ Assert.Equal((byte)255, blended.BgraPixels[4]);
+ Assert.Equal((byte)0, blended.BgraPixels[8]);
+ Assert.Equal((byte)0, blended.BgraPixels[12]);
+ }
+}