feat(text): composite shared text rasters in output
Raster static text on UI-thread changes and reuse the same transparent BGRA frame in preview and all compositor paths. Cache text frame identity in the frame-pump signature and invalidate static bakes on edits. Follow OBS text-source conventions: https://obsproject.com/kb/text-sources
This commit is contained in:
@@ -47,6 +47,7 @@ public partial class MainViewModel : ViewModelBase
|
||||
// born yet (startup crash regression from TASK 31, 2026-09-01; headless RealApp
|
||||
// tests never ran it, so it waited for the first native launch).
|
||||
private SceneGraph _sceneGraph = new();
|
||||
internal SceneGraph SceneGraphForTests => _sceneGraph;
|
||||
|
||||
/// <summary>Alert audio plays on the default device (creator ruling 2026-11-01): the WASAPI
|
||||
/// loopback then picks it up, so it is audible AND visible in the desktop sound bar.</summary>
|
||||
@@ -497,6 +498,7 @@ public partial class MainViewModel : ViewModelBase
|
||||
}
|
||||
ClearPreviewHistory();
|
||||
StagedScene = Scenes.FirstOrDefault(s => SceneCatalog.Is(s.Name, SceneCatalog.Starting)) ?? Scenes.FirstOrDefault();
|
||||
UpdateConfiguredTextOverlays();
|
||||
UpdateActiveBackground();
|
||||
UpdateActiveChatBoxPreviews();
|
||||
UpdateActiveAlertBoxPreviews();
|
||||
@@ -585,7 +587,7 @@ public partial class MainViewModel : ViewModelBase
|
||||
// Scene-element → latest frame, for the live compositor. The map mirrors the
|
||||
// preview: webcam by DeviceId, live captures (the background) by CaptureKey,
|
||||
// images/background by AssetId. A null frame leaves the element transparent.
|
||||
private VideoFrame? ResolveOutputFrame(SceneElement element)
|
||||
internal VideoFrame? ResolveOutputFrame(SceneElement element)
|
||||
{
|
||||
var frame = ResolveOutputFrameCore(element);
|
||||
// Output-side eyes (2026-09-01): preview showed the webcam but the recording
|
||||
@@ -644,6 +646,7 @@ public partial class MainViewModel : ViewModelBase
|
||||
// (caught by the resolver logging, 2026-09-01 take two).
|
||||
WebcamSceneConfig webcam => _cameraManager.GetLatestFrame(DeviceKeyForWebcam(webcam.WebcamId), EffectKeyFor(webcam)),
|
||||
Source { IsLiveCapture: true, CaptureKey: not null } live => _screenCaptureManager.GetLatestFrame(live.CaptureKey),
|
||||
Source { Type: SourceType.TextOverlay } text => _textOverlayRenderer.RenderFrame(text),
|
||||
Source { Type: SourceType.ChatBox } chatBox => RenderChatBox(chatBox),
|
||||
Source { Type: SourceType.Ticker } ticker => _alertLayer.RenderSceneTicker(ticker),
|
||||
Source { Type: SourceType.Scoreboard } => _scoreboardPresenter?.Frame,
|
||||
|
||||
Reference in New Issue
Block a user