From 0e7e3625657e8e8fd875429ebc5892a0e5b384fd Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Mon, 30 Oct 2017 18:45:50 -0400 Subject: [PATCH 1/4] Change internals of SVGWidget subclasses --- include/app.hpp | 4 + include/components.hpp | 25 +-- res/ComponentLibrary/PB61303.svg | 263 +++++++++++++++++++++++++++++ res/ComponentLibrary/PB61303_0.svg | 234 ------------------------- res/ComponentLibrary/PB61303_1.svg | 234 ------------------------- src/app/ModuleWidget.cpp | 9 + src/app/SVGPanel.cpp | 9 +- src/app/SVGSwitch.cpp | 15 +- src/engine.cpp | 3 +- 9 files changed, 293 insertions(+), 503 deletions(-) create mode 100644 res/ComponentLibrary/PB61303.svg delete mode 100644 res/ComponentLibrary/PB61303_0.svg delete mode 100644 res/ComponentLibrary/PB61303_1.svg diff --git a/include/app.hpp b/include/app.hpp index 9cb56c09..a252ab14 100644 --- a/include/app.hpp +++ b/include/app.hpp @@ -23,6 +23,9 @@ struct Port; #define RACK_GRID_WIDTH 15 #define RACK_GRID_HEIGHT 380 +static const Vec RACK_GRID_SIZE = Vec(15, 380); + + struct ModuleWidget : OpaqueWidget { Model *model = NULL; /** Owns the module pointer */ @@ -38,6 +41,7 @@ struct ModuleWidget : OpaqueWidget { void addInput(Port *input); void addOutput(Port *output); void addParam(ParamWidget *param); + void setPanel(std::shared_ptr svg); virtual json_t *toJson(); virtual void fromJson(json_t *rootJ); diff --git a/include/components.hpp b/include/components.hpp index 32adf720..640618f9 100644 --- a/include/components.hpp +++ b/include/components.hpp @@ -446,8 +446,6 @@ struct NKK : SVGSwitch, ToggleSwitch { addFrame(SVG::load(assetGlobal("res/ComponentLibrary/NKK_0.svg"))); addFrame(SVG::load(assetGlobal("res/ComponentLibrary/NKK_1.svg"))); addFrame(SVG::load(assetGlobal("res/ComponentLibrary/NKK_2.svg"))); - sw->wrap(); - box.size = sw->box.size; } }; @@ -455,8 +453,6 @@ struct CKSS : SVGSwitch, ToggleSwitch { CKSS() { addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKSS_0.svg"))); addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKSS_1.svg"))); - sw->wrap(); - box.size = sw->box.size; } }; @@ -464,8 +460,6 @@ struct CKD6 : SVGSwitch, MomentarySwitch { CKD6() { addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKD6_0.svg"))); addFrame(SVG::load(assetGlobal("res/ComponentLibrary/CKD6_1.svg"))); - sw->wrap(); - box.size = sw->box.size; } }; @@ -473,16 +467,12 @@ struct TL1105 : SVGSwitch, MomentarySwitch { TL1105() { addFrame(SVG::load(assetGlobal("res/ComponentLibrary/TL1105_0.svg"))); addFrame(SVG::load(assetGlobal("res/ComponentLibrary/TL1105_1.svg"))); - sw->wrap(); - box.size = sw->box.size; } }; struct LEDButton : SVGSwitch, MomentarySwitch { LEDButton() { addFrame(SVG::load(assetGlobal("res/ComponentLibrary/LEDButton.svg"))); - sw->wrap(); - box.size = sw->box.size; } }; @@ -491,8 +481,6 @@ struct BefacoSwitch : SVGSwitch, ToggleSwitch { addFrame(SVG::load(assetGlobal("res/ComponentLibrary/BefacoSwitch_0.svg"))); addFrame(SVG::load(assetGlobal("res/ComponentLibrary/BefacoSwitch_1.svg"))); addFrame(SVG::load(assetGlobal("res/ComponentLibrary/BefacoSwitch_2.svg"))); - sw->wrap(); - box.size = sw->box.size; } }; @@ -500,17 +488,12 @@ struct BefacoPush : SVGSwitch, MomentarySwitch { BefacoPush() { addFrame(SVG::load(assetGlobal("res/ComponentLibrary/BefacoPush_0.svg"))); addFrame(SVG::load(assetGlobal("res/ComponentLibrary/BefacoPush_1.svg"))); - sw->wrap(); - box.size = sw->box.size; } }; struct PB61303 : SVGSwitch, MomentarySwitch { PB61303() { - addFrame(SVG::load(assetGlobal("res/ComponentLibrary/PB61303_0.svg"))); - addFrame(SVG::load(assetGlobal("res/ComponentLibrary/PB61303_1.svg"))); - sw->wrap(); - box.size = sw->box.size; + addFrame(SVG::load(assetGlobal("res/ComponentLibrary/PB61303.svg"))); } }; @@ -521,16 +504,14 @@ struct PB61303 : SVGSwitch, MomentarySwitch { struct ScrewSilver : SVGScrew { ScrewSilver() { - sw->svg = SVG::load(assetGlobal("res/ComponentLibrary/ScrewSilver.svg")); - sw->wrap(); + sw->setSVG(SVG::load(assetGlobal("res/ComponentLibrary/ScrewSilver.svg"))); box.size = sw->box.size; } }; struct ScrewBlack : SVGScrew { ScrewBlack() { - sw->svg = SVG::load(assetGlobal("res/ComponentLibrary/ScrewBlack.svg")); - sw->wrap(); + sw->setSVG(SVG::load(assetGlobal("res/ComponentLibrary/ScrewBlack.svg"))); box.size = sw->box.size; } }; diff --git a/res/ComponentLibrary/PB61303.svg b/res/ComponentLibrary/PB61303.svg new file mode 100644 index 00000000..42ac4a99 --- /dev/null +++ b/res/ComponentLibrary/PB61303.svg @@ -0,0 +1,263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/res/ComponentLibrary/PB61303_0.svg b/res/ComponentLibrary/PB61303_0.svg deleted file mode 100644 index 80f0a6f3..00000000 --- a/res/ComponentLibrary/PB61303_0.svg +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/res/ComponentLibrary/PB61303_1.svg b/res/ComponentLibrary/PB61303_1.svg deleted file mode 100644 index d9c90ce8..00000000 --- a/res/ComponentLibrary/PB61303_1.svg +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 77f79b46..07eed233 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -42,6 +42,15 @@ void ModuleWidget::addParam(ParamWidget *param) { addChild(param); } +void ModuleWidget::setPanel(std::shared_ptr svg) { + SVGPanel *panel = new SVGPanel(); + panel->setBackground(svg); + addChild(panel); + + box.size = panel->box.size; +} + + json_t *ModuleWidget::toJson() { json_t *rootJ = json_object(); diff --git a/src/app/SVGPanel.cpp b/src/app/SVGPanel.cpp index 178d7d65..26a3b86b 100644 --- a/src/app/SVGPanel.cpp +++ b/src/app/SVGPanel.cpp @@ -19,19 +19,20 @@ struct PanelBorder : TransparentWidget { void SVGPanel::step() { if (nearf(gPixelRatio, 1.0)) { + // Small details draw poorly at low DPI, so oversample when drawing to the framebuffer oversample = 2.0; } FramebufferWidget::step(); } void SVGPanel::setBackground(std::shared_ptr svg) { - clearChildren(); - SVGWidget *sw = new SVGWidget(); - sw->wrap(); - sw->svg = svg; + sw->setSVG(svg); addChild(sw); + // Set size + box.size = sw->box.size.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE); + PanelBorder *pb = new PanelBorder(); pb->box.size = box.size; addChild(pb); diff --git a/src/app/SVGSwitch.cpp b/src/app/SVGSwitch.cpp index 1507a43e..3b48819d 100644 --- a/src/app/SVGSwitch.cpp +++ b/src/app/SVGSwitch.cpp @@ -11,10 +11,11 @@ SVGSwitch::SVGSwitch() { void SVGSwitch::addFrame(std::shared_ptr svg) { frames.push_back(svg); - // Automatically set the frame as this SVG file. - // This allows us to wrap() the widget after calling - if (!sw->svg) - sw->svg = svg; + // If this is our first frame, automatically set SVG and size + if (!sw->svg) { + sw->setSVG(svg); + box.size = sw->box.size; + } } void SVGSwitch::step() { @@ -22,9 +23,9 @@ void SVGSwitch::step() { } void SVGSwitch::onChange() { - int index = roundf(rescalef(value, minValue, maxValue, 0, frames.size() - 1)); - if (0 <= index && index < (int)frames.size()) - sw->svg = frames[index]; + assert(frames.size() > 0); + int index = clampi((int) roundf(value), 0, frames.size() - 1); + sw->setSVG(frames[index]); dirty = true; Switch::onChange(); } diff --git a/src/engine.cpp b/src/engine.cpp index d587e575..17e12785 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -35,8 +35,7 @@ static float smoothValue; float Light::getBrightness() { - // Scale by sqrt(2) since the RMS of a rectified sine is 1 / sqrt(2) - return sqrtf(fmaxf(0.0, value) * 2.0); + return sqrtf(fmaxf(0.0, value)); } void Light::setBrightnessSmooth(float brightness) { From 03ce2d6e2b157ee8e93cad71516103fcf1a33e85 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Tue, 31 Oct 2017 04:13:03 -0400 Subject: [PATCH 2/4] Fix framebuffer 1 pixel offset bug when position world coordinate is negative --- src/widgets/FramebufferWidget.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/widgets/FramebufferWidget.cpp b/src/widgets/FramebufferWidget.cpp index d3e85016..9d4a633d 100644 --- a/src/widgets/FramebufferWidget.cpp +++ b/src/widgets/FramebufferWidget.cpp @@ -46,6 +46,8 @@ void FramebufferWidget::draw(NVGcontext *vg) { assert(fabsf(xform[2]) < 1e-6); Vec s = Vec(xform[0], xform[3]); Vec b = Vec(xform[4], xform[5]); + Vec bi = b.floor(); + Vec bf = b.minus(bi); // Render to framebuffer if (dirty) { @@ -78,8 +80,7 @@ void FramebufferWidget::draw(NVGcontext *vg) { nvgScale(gFramebufferVg, gPixelRatio * oversample, gPixelRatio * oversample); // Use local scaling - Vec bFrac = Vec(fmodf(b.x, 1.0), fmodf(b.y, 1.0)); - nvgTranslate(gFramebufferVg, bFrac.x, bFrac.y); + nvgTranslate(gFramebufferVg, bf.x, bf.y); nvgScale(gFramebufferVg, s.x, s.y); Widget::draw(gFramebufferVg); @@ -92,10 +93,9 @@ void FramebufferWidget::draw(NVGcontext *vg) { } // Draw framebuffer image, using world coordinates - b = b.floor(); nvgSave(vg); nvgResetTransform(vg); - nvgTranslate(vg, b.x, b.y); + nvgTranslate(vg, bi.x, bi.y); nvgBeginPath(vg); nvgRect(vg, internal->box.pos.x, internal->box.pos.y, internal->box.size.x, internal->box.size.y); From 661e93bb2494cdb456ae9290f10ba79f5beadff2 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Tue, 31 Oct 2017 08:03:56 -0400 Subject: [PATCH 3/4] Remove old panel if ModuleWidget::setPanel is called multiple times, move in2px and mm2px to widgets.hpp --- include/app.hpp | 2 ++ include/rack.hpp | 9 --------- include/widgets.hpp | 9 +++++++++ src/app/ModuleWidget.cpp | 8 +++++++- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/app.hpp b/include/app.hpp index a252ab14..0f6e5bba 100644 --- a/include/app.hpp +++ b/include/app.hpp @@ -14,6 +14,7 @@ struct Wire; struct RackWidget; struct ParamWidget; struct Port; +struct SVGPanel; //////////////////// // module @@ -31,6 +32,7 @@ struct ModuleWidget : OpaqueWidget { /** Owns the module pointer */ Module *module = NULL; + SVGPanel *panel = NULL; std::vector inputs; std::vector outputs; std::vector params; diff --git a/include/rack.hpp b/include/rack.hpp index 6b1595b7..9593d29f 100644 --- a/include/rack.hpp +++ b/include/rack.hpp @@ -18,15 +18,6 @@ namespace rack { //////////////////// -inline Vec in2px(Vec inches) { - return inches.mult(SVG_DPI); -} - -inline Vec mm2px(Vec millimeters) { - return millimeters.mult(SVG_DPI / 25.4); -} - - template Model *createModel(std::string manufacturerSlug, std::string manufacturerName, std::string slug, std::string name) { struct TModel : Model { diff --git a/include/widgets.hpp b/include/widgets.hpp index 9e974c61..18d7321d 100644 --- a/include/widgets.hpp +++ b/include/widgets.hpp @@ -16,6 +16,15 @@ namespace rack { +inline Vec in2px(Vec inches) { + return inches.mult(SVG_DPI); +} + +inline Vec mm2px(Vec millimeters) { + return millimeters.mult(SVG_DPI / 25.4); +} + + //////////////////// // resources //////////////////// diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 07eed233..695fe0e9 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -43,7 +43,13 @@ void ModuleWidget::addParam(ParamWidget *param) { } void ModuleWidget::setPanel(std::shared_ptr svg) { - SVGPanel *panel = new SVGPanel(); + // Remove old panel + if (panel) { + removeChild(panel); + panel = NULL; + } + + panel = new SVGPanel(); panel->setBackground(svg); addChild(panel); From b5fdf5d5ba37aeeb49d9b51af105ee1a8d422016 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Tue, 31 Oct 2017 09:35:34 -0400 Subject: [PATCH 4/4] Light::setBrightnessSmooth() turns on high values immediately, fades out low values --- src/engine.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index 17e12785..6663e2bf 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -39,8 +39,15 @@ float Light::getBrightness() { } void Light::setBrightnessSmooth(float brightness) { - // lambda = 3 * framerate - value += (brightness * brightness - value) * sampleTime * (60.0 * 3.0); + float v = brightness * brightness; + if (v < value) { + // Fade out light with lambda = 3 * framerate + value += (v - value) * sampleTime * (60.0 * 3.0); + } + else { + // Immediately illuminate light + value = v; + } }