| @@ -6,6 +6,8 @@ | |||||
| #include "app/CableWidget.hpp" | #include "app/CableWidget.hpp" | ||||
| #include "app/PortWidget.hpp" | #include "app/PortWidget.hpp" | ||||
| #include "app/ParamWidget.hpp" | #include "app/ParamWidget.hpp" | ||||
| #include "history.hpp" | |||||
| #include <map> | |||||
| namespace rack { | namespace rack { | ||||
| @@ -21,6 +23,7 @@ struct RackWidget : widget::OpaqueWidget { | |||||
| /** The last mouse position in the RackWidget */ | /** The last mouse position in the RackWidget */ | ||||
| math::Vec mousePos; | math::Vec mousePos; | ||||
| ParamWidget *touchedParam = NULL; | ParamWidget *touchedParam = NULL; | ||||
| std::map<int, math::Vec> moduleDragPositions; | |||||
| RackWidget(); | RackWidget(); | ||||
| ~RackWidget(); | ~RackWidget(); | ||||
| @@ -55,6 +58,8 @@ struct RackWidget : widget::OpaqueWidget { | |||||
| void setModulePosForce(ModuleWidget *mw, math::Vec pos); | void setModulePosForce(ModuleWidget *mw, math::Vec pos); | ||||
| ModuleWidget *getModule(int moduleId); | ModuleWidget *getModule(int moduleId); | ||||
| bool isEmpty(); | bool isEmpty(); | ||||
| void updateModuleDragPositions(); | |||||
| history::ComplexAction *getModuleDragAction(); | |||||
| // Cable methods | // Cable methods | ||||
| @@ -53,6 +53,7 @@ struct ComplexAction : Action { | |||||
| void undo() override; | void undo() override; | ||||
| void redo() override; | void redo() override; | ||||
| void push(Action *action); | void push(Action *action); | ||||
| bool isEmpty(); | |||||
| }; | }; | ||||
| @@ -386,17 +386,16 @@ void ModuleWidget::onDragStart(const event::DragStart &e) { | |||||
| oldPos = box.pos; | oldPos = box.pos; | ||||
| dragPos = APP->scene->rack->mousePos.minus(box.pos); | dragPos = APP->scene->rack->mousePos.minus(box.pos); | ||||
| APP->scene->rack->updateModuleDragPositions(); | |||||
| } | } | ||||
| void ModuleWidget::onDragEnd(const event::DragEnd &e) { | void ModuleWidget::onDragEnd(const event::DragEnd &e) { | ||||
| if (!box.pos.isEqual(oldPos)) { | |||||
| // history::ModuleMove | |||||
| history::ModuleMove *h = new history::ModuleMove; | |||||
| h->moduleId = module->id; | |||||
| h->oldPos = oldPos; | |||||
| h->newPos = box.pos; | |||||
| APP->history->push(h); | |||||
| history::ComplexAction *h = APP->scene->rack->getModuleDragAction(); | |||||
| if (!h) { | |||||
| delete h; | |||||
| return; | |||||
| } | } | ||||
| APP->history->push(h); | |||||
| } | } | ||||
| void ModuleWidget::onDragMove(const event::DragMove &e) { | void ModuleWidget::onDragMove(const event::DragMove &e) { | ||||
| @@ -521,10 +521,10 @@ void RackWidget::setModulePosForce(ModuleWidget *mw, math::Vec pos) { | |||||
| ModuleWidget *RackWidget::getModule(int moduleId) { | ModuleWidget *RackWidget::getModule(int moduleId) { | ||||
| for (widget::Widget *w : moduleContainer->children) { | for (widget::Widget *w : moduleContainer->children) { | ||||
| ModuleWidget *moduleWidget = dynamic_cast<ModuleWidget*>(w); | |||||
| assert(moduleWidget); | |||||
| if (moduleWidget->module->id == moduleId) | |||||
| return moduleWidget; | |||||
| ModuleWidget *mw = dynamic_cast<ModuleWidget*>(w); | |||||
| assert(mw); | |||||
| if (mw->module->id == moduleId) | |||||
| return mw; | |||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| @@ -533,6 +533,34 @@ bool RackWidget::isEmpty() { | |||||
| return moduleContainer->children.empty(); | return moduleContainer->children.empty(); | ||||
| } | } | ||||
| void RackWidget::updateModuleDragPositions() { | |||||
| moduleDragPositions.clear(); | |||||
| for (widget::Widget *w : moduleContainer->children) { | |||||
| ModuleWidget *mw = dynamic_cast<ModuleWidget*>(w); | |||||
| assert(mw); | |||||
| moduleDragPositions[mw->module->id] = mw->box.pos; | |||||
| } | |||||
| } | |||||
| history::ComplexAction *RackWidget::getModuleDragAction() { | |||||
| history::ComplexAction *h = new history::ComplexAction; | |||||
| for (widget::Widget *w : moduleContainer->children) { | |||||
| ModuleWidget *mw = dynamic_cast<ModuleWidget*>(w); | |||||
| assert(mw); | |||||
| math::Vec pos = moduleDragPositions.at(mw->module->id); | |||||
| if (!pos.isEqual(mw->box.pos)) { | |||||
| history::ModuleMove *mmh = new history::ModuleMove; | |||||
| mmh->moduleId = mw->module->id; | |||||
| mmh->oldPos = pos; | |||||
| mmh->newPos = mw->box.pos; | |||||
| h->push(mmh); | |||||
| } | |||||
| } | |||||
| return h; | |||||
| } | |||||
| void RackWidget::clearCables() { | void RackWidget::clearCables() { | ||||
| for (widget::Widget *w : cableContainer->children) { | for (widget::Widget *w : cableContainer->children) { | ||||
| CableWidget *cw = dynamic_cast<CableWidget*>(w); | CableWidget *cw = dynamic_cast<CableWidget*>(w); | ||||
| @@ -294,21 +294,16 @@ static void Engine_relaunchWorkers(Engine *that) { | |||||
| assert(1 <= internal->threadCount); | assert(1 <= internal->threadCount); | ||||
| // Stop all workers | // Stop all workers | ||||
| DEBUG("1"); | |||||
| for (EngineWorker &worker : internal->workers) { | for (EngineWorker &worker : internal->workers) { | ||||
| worker.stop(); | worker.stop(); | ||||
| } | } | ||||
| DEBUG("2"); | |||||
| internal->engineBarrier.wait(); | internal->engineBarrier.wait(); | ||||
| // Destroy all workers | // Destroy all workers | ||||
| DEBUG("3"); | |||||
| for (EngineWorker &worker : internal->workers) { | for (EngineWorker &worker : internal->workers) { | ||||
| worker.join(); | worker.join(); | ||||
| } | } | ||||
| DEBUG("4"); | |||||
| internal->workers.resize(0); | internal->workers.resize(0); | ||||
| DEBUG("5"); | |||||
| // Configure main thread | // Configure main thread | ||||
| system::setThreadRealTime(internal->realTime); | system::setThreadRealTime(internal->realTime); | ||||
| @@ -318,7 +313,6 @@ static void Engine_relaunchWorkers(Engine *that) { | |||||
| internal->workerBarrier.total = internal->threadCount; | internal->workerBarrier.total = internal->threadCount; | ||||
| // Create workers | // Create workers | ||||
| DEBUG("6"); | |||||
| internal->workers.resize(internal->threadCount - 1); | internal->workers.resize(internal->threadCount - 1); | ||||
| for (int id = 1; id < internal->threadCount; id++) { | for (int id = 1; id < internal->threadCount; id++) { | ||||
| EngineWorker &worker = internal->workers[id - 1]; | EngineWorker &worker = internal->workers[id - 1]; | ||||
| @@ -326,7 +320,6 @@ static void Engine_relaunchWorkers(Engine *that) { | |||||
| worker.engine = that; | worker.engine = that; | ||||
| worker.start(); | worker.start(); | ||||
| } | } | ||||
| DEBUG("7"); | |||||
| } | } | ||||
| static void Engine_run(Engine *that) { | static void Engine_run(Engine *that) { | ||||
| @@ -32,6 +32,10 @@ void ComplexAction::push(Action *action) { | |||||
| actions.push_back(action); | actions.push_back(action); | ||||
| } | } | ||||
| bool ComplexAction::isEmpty() { | |||||
| return actions.empty(); | |||||
| } | |||||
| ModuleAdd::~ModuleAdd() { | ModuleAdd::~ModuleAdd() { | ||||
| json_decref(moduleJ); | json_decref(moduleJ); | ||||