From 32acefe1d557c7c15038bbc6e4c5dc9267609735 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Fri, 13 May 2022 01:20:37 -0400 Subject: [PATCH] Reorder and tweak behaviors in RackWidget::setModulePosForce() algorithm. --- src/app/RackWidget.cpp | 71 ++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index 17913660..79876b23 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -664,50 +664,22 @@ void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) { } void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) { - math::Rect newBox = mw->box; - newBox.pos = (pos / RACK_GRID_SIZE).round() * RACK_GRID_SIZE; - // Reset modules to their old positions, including this module for (auto& pair : internal->moduleOldPositions) { widget::Widget* w2 = pair.first; w2->box.pos = pair.second; } + math::Rect oldBox = mw->box; + math::Rect newBox = mw->box; + newBox.pos = (pos / RACK_GRID_SIZE).round() * RACK_GRID_SIZE; + // Comparator of X coordinates auto cmp = [&](const widget::Widget* a, const widget::Widget* b) { return a->box.getLeft() < b->box.getLeft(); }; - // Check if new box occupies old box - if (!(newBox.pos.y == mw->box.pos.y && newBox.getLeft() <= mw->box.getRight() && newBox.getRight() >= mw->box.getLeft())) { - // Collect modules to the right of old pos - std::set rightOldModules(cmp); - for (widget::Widget* w2 : internal->moduleContainer->children) { - // Skip this module - if (w2 == mw) - continue; - // Modules must be on the same row as old pos - if (w2->box.getTop() != mw->box.getTop()) - continue; - // Insert into rightOldModules - if (w2->box.getCenter().x >= mw->box.getCenter().x) - rightOldModules.insert(w2); - } - - // Shove old right modules to the left - float xRight = mw->box.getRight(); - for (auto it = rightOldModules.begin(); it != rightOldModules.end(); it++) { - widget::Widget* w2 = *it; - // Break when module is no longer touching - if (xRight < w2->box.getLeft()) - break; - xRight = w2->box.getRight(); - // Move module to the left by the width of mw, so it replaces its position - w2->box.pos.x -= mw->box.size.x; - } - } - - // Collect modules to the left and right of pos + // Collect modules to the left and right of new pos std::set leftModules(cmp); std::set rightModules(cmp); for (widget::Widget* w2 : internal->moduleContainer->children) { @@ -750,8 +722,41 @@ void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) { newBox.pos.x = rightModule->box.getLeft() - newBox.size.x; } + // Commit new pos mw->box.pos = (newBox.pos / RACK_GRID_SIZE).round() * RACK_GRID_SIZE; + // Collect modules to the left and right of old pos, including this module. + std::set leftOldModules(cmp); + std::set rightOldModules(cmp); + for (widget::Widget* w2 : internal->moduleContainer->children) { + // Modules must be on the same row as pos + if (w2->box.getTop() != oldBox.getTop()) + continue; + // Insert into leftOldModules or rightOldModules + if (w2->box.getLeft() < oldBox.getLeft()) + leftOldModules.insert(w2); + else + rightOldModules.insert(w2); + } + + widget::Widget* leftOldModule = leftOldModules.empty() ? NULL : *leftOldModules.rbegin(); + + // Shove right modules back to empty space left by module. + float xLeft = oldBox.getLeft(); + if (leftOldModule) + xLeft = std::max(xLeft, leftOldModule->box.getRight()); + float xRight = oldBox.getRight(); + for (auto it = rightOldModules.begin(); it != rightOldModules.end(); it++) { + widget::Widget* w2 = *it; + // Break when module is no longer touching + if (xRight < w2->box.getLeft()) + break; + // Move module to the left + xRight = w2->box.getRight(); + w2->box.pos.x = xLeft; + xLeft = w2->box.getRight(); + } + updateExpanders(); }