diff --git a/include/app.hpp b/include/app.hpp index 1ab3a233..7e1545d6 100644 --- a/include/app.hpp +++ b/include/app.hpp @@ -89,6 +89,7 @@ struct ModuleWidget : OpaqueWidget { virtual Menu *createContextMenu(); void draw(NVGcontext *vg) override; + void drawShadow(NVGcontext *vg); Vec dragPos; void onMouseDown(EventMouseDown &e) override; @@ -213,6 +214,7 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { json_t *toJson(); void fromJson(json_t *rootJ); + virtual void reset(); virtual void randomize(); void onMouseDown(EventMouseDown &e) override; void onChange(EventChange &e) override; diff --git a/src/app/Knob.cpp b/src/app/Knob.cpp index f47f3349..2442d0a4 100644 --- a/src/app/Knob.cpp +++ b/src/app/Knob.cpp @@ -17,12 +17,12 @@ void Knob::onDragStart(EventDragStart &e) { } void Knob::onDragMove(EventDragMove &e) { - // Drag slower if Mod float range = maxValue - minValue; float delta = KNOB_SENSITIVITY * -e.mouseRel.y * speed; if (std::isfinite(range)) delta *= range; + // Drag slower if Mod is held if (guiIsModPressed()) delta /= 16.0; dragValue += delta; diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 9c9beeac..564b58cc 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -167,7 +167,7 @@ void ModuleWidget::_delete() { void ModuleWidget::reset() { for (ParamWidget *param : params) { - param->setValue(param->defaultValue); + param->reset(); } if (module) { module->onReset(); @@ -189,6 +189,18 @@ void ModuleWidget::draw(NVGcontext *vg) { nvgResetScissor(vg); } +void ModuleWidget::drawShadow(NVGcontext *vg) { + nvgBeginPath(vg); + float r = 20; // Blur radius + float c = 20; // Corner radius + Vec b = 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); + NVGcolor shadowColor = nvgRGBAf(0, 0, 0, 0.2); + 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); +} + void ModuleWidget::onMouseDown(EventMouseDown &e) { Widget::onMouseDown(e); if (e.consumed) diff --git a/src/app/ParamWidget.cpp b/src/app/ParamWidget.cpp index d3a23009..7c56c34c 100644 --- a/src/app/ParamWidget.cpp +++ b/src/app/ParamWidget.cpp @@ -18,6 +18,10 @@ void ParamWidget::fromJson(json_t *rootJ) { setValue(json_number_value(valueJ)); } +void ParamWidget::reset() { + setValue(defaultValue); +} + void ParamWidget::randomize() { if (randomizable) setValue(rescale(randomUniform(), 0.0, 1.0, minValue, maxValue)); diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index eb05c874..ab32b761 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -12,6 +12,24 @@ namespace rack { +struct ModuleContainer : Widget { + void draw(NVGcontext *vg) override { + // Draw shadows behind each ModuleWidget first, so the shadow doesn't overlap the front. + for (Widget *child : children) { + if (!child->visible) + continue; + nvgSave(vg); + nvgTranslate(vg, child->box.pos.x, child->box.pos.y); + ModuleWidget *w = dynamic_cast(child); + w->drawShadow(vg); + nvgRestore(vg); + } + + Widget::draw(vg); + } +}; + + RackWidget::RackWidget() { rails = new FramebufferWidget(); rails->box.size = Vec(); @@ -23,7 +41,7 @@ RackWidget::RackWidget() { } addChild(rails); - moduleContainer = new Widget(); + moduleContainer = new ModuleContainer(); addChild(moduleContainer); wireContainer = new WireContainer(); diff --git a/src/engine.cpp b/src/engine.cpp index f08541fb..2590e82b 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -35,14 +35,14 @@ static float smoothValue; float Light::getBrightness() { - return sqrtf(fmaxf(0.0, value)); + return sqrtf(fmaxf(0.f, value)); } void Light::setBrightnessSmooth(float brightness) { - float v = (brightness > 0.0) ? brightness * brightness : 0.0; + float v = (brightness > 0.f) ? brightness * brightness : 0.f; if (v < value) { - // Fade out light with lambda = 2 * framerate - value += (v - value) * sampleTime * (60.0 * 2.0); + // Fade out light with lambda = framerate + value += (v - value) * sampleTime * (60.f * 1.f); } else { // Immediately illuminate light