From 1af22f1a126ba87411e5aae0802f122d460c8af0 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Sat, 2 Sep 2017 03:22:18 -0400 Subject: [PATCH] Render rails in a framebuffer --- include/app.hpp | 8 +++++ include/widgets.hpp | 1 + src/app/RackRail.cpp | 52 +++++++++++++++++++++++++++ src/app/RackWidget.cpp | 60 ++++++++----------------------- src/widgets/FramebufferWidget.cpp | 6 ++++ 5 files changed, 82 insertions(+), 45 deletions(-) create mode 100644 src/app/RackRail.cpp diff --git a/include/app.hpp b/include/app.hpp index 4b72a8d7..a13e453f 100644 --- a/include/app.hpp +++ b/include/app.hpp @@ -20,6 +20,9 @@ struct Scene; //////////////////// // A 1U module should be 15x380. Thus the width of a module should be a factor of 15. +#define RACK_GRID_WIDTH 15 +#define RACK_GRID_HEIGHT 380 + struct Model; struct ModuleWidget : OpaqueWidget { Model *model = NULL; @@ -79,6 +82,7 @@ struct WireWidget : OpaqueWidget { }; struct RackWidget : OpaqueWidget { + FramebufferWidget *rails; // Only put ModuleWidgets in here Widget *moduleContainer; // Only put WireWidgets in here @@ -100,6 +104,10 @@ struct RackWidget : OpaqueWidget { void onMouseDown(int button); }; +struct RackRail : TransparentWidget { + void draw(NVGcontext *vg); +}; + struct Panel : TransparentWidget { NVGcolor backgroundColor; NVGcolor borderColor; diff --git a/include/widgets.hpp b/include/widgets.hpp index c4f9cadf..b33ca048 100644 --- a/include/widgets.hpp +++ b/include/widgets.hpp @@ -206,6 +206,7 @@ struct FramebufferWidget : virtual Widget { ~FramebufferWidget(); void step(); void draw(NVGcontext *vg); + int getImageHandle(); }; struct QuantityWidget : virtual Widget { diff --git a/src/app/RackRail.cpp b/src/app/RackRail.cpp new file mode 100644 index 00000000..e126f38a --- /dev/null +++ b/src/app/RackRail.cpp @@ -0,0 +1,52 @@ +#include "app.hpp" + + +namespace rack { + +void RackRail::draw(NVGcontext *vg) { + const float railHeight = RACK_GRID_WIDTH; + + // 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); + + // Rails + nvgFillColor(vg, nvgRGBf(0.85, 0.85, 0.85)); + nvgStrokeWidth(vg, 1.0); + nvgStrokeColor(vg, nvgRGBf(0.7, 0.7, 0.7)); + float holeRadius = 3.5; + for (float railY = 0; railY < box.size.y; railY += RACK_GRID_HEIGHT) { + // Top rail + nvgBeginPath(vg); + nvgRect(vg, 0, railY, box.size.x, railHeight); + 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); + } + nvgFill(vg); + + nvgBeginPath(vg); + nvgMoveTo(vg, 0, railY + railHeight - 0.5); + nvgLineTo(vg, box.size.x, railY + railHeight - 0.5); + nvgStroke(vg); + + // Bottom rail + nvgBeginPath(vg); + nvgRect(vg, 0, railY + RACK_GRID_HEIGHT - railHeight, box.size.x, railHeight); + 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); + } + nvgFill(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); + } +} + + +} // namespace rack diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index 63edbe8c..174b10d9 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -8,8 +8,6 @@ namespace rack { -static Vec rackGridSize = Vec(15, 380); - struct WireContainer : TransparentWidget { void draw(NVGcontext *vg) { @@ -25,6 +23,12 @@ struct WireContainer : TransparentWidget { }; RackWidget::RackWidget() { + rails = new FramebufferWidget(); + RackRail *rail = new RackRail(); + rail->box.size = Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT); + rails->addChild(rail); + rails->box.size = rail->box.size; + moduleContainer = new Widget(); addChild(moduleContainer); @@ -33,6 +37,7 @@ RackWidget::RackWidget() { } RackWidget::~RackWidget() { + delete rails; } void RackWidget::clear() { @@ -241,12 +246,12 @@ void RackWidget::fromJson(json_t *rootJ) { void RackWidget::repositionModule(ModuleWidget *module) { // Create possible positions - int x0 = roundf(module->requestedPos.x / rackGridSize.x); - int y0 = roundf(module->requestedPos.y / rackGridSize.y); + int x0 = roundf(module->requestedPos.x / RACK_GRID_WIDTH); + int y0 = roundf(module->requestedPos.y / RACK_GRID_HEIGHT); std::vector positions; for (int y = maxi(0, y0 - 2); y < y0 + 2; y++) { for (int x = maxi(0, x0 - 40); x < x0 + 40; x++) { - positions.push_back(Vec(x * rackGridSize.x, y * rackGridSize.y)); + positions.push_back(Vec(x * RACK_GRID_WIDTH, y * RACK_GRID_HEIGHT)); } } @@ -275,6 +280,8 @@ void RackWidget::repositionModule(ModuleWidget *module) { } void RackWidget::step() { + rails->step(); + // Resize to be a bit larger than the ScrollWidget viewport assert(parent); assert(parent->parent); @@ -301,50 +308,13 @@ void RackWidget::step() { } void RackWidget::draw(NVGcontext *vg) { + // Draw rails nvgBeginPath(vg); nvgRect(vg, 0.0, 0.0, box.size.x, box.size.y); - - // Background color - nvgFillColor(vg, nvgRGBf(0.2, 0.2, 0.2)); + NVGpaint paint = nvgImagePattern(vg, rails->box.pos.x, rails->box.pos.y, rails->box.size.x, rails->box.size.y, 0.0, rails->getImageHandle(), 1.0); + nvgFillPaint(vg, paint); nvgFill(vg); - // Rails - // TODO Put this in a framebuffer cache and tile - const float railHeight = 15; - nvgFillColor(vg, nvgRGBf(0.85, 0.85, 0.85)); - nvgStrokeWidth(vg, 1.0); - nvgStrokeColor(vg, nvgRGBf(0.7, 0.7, 0.7)); - float holeRadius = 3.5; - for (float railY = 0; railY < box.size.y; railY += rackGridSize.y) { - // Top rail - nvgBeginPath(vg); - nvgRect(vg, 0, railY, box.size.x, railHeight); - for (float railX = 0; railX < box.size.x; railX += rackGridSize.x) { - nvgCircle(vg, railX + rackGridSize.x / 2, railY + railHeight / 2, holeRadius); - nvgPathWinding(vg, NVG_HOLE); - } - nvgFill(vg); - - nvgBeginPath(vg); - nvgMoveTo(vg, 0, railY + railHeight - 0.5); - nvgLineTo(vg, box.size.x, railY + railHeight - 0.5); - nvgStroke(vg); - - // Bottom rail - nvgBeginPath(vg); - nvgRect(vg, 0, railY + rackGridSize.y - railHeight, box.size.x, railHeight); - for (float railX = 0; railX < box.size.x; railX += rackGridSize.x) { - nvgCircle(vg, railX + rackGridSize.x / 2, railY + rackGridSize.y - railHeight + railHeight / 2, holeRadius); - nvgPathWinding(vg, NVG_HOLE); - } - nvgFill(vg); - - nvgBeginPath(vg); - nvgMoveTo(vg, 0, railY + rackGridSize.y - 0.5); - nvgLineTo(vg, box.size.x, railY + rackGridSize.y - 0.5); - nvgStroke(vg); - } - Widget::draw(vg); } diff --git a/src/widgets/FramebufferWidget.cpp b/src/widgets/FramebufferWidget.cpp index 07a7350c..4171ca0d 100644 --- a/src/widgets/FramebufferWidget.cpp +++ b/src/widgets/FramebufferWidget.cpp @@ -81,5 +81,11 @@ void FramebufferWidget::draw(NVGcontext *vg) { // nvgFill(vg); } +int FramebufferWidget::getImageHandle() { + if (!internal->fb) + return -1; + return internal->fb->image; +} + } // namespace rack