MCPcopy Create free account
hub / github.com/VCVRack/Rack / cloneAction

Method cloneAction

src/app/ModuleWidget.cpp:814–907  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

812}
813
814void ModuleWidget::cloneAction(bool cloneCables) {
815 // history::ComplexAction
816 history::ComplexAction* h = new history::ComplexAction;
817 h->name = string::translate("ModuleWidget.history.duplicateModule");
818
819 // Save patch store in this module so we can copy it below
820 APP->engine->prepareSaveModule(module);
821
822 // JSON serialization is the obvious way to do this
823 json_t* moduleJ = toJson();
824 DEFER({
825 json_decref(moduleJ);
826 });
827 engine::Module::jsonStripIds(moduleJ);
828
829 // Clone Module
830 INFO("Creating module %s", model->getFullName().c_str());
831 engine::Module* clonedModule = model->createModule();
832
833 // Set ID here so we can copy module storage dir
834 clonedModule->id = random::u64() % (1ull << 53);
835 system::copy(module->getPatchStorageDirectory(), clonedModule->getPatchStorageDirectory());
836
837 // This doesn't need a lock (via Engine::moduleFromJson()) because the Module is not added to the Engine yet.
838 try {
839 clonedModule->fromJson(moduleJ);
840 }
841 catch (Exception& e) {
842 WARN("%s", e.what());
843 }
844 APP->engine->addModule(clonedModule);
845
846 // Clone ModuleWidget
847 INFO("Creating module widget %s", model->getFullName().c_str());
848 ModuleWidget* clonedModuleWidget = model->createModuleWidget(clonedModule);
849 APP->scene->rack->updateModuleOldPositions();
850 APP->scene->rack->addModule(clonedModuleWidget);
851 // Place module to the right of `this` module, by forcing it to 1 HP to the right.
852 math::Vec clonedPos = box.pos;
853 clonedPos.x += clonedModuleWidget->box.getWidth();
854 if (settings::squeezeModules)
855 APP->scene->rack->squeezeModulePos(clonedModuleWidget, clonedPos);
856 else
857 APP->scene->rack->setModulePosNearest(clonedModuleWidget, clonedPos);
858 h->push(APP->scene->rack->getModuleDragAction());
859 APP->scene->rack->updateExpanders();
860
861 // history::ModuleAdd
862 history::ModuleAdd* hma = new history::ModuleAdd;
863 hma->setModule(clonedModuleWidget);
864 h->push(hma);
865
866 if (cloneCables) {
867 // Clone cables attached to input/output ports
868 for (PortWidget* pw : getPorts()) {
869 for (CableWidget* cw : APP->scene->rack->getCompleteCablesOnPort(pw)) {
870 // Skip input ports self-patched to this module's outputs, to avoid double-cloning them.
871 if (pw->type == engine::Port::OUTPUT && cw->cable->inputModule == module)

Callers 1

createContextMenuMethod · 0.80

Calls 15

translateFunction · 0.85
toJsonFunction · 0.85
u64Function · 0.85
copyFunction · 0.85
prepareSaveModuleMethod · 0.80
whatMethod · 0.80
getWidthMethod · 0.80
squeezeModulePosMethod · 0.80
setModulePosNearestMethod · 0.80
getModuleDragActionMethod · 0.80

Tested by

no test coverage detected