From 0839a7c041b4bd4c76df41927dac15e1501796fb Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 7 Oct 2021 22:26:49 -0400 Subject: [PATCH] Draw ModuleWidget shadow with drawLayer() instead of a custom drawShadow() method. --- include/app/ModuleWidget.hpp | 2 +- include/widget/Widget.hpp | 6 +++++- src/app/CableWidget.cpp | 2 ++ src/app/ModuleWidget.cpp | 27 ++++++++++++++++----------- src/app/RackWidget.cpp | 15 +++++---------- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/include/app/ModuleWidget.hpp b/include/app/ModuleWidget.hpp index 5e50c43a..f3879cba 100644 --- a/include/app/ModuleWidget.hpp +++ b/include/app/ModuleWidget.hpp @@ -62,7 +62,7 @@ struct ModuleWidget : widget::OpaqueWidget { std::vector getOutputs(); 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. It is recommended to add a blank `ui::MenuSeparator` first for spacing. diff --git a/include/widget/Widget.hpp b/include/widget/Widget.hpp index 36d14198..d2795829 100644 --- a/include/widget/Widget.hpp +++ b/include/widget/Widget.hpp @@ -128,7 +128,10 @@ struct Widget : WeakBase { 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); /** Override draw(const DrawArgs &args) instead */ 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. Layer 0 calls children's draw(). 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); diff --git a/src/app/CableWidget.cpp b/src/app/CableWidget.cpp index a0913d86..8de89140 100644 --- a/src/app/CableWidget.cpp +++ b/src/app/CableWidget.cpp @@ -350,6 +350,8 @@ void CableWidget::drawLayer(const DrawArgs& args, int layer) { nvgStrokeWidth(args.vg, thickness - 1.0); nvgStroke(args.vg); } + + Widget::drawLayer(args, layer); } diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 1e3aa25d..791acf00 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -284,17 +284,22 @@ void ModuleWidget::draw(const DrawArgs& args) { 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) { diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index 626a7860..8334a3f6 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -40,18 +40,13 @@ static ModuleWidget* moduleWidgetFromJson(json_t* moduleJ) { struct ModuleContainer : widget::Widget { 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(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); + + // Draw lights and light halos + Widget::drawLayer(args, 1); } };