|
|
@@ -696,30 +696,31 @@ void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) { |
|
|
|
} |
|
|
|
|
|
|
|
void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) { |
|
|
|
mw->setPosition(pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE)); |
|
|
|
math::Rect newBox = mw->box; |
|
|
|
newBox.pos = (pos / RACK_GRID_SIZE).round() * RACK_GRID_SIZE; |
|
|
|
|
|
|
|
// Comparison of X coordinates |
|
|
|
auto cmp = [&](const widget::Widget* a, const widget::Widget* b) { |
|
|
|
return a->box.pos.x < b->box.pos.x; |
|
|
|
}; |
|
|
|
|
|
|
|
// Collect modules to the left and right of `mw` |
|
|
|
// Collect modules to the left and right of pos |
|
|
|
std::set<widget::Widget*, decltype(cmp)> leftModules(cmp); |
|
|
|
std::set<widget::Widget*, decltype(cmp)> rightModules(cmp); |
|
|
|
for (widget::Widget* w2 : internal->moduleContainer->children) { |
|
|
|
// Skip this module |
|
|
|
if (w2 == mw) |
|
|
|
continue; |
|
|
|
// Reset position to old position |
|
|
|
// Reset position to old position, including this module |
|
|
|
auto it = internal->moduleOldPositions.find(w2); |
|
|
|
if (it != internal->moduleOldPositions.end()) { |
|
|
|
w2->box.pos = it->second; |
|
|
|
} |
|
|
|
// Modules must be on the same row as `mw` |
|
|
|
if (w2->box.getTop() != mw->box.getTop()) |
|
|
|
// Skip this module |
|
|
|
if (w2 == mw) |
|
|
|
continue; |
|
|
|
// Modules must be on the same row as pos |
|
|
|
if (w2->box.getTop() != newBox.getTop()) |
|
|
|
continue; |
|
|
|
// Insert into leftModules or rightModules |
|
|
|
if (w2->box.getCenter().x < mw->box.getCenter().x) |
|
|
|
if (w2->box.getCenter().x < newBox.getCenter().x) |
|
|
|
leftModules.insert(w2); |
|
|
|
else |
|
|
|
rightModules.insert(w2); |
|
|
@@ -729,35 +730,52 @@ void RackWidget::setModulePosForce(ModuleWidget* mw, math::Vec pos) { |
|
|
|
widget::Widget* rightModule = rightModules.empty() ? NULL : *rightModules.begin(); |
|
|
|
|
|
|
|
if (leftModule) { |
|
|
|
if (leftModule->box.getRight() > mw->box.getLeft()) { |
|
|
|
mw->box.pos.x = leftModule->box.getRight(); |
|
|
|
// Place right of leftModule |
|
|
|
if (leftModule->box.getRight() > newBox.getLeft()) { |
|
|
|
newBox.pos.x = leftModule->box.getRight(); |
|
|
|
} |
|
|
|
} |
|
|
|
if (rightModule) { |
|
|
|
if (mw->box.getRight() > rightModule->box.getLeft()) { |
|
|
|
mw->box.pos.x = rightModule->box.getLeft() - mw->box.size.x; |
|
|
|
// Place left of rightModule |
|
|
|
if (newBox.getRight() > rightModule->box.getLeft()) { |
|
|
|
newBox.pos.x = rightModule->box.getLeft() - newBox.size.x; |
|
|
|
} |
|
|
|
} |
|
|
|
if (leftModule && rightModule) { |
|
|
|
// If there isn't enough space between the last leftModule and first rightModule, place module to the right of the leftModule. |
|
|
|
if (leftModule->box.getRight() + mw->box.getWidth() > rightModule->box.getLeft()) { |
|
|
|
mw->box.pos.x = leftModule->box.getRight(); |
|
|
|
|
|
|
|
// Shove right modules |
|
|
|
float xLimit = mw->box.getRight(); |
|
|
|
for (auto it = rightModules.begin(); it != rightModules.end(); it++) { |
|
|
|
widget::Widget* w2 = *it; |
|
|
|
math::Vec newPos = w2->box.pos; |
|
|
|
newPos.x = xLimit; |
|
|
|
newPos.x = std::round(newPos.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; |
|
|
|
if (w2->box.pos.x > newPos.x) |
|
|
|
break; |
|
|
|
w2->box.pos = newPos; |
|
|
|
xLimit = w2->box.getRight(); |
|
|
|
if (leftModule->box.getRight() + newBox.getWidth() > rightModule->box.getLeft()) { |
|
|
|
// If module old position is to the left of the new position, shove other modules to the left instead of the right. |
|
|
|
if (mw->box.getTop() == newBox.getTop() && mw->box.getLeft() < newBox.getLeft()) { |
|
|
|
newBox.pos.x = rightModule->box.getLeft() - newBox.size.x; |
|
|
|
|
|
|
|
// Shove left modules |
|
|
|
float xLeft = newBox.getLeft(); |
|
|
|
for (auto it = leftModules.rbegin(); it != leftModules.rend(); it++) { |
|
|
|
widget::Widget* w2 = *it; |
|
|
|
if (w2->box.getRight() <= xLeft) |
|
|
|
break; |
|
|
|
w2->box.pos.x = std::round((xLeft - w2->box.size.x) / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; |
|
|
|
xLeft = w2->box.getLeft(); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
newBox.pos.x = leftModule->box.getRight(); |
|
|
|
|
|
|
|
// Shove right modules |
|
|
|
float xRight = newBox.getRight(); |
|
|
|
for (auto it = rightModules.begin(); it != rightModules.end(); it++) { |
|
|
|
widget::Widget* w2 = *it; |
|
|
|
if (w2->box.getLeft() >= xRight) |
|
|
|
break; |
|
|
|
w2->box.pos.x = std::round(xRight / RACK_GRID_WIDTH) * RACK_GRID_WIDTH; |
|
|
|
xRight = w2->box.getRight(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
mw->box.pos = (newBox.pos / RACK_GRID_SIZE).round() * RACK_GRID_SIZE; |
|
|
|
|
|
|
|
updateExpanders(); |
|
|
|
} |
|
|
|
|
|
|
|