// editor_input_deck.cpp — the DECKS band's input: toggles (committed at once, a discrete // final edit), knob grabs (grab-anchored vertical drag, committed on release), the live // knob-drag resolution, and the band's hover. Windows-only. #include "shell/instrument/reasampler_editor.h" #ifdef _WIN32 #include "core/instrument/ui/knob_deck.h" // hitTestDeck / layoutDeck #include "core/instrument/ui/param_slider.h" // knobDragValue (grab-anchored drag) #include "shell/instrument/editor_internal.h" #include "shell/instrument/reasampler_processor.h" namespace reasampler::vst { using namespace reasampler::ui; using namespace reasampler::instrument::ui; bool ReaSamplerEditor::deckKnobDisabled(int id) const { switch (static_cast(id)) { case ParamControl::kPitchEnvAttack: case ParamControl::kPitchEnvDecay: case ParamControl::kPitchEnvDepth: return !params_.play.pitchEnv.enabled; case ParamControl::kFilterMorph: case ParamControl::kFilterCutoff: case ParamControl::kFilterQ: case ParamControl::kFilterDrive: case ParamControl::kFilterModAmt: case ParamControl::kFilterVel: case ParamControl::kFilterKeyTrack: case ParamControl::kFilterEnvAttack: case ParamControl::kFilterEnvHold: case ParamControl::kFilterEnvDecay: case ParamControl::kFilterEnvSustain: case ParamControl::kFilterEnvRelease: return !params_.play.filter.enabled; default: return false; } } bool ReaSamplerEditor::mouseDownDeck(const FaceLayout& fl, int x, int y) { const Rect& band = fl.bands.decks; if (!contains(band, x, y)) return false; const DeckLayout dl = layoutDeck(fl.deckDescs, band.x, band.y, band.width); const DeckHit hit = hitTestDeck(dl, x, y); if (hit.kind == DeckHitKind::CaptionToggle || hit.kind == DeckHitKind::RowToggle) { switch (static_cast(hit.id)) { case ParamControl::kVoiceMode: { // Processor-side per-instance param: live setter (engine rebuild via the // drain-slot swap — tails survive), local snapshot in step. const VoiceMode m = (hit.segment == 1) ? VoiceMode::Mono : VoiceMode::Poly; if (m != voiceMode_) { voiceMode_ = m; processor_->setVoiceMode(m); } invalidate(); break; } case ParamControl::kMonoTrigger: { if (voiceMode_ != VoiceMode::Mono) break; // Disabled (inert) in Poly const MonoTrigger t = (hit.segment == 1) ? MonoTrigger::Legato : MonoTrigger::Retrigger; if (t != monoTrigger_) { monoTrigger_ = t; processor_->setMonoTrigger(t); } invalidate(); break; } case ParamControl::kFilterLaw: // Inert while the filter is off, matching its Disabled paint. if (!params_.play.filter.enabled) break; applyParamControl(hit.id, 0.0, hit.segment); commitAndReload(); break; default: // Parameter-set toggles (play mode / pitch engine / pitch-env + filter enable). applyParamControl(hit.id, 0.0, hit.segment); commitAndReload(); break; } return true; } if (hit.kind == DeckHitKind::Knob) { // Knobs of a disabled group are drawn but inert. if (deckKnobDisabled(hit.id)) return true; drag_ = DragKind::kDeckKnob; dragParamId_ = hit.id; dragKnobStartValue_ = deckControlNorm(hit.id); // Processor-side knobs (voice count / master gain) are transient live writes with no // parameter-set mutation, so they need no rollback snapshot. dragStartParams_ = params_; dragStartX_ = x; dragStartY_ = y; invalidate(); } // The deck band swallows its own clicks either way — no fall-through to the waveform. return true; } void ReaSamplerEditor::dragDeck(int x, int y) { // Radial knob: grab-anchored vertical drag — knobDragValue maps the y delta from the // value at grab (up = increase), so the value tracks relative motion and never jumps on // grab. Live feedback; parameter-set commits land on WM_LBUTTONUP. (void)x; applyDeckKnob(dragParamId_, knobDragValue(dragKnobStartValue_, y - dragStartY_)); invalidate(); } ReaSamplerEditor::HoverTarget ReaSamplerEditor::hoverDeck(const FaceLayout& fl, int x, int y) const { const Rect& band = fl.bands.decks; if (!contains(band, x, y)) return {}; const DeckLayout dl = layoutDeck(fl.deckDescs, band.x, band.y, band.width); const DeckHit dh = hitTestDeck(dl, x, y); if (dh.kind == DeckHitKind::None) return {}; return {HoverKind::kControl, dh.id}; } } // namespace reasampler::vst #endif // _WIN32