Browse Source

Add CircularShadow and add it to the SVGKnob framebuffer

tags/v0.3.0
Andrew Belt 7 years ago
parent
commit
59b39bf876
9 changed files with 111 additions and 47 deletions
  1. +32
    -0
      Makefile-plugin.inc
  2. +13
    -1
      include/app.hpp
  3. +15
    -1
      include/components.hpp
  4. +3
    -7
      include/widgets.hpp
  5. +21
    -0
      src/app/CircularShadow.cpp
  6. +9
    -22
      src/app/SVGKnob.cpp
  7. +1
    -1
      src/app/SVGPort.cpp
  8. +1
    -0
      src/gui.cpp
  9. +16
    -15
      src/widgets/FramebufferWidget.cpp

+ 32
- 0
Makefile-plugin.inc View File

@@ -0,0 +1,32 @@
ARCH ?= lin


FLAGS += -fPIC -g -Wall -O3 -msse -mfpmath=sse -ffast-math \
-I../../include
LDFLAGS +=


ifeq ($(ARCH), lin)
LDFLAGS += -shared
TARGET = plugin.so
endif

ifeq ($(ARCH), mac)
LDFLAGS += -shared -undefined dynamic_lookup
TARGET = plugin.dylib
endif

ifeq ($(ARCH), win)
LDFLAGS += -shared -L../../ -lRack
TARGET = plugin.dll
endif



all: $(TARGET)

clean:
rm -rfv build $(TARGET)


include ../../Makefile.inc

+ 13
- 1
include/app.hpp View File

