@@ -62,7 +62,7 @@ struct ModuleWidget : widget::OpaqueWidget { | |||||
std::vector<PortWidget*> getOutputs(); | std::vector<PortWidget*> getOutputs(); | ||||
void draw(const DrawArgs& args) override; | void draw(const DrawArgs& args) override; | ||||
void drawShadow(const DrawArgs& args); | |||||
void drawLayer(const DrawArgs& args, int layer) override; | |||||
/** Override to add context menu entries to your subclass. | /** Override to add context menu entries to your subclass. | ||||
It is recommended to add a blank `ui::MenuSeparator` first for spacing. | It is recommended to add a blank `ui::MenuSeparator` first for spacing. | ||||
@@ -128,7 +128,10 @@ struct Widget : WeakBase { | |||||
NVGLUframebuffer* fb = NULL; | NVGLUframebuffer* fb = NULL; | ||||
}; | }; | ||||
/** Draws the widget to the NanoVG context */ | |||||
/** Draws the widget to the NanoVG context. | |||||
When overriding, call the superclass draw() to recurse to children. | |||||
*/ | |||||
virtual void draw(const DrawArgs& args); | virtual void draw(const DrawArgs& args); | ||||
/** Override draw(const DrawArgs &args) instead */ | /** Override draw(const DrawArgs &args) instead */ | ||||
DEPRECATED virtual void draw(NVGcontext* vg) {} | DEPRECATED virtual void draw(NVGcontext* vg) {} | ||||
@@ -138,6 +141,7 @@ struct Widget : WeakBase { | |||||
Custom widgets may draw its children multiple times on different layers, passing an arbitrary layer number each time. | Custom widgets may draw its children multiple times on different layers, passing an arbitrary layer number each time. | ||||
Layer 0 calls children's draw(). | Layer 0 calls children's draw(). | ||||
When overriding, always wrap draw commands in `if (layer == ...) {}` to avoid drawing on all layers. | When overriding, always wrap draw commands in `if (layer == ...) {}` to avoid drawing on all layers. | ||||
When overriding, call the superclass drawLayer() to recurse to children. | |||||
*/ | */ | ||||
virtual void drawLayer(const DrawArgs& args, int layer); | virtual void drawLayer(const DrawArgs& args, int layer); | ||||
@@ -350,6 +350,8 @@ void CableWidget::drawLayer(const DrawArgs& args, int layer) { | |||||
nvgStrokeWidth(args.vg, thickness - 1.0); | nvgStrokeWidth(args.vg, thickness - 1.0); | ||||
nvgStroke(args.vg); | nvgStroke(args.vg); | ||||
} | } | ||||
Widget::drawLayer(args, layer); | |||||
} | } | ||||
@@ -284,17 +284,22 @@ void ModuleWidget::draw(const DrawArgs& args) { | |||||
nvgResetScissor(args.vg); | nvgResetScissor(args.vg); | ||||
} | } | ||||
void ModuleWidget::drawShadow(const DrawArgs& args) { | |||||
nvgBeginPath(args.vg); | |||||
float r = 20; // Blur radius | |||||
float c = 20; // Corner radius | |||||
math::Rect shadowBox = box.zeroPos().grow(math::Vec(10, -30)); | |||||
math::Rect shadowOutsideBox = shadowBox.grow(math::Vec(r, r)); | |||||
nvgRect(args.vg, RECT_ARGS(shadowOutsideBox)); | |||||
NVGcolor shadowColor = nvgRGBAf(0, 0, 0, 0.2); | |||||
NVGcolor transparentColor = nvgRGBAf(0, 0, 0, 0); | |||||
nvgFillPaint(args.vg, nvgBoxGradient(args.vg, RECT_ARGS(shadowBox), c, r, shadowColor, transparentColor)); | |||||
nvgFill(args.vg); | |||||
void ModuleWidget::drawLayer(const DrawArgs& args, int layer) { | |||||
if (layer == -1) { | |||||
nvgBeginPath(args.vg); | |||||
float r = 20; // Blur radius | |||||
float c = 20; // Corner radius | |||||
math::Rect shadowBox = box.zeroPos().grow(math::Vec(10, -30)); | |||||
math::Rect shadowOutsideBox = shadowBox.grow(math::Vec(r, r)); | |||||
nvgRect(args.vg, RECT_ARGS(shadowOutsideBox)); | |||||
NVGcolor shadowColor = nvgRGBAf(0, 0, 0, 0.2); | |||||
NVGcolor transparentColor = nvgRGBAf(0, 0, 0, 0); | |||||
nvgFillPaint(args.vg, nvgBoxGradient(args.vg, RECT_ARGS(shadowBox), c, r, shadowColor, transparentColor)); | |||||
nvgFill(args.vg); | |||||
} | |||||
else { | |||||
Widget::drawLayer(args, layer); | |||||
} | |||||
} | } | ||||
void ModuleWidget::onHover(const HoverEvent& e) { | void ModuleWidget::onHover(const HoverEvent& e) { | ||||
@@ -40,18 +40,13 @@ static ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) { | |||||
struct ModuleContainer : widget::Widget { | struct ModuleContainer : widget::Widget { | ||||
void draw(const DrawArgs& args) override { | void draw(const DrawArgs& args) override { | ||||
// Draw shadows behind each ModuleWidget first, so the shadow doesn't overlap the front of other ModuleWidgets. | |||||
for (widget::Widget* child : children) { | |||||
ModuleWidget* w = dynamic_cast<ModuleWidget*>(child); | |||||
assert(w); | |||||
nvgSave(args.vg); | |||||
nvgTranslate(args.vg, child->box.pos.x, child->box.pos.y); | |||||
w->drawShadow(args); | |||||
nvgRestore(args.vg); | |||||
} | |||||
// Draw ModuleWidget shadows | |||||
Widget::drawLayer(args, -1); | |||||
Widget::draw(args); | Widget::draw(args); | ||||
// Draw lights and light halos | |||||
Widget::drawLayer(args, 1); | |||||
} | } | ||||
}; | }; | ||||