Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rubbery-like-cables in Iplug2. Based on code https://gist.github.com/olilarkin/a4bb2552744001a677bd56160884b35c by @olilarkin
#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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.