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.

217 lines
5.3KB

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