diff --git a/include/app/ModuleWidget.hpp b/include/app/ModuleWidget.hpp index f526a5f7..157b1118 100644 --- a/include/app/ModuleWidget.hpp +++ b/include/app/ModuleWidget.hpp @@ -14,6 +14,9 @@ namespace app { /** Manages an engine::Module in the rack. */ struct ModuleWidget : widget::OpaqueWidget { + struct Internal; + Internal* internal; + plugin::Model* model = NULL; /** Owned. */ engine::Module* module = NULL; @@ -24,9 +27,6 @@ struct ModuleWidget : widget::OpaqueWidget { std::vector params; std::vector inputs; std::vector outputs; - /** For RackWidget dragging */ - math::Vec dragPos; - math::Vec oldPos; ModuleWidget(); DEPRECATED ModuleWidget(engine::Module* module) : ModuleWidget() { @@ -90,6 +90,9 @@ struct ModuleWidget : widget::OpaqueWidget { It is recommended to add a blank ui::MenuEntry first for spacing. */ virtual void appendContextMenu(ui::Menu* menu) {} + + math::Vec& dragPos(); + math::Vec& oldPos(); }; diff --git a/include/app/RackWidget.hpp b/include/app/RackWidget.hpp index c13f840f..fa3dc314 100644 --- a/include/app/RackWidget.hpp +++ b/include/app/RackWidget.hpp @@ -23,7 +23,6 @@ struct RackWidget : widget::OpaqueWidget { /** The last mouse position in the RackWidget */ math::Vec mousePos; ParamWidget* touchedParam = NULL; - std::map moduleDragPositions; int nextCableColorId = 0; RackWidget(); @@ -59,7 +58,7 @@ struct RackWidget : widget::OpaqueWidget { void setModulePosForce(ModuleWidget* mw, math::Vec pos); ModuleWidget* getModule(int moduleId); bool isEmpty(); - void updateModuleDragPositions(); + void updateModuleOldPositions(); history::ComplexAction* getModuleDragAction(); // Cable methods diff --git a/src/app/ModuleBrowser.cpp b/src/app/ModuleBrowser.cpp index a0b6f0ca..b61a907d 100644 --- a/src/app/ModuleBrowser.cpp +++ b/src/app/ModuleBrowser.cpp @@ -224,6 +224,10 @@ struct ModelBox : widget::OpaqueWidget { // Pretend the moduleWidget was clicked so it can be dragged in the RackWidget e.consume(mw); + + // Set the drag position at the center of the module + // TODO This doesn't work because ModuleWidget::onDragStart, which is called afterwards, overwrites this. + // mw->dragPos() = mw->box.size.div(2); } } diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 29fd4070..d6ba215e 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -241,13 +241,27 @@ struct ModuleDeleteItem : ui::MenuItem { }; +struct ModuleWidget::Internal { + /** The position the user clicked on the module to start dragging in the RackWidget. + */ + math::Vec dragPos; + /** The position in the RackWidget when dragging began. + Used for history::ModuleMove. + Set by RackWidget::updateModuleOldPositions() when *any* module begins dragging, since force-dragging can move other modules around. + */ + math::Vec oldPos; +}; + + ModuleWidget::ModuleWidget() { + internal = new Internal; box.size = math::Vec(0, RACK_GRID_HEIGHT); } ModuleWidget::~ModuleWidget() { clearChildren(); setModule(NULL); + delete internal; } void ModuleWidget::draw(const DrawArgs& args) { @@ -384,36 +398,30 @@ void ModuleWidget::onHoverKey(const event::HoverKey& e) { } void ModuleWidget::onDragStart(const event::DragStart& e) { - if (e.button != GLFW_MOUSE_BUTTON_LEFT) - return; - - oldPos = box.pos; - dragPos = APP->scene->rack->mousePos.minus(box.pos); - APP->scene->rack->updateModuleDragPositions(); + if (e.button == GLFW_MOUSE_BUTTON_LEFT) { + internal->dragPos = APP->scene->rack->mousePos.minus(box.pos); + APP->scene->rack->updateModuleOldPositions(); + } } void ModuleWidget::onDragEnd(const event::DragEnd& e) { - if (e.button != GLFW_MOUSE_BUTTON_LEFT) - return; - - history::ComplexAction* h = APP->scene->rack->getModuleDragAction(); - if (!h) { - delete h; - return; + if (e.button == GLFW_MOUSE_BUTTON_LEFT) { + history::ComplexAction* h = APP->scene->rack->getModuleDragAction(); + if (!h) + return; + APP->history->push(h); } - APP->history->push(h); } void ModuleWidget::onDragMove(const event::DragMove& e) { - if (e.button != GLFW_MOUSE_BUTTON_LEFT) - return; - - if (!settings::lockModules) { - math::Vec pos = APP->scene->rack->mousePos.minus(dragPos); - if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) - APP->scene->rack->setModulePosForce(this, pos); - else - APP->scene->rack->setModulePosNearest(this, pos); + if (e.button == GLFW_MOUSE_BUTTON_LEFT) { + if (!settings::lockModules) { + math::Vec pos = APP->scene->rack->mousePos.minus(internal->dragPos); + if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) + APP->scene->rack->setModulePosForce(this, pos); + else + APP->scene->rack->setModulePosNearest(this, pos); + } } } @@ -836,5 +844,14 @@ void ModuleWidget::createContextMenu() { } +math::Vec& ModuleWidget::dragPos() { + return internal->dragPos; +} + +math::Vec& ModuleWidget::oldPos() { + return internal->oldPos; +} + + } // namespace app } // namespace rack \ No newline at end of file diff --git a/src/app/PortWidget.cpp b/src/app/PortWidget.cpp index e9660f2f..fc85243a 100644 --- a/src/app/PortWidget.cpp +++ b/src/app/PortWidget.cpp @@ -276,7 +276,10 @@ void PortWidget::onDragDrop(const event::DragDrop& e) { } void PortWidget::onDragEnter(const event::DragEnter& e) { - createTooltip(); + PortWidget* pw = dynamic_cast(e.origin); + if (pw) { + createTooltip(); + } if (e.button != GLFW_MOUSE_BUTTON_LEFT) return; diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index 5887ce7e..44581643 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -521,12 +521,12 @@ bool RackWidget::isEmpty() { return moduleContainer->children.empty(); } -void RackWidget::updateModuleDragPositions() { - moduleDragPositions.clear(); +void RackWidget::updateModuleOldPositions() { + // Set all modules' oldPos field from their current position. for (widget::Widget* w : moduleContainer->children) { ModuleWidget* mw = dynamic_cast(w); assert(mw); - moduleDragPositions[mw->module->id] = mw->box.pos; + mw->oldPos() = mw->box.pos; } } @@ -536,20 +536,21 @@ history::ComplexAction* RackWidget::getModuleDragAction() { for (widget::Widget* w : moduleContainer->children) { ModuleWidget* mw = dynamic_cast(w); assert(mw); - // It is possible to add modules to the rack while dragging, so ignore modules that don't exist. - auto it = moduleDragPositions.find(mw->module->id); - if (it == moduleDragPositions.end()) - continue; // Create ModuleMove action if the module was moved. - math::Vec pos = it->second; - if (!pos.isEqual(mw->box.pos)) { + math::Vec oldPos = mw->oldPos(); + if (!oldPos.isEqual(mw->box.pos)) { history::ModuleMove* mmh = new history::ModuleMove; mmh->moduleId = mw->module->id; - mmh->oldPos = pos; + mmh->oldPos = oldPos; mmh->newPos = mw->box.pos; h->push(mmh); } } + + if (h->isEmpty()) { + delete h; + return NULL; + } return h; }