@@ -39,6 +39,8 @@ extern math::Vec windowSize; | |||||
extern math::Vec windowPos; | extern math::Vec windowPos; | ||||
/** Reverse the zoom scroll direction */ | /** Reverse the zoom scroll direction */ | ||||
extern bool invertZoom; | extern bool invertZoom; | ||||
/** Mouse wheel zooms instead of pans. */ | |||||
extern bool mouseWheelZoom; | |||||
/** Ratio between UI pixel and physical screen pixel. | /** Ratio between UI pixel and physical screen pixel. | ||||
0 for auto. | 0 for auto. | ||||
*/ | */ | ||||
@@ -378,7 +378,7 @@ struct KnobScrollSensitivityQuantity : Quantity { | |||||
setValue(std::log2(displayValue) + getDefaultValue()); | setValue(std::log2(displayValue) + getDefaultValue()); | ||||
} | } | ||||
std::string getLabel() override { | std::string getLabel() override { | ||||
return "Scroll wheel knob sensitivity"; | |||||
return "Mouse wheel knob sensitivity"; | |||||
} | } | ||||
int getDisplayPrecision() override { | int getDisplayPrecision() override { | ||||
return 2; | return 2; | ||||
@@ -428,6 +428,8 @@ struct ViewButton : MenuButton { | |||||
APP->scene->rackScroll->zoomToModules(); | APP->scene->rackScroll->zoomToModules(); | ||||
})); | })); | ||||
menu->addChild(createIndexPtrSubmenuItem("Mouse wheel", {"Scroll", "Zoom"}, &settings::mouseWheelZoom)); | |||||
menu->addChild(new ui::MenuSeparator); | menu->addChild(new ui::MenuSeparator); | ||||
menu->addChild(createMenuLabel("Appearance")); | menu->addChild(createMenuLabel("Appearance")); | ||||
@@ -596,7 +598,7 @@ struct ViewButton : MenuButton { | |||||
} | } | ||||
})); | })); | ||||
menu->addChild(createBoolPtrMenuItem("Scroll wheel knob control", "", &settings::knobScroll)); | |||||
menu->addChild(createBoolPtrMenuItem("Control knobs with mouse wheel", "", &settings::knobScroll)); | |||||
KnobScrollSensitivitySlider* knobScrollSensitivitySlider = new KnobScrollSensitivitySlider; | KnobScrollSensitivitySlider* knobScrollSensitivitySlider = new KnobScrollSensitivitySlider; | ||||
knobScrollSensitivitySlider->box.size.x = 250.0; | knobScrollSensitivitySlider->box.size.x = 250.0; | ||||
@@ -154,7 +154,12 @@ void RackScrollWidget::onHoverKey(const HoverKeyEvent& e) { | |||||
void RackScrollWidget::onHoverScroll(const HoverScrollEvent& e) { | void RackScrollWidget::onHoverScroll(const HoverScrollEvent& e) { | ||||
if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||||
int mods = APP->window->getMods(); | |||||
if ((mods & RACK_MOD_MASK) == (settings::mouseWheelZoom ? 0 : RACK_MOD_CTRL)) { | |||||
// Dispatch to children first and zoom only if they don't consume | |||||
OpaqueWidget::onHoverScroll(e); | |||||
if (e.isConsumed()) | |||||
return; | |||||
// Increase zoom | // Increase zoom | ||||
float zoomDelta = e.scrollDelta.y / 50 / 4; | float zoomDelta = e.scrollDelta.y / 50 / 4; | ||||
if (settings::invertZoom) | if (settings::invertZoom) | ||||
@@ -162,10 +167,9 @@ void RackScrollWidget::onHoverScroll(const HoverScrollEvent& e) { | |||||
float zoom = getZoom() * std::pow(2.f, zoomDelta); | float zoom = getZoom() * std::pow(2.f, zoomDelta); | ||||
setZoom(zoom, e.pos); | setZoom(zoom, e.pos); | ||||
e.consume(this); | e.consume(this); | ||||
return; | |||||
} | } | ||||
if (e.isConsumed()) | |||||
return; | |||||
ScrollWidget::onHoverScroll(e); | ScrollWidget::onHoverScroll(e); | ||||
} | } | ||||
@@ -26,6 +26,7 @@ bool windowMaximized = false; | |||||
math::Vec windowSize = math::Vec(1024, 720); | math::Vec windowSize = math::Vec(1024, 720); | ||||
math::Vec windowPos = math::Vec(NAN, NAN); | math::Vec windowPos = math::Vec(NAN, NAN); | ||||
bool invertZoom = false; | bool invertZoom = false; | ||||
bool mouseWheelZoom = false; | |||||
float pixelRatio = 0.0; | float pixelRatio = 0.0; | ||||
std::string uiTheme = "dark"; | std::string uiTheme = "dark"; | ||||
float cableOpacity = 0.5; | float cableOpacity = 0.5; | ||||
@@ -140,6 +141,8 @@ json_t* toJson() { | |||||
json_object_set_new(rootJ, "invertZoom", json_boolean(invertZoom)); | json_object_set_new(rootJ, "invertZoom", json_boolean(invertZoom)); | ||||
json_object_set_new(rootJ, "mouseWheelZoom", json_boolean(mouseWheelZoom)); | |||||
json_object_set_new(rootJ, "pixelRatio", json_real(pixelRatio)); | json_object_set_new(rootJ, "pixelRatio", json_real(pixelRatio)); | ||||
json_object_set_new(rootJ, "uiTheme", json_string(uiTheme.c_str())); | json_object_set_new(rootJ, "uiTheme", json_string(uiTheme.c_str())); | ||||
@@ -311,6 +314,10 @@ void fromJson(json_t* rootJ) { | |||||
if (invertZoomJ) | if (invertZoomJ) | ||||
invertZoom = json_boolean_value(invertZoomJ); | invertZoom = json_boolean_value(invertZoomJ); | ||||
json_t* mouseWheelZoomJ = json_object_get(rootJ, "mouseWheelZoom"); | |||||
if (mouseWheelZoomJ) | |||||
mouseWheelZoom = json_boolean_value(mouseWheelZoomJ); | |||||
json_t* pixelRatioJ = json_object_get(rootJ, "pixelRatio"); | json_t* pixelRatioJ = json_object_get(rootJ, "pixelRatio"); | ||||
if (pixelRatioJ) | if (pixelRatioJ) | ||||
pixelRatio = json_number_value(pixelRatioJ); | pixelRatio = json_number_value(pixelRatioJ); | ||||
@@ -147,11 +147,6 @@ void ScrollWidget::onHoverScroll(const HoverScrollEvent& e) { | |||||
if (e.isConsumed()) | if (e.isConsumed()) | ||||
return; | return; | ||||
int mods = APP->window->getMods(); | |||||
// Don't scroll when Ctrl is held because this interferes with RackScrollWidget zooming. | |||||
if ((mods & RACK_MOD_MASK) & RACK_MOD_CTRL) | |||||
return; | |||||
// Check if scrollable | // Check if scrollable | ||||
math::Rect offsetBound = getContainerOffsetBound(); | math::Rect offsetBound = getContainerOffsetBound(); | ||||
if (offsetBound.size.x <= 0.f && offsetBound.size.y <= 0.f) | if (offsetBound.size.x <= 0.f && offsetBound.size.y <= 0.f) | ||||
@@ -161,7 +156,8 @@ void ScrollWidget::onHoverScroll(const HoverScrollEvent& e) { | |||||
// Flip coordinates if shift is held | // Flip coordinates if shift is held | ||||
// Mac (or GLFW?) already does this for us. | // Mac (or GLFW?) already does this for us. | ||||
#if !defined ARCH_MAC | #if !defined ARCH_MAC | ||||
if ((mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT) | |||||
int mods = APP->window->getMods(); | |||||
if ((mods & RACK_MOD_MASK) & GLFW_MOD_SHIFT) | |||||
scrollDelta = scrollDelta.flip(); | scrollDelta = scrollDelta.flip(); | ||||
#endif | #endif | ||||