diff --git a/CHANGELOG.md b/CHANGELOG.md index 80387841..2cd8cad2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ In this document, Mod is Ctrl on Windows/Linux and Cmd on Mac. - Add "Primary module" context menu item to VCV Audio modules to select which audio device clocks the engine. - Allow other modules such as VCV Recorder to be the primary module, to render audio faster than real-time. - Remove "Real-time priority" menu item, since the thread priority is now managed elsewhere (RtAudio, etc). +- Duplicate cables patched to inputs when a module is duplicated. +- Add module tags to module context menu. +- Add module manual URL (if plugin developer supplies it) to module context menu item. +- Add quick access to user module patches from `/presets//` to module context menu. - API - Add `Module::configInput()` and `Module::configOutput()` for adding names to ports. - Replace `ParamWidget::paramQuantity` with `ParamWidget::getParamQuantity()`. diff --git a/include/app/CableWidget.hpp b/include/app/CableWidget.hpp index 19c5b179..7d43885c 100644 --- a/include/app/CableWidget.hpp +++ b/include/app/CableWidget.hpp @@ -12,13 +12,13 @@ namespace app { struct CableWidget : widget::OpaqueWidget { + /** Owned. */ + engine::Cable* cable = NULL; + NVGcolor color; PortWidget* inputPort = NULL; PortWidget* outputPort = NULL; PortWidget* hoveredInputPort = NULL; PortWidget* hoveredOutputPort = NULL; - /** Owned. */ - engine::Cable* cable = NULL; - NVGcolor color; CableWidget(); ~CableWidget(); diff --git a/src/app/ModuleWidget.cpp b/src/app/ModuleWidget.cpp index 214251cb..11b4c1d0 100644 --- a/src/app/ModuleWidget.cpp +++ b/src/app/ModuleWidget.cpp @@ -778,6 +778,10 @@ void ModuleWidget::disconnectAction() { } void ModuleWidget::cloneAction() { + // history::ComplexAction + history::ComplexAction* h = new history::ComplexAction; + + // Clone Module engine::Module* clonedModule = model->createModule(); // JSON serialization is the obvious way to do this json_t* moduleJ = toJson(); @@ -787,13 +791,45 @@ void ModuleWidget::cloneAction() { clonedModule->id = -1; APP->engine->addModule(clonedModule); + // Clone ModuleWidget ModuleWidget* clonedModuleWidget = model->createModuleWidget(clonedModule); APP->scene->rack->addModuleAtMouse(clonedModuleWidget); // history::ModuleAdd - history::ModuleAdd* h = new history::ModuleAdd; - h->name = "clone modules"; - h->setModule(clonedModuleWidget); + history::ModuleAdd* hma = new history::ModuleAdd; + hma->name = "clone modules"; + hma->setModule(clonedModuleWidget); + h->push(hma); + + // Clone cables attached to input ports + for (PortWidget* pw : inputs) { + std::list cables = APP->scene->rack->getCablesOnPort(pw); + for (CableWidget* cw : cables) { + // Create cable attached to cloned ModuleWidget's input + engine::Cable* clonedCable = new engine::Cable; + clonedCable->id = -1; + clonedCable->inputModule = clonedModule; + clonedCable->inputId = cw->cable->inputId; + // If cable is self-patched, attach to cloned module instead + if (cw->cable->outputModule == module) + clonedCable->outputModule = clonedModule; + else + clonedCable->outputModule = cw->cable->outputModule; + clonedCable->outputId = cw->cable->outputId; + APP->engine->addCable(clonedCable); + + app::CableWidget* clonedCw = new app::CableWidget; + clonedCw->setCable(clonedCable); + clonedCw->color = cw->color; + APP->scene->rack->addCable(clonedCw); + + // history::CableAdd + history::CableAdd* hca = new history::CableAdd; + hca->setCable(clonedCw); + h->push(hca); + } + } + APP->history->push(h); }