Skip to content

Commit

Permalink
Dyanmic Deactivation of Widgets; Use in RingMod (#981)
Browse files Browse the repository at this point in the history
Knobs and Menu Items get dynamic deactivation as an option.
The ring modulator uses this.
  • Loading branch information
baconpaul committed Jan 12, 2024
1 parent f7037ec commit 9c5ad89
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 5 deletions.
1 change: 1 addition & 0 deletions docs/nightlychangelog.md
Expand Up @@ -11,5 +11,6 @@ A small fix release after 2.2.1
- Some tweaks to the ringmod, including changing display when connecting and
disconnecting
- FX sidechains participate in neighbor inputs
- RingMod deactivates useless controls when sideband attached


4 changes: 4 additions & 0 deletions src/LayoutEngine.h
Expand Up @@ -60,6 +60,8 @@ struct LayoutItem
bool dynamicLabel{false};
std::function<std::string(modules::XTModule *m)> dynLabelFn{nullptr};

std::function<bool(modules::XTModule *m)> dynamicDeactivateFn{nullptr};

static LayoutItem createLCDArea(float ht)
{
auto res = LayoutItem();
Expand Down Expand Up @@ -284,6 +286,7 @@ template <typename W, int param0, int clockId = -1> struct LayoutEngine
}
if (knob)
{
knob->dynamicDeactivateFn = lay.dynamicDeactivateFn;
w->addChild(knob->asWidget());
auto boxx0 = lay.xcmm - lc::columnWidth_MM * 0.5 - halfSize;
auto boxy0 = lay.ycmm + 8.573 + halfSize - 5;
Expand Down Expand Up @@ -560,6 +563,7 @@ template <typename W, int param0, int clockId = -1> struct LayoutEngine
rack::Vec(xpos, ypos), rack::Vec(width, height), module, lay.parId);
wid->upcaseDisplay = false;
wid->centerDisplay = true;
wid->dynamicDeactivateFn = lay.dynamicDeactivateFn;

if (sd == 0)
{
Expand Down
117 changes: 113 additions & 4 deletions src/XTWidgets.h
Expand Up @@ -308,6 +308,9 @@ struct ModulatableKnob
{
virtual void setIsModEditing(bool b) = 0;
virtual rack::Widget *asWidget() = 0;

bool deactivated{false};
std::function<bool(modules::XTModule *m)> dynamicDeactivateFn{nullptr};
};

struct KnobN : public rack::componentlibrary::RoundKnob, style::StyleParticipant, ModulatableKnob
Expand Down Expand Up @@ -388,6 +391,9 @@ struct KnobN : public rack::componentlibrary::RoundKnob, style::StyleParticipant

void drawRing(NVGcontext *vg)
{
if (deactivated)
return;

float radius = rack::mm2px(ringWidth_MM * 2 + knobSize_MM) * 0.5;
nvgBeginPath(vg);
nvgArc(vg, box.size.x * 0.5, box.size.y * 0.5, radius, minAngle - M_PI_2, maxAngle - M_PI_2,
Expand All @@ -400,6 +406,9 @@ struct KnobN : public rack::componentlibrary::RoundKnob, style::StyleParticipant

void drawValueRing(NVGcontext *vg)
{
if (deactivated)
return;

if (isModEditing)
return;
auto *pq = getParamQuantity();
Expand Down Expand Up @@ -455,12 +464,15 @@ struct KnobN : public rack::componentlibrary::RoundKnob, style::StyleParticipant
BufferedDrawFunctionWidget *bw{nullptr}, *bwValue{nullptr}, *bwShadow{nullptr};
void onChange(const ChangeEvent &e) override;
void onStyleChanged() override { setupWidgets(); }

std::shared_ptr<rack::window::Svg> ptrSvg;
void setupWidgets()
{
auto compDir = style()->skinAssetDir() + "/components";

setSvg(
rack::Svg::load(rack::asset::plugin(pluginInstance, compDir + "/" + knobPointerAsset)));
ptrSvg =
rack::Svg::load(rack::asset::plugin(pluginInstance, compDir + "/" + knobPointerAsset));
setSvg(ptrSvg);
bg->setSvg(rack::Svg::load(
rack::asset::plugin(pluginInstance, compDir + "/" + knobBackgroundAsset)));
// bg->visible = false;
Expand Down Expand Up @@ -532,6 +544,19 @@ struct KnobN : public rack::componentlibrary::RoundKnob, style::StyleParticipant
nvgRestore(vg);
}

void setDeactivated(bool isDA)
{
deactivated = isDA;

bw->dirty = true;
bwValue->dirty = true;

bwShadow->dirty = true;

sw->setVisible(!deactivated);
fb->dirty = true;
}

float priorMDA{0};
bool priorBip{false};
void step() override
Expand All @@ -550,9 +575,66 @@ struct KnobN : public rack::componentlibrary::RoundKnob, style::StyleParticipant
bwValue->dirty = true;
priorBip = bip;
}

if (dynamicDeactivateFn)
{
auto xtm = static_cast<modules::XTModule *>(module);
auto oda = deactivated;
auto nda = dynamicDeactivateFn(xtm);
if (oda != nda)
{
setDeactivated(nda);
}
}
}
rack::componentlibrary::RoundKnob::step();
}

void onHover(const HoverEvent &e) override
{
if (!deactivated)
rack::componentlibrary::RoundKnob::onHover(e);
}
void onButton(const ButtonEvent &e) override
{
if (!deactivated)
rack::componentlibrary::RoundKnob::onButton(e);
}

void onDragStart(const DragStartEvent &e) override
{
if (!deactivated)
rack::componentlibrary::RoundKnob::onDragStart(e);
}
void onDragEnd(const DragEndEvent &e) override
{
if (!deactivated)
rack::componentlibrary::RoundKnob::onDragEnd(e);
}

void onDragMove(const DragMoveEvent &e) override
{
if (!deactivated)
rack::componentlibrary::RoundKnob::onDragMove(e);
}

void onDragLeave(const DragLeaveEvent &e) override
{
if (!deactivated)
rack::componentlibrary::RoundKnob::onDragLeave(e);
}

void onHoverScroll(const HoverScrollEvent &e) override
{
if (!deactivated)
rack::componentlibrary::RoundKnob::onHoverScroll(e);
}

void onLeave(const LeaveEvent &e) override
{
if (!deactivated)
rack::componentlibrary::RoundKnob::onLeave(e);
}
};

struct Knob9 : KnobN
Expand Down Expand Up @@ -1616,7 +1698,9 @@ struct PlotAreaMenuItem : public rack::app::Knob, style::StyleParticipant
static constexpr float padTop_MM = 1.4;
static constexpr float padBot_MM = 1.6;
BufferedDrawFunctionWidget *bdw{nullptr};
std::function<std::string(const std::string &)> transformLabel;
std::function<std::string(const std::string &)> transformLabel{nullptr};
bool deactivated{false};
std::function<bool(modules::XTModule *)> dynamicDeactivateFn{nullptr};
std::function<void()> onShowMenu = []() {};
bool upcaseDisplay{true};
bool centerDisplay{false};
Expand Down Expand Up @@ -1655,7 +1739,10 @@ struct PlotAreaMenuItem : public rack::app::Knob, style::StyleParticipant
pv = transformLabel(pv);

nvgBeginPath(vg);
nvgFillColor(vg, style()->getColor(style::XTStyle::PLOT_CONTROL_TEXT));
if (deactivated)
nvgFillColor(vg, style()->getColor(style::XTStyle::PLOT_MARKS));
else
nvgFillColor(vg, style()->getColor(style::XTStyle::PLOT_CONTROL_TEXT));
nvgFontFaceId(vg, style()->fontIdBold(vg));
nvgFontSize(vg, layout::LayoutConstants::labelSize_pt * 96 / 72);
if (centerDisplay)
Expand Down Expand Up @@ -1689,8 +1776,17 @@ struct PlotAreaMenuItem : public rack::app::Knob, style::StyleParticipant
Widget::onChange(e);
}

