You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
5.1KB

  1. #include "scene.hpp"
  2. #include "engine.hpp"
  3. #include "plugin.hpp"
  4. namespace rack {
  5. ModuleWidget::~ModuleWidget() {
  6. // Make sure WireWidget destructors are called *before* removing `module` from the rack.
  7. disconnectPorts();
  8. setModule(NULL);
  9. }
  10. void ModuleWidget::setModule(Module *module) {
  11. if (this->module) {
  12. engineRemoveModule(this->module);
  13. delete this->module;
  14. }
  15. if (module) {
  16. engineAddModule(module);
  17. }
  18. this->module = module;
  19. }
  20. void ModuleWidget::addInput(InputPort *input) {
  21. inputs.push_back(input);
  22. addChild(input);
  23. }
  24. void ModuleWidget::addOutput(OutputPort *output) {
  25. outputs.push_back(output);
  26. addChild(output);
  27. }
  28. void ModuleWidget::addParam(ParamWidget *param) {
  29. params.push_back(param);
  30. addChild(param);
  31. }
  32. json_t *ModuleWidget::toJson() {
  33. json_t *root = json_object();
  34. // plugin
  35. json_object_set_new(root, "plugin", json_string(model->plugin->slug.c_str()));
  36. // model
  37. json_object_set_new(root, "model", json_string(model->slug.c_str()));
  38. // pos
  39. json_t *pos = json_pack("[f, f]", (double) box.pos.x, (double) box.pos.y);
  40. json_object_set_new(root, "pos", pos);
  41. // params
  42. json_t *paramsJ = json_array();
  43. for (ParamWidget *paramWidget : params) {
  44. json_t *paramJ = paramWidget->toJson();
  45. json_array_append_new(paramsJ, paramJ);
  46. }
  47. json_object_set_new(root, "params", paramsJ);
  48. return root;
  49. }
  50. void ModuleWidget::fromJson(json_t *root) {
  51. // pos
  52. json_t *pos = json_object_get(root, "pos");
  53. double x, y;
  54. json_unpack(pos, "[F, F]", &x, &y);
  55. box.pos = Vec(x, y);
  56. // params
  57. json_t *paramsJ = json_object_get(root, "params");
  58. size_t paramId;
  59. json_t *paramJ;
  60. json_array_foreach(paramsJ, paramId, paramJ) {
  61. if (0 <= paramId && paramId < params.size()) {
  62. params[paramId]->fromJson(paramJ);
  63. }
  64. }
  65. }
  66. void ModuleWidget::disconnectPorts() {
  67. for (InputPort *input : inputs) {
  68. input->disconnect();
  69. }
  70. for (OutputPort *output : outputs) {
  71. output->disconnect();
  72. }
  73. }
  74. void ModuleWidget::resetParams() {
  75. for (ParamWidget *param : params) {
  76. param->setValue(param->defaultValue);
  77. }
  78. }
  79. void ModuleWidget::cloneParams(ModuleWidget *source) {
  80. assert(params.size() == source->params.size());
  81. for (size_t i = 0; i < params.size(); i++) {
  82. params[i]->setValue(source->params[i]->value);
  83. }
  84. }
  85. void ModuleWidget::draw(NVGcontext *vg) {
  86. Widget::draw(vg);
  87. bndBevel(vg, 0.0, 0.0, box.size.x, box.size.y);
  88. // CPU usage text
  89. if (dynamic_cast<RackScene*>(gScene)->toolbar->cpuUsageButton->value != 0.0) {
  90. float cpuTime = module ? module->cpuTime : 0.0;
  91. std::string text = stringf("%.1f%%", cpuTime * 100.0);
  92. nvgSave(vg);
  93. nvgBeginPath(vg);
  94. nvgRect(vg, 0.0, 0.0, box.size.x, BND_WIDGET_HEIGHT);
  95. nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0));
  96. nvgFill(vg);
  97. nvgBeginPath(vg);
  98. cpuTime = clampf(cpuTime, 0.0, 1.0);
  99. nvgRect(vg, 0.0, 0.0, box.size.x * cpuTime, BND_WIDGET_HEIGHT);
  100. nvgFillColor(vg, nvgHSL(0.33 * cubic(1.0 - cpuTime), 1.0, 0.4));
  101. nvgFill(vg);
  102. bndMenuItem(vg, 0.0, 0.0, box.size.x, BND_WIDGET_HEIGHT, BND_DEFAULT, -1, text.c_str());
  103. nvgRestore(vg);
  104. }
  105. }
  106. void ModuleWidget::onDragStart() {
  107. dragPos = gMousePos.minus(getAbsolutePos());
  108. }
  109. void ModuleWidget::onDragMove(Vec mouseRel) {
  110. requestedPos = gMousePos.minus(parent->getAbsolutePos()).minus(dragPos);
  111. requested = true;
  112. }
  113. void ModuleWidget::onDragEnd() {
  114. }
  115. struct DisconnectPortsMenuItem : MenuItem {
  116. ModuleWidget *moduleWidget;
  117. void onAction() {
  118. moduleWidget->disconnectPorts();
  119. }
  120. };
  121. struct ResetParamsMenuItem : MenuItem {
  122. ModuleWidget *moduleWidget;
  123. void onAction() {
  124. moduleWidget->resetParams();
  125. }
  126. };
  127. struct CloneModuleMenuItem : MenuItem {
  128. ModuleWidget *moduleWidget;
  129. void onAction() {
  130. // Create new module from model
  131. ModuleWidget *clonedModuleWidget = moduleWidget->model->createModuleWidget();
  132. clonedModuleWidget->requestedPos = moduleWidget->box.pos;
  133. clonedModuleWidget->requested = true;
  134. clonedModuleWidget->cloneParams(moduleWidget);
  135. gRackWidget->moduleContainer->addChild(clonedModuleWidget);
  136. }
  137. };
  138. struct DeleteModuleMenuItem : MenuItem {
  139. ModuleWidget *moduleWidget;
  140. void onAction() {
  141. gRackWidget->moduleContainer->removeChild(moduleWidget);
  142. delete moduleWidget;
  143. }
  144. };
  145. void ModuleWidget::onMouseDown(int button) {
  146. if (button == 1) {
  147. MenuOverlay *overlay = new MenuOverlay();
  148. Menu *menu = new Menu();
  149. menu->box.pos = gMousePos;
  150. {
  151. MenuLabel *menuLabel = new MenuLabel();
  152. menuLabel->text = model->plugin->name + ": " + model->name;
  153. menu->pushChild(menuLabel);
  154. ResetParamsMenuItem *resetItem = new ResetParamsMenuItem();
  155. resetItem->text = "Reset parameters";
  156. resetItem->moduleWidget = this;
  157. menu->pushChild(resetItem);
  158. DisconnectPortsMenuItem *disconnectItem = new DisconnectPortsMenuItem();
  159. disconnectItem->text = "Disconnect cables";
  160. disconnectItem->moduleWidget = this;
  161. menu->pushChild(disconnectItem);
  162. CloneModuleMenuItem *cloneItem = new CloneModuleMenuItem();
  163. cloneItem->text = "Clone";
  164. cloneItem->moduleWidget = this;
  165. menu->pushChild(cloneItem);
  166. DeleteModuleMenuItem *deleteItem = new DeleteModuleMenuItem();
  167. deleteItem->text = "Delete";
  168. deleteItem->moduleWidget = this;
  169. menu->pushChild(deleteItem);
  170. }
  171. overlay->addChild(menu);
  172. gScene->setOverlay(overlay);
  173. }
  174. }
  175. } // namespace rack