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:
@@ -0,0 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ytLive.Models;
|
||||
using ytLive.Services;
|
||||
|
||||
namespace ytLive.ViewModels;
|
||||
|
||||
public partial class MainViewModel
|
||||
{
|
||||
private readonly TextOverlayRenderer _textOverlayRenderer = new();
|
||||
private readonly HashSet<Source> _wiredTextOverlays = new();
|
||||
|
||||
private void UpdateConfiguredTextOverlays()
|
||||
{
|
||||
var sources = Scenes.SelectMany(scene => scene.Elements).OfType<Source>()
|
||||
.Where(source => source.Type == SourceType.TextOverlay).ToArray();
|
||||
RetainTextOverlaySubscriptions();
|
||||
_textOverlayRenderer.Retain(sources);
|
||||
foreach (var source in sources)
|
||||
{
|
||||
if (source.Width <= 0) source.Width = 900;
|
||||
if (source.Height <= 0) source.Height = 140;
|
||||
WireTextOverlaySource(source);
|
||||
_textOverlayRenderer.UpdatePreview(source);
|
||||
}
|
||||
}
|
||||
|
||||
private void WireTextOverlaySource(Source source)
|
||||
{
|
||||
if (_wiredTextOverlays.Add(source))
|
||||
source.PropertyChanged += OnElementPropertyChanged;
|
||||
}
|
||||
|
||||
private void UpdateTextOverlayPreview(Source source) => _textOverlayRenderer.UpdatePreview(source);
|
||||
|
||||
private void RemoveTextOverlayPreview(Source source)
|
||||
{
|
||||
if (_wiredTextOverlays.Remove(source))
|
||||
source.PropertyChanged -= OnElementPropertyChanged;
|
||||
_textOverlayRenderer.Remove(source);
|
||||
}
|
||||
|
||||
private void RetainTextOverlaySubscriptions()
|
||||
{
|
||||
var active = Scenes.SelectMany(scene => scene.Elements).OfType<Source>()
|
||||
.Where(source => source.Type == SourceType.TextOverlay).ToHashSet();
|
||||
foreach (var source in _wiredTextOverlays.ToArray())
|
||||
if (!active.Contains(source))
|
||||
RemoveTextOverlayPreview(source);
|
||||
}
|
||||
|
||||
private void OnTextOverlayPropertyChanged(Source source, string? propertyName)
|
||||
{
|
||||
if (propertyName is nameof(Source.TextContent) or nameof(Source.TextFontFamily)
|
||||
or nameof(Source.TextFontSize) or nameof(Source.TextColor) or nameof(Source.TextBold)
|
||||
or nameof(Source.TextItalic) or nameof(Source.TextUnderline) or nameof(Source.TextAlignment)
|
||||
or nameof(Source.Width) or nameof(Source.Height))
|
||||
UpdateTextOverlayPreview(source);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user