docs(phase-10-reframe): fold Wave R2 eval into lava spec + PLAN (7th control, flat coalescing fluid, up-and-out collision)
This commit is contained in:
@@ -207,15 +207,17 @@ A **major reframe of the Mix visualizer's effects, controls, and color model**,
|
|||||||
**This supersedes the original Phase 10 (Waves 1–4) effects/controls/color design** — `product-notes/mix-visualizer-webgl-renderer.md` §4 (effects) and §7 (popover-controls) are marked superseded with a pointer to the reframe spec. The renderer *infrastructure* carries forward unchanged.
|
**This supersedes the original Phase 10 (Waves 1–4) effects/controls/color design** — `product-notes/mix-visualizer-webgl-renderer.md` §4 (effects) and §7 (popover-controls) are marked superseded with a pointer to the reframe spec. The renderer *infrastructure* carries forward unchanged.
|
||||||
|
|
||||||
**The three reframes:**
|
**The three reframes:**
|
||||||
- **Lava → CPU-physics wax blobs.** Keep the single-pass WebGL2 fragment renderer; add a small CPU-side per-frame physics step modeling ~16–32 Lagrangian "wax blobs" (position/velocity/temperature/radius) uploaded as uniforms and blended with `smin` SDF metaballs. The waveform and lava share **the same plane WITH real 2D elastic collision** (blob↔waveform-boundary + blob↔blob) — the waveform pushes the fluid out of its way (read-only authority preserved; the fluid never deforms the waveform). At heat 0 the wax rests at the bottom and only collision moves it (collision always on, independent of heat); at heat max many bubbles rise/morph per second. **Rejected: a full ping-pong FBO Navier-Stokes fluid sim** — a lava lamp is high-viscosity/low-turbulence, the opposite regime; large rewrite for unwanted realism. Deliberate later upgrade only.
|
- **Lava → CPU-physics wax blobs.** Keep the single-pass WebGL2 fragment renderer; add a small CPU-side per-frame physics step modeling ~16–32 Lagrangian "wax blobs" (position/velocity/temperature/radius) uploaded as uniforms and blended with `smin` SDF metaballs. The waveform and lava share **the same plane WITH real 2D elastic collision** (blob↔waveform-boundary + blob↔blob) — the waveform pushes the fluid out of its way (read-only authority preserved; the fluid never deforms the waveform). **Refined by Daniel's Wave R2 eval:** the fluid must read **flat** (an evenly-lit unified body, NOT blobs with bright pointed centers / cone-like radial gradients) and **melt into one fluid** (low viscosity / strong coalescence — "behave more like a fluid," not stiff globs in contact; the slow wax-like *motion* damping and the freely-coalescing *surface* are independent). **Energy-coupled dynamics:** higher heat/energy → **smaller bubbles + more turbulence** (many small lively turbulent bubbles at high heat; fewer, larger, calmer wax at low heat) — the lamp should feel dynamic and fun. At heat 0 the wax rests on the floor and only collision moves it (collision always on, independent of heat); at heat max many small turbulent bubbles rise/morph per second. **Tuning anchor: Daniel's sweet spot is ~20% gravity / ~100% heat** — calibrate defaults/ranges so that combination lands lively. **Rejected: a full ping-pong FBO Navier-Stokes fluid sim** — a lava lamp is high-viscosity/low-turbulence, the opposite regime; large rewrite for unwanted realism. Deliberate later upgrade only.
|
||||||
- **Color → three-color OKLab gradient with three motions.** One source of truth (`DeepDrftPalettes`), no hardcoded hexes. Always A→B linear from the center line outward. Three combined motions: (1) anchors A/B **rotate among three theme colors X/Y/Z** at the rotation-speed control's rate — **OKLab interpolation, never through the rainbow** (the cyan fix is structural, not a tuning dial); (2) per-bar sinusoidal variation **baked at segment entry and fixed as the segment scrolls** — realized by **keying the sinusoid to mix-time** so it travels with the segment by construction (decided 2026-06-16; the explicit ring-buffer alternative is rejected for maintainability); (3) per-bar gradient curve shifts with scroll height (mostly A at bottom → mostly B at top). The static noise/frost texture is **removed** (Daniel: makes the screen look dirty).
|
- **Color → three-color OKLab gradient with three motions.** One source of truth (`DeepDrftPalettes`), no hardcoded hexes. Always A→B linear from the center line outward. Three combined motions: (1) anchors A/B **rotate among three theme colors X/Y/Z** at the rotation-speed control's rate — **OKLab interpolation, never through the rainbow** (the cyan fix is structural, not a tuning dial); (2) per-bar sinusoidal variation **baked at segment entry and fixed as the segment scrolls** — realized by **keying the sinusoid to mix-time** so it travels with the segment by construction (decided 2026-06-16; the explicit ring-buffer alternative is rejected for maintainability); (3) per-bar gradient curve shifts with scroll height (mostly A at bottom → mostly B at top). The static noise/frost texture is **removed** (Daniel: makes the screen look dirty).
|
||||||
- **Controls → six knobs in an inline collapse/expand knob-bar.** Replaces the four: (1) waveform scroll speed [replaces resolution/zoom as a standalone control], (2) gradient rotation speed, (3) lava gravity, (4) lava heat, (5) blob density/size, (6) collision strength (soft→hard). **NOT a popover or drawer — an inline collapse/expand knob-bar** (decided 2026-06-16): an `@if`-guarded **animated flex row of the six `RadialKnob`s** living inline in the controls area, expanding/collapsing **in place** (CSS width/opacity/transform transition) so it reads as the controls collapsing/expanding, not a floating surface. The lava-lamp icon button toggles a bound bool — no MudPopover/MudDrawer. Styled to **match the NowPlaying hero aesthetic** (the session-detail hero overlay — translucent dark glass, overlay-label typography, `Color.Secondary`). Also: overflow-clip the visualizer to the **dynamic footer height** (the player bar changes height minimized/expanded) so visuals stop cleanly above it; the clip line is also the lava rest line.
|
- **Controls → seven knobs in an inline collapse/expand knob-bar.** Replaces the four: (1) waveform scroll speed [replaces resolution/zoom as a standalone control], (2) gradient rotation speed, (3) lava gravity, (4) lava heat, (5) blob density/size, (6) collision strength (soft mush→hard up-and-out throw), (7) **waveform width** [added in the Wave R2 eval — narrows the waveform band so the lava fluid has more room to move on loud/busy songs; scales the waveform's amplitude→width mapping and its collision boundary]. **NOT a popover or drawer — an inline collapse/expand knob-bar** (decided 2026-06-16): an `@if`-guarded **animated flex row of the seven `RadialKnob`s** living inline in the controls area, expanding/collapsing **in place** (CSS width/opacity/transform transition) so it reads as the controls collapsing/expanding, not a floating surface. The lava-lamp icon button toggles a bound bool — no MudPopover/MudDrawer. Styled to **match the NowPlaying hero aesthetic** (the session-detail hero overlay — translucent dark glass, overlay-label typography, `Color.Secondary`). Also: overflow-clip the visualizer to the **dynamic footer height** (the player bar changes height minimized/expanded) so visuals stop cleanly above it; the clip line is also the lava rest line.
|
||||||
|
|
||||||
**Plus: redraw the lava-lamp glyph.** The current `DDIcons.LavaLamp` is rejected (Daniel: "form is shit, colors are shit"). Redraw to the classic 1970s silhouette — a wide truncated-cone metal **base**, a bulbous→roundedly-pointed teardrop **glass body**, a small cone **cap** ("offset cones") — with **navy fluid + moss blobs** (the theme's blue+green, faithful to the reference and on-theme) and a neutral/metallic base+cap. Authored in `DeepDrftShared.Client/Common/DDIcons.cs` as inner SVG markup (no `<svg>` wrapper; 24×24 viewBox); body silhouette `currentColor`, the two accent fills are commented literals traced to their `DeepDrftPalettes` source (SVG cannot resolve `var()`).
|
**Plus: redraw the lava-lamp glyph.** The current `DDIcons.LavaLamp` is rejected (Daniel: "form is shit, colors are shit"). Redraw to the classic 1970s silhouette — a wide truncated-cone metal **base**, a bulbous→roundedly-pointed teardrop **glass body**, a small cone **cap** ("offset cones") — with **navy fluid + moss blobs** (the theme's blue+green, faithful to the reference and on-theme) and a neutral/metallic base+cap. Authored in `DeepDrftShared.Client/Common/DDIcons.cs` as inner SVG markup (no `<svg>` wrapper; 24×24 viewBox); body silhouette `currentColor`, the two accent fills are commented literals traced to their `DeepDrftPalettes` source (SVG cannot resolve `var()`).
|
||||||
|
|
||||||
Heat→intensity and collision soft↔hard transfer functions are **staff-engineer tuning tasks** (endpoints fixed in the spec, formulas not). Full design, the wax-blob model, the collision model, the three-motion color model, the inline knob-bar, the icon redraw, observable acceptance criteria, and phasing: `product-notes/phase-10-mix-visualizer-lava-reframe.md`.
|
Heat→intensity and collision soft↔hard transfer functions are **staff-engineer tuning tasks** (endpoints fixed in the spec — heat 0 = wax rests on floor / heat max = many small turbulent rising bubbles; collision soft = gentle mush / hard = high-elasticity up-and-out throw, wide range, smooth/no jitter — formulas not). Full design, the wax-blob model, the collision model, the three-motion color model, the inline knob-bar, the icon redraw, observable acceptance criteria, and phasing: `product-notes/phase-10-mix-visualizer-lava-reframe.md`.
|
||||||
|
|
||||||
**Sequenced as four reframe waves.** `Wave R1 → Wave R2 → (Wave R3 ‖ Wave R4)`. Wave R1 (de-noise + dynamic footer clip + icon redraw) is a cheap unblock for a clean substrate. Wave R2 (wax-blob physics + 2D collision) is the load-bearing prerequisite — prove the lava before the color and the UI. Wave R3 (OKLab three-color gradient, the three motions) and Wave R4 (six controls + NowPlaying-styled inline knob-bar + widened state to six properties + extended bridge handle) both depend on Wave R2 but are independent of each other. **Both prior open Daniel calls are now decided:** controls-UI is an inline collapse/expand knob-bar (not popover/drawer); per-segment color is mix-time-keyed.
|
**Open / undecided (spec §10):** (a) **pause behavior** — whether the lava keeps convecting while audio is *paused* (lamp "always on") vs. the current freeze-on-pause (rAF gated on `isPlaying`) is an **undecided Daniel call**; default to freeze-on-pause until decided, switching is a localized gating change, not a model change. (b) **Future enhancement (deferred, NOT in R1–R4 scope):** a per-control **"auto-modulate" checkbox** that slowly oscillates each knob's value via a low-frequency oscillator so the visualizer drifts on its own — Daniel flagged it as a cool future idea; the knob-bar layout leaves room but nothing builds it now.
|
||||||
|
|
||||||
|
**Sequenced as four reframe waves.** `Wave R1 → Wave R2 → (Wave R3 ‖ Wave R4)`. Wave R1 (de-noise + dynamic footer clip + icon redraw) is a cheap unblock for a clean substrate. Wave R2 (wax-blob physics + 2D collision) is the load-bearing prerequisite — prove the lava before the color and the UI. Wave R3 (OKLab three-color gradient, the three motions) and Wave R4 (seven controls — including the new waveform-width knob — + NowPlaying-styled inline knob-bar + widened state to seven properties + extended bridge handle) both depend on Wave R2 but are independent of each other. **Both prior open Daniel calls are now decided:** controls-UI is an inline collapse/expand knob-bar (not popover/drawer); per-segment color is mix-time-keyed.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ This spec **supersedes** the original Phase 10 effects/controls/color design:
|
|||||||
- `product-notes/mix-visualizer-webgl-renderer.md` **§4 (the four visual effects)** — superseded by
|
- `product-notes/mix-visualizer-webgl-renderer.md` **§4 (the four visual effects)** — superseded by
|
||||||
§3–§6 here.
|
§3–§6 here.
|
||||||
- `product-notes/mix-visualizer-webgl-renderer.md` **§7 (Wave 4 popover-controls rework)** — superseded
|
- `product-notes/mix-visualizer-webgl-renderer.md` **§7 (Wave 4 popover-controls rework)** — superseded
|
||||||
by §7 here (the trigger and the widened body are kept; the four-knob popover becomes a six-knob
|
by §7 here (the trigger and the widened body are kept; the four-knob popover becomes a seven-knob
|
||||||
inline collapse/expand knob-bar — see §7).
|
inline collapse/expand knob-bar — see §7).
|
||||||
|
|
||||||
What carries forward unchanged from Phase 10's landed waves (do **not** re-derive — reference it):
|
What carries forward unchanged from Phase 10's landed waves (do **not** re-derive — reference it):
|
||||||
@@ -60,9 +60,9 @@ Cross-references (read these before implementing):
|
|||||||
geometry, the datum texture, and the playhead machinery are reused; the §4-effect GLSL (the bubble
|
geometry, the datum texture, and the playhead machinery are reused; the §4-effect GLSL (the bubble
|
||||||
SDF, the detach blobs, the HSL `mixHsl`/`vivify` color, the glass) is the part being replaced.
|
SDF, the detach blobs, the HSL `mixHsl`/`vivify` color, the glass) is the part being replaced.
|
||||||
- `DeepDrftPublic.Client/Controls/MixVisualizerControls.razor[.cs]` — the four-knob control component;
|
- `DeepDrftPublic.Client/Controls/MixVisualizerControls.razor[.cs]` — the four-knob control component;
|
||||||
becomes six knobs in an inline collapse/expand bar (§7).
|
becomes seven knobs in an inline collapse/expand bar (§7).
|
||||||
- `DeepDrftPublic.Client/Services/MixVisualizerControlState.cs` — the scoped four-property state holder;
|
- `DeepDrftPublic.Client/Services/MixVisualizerControlState.cs` — the scoped four-property state holder;
|
||||||
widens to six properties (§7c).
|
widens to seven properties (§7c).
|
||||||
- `DeepDrftPublic.Client/Controls/MixZoomMapping.cs` — reused unchanged for the scroll-speed control.
|
- `DeepDrftPublic.Client/Controls/MixZoomMapping.cs` — reused unchanged for the scroll-speed control.
|
||||||
- `DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor[.cs/.css]` — the bridge. Extend the handle
|
- `DeepDrftPublic.Client/Controls/MixWaveformVisualizer.razor[.cs/.css]` — the bridge. Extend the handle
|
||||||
with the new control setters; the `.css` gains the overflow-clip work (§2).
|
with the new control setters; the `.css` gains the overflow-clip work (§2).
|
||||||
@@ -85,7 +85,7 @@ Cross-references (read these before implementing):
|
|||||||
metaballs in the existing fragment shader, sharing the *same plane* as the waveform **with real 2D
|
metaballs in the existing fragment shader, sharing the *same plane* as the waveform **with real 2D
|
||||||
collision** — the waveform pushes the fluid out of its way. Replace the navy↔moss treatment with a
|
collision** — the waveform pushes the fluid out of its way. Replace the navy↔moss treatment with a
|
||||||
**three-color, OKLab-interpolated, per-segment-baked gradient** that animates along three combined
|
**three-color, OKLab-interpolated, per-segment-baked gradient** that animates along three combined
|
||||||
motions. Replace the four-knob popover with a **six-knob inline collapse/expand knob-bar** styled to
|
motions. Replace the four-knob popover with a **seven-knob inline collapse/expand knob-bar** styled to
|
||||||
match the hero NowPlaying aesthetic. Remove the static noise texture that makes the screen look dirty.
|
match the hero NowPlaying aesthetic. Remove the static noise texture that makes the screen look dirty.
|
||||||
Redraw the lava-lamp trigger glyph to the classic 1970s silhouette (§7f).
|
Redraw the lava-lamp trigger glyph to the classic 1970s silhouette (§7f).
|
||||||
|
|
||||||
@@ -98,8 +98,8 @@ Redraw the lava-lamp trigger glyph to the classic 1970s silhouette (§7f).
|
|||||||
- The **three-color OKLab gradient model** with three combined motions: anchor rotation among X/Y/Z,
|
- The **three-color OKLab gradient model** with three combined motions: anchor rotation among X/Y/Z,
|
||||||
per-segment sinusoidal variation baked at segment entry, and the per-bar curve shift with scroll
|
per-segment sinusoidal variation baked at segment entry, and the per-bar curve shift with scroll
|
||||||
height (§6).
|
height (§6).
|
||||||
- **Six controls** replacing the four: scroll speed, gradient rotation speed, lava gravity, lava heat,
|
- **Seven controls** replacing the four: scroll speed, gradient rotation speed, lava gravity, lava heat,
|
||||||
blob density/size, collision strength (§7).
|
blob density/size, collision strength, waveform width (§7).
|
||||||
- The **inline collapse/expand knob-bar** (replacing the popover) styled to the NowPlaying hero
|
- The **inline collapse/expand knob-bar** (replacing the popover) styled to the NowPlaying hero
|
||||||
aesthetic (§7).
|
aesthetic (§7).
|
||||||
- A **redrawn `DDIcons.LavaLamp`** glyph — classic 1970s lava-lamp silhouette (§7f).
|
- A **redrawn `DDIcons.LavaLamp`** glyph — classic 1970s lava-lamp silhouette (§7f).
|
||||||
@@ -133,7 +133,7 @@ Redraw the lava-lamp trigger glyph to the classic 1970s silhouette (§7f).
|
|||||||
| Color model (HSL navy↔moss) | — | OKLab three-color gradient, 3 motions (§6) |
|
| Color model (HSL navy↔moss) | — | OKLab three-color gradient, 3 motions (§6) |
|
||||||
| Glass treatment | — | folded into the blob shading (§4f); no separate glass dials |
|
| Glass treatment | — | folded into the blob shading (§4f); no separate glass dials |
|
||||||
| Static noise/frost texture | — | **removed** (§3) |
|
| Static noise/frost texture | — | **removed** (§3) |
|
||||||
| Controls (4 knobs, popover) | — | 6 knobs in an inline collapse/expand bar (§7) |
|
| Controls (4 knobs, popover) | — | 7 knobs in an inline collapse/expand bar (§7) |
|
||||||
| Lava-lamp trigger glyph | trigger placement kept | glyph **redrawn** (§7f) |
|
| Lava-lamp trigger glyph | trigger placement kept | glyph **redrawn** (§7f) |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -236,6 +236,23 @@ This fixes "giant disconnected circles": the prior approach had too few scripted
|
|||||||
= 6`) with hash-driven pseudo-motion and no physics, so they read as detached discs. Real physics on
|
= 6`) with hash-driven pseudo-motion and no physics, so they read as detached discs. Real physics on
|
||||||
16–32 blobs with `smin` merging reads as continuous wax that splits and recombines.
|
16–32 blobs with `smin` merging reads as continuous wax that splits and recombines.
|
||||||
|
|
||||||
|
**The fluid must read FLAT, and the blobs must melt into one unified fluid (from Daniel's Wave R2 eval).**
|
||||||
|
Two refinements to the rendered result, both load-bearing:
|
||||||
|
|
||||||
|
- **Flat fluid surface, not bright pointed centers.** The metaball/fluid surface must read **flat** —
|
||||||
|
an evenly-lit fluid body. It must **NOT** read as blobs with bright pointed centers / cone-like radial
|
||||||
|
gradients (a per-blob radial falloff peaking at each center reads as a field of glowing cones, which
|
||||||
|
Daniel rejected). Shade the *composited* surface, not each blob's center: the brightness should be a
|
||||||
|
property of the unified fluid's surface (normal/Fresnel from the SDF, §4f), flat across the body, not a
|
||||||
|
per-blob hotspot.
|
||||||
|
- **Melt into one fluid — low viscosity, strong coalescence.** The blobs must **coalesce into a single
|
||||||
|
unified fluid** rather than reading as distinct stiff globs that merely touch. Bias the `smin` blend
|
||||||
|
radius wide and the inter-blob cohesion high so overlapping/near blobs **melt together** into one
|
||||||
|
continuous body — "behave more like a fluid," not like rigid beads in contact. This trades against the
|
||||||
|
earlier "high-viscosity wax, not water" damping note (§4a integration): keep the *motion* viscous and
|
||||||
|
slow, but make the *surface* coalesce freely. The damping is on velocity (slow, wax-like movement); the
|
||||||
|
coalescence is on the surface field (fluid, unified). They are independent.
|
||||||
|
|
||||||
### 4b. Blob shape — varied, organic, not always circular
|
### 4b. Blob shape — varied, organic, not always circular
|
||||||
|
|
||||||
Blobs range **~20px to ~100px** across and are **not always circular** — they should read as varied,
|
Blobs range **~20px to ~100px** across and are **not always circular** — they should read as varied,
|
||||||
@@ -253,10 +270,31 @@ wax," not "N identical circles."
|
|||||||
**always on, independent of heat** (§5).
|
**always on, independent of heat** (§5).
|
||||||
- At **heat = max**, **many bubbles rise and morph per second** — a busy, actively roiling lamp.
|
- At **heat = max**, **many bubbles rise and morph per second** — a busy, actively roiling lamp.
|
||||||
|
|
||||||
The mapping from the 0..1 heat scalar to effect intensity (rise rate, how many blobs are buoyant at
|
**Energy-coupled dynamics (from Daniel's Wave R2 eval) — heat changes the *character* of the wax, not
|
||||||
once, churn frequency) is a **well-tuned transfer function that staff-engineer owns** — this spec does
|
just the rise rate.** Higher heat/energy → **smaller bubbles + more turbulence**; lower heat → **fewer,
|
||||||
not fix a formula. Note it as a tuning task: the requirement is the *endpoints* (0 = rest-at-bottom,
|
larger, calmer wax**. Concretely:
|
||||||
collision-only; max = many rising/morphing per second) and a smooth, good-feeling sweep between them.
|
|
||||||
|
- **High heat:** lots of **small, lively, turbulent bubbles** — the wax fragments into many small active
|
||||||
|
blobs with visible churn/turbulence. Energetic and busy.
|
||||||
|
- **Low heat:** **fewer, larger, calmer** masses — big lazy wax that mostly rests and drifts.
|
||||||
|
|
||||||
|
So heat couples to *both* buoyancy (rise) *and* the effective blob size/count distribution and the
|
||||||
|
turbulence in the velocity field. (This interacts with the blob density/size control, §4e — heat shifts
|
||||||
|
the wax toward the small-and-many end of whatever the density control sets.) **The visualizer should feel
|
||||||
|
dynamic and fun** — heat is the "liveliness" axis, and the whole point is that turning it up makes the
|
||||||
|
lamp visibly come alive, not merely rise faster.
|
||||||
|
|
||||||
|
The mapping from the 0..1 heat scalar to effect intensity (rise rate, bubble size/count split, churn
|
||||||
|
frequency, turbulence) is a **well-tuned transfer function that staff-engineer owns** — this spec does
|
||||||
|
not fix a formula. Note it as a tuning task: the requirement is the *endpoints* (0 = wax rests on the
|
||||||
|
floor, collision-only; max = many small turbulent rising bubbles) and a smooth, good-feeling, dynamic
|
||||||
|
sweep between them.
|
||||||
|
|
||||||
|
**Tuning reference — Daniel's sweet spot is ~20% gravity / ~100% heat.** Calibrate the defaults and the
|
||||||
|
transfer-function ranges so that this combination lands in a great-feeling, lively state (it is the
|
||||||
|
target the small-turbulent-bubble behavior above is described against). Treat ~20% gravity / ~100% heat
|
||||||
|
as the calibration anchor for where "dynamic and fun" should sit; the ranges should make that reachable
|
||||||
|
and good, not extreme.
|
||||||
|
|
||||||
### 4d. Gravity control
|
### 4d. Gravity control
|
||||||
|
|
||||||
@@ -320,6 +358,16 @@ is a separate phase, not a tuning step.
|
|||||||
Mass can be derived from radius (bigger blob = more mass) so large blobs shove small ones convincingly —
|
Mass can be derived from radius (bigger blob = more mass) so large blobs shove small ones convincingly —
|
||||||
staff-engineer's call; the requirement is *elastic 2D collision on both pairs.*
|
staff-engineer's call; the requirement is *elastic 2D collision on both pairs.*
|
||||||
|
|
||||||
|
**High elasticity, and the throw is UP AND OUT, not just sideways (from Daniel's Wave R2 eval).** The
|
||||||
|
collision is **highly elastic** at the hard end. Critically, when the waveform collides with the wax at
|
||||||
|
high collision strength it must **throw the bubbles UPWARD AND OUTWARD** — the waveform surface impulse
|
||||||
|
has a vertical (lift) component, not merely horizontal displacement. The earlier "pushed out along the
|
||||||
|
waveform's surface normal" framing is too flat: the desired read is the waveform *kicking* the fluid up
|
||||||
|
and away, like a paddle slapping liquid, so the lava springs off it. Staff-engineer composes the impulse
|
||||||
|
so a hard collision imparts both outward (normal) and upward (lift) velocity to the struck blobs.
|
||||||
|
**Collision must be smooth — no jitter** (no per-frame popping/vibration at the boundary; the response
|
||||||
|
must integrate stably even at high elasticity).
|
||||||
|
|
||||||
### 5b. Collision always on, independent of heat
|
### 5b. Collision always on, independent of heat
|
||||||
|
|
||||||
Per §4c: the waveform↔lava collision runs **at all heat levels, including heat = 0.** At rest the
|
Per §4c: the waveform↔lava collision runs **at all heat levels, including heat = 0.** At rest the
|
||||||
@@ -328,18 +376,24 @@ lava feeling like one physical system rather than two layers.
|
|||||||
|
|
||||||
### 5c. Collision strength — soft → hard (the sixth control)
|
### 5c. Collision strength — soft → hard (the sixth control)
|
||||||
|
|
||||||
A **collision strength** control sweeps the interaction from **soft → 100% hard.** It blends between two
|
A **collision strength** control sweeps the interaction from **genuinely soft → 100% hard** across a
|
||||||
behaviors:
|
**wide soft↔hard range** (from Daniel's Wave R2 eval — the soft end must be genuinely soft, not a faint
|
||||||
|
version of hard, and the spread between the two ends should be large and expressive). It blends between
|
||||||
|
two behaviors:
|
||||||
|
|
||||||
- **(a) Hard obstacle:** the waveform is a rigid wall the fluid flows around — full elastic reflection,
|
- **(a) Hard / high-elasticity throw:** the waveform is a near-rigid surface that **throws the wax UP AND
|
||||||
blobs cannot enter the silhouette at all.
|
OUT** — high restitution, the struck blobs spring off the boundary with both outward (normal) and
|
||||||
- **(b) Soft displacement/shove:** the waveform gently pushes the fluid aside — a soft penalty force
|
upward (lift) velocity (§5a). At max it reads as the waveform energetically kicking the lava off it.
|
||||||
proportional to penetration depth, blobs squish against and partially into the boundary before being
|
- **(b) Soft mush:** the waveform gently **mushes** the lava around — a soft penalty force proportional to
|
||||||
eased out.
|
penetration depth, the wax squishes against and partially into the boundary and slowly eases back, with
|
||||||
|
little or no springy throw. At/near min it must be **genuinely soft** — the fluid yields and gently
|
||||||
|
deforms, no kick.
|
||||||
|
|
||||||
The knob blends (b) → (a) as it sweeps 0 → 1. At 0 it is a gentle shove (the fluid yields and slowly
|
The knob blends (b) → (a) as it sweeps 0 → 1: at 0, gentle mushing of the lava (soft, yielding, slow
|
||||||
recovers); at 1 it is a hard wall (crisp reflection, no penetration). The same blend factor can scale the
|
recovery); at 1, a high-elasticity up-and-out throw. The range must be **wide** so the difference between
|
||||||
blob↔blob restitution for consistency (softer overall world at low strength), staff-engineer's call.
|
ends is dramatic, and the sweep must stay **smooth with no jitter** at any setting (§5a). The same blend
|
||||||
|
factor can scale the blob↔blob restitution for consistency (softer overall world at low strength),
|
||||||
|
staff-engineer's call.
|
||||||
|
|
||||||
> **Dropped:** the earlier Phase 10 "bubbles spawn from peaks" idea is **not relevant** to this model —
|
> **Dropped:** the earlier Phase 10 "bubbles spawn from peaks" idea is **not relevant** to this model —
|
||||||
> blobs are a persistent physical population, not spawned-from-the-waveform particles. Do not carry it
|
> blobs are a persistent physical population, not spawned-from-the-waveform particles. Do not carry it
|
||||||
@@ -347,9 +401,13 @@ blob↔blob restitution for consistency (softer overall world at low strength),
|
|||||||
|
|
||||||
### 5d. Transfer functions left to staff-engineer
|
### 5d. Transfer functions left to staff-engineer
|
||||||
|
|
||||||
As with heat (§4c), the exact penetration-penalty curve, restitution coefficients, and the soft↔hard
|
As with heat (§4c), the exact penetration-penalty curve, restitution coefficients, the lift/normal
|
||||||
blend shape are **staff-engineer tuning tasks.** This spec fixes the *model* (two elastic collision
|
impulse split, and the soft↔hard blend shape are **staff-engineer tuning tasks.** This spec fixes the
|
||||||
pairs, a soft↔hard blend on a knob, collision always on) and the *endpoints*, not the constants.
|
*model* (two elastic collision pairs, a wide soft↔hard blend on a knob, collision always on, smooth/no
|
||||||
|
jitter) and the *endpoints* (soft = gentle mush; hard = high-elasticity up-and-out throw), not the
|
||||||
|
constants. The heat transfer-function endpoints are likewise fixed (heat 0 = wax rests on the floor;
|
||||||
|
heat max = many small turbulent rising bubbles) with the ~20% gravity / ~100% heat sweet spot as the
|
||||||
|
calibration anchor (§4c).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -442,18 +500,19 @@ OKLab. Drop the `mixHsl` / `vivify` / `VIVID_*` machinery entirely.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. The six controls + the inline collapse/expand knob-bar
|
## 7. The seven controls + the inline collapse/expand knob-bar
|
||||||
|
|
||||||
### 7a. The six controls (replacing the four)
|
### 7a. The seven controls (replacing the four)
|
||||||
|
|
||||||
| # | Control | What it drives | Range | Replaces |
|
| # | Control | What it drives | Range | Replaces |
|
||||||
|---|---------|----------------|-------|----------|
|
|---|---------|----------------|-------|----------|
|
||||||
| 1 | **Waveform scroll speed** | Apparent bottom-to-top scroll rate (decouples scroll from zoom) | normalized, mapped via `MixZoomMapping` or a new scroll-rate map | the old **resolution/zoom** control — *resolution as a standalone control is gone* |
|
| 1 | **Waveform scroll speed** | Apparent bottom-to-top scroll rate (decouples scroll from zoom) | normalized, mapped via `MixZoomMapping` or a new scroll-rate map | the old **resolution/zoom** control — *resolution as a standalone control is gone* |
|
||||||
| 2 | **Color gradient rotation speed** | Motion 1 anchor-rotation rate among X/Y/Z (§6b) | normalized 0→1 → slow→fast cycle | the old **color-shift speed** |
|
| 2 | **Color gradient rotation speed** | Motion 1 anchor-rotation rate among X/Y/Z (§6b) | normalized 0→1 → slow→fast cycle | the old **color-shift speed** |
|
||||||
| 3 | **Lava gravity** | Downward force on the wax (§4d) | normalized 0→1 | new |
|
| 3 | **Lava gravity** | Downward force on the wax (§4d) | normalized 0→1 | new |
|
||||||
| 4 | **Lava heat** | Energy into the system; 0 = rest-at-bottom, max = many rising/morphing (§4c) | normalized 0→1 | the old **detach**, re-modeled |
|
| 4 | **Lava heat** | Energy into the system; 0 = rest-at-bottom, max = many small turbulent rising bubbles (§4c) | normalized 0→1 | the old **detach**, re-modeled |
|
||||||
| 5 | **Blob density/size** | Amount of wax — count/size within the 16–32 / 20–100px bands (§4e) | normalized 0→1 | new (the old **bubblyness** is gone; bulge is now physical) |
|
| 5 | **Blob density/size** | Amount of wax — count/size within the 16–32 / 20–100px bands (§4e) | normalized 0→1 | new (the old **bubblyness** is gone; bulge is now physical) |
|
||||||
| 6 | **Collision strength** | Soft → 100% hard waveform/blob collision (§5c) | normalized 0→1 → soft→hard | new |
|
| 6 | **Collision strength** | Soft mush → 100% hard up-and-out throw, waveform/blob collision (§5c) | normalized 0→1 → soft→hard | new |
|
||||||
|
| 7 | **Waveform width** | Width of the waveform portion of the visualizer — narrows the waveform band so the lava fluid has more room to move (§7a, below) | normalized 0→1 → narrow→wide | new (added in the Wave R2 eval) |
|
||||||
|
|
||||||
Note the swap: **resolution/zoom as a standalone control is removed — scroll speed replaces it.** The
|
Note the swap: **resolution/zoom as a standalone control is removed — scroll speed replaces it.** The
|
||||||
`MIN_VISIBLE_SECONDS` anchor still exists internally for the datum-density framing, but the user-facing
|
`MIN_VISIBLE_SECONDS` anchor still exists internally for the datum-density framing, but the user-facing
|
||||||
@@ -461,14 +520,24 @@ control is "how fast does it scroll," not "how much do I see." Staff-engineer de
|
|||||||
speed reuses `MixZoomMapping` (treating it as a scroll-rate map) or gets a fresh linear map; either way
|
speed reuses `MixZoomMapping` (treating it as a scroll-rate map) or gets a fresh linear map; either way
|
||||||
keep the log-feel continuity that made the zoom slider feel good.
|
keep the log-feel continuity that made the zoom slider feel good.
|
||||||
|
|
||||||
|
**Control 7 — waveform width (added in the Wave R2 eval).** Adjusts the **width of the waveform portion**
|
||||||
|
of the visualizer — i.e. how much horizontal band the symmetric ±amplitude waveform silhouette occupies.
|
||||||
|
**The point of the control:** on loud/busy songs the waveform is wide and crowds the canvas; narrowing it
|
||||||
|
gives the **lava fluid more room to move**. Low = a narrow waveform band (more room for lava); high = a
|
||||||
|
wide waveform band. Mechanically this scales the waveform's amplitude→screen-width mapping (the half-width
|
||||||
|
the silhouette extends from the center line for a given loudness), which also resizes the collision
|
||||||
|
boundary the fluid parts around (§5) — narrowing the waveform literally clears space for the wax. The
|
||||||
|
datum and scroll geometry are unchanged; only the horizontal extent of the waveform band scales.
|
||||||
|
|
||||||
Defaults are Daniel's to tune on screen (his standing preference — he tunes ranges by hand once it is
|
Defaults are Daniel's to tune on screen (his standing preference — he tunes ranges by hand once it is
|
||||||
live). Recommended starting points: scroll speed ~mid, rotation ~0.3, gravity ~0.5, heat ~0.3, density
|
live). Recommended starting points: scroll speed ~mid, rotation ~0.3, gravity ~0.2, heat ~1.0, density
|
||||||
~0.4, collision ~0.5. These are feel-anchors, not commitments.
|
~0.4, collision ~0.5, width ~0.6. The **~20% gravity / ~100% heat** anchor reflects Daniel's stated sweet
|
||||||
|
spot (§4c). These are feel-anchors, not commitments.
|
||||||
|
|
||||||
### 7b. The inline collapse/expand knob-bar (decided — NOT a popover or drawer)
|
### 7b. The inline collapse/expand knob-bar (decided — NOT a popover or drawer)
|
||||||
|
|
||||||
**Decision (Daniel, 2026-06-16): the controls are an inline collapse/expand knob-bar, NOT a floating
|
**Decision (Daniel, 2026-06-16): the controls are an inline collapse/expand knob-bar, NOT a floating
|
||||||
popover or a drawer.** The six RadialKnobs live **inline in the controls area** (where the controls sit
|
popover or a drawer.** The seven RadialKnobs live **inline in the controls area** (where the controls sit
|
||||||
today) as an **`@if`-guarded flex row** that **animates open and closed in place**. It must read as
|
today) as an **`@if`-guarded flex row** that **animates open and closed in place**. It must read as
|
||||||
**part of the controls collapsing/expanding** — the knob row expanding out from its predecessor — **not**
|
**part of the controls collapsing/expanding** — the knob row expanding out from its predecessor — **not**
|
||||||
a separate surface hanging off the icon.
|
a separate surface hanging off the icon.
|
||||||
@@ -478,9 +547,10 @@ a separate surface hanging off the icon.
|
|||||||
- A **bound `bool`** (e.g. `_controlsExpanded`) gates the knob row. The **lava-lamp icon button toggles
|
- A **bound `bool`** (e.g. `_controlsExpanded`) gates the knob row. The **lava-lamp icon button toggles
|
||||||
it** — the same `DDIcons.LavaLamp` trigger kept from Phase 10 §7c, now redrawn (§7f), now a
|
it** — the same `DDIcons.LavaLamp` trigger kept from Phase 10 §7c, now redrawn (§7f), now a
|
||||||
collapse/expand toggle instead of a popover anchor.
|
collapse/expand toggle instead of a popover anchor.
|
||||||
- When toggled open, the flex row of six knobs **animates open** via **CSS transition** — width / opacity
|
- When toggled open, the flex row of seven knobs **animates open** via **CSS transition** — width / opacity
|
||||||
/ transform — **expanding out from the icon / its predecessor element**, so it reads as the controls
|
/ transform — **expanding out from the icon / its predecessor element**, so it reads as the controls
|
||||||
growing in place. When toggled closed it collapses back the same way.
|
growing in place. When toggled closed it collapses back the same way. (Seven knobs is wider than six —
|
||||||
|
see the wrap note below.)
|
||||||
- **Animation intent:** a smooth in-place expansion (expand-from-icon / slide-open flex row), reading as
|
- **Animation intent:** a smooth in-place expansion (expand-from-icon / slide-open flex row), reading as
|
||||||
one continuous collapse/expand of the controls area — not a panel popping into existence over the page.
|
one continuous collapse/expand of the controls area — not a panel popping into existence over the page.
|
||||||
Use the codebase's existing transition vocabulary (the existing controls/transition CSS) so the motion
|
Use the codebase's existing transition vocabulary (the existing controls/transition CSS) so the motion
|
||||||
@@ -491,36 +561,37 @@ a separate surface hanging off the icon.
|
|||||||
|
|
||||||
**Why this over the Phase 10 popover.** The popover read as a detached panel hanging off the icon; Daniel
|
**Why this over the Phase 10 popover.** The popover read as a detached panel hanging off the icon; Daniel
|
||||||
wants the controls to *be* the controls — collapsing and expanding in place. The inline animated flex row
|
wants the controls to *be* the controls — collapsing and expanding in place. The inline animated flex row
|
||||||
keeps the six knobs in the page's flow, makes the open/close a property of the controls themselves, and
|
keeps the seven knobs in the page's flow, makes the open/close a property of the controls themselves, and
|
||||||
avoids the popover/drawer overlay machinery entirely. (Prior-art touchstone: an inline "expand for
|
avoids the popover/drawer overlay machinery entirely. (Prior-art touchstone: an inline "expand for
|
||||||
advanced settings" disclosure row — e.g. a toolbar that grows a secondary row of controls in place —
|
advanced settings" disclosure row — e.g. a toolbar that grows a secondary row of controls in place —
|
||||||
rather than a flyout/menu.)
|
rather than a flyout/menu.)
|
||||||
|
|
||||||
**Layout note.** Six knobs in a flex row may wrap on narrow viewports (2×3 / 3×2) — a layout call, but
|
**Layout note.** Seven knobs in a flex row may wrap on narrow viewports (e.g. 4×3 / 3×4 / 2-row) — a
|
||||||
all six must remain reachable, and the wrap must still read as part of the inline collapse/expand (the
|
layout call, but all seven must remain reachable, and the wrap must still read as part of the inline
|
||||||
whole block grows/shrinks), not as a separate surface.
|
collapse/expand (the whole block grows/shrinks), not as a separate surface.
|
||||||
|
|
||||||
### 7c. State — widen to six properties
|
### 7c. State — widen to seven properties
|
||||||
|
|
||||||
Widen `MixVisualizerControlState` from four properties to **six**: `ScrollSpeed` (replacing
|
Widen `MixVisualizerControlState` from four properties to **seven**: `ScrollSpeed` (replacing
|
||||||
`VisibleSeconds` as the user-facing axis, or keep `VisibleSeconds` internally and add a `ScrollSpeed`
|
`VisibleSeconds` as the user-facing axis, or keep `VisibleSeconds` internally and add a `ScrollSpeed`
|
||||||
that maps to it — staff-engineer's call), `GradientRotationSpeed` (rename of `ColorShiftSpeed`),
|
that maps to it — staff-engineer's call), `GradientRotationSpeed` (rename of `ColorShiftSpeed`),
|
||||||
`LavaGravity`, `LavaHeat` (re-modeled from `Detach`), `BlobDensity`, `CollisionStrength`. Each with a
|
`LavaGravity`, `LavaHeat` (re-modeled from `Detach`), `BlobDensity`, `CollisionStrength`, and
|
||||||
`const` default mirrored to the TS tuning anchors (keep the C#↔TS default-sync discipline the existing
|
`WaveformWidth` (the seventh, added in the Wave R2 eval — drives the waveform-band horizontal extent,
|
||||||
`Default*` consts have). Same scoped-DI persistence model: survives SPA nav within a session, resets on
|
§7a). Each with a `const` default mirrored to the TS tuning anchors (keep the C#↔TS default-sync
|
||||||
fresh load. Same `Changed` event seam — the bridge subscribes and pushes the affected uniform; the
|
discipline the existing `Default*` consts have). Same scoped-DI persistence model: survives SPA nav
|
||||||
knob-bar component only mutates state and raises `Changed`. **This is the same architecture as today, just
|
within a session, resets on fresh load. Same `Changed` event seam — the bridge subscribes and pushes the
|
||||||
six properties instead of four.**
|
affected uniform; the knob-bar component only mutates state and raises `Changed`. **This is the same
|
||||||
|
architecture as today, just seven properties instead of four.**
|
||||||
|
|
||||||
The bridge handle gains setters for the new controls (`setScrollSpeed`, `setGradientRotationSpeed`,
|
The bridge handle gains setters for the new controls (`setScrollSpeed`, `setGradientRotationSpeed`,
|
||||||
`setLavaGravity`, `setLavaHeat`, `setBlobDensity`, `setCollisionStrength`) — extend, don't redesign,
|
`setLavaGravity`, `setLavaHeat`, `setBlobDensity`, `setCollisionStrength`, `setWaveformWidth`) — extend,
|
||||||
mirroring how Phase 10 §2d extended the handle.
|
don't redesign, mirroring how Phase 10 §2d extended the handle.
|
||||||
|
|
||||||
### 7d. RadialKnob — consumed unchanged, six instead of four
|
### 7d. RadialKnob — consumed unchanged, seven instead of four
|
||||||
|
|
||||||
`RadialKnob` (`DeepDrftShared.Client/Components/RadialKnob.razor`) is consumed as-is (its API is fixed —
|
`RadialKnob` (`DeepDrftShared.Client/Components/RadialKnob.razor`) is consumed as-is (its API is fixed —
|
||||||
`Value`/`ValueChanged`/`Min`/`Max`/`Step`/`Label`/`Size`/`Color`/`HoldValue`; no icon slot; `Label` is
|
`Value`/`ValueChanged`/`Min`/`Max`/`Step`/`Label`/`Size`/`Color`/`HoldValue`; no icon slot; `Label` is
|
||||||
SVG text). Six knobs in the inline bar, each with an adjacent `MudIcon` caption (the no-icon-slot
|
SVG text). Seven knobs in the inline bar, each with an adjacent `MudIcon` caption (the no-icon-slot
|
||||||
constraint from Phase 10 §7e still holds). `HoldValue=false` so they are live. `Step="0.001"` for
|
constraint from Phase 10 §7e still holds). `HoldValue=false` so they are live. `Step="0.001"` for
|
||||||
continuous feel. Suggested Material icons per control (staff-engineer picks final glyphs):
|
continuous feel. Suggested Material icons per control (staff-engineer picks final glyphs):
|
||||||
|
|
||||||
@@ -532,9 +603,10 @@ continuous feel. Suggested Material icons per control (staff-engineer picks fina
|
|||||||
| 4. Lava heat | `LocalFireDepartment` / `Whatshot` |
|
| 4. Lava heat | `LocalFireDepartment` / `Whatshot` |
|
||||||
| 5. Blob density/size | `BubbleChart` / `Grain` |
|
| 5. Blob density/size | `BubbleChart` / `Grain` |
|
||||||
| 6. Collision strength | `Adjust` / `Compress` |
|
| 6. Collision strength | `Adjust` / `Compress` |
|
||||||
|
| 7. Waveform width | `WidthNormal` / `SwapHoriz` / `SettingsEthernet` (a horizontal-extent glyph) |
|
||||||
|
|
||||||
Six knobs in a row may wrap on narrow viewports (2×3 / 3×2) — a layout call, but all six must remain
|
Seven knobs in a row may wrap on narrow viewports (4×3 / 3×4 / two rows) — a layout call, but all seven
|
||||||
reachable.
|
must remain reachable.
|
||||||
|
|
||||||
### 7e. Aesthetic target — match the NowPlaying hero
|
### 7e. Aesthetic target — match the NowPlaying hero
|
||||||
|
|
||||||
@@ -629,58 +701,69 @@ convention, and the theme-alignment discipline — not the exact coordinates.)
|
|||||||
|
|
||||||
**Lava behavior**
|
**Lava behavior**
|
||||||
|
|
||||||
5. **Heat 0 = rest + collision-only.** At heat 0 the wax pools at the rest line and does not rise on its
|
5. **Heat 0 = rest + collision-only.** At heat 0 the wax rests on the floor (pooled at the rest line) and
|
||||||
own; the waveform pushing through it still displaces it (collision always on).
|
does not rise on its own; the waveform pushing through it still displaces it (collision always on).
|
||||||
6. **Heat max = active.** At max heat, many bubbles rise and morph per second — an actively roiling lamp.
|
6. **Heat max = small turbulent bubbles.** At max heat, the wax breaks into **many small, lively,
|
||||||
7. **Blobs.** Blobs read as varied organic wax shapes (not N identical circles), in the ~20–100px range,
|
turbulent bubbles** that rise and morph per second — an actively roiling, fragmented lamp (not a few
|
||||||
|
big masses rising faster). Energy couples to bubble size/count and turbulence, not just rise rate.
|
||||||
|
7. **Flat, unified fluid.** The fluid reads **flat** — an evenly-lit fluid body, **not** blobs with bright
|
||||||
|
pointed centers / cone-like radial gradients. Blobs **melt into one unified fluid** (strong
|
||||||
|
coalescence) rather than distinct stiff globs in contact.
|
||||||
|
8. **Blobs.** Blobs read as varied organic wax shapes (not N identical circles), in the ~20–100px range,
|
||||||
merging and splitting via `smin` — no "giant disconnected circles."
|
merging and splitting via `smin` — no "giant disconnected circles."
|
||||||
8. **Gravity** changes settling/rise behavior independently of heat.
|
9. **Gravity** changes settling/rise behavior independently of heat. At the **~20% gravity / ~100% heat**
|
||||||
9. **Blob density/size** changes how much wax is in the system across its range.
|
sweet spot the lamp reads dynamic, lively, and fun (the calibration anchor, §4c).
|
||||||
|
10. **Blob density/size** changes how much wax is in the system across its range.
|
||||||
|
|
||||||
**Collision**
|
**Collision**
|
||||||
|
|
||||||
10. **Two elastic pairs.** Blob↔waveform and blob↔blob both collide elastically.
|
11. **Two elastic pairs.** Blob↔waveform and blob↔blob both collide elastically.
|
||||||
11. **Collision strength** sweeps soft (fluid yields and recovers) → hard (rigid wall, no penetration)
|
12. **Collision strength — wide soft↔hard sweep.** Sweeps **genuinely soft mush** (the waveform gently
|
||||||
across its range.
|
pushes the lava around; fluid yields and slowly recovers, no springy kick) → **hard up-and-out throw**
|
||||||
|
(high elasticity; the waveform throws the bubbles **upward and outward**, not just sideways). The
|
||||||
|
range is wide/expressive and the response is **smooth — no jitter** at any setting.
|
||||||
|
|
||||||
**Color**
|
**Color**
|
||||||
|
|
||||||
12. **Three-color OKLab gradient.** A→B linear from center outward; no cyan, no rainbow excursion — the
|
13. **Three-color OKLab gradient.** A→B linear from center outward; no cyan, no rainbow excursion — the
|
||||||
blend stays faithful to the theme colors at all rotation phases.
|
blend stays faithful to the theme colors at all rotation phases.
|
||||||
13. **Anchor rotation.** A and B rotate among X/Y/Z over time at the gradient-rotation-speed rate;
|
14. **Anchor rotation.** A and B rotate among X/Y/Z over time at the gradient-rotation-speed rate;
|
||||||
dragging the control visibly changes the rotation rate, never frozen at the slow end.
|
dragging the control visibly changes the rotation rate, never frozen at the slow end.
|
||||||
14. **Per-segment bake (mix-time-keyed).** A segment's colors are fixed when it enters at the bottom and
|
15. **Per-segment bake (mix-time-keyed).** A segment's colors are fixed when it enters at the bottom and
|
||||||
travel with it unchanged as it scrolls up and out — colors do not recompute under a stationary
|
travel with it unchanged as it scrolls up and out — colors do not recompute under a stationary
|
||||||
segment. (Realized via the mix-time-keyed sinusoid, §6b motion 2.)
|
segment. (Realized via the mix-time-keyed sinusoid, §6b motion 2.)
|
||||||
15. **Per-bar curve shift.** A bar is mostly A at the bottom and mostly B by the top — color appears to
|
16. **Per-bar curve shift.** A bar is mostly A at the bottom and mostly B by the top — color appears to
|
||||||
move outward as the bar climbs.
|
move outward as the bar climbs.
|
||||||
16. **One source of truth.** No hardcoded theme hexes in the visualizer; a `DeepDrftPalettes` edit or a
|
17. **One source of truth.** No hardcoded theme hexes in the visualizer; a `DeepDrftPalettes` edit or a
|
||||||
dark-mode toggle re-themes the field live with no duplicate to maintain. (The icon's two accent
|
dark-mode toggle re-themes the field live with no duplicate to maintain. (The icon's two accent
|
||||||
literals are the documented, commented exception — §7f.)
|
literals are the documented, commented exception — §7f.)
|
||||||
|
|
||||||
**Controls / knob-bar**
|
**Controls / knob-bar**
|
||||||
|
|
||||||
17. **Six controls.** Exactly six RadialKnobs — scroll speed, gradient rotation speed, gravity, heat,
|
18. **Seven controls.** Exactly seven RadialKnobs — scroll speed, gradient rotation speed, gravity, heat,
|
||||||
density/size, collision strength — each captioned with an icon; resolution/zoom as a standalone
|
density/size, collision strength, **waveform width** — each captioned with an icon; resolution/zoom as
|
||||||
control is gone.
|
a standalone control is gone.
|
||||||
18. **Inline collapse/expand.** Clicking the lava-lamp icon expands the six-knob flex row **in place**
|
19. **Waveform width.** Dragging the waveform-width control narrows/widens the waveform band across its
|
||||||
|
range; narrowing it visibly clears horizontal space for the lava (and shrinks the collision boundary
|
||||||
|
the fluid parts around). The datum/scroll geometry is otherwise unchanged.
|
||||||
|
20. **Inline collapse/expand.** Clicking the lava-lamp icon expands the seven-knob flex row **in place**
|
||||||
(animated open/closed via CSS transition), reading as the controls collapsing/expanding — **not** a
|
(animated open/closed via CSS transition), reading as the controls collapsing/expanding — **not** a
|
||||||
floating popover or drawer. Clicking again collapses it; dragging a knob does not collapse it.
|
floating popover or drawer. Clicking again collapses it; dragging a knob does not collapse it.
|
||||||
19. **NowPlaying aesthetic.** The knob-bar's surface color + structure match the session hero now-playing
|
21. **NowPlaying aesthetic.** The knob-bar's surface color + structure match the session hero now-playing
|
||||||
overlay (translucent dark glass, overlay-label typography, `Color.Secondary` accents).
|
overlay (translucent dark glass, overlay-label typography, `Color.Secondary` accents).
|
||||||
20. **Persistence + read-only.** All six positions survive SPA nav within a session, reset on fresh
|
22. **Persistence + read-only.** All seven positions survive SPA nav within a session, reset on fresh
|
||||||
load; no control and no knob-bar element is a seek/playback surface; the bridge and read-only contract
|
load; no control and no knob-bar element is a seek/playback surface; the bridge and read-only contract
|
||||||
are intact.
|
are intact.
|
||||||
|
|
||||||
**Icon**
|
**Icon**
|
||||||
|
|
||||||
21. **Redrawn lava-lamp glyph.** The trigger shows the classic 1970s silhouette — wide truncated-cone
|
23. **Redrawn lava-lamp glyph.** The trigger shows the classic 1970s silhouette — wide truncated-cone
|
||||||
base, bulbous→roundedly-pointed teardrop glass body, small cone cap — with navy fluid + moss blobs
|
base, bulbous→roundedly-pointed teardrop glass body, small cone cap — with navy fluid + moss blobs
|
||||||
and a neutral/metallic base+cap; body tints via `currentColor`; renders cleanly at ~24px.
|
and a neutral/metallic base+cap; body tints via `currentColor`; renders cleanly at ~24px.
|
||||||
|
|
||||||
**Performance**
|
**Performance**
|
||||||
|
|
||||||
22. **60 FPS** on a mid-range desktop with heat, density, and collision at non-trivial values
|
24. **60 FPS** on a mid-range desktop with heat, density, and collision at non-trivial values
|
||||||
simultaneously; graceful degrade (drop internal resolution before frames) on weaker/mobile devices.
|
simultaneously; graceful degrade (drop internal resolution before frames) on weaker/mobile devices.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -695,27 +778,30 @@ under the open Phase 10 and distinct from its landed Waves 1–4.**
|
|||||||
Remove the static noise/frost layer (§3), implement the dynamic footer-height clip + lava-rest line
|
Remove the static noise/frost layer (§3), implement the dynamic footer-height clip + lava-rest line
|
||||||
(§2c), and **redraw the `DDIcons.LavaLamp` glyph** (§7f — independent, can land anytime, grouped here as
|
(§2c), and **redraw the `DDIcons.LavaLamp` glyph** (§7f — independent, can land anytime, grouped here as
|
||||||
cheap polish). Small, independent, and gives a clean substrate to build the lava on. **Acceptance:** §8
|
cheap polish). Small, independent, and gives a clean substrate to build the lava on. **Acceptance:** §8
|
||||||
#3, #4, #21.
|
#3, #4, #23.
|
||||||
|
|
||||||
### Wave R2 — The wax-blob physics + collision (the load-bearing step)
|
### Wave R2 — The wax-blob physics + collision (the load-bearing step)
|
||||||
Stand up the CPU physics step (16–32 blobs: position/velocity/temperature/radius), the per-frame uniform
|
Stand up the CPU physics step (16–32 blobs: position/velocity/temperature/radius), the per-frame uniform
|
||||||
upload, the `smin` metaball render, the heat/gravity/density mapping, and the 2D collision model (both
|
upload, the `smin` metaball render (**flat, coalescing fluid** — §4a refinement), the heat/gravity/density
|
||||||
pairs, the soft↔hard blend). This is where the architecture is proven; it replaces the §4-effect GLSL.
|
mapping (**energy-coupled: high heat → small turbulent bubbles** — §4c), and the 2D collision model (both
|
||||||
**Acceptance:** §8 #1, #5–#11, #22 (at this wave's workload). Controls can be temporary sliders/debug
|
pairs, the wide soft-mush ↔ hard up-and-out-throw blend, smooth/no jitter — §5a/§5c). This is where the
|
||||||
knobs here — the real inline knob-bar is Wave R4.
|
architecture is proven; it replaces the §4-effect GLSL. **Acceptance:** §8 #1, #5–#12, #24 (at this wave's
|
||||||
|
workload). Controls can be temporary sliders/debug knobs here — the real inline knob-bar is Wave R4.
|
||||||
|
|
||||||
### Wave R3 — The OKLab three-color gradient (the three motions)
|
### Wave R3 — The OKLab three-color gradient (the three motions)
|
||||||
Replace the HSL `mixHsl`/`vivify` color with OKLab interpolation; implement the three motions (anchor
|
Replace the HSL `mixHsl`/`vivify` color with OKLab interpolation; implement the three motions (anchor
|
||||||
rotation among X/Y/Z, per-segment baked sinusoidal variation **keyed to mix-time**, per-bar curve shift),
|
rotation among X/Y/Z, per-segment baked sinusoidal variation **keyed to mix-time**, per-bar curve shift),
|
||||||
sourced from `DeepDrftPalettes` with no hardcoded duplicates. **Acceptance:** §8 #12–#16. The
|
sourced from `DeepDrftPalettes` with no hardcoded duplicates. **Acceptance:** §8 #13–#17. The
|
||||||
per-segment-bake requirement (§6b motion 2) uses the mix-time-keyed realization so it travels with the
|
per-segment-bake requirement (§6b motion 2) uses the mix-time-keyed realization so it travels with the
|
||||||
segment by construction (decided — §6b).
|
segment by construction (decided — §6b).
|
||||||
|
|
||||||
### Wave R4 — Six controls + the NowPlaying-styled inline knob-bar
|
### Wave R4 — Seven controls + the NowPlaying-styled inline knob-bar
|
||||||
Widen `MixVisualizerControlState` to six properties; replace the four-knob popover with the six-knob
|
Widen `MixVisualizerControlState` to **seven** properties (including the new **waveform width** control,
|
||||||
**inline collapse/expand knob-bar** (§7b — `@if`-guarded animated flex row, lava-lamp icon toggles it, no
|
§7a); replace the four-knob popover with the seven-knob **inline collapse/expand knob-bar** (§7b —
|
||||||
popover/drawer); style it to the session-hero aesthetic; extend the bridge handle with the new setters.
|
`@if`-guarded animated flex row, lava-lamp icon toggles it, no popover/drawer); wire the waveform-width
|
||||||
**Acceptance:** §8 #17–#20.
|
control to scale the waveform-band extent and its collision boundary (§7a); style it to the session-hero
|
||||||
|
aesthetic; extend the bridge handle with the new setters (including `setWaveformWidth`). **Acceptance:**
|
||||||
|
§8 #18–#22.
|
||||||
|
|
||||||
**Dependency shape:** `Wave R1 → Wave R2 → (Wave R3 ‖ Wave R4)`. Wave R1 is a quick unblock (and folds in
|
**Dependency shape:** `Wave R1 → Wave R2 → (Wave R3 ‖ Wave R4)`. Wave R1 is a quick unblock (and folds in
|
||||||
the independent icon redraw). Wave R2 is the prerequisite for everything visual. Waves R3 (color) and R4
|
the independent icon redraw). Wave R2 is the prerequisite for everything visual. Waves R3 (color) and R4
|
||||||
@@ -727,8 +813,9 @@ ranges/transfer-functions by hand once on screen throughout (his standing prefer
|
|||||||
|
|
||||||
## 10. Open items
|
## 10. Open items
|
||||||
|
|
||||||
Tuning knobs only — the controls-UI fork and the per-segment-storage fork are both now **decided** (§7b
|
Tuning knobs, one undecided behavior call, and one deferred future idea — the controls-UI fork and the
|
||||||
inline knob-bar; §6b mix-time-keyed). None block starting Wave R1.
|
per-segment-storage fork are both now **decided** (§7b inline knob-bar; §6b mix-time-keyed). None of the
|
||||||
|
items below block starting Wave R1.
|
||||||
|
|
||||||
- **§4c, §5d — transfer functions:** heat 0..1 → rise/morph intensity; collision 0..1 → soft↔hard blend
|
- **§4c, §5d — transfer functions:** heat 0..1 → rise/morph intensity; collision 0..1 → soft↔hard blend
|
||||||
shape; restitution coefficients; penetration-penalty curve. All staff-engineer tuning tasks with the
|
shape; restitution coefficients; penetration-penalty curve. All staff-engineer tuning tasks with the
|
||||||
@@ -741,4 +828,29 @@ inline knob-bar; §6b mix-time-keyed). None block starting Wave R1.
|
|||||||
(strongest match in the tree) or point to a different component.
|
(strongest match in the tree) or point to a different component.
|
||||||
- **§7f — icon accent literals:** the two literal navy/moss stops the SVG forces (commented to their
|
- **§7f — icon accent literals:** the two literal navy/moss stops the SVG forces (commented to their
|
||||||
`DeepDrftPalettes` source) — exact hexes are staff-engineer's to pull from the palette.
|
`DeepDrftPalettes` source) — exact hexes are staff-engineer's to pull from the palette.
|
||||||
- **Defaults** for all six controls — Daniel tunes on screen.
|
- **§7d — waveform-width icon glyph:** `WidthNormal` / `SwapHoriz` / `SettingsEthernet` suggested;
|
||||||
|
staff-engineer picks the final horizontal-extent glyph.
|
||||||
|
- **Defaults** for all seven controls — Daniel tunes on screen (the ~20% gravity / ~100% heat sweet spot,
|
||||||
|
§4c, anchors the heat/gravity pair).
|
||||||
|
|
||||||
|
### Undecided — Daniel calls (not blocking, but unresolved)
|
||||||
|
|
||||||
|
- **Pause behavior — does the lava keep convecting while audio is paused?** Today the visualizer freezes
|
||||||
|
on pause (the rAF loop is gated on `isPlaying` — Phase 10 §2e, carried forward). The reframe's wax
|
||||||
|
physics raises the question of whether the lava should **keep convecting/bubbling while paused** (the
|
||||||
|
lamp is "always on," the way a real lava lamp keeps going regardless of the music) or **freeze with the
|
||||||
|
scroll** as it does now. **Undecided — Daniel's call.** It affects the rAF-gating rule and whether the
|
||||||
|
physics step runs decoupled from playback. Flagged here; not blocking Wave R1/R2 (default to the current
|
||||||
|
freeze-on-pause behavior until Daniel decides; switching to always-convect is a localized change to the
|
||||||
|
gating, not the model).
|
||||||
|
|
||||||
|
### Future enhancements (explicitly out of the current reframe scope)
|
||||||
|
|
||||||
|
- **Per-control slow LFO auto-modulation.** Each knob could carry an optional **"auto-modulate" checkbox**
|
||||||
|
that, when enabled, gently oscillates that control's value over time via a **low-frequency oscillator**
|
||||||
|
(a slow sinusoid around the knob's set point), so the visualizer drifts and breathes on its own without
|
||||||
|
the user touching it. Daniel flagged this as a "cool future enhancement" (Wave R2 eval). **Deferred — not
|
||||||
|
in the R1–R4 scope.** When picked up it is additive: a per-control bool + amplitude/rate in
|
||||||
|
`MixVisualizerControlState`, an LFO applied at the bridge before the uniform push, and a small checkbox
|
||||||
|
affordance per knob in the inline knob-bar. Captured so the knob-bar's per-control layout (§7b) leaves
|
||||||
|
room for a future toggle, but nothing in R1–R4 builds it.
|
||||||
|
|||||||
Reference in New Issue
Block a user