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 // params
//////////////////// ////////////////////


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

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


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


struct Switch : ParamWidget, SpriteWidget { struct Switch : ParamWidget, SpriteWidget {
}; };


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

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


+ 15
- 1
include/components.hpp View File

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


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


struct ValueLight : Light { 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 // 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 /** 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. Events are not passed to the underlying scene.
*/ */
struct FramebufferWidget : virtual Widget { 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; 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. This prevents cutting the rendered SVG off on the box edges.
*/ */
int margin = 0; int margin = 0;
/** The root object in the framebuffer scene /** The root object in the framebuffer scene
The FramebufferWidget owns the pointer The FramebufferWidget owns the pointer
*/ */
Widget *scene = NULL;
struct Internal; struct Internal;
Internal *internal; Internal *internal;


FramebufferWidget(); FramebufferWidget();
~FramebufferWidget(); ~FramebufferWidget();
void setScene(Widget *w) {
scene = w;
}
void step(); void step();
void draw(NVGcontext *vg); 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() { SVGKnob::SVGKnob() {
margin = 1;
margin = 4;

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


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


sw = new SVGWidget(); sw = new SVGWidget();
tw->addChild(sw); tw->addChild(sw);
@@ -33,30 +38,12 @@ void SVGKnob::step() {
tw->translate(center); tw->translate(center);
tw->rotate(angle); tw->rotate(angle);
tw->translate(center.neg()); tw->translate(center.neg());
// Resize shadow
shadow->box.size = box.size;
} }
FramebufferWidget::step(); 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() { void SVGKnob::onChange() {
dirty = true; dirty = true;
ParamWidget::onChange(); ParamWidget::onChange();


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

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


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


void SVGPort::setSVG(std::shared_ptr<SVG> svg) { 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_CONTEXT_VERSION_MINOR, 2);
// glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
std::string title = gApplicationName + " " + gApplicationVersion; std::string title = gApplicationName + " " + gApplicationVersion;
window = glfwCreateWindow(1000, 750, title.c_str(), NULL, NULL); window = glfwCreateWindow(1000, 750, title.c_str(), NULL, NULL);
assert(window); assert(window);


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

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


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


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


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


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


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


// Render the scene to the framebuffer if dirty // Render the scene to the framebuffer if dirty
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); internal->setFramebuffer(NULL);
NVGLUframebuffer *fb = nvgluCreateFramebuffer(gVg, width, height, NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY); 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); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(gVg, width, height, pixelRatio); 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); nvgEndFrame(gVg);
nvgluBindFramebuffer(NULL); nvgluBindFramebuffer(NULL);
@@ -72,17 +72,18 @@ void FramebufferWidget::step() {
void FramebufferWidget::draw(NVGcontext *vg) { void FramebufferWidget::draw(NVGcontext *vg) {
if (!internal->fb) if (!internal->fb)
return; return;
if (!scene)
return;


// Draw framebuffer image // Draw framebuffer image
int width, height; int width, height;
nvgImageSize(vg, internal->fb->image, &width, &height); nvgImageSize(vg, internal->fb->image, &width, &height);
nvgBeginPath(vg); 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); nvgFillPaint(vg, paint);
nvgFill(vg); nvgFill(vg);

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






Loading…
Cancel
Save