Browse Source

Add ModuleWidget force movement.

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
6fd01b217a
3 changed files with 40 additions and 10 deletions
  1. +2
    -1
      include/app/RackWidget.hpp
  2. +4
    -1
      src/app/ModuleWidget.cpp
  3. +34
    -8
      src/app/RackWidget.cpp

+ 2
- 1
include/app/RackWidget.hpp View File

@@ -51,7 +51,8 @@ struct RackWidget : widget::OpaqueWidget {
/** Sets a module's box if non-colliding. Returns true if set */
bool requestModulePos(ModuleWidget *mw, math::Vec pos);
/** Moves a module to the closest non-colliding position */
bool requestModulePosNearest(ModuleWidget *mw, math::Vec pos);
void setModulePosNearest(ModuleWidget *mw, math::Vec pos);
void setModulePosForce(ModuleWidget *mw, math::Vec pos);
ModuleWidget *getModule(int moduleId);
bool isEmpty();



+ 4
- 1
src/app/ModuleWidget.cpp View File

@@ -406,7 +406,10 @@ void ModuleWidget::onDragEnd(const event::DragEnd &e) {
void ModuleWidget::onDragMove(const event::DragMove &e) {
if (!settings::lockModules) {
math::Vec pos = APP->scene->rack->mousePos.minus(dragPos);
APP->scene->rack->requestModulePosNearest(this, pos);
if ((APP->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL)
APP->scene->rack->setModulePosForce(this, pos);
else
APP->scene->rack->setModulePosNearest(this, pos);
}
}



+ 34
- 8
src/app/RackWidget.cpp View File

@@ -376,7 +376,7 @@ void RackWidget::addModuleAtMouse(ModuleWidget *mw) {
assert(mw);
// Move module nearest to the mouse position
math::Vec pos = mousePos.minus(mw->box.size.div(2));
requestModulePosNearest(mw, pos);
setModulePosNearest(mw, pos);
addModule(mw);
}

@@ -403,15 +403,15 @@ void RackWidget::removeModule(ModuleWidget *m) {
bool RackWidget::requestModulePos(ModuleWidget *mw, math::Vec pos) {
// Check intersection with other modules
math::Rect mwBox = math::Rect(pos, mw->box.size);
for (widget::Widget *mw2 : moduleContainer->children) {
for (widget::Widget *w2 : moduleContainer->children) {
// Don't intersect with self
if (mw == mw2)
if (mw == w2)
continue;
// Don't intersect with invisible modules
if (!mw2->visible)
if (!w2->visible)
continue;
// Check intersection
if (mwBox.isIntersecting(mw2->box)) {
if (mwBox.isIntersecting(w2->box)) {
return false;
}
}
@@ -422,7 +422,7 @@ bool RackWidget::requestModulePos(ModuleWidget *mw, math::Vec pos) {
return true;
}

bool RackWidget::requestModulePosNearest(ModuleWidget *mw, math::Vec pos) {
void RackWidget::setModulePosNearest(ModuleWidget *mw, math::Vec pos) {
// Dijkstra's algorithm to generate a sorted list of Vecs closest to `pos`.

// Comparison of distance of Vecs to `pos`
@@ -447,7 +447,7 @@ bool RackWidget::requestModulePosNearest(ModuleWidget *mw, math::Vec pos) {
math::Vec testPos = queue.top();
// Check testPos
if (requestModulePos(mw, testPos))
return true;
return;
// Move testPos to visited set
queue.pop();
visited.insert(testPos);
@@ -469,7 +469,33 @@ bool RackWidget::requestModulePosNearest(ModuleWidget *mw, math::Vec pos) {

// We failed to find a box. This shouldn't happen on an infinite rack.
assert(0);
return false;
}

static void shoveIntersectingInvisibleModules(RackWidget *that, ModuleWidget *mw) {
for (widget::Widget *w2 : that->moduleContainer->children) {
if (w2->visible)
continue;
if (mw->box.isIntersecting(w2->box)) {
ModuleWidget *mw2 = dynamic_cast<ModuleWidget*>(w2);
mw2->visible = true;
that->setModulePosNearest(mw2, mw2->box.pos);
shoveIntersectingInvisibleModules(that, mw2);
}
}
}

void RackWidget::setModulePosForce(ModuleWidget *mw, math::Vec pos) {
for (widget::Widget *w2 : moduleContainer->children) {
w2->visible = false;
}

mw->visible = true;
mw->box.pos = pos.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE);
shoveIntersectingInvisibleModules(this, mw);

for (widget::Widget *w2 : moduleContainer->children) {
w2->visible = true;
}
}

ModuleWidget *RackWidget::getModule(int moduleId) {


Loading…
Cancel
Save