@@ -89,6 +89,7 @@ struct ModuleWidget : OpaqueWidget { | |||||
virtual Menu *createContextMenu(); | virtual Menu *createContextMenu(); | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
void drawShadow(NVGcontext *vg); | |||||
Vec dragPos; | Vec dragPos; | ||||
void onMouseDown(EventMouseDown &e) override; | void onMouseDown(EventMouseDown &e) override; | ||||
@@ -213,6 +214,7 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { | |||||
json_t *toJson(); | json_t *toJson(); | ||||
void fromJson(json_t *rootJ); | void fromJson(json_t *rootJ); | ||||
virtual void reset(); | |||||
virtual void randomize(); | virtual void randomize(); | ||||
void onMouseDown(EventMouseDown &e) override; | void onMouseDown(EventMouseDown &e) override; | ||||
void onChange(EventChange &e) override; | void onChange(EventChange &e) override; | ||||
@@ -17,12 +17,12 @@ void Knob::onDragStart(EventDragStart &e) { | |||||
} | } | ||||
void Knob::onDragMove(EventDragMove &e) { | void Knob::onDragMove(EventDragMove &e) { | ||||
// Drag slower if Mod | |||||
float range = maxValue - minValue; | float range = maxValue - minValue; | ||||
float delta = KNOB_SENSITIVITY * -e.mouseRel.y * speed; | float delta = KNOB_SENSITIVITY * -e.mouseRel.y * speed; | ||||
if (std::isfinite(range)) | if (std::isfinite(range)) | ||||
delta *= range; | delta *= range; | ||||
// Drag slower if Mod is held | |||||
if (guiIsModPressed()) | if (guiIsModPressed()) | ||||
delta /= 16.0; | delta /= 16.0; | ||||
dragValue += delta; | dragValue += delta; | ||||
@@ -167,7 +167,7 @@ void ModuleWidget::_delete() { | |||||
void ModuleWidget::reset() { | void ModuleWidget::reset() { | ||||
for (ParamWidget *param : params) { | for (ParamWidget *param : params) { | ||||
param->setValue(param->defaultValue); | |||||
param->reset(); | |||||
} | } | ||||
if (module) { | if (module) { | ||||
module->onReset(); | module->onReset(); | ||||
@@ -189,6 +189,18 @@ void ModuleWidget::draw(NVGcontext *vg) { | |||||
nvgResetScissor(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) { | void ModuleWidget::onMouseDown(EventMouseDown &e) { | ||||
Widget::onMouseDown(e); | Widget::onMouseDown(e); | ||||
if (e.consumed) | if (e.consumed) | ||||
@@ -18,6 +18,10 @@ void ParamWidget::fromJson(json_t *rootJ) { | |||||
setValue(json_number_value(valueJ)); | setValue(json_number_value(valueJ)); | ||||
} | } | ||||
void ParamWidget::reset() { | |||||
setValue(defaultValue); | |||||
} | |||||
void ParamWidget::randomize() { | void ParamWidget::randomize() { | ||||
if (randomizable) | if (randomizable) | ||||
setValue(rescale(randomUniform(), 0.0, 1.0, minValue, maxValue)); | setValue(rescale(randomUniform(), 0.0, 1.0, minValue, maxValue)); | ||||
@@ -12,6 +12,24 @@ | |||||
namespace rack { | 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<ModuleWidget*>(child); | |||||
w->drawShadow(vg); | |||||
nvgRestore(vg); | |||||
} | |||||
Widget::draw(vg); | |||||
} | |||||
}; | |||||
RackWidget::RackWidget() { | RackWidget::RackWidget() { | ||||
rails = new FramebufferWidget(); | rails = new FramebufferWidget(); | ||||
rails->box.size = Vec(); | rails->box.size = Vec(); | ||||
@@ -23,7 +41,7 @@ RackWidget::RackWidget() { | |||||
} | } | ||||
addChild(rails); | addChild(rails); | ||||
moduleContainer = new Widget(); | |||||
moduleContainer = new ModuleContainer(); | |||||
addChild(moduleContainer); | addChild(moduleContainer); | ||||
wireContainer = new WireContainer(); | wireContainer = new WireContainer(); | ||||
@@ -35,14 +35,14 @@ static float smoothValue; | |||||
float Light::getBrightness() { | float Light::getBrightness() { | ||||
return sqrtf(fmaxf(0.0, value)); | |||||
return sqrtf(fmaxf(0.f, value)); | |||||
} | } | ||||
void Light::setBrightnessSmooth(float brightness) { | 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) { | 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 { | else { | ||||
// Immediately illuminate light | // Immediately illuminate light | ||||