Browse Source

Reorder and tweak behaviors in RackWidget::setModulePosForce() algorithm.

tags/v2.1.1
Andrew Belt 2 years ago
parent
commit
32acefe1d5
1 changed files with 38 additions and 33 deletions
  1. +38
    -33
      src/app/RackWidget.cpp

+ 38
- 33
src/app/RackWidget.cpp View File

@@ -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<widget::Widget*, decltype(cmp)> 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<widget::Widget*, decltype(cmp)> leftModules(cmp);
std::set<widget::Widget*, decltype(cmp)> 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<widget::Widget*, decltype(cmp)> leftOldModules(cmp);
std::set<widget::Widget*, decltype(cmp)> 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();
}



Loading…
Cancel
Save