Phase 10 reframe R4: seven-knob inline visualizer controls, always-on lava loop, filled lava-lamp icon
This commit is contained in:
@@ -2,96 +2,144 @@
|
||||
@using DeepDrftPublic.Client.Services
|
||||
@inject MixVisualizerControlState ControlState
|
||||
|
||||
@* The Mix visualizer controls (Phase 10, Wave 4). Four continuous RadialKnobs — resolution,
|
||||
bubblyness, detach, color-shift speed — laid out in a row. This component lives inside the
|
||||
lava-lamp popover on the Mix detail page (Wave 4 moved it out of the always-visible TopContent row).
|
||||
@* The Mix visualizer controls (lava reframe Wave R4). SEVEN continuous RadialKnobs — scroll speed,
|
||||
gradient rotation speed, lava gravity, lava heat, blob density, collision strength, waveform width —
|
||||
each its own dedicated control with a Material-icon caption (no more R2 temp-remapping: no knob
|
||||
caption misrepresents its function). The bar lives INLINE in the mix-detail controls area and
|
||||
ANIMATES open/closed in place via CSS transition off the @Expanded flag — it reads as the controls
|
||||
collapsing/expanding, NOT a floating popover/drawer (§7b).
|
||||
|
||||
It 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).
|
||||
affected dial 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 (read-only contract §D).
|
||||
|
||||
RadialKnob has no icon slot (its Label renders as SVG text), so each control's Material icon rides
|
||||
beside its knob as an adjacent MudIcon caption (spec §7e). HoldValue stays false so the knobs are
|
||||
live — ValueChanged fires continuously during drag, exactly as the sliders fired before, preserving
|
||||
the "visibly and continuously affects its target" feel and the Changed/NotifyChanged seam. *@
|
||||
RadialKnob has no icon slot (its Label renders as SVG text) and no aria attribute-capture, so each
|
||||
control's Material icon rides beside its knob as an adjacent MudIcon caption and the accessible name
|
||||
rides on the wrapping group div (§7d). HoldValue stays false so the knobs are live — ValueChanged
|
||||
fires continuously during drag, preserving the Changed/NotifyChanged seam.
|
||||
|
||||
<div class="mix-visualizer-controls">
|
||||
Aesthetic: the bar matches the session-hero NowPlaying overlay (§7e) — a translucent dark glass
|
||||
surface with overlay-label captions and Color.Secondary accents, so it reads as of-a-piece with the
|
||||
hero rather than a generic MudBlazor panel. *@
|
||||
|
||||
@* RadialKnob exposes no aria-label/attribute-capture and is out of scope to modify, so the
|
||||
accessible name rides on the wrapping group div instead (a plain element accepts it).
|
||||
R2 TEMP: this knob is repurposed from resolution/zoom to WAVEFORM WIDTH for in-browser lava
|
||||
testing (scroll speed isn't critical for evaluating the lava). The on-screen icon still reads
|
||||
ZoomIn; R4 redraws the controls and restores the resolution mapping. *@
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Waveform width (R2 temp: on the resolution knob)">
|
||||
<RadialKnob Value="@ControlState.WaveformWidth"
|
||||
ValueChanged="@OnWaveformWidthChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="72"
|
||||
Color="Color.Primary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.ZoomIn" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<div class="mix-visualizer-controls-bar @(Expanded ? "is-expanded" : "")" aria-hidden="@(!Expanded)">
|
||||
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Waveform scroll speed">
|
||||
<RadialKnob Value="@ControlState.ScrollSpeed"
|
||||
ValueChanged="@OnScrollSpeedChanged"
|
||||
Min="0" Max="1" Step="0.001"
|
||||
Size="64"
|
||||
Color="Color.Secondary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.Speed" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Bubblyness">
|
||||
<RadialKnob Value="@ControlState.Bubblyness"
|
||||
ValueChanged="@OnBubblynessChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="72"
|
||||
Color="Color.Primary" />
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Color gradient rotation speed">
|
||||
<RadialKnob Value="@ControlState.GradientRotationSpeed"
|
||||
ValueChanged="@OnGradientRotationSpeedChanged"
|
||||
Min="0" Max="1" Step="0.001"
|
||||
Size="64"
|
||||
Color="Color.Secondary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.Palette" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Lava gravity">
|
||||
<RadialKnob Value="@ControlState.LavaGravity"
|
||||
ValueChanged="@OnLavaGravityChanged"
|
||||
Min="0" Max="1" Step="0.001"
|
||||
Size="64"
|
||||
Color="Color.Secondary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.ArrowDownward" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Lava heat">
|
||||
<RadialKnob Value="@ControlState.LavaHeat"
|
||||
ValueChanged="@OnLavaHeatChanged"
|
||||
Min="0" Max="1" Step="0.001"
|
||||
Size="64"
|
||||
Color="Color.Secondary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.LocalFireDepartment" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Blob density and size">
|
||||
<RadialKnob Value="@ControlState.BlobDensity"
|
||||
ValueChanged="@OnBlobDensityChanged"
|
||||
Min="0" Max="1" Step="0.001"
|
||||
Size="64"
|
||||
Color="Color.Secondary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.BubbleChart" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Detach (unleash the lava lamp)">
|
||||
<RadialKnob Value="@ControlState.Detach"
|
||||
ValueChanged="@OnDetachChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="72"
|
||||
Color="Color.Primary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.Air" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Collision strength">
|
||||
<RadialKnob Value="@ControlState.CollisionStrength"
|
||||
ValueChanged="@OnCollisionStrengthChanged"
|
||||
Min="0" Max="1" Step="0.001"
|
||||
Size="64"
|
||||
Color="Color.Secondary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.Compress" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
</div>
|
||||
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Color-shift speed">
|
||||
<RadialKnob Value="@ControlState.ColorShiftSpeed"
|
||||
ValueChanged="@OnColorShiftSpeedChanged"
|
||||
Min="0"
|
||||
Max="1"
|
||||
Step="0.001"
|
||||
Size="72"
|
||||
Color="Color.Primary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.Palette" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
<div class="mix-visualizer-control" role="group" aria-label="Waveform width">
|
||||
<RadialKnob Value="@ControlState.WaveformWidth"
|
||||
ValueChanged="@OnWaveformWidthChanged"
|
||||
Min="0" Max="1" Step="0.001"
|
||||
Size="64"
|
||||
Color="Color.Secondary" />
|
||||
<MudIcon Icon="@Icons.Material.Filled.SettingsEthernet" Size="Size.Small" Class="mix-visualizer-control-icon" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@code {
|
||||
// R2 TEMP: the resolution knob is repurposed to WAVEFORM WIDTH (already normalized [0,1], binds
|
||||
// directly). R4 restores the log zoom mapping (MixZoomMapping) and gives width its own knob.
|
||||
/// <summary>
|
||||
/// Whether the knob bar is expanded. Owned by the host page (the lava-lamp toggle button flips it);
|
||||
/// drives the CSS open/close transition. When false the bar collapses to zero size in place.
|
||||
/// </summary>
|
||||
[Parameter] public bool Expanded { get; set; }
|
||||
|
||||
// Each handler mutates its own dedicated property then raises Changed — the bridge re-reads and
|
||||
// pushes the affected dial. All values are already normalized [0,1]; the bridge maps scroll speed
|
||||
// to a visible time-span and routes the rest straight to the lava/colour dials.
|
||||
|
||||
private void OnScrollSpeedChanged(double value)
|
||||
{
|
||||
ControlState.ScrollSpeed = value;
|
||||
ControlState.NotifyChanged();
|
||||
}
|
||||
|
||||
private void OnGradientRotationSpeedChanged(double value)
|
||||
{
|
||||
ControlState.GradientRotationSpeed = value;
|
||||
ControlState.NotifyChanged();
|
||||
}
|
||||
|
||||
private void OnLavaGravityChanged(double value)
|
||||
{
|
||||
ControlState.LavaGravity = value;
|
||||
ControlState.NotifyChanged();
|
||||
}
|
||||
|
||||
private void OnLavaHeatChanged(double value)
|
||||
{
|
||||
ControlState.LavaHeat = value;
|
||||
ControlState.NotifyChanged();
|
||||
}
|
||||
|
||||
private void OnBlobDensityChanged(double value)
|
||||
{
|
||||
ControlState.BlobDensity = value;
|
||||
ControlState.NotifyChanged();
|
||||
}
|
||||
|
||||
private void OnCollisionStrengthChanged(double value)
|
||||
{
|
||||
ControlState.CollisionStrength = value;
|
||||
ControlState.NotifyChanged();
|
||||
}
|
||||
|
||||
private void OnWaveformWidthChanged(double value)
|
||||
{
|
||||
ControlState.WaveformWidth = value;
|
||||
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