Phase S FB1 (r11): Sample-view recomposition — knob deck + elastic full-width hero + curve popup w/ right-click delete + post-mixer master gain (ComponentState v8)
This commit is contained in:
@@ -33,7 +33,8 @@
|
||||
#include "editor_geometry.h" // Rect (the shell's sub-rect type, shared with the pure modules)
|
||||
#include "envelope_edit.h" // EnvClampBounds / NodeHit (S-VIEW-3 envelope node hit-test/edit)
|
||||
#include "envelope_overlay.h" // AmpEnvelope / EnvNode (S-VIEW-3 envelope overlay draw seam)
|
||||
#include "param_slider.h" // ControlRow (the S12/S15/S16 control-surface geometry)
|
||||
#include "knob_deck.h" // DeckGroupDesc / DeckLayout (r11 Sample-face knob deck, FB1)
|
||||
#include "param_slider.h" // ControlRow + the FA4 radial-knob primitive (S12/S15/S16 + r11)
|
||||
#include "peaks.h" // Envelope (the cached peak thumbnail)
|
||||
#include "sample_map.h" // SampleChoice, BankChoice, PerformanceMap (the shell's snapshot)
|
||||
#include "velocity_curve.h" // VelocityCurve (S-VIEW-10 transfer-curve editor state)
|
||||
@@ -80,9 +81,11 @@ private:
|
||||
// marker on the S11 waveform surface (which marker is in waveMarker_); kEnvNode is a
|
||||
// draggable envelope breakpoint on the Sample-view hero overlay (S-VIEW-3, which node in
|
||||
// envNode_); kCurveNode is a draggable velocity-curve control point in the S-VIEW-10
|
||||
// transfer-curve editor (which point in curvePointIndex_).
|
||||
// transfer-curve editor (which point in curvePointIndex_); kDeckKnob is a GRAB-ANCHORED
|
||||
// vertical radial-knob drag on the r11 Sample-face deck/cluster (which control in
|
||||
// dragParamId_; the value at grab in dragKnobStartValue_ — no jump on grab, FA4).
|
||||
enum class DragKind { kNone, kRootMarker, kZoneLow, kZoneHigh, kZoneBody, kWaveMarker,
|
||||
kScrollThumb, kParamSlider, kEnvNode, kCurveNode };
|
||||
kScrollThumb, kParamSlider, kEnvNode, kCurveNode, kDeckKnob };
|
||||
|
||||
// The parameter controls on the setup surface (S12 AHDSR + the S15/S16 control surfaces).
|
||||
// The int value is the ControlDesc id the pure param_slider hit-test returns; the shell
|
||||
@@ -103,6 +106,12 @@ private:
|
||||
kPitchEnvDecay, // AD pitch decay (S16)
|
||||
kPitchEnvDepth, // AD pitch depth in +/- semitones (S16)
|
||||
kKeyTrack, // S-VIEW-6 key-tracking 0..200% (lives on PerformanceZone, not ZonePlaySeconds)
|
||||
// r11 deck-only controls (FB1): processor-side per-instance params, NOT zone params —
|
||||
// routed to the processor setters, never through applyZoneControl / the map.
|
||||
kVoiceCount, // Phase S polyphony bound (1..32) — a stepped knob in the VOICE group
|
||||
kVoiceMode, // Poly | Mono caption toggle (VOICE group)
|
||||
kMonoTrigger, // Retrig | Legato row toggle (VOICE group; live only in Mono)
|
||||
kMasterGain, // FB1 post-mixer master gain knob (-inf..+24 dB taper, MASTER group)
|
||||
kCount
|
||||
};
|
||||
|
||||
@@ -134,8 +143,11 @@ private:
|
||||
kPreview, // the Sample-view preview-trigger button
|
||||
kAddZone, // the "+ Add Zone" button
|
||||
kDeleteZone, // the "Delete" zone button
|
||||
kControl, // a param-panel control row (index = ControlDesc id)
|
||||
kControl, // a param-panel control row / deck element (index = control id)
|
||||
kCurveNode, // a velocity-curve control point (index = point index, S-VIEW-10)
|
||||
kVelKnob, // the cluster preview-velocity radial knob (r11)
|
||||
kCurveButton, // the cluster mini curve-preview button (r11 — opens the popup)
|
||||
kPopupClose, // the curve popup's Close (x) button (r11)
|
||||
};
|
||||
struct HoverTarget {
|
||||
HoverKind kind = HoverKind::kNone;
|
||||
@@ -146,11 +158,19 @@ private:
|
||||
|
||||
#ifdef _WIN32
|
||||
void paint(HDC hdc);
|
||||
void paintSample(LICE_IBitmap* bmp, int w, int h); // S-VIEW-2 home face
|
||||
void paintSample(LICE_IBitmap* bmp, int w, int h); // S-VIEW-2/r11 home face
|
||||
void paintBrowse(LICE_IBitmap* bmp, int w, int h); // S-VIEW-5 modal picker overlay
|
||||
void paintZone(LICE_IBitmap* bmp, int w, int h); // S-VIEW-8 zone surface
|
||||
void paintEmptyState(LICE_IBitmap* bmp, const Rect& area);
|
||||
void paintControls(LICE_IBitmap* bmp, const Rect& panel, const PerformanceZone& zone); // S12/S15/S16 + keyTrack
|
||||
void paintControls(LICE_IBitmap* bmp, const Rect& panel, const PerformanceZone& zone); // S12/S15/S16 + keyTrack (Zone surface; the Sample face uses the r11 knob deck)
|
||||
|
||||
// --- r11 Sample-face recomposition (FB1) ---------------------------------------
|
||||
// The knob deck: the fenced task groups (AMP ENVELOPE / PITCH / PITCH ENV / VOICE /
|
||||
// MASTER) drawn through the L1 kit — group fence + caption + compact caption toggles +
|
||||
// radial knobs (param_slider's FA4 primitive) with label<->value swap on hover/drag.
|
||||
void paintKnobDeck(LICE_IBitmap* bmp, const Rect& deckArea, const PerformanceZone& zone);
|
||||
// The centered curve-popup sheet (wash + title + close + full-size curve editor).
|
||||
void paintCurvePopup(LICE_IBitmap* bmp, int w, int h);
|
||||
// Trace the S-VIEW-3 amp-envelope overlay + its draggable node handles over `waveArea` for
|
||||
// `zone`'s play params, at the sample's wall-clock duration. Shared by the Sample hero band.
|
||||
void paintEnvelopeOverlay(LICE_IBitmap* bmp, const Rect& waveArea, const PerformanceZone& zone,
|
||||
@@ -170,6 +190,11 @@ private:
|
||||
void onMouseDown(int x, int y);
|
||||
void onMouseMove(int x, int y);
|
||||
void onMouseUp(int x, int y);
|
||||
// r11: right-click — the curve popup's PRIMARY node-delete affordance (issue 3c). Only
|
||||
// acts while the popup is open; a right-click on a popup curve node deletes it through
|
||||
// the same commit path as Alt-click (deletePoint's endpoint guard makes endpoint
|
||||
// right-clicks a safe no-op). Everything else ignores right-clicks.
|
||||
void onMouseRDown(int x, int y);
|
||||
|
||||
// Route a click at (x,y) into the param control panel `panel` editing map_.zones[zoneIndex]:
|
||||
// a toggle segment commits immediately, a slider grab starts a live param-drag (kParamSlider),
|
||||
@@ -337,6 +362,37 @@ private:
|
||||
// needs a concrete zone to write. Returns -1 if selectedId_ is empty.
|
||||
int ensureSampleZone();
|
||||
|
||||
// --- r11 knob-deck plumbing (FB1) ---------------------------------------------
|
||||
//
|
||||
// The deck is the r11 replacement for the Sample face's slider control strip: the pure
|
||||
// knob_deck module lays out the fenced groups, param_slider's FA4 primitive owns the
|
||||
// value<->needle map, and these members own the control-id <-> value binding (the same
|
||||
// division of labor paintControls/applyControl use for the Zone surface's sliders).
|
||||
|
||||
// The deck group descriptors for the current mode: AMP ENVELOPE (Gate: A/H/D/S/R;
|
||||
// Trigger: Fade In / Length % / Fade Out + two RESERVED blanks so a mode flip never
|
||||
// reflows the neighbours) / PITCH (Key Track) / PITCH ENV (P.Attack/P.Decay/P.Depth) /
|
||||
// VOICE (Voices knob + Poly|Mono caption toggle + Retrig|Legato row toggle) / MASTER
|
||||
// (the FB1 post-mixer Gain knob).
|
||||
std::vector<DeckGroupDesc> deckGroupDescs(const ZonePlaySeconds& play) const;
|
||||
|
||||
// The normalized [0,1] value a deck knob shows for `zone` — zone params route through
|
||||
// controlValue/keyTrack; the processor-side ids (voice count, master gain, and the
|
||||
// cluster's preview velocity via the -2 sentinel) read the processor's live value, so
|
||||
// the knob and its storage are two views on one model (re-read each paint).
|
||||
double deckControlNorm(int id, const PerformanceZone& zone) const;
|
||||
|
||||
// Apply a deck-knob value: zone params write map_.zones[zoneIndex] (live-drag semantics,
|
||||
// commit on release); processor params (voice count / master gain / preview velocity)
|
||||
// write through the processor setters immediately (transient — no map edit, no reload).
|
||||
// zoneIndex is ignored for processor-side ids.
|
||||
void applyDeckKnob(int zoneIndex, int id, double norm);
|
||||
|
||||
// The knob's live value label (shown in place of the name label during hover/drag):
|
||||
// seconds ("0.123s"), percents ("85%"), source frames ("8820f"), signed semitones
|
||||
// ("+3.5st"), a voice count ("16"), or the master-gain dB ("-inf"/"+2.4dB").
|
||||
std::string deckValueLabel(int id, const PerformanceZone& zone) const;
|
||||
|
||||
ReaSamplerProcessor* processor_ = nullptr;
|
||||
|
||||
// --- Snapshot of the live bank (drawn each paint; refreshed off the audio thread) ---
|
||||
@@ -444,6 +500,15 @@ private:
|
||||
Rect dragCurveRect_{};
|
||||
int dragCurveZone_ = -1;
|
||||
|
||||
// r11 deck-knob drag (FB1): the control's normalized value AT GRAB — knobDragValue maps
|
||||
// the vertical pixel delta from this anchor, so a grab never jumps the value (FA4).
|
||||
double dragKnobStartValue_ = 0.0;
|
||||
|
||||
// r11 curve popup (FB1): open flag — editor-local, never persisted. The popup edits the
|
||||
// picked capture's one-zone site (effectiveSampleZone / ensureSampleZone), re-resolved
|
||||
// each paint so a sync-tick refresh mid-open stays coherent.
|
||||
bool curvePopupOpen_ = false;
|
||||
|
||||
// --- Peak-thumbnail cache (mirror of bank_panel; id -> envelope at a bin width) ------
|
||||
// Keyed by "id|binCount" so a resize recomputes at the new width. Cleared on refresh so
|
||||
// a bank edit (a re-captured or deleted sample) does not show a stale thumbnail.
|
||||
|
||||
Reference in New Issue
Block a user