void onHover(const HoverEvent &e) override
{
if (!deactivated)
rack::app::Knob::onHover(e);
}

void onAction(const ActionEvent &e) override
{
if (deactivated)
return;

onShowMenu();
e.consume(this);
}
Expand All @@ -1710,6 +1806,19 @@ struct PlotAreaMenuItem : public rack::app::Knob, style::StyleParticipant
cacheString = pv;
}
}

if (dynamicDeactivateFn)
{
auto xtm = static_cast<modules::XTModule *>(module);

auto oda = deactivated;
auto nda = dynamicDeactivateFn(xtm);
if (oda != nda)
{
deactivated = nda;
bdw->dirty = true;
}
}
}
rack::Knob::step();
}
Expand Down
14 changes: 13 additions & 1 deletion src/fxconfig/RingModulator.h
Expand Up @@ -48,7 +48,7 @@ template <> FXConfig<fxt_ringmod>::layout_t FXConfig<fxt_ringmod>::getLayout()
typedef RingModulatorEffect rm_t;

// clang-format off
return {
FXConfig<fxt_ringmod>::layout_t res = {
{LayoutItem::KNOB12, "FREQUENCY", rm_t::rm_carrier_freq, colC, row1},

{LayoutItem::KNOB9, "BIAS", rm_t::rm_diode_fwdbias, col[0], row2},
Expand All @@ -75,6 +75,18 @@ template <> FXConfig<fxt_ringmod>::layout_t FXConfig<fxt_ringmod>::getLayout()
LayoutItem::createRightMenuItem("Voices", rm_t::rm_unison_voices)
};
// clang-format on

// this indexing is a bit of a hack
res[0].dynamicDeactivateFn = [](auto m) {
auto fxm = static_cast<FX<fxt_ringmod> *>(m);
auto &p = fxm->fxstorage->p[RingModulatorEffect::rm_carrier_shape];
return p.val.i == p.val_max.i;
};
res[13].dynamicDeactivateFn = res[0].dynamicDeactivateFn;
res[16].dynamicDeactivateFn = res[0].dynamicDeactivateFn;
res[17].dynamicDeactivateFn = res[0].dynamicDeactivateFn;

return res;
}

template <> void FXConfig<fxt_ringmod>::configSpecificParams(FX<fxt_ringmod> *m)
Expand Down

0 comments on commit 9c5ad89

Please sign in to comment.