@@ -22,6 +22,7 @@ struct ScrollWidget : widget::OpaqueWidget { | |||||
bool hideScrollbars = false; | bool hideScrollbars = false; | ||||
ScrollWidget(); | ScrollWidget(); | ||||
~ScrollWidget(); | |||||
void scrollTo(math::Rect r); | void scrollTo(math::Rect r); | ||||
/** Returns the bound of allowed `offset` values in pixels. */ | /** Returns the bound of allowed `offset` values in pixels. */ | ||||
math::Rect getContainerOffsetBound(); | math::Rect getContainerOffsetBound(); | ||||
@@ -29,8 +30,11 @@ struct ScrollWidget : widget::OpaqueWidget { | |||||
math::Vec getHandleOffset(); | math::Vec getHandleOffset(); | ||||
/** Returns the handle size relative to the scrollbar. [0, 1]. */ | /** Returns the handle size relative to the scrollbar. [0, 1]. */ | ||||
math::Vec getHandleSize(); | math::Vec getHandleSize(); | ||||
/** The user is considered scrolling with the wheel until the mouse is moved. */ | |||||
bool isScrolling(); | |||||
void draw(const DrawArgs& args) override; | void draw(const DrawArgs& args) override; | ||||
void step() override; | void step() override; | ||||
void onHover(const HoverEvent& e) override; | |||||
void onButton(const ButtonEvent& e) override; | void onButton(const ButtonEvent& e) override; | ||||
void onDragStart(const DragStartEvent& e) override; | void onDragStart(const DragStartEvent& e) override; | ||||
void onDragMove(const DragMoveEvent& e) override; | void onDragMove(const DragMoveEvent& e) override; | ||||
@@ -1,6 +1,7 @@ | |||||
#include <app/Knob.hpp> | #include <app/Knob.hpp> | ||||
#include <context.hpp> | #include <context.hpp> | ||||
#include <app/Scene.hpp> | #include <app/Scene.hpp> | ||||
#include <app/RackScrollWidget.hpp> | |||||
#include <random.hpp> | #include <random.hpp> | ||||
#include <history.hpp> | #include <history.hpp> | ||||
#include <settings.hpp> | #include <settings.hpp> | ||||
@@ -226,38 +227,43 @@ void Knob::onDragLeave(const DragLeaveEvent& e) { | |||||
void Knob::onHoverScroll(const HoverScrollEvent& e) { | void Knob::onHoverScroll(const HoverScrollEvent& e) { | ||||
ParamWidget::onHoverScroll(e); | ParamWidget::onHoverScroll(e); | ||||
if (settings::knobScroll) { | |||||
engine::ParamQuantity* pq = getParamQuantity(); | |||||
if (pq) { | |||||
float value = pq->getSmoothValue(); | |||||
if (!settings::knobScroll) | |||||
return; | |||||
float rangeRatio; | |||||
if (pq->isBounded()) { | |||||
rangeRatio = pq->getRange(); | |||||
} | |||||
else { | |||||
rangeRatio = 1.f; | |||||
} | |||||
if (APP->scene->rackScroll->isScrolling()) | |||||
return; | |||||
float delta = e.scrollDelta.y; | |||||
delta *= settings::knobScrollSensitivity; | |||||
delta *= getModSpeed(); | |||||
delta *= rangeRatio; | |||||
engine::ParamQuantity* pq = getParamQuantity(); | |||||
if (!pq) | |||||
return; | |||||
// Handle value snapping | |||||
if (pq->snapEnabled) { | |||||
// Replace delta with an accumulated delta since the last integer knob. | |||||
internal->snapDelta += delta; | |||||
delta = std::trunc(internal->snapDelta); | |||||
internal->snapDelta -= delta; | |||||
} | |||||
float value = pq->getSmoothValue(); | |||||
value += delta; | |||||
pq->setSmoothValue(value); | |||||
float rangeRatio; | |||||
if (pq->isBounded()) { | |||||
rangeRatio = pq->getRange(); | |||||
} | |||||
else { | |||||
rangeRatio = 1.f; | |||||
} | |||||
e.consume(this); | |||||
} | |||||
float delta = e.scrollDelta.y; | |||||
delta *= settings::knobScrollSensitivity; | |||||
delta *= getModSpeed(); | |||||
delta *= rangeRatio; | |||||
// Handle value snapping | |||||
if (pq->snapEnabled) { | |||||
// Replace delta with an accumulated delta since the last integer knob. | |||||
internal->snapDelta += delta; | |||||
delta = std::trunc(internal->snapDelta); | |||||
internal->snapDelta -= delta; | |||||
} | } | ||||
value += delta; | |||||
pq->setSmoothValue(value); | |||||
e.consume(this); | |||||
} | } | ||||
@@ -114,10 +114,6 @@ void RackScrollWidget::onHoverKey(const HoverKeyEvent& e) { | |||||
void RackScrollWidget::onHoverScroll(const HoverScrollEvent& e) { | void RackScrollWidget::onHoverScroll(const HoverScrollEvent& e) { | ||||
ScrollWidget::onHoverScroll(e); | |||||
if (e.isConsumed()) | |||||
return; | |||||
if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) { | if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) { | ||||
// Increase zoom | // Increase zoom | ||||
float zoomDelta = e.scrollDelta.y / 50 / 4; | float zoomDelta = e.scrollDelta.y / 50 / 4; | ||||
@@ -132,6 +128,10 @@ void RackScrollWidget::onHoverScroll(const HoverScrollEvent& e) { | |||||
internal->zoomPos = e.pos; | internal->zoomPos = e.pos; | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
if (e.isConsumed()) | |||||
return; | |||||
ScrollWidget::onHoverScroll(e); | |||||
} | } | ||||
@@ -6,10 +6,14 @@ namespace rack { | |||||
namespace ui { | namespace ui { | ||||
// Internal not currently used | |||||
struct ScrollWidget::Internal { | |||||
bool scrolling = false; | |||||
}; | |||||
ScrollWidget::ScrollWidget() { | ScrollWidget::ScrollWidget() { | ||||
internal = new Internal; | |||||
container = new widget::Widget; | container = new widget::Widget; | ||||
addChild(container); | addChild(container); | ||||
@@ -25,6 +29,11 @@ ScrollWidget::ScrollWidget() { | |||||
} | } | ||||
ScrollWidget::~ScrollWidget() { | |||||
delete internal; | |||||
} | |||||
void ScrollWidget::scrollTo(math::Rect r) { | void ScrollWidget::scrollTo(math::Rect r) { | ||||
math::Rect bound = math::Rect::fromMinMax(r.getBottomRight().minus(box.size), r.pos); | math::Rect bound = math::Rect::fromMinMax(r.getBottomRight().minus(box.size), r.pos); | ||||
offset = offset.clampSafe(bound); | offset = offset.clampSafe(bound); | ||||
@@ -49,6 +58,11 @@ math::Vec ScrollWidget::getHandleSize() { | |||||
} | } | ||||
bool ScrollWidget::isScrolling() { | |||||
return internal->scrolling; | |||||
} | |||||
void ScrollWidget::draw(const DrawArgs& args) { | void ScrollWidget::draw(const DrawArgs& args) { | ||||
nvgScissor(args.vg, RECT_ARGS(args.clipBox)); | nvgScissor(args.vg, RECT_ARGS(args.clipBox)); | ||||
Widget::draw(args); | Widget::draw(args); | ||||
@@ -88,6 +102,15 @@ void ScrollWidget::step() { | |||||
} | } | ||||
void ScrollWidget::onHover(const HoverEvent& e) { | |||||
OpaqueWidget::onHover(e); | |||||
if (!e.mouseDelta.isZero()) { | |||||
internal->scrolling = false; | |||||
} | |||||
} | |||||
void ScrollWidget::onButton(const ButtonEvent& e) { | void ScrollWidget::onButton(const ButtonEvent& e) { | ||||
math::Rect offsetBound = getContainerOffsetBound(); | math::Rect offsetBound = getContainerOffsetBound(); | ||||
// Check if scrollable | // Check if scrollable | ||||
@@ -144,6 +167,7 @@ void ScrollWidget::onHoverScroll(const HoverScrollEvent& e) { | |||||
offset = offset.minus(scrollDelta); | offset = offset.minus(scrollDelta); | ||||
e.consume(this); | e.consume(this); | ||||
internal->scrolling = true; | |||||
} | } | ||||