| @@ -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); | |||||
| } | } | ||||
| }; | }; | ||||