@@ -104,6 +104,11 @@ struct Panel : TransparentWidget {
// params
////////////////////

struct CircularShadow : TransparentWidget {
float blur = 0.0;
void draw(NVGcontext *vg);
};

struct Light : TransparentWidget {
NVGcolor color;
void draw(NVGcontext *vg);
@@ -137,17 +142,24 @@ struct SVGKnob : Knob, FramebufferWidget {
/** Not owned */
TransformWidget *tw;
SVGWidget *sw;
CircularShadow *shadow;

SVGKnob();
void setSVG(std::shared_ptr<SVG> svg);
void step();
void draw(NVGcontext *vg);
void onChange();
};

struct Switch : ParamWidget, SpriteWidget {
};

struct SVGSwitch : ParamWidget, FramebufferWidget {
/** Not owned */
TransformWidget *tw;
SVGWidget *swPressed;
SVGWidget *swReleased;
};

struct ToggleSwitch : virtual Switch {
void onDragStart() {
index = 1;


+ 15
- 1
include/components.hpp View File

@@ -360,7 +360,7 @@ struct CL1362Port : SpritePort {
};

////////////////////
// Lights
// LEDs
////////////////////

struct ValueLight : Light {
@@ -413,6 +413,20 @@ struct SmallLight : BASE {
}
};

////////////////////
// Switches
////////////////////

// struct BefacoBigKnob : {
// BefacoBigKnob() {
// box.size = Vec(75, 75);
// minAngle = -0.75*M_PI;
// maxAngle = 0.75*M_PI;
// setSVG(SVG::load("res/ComponentLibrary/BefacoBigKnob.svg"));
// }
// };


////////////////////
// Misc
////////////////////


+ 3
- 7
include/widgets.hpp View File

@@ -186,28 +186,24 @@ struct SVGWidget : virtual Widget {
};

/** Caches a widget's draw() result to a framebuffer so it is called less frequently
When `dirty` is true, `scene` will be re-rendered on the next call to step().
When `dirty` is true, its children will be re-rendered on the next call to step().
Events are not passed to the underlying scene.
*/
struct FramebufferWidget : virtual Widget {
/** Set this to true to re-render the scene to the framebuffer in the next step() */
/** Set this to true to re-render the children to the framebuffer in the next step() */
bool dirty = true;
/** A margin in pixels around the scene in the framebuffer
/** A margin in pixels around the children in the framebuffer
This prevents cutting the rendered SVG off on the box edges.
*/
int margin = 0;
/** The root object in the framebuffer scene
The FramebufferWidget owns the pointer
*/
Widget *scene = NULL;
struct Internal;
Internal *internal;

FramebufferWidget();
~FramebufferWidget();
void setScene(Widget *w) {
scene = w;
}
void step();
void draw(NVGcontext *vg);
};


+ 21
- 0
src/app/CircularShadow.cpp View File

@@ -0,0 +1,21 @@
#include "app.hpp"


namespace rack {


void CircularShadow::draw(NVGcontext *vg) {
nvgBeginPath(vg);
nvgRect(vg, -blur, -blur, box.size.x + 2*blur, box.size.y + 2*blur);
nvgFillColor(vg, nvgRGBAf(0.0, 0.0, 0.0, 0.25));
Vec c = box.size.div(2.0);
float radius = c.x;
NVGcolor icol = nvgRGBAf(0.0, 0.0, 0.0, 0.25);
NVGcolor ocol = nvgRGBAf(0.0, 0.0, 0.0, 0.0);
NVGpaint paint = nvgRadialGradient(vg, c.x, c.y, radius - blur/2, radius + blur/2, icol, ocol);
nvgFillPaint(vg, paint);
nvgFill(vg);
}


} // namespace rack

+ 9
- 22
src/app/SVGKnob.cpp View File

@@ -5,10 +5,15 @@ namespace rack {


SVGKnob::SVGKnob() {
margin = 1;
margin = 4;

shadow = new CircularShadow();
shadow->blur = 5.0;
shadow->box.pos = Vec(0, 1);
addChild(shadow);

tw = new TransformWidget();
setScene(tw);
addChild(tw);

sw = new SVGWidget();
tw->addChild(sw);
@@ -33,30 +38,12 @@ void SVGKnob::step() {
tw->translate(center);
tw->rotate(angle);
tw->translate(center.neg());
// Resize shadow
shadow->box.size = box.size;
}
FramebufferWidget::step();
}

void SVGKnob::draw(NVGcontext *vg) {
// Draw circular shadow below knob
// TODO This is a hack. Make a CircularShadow its own class
{
nvgBeginPath(vg);
float margin = 5.0;
nvgRect(vg, -margin, -margin, box.size.x + 2*margin, box.size.y + 2*margin);
nvgFillColor(vg, nvgRGBAf(0.0, 0.0, 0.0, 0.25));
Vec c = box.size.div(2.0);
float radius = c.x;
NVGcolor icol = nvgRGBAf(0.0, 0.0, 0.0, 0.25);
NVGcolor ocol = nvgRGBAf(0.0, 0.0, 0.0, 0.0);
NVGpaint paint = nvgRadialGradient(vg, c.x, c.y + 1, radius, radius + 3, icol, ocol);
nvgFillPaint(vg, paint);
nvgFill(vg);
}

FramebufferWidget::draw(vg);
}

void SVGKnob::onChange() {
dirty = true;
ParamWidget::onChange();


+ 1
- 1
src/app/SVGPort.cpp View File

@@ -6,7 +6,7 @@ namespace rack {

SVGPort::SVGPort() {
sw = new SVGWidget();
setScene(sw);
addChild(sw);
}

void SVGPort::setSVG(std::shared_ptr<SVG> svg) {


+ 1
- 0
src/gui.cpp View File

@@ -197,6 +197,7 @@ void guiInit() {
// glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
// glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
std::string title = gApplicationName + " " + gApplicationVersion;
window = glfwCreateWindow(1000, 750, title.c_str(), NULL, NULL);
assert(window);


+ 16
- 15
src/widgets/FramebufferWidget.cpp View File

@@ -10,6 +10,7 @@ namespace rack {

struct FramebufferWidget::Internal {
NVGLUframebuffer *fb = NULL;
Vec offset;

~Internal() {
setFramebuffer(NULL);
@@ -26,24 +27,23 @@ FramebufferWidget::FramebufferWidget() {
}

FramebufferWidget::~FramebufferWidget() {
if (scene) {
delete scene;
}
delete internal;
}

void FramebufferWidget::step() {
if (!scene)
if (children.empty())
return;

// Step scene before rendering
scene->step();
// Step children before rendering
Widget::step();

// Render the scene to the framebuffer if dirty
if (dirty) {
assert(scene->box.size.isFinite());
int width = ceilf(scene->box.size.x) + 2*margin;
int height = ceilf(scene->box.size.y) + 2*margin;
Rect childrenBox = getChildrenBoundingBox();
assert(childrenBox.size.isFinite());
int width = ceilf(childrenBox.size.x) + 2*margin;
int height = ceilf(childrenBox.size.y) + 2*margin;
internal->offset = childrenBox.pos.minus(Vec(margin, margin));

internal->setFramebuffer(NULL);
NVGLUframebuffer *fb = nvgluCreateFramebuffer(gVg, width, height, NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
@@ -59,8 +59,8 @@ void FramebufferWidget::step() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(gVg, width, height, pixelRatio);

nvgTranslate(gVg, margin, margin);
scene->draw(gVg);
nvgTranslate(gVg, -internal->offset.x, -internal->offset.y);
Widget::draw(gVg);

nvgEndFrame(gVg);
nvgluBindFramebuffer(NULL);
@@ -72,17 +72,18 @@ void FramebufferWidget::step() {
void FramebufferWidget::draw(NVGcontext *vg) {
if (!internal->fb)
return;
if (!scene)
return;

// Draw framebuffer image
int width, height;
nvgImageSize(vg, internal->fb->image, &width, &height);
nvgBeginPath(vg);
nvgRect(vg, -margin, -margin, width, height);
NVGpaint paint = nvgImagePattern(vg, -margin + scene->box.pos.x, -margin + scene->box.pos.y, width, height, 0.0, internal->fb->image, 1.0);
nvgRect(vg, internal->offset.x, internal->offset.y, width, height);
NVGpaint paint = nvgImagePattern(vg, internal->offset.x, internal->offset.y, width, height, 0.0, internal->fb->image, 1.0);
nvgFillPaint(vg, paint);
nvgFill(vg);

// nvgFillColor(vg, nvgRGBA(255, 0, 0, 64));
// nvgFill(vg);
}




Loading…
Cancel
Save