Phase 10 reframe R4: seven-knob inline visualizer controls, always-on lava loop, filled lava-lamp icon
This commit is contained in:
@@ -1,89 +1,103 @@
|
||||
namespace DeepDrftPublic.Client.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the Mix visualizer's four continuous-control positions for the lifetime of the WASM app
|
||||
/// Holds the Mix visualizer's seven 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
|
||||
/// second mix and the knobs 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).
|
||||
/// load" without any cookie/localStorage round-trip (lava reframe §7c).
|
||||
///
|
||||
/// 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.
|
||||
/// One state object, seven properties — not seven sibling holders, and (deliberately) NO constructor
|
||||
/// parameters: this is a plain scoped value holder, so widening it from four to seven properties adds
|
||||
/// fields + defaults only and never forces a consumer constructor to grow. 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.
|
||||
/// <see cref="Changed"/> is the decoupling seam between the controls bar 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.
|
||||
/// and pushes the affected uniform/dial 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;
|
||||
|
||||
// R2 TEMP (Phase 10 reframe Wave R2): the FOUR controls below are re-routed to the new
|
||||
// lava physics for Daniel's in-browser test — the JS handle setters map them as:
|
||||
// Bubblyness → lava GRAVITY, Detach → lava HEAT, ColorShiftSpeed → COLLISION STRENGTH,
|
||||
// Resolution (VisibleSeconds knob) → WAVEFORM WIDTH (see MixVisualizerControls.razor).
|
||||
// The defaults are tuned to Daniel's sweet spot (~20% gravity, ~100% heat). Wave R4
|
||||
// replaces this with the proper seven-knob set + its own typed properties. Keep these
|
||||
// mirrored to the DEFAULT_* anchors in MixVisualizer.ts, as the existing sync discipline.
|
||||
// ── The seven control defaults (lava reframe §7a). Each mirrors a DEFAULT_* anchor in
|
||||
// MixVisualizer.ts; keep the two in sync, as the existing default-sync discipline requires.
|
||||
// Feel-anchors only — Daniel tunes on screen; the ~20% gravity / ~100% heat pair is his stated
|
||||
// sweet spot (§4c).
|
||||
|
||||
/// <summary>
|
||||
/// Default GRAVITY dial (R2 temp; was bulge). Mirrors <c>DEFAULT_BUBBLYNESS</c> in MixVisualizer.ts.
|
||||
/// Normalized [0,1]; 0 = near-weightless float, 1 = wax falls + settles fast. Tuned to Daniel's
|
||||
/// ~20% sweet spot so the wax is buoyant-dominated and flows.
|
||||
/// Default scroll-speed dial. Mirrors <c>DEFAULT_SCROLL_SPEED</c> in MixVisualizer.ts. Normalized
|
||||
/// [0,1] → mapped to the visible time-span via <see cref="MixZoomMapping"/> (0 = slow/wide window,
|
||||
/// 1 = fast/tight window). Opens mid-range.
|
||||
/// </summary>
|
||||
public const double DefaultBubblyness = 0.2;
|
||||
public const double DefaultScrollSpeed = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// Default HEAT dial (R2 temp; was detach). Mirrors <c>DEFAULT_DETACH</c> in MixVisualizer.ts.
|
||||
/// Normalized [0,1]; 0 = wax rests at the bottom (collision-only), 1 = lots of small turbulent
|
||||
/// bubbles. Tuned to Daniel's ~100% sweet spot.
|
||||
/// Default gradient-rotation-speed dial. Mirrors <c>DEFAULT_GRADIENT_ROTATION_SPEED</c> in
|
||||
/// MixVisualizer.ts. Normalized [0,1] → slow→fast anchor-rotation. INERT until Wave R3 builds the
|
||||
/// OKLab three-colour gradient that consumes it.
|
||||
/// </summary>
|
||||
public const double DefaultDetach = 1.0;
|
||||
public const double DefaultGradientRotationSpeed = 0.3;
|
||||
|
||||
/// <summary>
|
||||
/// Default COLLISION-STRENGTH dial (R2 temp; was color-shift). Mirrors
|
||||
/// <c>DEFAULT_COLOR_SHIFT_SPEED</c> in MixVisualizer.ts. Normalized [0,1]; 0 = soft mush,
|
||||
/// 1 = hard elastic throw.
|
||||
/// Default lava-gravity dial. Mirrors <c>DEFAULT_LAVA_GRAVITY</c> in MixVisualizer.ts. Normalized
|
||||
/// [0,1]; 0 = near-weightless float, 1 = wax falls + settles fast. Tuned to Daniel's ~20% sweet spot.
|
||||
/// </summary>
|
||||
public const double DefaultColorShiftSpeed = 0.5;
|
||||
public const double DefaultLavaGravity = 0.2;
|
||||
|
||||
/// <summary>
|
||||
/// Default WAVEFORM-WIDTH dial (R2 temp; routed to the resolution/zoom knob this wave). Mirrors
|
||||
/// <c>DEFAULT_WAVEFORM_WIDTH</c> in MixVisualizer.ts. Normalized [0,1]; 1 = full ribbon width
|
||||
/// (prior look), lower narrows the band so the lava gets more room. Opens at full width.
|
||||
/// Default lava-heat dial. Mirrors <c>DEFAULT_LAVA_HEAT</c> in MixVisualizer.ts. Normalized [0,1];
|
||||
/// 0 = wax rests at the bottom (collision-only), 1 = many small turbulent rising bubbles. Tuned to
|
||||
/// Daniel's ~100% sweet spot.
|
||||
/// </summary>
|
||||
public const double DefaultWaveformWidth = 1.0;
|
||||
|
||||
/// <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;
|
||||
public const double DefaultLavaHeat = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// Waveform width, normalized [0,1]. R2 TEMP: routed to the resolution/zoom knob for in-browser
|
||||
/// testing (Wave R4 gives it its own knob and restores the resolution knob to VisibleSeconds).
|
||||
/// Default blob-density dial. Mirrors <c>DEFAULT_BLOB_DENSITY</c> in MixVisualizer.ts. Normalized
|
||||
/// [0,1]; 0 = a few large lazy blobs, 1 = many smaller active blobs.
|
||||
/// </summary>
|
||||
public const double DefaultBlobDensity = 0.4;
|
||||
|
||||
/// <summary>
|
||||
/// Default collision-strength dial. Mirrors <c>DEFAULT_COLLISION_STRENGTH</c> in MixVisualizer.ts.
|
||||
/// Normalized [0,1]; 0 = soft mush, 1 = hard elastic up-and-out throw.
|
||||
/// </summary>
|
||||
public const double DefaultCollisionStrength = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// Default waveform-width dial. Mirrors <c>DEFAULT_WAVEFORM_WIDTH</c> in MixVisualizer.ts.
|
||||
/// Normalized [0,1]; 1 = full ribbon width, lower narrows the band so the lava gets more room.
|
||||
/// </summary>
|
||||
public const double DefaultWaveformWidth = 0.6;
|
||||
|
||||
/// <summary>Apparent bottom-to-top scroll rate, normalized [0,1]. Bridge maps it to a visible
|
||||
/// time-span via <see cref="MixZoomMapping"/>; the standalone resolution/zoom control is gone.</summary>
|
||||
public double ScrollSpeed { get; set; } = DefaultScrollSpeed;
|
||||
|
||||
/// <summary>Gradient anchor-rotation rate, normalized [0,1]. Inert until Wave R3 consumes it.</summary>
|
||||
public double GradientRotationSpeed { get; set; } = DefaultGradientRotationSpeed;
|
||||
|
||||
/// <summary>Downward force on the wax, normalized [0,1].</summary>
|
||||
public double LavaGravity { get; set; } = DefaultLavaGravity;
|
||||
|
||||
/// <summary>Energy into the lava system, normalized [0,1]. 0 = rest-at-bottom, 1 = roiling.</summary>
|
||||
public double LavaHeat { get; set; } = DefaultLavaHeat;
|
||||
|
||||
/// <summary>Amount of wax (blob count/size), normalized [0,1].</summary>
|
||||
public double BlobDensity { get; set; } = DefaultBlobDensity;
|
||||
|
||||
/// <summary>Collision hardness, normalized [0,1]. 0 = soft mush, 1 = hard up-and-out throw.</summary>
|
||||
public double CollisionStrength { get; set; } = DefaultCollisionStrength;
|
||||
|
||||
/// <summary>Waveform-band horizontal extent, normalized [0,1]. Narrowing clears room for the lava.</summary>
|
||||
public double WaveformWidth { get; set; } = DefaultWaveformWidth;
|
||||
|
||||
/// <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.
|
||||
/// affected dial(s). Mutators set the property then raise this; subscribers re-read the values.
|
||||
/// </summary>
|
||||
public event Action? Changed;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user