Created
October 19, 2020 19:42
-
-
Save MartinBspheroid/8b45168f4c8a42c614c35be69d3ed44a to your computer and use it in GitHub Desktop.
Rubbery-like-cables in Iplug2. Based on code https://gist.github.com/olilarkin/a4bb2552744001a677bd56160884b35c by @olilarkin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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