diff --git a/include/app/RackWidget.hpp b/include/app/RackWidget.hpp index 8fe5b98f..7052b657 100644 --- a/include/app/RackWidget.hpp +++ b/include/app/RackWidget.hpp @@ -86,6 +86,7 @@ struct RackWidget : widget::OpaqueWidget { bool areSelectedModulesBypassed(); void deleteSelectedModulesAction(); bool requestSelectedModulePos(math::Vec delta); + void setSelectedModulesPosNearest(math::Vec delta); void appendSelectionContextMenu(ui::Menu* menu); // Cable methods diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 7386b371..d41547eb 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -463,7 +463,7 @@ void ModuleWidget::onDragMove(const DragMoveEvent& e) { if (internal->selected) { pos = (pos / RACK_GRID_SIZE).round() * RACK_GRID_SIZE; math::Vec delta = pos.minus(box.pos); - APP->scene->rack->requestSelectedModulePos(delta); + APP->scene->rack->setSelectedModulesPosNearest(delta); } else { if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index 668c5d6d..dc7c1bb2 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -496,7 +497,7 @@ bool RackWidget::requestModulePos(ModuleWidget* mw, math::Vec pos) { return true; } -void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) { +static void eachNearestGridPos(math::Vec pos, std::function f) { // Dijkstra's algorithm to generate a sorted list of Vecs closest to `pos`. // Comparison of distance of Vecs to `pos` @@ -520,7 +521,7 @@ void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) { while (!queue.empty()) { math::Vec testPos = queue.top(); // Check testPos - if (requestModulePos(mw, testPos)) + if (f(testPos)) return; // Move testPos to visited set queue.pop(); @@ -545,6 +546,12 @@ void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) { assert(false); } +void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) { + eachNearestGridPos(pos, [&](math::Vec pos) -> bool { + return requestModulePos(mw, pos); + }); +} + void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) { mw->setPosition(pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE)); @@ -835,6 +842,12 @@ bool RackWidget::requestSelectedModulePos(math::Vec delta) { return true; } +void RackWidget::setSelectedModulesPosNearest(math::Vec delta) { + eachNearestGridPos(delta, [&](math::Vec delta) -> bool { + return requestSelectedModulePos(delta); + }); +} + void RackWidget::appendSelectionContextMenu(ui::Menu* menu) { int n = getNumSelectedModules(); menu->addChild(createMenuLabel(string::f("%d selected %s", n, n == 1 ? "module" : "modules")));