Skip to content

Instantly share code, notes, and snippets.

@MartinBspheroid
Created October 19, 2020 19:42

Revisions

  1. MartinBspheroid created this gist Oct 19, 2020.
    189 changes: 189 additions & 0 deletions IPlugEffect.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,189 @@
    #include "IPlugEffect.h"
    #include "IPlug_include_in_plug_src.h"
    #include "IControls.h"

    constexpr auto CN = 30;
    struct Cable
    {
    IVec2 pos1;
    IVec2 pos2;
    IColor color;

    Cable(float x, float y, const IColor& color)
    : pos1(x, y)
    , pos2(x + 1, y + 1)
    , color(color)
    {
    }
    };

    class CableControl : public IControl
    {
    private:
    WDL_PtrList<Cable> mCables;

    public:
    CableControl(const IRECT& bounds)
    : IControl(bounds)
    {
    mIgnoreMouse = true;
    }

    ~CableControl()
    {
    mCables.Empty(true);
    }

    void Draw(IGraphics& g) override
    {
    for (int i = 0; i < mCables.GetSize(); i++)
    {
    DrawCable(g, mCables.Get(i));
    }
    }

    Cable* AddCable(float x, float y, const IColor& color)
    {
    Cable* pNewCable = mCables.Add(new Cable(x, y, color));
    SetDirty(false);
    return pNewCable;
    }

    void RemoveCable(Cable* pCable)
    {
    mCables.DeletePtr(pCable, true);
    SetDirty(false);
    }

    private:
    void DrawCable(IGraphics& g, Cable* cable)
    {
    float d = (abs(cable->pos1.x - cable->pos2.x) + abs(cable->pos1.y - cable->pos2.y)) *0.25;

    g.PathMoveTo(cable->pos1.x, cable->pos1.y+5);
    g.PathCubicBezierTo(cable->pos1.x, cable->pos1.y + d+ 5, cable->pos2.x, cable->pos2.y + d+5, cable->pos2.x, cable->pos2.y+5);
    g.PathStroke(COLOR_BLACK_DROP_SHADOW.WithOpacity(0.2), 8.f);

    g.PathMoveTo(cable->pos1.x, cable->pos1.y);
    g.PathCubicBezierTo(cable->pos1.x, cable->pos1.y + d+5, cable->pos2.x, cable->pos2.y + d+5, cable->pos2.x, cable->pos2.y);
    g.PathStroke(cable->color, 6.f);
    g.FillCircle(cable->color, cable->pos1.x, cable->pos1.y, 5);
    g.FillCircle(cable->color, cable->pos2.x, cable->pos2.y, 5);
    }

    };

    class PlugControl : public IControl
    {
    public:
    PlugControl(const IRECT& bounds, CableControl* pCableControl)
    : IControl(bounds)
    , mCableControl(pCableControl)
    {}

    void Draw(IGraphics& g) override
    {
    g.FillEllipse(COLOR_RED, mRECT);

    if (mMouseIsOver || mAboutToConnect)
    {
    g.DrawEllipse(COLOR_BLACK, mRECT, 0, 3);
    }
    }

    void OnMouseDown(float x, float y, const IMouseMod& mod) override
    {

    mLastCable = mCableControl->AddCable(mRECT.MW(), mRECT.MH(), COLOR_RED.GetRandomColor());
    }

    void OnMouseUp(float x, float y, const IMouseMod& mod) override
    {
    bool valid = false;
    for (int i = 0; i < CN; i++)
    {
    PlugControl* pPlug = GetUI()->GetControlWithTag(i)->As<PlugControl>();
    if (pPlug != this)
    valid |= pPlug->GetRECT().Contains(x, y);
    }

    if (!valid) {
    mCableControl->RemoveCable(mLastCable);
    }


    mLastCable = nullptr;
    }

    void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod& mod) override
    {
    if (mLastCable) {
    mLastCable->pos2 = { x, y };

    for (int i = 0; i < CN; i++)
    {
    PlugControl* pPlug = GetUI()->GetControlWithTag(i)->As<PlugControl>();
    pPlug->mAboutToConnect = pPlug->GetRECT().Contains(x, y);
    }

    mCableControl->SetDirty(false);
    }
    }

    bool mAboutToConnect = false;

    private:
    Cable* mLastCable = nullptr;
    CableControl* mCableControl = nullptr;

    };


    IPlugEffect::IPlugEffect(const InstanceInfo& info)
    : Plugin(info, MakeConfig(kNumParams, kNumPresets))
    {
    GetParam(kGain)->InitDouble("Gain", 0., 0., 100.0, 0.01, "%");

    #if IPLUG_EDITOR // http://bit.ly/2S64BDd
    mMakeGraphicsFunc = [&]() {
    return MakeGraphics(*this, PLUG_WIDTH, PLUG_HEIGHT, PLUG_FPS, GetScaleForScreen(PLUG_HEIGHT));
    };

    mLayoutFunc = [&](IGraphics* pGraphics) {
    pGraphics->AttachCornerResizer(EUIResizerMode::Scale, false);
    pGraphics->AttachPanelBackground(COLOR_GRAY);
    pGraphics->EnableMouseOver(true);
    pGraphics->LoadFont("Roboto-Regular", ROBOTO_FN);
    const IRECT b = pGraphics->GetBounds();
    CableControl* pCableControl = new CableControl(b);
    IRECT base = IRECT(0, 0, 20, 20).GetTranslated(200, 50);
    float off = b.H() / (CN / 2);
    for (size_t i = 0; i < CN / 2; i++)
    {
    pGraphics->AttachControl(new PlugControl(base.GetTranslated(50+(i*3), i * off), pCableControl), i);
    } for (size_t i = 0; i < CN / 2; i++)
    {
    pGraphics->AttachControl(new PlugControl(base.GetTranslated(200- (i * 3), i * off), pCableControl), CN/2+i);
    }




    pGraphics->AttachControl(pCableControl);
    };
    #endif
    }

    #if IPLUG_DSP
    void IPlugEffect::ProcessBlock(sample** inputs, sample** outputs, int nFrames)
    {
    const double gain = GetParam(kGain)->Value() / 100.;
    const int nChans = NOutChansConnected();

    for (int s = 0; s < nFrames; s++) {
    for (int c = 0; c < nChans; c++) {
    outputs[c][s] = inputs[c][s] * gain;
    }
    }
    }
    #endif