feat(text): add static text editor and preview

TextOverlay layers now have a multiline editor, Windows font and size controls, color/emphasis/alignment settings, and a visible draggable preview. Text sources follow OBS's static text-source conventions: https://obsproject.com/kb/text-sources
This commit is contained in:
2026-11-04 14:28:47 -08:00
parent 60c4a0032f
commit 58eb640c4e
7 changed files with 210 additions and 10 deletions
+63 -1
View File
@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Helpers="clr-namespace:ytLive.Helpers"
xmlns:models="clr-namespace:ytLive.Models">
xmlns:models="clr-namespace:ytLive.Models"
xmlns:media="clr-namespace:System.Windows.Media;assembly=PresentationCore">
<UserControl.Resources>
<!-- TASK 63: the border-colour drop-down is the app's own YtComboBox, so the
colour entries are drawn by TEMPLATES, in the theme's colours and with the
@@ -317,6 +318,67 @@
<ScrollViewer x:Name="ElementsScrollViewer" Grid.Row="6" VerticalScrollBarVisibility="Auto" Background="Transparent"
Visibility="{Binding SelectedElement, Converter={StaticResource NotNullToVis}}">
<StackPanel x:Name="ElementsPanel" Margin="8,4,0,0">
<StackPanel Visibility="{Binding SelectedElement.IsTextOverlay, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
<TextBlock Text="Text" Style="{StaticResource PropertyHeader}"/>
<TextBlock Text="Static text — it will not animate automatically. Move and resize it in the preview."
Style="{StaticResource PropertyHint}" Margin="0,0,0,6" TextWrapping="Wrap"/>
<TextBox x:Name="TextLayerEditor" Text="{Binding SelectedElement.TextContent, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource YtTextBoxCompact}" AcceptsReturn="True" TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" MinHeight="72" MaxHeight="120"
AutomationProperties.Name="Text layer content"/>
<TextBlock Text="Font" Style="{StaticResource PropertyHeader}"/>
<ComboBox IsEditable="True" ItemsSource="{x:Static media:Fonts.SystemFontFamilies}"
DisplayMemberPath="Source"
Text="{Binding SelectedElement.TextFontFamily, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource YtComboBox}" Height="26" Margin="0,0,0,6"
AutomationProperties.Name="Text layer font"/>
<DockPanel Margin="0,0,0,6" LastChildFill="False">
<TextBlock DockPanel.Dock="Left" Text="Size" Style="{StaticResource PropertyFieldLabel}"
Width="42" VerticalAlignment="Center"/>
<ComboBox IsEditable="True"
Text="{Binding SelectedElement.TextFontSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource YtComboBox}" Height="26" Width="76"
AutomationProperties.Name="Text layer size">
<ComboBoxItem Content="12"/><ComboBoxItem Content="16"/>
<ComboBoxItem Content="20"/><ComboBoxItem Content="24"/>
<ComboBoxItem Content="32"/><ComboBoxItem Content="36"/>
<ComboBoxItem Content="48"/><ComboBoxItem Content="60"/>
<ComboBoxItem Content="72"/><ComboBoxItem Content="96"/>
<ComboBoxItem Content="120"/><ComboBoxItem Content="144"/>
<ComboBoxItem Content="180"/><ComboBoxItem Content="240"/>
<ComboBoxItem Content="300"/>
</ComboBox>
</DockPanel>
<DockPanel Margin="0,0,0,6" LastChildFill="False">
<TextBlock DockPanel.Dock="Left" Text="Color" Style="{StaticResource PropertyFieldLabel}"
Width="42" VerticalAlignment="Center"/>
<TextBox x:Name="TextLayerColorEditor"
Text="{Binding SelectedElement.TextColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource YtTextBoxCompact}" MaxLength="9" Width="82"
ToolTip="#RRGGBB or #AARRGGBB" AutomationProperties.Name="Text layer color"/>
<Border Width="18" Height="18" Margin="8,0,0,0" CornerRadius="2"
Background="{Binding SelectedElement.TextColor, Converter={StaticResource HexToBrush}}"
BorderBrush="{StaticResource Brush.Outline}" BorderThickness="1"
VerticalAlignment="Center"/>
</DockPanel>
<WrapPanel Margin="0,0,0,4">
<CheckBox Style="{StaticResource PropertyPillCheck}" Content="Bold" Margin="0,0,8,4"
IsChecked="{Binding SelectedElement.TextBold, Mode=TwoWay}"/>
<CheckBox Style="{StaticResource PropertyPillCheck}" Content="Italic" Margin="0,0,8,4"
IsChecked="{Binding SelectedElement.TextItalic, Mode=TwoWay}"/>
<CheckBox Style="{StaticResource PropertyPillCheck}" Content="Underline" Margin="0,0,8,4"
IsChecked="{Binding SelectedElement.TextUnderline, Mode=TwoWay}"/>
</WrapPanel>
<TextBlock Text="Alignment" Style="{StaticResource PropertyHeader}"/>
<ComboBox SelectedValuePath="Tag"
SelectedValue="{Binding SelectedElement.TextAlignment, Mode=TwoWay}"
Style="{StaticResource YtComboBox}" Height="26">
<ComboBoxItem Content="Left" Tag="{x:Static models:TextLayerAlignment.Left}"/>
<ComboBoxItem Content="Center" Tag="{x:Static models:TextLayerAlignment.Center}"/>
<ComboBoxItem Content="Right" Tag="{x:Static models:TextLayerAlignment.Right}"/>
</ComboBox>
</StackPanel>
<!-- Opacity + mirror/shape (draggable elements: image, webcam) -->
<StackPanel Visibility="{Binding SelectedElement.IsDraggable, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
<StackPanel Visibility="{Binding SelectedElement.IsChatBox, Converter={StaticResource InverseBoolToVis}}">