@@ -6,6 +6,7 @@ Tip: Use `git checkout v0.3.2` for example to check out any previous version men | |||||
- Added sub-menus for each plugin, includes optional plugin metadata like URLs | - Added sub-menus for each plugin, includes optional plugin metadata like URLs | ||||
- Added new scrolling methods: middle-click-and-drag, shift-scroll, and arrow keys | - Added new scrolling methods: middle-click-and-drag, shift-scroll, and arrow keys | ||||
- Added engine pausing in sample rate menu | - Added engine pausing in sample rate menu | ||||
- Added resizable blank to Core | |||||
- Support for AMD Phenom II processors | - Support for AMD Phenom II processors | ||||
- Use self-contained Mac app bundle, no need for a Rack folder | - Use self-contained Mac app bundle, no need for a Rack folder | ||||
@@ -35,28 +35,30 @@ struct ModuleWidget : OpaqueWidget { | |||||
~ModuleWidget(); | ~ModuleWidget(); | ||||
void setModule(Module *module); | void setModule(Module *module); | ||||
// Convenience functions for adding special widgets (calls addChild()) | |||||
/** Convenience functions for adding special widgets (calls addChild()) */ | |||||
void addInput(Port *input); | void addInput(Port *input); | ||||
void addOutput(Port *output); | void addOutput(Port *output); | ||||
void addParam(ParamWidget *param); | void addParam(ParamWidget *param); | ||||
json_t *toJson(); | |||||
void fromJson(json_t *root); | |||||
/** Disconnects cables from all ports */ | |||||
void disconnect(); | |||||
/** Resets the state of the module */ | |||||
void initialize(); | |||||
/** Randomizes the state of the module | |||||
This method just randomizes parameters. Override and call this function if your module contains other state information that you wish to randomize. | |||||
virtual json_t *toJson(); | |||||
virtual void fromJson(json_t *rootJ); | |||||
/** Disconnects cables from all ports | |||||
Called when the user clicks Disconnect Cables in the context menu. | |||||
*/ | |||||
virtual void disconnect(); | |||||
/** Resets the parameters of the module and calls the Module's randomize(). | |||||
Called when the user clicks Initialize in the context menu. | |||||
*/ | */ | ||||
void randomize(); | |||||
virtual void initialize(); | |||||
/** Randomizes the parameters of the module and calls the Module's randomize(). | |||||
Called when the user clicks Randomize in the context menu. | |||||
*/ | |||||
virtual void randomize(); | |||||
virtual Menu *createContextMenu(); | virtual Menu *createContextMenu(); | ||||
void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
bool requested = false; | |||||
Vec requestedPos; | |||||
Vec dragPos; | Vec dragPos; | ||||
Widget *onMouseMove(Vec pos, Vec mouseRel); | Widget *onMouseMove(Vec pos, Vec mouseRel); | ||||
Widget *onHoverKey(Vec pos, int key); | Widget *onHoverKey(Vec pos, int key); | ||||
@@ -118,14 +120,16 @@ struct RackWidget : OpaqueWidget { | |||||
void savePatch(std::string filename); | void savePatch(std::string filename); | ||||
void loadPatch(std::string filename); | void loadPatch(std::string filename); | ||||
json_t *toJson(); | json_t *toJson(); | ||||
void fromJson(json_t *root); | |||||
void fromJson(json_t *rootJ); | |||||
void addModule(ModuleWidget *m); | void addModule(ModuleWidget *m); | ||||
/** Transfers ownership to the caller so they must `delete` it if that is the intension */ | /** Transfers ownership to the caller so they must `delete` it if that is the intension */ | ||||
void deleteModule(ModuleWidget *m); | void deleteModule(ModuleWidget *m); | ||||
void cloneModule(ModuleWidget *m); | void cloneModule(ModuleWidget *m); | ||||
/** Sets a module's box if non-colliding. Returns true if set */ | |||||
bool requestModuleBox(ModuleWidget *m, Rect box); | |||||
/** Moves a module to the closest non-colliding position */ | /** Moves a module to the closest non-colliding position */ | ||||
void repositionModule(ModuleWidget *m); | |||||
bool requestModuleBoxNearest(ModuleWidget *m, Rect box); | |||||
void step(); | void step(); | ||||
void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
@@ -138,7 +142,6 @@ struct RackRail : TransparentWidget { | |||||
struct Panel : TransparentWidget { | struct Panel : TransparentWidget { | ||||
NVGcolor backgroundColor; | NVGcolor backgroundColor; | ||||
NVGcolor borderColor; | |||||
std::shared_ptr<Image> backgroundImage; | std::shared_ptr<Image> backgroundImage; | ||||
void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
}; | }; | ||||
@@ -167,7 +170,7 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { | |||||
int paramId; | int paramId; | ||||
json_t *toJson(); | json_t *toJson(); | ||||
void fromJson(json_t *root); | |||||
void fromJson(json_t *rootJ); | |||||
virtual void randomize(); | virtual void randomize(); | ||||
void onMouseDownOpaque(int button); | void onMouseDownOpaque(int button); | ||||
void onChange(); | void onChange(); | ||||
@@ -617,14 +617,12 @@ struct LightPanel : Panel { | |||||
LightPanel() { | LightPanel() { | ||||
// backgroundColor = nvgRGB(0xe6, 0xe6, 0xe6); | // backgroundColor = nvgRGB(0xe6, 0xe6, 0xe6); | ||||
backgroundColor = nvgRGB(0xf0, 0xf0, 0xf0); | backgroundColor = nvgRGB(0xf0, 0xf0, 0xf0); | ||||
borderColor = nvgRGB(0xac, 0xac, 0xac); | |||||
} | } | ||||
}; | }; | ||||
struct DarkPanel : Panel { | struct DarkPanel : Panel { | ||||
DarkPanel() { | DarkPanel() { | ||||
backgroundColor = nvgRGB(0x17, 0x17, 0x17); | backgroundColor = nvgRGB(0x17, 0x17, 0x17); | ||||
borderColor = nvgRGB(0x5e, 0x5e, 0x5e); | |||||
} | } | ||||
}; | }; | ||||
@@ -55,7 +55,7 @@ struct Module { | |||||
virtual json_t *toJson() { return NULL; } | virtual json_t *toJson() { return NULL; } | ||||
virtual void fromJson(json_t *root) {} | virtual void fromJson(json_t *root) {} | ||||
/** Override these to implement behavior when user clicks Initialize and Randomize */ | |||||
/** Override these to implement spacial behavior when user clicks Initialize and Randomize */ | |||||
virtual void initialize() {} | virtual void initialize() {} | ||||
virtual void randomize() {} | virtual void randomize() {} | ||||
}; | }; | ||||
@@ -6,6 +6,7 @@ | |||||
namespace rack { | namespace rack { | ||||
ModuleWidget::~ModuleWidget() { | ModuleWidget::~ModuleWidget() { | ||||
// Make sure WireWidget destructors are called *before* removing `module` from the rack. | // Make sure WireWidget destructors are called *before* removing `module` from the rack. | ||||
disconnect(); | disconnect(); | ||||
@@ -49,8 +50,8 @@ json_t *ModuleWidget::toJson() { | |||||
// model | // model | ||||
json_object_set_new(rootJ, "model", json_string(model->slug.c_str())); | json_object_set_new(rootJ, "model", json_string(model->slug.c_str())); | ||||
// pos | // pos | ||||
json_t *pos = json_pack("[f, f]", (double) box.pos.x, (double) box.pos.y); | |||||
json_object_set_new(rootJ, "pos", pos); | |||||
json_t *posJ = json_pack("[f, f]", (double) box.pos.x, (double) box.pos.y); | |||||
json_object_set_new(rootJ, "pos", posJ); | |||||
// params | // params | ||||
json_t *paramsJ = json_array(); | json_t *paramsJ = json_array(); | ||||
for (ParamWidget *paramWidget : params) { | for (ParamWidget *paramWidget : params) { | ||||
@@ -70,12 +71,10 @@ json_t *ModuleWidget::toJson() { | |||||
} | } | ||||
void ModuleWidget::fromJson(json_t *rootJ) { | void ModuleWidget::fromJson(json_t *rootJ) { | ||||
initialize(); | |||||
// pos | // pos | ||||
json_t *pos = json_object_get(rootJ, "pos"); | |||||
json_t *posJ = json_object_get(rootJ, "pos"); | |||||
double x, y; | double x, y; | ||||
json_unpack(pos, "[F, F]", &x, &y); | |||||
json_unpack(posJ, "[F, F]", &x, &y); | |||||
box.pos = Vec(x, y); | box.pos = Vec(x, y); | ||||
// params | // params | ||||
@@ -197,8 +196,9 @@ void ModuleWidget::onDragStart() { | |||||
} | } | ||||
void ModuleWidget::onDragMove(Vec mouseRel) { | void ModuleWidget::onDragMove(Vec mouseRel) { | ||||
requestedPos = gMousePos.minus(parent->getAbsolutePos()).minus(dragPos); | |||||
requested = true; | |||||
Rect newBox = box; | |||||
newBox.pos = gMousePos.minus(parent->getAbsolutePos()).minus(dragPos); | |||||
gRackWidget->requestModuleBoxNearest(this, newBox); | |||||
} | } | ||||
void ModuleWidget::onDragEnd() { | void ModuleWidget::onDragEnd() { | ||||
@@ -3,13 +3,16 @@ | |||||
namespace rack { | namespace rack { | ||||
void Panel::draw(NVGcontext *vg) { | void Panel::draw(NVGcontext *vg) { | ||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgRect(vg, 0.0, 0.0, box.size.x, box.size.y); | nvgRect(vg, 0.0, 0.0, box.size.x, box.size.y); | ||||
// Background color | // Background color | ||||
nvgFillColor(vg, backgroundColor); | |||||
nvgFill(vg); | |||||
if (backgroundColor.a > 0) { | |||||
nvgFillColor(vg, backgroundColor); | |||||
nvgFill(vg); | |||||
} | |||||
// Background image | // Background image | ||||
if (backgroundImage) { | if (backgroundImage) { | ||||
@@ -21,11 +24,14 @@ void Panel::draw(NVGcontext *vg) { | |||||
} | } | ||||
// Border | // Border | ||||
NVGcolor borderColor = nvgRGBAf(0.5, 0.5, 0.5, 0.5); | |||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgRect(vg, 0.5, 0.5, box.size.x - 1, box.size.y - 1); | |||||
nvgRect(vg, 0.5, 0.5, box.size.x - 1.0, box.size.y - 1.0); | |||||
nvgStrokeColor(vg, borderColor); | nvgStrokeColor(vg, borderColor); | ||||
nvgStrokeWidth(vg, 1.0); | nvgStrokeWidth(vg, 1.0); | ||||
nvgStroke(vg); | nvgStroke(vg); | ||||
Widget::draw(vg); | |||||
} | } | ||||
} // namespace rack | } // namespace rack |
@@ -28,6 +28,8 @@ void Port::onMouseDownOpaque(int button) { | |||||
} | } | ||||
void Port::onDragEnd() { | void Port::onDragEnd() { | ||||
// FIXME | |||||
// If the source Port is deleted, this will be called, removing the cable | |||||
gRackWidget->wireContainer->commitActiveWire(); | gRackWidget->wireContainer->commitActiveWire(); | ||||
} | } | ||||
@@ -261,15 +261,27 @@ void RackWidget::cloneModule(ModuleWidget *m) { | |||||
json_t *moduleJ = m->toJson(); | json_t *moduleJ = m->toJson(); | ||||
clonedModuleWidget->fromJson(moduleJ); | clonedModuleWidget->fromJson(moduleJ); | ||||
json_decref(moduleJ); | json_decref(moduleJ); | ||||
clonedModuleWidget->requestedPos = m->box.pos; | |||||
clonedModuleWidget->requested = true; | |||||
Rect clonedBox = clonedModuleWidget->box; | |||||
clonedBox.pos = m->box.pos; | |||||
requestModuleBoxNearest(clonedModuleWidget, clonedBox); | |||||
addModule(clonedModuleWidget); | addModule(clonedModuleWidget); | ||||
} | } | ||||
void RackWidget::repositionModule(ModuleWidget *m) { | |||||
bool RackWidget::requestModuleBox(ModuleWidget *m, Rect box) { | |||||
for (Widget *child2 : moduleContainer->children) { | |||||
if (m == child2) continue; | |||||
if (box.intersects(child2->box)) { | |||||
return false; | |||||
} | |||||
} | |||||
m->box = box; | |||||
return true; | |||||
} | |||||
bool RackWidget::requestModuleBoxNearest(ModuleWidget *m, Rect box) { | |||||
// Create possible positions | // Create possible positions | ||||
int x0 = roundf(m->requestedPos.x / RACK_GRID_WIDTH); | |||||
int y0 = roundf(m->requestedPos.y / RACK_GRID_HEIGHT); | |||||
int x0 = roundf(box.pos.x / RACK_GRID_WIDTH); | |||||
int y0 = roundf(box.pos.y / RACK_GRID_HEIGHT); | |||||
std::vector<Vec> positions; | std::vector<Vec> positions; | ||||
for (int y = maxi(0, y0 - 4); y < y0 + 4; y++) { | for (int y = maxi(0, y0 - 4); y < y0 + 4; y++) { | ||||
for (int x = maxi(0, x0 - 200); x < x0 + 200; x++) { | for (int x = maxi(0, x0 - 200); x < x0 + 200; x++) { | ||||
@@ -278,27 +290,18 @@ void RackWidget::repositionModule(ModuleWidget *m) { | |||||
} | } | ||||
// Sort possible positions by distance to the requested position | // Sort possible positions by distance to the requested position | ||||
Vec requestedPos = m->requestedPos; | |||||
std::sort(positions.begin(), positions.end(), [requestedPos](Vec a, Vec b) { | |||||
return a.minus(requestedPos).norm() < b.minus(requestedPos).norm(); | |||||
std::sort(positions.begin(), positions.end(), [box](Vec a, Vec b) { | |||||
return a.minus(box.pos).norm() < b.minus(box.pos).norm(); | |||||
}); | }); | ||||
// Find a position that does not collide | // Find a position that does not collide | ||||
for (Vec pos : positions) { | |||||
Rect newBox = Rect(pos, m->box.size); | |||||
bool collides = false; | |||||
for (Widget *child2 : moduleContainer->children) { | |||||
if (m == child2) continue; | |||||
if (newBox.intersects(child2->box)) { | |||||
collides = true; | |||||
break; | |||||
} | |||||
} | |||||
if (collides) continue; | |||||
m->box.pos = pos; | |||||
break; | |||||
for (Vec position : positions) { | |||||
Rect newBox = box; | |||||
newBox.pos = position; | |||||
if (requestModuleBox(m, newBox)) | |||||
return true; | |||||
} | } | ||||
return false; | |||||
} | } | ||||
void RackWidget::step() { | void RackWidget::step() { | ||||
@@ -309,16 +312,6 @@ void RackWidget::step() { | |||||
// We assume that the size is reset by a parent before calling step(). Otherwise it will grow unbounded. | // We assume that the size is reset by a parent before calling step(). Otherwise it will grow unbounded. | ||||
box.size = box.size.max(moduleSize); | box.size = box.size.max(moduleSize); | ||||
// Reposition modules | |||||
for (Widget *child : moduleContainer->children) { | |||||
ModuleWidget *module = dynamic_cast<ModuleWidget*>(child); | |||||
assert(module); | |||||
if (module->requested) { | |||||
repositionModule(module); | |||||
module->requested = false; | |||||
} | |||||
} | |||||
// Autosave every 15 seconds | // Autosave every 15 seconds | ||||
if (gGuiFrame % (60*15) == 0) { | if (gGuiFrame % (60*15) == 0) { | ||||
savePatch(assetLocal("autosave.vcv")); | savePatch(assetLocal("autosave.vcv")); | ||||
@@ -344,9 +337,12 @@ struct AddModuleMenuItem : MenuItem { | |||||
Vec modulePos; | Vec modulePos; | ||||
void onAction() { | void onAction() { | ||||
ModuleWidget *moduleWidget = model->createModuleWidget(); | ModuleWidget *moduleWidget = model->createModuleWidget(); | ||||
moduleWidget->requestedPos = modulePos.minus(moduleWidget->box.getCenter()); | |||||
moduleWidget->requested = true; | |||||
gRackWidget->moduleContainer->addChild(moduleWidget); | gRackWidget->moduleContainer->addChild(moduleWidget); | ||||
// Move module nearest to the mouse position | |||||
Rect box; | |||||
box.size = moduleWidget->box.size; | |||||
box.pos = modulePos.minus(box.getCenter()); | |||||
gRackWidget->requestModuleBoxNearest(moduleWidget, box); | |||||
} | } | ||||
}; | }; | ||||
@@ -6,11 +6,7 @@ namespace rack { | |||||
struct PanelBorder : TransparentWidget { | struct PanelBorder : TransparentWidget { | ||||
void draw(NVGcontext *vg) { | void draw(NVGcontext *vg) { | ||||
nvgBeginPath(vg); | |||||
nvgRect(vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
NVGcolor borderColor = nvgRGBAf(0.5, 0.5, 0.5, 0.5); | NVGcolor borderColor = nvgRGBAf(0.5, 0.5, 0.5, 0.5); | ||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgRect(vg, 0.5, 0.5, box.size.x - 1.0, box.size.y - 1.0); | nvgRect(vg, 0.5, 0.5, box.size.x - 1.0, box.size.y - 1.0); | ||||
nvgStrokeColor(vg, borderColor); | nvgStrokeColor(vg, borderColor); | ||||
@@ -21,6 +17,8 @@ struct PanelBorder : TransparentWidget { | |||||
void SVGPanel::setBackground(std::shared_ptr<SVG> svg) { | void SVGPanel::setBackground(std::shared_ptr<SVG> svg) { | ||||
clearChildren(); | |||||
SVGWidget *sw = new SVGWidget(); | SVGWidget *sw = new SVGWidget(); | ||||
sw->wrap(); | sw->wrap(); | ||||
sw->svg = svg; | sw->svg = svg; | ||||
@@ -432,6 +432,11 @@ AudioInterfaceWidget::AudioInterfaceWidget() { | |||||
addChild(panel); | addChild(panel); | ||||
} | } | ||||
// addChild(createScrew<ScrewSilver>(Vec(15, 0))); | |||||
// addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 0))); | |||||
// addChild(createScrew<ScrewSilver>(Vec(15, 365))); | |||||
// addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 365))); | |||||
float margin = 5; | float margin = 5; | ||||
float labelHeight = 15; | float labelHeight = 15; | ||||
float yPos = margin; | float yPos = margin; | ||||
@@ -0,0 +1,109 @@ | |||||
#include "core.hpp" | |||||
using namespace rack; | |||||
struct ModuleResizeHandle : Widget { | |||||
bool right = false; | |||||
float originalWidth; | |||||
float totalX; | |||||
ModuleResizeHandle() { | |||||
box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT); | |||||
} | |||||
Widget *onMouseDown(Vec pos, int button) { | |||||
if (button == 0) | |||||
return this; | |||||
return NULL; | |||||
} | |||||
void onDragStart() { | |||||
assert(parent); | |||||
originalWidth = parent->box.size.x; | |||||
totalX = 0.0; | |||||
} | |||||
void onDragMove(Vec mouseRel) { | |||||
ModuleWidget *m = dynamic_cast<ModuleWidget*>(parent); | |||||
assert(m); | |||||
totalX += mouseRel.x; | |||||
float targetWidth = originalWidth; | |||||
if (right) | |||||
targetWidth += totalX; | |||||
else | |||||
targetWidth -= totalX; | |||||
targetWidth = RACK_GRID_WIDTH * roundf(targetWidth / RACK_GRID_WIDTH); | |||||
targetWidth = fmaxf(targetWidth, RACK_GRID_WIDTH * 3); | |||||
Rect newBox = m->box; | |||||
newBox.size.x = targetWidth; | |||||
if (!right) { | |||||
newBox.pos.x = m->box.pos.x + m->box.size.x - newBox.size.x; | |||||
} | |||||
gRackWidget->requestModuleBox(m, newBox); | |||||
} | |||||
void draw(NVGcontext *vg) { | |||||
for (float x = 5.0; x <= 10.0; x += 5.0) { | |||||
nvgBeginPath(vg); | |||||
const float margin = 5.0; | |||||
nvgMoveTo(vg, x + 0.5, margin + 0.5); | |||||
nvgLineTo(vg, x + 0.5, box.size.y - margin + 0.5); | |||||
nvgStrokeWidth(vg, 1.0); | |||||
nvgStrokeColor(vg, nvgRGBAf(0.5, 0.5, 0.5, 0.5)); | |||||
nvgStroke(vg); | |||||
} | |||||
} | |||||
}; | |||||
BlankWidget::BlankWidget() { | |||||
box.size = Vec(RACK_GRID_WIDTH * 10, RACK_GRID_HEIGHT); | |||||
{ | |||||
panel = new LightPanel(); | |||||
panel->box.size = box.size; | |||||
addChild(panel); | |||||
} | |||||
ModuleResizeHandle *leftHandle = new ModuleResizeHandle(); | |||||
ModuleResizeHandle *rightHandle = new ModuleResizeHandle(); | |||||
rightHandle->right = true; | |||||
this->rightHandle = rightHandle; | |||||
addChild(leftHandle); | |||||
addChild(rightHandle); | |||||
addChild(createScrew<ScrewSilver>(Vec(15, 0))); | |||||
addChild(createScrew<ScrewSilver>(Vec(15, 365))); | |||||
topRightScrew = createScrew<ScrewSilver>(Vec(box.size.x - 30, 0)); | |||||
bottomRightScrew = createScrew<ScrewSilver>(Vec(box.size.x - 30, 365)); | |||||
addChild(topRightScrew); | |||||
addChild(bottomRightScrew); | |||||
} | |||||
void BlankWidget::step() { | |||||
panel->box.size = box.size; | |||||
topRightScrew->box.pos.x = box.size.x - 30; | |||||
bottomRightScrew->box.pos.x = box.size.x - 30; | |||||
if (box.size.x < RACK_GRID_WIDTH * 6) { | |||||
topRightScrew->visible = bottomRightScrew->visible = false; | |||||
} | |||||
else { | |||||
topRightScrew->visible = bottomRightScrew->visible = true; | |||||
} | |||||
rightHandle->box.pos.x = box.size.x - rightHandle->box.size.x; | |||||
ModuleWidget::step(); | |||||
} | |||||
json_t *BlankWidget::toJson() { | |||||
json_t *rootJ = ModuleWidget::toJson(); | |||||
// // width | |||||
json_object_set_new(rootJ, "width", json_real(box.size.x)); | |||||
return rootJ; | |||||
} | |||||
void BlankWidget::fromJson(json_t *rootJ) { | |||||
ModuleWidget::fromJson(rootJ); | |||||
// width | |||||
json_t *widthJ = json_object_get(rootJ, "width"); | |||||
if (widthJ) | |||||
box.size.x = json_number_value(widthJ); | |||||
} |
@@ -0,0 +1,44 @@ | |||||
#include "core.hpp" | |||||
using namespace rack; | |||||
struct Bridge : Module { | |||||
enum ParamIds { | |||||
NUM_PARAMS | |||||
}; | |||||
enum InputIds { | |||||
NUM_INPUTS | |||||
}; | |||||
enum OutputIds { | |||||
NUM_OUTPUTS | |||||
}; | |||||
Bridge() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
} | |||||
~Bridge() { | |||||
} | |||||
void step(); | |||||
}; | |||||
void Bridge::step() { | |||||
} | |||||
BridgeWidget::BridgeWidget() { | |||||
Bridge *module = new Bridge(); | |||||
setModule(module); | |||||
box.size = Vec(15*8, 380); | |||||
{ | |||||
Panel *panel = new LightPanel(); | |||||
panel->box.size = box.size; | |||||
addChild(panel); | |||||
} | |||||
addChild(createScrew<ScrewSilver>(Vec(15, 0))); | |||||
addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 0))); | |||||
addChild(createScrew<ScrewSilver>(Vec(15, 365))); | |||||
addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 365))); | |||||
} |
@@ -8,4 +8,6 @@ void init(rack::Plugin *plugin) { | |||||
createModel<AudioInterfaceWidget>(plugin, "AudioInterface", "Audio Interface"); | createModel<AudioInterfaceWidget>(plugin, "AudioInterface", "Audio Interface"); | ||||
createModel<MidiToCVWidget>(plugin, "MIDIToCVInterface", "MIDI-to-CV Interface"); | createModel<MidiToCVWidget>(plugin, "MIDIToCVInterface", "MIDI-to-CV Interface"); | ||||
createModel<MIDICCToCVWidget>(plugin, "MIDICCToCVInterface", "MIDI CC-to-CV Interface"); | createModel<MIDICCToCVWidget>(plugin, "MIDICCToCVInterface", "MIDI CC-to-CV Interface"); | ||||
// createModel<BridgeWidget>(plugin, "Bridge", "Bridge"); | |||||
createModel<BlankWidget>(plugin, "Blank", "Blank"); | |||||
} | } |
@@ -21,3 +21,18 @@ struct MIDICCToCVWidget : ModuleWidget { | |||||
MIDICCToCVWidget(); | MIDICCToCVWidget(); | ||||
void step(); | void step(); | ||||
}; | }; | ||||
struct BridgeWidget : ModuleWidget { | |||||
BridgeWidget(); | |||||
}; | |||||
struct BlankWidget : ModuleWidget { | |||||
Panel *panel; | |||||
Widget *topRightScrew; | |||||
Widget *bottomRightScrew; | |||||
Widget *rightHandle; | |||||
BlankWidget(); | |||||
void step(); | |||||
json_t *toJson(); | |||||
void fromJson(json_t *rootJ); | |||||
}; |