TASK 4 ship step 5.5: social bar bug fixes + bar on the live output — direction-snap drag (SocialBarSnap.Decide + ClearValue, local Canvas.Top was overriding the binding), fediverse nodeinfo subdomain probing + load-time heal (settable FediverseSoftware), SocialBarRenderer strip blitted above the flash via a re-read FramePump socialBar seam — 155 tests passing, 0 warnings
This commit is contained in:
@@ -18,13 +18,16 @@ public sealed class SceneCompositor
|
||||
/// Composite <paramref name="scene"/> into the tier's output frame. Layer order (back →
|
||||
/// front): live backdrop (the scene's <c>IsBackdrop</c> source) → background image →
|
||||
/// visible elements (z-order = <c>Elements</c> order, mirroring the XAML DataTemplate) →
|
||||
/// branding flash. Transparent regions read opaque black.
|
||||
/// branding flash → social bar (a global overlay; spans the master width at
|
||||
/// <paramref name="socialBarTop"/>). Transparent regions read opaque black.
|
||||
/// </summary>
|
||||
public VideoFrame Render(
|
||||
Scene scene,
|
||||
Func<SceneElement, VideoFrame?> frameFor,
|
||||
VideoFrame? flashFrame,
|
||||
CompositorOptions options)
|
||||
CompositorOptions options,
|
||||
VideoFrame? socialBarFrame = null,
|
||||
int socialBarTop = 0)
|
||||
{
|
||||
if (scene == null) throw new ArgumentNullException(nameof(scene));
|
||||
if (frameFor == null) throw new ArgumentNullException(nameof(frameFor));
|
||||
@@ -79,7 +82,10 @@ public sealed class SceneCompositor
|
||||
}
|
||||
|
||||
if (flashFrame != null)
|
||||
BlitFlash(buffer, cropW, cropH, options, flashFrame);
|
||||
BlitOverlay(buffer, cropW, cropH, options, flashFrame, 0, 0);
|
||||
|
||||
if (socialBarFrame != null && socialBarFrame.Width > 0 && socialBarFrame.Height > 0)
|
||||
BlitOverlay(buffer, cropW, cropH, options, socialBarFrame, 0, socialBarTop);
|
||||
|
||||
return StretchMath.BilinearScale(
|
||||
new VideoFrame(cropW, cropH, buffer), options.OutputWidth, options.OutputHeight);
|
||||
@@ -166,17 +172,20 @@ public sealed class SceneCompositor
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>1:1 copy of the master-sized branding flash, cropped to the active source rect.</summary>
|
||||
private static void BlitFlash(byte[] dst, int dstW, int dstH, CompositorOptions options, VideoFrame flash)
|
||||
/// <summary>1:1 copy of a master-sized overlay (flash, social bar) cropped to the
|
||||
/// active source rect. The overlay is positioned in master space by (sx0, sy0).</summary>
|
||||
private static void BlitOverlay(
|
||||
byte[] dst, int dstW, int dstH, CompositorOptions options,
|
||||
VideoFrame overlay, int sx0, int sy0)
|
||||
{
|
||||
for (var y = 0; y < dstH; y++)
|
||||
{
|
||||
for (var x = 0; x < dstW; x++)
|
||||
{
|
||||
var sx = x + options.SourceRectX;
|
||||
var sy = y + options.SourceRectY;
|
||||
if (sx >= flash.Width || sy >= flash.Height) continue;
|
||||
var sample = StretchMath.SampleBgra(flash.BgraPixels, flash.Width, flash.Height, sx, sy);
|
||||
var sx = x + options.SourceRectX - sx0;
|
||||
var sy = y + options.SourceRectY - sy0;
|
||||
if (sx < 0 || sy < 0 || sx >= overlay.Width || sy >= overlay.Height) continue;
|
||||
var sample = StretchMath.SampleBgra(overlay.BgraPixels, overlay.Width, overlay.Height, sx, sy);
|
||||
BlendPixel(dst, (y * dstW + x) * 4, sample, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user