Files
deepdrft/DeepDrftPublic.Client/Services/MixVisualizerControlState.cs
T

69 lines
3.6 KiB
C#

namespace DeepDrftPublic.Client.Services;
/// <summary>
/// Holds the Mix visualizer's four continuous-control positions for the lifetime of the WASM app
/// instance. Scoped in DI, so it lives across SPA navigations within one listening session — open a
/// second mix and the sliders keep where you left them — but a fresh page load (F5) constructs a new
/// instance, resetting to defaults. That matches the spec's "persist within session, reset on fresh
/// load" without any cookie/localStorage round-trip (see mix-visualizer-webgl-renderer §3c).
///
/// One state object, four properties — not four sibling holders (Daniel's decided shape, spec §3c).
/// Each C#-side default mirrors a TS-side tuning anchor in MixVisualizer.ts; keep the two in sync, as
/// the existing <c>DefaultVisibleSeconds</c> / <c>DEFAULT_VISIBLE_SECONDS</c> pair does.
///
/// <para>
/// <see cref="Changed"/> is the decoupling seam between the controls row and the visualizer bridge.
/// The controls component (a sibling of the backdrop in the page tree) only mutates this shared state
/// and raises <see cref="Changed"/>; the bridge component (<c>MixWaveformVisualizer</c>) subscribes
/// and pushes the affected uniform to the JS module. This keeps the JS module handle single-owned by
/// the bridge — no handle sharing, no service-locator, no cross-component interop.
/// </para>
/// </summary>
public sealed class MixVisualizerControlState
{
/// <summary>
/// Default opening window. Mirrors <c>DEFAULT_VISIBLE_SECONDS</c> in MixVisualizer.ts; keep the
/// two in sync (the TS owns the rendering anchors, this owns the C#-side session default).
/// </summary>
public const double DefaultVisibleSeconds = 10.0;
/// <summary>
/// Default bulge amount. Mirrors <c>DEFAULT_BUBBLYNESS</c> in MixVisualizer.ts. Normalized [0,1];
/// 0 = straight rectangular bars, 1 = fully rounded liquid silhouettes (still attached).
/// </summary>
public const double DefaultBubblyness = 0.35;
/// <summary>
/// Default detach amount. Mirrors <c>DEFAULT_DETACH</c> in MixVisualizer.ts. Normalized [0,1];
/// 0 = fully attached, 1 = blobs separate and float upward. Off by default.
/// </summary>
public const double DefaultDetach = 0.0;
/// <summary>
/// Default color-shift speed. Mirrors <c>DEFAULT_COLOR_SHIFT_SPEED</c> in MixVisualizer.ts.
/// Normalized [0,1], mapped to a gradient-morph cycle period in the shader (slow → quick).
/// </summary>
public const double DefaultColorShiftSpeed = 0.3;
/// <summary>Visible time-span in seconds (the resolution/zoom control). Reused as-is from 8.K.</summary>
public double VisibleSeconds { get; set; } = DefaultVisibleSeconds;
/// <summary>Bulge amount, normalized [0,1]. Inert until Wave 3 consumes the uniform.</summary>
public double Bubblyness { get; set; } = DefaultBubblyness;
/// <summary>Lava-lamp detachment, normalized [0,1]. Inert until Wave 3 consumes the uniform.</summary>
public double Detach { get; set; } = DefaultDetach;
/// <summary>Gradient-morph rate, normalized [0,1]. Inert until Wave 3 consumes the uniform.</summary>
public double ColorShiftSpeed { get; set; } = DefaultColorShiftSpeed;
/// <summary>
/// Raised whenever any control value changes. The visualizer bridge subscribes to push the
/// affected uniform(s). Mutators set the property then raise this; subscribers re-read the values.
/// </summary>
public event Action? Changed;
/// <summary>Raise <see cref="Changed"/>. Called by the controls component after mutating a value.</summary>
public void NotifyChanged() => Changed?.Invoke();
}