feat(visualizer): controls row + unified MixVisualizerControlState; 3 inert uniforms wired (P10 W2)
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
@namespace DeepDrftPublic.Client.Controls
|
||||
@using DeepDrftPublic.Client.Services
|
||||
@inject MixVisualizerControlState ControlState
|
||||
|
||||
@* The Mix visualizer controls row (Phase 10, Wave 2). Four continuous sliders — resolution,
|
||||
bubblyness, detach, color-shift speed — placed above the mix details and below the back button.
|
||||
This component owns NO JS interop: it mutates the shared, session-scoped MixVisualizerControlState
|
||||
and raises its Changed event. The backdrop bridge (MixWaveformVisualizer) subscribes to that event
|
||||
and pushes the affected uniform to the WebGL module. That keeps the JS module handle single-owned
|
||||
by the bridge and this component purely presentational. None of these is a seek surface (spec §D). *@
|
||||
|
||||
<div class="mix-visualizer-controls">
|
||||
|
||||
<div class="mix-visualizer-control">
|
||||
<MudIcon Icon="@Icons.Material.Filled.ZoomIn" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<MudSlider T="double"
|
||||
Value="@ResolutionFraction"
|
||||
ValueChanged="@OnResolutionChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
aria-label="Resolution (visible time-span)" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control">
|
||||
<MudIcon Icon="@Icons.Material.Filled.BubbleChart" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<MudSlider T="double"
|
||||
Value="@ControlState.Bubblyness"
|
||||
ValueChanged="@OnBubblynessChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
aria-label="Bubblyness" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Air" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<MudSlider T="double"
|
||||
Value="@ControlState.Detach"
|
||||
ValueChanged="@OnDetachChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
aria-label="Detach (unleash the lava lamp)" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Palette" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<MudSlider T="double"
|
||||
Value="@ControlState.ColorShiftSpeed"
|
||||
ValueChanged="@OnColorShiftSpeedChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
aria-label="Color-shift speed" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@code {
|
||||
// Resolution rides the log mapping (slider fraction [0,1] ↔ visible seconds); the other three are
|
||||
// already normalized [0,1] and bind to their state properties directly.
|
||||
private double ResolutionFraction => MixZoomMapping.SecondsToFraction(ControlState.VisibleSeconds);
|
||||
|
||||
private void OnResolutionChanged(double fraction)
|
||||
{
|
||||
ControlState.VisibleSeconds = MixZoomMapping.FractionToSeconds(fraction);
|
||||
ControlState.NotifyChanged();
|
||||
}
|
||||
|
||||
private void OnBubblynessChanged(double value)
|
||||
{
|
||||
ControlState.Bubblyness = value;
|
||||
ControlState.NotifyChanged();
|
||||
}
|
||||
|
||||
private void OnDetachChanged(double value)
|
||||
{
|
||||
ControlState.Detach = value;
|
||||
ControlState.NotifyChanged();
|
||||
}
|
||||
|
||||
private void OnColorShiftSpeedChanged(double value)
|
||||
{
|
||||
ControlState.ColorShiftSpeed = value;
|
||||
ControlState.NotifyChanged();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user