| @@ -27,8 +27,8 @@ struct CableWidget : OpaqueWidget { | |||||
| math::Vec getInputPos(); | math::Vec getInputPos(); | ||||
| json_t *toJson(); | json_t *toJson(); | ||||
| void fromJson(json_t *rootJ, const std::map<int, ModuleWidget*> &moduleWidgets); | void fromJson(json_t *rootJ, const std::map<int, ModuleWidget*> &moduleWidgets); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void drawPlugs(NVGcontext *vg); | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void drawPlugs(const DrawContext &ctx); | |||||
| }; | }; | ||||
| @@ -10,7 +10,7 @@ struct CircularShadow : TransparentWidget { | |||||
| float blurRadius; | float blurRadius; | ||||
| float opacity; | float opacity; | ||||
| CircularShadow(); | CircularShadow(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -9,12 +9,12 @@ namespace rack { | |||||
| struct LedDisplay : Widget { | struct LedDisplay : Widget { | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| struct LedDisplaySeparator : TransparentWidget { | struct LedDisplaySeparator : TransparentWidget { | ||||
| LedDisplaySeparator(); | LedDisplaySeparator(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| struct LedDisplayChoice : TransparentWidget { | struct LedDisplayChoice : TransparentWidget { | ||||
| @@ -23,7 +23,7 @@ struct LedDisplayChoice : TransparentWidget { | |||||
| math::Vec textOffset; | math::Vec textOffset; | ||||
| NVGcolor color; | NVGcolor color; | ||||
| LedDisplayChoice(); | LedDisplayChoice(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onButton(const event::Button &e) override; | void onButton(const event::Button &e) override; | ||||
| }; | }; | ||||
| @@ -32,7 +32,7 @@ struct LedDisplayTextField : TextField { | |||||
| math::Vec textOffset; | math::Vec textOffset; | ||||
| NVGcolor color; | NVGcolor color; | ||||
| LedDisplayTextField(); | LedDisplayTextField(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| int getTextPosition(math::Vec mousePos) override; | int getTextPosition(math::Vec mousePos) override; | ||||
| }; | }; | ||||
| @@ -10,9 +10,9 @@ struct LightWidget : TransparentWidget { | |||||
| NVGcolor bgColor = nvgRGBA(0, 0, 0, 0); | NVGcolor bgColor = nvgRGBA(0, 0, 0, 0); | ||||
| NVGcolor color = nvgRGBA(0, 0, 0, 0); | NVGcolor color = nvgRGBA(0, 0, 0, 0); | ||||
| NVGcolor borderColor = nvgRGBA(0, 0, 0, 0); | NVGcolor borderColor = nvgRGBA(0, 0, 0, 0); | ||||
| void draw(NVGcontext *vg) override; | |||||
| virtual void drawLight(NVGcontext *vg); | |||||
| virtual void drawHalo(NVGcontext *vg); | |||||
| void draw(const DrawContext &ctx) override; | |||||
| virtual void drawLight(const DrawContext &ctx); | |||||
| virtual void drawHalo(const DrawContext &ctx); | |||||
| }; | }; | ||||
| @@ -13,7 +13,7 @@ struct ModuleBrowser : OpaqueWidget { | |||||
| ModuleBrowser(); | ModuleBrowser(); | ||||
| void step() override; | void step() override; | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onHoverKey(const event::HoverKey &e) override; | void onHoverKey(const event::HoverKey &e) override; | ||||
| }; | }; | ||||
| @@ -30,8 +30,8 @@ struct ModuleWidget : OpaqueWidget { | |||||
| } | } | ||||
| ~ModuleWidget(); | ~ModuleWidget(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void drawShadow(NVGcontext *vg); | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void drawShadow(const DrawContext &ctx); | |||||
| void onHover(const event::Hover &e) override; | void onHover(const event::Hover &e) override; | ||||
| void onButton(const event::Button &e) override; | void onButton(const event::Button &e) override; | ||||
| @@ -16,7 +16,7 @@ struct ParamWidget : OpaqueWidget { | |||||
| ~ParamWidget(); | ~ParamWidget(); | ||||
| void step() override; | void step() override; | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onButton(const event::Button &e) override; | void onButton(const event::Button &e) override; | ||||
| void onEnter(const event::Enter &e) override; | void onEnter(const event::Enter &e) override; | ||||
| void onLeave(const event::Leave &e) override; | void onLeave(const event::Leave &e) override; | ||||
| @@ -23,7 +23,7 @@ struct PortWidget : OpaqueWidget { | |||||
| ~PortWidget(); | ~PortWidget(); | ||||
| void step() override; | void step() override; | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onButton(const event::Button &e) override; | void onButton(const event::Button &e) override; | ||||
| void onDragStart(const event::DragStart &e) override; | void onDragStart(const event::DragStart &e) override; | ||||
| @@ -7,7 +7,7 @@ namespace rack { | |||||
| struct RackRail : TransparentWidget { | struct RackRail : TransparentWidget { | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -8,7 +8,7 @@ namespace rack { | |||||
| struct RackScrollWidget : ScrollWidget { | struct RackScrollWidget : ScrollWidget { | ||||
| void step() override; | void step() override; | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -22,7 +22,7 @@ struct RackWidget : OpaqueWidget { | |||||
| ~RackWidget(); | ~RackWidget(); | ||||
| void step() override; | void step() override; | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onHover(const event::Hover &e) override; | void onHover(const event::Hover &e) override; | ||||
| void onHoverKey(const event::HoverKey &e) override; | void onHoverKey(const event::HoverKey &e) override; | ||||
| @@ -10,7 +10,7 @@ namespace rack { | |||||
| struct PanelBorder : TransparentWidget { | struct PanelBorder : TransparentWidget { | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -28,7 +28,7 @@ struct Scene : OpaqueWidget { | |||||
| Scene(); | Scene(); | ||||
| ~Scene(); | ~Scene(); | ||||
| void step() override; | void step() override; | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onHoverKey(const event::HoverKey &e) override; | void onHoverKey(const event::HoverKey &e) override; | ||||
| void onPathDrop(const event::PathDrop &e) override; | void onPathDrop(const event::PathDrop &e) override; | ||||
| @@ -12,7 +12,7 @@ struct Toolbar : OpaqueWidget { | |||||
| float cableTension = 0.5; | float cableTension = 0.5; | ||||
| Toolbar(); | Toolbar(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -15,7 +15,7 @@ struct Button : OpaqueWidget { | |||||
| Button(); | Button(); | ||||
| ~Button(); | ~Button(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onEnter(const event::Enter &e) override; | void onEnter(const event::Enter &e) override; | ||||
| void onLeave(const event::Leave &e) override; | void onLeave(const event::Leave &e) override; | ||||
| void onDragStart(const event::DragStart &e) override; | void onDragStart(const event::DragStart &e) override; | ||||
| @@ -7,7 +7,7 @@ namespace rack { | |||||
| struct ChoiceButton : Button { | struct ChoiceButton : Button { | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -19,7 +19,7 @@ struct Label : Widget { | |||||
| Alignment alignment = LEFT_ALIGNMENT; | Alignment alignment = LEFT_ALIGNMENT; | ||||
| Label(); | Label(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -17,7 +17,7 @@ struct Menu : OpaqueWidget { | |||||
| ~Menu(); | ~Menu(); | ||||
| void setChildMenu(Menu *menu); | void setChildMenu(Menu *menu); | ||||
| void step() override; | void step() override; | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onHoverScroll(const event::HoverScroll &e) override; | void onHoverScroll(const event::HoverScroll &e) override; | ||||
| }; | }; | ||||
| @@ -17,7 +17,7 @@ struct MenuItem : MenuEntry { | |||||
| std::string rightText; | std::string rightText; | ||||
| bool disabled = false; | bool disabled = false; | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void step() override; | void step() override; | ||||
| void onEnter(const event::Enter &e) override; | void onEnter(const event::Enter &e) override; | ||||
| void onDragDrop(const event::DragDrop &e) override; | void onDragDrop(const event::DragDrop &e) override; | ||||
| @@ -9,7 +9,7 @@ namespace rack { | |||||
| struct MenuLabel : MenuEntry { | struct MenuLabel : MenuEntry { | ||||
| std::string text; | std::string text; | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void step() override; | void step() override; | ||||
| }; | }; | ||||
| @@ -8,7 +8,7 @@ namespace rack { | |||||
| struct MenuSeparator : MenuEntry { | struct MenuSeparator : MenuEntry { | ||||
| MenuSeparator(); | MenuSeparator(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -7,7 +7,7 @@ namespace rack { | |||||
| struct PasswordField : TextField { | struct PasswordField : TextField { | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -12,7 +12,7 @@ struct ProgressBar : Widget { | |||||
| ProgressBar(); | ProgressBar(); | ||||
| ~ProgressBar(); | ~ProgressBar(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -13,7 +13,7 @@ struct RadioButton : OpaqueWidget { | |||||
| RadioButton(); | RadioButton(); | ||||
| ~RadioButton(); | ~RadioButton(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onEnter(const event::Enter &e) override; | void onEnter(const event::Enter &e) override; | ||||
| void onLeave(const event::Leave &e) override; | void onLeave(const event::Leave &e) override; | ||||
| void onDragDrop(const event::DragDrop &e) override; | void onDragDrop(const event::DragDrop &e) override; | ||||
| @@ -18,7 +18,7 @@ struct ScrollBar : OpaqueWidget { | |||||
| float size = 0.0; | float size = 0.0; | ||||
| ScrollBar(); | ScrollBar(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onDragStart(const event::DragStart &e) override; | void onDragStart(const event::DragStart &e) override; | ||||
| void onDragMove(const event::DragMove &e) override; | void onDragMove(const event::DragMove &e) override; | ||||
| void onDragEnd(const event::DragEnd &e) override; | void onDragEnd(const event::DragEnd &e) override; | ||||
| @@ -16,7 +16,7 @@ struct ScrollWidget : OpaqueWidget { | |||||
| ScrollWidget(); | ScrollWidget(); | ||||
| void scrollTo(math::Rect r); | void scrollTo(math::Rect r); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void step() override; | void step() override; | ||||
| void onHover(const event::Hover &e) override; | void onHover(const event::Hover &e) override; | ||||
| void onHoverScroll(const event::HoverScroll &e) override; | void onHoverScroll(const event::HoverScroll &e) override; | ||||
| @@ -14,7 +14,7 @@ struct Slider : OpaqueWidget { | |||||
| Slider(); | Slider(); | ||||
| ~Slider(); | ~Slider(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onDragStart(const event::DragStart &e) override; | void onDragStart(const event::DragStart &e) override; | ||||
| void onDragMove(const event::DragMove &e) override; | void onDragMove(const event::DragMove &e) override; | ||||
| void onDragEnd(const event::DragEnd &e) override; | void onDragEnd(const event::DragEnd &e) override; | ||||
| @@ -20,7 +20,7 @@ struct TextField : OpaqueWidget { | |||||
| int selection = 0; | int selection = 0; | ||||
| TextField(); | TextField(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onButton(const event::Button &e) override; | void onButton(const event::Button &e) override; | ||||
| void onHover(const event::Hover &e) override; | void onHover(const event::Hover &e) override; | ||||
| void onEnter(const event::Enter &e) override; | void onEnter(const event::Enter &e) override; | ||||
| @@ -10,7 +10,7 @@ struct Tooltip : Widget { | |||||
| std::string text; | std::string text; | ||||
| void step() override; | void step() override; | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| }; | }; | ||||
| @@ -27,7 +27,7 @@ struct FramebufferWidget : Widget { | |||||
| FramebufferWidget(); | FramebufferWidget(); | ||||
| ~FramebufferWidget(); | ~FramebufferWidget(); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| virtual void drawFramebuffer(); | virtual void drawFramebuffer(); | ||||
| int getImageHandle(); | int getImageHandle(); | ||||
| @@ -26,9 +26,9 @@ struct SVGWidget : Widget { | |||||
| wrap(); | wrap(); | ||||
| } | } | ||||
| void draw(NVGcontext *vg) override { | |||||
| void draw(const DrawContext &ctx) override { | |||||
| if (svg && svg->handle) { | if (svg && svg->handle) { | ||||
| svgDraw(vg, svg->handle); | |||||
| svgDraw(ctx.vg, svg->handle); | |||||
| } | } | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -36,10 +36,10 @@ struct TransformWidget : Widget { | |||||
| nvgTransformPremultiply(transform, t); | nvgTransformPremultiply(transform, t); | ||||
| } | } | ||||
| void draw(NVGcontext *vg) override { | |||||
| void draw(const DrawContext &ctx) override { | |||||
| // No need to save the state because that is done in the parent | // No need to save the state because that is done in the parent | ||||
| nvgTransform(vg, transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]); | |||||
| Widget::draw(vg); | |||||
| nvgTransform(ctx.vg, transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]); | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -10,6 +10,11 @@ | |||||
| namespace rack { | namespace rack { | ||||
| struct DrawContext { | |||||
| mutable NVGcontext *vg; | |||||
| }; | |||||
| /** A node in the 2D scene graph | /** A node in the 2D scene graph | ||||
| */ | */ | ||||
| struct Widget { | struct Widget { | ||||
| @@ -67,8 +72,10 @@ struct Widget { | |||||
| /** Advances the module by one frame */ | /** Advances the module by one frame */ | ||||
| virtual void step(); | virtual void step(); | ||||
| /** Draws to NanoVG context */ | |||||
| virtual void draw(NVGcontext *vg); | |||||
| /** Draws the widget to the NanoVG context */ | |||||
| virtual void draw(const DrawContext &ctx); | |||||
| /** Override `draw(const DrawContext &ctx)` instead */ | |||||
| DEPRECATED virtual void draw(NVGcontext *vg) {} | |||||
| // Events | // Events | ||||
| @@ -11,7 +11,7 @@ struct ZoomWidget : Widget { | |||||
| math::Vec getRelativeOffset(math::Vec v, Widget *relative) override; | math::Vec getRelativeOffset(math::Vec v, Widget *relative) override; | ||||
| math::Rect getViewport(math::Rect r) override; | math::Rect getViewport(math::Rect r) override; | ||||
| void setZoom(float zoom); | void setZoom(float zoom); | ||||
| void draw(NVGcontext *vg) override; | |||||
| void draw(const DrawContext &ctx) override; | |||||
| void onHover(const event::Hover &e) override { | void onHover(const event::Hover &e) override { | ||||
| event::Hover e2 = e; | event::Hover e2 = e; | ||||
| @@ -16,12 +16,12 @@ struct BlankPanel : Widget { | |||||
| panelBorder->box.size = box.size; | panelBorder->box.size = box.size; | ||||
| } | } | ||||
| void draw(NVGcontext *vg) override { | |||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| nvgFillColor(vg, nvgRGB(0xe6, 0xe6, 0xe6)); | |||||
| nvgFill(vg); | |||||
| Widget::draw(vg); | |||||
| void draw(const DrawContext &ctx) override { | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| nvgFillColor(ctx.vg, nvgRGB(0xe6, 0xe6, 0xe6)); | |||||
| nvgFill(ctx.vg); | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -64,15 +64,15 @@ struct ModuleResizeHandle : Widget { | |||||
| } | } | ||||
| app()->scene->rackWidget->requestModuleBox(m, newBox); | app()->scene->rackWidget->requestModuleBox(m, newBox); | ||||
| } | } | ||||
| void draw(NVGcontext *vg) override { | |||||
| void draw(const DrawContext &ctx) override { | |||||
| for (float x = 5.0; x <= 10.0; x += 5.0) { | for (float x = 5.0; x <= 10.0; x += 5.0) { | ||||
| nvgBeginPath(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| const float margin = 5.0; | 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); | |||||
| nvgMoveTo(ctx.vg, x + 0.5, margin + 0.5); | |||||
| nvgLineTo(ctx.vg, x + 0.5, box.size.y - margin + 0.5); | |||||
| nvgStrokeWidth(ctx.vg, 1.0); | |||||
| nvgStrokeColor(ctx.vg, nvgRGBAf(0.5, 0.5, 0.5, 0.5)); | |||||
| nvgStroke(ctx.vg); | |||||
| } | } | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -10,67 +10,67 @@ | |||||
| namespace rack { | namespace rack { | ||||
| static void drawPlug(NVGcontext *vg, math::Vec pos, NVGcolor color) { | |||||
| static void drawPlug(const DrawContext &ctx, math::Vec pos, NVGcolor color) { | |||||
| NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | ||||
| // Plug solid | // Plug solid | ||||
| nvgBeginPath(vg); | |||||
| nvgCircle(vg, pos.x, pos.y, 9); | |||||
| nvgFillColor(vg, color); | |||||
| nvgFill(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgCircle(ctx.vg, pos.x, pos.y, 9); | |||||
| nvgFillColor(ctx.vg, color); | |||||
| nvgFill(ctx.vg); | |||||
| // Border | // Border | ||||
| nvgStrokeWidth(vg, 1.0); | |||||
| nvgStrokeColor(vg, colorOutline); | |||||
| nvgStroke(vg); | |||||
| nvgStrokeWidth(ctx.vg, 1.0); | |||||
| nvgStrokeColor(ctx.vg, colorOutline); | |||||
| nvgStroke(ctx.vg); | |||||
| // Hole | // Hole | ||||
| nvgBeginPath(vg); | |||||
| nvgCircle(vg, pos.x, pos.y, 5); | |||||
| nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); | |||||
| nvgFill(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgCircle(ctx.vg, pos.x, pos.y, 5); | |||||
| nvgFillColor(ctx.vg, nvgRGBf(0.0, 0.0, 0.0)); | |||||
| nvgFill(ctx.vg); | |||||
| } | } | ||||
| static void drawCable(NVGcontext *vg, math::Vec pos1, math::Vec pos2, NVGcolor color, float thickness, float tension, float opacity) { | |||||
| static void drawCable(const DrawContext &ctx, math::Vec pos1, math::Vec pos2, NVGcolor color, float thickness, float tension, float opacity) { | |||||
| NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.10); | NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.10); | ||||
| NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | ||||
| // Cable | // Cable | ||||
| if (opacity > 0.0) { | if (opacity > 0.0) { | ||||
| nvgSave(vg); | |||||
| nvgSave(ctx.vg); | |||||
| // This power scaling looks more linear than actual linear scaling | // This power scaling looks more linear than actual linear scaling | ||||
| nvgGlobalAlpha(vg, std::pow(opacity, 1.5)); | |||||
| nvgGlobalAlpha(ctx.vg, std::pow(opacity, 1.5)); | |||||
| float dist = pos1.minus(pos2).norm(); | float dist = pos1.minus(pos2).norm(); | ||||
| math::Vec slump; | math::Vec slump; | ||||
| slump.y = (1.0 - tension) * (150.0 + 1.0*dist); | slump.y = (1.0 - tension) * (150.0 + 1.0*dist); | ||||
| math::Vec pos3 = pos1.plus(pos2).div(2).plus(slump); | math::Vec pos3 = pos1.plus(pos2).div(2).plus(slump); | ||||
| nvgLineJoin(vg, NVG_ROUND); | |||||
| nvgLineJoin(ctx.vg, NVG_ROUND); | |||||
| // Shadow | // Shadow | ||||
| math::Vec pos4 = pos3.plus(slump.mult(0.08)); | math::Vec pos4 = pos3.plus(slump.mult(0.08)); | ||||
| nvgBeginPath(vg); | |||||
| nvgMoveTo(vg, pos1.x, pos1.y); | |||||
| nvgQuadTo(vg, pos4.x, pos4.y, pos2.x, pos2.y); | |||||
| nvgStrokeColor(vg, colorShadow); | |||||
| nvgStrokeWidth(vg, thickness); | |||||
| nvgStroke(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgMoveTo(ctx.vg, pos1.x, pos1.y); | |||||
| nvgQuadTo(ctx.vg, pos4.x, pos4.y, pos2.x, pos2.y); | |||||
| nvgStrokeColor(ctx.vg, colorShadow); | |||||
| nvgStrokeWidth(ctx.vg, thickness); | |||||
| nvgStroke(ctx.vg); | |||||
| // Cable outline | // Cable outline | ||||
| nvgBeginPath(vg); | |||||
| nvgMoveTo(vg, pos1.x, pos1.y); | |||||
| nvgQuadTo(vg, pos3.x, pos3.y, pos2.x, pos2.y); | |||||
| nvgStrokeColor(vg, colorOutline); | |||||
| nvgStrokeWidth(vg, thickness); | |||||
| nvgStroke(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgMoveTo(ctx.vg, pos1.x, pos1.y); | |||||
| nvgQuadTo(ctx.vg, pos3.x, pos3.y, pos2.x, pos2.y); | |||||
| nvgStrokeColor(ctx.vg, colorOutline); | |||||
| nvgStrokeWidth(ctx.vg, thickness); | |||||
| nvgStroke(ctx.vg); | |||||
| // Cable solid | // Cable solid | ||||
| nvgStrokeColor(vg, color); | |||||
| nvgStrokeWidth(vg, thickness - 2); | |||||
| nvgStroke(vg); | |||||
| nvgStrokeColor(ctx.vg, color); | |||||
| nvgStrokeWidth(ctx.vg, thickness - 2); | |||||
| nvgStroke(ctx.vg); | |||||
| nvgRestore(vg); | |||||
| nvgRestore(ctx.vg); | |||||
| } | } | ||||
| } | } | ||||
| @@ -205,7 +205,7 @@ void CableWidget::fromJson(json_t *rootJ, const std::map<int, ModuleWidget*> &mo | |||||
| } | } | ||||
| } | } | ||||
| void CableWidget::draw(NVGcontext *vg) { | |||||
| void CableWidget::draw(const DrawContext &ctx) { | |||||
| float opacity = settings::cableOpacity; | float opacity = settings::cableOpacity; | ||||
| float tension = settings::cableTension; | float tension = settings::cableTension; | ||||
| @@ -235,33 +235,33 @@ void CableWidget::draw(NVGcontext *vg) { | |||||
| math::Vec outputPos = getOutputPos(); | math::Vec outputPos = getOutputPos(); | ||||
| math::Vec inputPos = getInputPos(); | math::Vec inputPos = getInputPos(); | ||||
| drawCable(vg, outputPos, inputPos, color, thickness, tension, opacity); | |||||
| drawCable(ctx, outputPos, inputPos, color, thickness, tension, opacity); | |||||
| } | } | ||||
| void CableWidget::drawPlugs(NVGcontext *vg) { | |||||
| void CableWidget::drawPlugs(const DrawContext &ctx) { | |||||
| // TODO Figure out a way to draw plugs first and cables last, and cut the plug portion of the cable off. | // TODO Figure out a way to draw plugs first and cables last, and cut the plug portion of the cable off. | ||||
| math::Vec outputPos = getOutputPos(); | math::Vec outputPos = getOutputPos(); | ||||
| math::Vec inputPos = getInputPos(); | math::Vec inputPos = getInputPos(); | ||||
| // Draw plug if the cable is on top, or if the cable is incomplete | // Draw plug if the cable is on top, or if the cable is incomplete | ||||
| if (!isComplete() || app()->scene->rackWidget->getTopCable(outputPort) == this) { | if (!isComplete() || app()->scene->rackWidget->getTopCable(outputPort) == this) { | ||||
| drawPlug(vg, outputPos, color); | |||||
| drawPlug(ctx, outputPos, color); | |||||
| if (isComplete()) { | if (isComplete()) { | ||||
| // Draw plug light | // Draw plug light | ||||
| nvgSave(vg); | |||||
| nvgTranslate(vg, outputPos.x - 4, outputPos.y - 4); | |||||
| outputPort->plugLight->draw(vg); | |||||
| nvgRestore(vg); | |||||
| nvgSave(ctx.vg); | |||||
| nvgTranslate(ctx.vg, outputPos.x - 4, outputPos.y - 4); | |||||
| outputPort->plugLight->draw(ctx); | |||||
| nvgRestore(ctx.vg); | |||||
| } | } | ||||
| } | } | ||||
| if (!isComplete() || app()->scene->rackWidget->getTopCable(inputPort) == this) { | if (!isComplete() || app()->scene->rackWidget->getTopCable(inputPort) == this) { | ||||
| drawPlug(vg, inputPos, color); | |||||
| drawPlug(ctx, inputPos, color); | |||||
| if (isComplete()) { | if (isComplete()) { | ||||
| nvgSave(vg); | |||||
| nvgTranslate(vg, inputPos.x - 4, inputPos.y - 4); | |||||
| inputPort->plugLight->draw(vg); | |||||
| nvgRestore(vg); | |||||
| nvgSave(ctx.vg); | |||||
| nvgTranslate(ctx.vg, inputPos.x - 4, inputPos.y - 4); | |||||
| inputPort->plugLight->draw(ctx); | |||||
| nvgRestore(ctx.vg); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -9,19 +9,19 @@ CircularShadow::CircularShadow() { | |||||
| opacity = 0.15; | opacity = 0.15; | ||||
| } | } | ||||
| void CircularShadow::draw(NVGcontext *vg) { | |||||
| void CircularShadow::draw(const DrawContext &ctx) { | |||||
| if (opacity <= 0.0) | if (opacity <= 0.0) | ||||
| return; | return; | ||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, -blurRadius, -blurRadius, box.size.x + 2*blurRadius, box.size.y + 2*blurRadius); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, -blurRadius, -blurRadius, box.size.x + 2*blurRadius, box.size.y + 2*blurRadius); | |||||
| math::Vec center = box.size.div(2.0); | math::Vec center = box.size.div(2.0); | ||||
| float radius = center.x; | float radius = center.x; | ||||
| NVGcolor icol = nvgRGBAf(0.0, 0.0, 0.0, opacity); | NVGcolor icol = nvgRGBAf(0.0, 0.0, 0.0, opacity); | ||||
| NVGcolor ocol = nvgRGBAf(0.0, 0.0, 0.0, 0.0); | NVGcolor ocol = nvgRGBAf(0.0, 0.0, 0.0, 0.0); | ||||
| NVGpaint paint = nvgRadialGradient(vg, center.x, center.y, radius - blurRadius, radius, icol, ocol); | |||||
| nvgFillPaint(vg, paint); | |||||
| nvgFill(vg); | |||||
| NVGpaint paint = nvgRadialGradient(ctx.vg, center.x, center.y, radius - blurRadius, radius, icol, ocol); | |||||
| nvgFillPaint(ctx.vg, paint); | |||||
| nvgFill(ctx.vg); | |||||
| } | } | ||||
| @@ -8,13 +8,13 @@ | |||||
| namespace rack { | namespace rack { | ||||
| void LedDisplay::draw(NVGcontext *vg) { | |||||
| nvgBeginPath(vg); | |||||
| nvgRoundedRect(vg, 0, 0, box.size.x, box.size.y, 5.0); | |||||
| nvgFillColor(vg, nvgRGB(0x00, 0x00, 0x00)); | |||||
| nvgFill(vg); | |||||
| void LedDisplay::draw(const DrawContext &ctx) { | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRoundedRect(ctx.vg, 0, 0, box.size.x, box.size.y, 5.0); | |||||
| nvgFillColor(ctx.vg, nvgRGB(0x00, 0x00, 0x00)); | |||||
| nvgFill(ctx.vg); | |||||
| Widget::draw(vg); | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| @@ -22,13 +22,13 @@ LedDisplaySeparator::LedDisplaySeparator() { | |||||
| box.size = math::Vec(); | box.size = math::Vec(); | ||||
| } | } | ||||
| void LedDisplaySeparator::draw(NVGcontext *vg) { | |||||
| nvgBeginPath(vg); | |||||
| nvgMoveTo(vg, 0, 0); | |||||
| nvgLineTo(vg, box.size.x, box.size.y); | |||||
| nvgStrokeWidth(vg, 1.0); | |||||
| nvgStrokeColor(vg, nvgRGB(0x33, 0x33, 0x33)); | |||||
| nvgStroke(vg); | |||||
| void LedDisplaySeparator::draw(const DrawContext &ctx) { | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgMoveTo(ctx.vg, 0, 0); | |||||
| nvgLineTo(ctx.vg, box.size.x, box.size.y); | |||||
| nvgStrokeWidth(ctx.vg, 1.0); | |||||
| nvgStrokeColor(ctx.vg, nvgRGB(0x33, 0x33, 0x33)); | |||||
| nvgStroke(ctx.vg); | |||||
| } | } | ||||
| @@ -39,19 +39,19 @@ LedDisplayChoice::LedDisplayChoice() { | |||||
| textOffset = math::Vec(10, 18); | textOffset = math::Vec(10, 18); | ||||
| } | } | ||||
| void LedDisplayChoice::draw(NVGcontext *vg) { | |||||
| nvgScissor(vg, 0, 0, box.size.x, box.size.y); | |||||
| void LedDisplayChoice::draw(const DrawContext &ctx) { | |||||
| nvgScissor(ctx.vg, 0, 0, box.size.x, box.size.y); | |||||
| if (font->handle >= 0) { | if (font->handle >= 0) { | ||||
| nvgFillColor(vg, color); | |||||
| nvgFontFaceId(vg, font->handle); | |||||
| nvgTextLetterSpacing(vg, 0.0); | |||||
| nvgFillColor(ctx.vg, color); | |||||
| nvgFontFaceId(ctx.vg, font->handle); | |||||
| nvgTextLetterSpacing(ctx.vg, 0.0); | |||||
| nvgFontSize(vg, 12); | |||||
| nvgText(vg, textOffset.x, textOffset.y, text.c_str(), NULL); | |||||
| nvgFontSize(ctx.vg, 12); | |||||
| nvgText(ctx.vg, textOffset.x, textOffset.y, text.c_str(), NULL); | |||||
| } | } | ||||
| nvgResetScissor(vg); | |||||
| nvgResetScissor(ctx.vg); | |||||
| } | } | ||||
| void LedDisplayChoice::onButton(const event::Button &e) { | void LedDisplayChoice::onButton(const event::Button &e) { | ||||
| @@ -70,14 +70,14 @@ LedDisplayTextField::LedDisplayTextField() { | |||||
| } | } | ||||
| void LedDisplayTextField::draw(NVGcontext *vg) { | |||||
| nvgScissor(vg, 0, 0, box.size.x, box.size.y); | |||||
| void LedDisplayTextField::draw(const DrawContext &ctx) { | |||||
| nvgScissor(ctx.vg, 0, 0, box.size.x, box.size.y); | |||||
| // Background | // Background | ||||
| nvgBeginPath(vg); | |||||
| nvgRoundedRect(vg, 0, 0, box.size.x, box.size.y, 5.0); | |||||
| nvgFillColor(vg, nvgRGB(0x00, 0x00, 0x00)); | |||||
| nvgFill(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRoundedRect(ctx.vg, 0, 0, box.size.x, box.size.y, 5.0); | |||||
| nvgFillColor(ctx.vg, nvgRGB(0x00, 0x00, 0x00)); | |||||
| nvgFill(ctx.vg); | |||||
| // Text | // Text | ||||
| if (font->handle >= 0) { | if (font->handle >= 0) { | ||||
| @@ -87,14 +87,14 @@ void LedDisplayTextField::draw(NVGcontext *vg) { | |||||
| highlightColor.a = 0.5; | highlightColor.a = 0.5; | ||||
| int begin = std::min(cursor, selection); | int begin = std::min(cursor, selection); | ||||
| int end = (this == app()->event->selectedWidget) ? std::max(cursor, selection) : -1; | int end = (this == app()->event->selectedWidget) ? std::max(cursor, selection) : -1; | ||||
| bndIconLabelCaret(vg, textOffset.x, textOffset.y, | |||||
| bndIconLabelCaret(ctx.vg, textOffset.x, textOffset.y, | |||||
| box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y, | box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y, | ||||
| -1, color, 12, text.c_str(), highlightColor, begin, end); | -1, color, 12, text.c_str(), highlightColor, begin, end); | ||||
| bndSetFont(app()->window->uiFont->handle); | bndSetFont(app()->window->uiFont->handle); | ||||
| } | } | ||||
| nvgResetScissor(vg); | |||||
| nvgResetScissor(ctx.vg); | |||||
| } | } | ||||
| int LedDisplayTextField::getTextPosition(math::Vec mousePos) { | int LedDisplayTextField::getTextPosition(math::Vec mousePos) { | ||||
| @@ -5,45 +5,45 @@ | |||||
| namespace rack { | namespace rack { | ||||
| void LightWidget::draw(NVGcontext *vg) { | |||||
| drawLight(vg); | |||||
| drawHalo(vg); | |||||
| void LightWidget::draw(const DrawContext &ctx) { | |||||
| drawLight(ctx); | |||||
| drawHalo(ctx); | |||||
| } | } | ||||
| void LightWidget::drawLight(NVGcontext *vg) { | |||||
| void LightWidget::drawLight(const DrawContext &ctx) { | |||||
| float radius = box.size.x / 2.0; | float radius = box.size.x / 2.0; | ||||
| nvgBeginPath(vg); | |||||
| nvgCircle(vg, radius, radius, radius); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgCircle(ctx.vg, radius, radius, radius); | |||||
| // Background | // Background | ||||
| nvgFillColor(vg, bgColor); | |||||
| nvgFill(vg); | |||||
| nvgFillColor(ctx.vg, bgColor); | |||||
| nvgFill(ctx.vg); | |||||
| // Foreground | // Foreground | ||||
| nvgFillColor(vg, color); | |||||
| nvgFill(vg); | |||||
| nvgFillColor(ctx.vg, color); | |||||
| nvgFill(ctx.vg); | |||||
| // Border | // Border | ||||
| nvgStrokeWidth(vg, 0.5); | |||||
| nvgStrokeColor(vg, borderColor); | |||||
| nvgStroke(vg); | |||||
| nvgStrokeWidth(ctx.vg, 0.5); | |||||
| nvgStrokeColor(ctx.vg, borderColor); | |||||
| nvgStroke(ctx.vg); | |||||
| } | } | ||||
| void LightWidget::drawHalo(NVGcontext *vg) { | |||||
| void LightWidget::drawHalo(const DrawContext &ctx) { | |||||
| float radius = box.size.x / 2.0; | float radius = box.size.x / 2.0; | ||||
| float oradius = radius + 15.0; | float oradius = radius + 15.0; | ||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, radius - oradius, radius - oradius, 2*oradius, 2*oradius); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, radius - oradius, radius - oradius, 2*oradius, 2*oradius); | |||||
| NVGpaint paint; | NVGpaint paint; | ||||
| NVGcolor icol = color::mult(color, 0.08); | NVGcolor icol = color::mult(color, 0.08); | ||||
| NVGcolor ocol = nvgRGB(0, 0, 0); | NVGcolor ocol = nvgRGB(0, 0, 0); | ||||
| paint = nvgRadialGradient(vg, radius, radius, radius, oradius, icol, ocol); | |||||
| nvgFillPaint(vg, paint); | |||||
| nvgGlobalCompositeOperation(vg, NVG_LIGHTER); | |||||
| nvgFill(vg); | |||||
| paint = nvgRadialGradient(ctx.vg, radius, radius, radius, oradius, icol, ocol); | |||||
| nvgFillPaint(ctx.vg, paint); | |||||
| nvgGlobalCompositeOperation(ctx.vg, NVG_LIGHTER); | |||||
| nvgFill(ctx.vg); | |||||
| } | } | ||||
| @@ -47,9 +47,7 @@ struct ModuleBox : OpaqueWidget { | |||||
| addChild(pluginLabel); | addChild(pluginLabel); | ||||
| } | } | ||||
| void draw(NVGcontext *vg) override { | |||||
| DEBUG("%p model", model); | |||||
| void draw(const DrawContext &ctx) override { | |||||
| // Lazily create ModuleWidget when drawn | // Lazily create ModuleWidget when drawn | ||||
| if (!initialized) { | if (!initialized) { | ||||
| Widget *transparentWidget = new TransparentWidget; | Widget *transparentWidget = new TransparentWidget; | ||||
| @@ -76,12 +74,12 @@ struct ModuleBox : OpaqueWidget { | |||||
| initialized = true; | initialized = true; | ||||
| } | } | ||||
| OpaqueWidget::draw(vg); | |||||
| OpaqueWidget::draw(ctx); | |||||
| if (app()->event->hoveredWidget == this) { | if (app()->event->hoveredWidget == this) { | ||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| nvgFillColor(vg, nvgRGBAf(1, 1, 1, 0.25)); | |||||
| nvgFill(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| nvgFillColor(ctx.vg, nvgRGBAf(1, 1, 1, 0.25)); | |||||
| nvgFill(ctx.vg); | |||||
| } | } | ||||
| } | } | ||||
| @@ -137,9 +135,9 @@ void ModuleBrowser::step() { | |||||
| OpaqueWidget::step(); | OpaqueWidget::step(); | ||||
| } | } | ||||
| void ModuleBrowser::draw(NVGcontext *vg) { | |||||
| bndMenuBackground(vg, 0.0, 0.0, box.size.x, box.size.y, 0); | |||||
| Widget::draw(vg); | |||||
| void ModuleBrowser::draw(const DrawContext &ctx) { | |||||
| bndMenuBackground(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, 0); | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| void ModuleBrowser::onHoverKey(const event::HoverKey &e) { | void ModuleBrowser::onHoverKey(const event::HoverKey &e) { | ||||
| @@ -136,57 +136,57 @@ ModuleWidget::~ModuleWidget() { | |||||
| setModule(NULL); | setModule(NULL); | ||||
| } | } | ||||
| void ModuleWidget::draw(NVGcontext *vg) { | |||||
| void ModuleWidget::draw(const DrawContext &ctx) { | |||||
| if (module && module->bypass) { | if (module && module->bypass) { | ||||
| nvgGlobalAlpha(vg, 0.5); | |||||
| nvgGlobalAlpha(ctx.vg, 0.5); | |||||
| } | } | ||||
| // nvgScissor(vg, 0, 0, box.size.x, box.size.y); | |||||
| Widget::draw(vg); | |||||
| // nvgScissor(ctx.vg, 0, 0, box.size.x, box.size.y); | |||||
| Widget::draw(ctx); | |||||
| // Power meter | // Power meter | ||||
| if (module && settings::powerMeter) { | if (module && settings::powerMeter) { | ||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, | |||||
| 0, box.size.y - 20, | 0, box.size.y - 20, | ||||
| 65, 20); | 65, 20); | ||||
| nvgFillColor(vg, nvgRGBAf(0, 0, 0, 0.75)); | |||||
| nvgFill(vg); | |||||
| nvgFillColor(ctx.vg, nvgRGBAf(0, 0, 0, 0.75)); | |||||
| nvgFill(ctx.vg); | |||||
| std::string cpuText = string::f("%.2f ÎĽs", module->cpuTime * 1e6f); | std::string cpuText = string::f("%.2f ÎĽs", module->cpuTime * 1e6f); | ||||
| bndLabel(vg, 2.0, box.size.y - 20.0, INFINITY, INFINITY, -1, cpuText.c_str()); | |||||
| bndLabel(ctx.vg, 2.0, box.size.y - 20.0, INFINITY, INFINITY, -1, cpuText.c_str()); | |||||
| float p = math::clamp(module->cpuTime / app()->engine->getSampleTime(), 0.f, 1.f); | float p = math::clamp(module->cpuTime / app()->engine->getSampleTime(), 0.f, 1.f); | ||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, | |||||
| 0, (1.f - p) * box.size.y, | 0, (1.f - p) * box.size.y, | ||||
| 5, p * box.size.y); | 5, p * box.size.y); | ||||
| nvgFillColor(vg, nvgRGBAf(1, 0, 0, 1.0)); | |||||
| nvgFill(vg); | |||||
| nvgFillColor(ctx.vg, nvgRGBAf(1, 0, 0, 1.0)); | |||||
| nvgFill(ctx.vg); | |||||
| } | } | ||||
| // if (module) { | // if (module) { | ||||
| // nvgBeginPath(vg); | |||||
| // nvgRect(vg, 0, 0, 20, 20); | |||||
| // nvgFillColor(vg, nvgRGBAf(0, 0, 0, 0.75)); | |||||
| // nvgFill(vg); | |||||
| // nvgBeginPath(ctx.vg); | |||||
| // nvgRect(ctx.vg, 0, 0, 20, 20); | |||||
| // nvgFillColor(ctx.vg, nvgRGBAf(0, 0, 0, 0.75)); | |||||
| // nvgFill(ctx.vg); | |||||
| // std::string debugText = string::f("%d", module->id); | // std::string debugText = string::f("%d", module->id); | ||||
| // bndLabel(vg, 0, 0, INFINITY, INFINITY, -1, debugText.c_str()); | |||||
| // bndLabel(ctx.vg, 0, 0, INFINITY, INFINITY, -1, debugText.c_str()); | |||||
| // } | // } | ||||
| // nvgResetScissor(vg); | |||||
| // nvgResetScissor(ctx.vg); | |||||
| } | } | ||||
| void ModuleWidget::drawShadow(NVGcontext *vg) { | |||||
| nvgBeginPath(vg); | |||||
| void ModuleWidget::drawShadow(const DrawContext &ctx) { | |||||
| nvgBeginPath(ctx.vg); | |||||
| float r = 20; // Blur radius | float r = 20; // Blur radius | ||||
| float c = 20; // Corner radius | float c = 20; // Corner radius | ||||
| math::Vec b = math::Vec(-10, 30); // Offset from each corner | math::Vec b = math::Vec(-10, 30); // Offset from each corner | ||||
| nvgRect(vg, b.x - r, b.y - r, box.size.x - 2*b.x + 2*r, box.size.y - 2*b.y + 2*r); | |||||
| nvgRect(ctx.vg, b.x - r, b.y - r, box.size.x - 2*b.x + 2*r, box.size.y - 2*b.y + 2*r); | |||||
| NVGcolor shadowColor = nvgRGBAf(0, 0, 0, 0.2); | NVGcolor shadowColor = nvgRGBAf(0, 0, 0, 0.2); | ||||
| NVGcolor transparentColor = nvgRGBAf(0, 0, 0, 0); | NVGcolor transparentColor = nvgRGBAf(0, 0, 0, 0); | ||||
| nvgFillPaint(vg, nvgBoxGradient(vg, b.x, b.y, box.size.x - 2*b.x, box.size.y - 2*b.y, c, r, shadowColor, transparentColor)); | |||||
| nvgFill(vg); | |||||
| nvgFillPaint(ctx.vg, nvgBoxGradient(ctx.vg, b.x, b.y, box.size.x - 2*b.x, box.size.y - 2*b.y, c, r, shadowColor, transparentColor)); | |||||
| nvgFill(ctx.vg); | |||||
| } | } | ||||
| void ModuleWidget::onHover(const event::Hover &e) { | void ModuleWidget::onHover(const event::Hover &e) { | ||||
| @@ -125,19 +125,19 @@ void ParamWidget::step() { | |||||
| OpaqueWidget::step(); | OpaqueWidget::step(); | ||||
| } | } | ||||
| void ParamWidget::draw(NVGcontext *vg) { | |||||
| Widget::draw(vg); | |||||
| void ParamWidget::draw(const DrawContext &ctx) { | |||||
| Widget::draw(ctx); | |||||
| // if (paramQuantity) { | // if (paramQuantity) { | ||||
| // nvgBeginPath(vg); | |||||
| // nvgRect(vg, | |||||
| // nvgBeginPath(ctx.vg); | |||||
| // nvgRect(ctx.vg, | |||||
| // box.size.x - 12, box.size.y - 12, | // box.size.x - 12, box.size.y - 12, | ||||
| // 12, 12); | // 12, 12); | ||||
| // nvgFillColor(vg, nvgRGBAf(1, 0, 1, 0.9)); | |||||
| // nvgFill(vg); | |||||
| // nvgFillColor(ctx.vg, nvgRGBAf(1, 0, 1, 0.9)); | |||||
| // nvgFill(ctx.vg); | |||||
| // std::string mapText = string::f("%d", paramQuantity->paramId); | // std::string mapText = string::f("%d", paramQuantity->paramId); | ||||
| // bndLabel(vg, box.size.x - 17.0, box.size.y - 16.0, INFINITY, INFINITY, -1, mapText.c_str()); | |||||
| // bndLabel(ctx.vg, box.size.x - 17.0, box.size.y - 16.0, INFINITY, INFINITY, -1, mapText.c_str()); | |||||
| // } | // } | ||||
| } | } | ||||
| @@ -51,14 +51,14 @@ void PortWidget::step() { | |||||
| plugLight->setBrightnesses(values); | plugLight->setBrightnesses(values); | ||||
| } | } | ||||
| void PortWidget::draw(NVGcontext *vg) { | |||||
| void PortWidget::draw(const DrawContext &ctx) { | |||||
| CableWidget *cw = app()->scene->rackWidget->incompleteCable; | CableWidget *cw = app()->scene->rackWidget->incompleteCable; | ||||
| if (cw) { | if (cw) { | ||||
| // Dim the PortWidget if the active cable cannot plug into this PortWidget | // Dim the PortWidget if the active cable cannot plug into this PortWidget | ||||
| if (type == OUTPUT ? cw->outputPort : cw->inputPort) | if (type == OUTPUT ? cw->outputPort : cw->inputPort) | ||||
| nvgGlobalAlpha(vg, 0.5); | |||||
| nvgGlobalAlpha(ctx.vg, 0.5); | |||||
| } | } | ||||
| Widget::draw(vg); | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| void PortWidget::onButton(const event::Button &e) { | void PortWidget::onButton(const event::Button &e) { | ||||
| @@ -3,57 +3,57 @@ | |||||
| namespace rack { | namespace rack { | ||||
| void RackRail::draw(NVGcontext *vg) { | |||||
| void RackRail::draw(const DrawContext &ctx) { | |||||
| const float railHeight = RACK_GRID_WIDTH; | const float railHeight = RACK_GRID_WIDTH; | ||||
| // Background color | // Background color | ||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| nvgFillColor(vg, nvgRGBf(0.2, 0.2, 0.2)); | |||||
| nvgFill(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| nvgFillColor(ctx.vg, nvgRGBf(0.2, 0.2, 0.2)); | |||||
| nvgFill(ctx.vg); | |||||
| // Rails | // Rails | ||||
| nvgFillColor(vg, nvgRGBf(0.85, 0.85, 0.85)); | |||||
| nvgStrokeWidth(vg, 1.0); | |||||
| nvgStrokeColor(vg, nvgRGBf(0.7, 0.7, 0.7)); | |||||
| nvgFillColor(ctx.vg, nvgRGBf(0.85, 0.85, 0.85)); | |||||
| nvgStrokeWidth(ctx.vg, 1.0); | |||||
| nvgStrokeColor(ctx.vg, nvgRGBf(0.7, 0.7, 0.7)); | |||||
| float holeRadius = 3.5; | float holeRadius = 3.5; | ||||
| for (float railY = 0; railY < box.size.y; railY += RACK_GRID_HEIGHT) { | for (float railY = 0; railY < box.size.y; railY += RACK_GRID_HEIGHT) { | ||||
| // Top rail | // Top rail | ||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, 0, railY, box.size.x, railHeight); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, 0, railY, box.size.x, railHeight); | |||||
| for (float railX = 0; railX < box.size.x; railX += RACK_GRID_WIDTH) { | for (float railX = 0; railX < box.size.x; railX += RACK_GRID_WIDTH) { | ||||
| nvgCircle(vg, railX + RACK_GRID_WIDTH / 2, railY + railHeight / 2, holeRadius); | |||||
| nvgPathWinding(vg, NVG_HOLE); | |||||
| nvgCircle(ctx.vg, railX + RACK_GRID_WIDTH / 2, railY + railHeight / 2, holeRadius); | |||||
| nvgPathWinding(ctx.vg, NVG_HOLE); | |||||
| } | } | ||||
| nvgFill(vg); | |||||
| nvgFill(ctx.vg); | |||||
| nvgBeginPath(vg); | |||||
| nvgMoveTo(vg, 0, railY + railHeight - 0.5); | |||||
| nvgLineTo(vg, box.size.x, railY + railHeight - 0.5); | |||||
| nvgStroke(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgMoveTo(ctx.vg, 0, railY + railHeight - 0.5); | |||||
| nvgLineTo(ctx.vg, box.size.x, railY + railHeight - 0.5); | |||||
| nvgStroke(ctx.vg); | |||||
| // Bottom rail | // Bottom rail | ||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, 0, railY + RACK_GRID_HEIGHT - railHeight, box.size.x, railHeight); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, 0, railY + RACK_GRID_HEIGHT - railHeight, box.size.x, railHeight); | |||||
| for (float railX = 0; railX < box.size.x; railX += RACK_GRID_WIDTH) { | for (float railX = 0; railX < box.size.x; railX += RACK_GRID_WIDTH) { | ||||
| nvgCircle(vg, railX + RACK_GRID_WIDTH / 2, railY + RACK_GRID_HEIGHT - railHeight + railHeight / 2, holeRadius); | |||||
| nvgPathWinding(vg, NVG_HOLE); | |||||
| nvgCircle(ctx.vg, railX + RACK_GRID_WIDTH / 2, railY + RACK_GRID_HEIGHT - railHeight + railHeight / 2, holeRadius); | |||||
| nvgPathWinding(ctx.vg, NVG_HOLE); | |||||
| } | } | ||||
| nvgFill(vg); | |||||
| nvgFill(ctx.vg); | |||||
| nvgBeginPath(vg); | |||||
| nvgMoveTo(vg, 0, railY + RACK_GRID_HEIGHT - 0.5); | |||||
| nvgLineTo(vg, box.size.x, railY + RACK_GRID_HEIGHT - 0.5); | |||||
| nvgStroke(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgMoveTo(ctx.vg, 0, railY + RACK_GRID_HEIGHT - 0.5); | |||||
| nvgLineTo(ctx.vg, box.size.x, railY + RACK_GRID_HEIGHT - 0.5); | |||||
| nvgStroke(ctx.vg); | |||||
| } | } | ||||
| // Useful for screenshots | // Useful for screenshots | ||||
| if (0) { | if (0) { | ||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| nvgFillColor(vg, nvgRGBf(1.0, 1.0, 1.0)); | |||||
| nvgFill(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| nvgFillColor(ctx.vg, nvgRGBf(1.0, 1.0, 1.0)); | |||||
| nvgFill(ctx.vg); | |||||
| } | } | ||||
| } | } | ||||
| @@ -27,20 +27,20 @@ void RackScrollWidget::step() { | |||||
| } | } | ||||
| void RackScrollWidget::draw(NVGcontext *vg) { | |||||
| ScrollWidget::draw(vg); | |||||
| void RackScrollWidget::draw(const DrawContext &ctx) { | |||||
| ScrollWidget::draw(ctx); | |||||
| if (app()->scene->rackWidget->isEmpty()) { | if (app()->scene->rackWidget->isEmpty()) { | ||||
| math::Rect b; | math::Rect b; | ||||
| b.size = math::Vec(600, 300); | b.size = math::Vec(600, 300); | ||||
| b.pos = box.size.minus(b.size).div(2); | b.pos = box.size.minus(b.size).div(2); | ||||
| NVGcolor bg = nvgRGBAf(0, 0, 0, 0.4); | NVGcolor bg = nvgRGBAf(0, 0, 0, 0.4); | ||||
| bndInnerBox(vg, b.pos.x, b.pos.y, b.size.x, b.size.y, | |||||
| bndInnerBox(ctx.vg, b.pos.x, b.pos.y, b.size.x, b.size.y, | |||||
| 0, 0, 0, 0, bg, bg); | 0, 0, 0, 0, bg, bg); | ||||
| NVGcolor fg = nvgRGBAf(1, 1, 1, 0.25); | NVGcolor fg = nvgRGBAf(1, 1, 1, 0.25); | ||||
| std::string text = "Right-click or press Enter to add modules"; | std::string text = "Right-click or press Enter to add modules"; | ||||
| bndIconLabelValue(vg, b.pos.x, b.pos.y + 80, b.size.x, b.size.y, -1, fg, BND_CENTER, 80, text.c_str(), NULL); | |||||
| bndIconLabelValue(ctx.vg, b.pos.x, b.pos.y + 80, b.size.x, b.size.y, -1, fg, BND_CENTER, 80, text.c_str(), NULL); | |||||
| } | } | ||||
| } | } | ||||
| @@ -42,32 +42,32 @@ static ModuleWidget *moduleFromJson(json_t *moduleJ) { | |||||
| struct ModuleContainer : Widget { | struct ModuleContainer : Widget { | ||||
| void draw(NVGcontext *vg) override { | |||||
| void draw(const DrawContext &ctx) override { | |||||
| // Draw shadows behind each ModuleWidget first, so the shadow doesn't overlap the front of other ModuleWidgets. | // Draw shadows behind each ModuleWidget first, so the shadow doesn't overlap the front of other ModuleWidgets. | ||||
| for (Widget *child : children) { | for (Widget *child : children) { | ||||
| ModuleWidget *w = dynamic_cast<ModuleWidget*>(child); | ModuleWidget *w = dynamic_cast<ModuleWidget*>(child); | ||||
| assert(w); | assert(w); | ||||
| nvgSave(vg); | |||||
| nvgTranslate(vg, child->box.pos.x, child->box.pos.y); | |||||
| w->drawShadow(vg); | |||||
| nvgRestore(vg); | |||||
| nvgSave(ctx.vg); | |||||
| nvgTranslate(ctx.vg, child->box.pos.x, child->box.pos.y); | |||||
| w->drawShadow(ctx); | |||||
| nvgRestore(ctx.vg); | |||||
| } | } | ||||
| Widget::draw(vg); | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| }; | }; | ||||
| struct CableContainer : TransparentWidget { | struct CableContainer : TransparentWidget { | ||||
| void draw(NVGcontext *vg) override { | |||||
| Widget::draw(vg); | |||||
| void draw(const DrawContext &ctx) override { | |||||
| Widget::draw(ctx); | |||||
| // Draw cable plugs | // Draw cable plugs | ||||
| for (Widget *w : children) { | for (Widget *w : children) { | ||||
| CableWidget *cw = dynamic_cast<CableWidget*>(w); | CableWidget *cw = dynamic_cast<CableWidget*>(w); | ||||
| assert(cw); | assert(cw); | ||||
| cw->drawPlugs(vg); | |||||
| cw->drawPlugs(ctx); | |||||
| } | } | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -116,8 +116,8 @@ void RackWidget::step() { | |||||
| Widget::step(); | Widget::step(); | ||||
| } | } | ||||
| void RackWidget::draw(NVGcontext *vg) { | |||||
| Widget::draw(vg); | |||||
| void RackWidget::draw(const DrawContext &ctx) { | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| void RackWidget::onHover(const event::Hover &e) { | void RackWidget::onHover(const event::Hover &e) { | ||||
| @@ -4,13 +4,13 @@ | |||||
| namespace rack { | namespace rack { | ||||
| void PanelBorder::draw(NVGcontext *vg) { | |||||
| void PanelBorder::draw(const DrawContext &ctx) { | |||||
| NVGcolor borderColor = nvgRGBAf(0.5, 0.5, 0.5, 0.5); | NVGcolor borderColor = nvgRGBAf(0.5, 0.5, 0.5, 0.5); | ||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, 0.5, 0.5, box.size.x - 1.0, box.size.y - 1.0); | |||||
| nvgStrokeColor(vg, borderColor); | |||||
| nvgStrokeWidth(vg, 1.0); | |||||
| nvgStroke(vg); | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, 0.5, 0.5, box.size.x - 1.0, box.size.y - 1.0); | |||||
| nvgStrokeColor(ctx.vg, borderColor); | |||||
| nvgStrokeWidth(ctx.vg, 1.0); | |||||
| nvgStroke(ctx.vg); | |||||
| } | } | ||||
| @@ -85,8 +85,8 @@ void Scene::step() { | |||||
| } | } | ||||
| } | } | ||||
| void Scene::draw(NVGcontext *vg) { | |||||
| OpaqueWidget::draw(vg); | |||||
| void Scene::draw(const DrawContext &ctx) { | |||||
| OpaqueWidget::draw(ctx); | |||||
| } | } | ||||
| void Scene::onHoverKey(const event::HoverKey &e) { | void Scene::onHoverKey(const event::HoverKey &e) { | ||||
| @@ -26,8 +26,8 @@ struct MenuButton : Button { | |||||
| box.size.x = bndLabelWidth(app()->window->vg, -1, text.c_str()); | box.size.x = bndLabelWidth(app()->window->vg, -1, text.c_str()); | ||||
| Widget::step(); | Widget::step(); | ||||
| } | } | ||||
| void draw(NVGcontext *vg) override { | |||||
| bndMenuItem(vg, 0.0, 0.0, box.size.x, box.size.y, state, -1, text.c_str()); | |||||
| void draw(const DrawContext &ctx) override { | |||||
| bndMenuItem(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, state, -1, text.c_str()); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -570,16 +570,16 @@ struct PluginsButton : MenuButton { | |||||
| } | } | ||||
| } | } | ||||
| void draw(NVGcontext *vg) override { | |||||
| MenuButton::draw(vg); | |||||
| void draw(const DrawContext &ctx) override { | |||||
| MenuButton::draw(ctx); | |||||
| // if (1) { | // if (1) { | ||||
| // // Notification circle | // // Notification circle | ||||
| // nvgBeginPath(vg); | |||||
| // nvgCircle(vg, box.size.x - 3, 3, 4.0); | |||||
| // nvgFillColor(vg, nvgRGBf(1.0, 0.0, 0.0)); | |||||
| // nvgFill(vg); | |||||
| // nvgStrokeColor(vg, nvgRGBf(0.5, 0.0, 0.0)); | |||||
| // nvgStroke(vg); | |||||
| // nvgBeginPath(ctx.vg); | |||||
| // nvgCircle(ctx.vg, box.size.x - 3, 3, 4.0); | |||||
| // nvgFillColor(ctx.vg, nvgRGBf(1.0, 0.0, 0.0)); | |||||
| // nvgFill(ctx.vg); | |||||
| // nvgStrokeColor(ctx.vg, nvgRGBf(0.5, 0.0, 0.0)); | |||||
| // nvgStroke(ctx.vg); | |||||
| // } | // } | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -664,11 +664,11 @@ Toolbar::Toolbar() { | |||||
| layout->addChild(helpButton); | layout->addChild(helpButton); | ||||
| } | } | ||||
| void Toolbar::draw(NVGcontext *vg) { | |||||
| bndMenuBackground(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_ALL); | |||||
| bndBevel(vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| void Toolbar::draw(const DrawContext &ctx) { | |||||
| bndMenuBackground(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_ALL); | |||||
| bndBevel(ctx.vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| Widget::draw(vg); | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| @@ -13,8 +13,8 @@ Button::~Button() { | |||||
| delete quantity; | delete quantity; | ||||
| } | } | ||||
| void Button::draw(NVGcontext *vg) { | |||||
| bndToolButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); | |||||
| void Button::draw(const DrawContext &ctx) { | |||||
| bndToolButton(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); | |||||
| } | } | ||||
| void Button::onEnter(const event::Enter &e) { | void Button::onEnter(const event::Enter &e) { | ||||
| @@ -4,8 +4,8 @@ | |||||
| namespace rack { | namespace rack { | ||||
| void ChoiceButton::draw(NVGcontext *vg) { | |||||
| bndChoiceButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); | |||||
| void ChoiceButton::draw(const DrawContext &ctx) { | |||||
| bndChoiceButton(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str()); | |||||
| } | } | ||||
| @@ -10,7 +10,7 @@ Label::Label() { | |||||
| color = bndGetTheme()->regularTheme.textColor; | color = bndGetTheme()->regularTheme.textColor; | ||||
| } | } | ||||
| void Label::draw(NVGcontext *vg) { | |||||
| void Label::draw(const DrawContext &ctx) { | |||||
| // TODO | // TODO | ||||
| // Custom font sizes do not work with right or center alignment | // Custom font sizes do not work with right or center alignment | ||||
| float x; | float x; | ||||
| @@ -20,14 +20,14 @@ void Label::draw(NVGcontext *vg) { | |||||
| x = 0.0; | x = 0.0; | ||||
| } break; | } break; | ||||
| case RIGHT_ALIGNMENT: { | case RIGHT_ALIGNMENT: { | ||||
| x = box.size.x - bndLabelWidth(vg, -1, text.c_str()); | |||||
| x = box.size.x - bndLabelWidth(ctx.vg, -1, text.c_str()); | |||||
| } break; | } break; | ||||
| case CENTER_ALIGNMENT: { | case CENTER_ALIGNMENT: { | ||||
| x = (box.size.x - bndLabelWidth(vg, -1, text.c_str())) / 2.0; | |||||
| x = (box.size.x - bndLabelWidth(ctx.vg, -1, text.c_str())) / 2.0; | |||||
| } break; | } break; | ||||
| } | } | ||||
| bndIconLabelValue(vg, x, 0.0, box.size.x, box.size.y, -1, color, BND_LEFT, fontSize, text.c_str(), NULL); | |||||
| bndIconLabelValue(ctx.vg, x, 0.0, box.size.x, box.size.y, -1, color, BND_LEFT, fontSize, text.c_str(), NULL); | |||||
| } | } | ||||
| @@ -48,9 +48,9 @@ void Menu::step() { | |||||
| } | } | ||||
| } | } | ||||
| void Menu::draw(NVGcontext *vg) { | |||||
| bndMenuBackground(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE); | |||||
| Widget::draw(vg); | |||||
| void Menu::draw(const DrawContext &ctx) { | |||||
| bndMenuBackground(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE); | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| void Menu::onHoverScroll(const event::HoverScroll &e) { | void Menu::onHoverScroll(const event::HoverScroll &e) { | ||||
| @@ -4,7 +4,7 @@ | |||||
| namespace rack { | namespace rack { | ||||
| void MenuItem::draw(NVGcontext *vg) { | |||||
| void MenuItem::draw(const DrawContext &ctx) { | |||||
| BNDwidgetState state = BND_DEFAULT; | BNDwidgetState state = BND_DEFAULT; | ||||
| if (app()->event->hoveredWidget == this) | if (app()->event->hoveredWidget == this) | ||||
| @@ -17,14 +17,14 @@ void MenuItem::draw(NVGcontext *vg) { | |||||
| // Main text and background | // Main text and background | ||||
| if (!disabled) | if (!disabled) | ||||
| bndMenuItem(vg, 0.0, 0.0, box.size.x, box.size.y, state, -1, text.c_str()); | |||||
| bndMenuItem(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, state, -1, text.c_str()); | |||||
| else | else | ||||
| bndMenuLabel(vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str()); | |||||
| bndMenuLabel(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str()); | |||||
| // Right text | // Right text | ||||
| float x = box.size.x - bndLabelWidth(vg, -1, rightText.c_str()); | |||||
| float x = box.size.x - bndLabelWidth(ctx.vg, -1, rightText.c_str()); | |||||
| NVGcolor rightColor = (state == BND_DEFAULT && !disabled) ? bndGetTheme()->menuTheme.textColor : bndGetTheme()->menuTheme.textSelectedColor; | NVGcolor rightColor = (state == BND_DEFAULT && !disabled) ? bndGetTheme()->menuTheme.textColor : bndGetTheme()->menuTheme.textSelectedColor; | ||||
| bndIconLabelValue(vg, x, 0.0, box.size.x, box.size.y, -1, rightColor, BND_LEFT, BND_LABEL_FONT_SIZE, rightText.c_str(), NULL); | |||||
| bndIconLabelValue(ctx.vg, x, 0.0, box.size.x, box.size.y, -1, rightColor, BND_LEFT, BND_LABEL_FONT_SIZE, rightText.c_str(), NULL); | |||||
| } | } | ||||
| void MenuItem::step() { | void MenuItem::step() { | ||||
| @@ -5,8 +5,8 @@ | |||||
| namespace rack { | namespace rack { | ||||
| void MenuLabel::draw(NVGcontext *vg) { | |||||
| bndMenuLabel(vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str()); | |||||
| void MenuLabel::draw(const DrawContext &ctx) { | |||||
| bndMenuLabel(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str()); | |||||
| } | } | ||||
| void MenuLabel::step() { | void MenuLabel::step() { | ||||
| @@ -8,14 +8,14 @@ MenuSeparator::MenuSeparator() { | |||||
| box.size.y = BND_WIDGET_HEIGHT / 2; | box.size.y = BND_WIDGET_HEIGHT / 2; | ||||
| } | } | ||||
| void MenuSeparator::draw(NVGcontext *vg) { | |||||
| nvgBeginPath(vg); | |||||
| void MenuSeparator::draw(const DrawContext &ctx) { | |||||
| nvgBeginPath(ctx.vg); | |||||
| const float margin = 8.0; | const float margin = 8.0; | ||||
| nvgMoveTo(vg, margin, box.size.y / 2.0); | |||||
| nvgLineTo(vg, box.size.x - margin, box.size.y / 2.0); | |||||
| nvgStrokeWidth(vg, 1.0); | |||||
| nvgStrokeColor(vg, color::alpha(bndGetTheme()->menuTheme.textColor, 0.25)); | |||||
| nvgStroke(vg); | |||||
| nvgMoveTo(ctx.vg, margin, box.size.y / 2.0); | |||||
| nvgLineTo(ctx.vg, box.size.x - margin, box.size.y / 2.0); | |||||
| nvgStrokeWidth(ctx.vg, 1.0); | |||||
| nvgStrokeColor(ctx.vg, color::alpha(bndGetTheme()->menuTheme.textColor, 0.25)); | |||||
| nvgStroke(ctx.vg); | |||||
| } | } | ||||
| @@ -4,10 +4,10 @@ | |||||
| namespace rack { | namespace rack { | ||||
| void PasswordField::draw(NVGcontext *vg) { | |||||
| void PasswordField::draw(const DrawContext &ctx) { | |||||
| std::string textTmp = text; | std::string textTmp = text; | ||||
| text = std::string(textTmp.size(), '*'); | text = std::string(textTmp.size(), '*'); | ||||
| TextField::draw(vg); | |||||
| TextField::draw(ctx); | |||||
| text = textTmp; | text = textTmp; | ||||
| } | } | ||||
| @@ -13,10 +13,10 @@ ProgressBar::~ProgressBar() { | |||||
| delete quantity; | delete quantity; | ||||
| } | } | ||||
| void ProgressBar::draw(NVGcontext *vg) { | |||||
| void ProgressBar::draw(const DrawContext &ctx) { | |||||
| float progress = quantity ? quantity->getScaledValue() : 0.f; | float progress = quantity ? quantity->getScaledValue() : 0.f; | ||||
| std::string text = quantity ? quantity->getString() : ""; | std::string text = quantity ? quantity->getString() : ""; | ||||
| bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_ALL, BND_DEFAULT, progress, text.c_str(), NULL); | |||||
| bndSlider(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_ALL, BND_DEFAULT, progress, text.c_str(), NULL); | |||||
| } | } | ||||
| @@ -13,11 +13,11 @@ RadioButton::~RadioButton() { | |||||
| delete quantity; | delete quantity; | ||||
| } | } | ||||
| void RadioButton::draw(NVGcontext *vg) { | |||||
| void RadioButton::draw(const DrawContext &ctx) { | |||||
| std::string label; | std::string label; | ||||
| if (quantity) | if (quantity) | ||||
| label = quantity->getLabel(); | label = quantity->getLabel(); | ||||
| bndRadioButton(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, label.c_str()); | |||||
| bndRadioButton(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, label.c_str()); | |||||
| } | } | ||||
| void RadioButton::onEnter(const event::Enter &e) { | void RadioButton::onEnter(const event::Enter &e) { | ||||
| @@ -14,8 +14,8 @@ ScrollBar::ScrollBar() { | |||||
| box.size = math::Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT); | box.size = math::Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT); | ||||
| } | } | ||||
| void ScrollBar::draw(NVGcontext *vg) { | |||||
| bndScrollBar(vg, 0.0, 0.0, box.size.x, box.size.y, state, offset, size); | |||||
| void ScrollBar::draw(const DrawContext &ctx) { | |||||
| bndScrollBar(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, state, offset, size); | |||||
| } | } | ||||
| void ScrollBar::onDragStart(const event::DragStart &e) { | void ScrollBar::onDragStart(const event::DragStart &e) { | ||||
| @@ -26,10 +26,10 @@ void ScrollWidget::scrollTo(math::Rect r) { | |||||
| offset = offset.clampSafe(bound); | offset = offset.clampSafe(bound); | ||||
| } | } | ||||
| void ScrollWidget::draw(NVGcontext *vg) { | |||||
| nvgScissor(vg, 0, 0, box.size.x, box.size.y); | |||||
| Widget::draw(vg); | |||||
| nvgResetScissor(vg); | |||||
| void ScrollWidget::draw(const DrawContext &ctx) { | |||||
| nvgScissor(ctx.vg, 0, 0, box.size.x, box.size.y); | |||||
| Widget::draw(ctx); | |||||
| nvgResetScissor(ctx.vg); | |||||
| } | } | ||||
| void ScrollWidget::step() { | void ScrollWidget::step() { | ||||
| @@ -16,10 +16,10 @@ Slider::~Slider() { | |||||
| delete quantity; | delete quantity; | ||||
| } | } | ||||
| void Slider::draw(NVGcontext *vg) { | |||||
| void Slider::draw(const DrawContext &ctx) { | |||||
| float progress = quantity ? quantity->getScaledValue() : 0.f; | float progress = quantity ? quantity->getScaledValue() : 0.f; | ||||
| std::string text = quantity ? quantity->getString() : ""; | std::string text = quantity ? quantity->getString() : ""; | ||||
| bndSlider(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, progress, text.c_str(), NULL); | |||||
| bndSlider(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, progress, text.c_str(), NULL); | |||||
| } | } | ||||
| void Slider::onDragStart(const event::DragStart &e) { | void Slider::onDragStart(const event::DragStart &e) { | ||||
| @@ -7,8 +7,8 @@ TextField::TextField() { | |||||
| box.size.y = BND_WIDGET_HEIGHT; | box.size.y = BND_WIDGET_HEIGHT; | ||||
| } | } | ||||
| void TextField::draw(NVGcontext *vg) { | |||||
| nvgScissor(vg, 0, 0, box.size.x, box.size.y); | |||||
| void TextField::draw(const DrawContext &ctx) { | |||||
| nvgScissor(ctx.vg, 0, 0, box.size.x, box.size.y); | |||||
| BNDwidgetState state; | BNDwidgetState state; | ||||
| if (this == app()->event->selectedWidget) | if (this == app()->event->selectedWidget) | ||||
| @@ -20,13 +20,13 @@ void TextField::draw(NVGcontext *vg) { | |||||
| int begin = std::min(cursor, selection); | int begin = std::min(cursor, selection); | ||||
| int end = std::max(cursor, selection); | int end = std::max(cursor, selection); | ||||
| bndTextField(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str(), begin, end); | |||||
| bndTextField(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str(), begin, end); | |||||
| // Draw placeholder text | // Draw placeholder text | ||||
| if (text.empty() && state != BND_ACTIVE) { | if (text.empty() && state != BND_ACTIVE) { | ||||
| bndIconLabelCaret(vg, 0.0, 0.0, box.size.x, box.size.y, -1, bndGetTheme()->textFieldTheme.itemColor, 13, placeholder.c_str(), bndGetTheme()->textFieldTheme.itemColor, 0, -1); | |||||
| bndIconLabelCaret(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, -1, bndGetTheme()->textFieldTheme.itemColor, 13, placeholder.c_str(), bndGetTheme()->textFieldTheme.itemColor, 0, -1); | |||||
| } | } | ||||
| nvgResetScissor(vg); | |||||
| nvgResetScissor(ctx.vg); | |||||
| } | } | ||||
| void TextField::onButton(const event::Button &e) { | void TextField::onButton(const event::Button &e) { | ||||
| @@ -13,10 +13,10 @@ void Tooltip::step() { | |||||
| Widget::step(); | Widget::step(); | ||||
| } | } | ||||
| void Tooltip::draw(NVGcontext *vg) { | |||||
| bndTooltipBackground(vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| bndMenuLabel(vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str()); | |||||
| Widget::draw(vg); | |||||
| void Tooltip::draw(const DrawContext &ctx) { | |||||
| bndTooltipBackground(ctx.vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
| bndMenuLabel(ctx.vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str()); | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| @@ -14,17 +14,17 @@ FramebufferWidget::~FramebufferWidget() { | |||||
| nvgluDeleteFramebuffer(fb); | nvgluDeleteFramebuffer(fb); | ||||
| } | } | ||||
| void FramebufferWidget::draw(NVGcontext *vg) { | |||||
| void FramebufferWidget::draw(const DrawContext &ctx) { | |||||
| // Bypass framebuffer rendering if we're already drawing in a framebuffer | // Bypass framebuffer rendering if we're already drawing in a framebuffer | ||||
| // In other words, disallow nested framebuffers. They look bad. | // In other words, disallow nested framebuffers. They look bad. | ||||
| if (vg == app()->window->fbVg) { | |||||
| Widget::draw(vg); | |||||
| if (ctx.vg == app()->window->fbVg) { | |||||
| Widget::draw(ctx); | |||||
| return; | return; | ||||
| } | } | ||||
| // Get world transform | // Get world transform | ||||
| float xform[6]; | float xform[6]; | ||||
| nvgCurrentTransform(vg, xform); | |||||
| nvgCurrentTransform(ctx.vg, xform); | |||||
| // Skew and rotate is not supported | // Skew and rotate is not supported | ||||
| assert(math::isNear(xform[1], 0.f)); | assert(math::isNear(xform[1], 0.f)); | ||||
| assert(math::isNear(xform[2], 0.f)); | assert(math::isNear(xform[2], 0.f)); | ||||
| @@ -65,7 +65,7 @@ void FramebufferWidget::draw(NVGcontext *vg) { | |||||
| nvgluDeleteFramebuffer(fb); | nvgluDeleteFramebuffer(fb); | ||||
| // Create a framebuffer from the main nanovg context. We will draw to this in the secondary nanovg context. | // Create a framebuffer from the main nanovg context. We will draw to this in the secondary nanovg context. | ||||
| if (fbSize.isFinite() && !fbSize.isZero()) | if (fbSize.isFinite() && !fbSize.isZero()) | ||||
| fb = nvgluCreateFramebuffer(vg, fbSize.x, fbSize.y, 0); | |||||
| fb = nvgluCreateFramebuffer(ctx.vg, fbSize.x, fbSize.y, 0); | |||||
| } | } | ||||
| if (!fb) | if (!fb) | ||||
| @@ -80,28 +80,28 @@ void FramebufferWidget::draw(NVGcontext *vg) { | |||||
| return; | return; | ||||
| // Draw framebuffer image, using world coordinates | // Draw framebuffer image, using world coordinates | ||||
| nvgSave(vg); | |||||
| nvgResetTransform(vg); | |||||
| nvgSave(ctx.vg); | |||||
| nvgResetTransform(ctx.vg); | |||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, | |||||
| nvgBeginPath(ctx.vg); | |||||
| nvgRect(ctx.vg, | |||||
| offsetI.x + fbBox.pos.x, | offsetI.x + fbBox.pos.x, | ||||
| offsetI.y + fbBox.pos.y, | offsetI.y + fbBox.pos.y, | ||||
| fbBox.size.x, fbBox.size.y); | fbBox.size.x, fbBox.size.y); | ||||
| NVGpaint paint = nvgImagePattern(vg, | |||||
| NVGpaint paint = nvgImagePattern(ctx.vg, | |||||
| offsetI.x + fbBox.pos.x, | offsetI.x + fbBox.pos.x, | ||||
| offsetI.y + fbBox.pos.y, | offsetI.y + fbBox.pos.y, | ||||
| fbBox.size.x, fbBox.size.y, | fbBox.size.x, fbBox.size.y, | ||||
| 0.0, fb->image, 1.0); | 0.0, fb->image, 1.0); | ||||
| nvgFillPaint(vg, paint); | |||||
| nvgFill(vg); | |||||
| nvgFillPaint(ctx.vg, paint); | |||||
| nvgFill(ctx.vg); | |||||
| // For debugging the bounding box of the framebuffer | // For debugging the bounding box of the framebuffer | ||||
| // nvgStrokeWidth(vg, 2.0); | |||||
| // nvgStrokeColor(vg, nvgRGBAf(1, 1, 0, 0.5)); | |||||
| // nvgStroke(vg); | |||||
| // nvgStrokeWidth(ctx.vg, 2.0); | |||||
| // nvgStrokeColor(ctx.vg, nvgRGBAf(1, 1, 0, 0.5)); | |||||
| // nvgStroke(ctx.vg); | |||||
| nvgRestore(vg); | |||||
| nvgRestore(ctx.vg); | |||||
| } | } | ||||
| void FramebufferWidget::drawFramebuffer() { | void FramebufferWidget::drawFramebuffer() { | ||||
| @@ -115,7 +115,9 @@ void FramebufferWidget::drawFramebuffer() { | |||||
| nvgTranslate(vg, fbOffset.x, fbOffset.y); | nvgTranslate(vg, fbOffset.x, fbOffset.y); | ||||
| nvgScale(vg, fbScale.x, fbScale.y); | nvgScale(vg, fbScale.x, fbScale.y); | ||||
| Widget::draw(vg); | |||||
| DrawContext ctx; | |||||
| ctx.vg = vg; | |||||
| Widget::draw(ctx); | |||||
| glViewport(0.0, 0.0, fbSize.x, fbSize.y); | glViewport(0.0, 0.0, fbSize.x, fbSize.y); | ||||
| glClearColor(0.0, 0.0, 0.0, 0.0); | glClearColor(0.0, 0.0, 0.0, 0.0); | ||||
| @@ -93,7 +93,7 @@ void Widget::step() { | |||||
| } | } | ||||
| } | } | ||||
| void Widget::draw(NVGcontext *vg) { | |||||
| void Widget::draw(const DrawContext &ctx) { | |||||
| for (Widget *child : children) { | for (Widget *child : children) { | ||||
| // Don't draw if invisible | // Don't draw if invisible | ||||
| if (!child->visible) | if (!child->visible) | ||||
| @@ -102,19 +102,26 @@ void Widget::draw(NVGcontext *vg) { | |||||
| if (!box.zeroPos().intersects(child->box)) | if (!box.zeroPos().intersects(child->box)) | ||||
| continue; | continue; | ||||
| nvgSave(vg); | |||||
| nvgTranslate(vg, child->box.pos.x, child->box.pos.y); | |||||
| child->draw(vg); | |||||
| nvgSave(ctx.vg); | |||||
| nvgTranslate(ctx.vg, child->box.pos.x, child->box.pos.y); | |||||
| DrawContext childCtx = ctx; | |||||
| child->draw(childCtx); | |||||
| #pragma GCC diagnostic push | |||||
| #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |||||
| child->draw(ctx.vg); | |||||
| #pragma GCC diagnostic pop | |||||
| // Draw red hitboxes | // Draw red hitboxes | ||||
| // if (app()->event->hoveredWidget == child) { | // if (app()->event->hoveredWidget == child) { | ||||
| // nvgBeginPath(vg); | |||||
| // nvgRect(vg, 0, 0, child->box.size.x, child->box.size.y); | |||||
| // nvgFillColor(vg, nvgRGBAf(1, 0, 0, 0.5)); | |||||
| // nvgFill(vg); | |||||
| // nvgBeginPath(ctx.vg); | |||||
| // nvgRect(ctx.vg, 0, 0, child->box.size.x, child->box.size.y); | |||||
| // nvgFillColor(ctx.vg, nvgRGBAf(1, 0, 0, 0.5)); | |||||
| // nvgFill(ctx.vg); | |||||
| // } | // } | ||||
| nvgRestore(vg); | |||||
| nvgRestore(ctx.vg); | |||||
| } | } | ||||
| } | } | ||||
| @@ -28,10 +28,10 @@ void ZoomWidget::setZoom(float zoom) { | |||||
| Widget::onZoom(eZoom); | Widget::onZoom(eZoom); | ||||
| } | } | ||||
| void ZoomWidget::draw(NVGcontext *vg) { | |||||
| void ZoomWidget::draw(const DrawContext &ctx) { | |||||
| // No need to save the state because that is done in the parent | // No need to save the state because that is done in the parent | ||||
| nvgScale(vg, zoom, zoom); | |||||
| Widget::draw(vg); | |||||
| nvgScale(ctx.vg, zoom, zoom); | |||||
| Widget::draw(ctx); | |||||
| } | } | ||||
| @@ -359,7 +359,9 @@ void Window::run() { | |||||
| // nvgReset(vg); | // nvgReset(vg); | ||||
| // nvgScale(vg, pixelRatio, pixelRatio); | // nvgScale(vg, pixelRatio, pixelRatio); | ||||
| app()->event->rootWidget->draw(vg); | |||||
| DrawContext ctx; | |||||
| ctx.vg = vg; | |||||
| app()->event->rootWidget->draw(ctx); | |||||
| glViewport(0, 0, fbWidth, fbHeight); | glViewport(0, 0, fbWidth, fbHeight); | ||||
| glClearColor(0.0, 0.0, 0.0, 1.0); | glClearColor(0.0, 0.0, 0.0, 1.0); | ||||