instrument: one staged-envelope system — per-segment curves, the sustain-less AHD, and a shared overlay for all three envelopes
Trigger's fade pair folds into the AHD (and goes live); the release anchors right; Preserve rings its synthetic tail out instead of cutting it. Payload v10.
This commit is contained in:
@@ -60,11 +60,13 @@ void ReaSamplerEditor::paintDeck(LICE_IBitmap* bmp, const FaceLayout& fl) {
|
||||
case ParamControl::kDecay: return "Decay";
|
||||
case ParamControl::kSustain: return "Sustain";
|
||||
case ParamControl::kRelease: return "Release";
|
||||
case ParamControl::kTrigFadeIn: return "Fade In";
|
||||
case ParamControl::kTrigLength: return "Len %";
|
||||
case ParamControl::kTrigFadeOut: return "Fade Out";
|
||||
case ParamControl::kTrigAttack: return "Attack";
|
||||
case ParamControl::kTrigHold: return "Hold";
|
||||
case ParamControl::kTrigDecay: return "Decay";
|
||||
case ParamControl::kKeyTrack: return "Key Trk";
|
||||
case ParamControl::kPitchEnvAttack: return "P.Att";
|
||||
case ParamControl::kPitchEnvHold: return "P.Hold";
|
||||
case ParamControl::kPitchEnvDecay: return "P.Dec";
|
||||
case ParamControl::kPitchEnvDepth: return "P.Depth";
|
||||
case ParamControl::kVoiceCount: return "Voices";
|
||||
@@ -81,6 +83,9 @@ void ReaSamplerEditor::paintDeck(LICE_IBitmap* bmp, const FaceLayout& fl) {
|
||||
case ParamControl::kFilterEnvDecay: return "F.Dec";
|
||||
case ParamControl::kFilterEnvSustain: return "F.Sus";
|
||||
case ParamControl::kFilterEnvRelease: return "F.Rel";
|
||||
case ParamControl::kFilterTrigAttack: return "F.Att";
|
||||
case ParamControl::kFilterTrigHold: return "F.Hold";
|
||||
case ParamControl::kFilterTrigDecay: return "F.Dec";
|
||||
default: return "";
|
||||
}
|
||||
};
|
||||
@@ -103,6 +108,22 @@ void ReaSamplerEditor::paintDeck(LICE_IBitmap* bmp, const FaceLayout& fl) {
|
||||
}
|
||||
kitText(bmp, g.caption, caption, Font::Micro, Role::TextDim);
|
||||
|
||||
// The overlay-select radio: filled in the tertiary accent (the colour the overlay
|
||||
// traces in) when this group's envelope is the one on the waveform, hollow otherwise.
|
||||
if (g.captionRadio.id >= 0) {
|
||||
const bool on = (overlayEnv_ == overlayEnvForRadio(g.captionRadio.id));
|
||||
const bool hov = isHovered(HoverKind::kEnvRadio, g.captionRadio.id);
|
||||
const Rect& rb = g.captionRadio.box;
|
||||
LICE_DrawRect(bmp, rb.x, rb.y, rb.width - 1, rb.height - 1,
|
||||
toLice(roleColor(on || hov ? Role::AccentTertiary
|
||||
: Role::LineHairline)),
|
||||
1.0f, 0);
|
||||
if (on) {
|
||||
LICE_FillRect(bmp, rb.x + 3, rb.y + 3, rb.width - 6, rb.height - 6,
|
||||
toLice(roleColor(Role::AccentTertiary)), 1.0f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// The compact caption toggle (right-anchored in the caption row, never full-width).
|
||||
if (g.captionToggle.id >= 0) {
|
||||
switch (static_cast<ParamControl>(g.captionToggle.id)) {
|
||||
@@ -142,7 +163,7 @@ void ReaSamplerEditor::paintDeck(LICE_IBitmap* bmp, const FaceLayout& fl) {
|
||||
// The knobs. A dependent group's knobs draw Disabled (not hidden) — stable geometry.
|
||||
// The predicate is the input side's, so the drawn state and the inert grab agree.
|
||||
for (const DeckCellLayout& c : g.cells) {
|
||||
if (c.id < 0) continue; // reserved blank cell (the Trigger face's two spares)
|
||||
if (c.id < 0) continue; // reserved blank cell (the Trigger face's spare)
|
||||
const bool disabled = deckKnobDisabled(c.id);
|
||||
const bool dragging = (drag_ == DragKind::kDeckKnob && dragParamId_ == c.id);
|
||||
const bool hov = !disabled && isHovered(HoverKind::kControl, c.id);
|
||||
@@ -151,9 +172,28 @@ void ReaSamplerEditor::paintDeck(LICE_IBitmap* bmp, const FaceLayout& fl) {
|
||||
: (dragging ? InteractionState::Dragging
|
||||
: (hov ? InteractionState::Hover : InteractionState::Rest));
|
||||
drawKnobFace(bmp, c.knob, deckControlNorm(c.id), st);
|
||||
const std::string label = (dragging || hov)
|
||||
? deckValueLabel(c.id)
|
||||
: std::string(knobName(static_cast<ParamControl>(c.id)));
|
||||
|
||||
// The inner dial rides only the knobs whose stage is sloped — deck_groups owns
|
||||
// that rule, so a Hold or Sustain cell simply has no curve id and draws none.
|
||||
const ParamControl curve = curveParamFor(static_cast<ParamControl>(c.id));
|
||||
const bool innerDragging =
|
||||
(drag_ == DragKind::kDeckKnob && dragInnerCellId_ == c.id);
|
||||
const bool innerHov = !disabled && isHovered(HoverKind::kInnerDial, c.id);
|
||||
if (curve != ParamControl::kCount) {
|
||||
const InteractionState ist =
|
||||
disabled ? InteractionState::Disabled
|
||||
: (innerDragging ? InteractionState::Dragging
|
||||
: (innerHov ? InteractionState::Hover
|
||||
: InteractionState::Rest));
|
||||
drawInnerDial(bmp, c.inner, deckControlNorm(static_cast<int>(curve)), ist);
|
||||
}
|
||||
|
||||
// One label band, so the inner dial's readout takes it while the inner dial is the
|
||||
// one being touched.
|
||||
std::string label;
|
||||
if (innerDragging || innerHov) label = deckValueLabel(static_cast<int>(curve));
|
||||
else if (dragging || hov) label = deckValueLabel(c.id);
|
||||
else label = std::string(knobName(static_cast<ParamControl>(c.id)));
|
||||
kitTextCentered(bmp, c.label, label.c_str(), Font::Micro, Role::TextDim);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user