Revert "Fix UI polish: scrollbar deselect, web source inline buttons, countdown in Sources, volume click-to-position, meter decay"

This reverts commit dc91c855ef.
This commit is contained in:
2026-08-17 17:59:43 -07:00
parent b7b015b12b
commit c7d4b3b6d9
6 changed files with 48 additions and 65 deletions
+37 -29
View File
@@ -278,10 +278,6 @@
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
@@ -301,7 +297,7 @@
</ContextMenu>
</Grid.ContextMenu>
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Name}" VerticalAlignment="Center"
<TextBlock Grid.Column="0" Text="{Binding Name}" VerticalAlignment="Center"
Padding="4,2" TextTrimming="CharacterEllipsis">
<TextBlock.Style>
<Style TargetType="TextBlock">
@@ -315,7 +311,7 @@
</TextBlock.Style>
</TextBlock>
<TextBox Grid.Row="0" Grid.Column="0" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
<TextBox Grid.Column="0" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
Background="#0f3460" Foreground="#e0e0e0" BorderThickness="0"
Padding="4,2" VerticalContentAlignment="Center"
IsVisibleChanged="SourceNameBox_IsVisibleChanged"
@@ -332,38 +328,27 @@
</TextBox.Style>
</TextBox>
<Button Grid.Row="0" Grid.Column="1" ToolTip="Edit Source Name"
<Button Grid.Column="1" ToolTip="Edit Source Name"
Command="{Binding DataContext.EditElementCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding}" Style="{StaticResource IconButton}">
<Path Data="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"
Fill="#d0d0d0" Width="13" Height="13" Stretch="Uniform"/>
</Button>
<Button Grid.Row="0" Grid.Column="2" Style="{StaticResource EyeButton}"
<Button Grid.Column="2" Style="{StaticResource EyeButton}"
Command="{Binding DataContext.ToggleElementVisibilityCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding}">
<Path Style="{StaticResource EyeIconStyle}" Fill="#d0d0d0"
Width="13" Height="13" Stretch="Uniform"/>
</Button>
<Button Grid.Row="0" Grid.Column="3" ToolTip="Remove Source"
<Button Grid.Column="3" ToolTip="Remove Source"
Command="{Binding DataContext.RemoveSourceCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding}" Style="{StaticResource IconButton}"
Visibility="{Binding IsBackdrop, Converter={StaticResource HiddenBoolToVis}}">
<Path Data="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"
Fill="#d0d0d0" Width="13" Height="13" Stretch="Uniform"/>
</Button>
<!-- Countdown timer: inline in source list row 1 -->
<DockPanel Grid.Row="1" Grid.ColumnSpan="4" Margin="8,2,4,2"
Visibility="{Binding Type, Converter={StaticResource SourceTypeToCountdownVis}, ConverterParameter=Countdown}">
<TextBlock Text="{Binding TimerMinutes, StringFormat={}{0} min}" Foreground="#a0a0b0" FontSize="11"
DockPanel.Dock="Right" VerticalAlignment="Center" Margin="6,0,0,0" Width="42"/>
<Slider DockPanel.Dock="Left" Width="130" Minimum="1" Maximum="30"
Value="{Binding TimerMinutes, Mode=TwoWay}"
VerticalAlignment="Center" TickFrequency="1" IsSnapToTickEnabled="True"
Style="{StaticResource CompactSlider}"/>
</DockPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
@@ -381,7 +366,7 @@
Visibility="{Binding SelectedElement, Converter={StaticResource NotNullToVis}}">
<TextBlock Text="ELEMENTS" Style="{StaticResource SectionHeader}" VerticalAlignment="Center"/>
</StackPanel>
<ScrollViewer x:Name="ElementsScrollViewer" Grid.Row="7" VerticalScrollBarVisibility="Auto" Background="Transparent"
<ScrollViewer Grid.Row="7" VerticalScrollBarVisibility="Auto" Background="Transparent"
Visibility="{Binding SelectedElement, Converter={StaticResource NotNullToVis}}">
<StackPanel x:Name="ElementsPanel" Margin="0,4,0,0">
<!-- Opacity + mirror/shape (draggable elements: image, webcam) -->
@@ -440,25 +425,48 @@
</DockPanel>
</StackPanel>
<!-- Web source config -->
<StackPanel Visibility="{Binding SelectedElement.Type, Converter={StaticResource SourceTypeToWebVis}, ConverterParameter=WebSource}" Margin="0,0,0,8">
<TextBlock Text="URI" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"/>
<DockPanel>
<!-- Countdown config -->
<StackPanel Visibility="{Binding SelectedElement.Type, Converter={StaticResource SourceTypeToCountdownVis}, ConverterParameter=Countdown}" Margin="0,0,0,8">
<TextBlock Text="Timer (minutes)" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"/>
<DockPanel Margin="0,0,0,6">
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
Width="22" Height="22" ToolTip="Revert"
Click="CountdownRevert_Click" Margin="4,0,0,0">
<Path Data="M5,5 L15,15 M15,5 L5,15" Stroke="#e94560" StrokeThickness="2"
Width="14" Height="14" Stretch="Uniform"/>
</Button>
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
IsEnabled="False" Width="22" Height="22" Margin="4,0,0,0">
<Path Data="M4,9 L8,14 L16,4" Stroke="#22c55e" StrokeThickness="2"
Width="14" Height="14" Stretch="Uniform"/>
</Button>
<Slider DockPanel.Dock="Left" Width="120" Minimum="1" Maximum="60"
Value="{Binding SelectedElement.TimerMinutes, Mode=TwoWay}"
VerticalAlignment="Center" TickFrequency="1" IsSnapToTickEnabled="True"/>
<TextBlock Text="{Binding SelectedElement.TimerMinutes}" Foreground="#a0a0b0" FontSize="11"
VerticalAlignment="Center" Margin="8,0,0,0" Width="20"/>
</DockPanel>
</StackPanel>
<!-- Web source config -->
<StackPanel Visibility="{Binding SelectedElement.Type, Converter={StaticResource SourceTypeToWebVis}, ConverterParameter=WebSource}" Margin="0,0,0,8">
<TextBlock Text="URI" Foreground="#a0a0b0" FontSize="11" Margin="0,0,0,2"/>
<TextBox Text="{Binding SelectedElement.WebUri, UpdateSourceTrigger=PropertyChanged}"
Background="#0f3460" Foreground="#e0d0e0" BorderThickness="1"
BorderBrush="#2c3a5c" Padding="4,2" FontSize="12"
ToolTip="https://example.com"/>
<DockPanel Margin="0,4,0,0">
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
Width="22" Height="22" ToolTip="Revert"
Click="WebRevert_Click" Margin="4,0,0,0">
<Path Data="M5,5 L15,15 M15,5 L5,15" Stroke="#e94560" StrokeThickness="2"
Width="14" Height="14" Stretch="Uniform"/>
</Button>
<TextBox Text="{Binding SelectedElement.WebUri, UpdateSourceTrigger=PropertyChanged}"
Background="#0f3460" Foreground="#e0d0e0" BorderThickness="1"
BorderBrush="#2c3a5c" Padding="4,2" FontSize="12"
ToolTip="https://example.com"/>
<Button DockPanel.Dock="Right" Style="{StaticResource IconButton}"
IsEnabled="False" Width="22" Height="22" Margin="4,0,0,0">
<Path Data="M4,9 L8,14 L16,4" Stroke="#22c55e" StrokeThickness="2"
Width="14" Height="14" Stretch="Uniform"/>
</Button>
</DockPanel>
</StackPanel>
+3 -18
View File
@@ -83,11 +83,8 @@ public partial class MainWindow : Window
private void VolumeSlider_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is Slider slider && ClickIsOnTrackBackground(slider, e))
{
if (sender is Slider slider)
SetSliderValueFromClick(slider, e);
e.Handled = true;
}
if (sender is FrameworkElement { DataContext: MainViewModel vm })
vm.SetVolumeAdjusting(true);
}
@@ -106,11 +103,8 @@ public partial class MainWindow : Window
private void GameVolumeSlider_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is Slider slider && ClickIsOnTrackBackground(slider, e))
{
if (sender is Slider slider)
SetSliderValueFromClick(slider, e);
e.Handled = true;
}
if (sender is FrameworkElement { DataContext: MainViewModel vm })
vm.SetGameVolumeAdjusting(true);
}
@@ -127,15 +121,6 @@ public partial class MainWindow : Window
vm.SetGameVolumeAdjusting(false);
}
private static bool ClickIsOnTrackBackground(Slider slider, MouseButtonEventArgs e)
{
var track = slider.Template.FindName("PART_Track", slider) as System.Windows.Controls.Primitives.Track;
if (track == null) return false;
if (track.Thumb != null && IsDescendantOf(e.OriginalSource as DependencyObject, track.Thumb))
return false;
return true;
}
private static void SetSliderValueFromClick(Slider slider, MouseButtonEventArgs e)
{
var track = slider.Template.FindName("PART_Track", slider) as System.Windows.Controls.Primitives.Track;
@@ -224,7 +209,7 @@ public partial class MainWindow : Window
if (e.OriginalSource is not DependencyObject original) return;
if (IsDescendantOf(original, PreviewGrid)) return;
if (IsDescendantOf(original, SourceList)) return;
if (IsDescendantOf(original, ElementsScrollViewer)) return;
if (IsDescendantOf(original, ElementsPanel)) return;
_viewModel.SelectedElement = null;
}
+1 -1
View File
@@ -96,7 +96,7 @@ public class Source : SceneElement
public int TimerMinutes
{
get => _timerMinutes;
set => Set(ref _timerMinutes, Math.Clamp(value, 1, 30));
set => Set(ref _timerMinutes, Math.Clamp(value, 1, 60));
}
// Web source config
+4 -14
View File
@@ -1,27 +1,18 @@
namespace ytLive.Services.Audio;
/// <summary>
/// Computes the smoothed level (0..1) from captured samples. Pure —
/// Computes the smoothed mic level (0..1) from captured samples. Pure —
/// unit-tested; the <see cref="AudioMixer"/> only feeds it and forwards the
/// result. RMS-based so it tracks perceived loudness, smoothed so the meter
/// does not flicker. Supports asymmetric smoothing: fast attack (rise) and
/// configurable decay (fall) so the meter responds quickly to silence.
/// does not flicker.
/// </summary>
public sealed class AudioLevelMeter
{
private const float Smoothing = 0.2f;
private float _level;
public float Level => _level;
public AudioLevelMeter(float attackSmoothing = 0.2f, float decaySmoothing = 0.08f)
{
AttackSmoothing = attackSmoothing;
DecaySmoothing = decaySmoothing;
}
public float AttackSmoothing { get; }
public float DecaySmoothing { get; }
/// <summary>
/// Maps a linear level (0..1) onto the meter's display scale: -60 dBFS..0 dBFS
/// spread linearly across 0..1, with +10 dB of input amplification. Linear RMS
@@ -53,8 +44,7 @@ public sealed class AudioLevelMeter
}
var rms = (float)Math.Sqrt(sumSquares / count);
var smoothing = rms > _level ? AttackSmoothing : DecaySmoothing;
_level = _level * (1 - smoothing) + rms * smoothing;
_level = _level * (1 - Smoothing) + rms * Smoothing;
return _level;
}
+1 -1
View File
@@ -57,7 +57,7 @@ public sealed class AudioMixer : IDisposable
_mic = mic;
_loopback = loopback;
_meter = new AudioLevelMeter();
_loopbackMeter = new AudioLevelMeter(attackSmoothing: 0.2f, decaySmoothing: 0.08f);
_loopbackMeter = new AudioLevelMeter();
_log = log;
_micGain = micGain;
_loopbackGain = loopbackGain;
+2 -2
View File
@@ -818,12 +818,12 @@ No changes to `MusicPlayer`, the 0.20 cap, the ducker, or the meter zones. Build
1. ✅ TRAX volume — `LocalGain = GameAudioVolume * 0.2` so TRAX is 20% of the desktop audio slider (was 100%, now quieter)
2. ✅ TRAX tooltip — replaced `ToolTip` binding with `ToolTipService.ToolTip` + `Placement="Top"` to fix z-order inside Viewbox overlay
3. ✅ Mic meter boost — `MeterLevel` multiplied by 1.2× before clamping so the bar reads ~20% higher at same input level
4. ✅ Click-to-position sliders — clicking anywhere on the mic/game volume slider track now jumps the thumb to that position before starting the drag (fixed: RepeatButton no longer overrides click position; Thumb drag still works)
4. ✅ Click-to-position sliders — clicking anywhere on the mic/game volume slider track now jumps the thumb to that position before starting the drag
5. ✅ Backdrop visibility — the dedicated `<Image>` now binds `Visibility` to `BackdropVisible` (ViewModel property); compositor checks `IsVisible` before blit
6. ✅ Rename "Backdrop" → "Game Capture" in `EnsureBackdrop()` + test assertions
7. ✅ Elements panel — new "ELEMENTS" section beneath Sources list; per-element config with live preview, ✕ revert, ✓ applied indicator
8. ✅ Webcam border config — color hex input + color swatch picker, border thickness 0–10 slider
9. ✅ Countdown source — `SourceType.Countdown`, pick list (Starting/BRB scenes only), timer minutes 1–30 default 15, inline slider in source list row
9. ✅ Countdown source — `SourceType.Countdown`, pick list (Starting/BRB scenes only), timer minutes 1–60 default 15
10. ✅ Web source — `SourceType.WebSource`, pick list (all scenes), URI text input
---