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.

205 lines
4.4KB

  1. #include "app/PortWidget.hpp"
  2. #include "app/Scene.hpp"
  3. #include "window.hpp"
  4. #include "app.hpp"
  5. #include "history.hpp"
  6. #include "componentlibrary.hpp"
  7. namespace rack {
  8. namespace app {
  9. struct PlugLight : MultiLightWidget {
  10. PlugLight() {
  11. addBaseColor(componentlibrary::SCHEME_GREEN);
  12. addBaseColor(componentlibrary::SCHEME_RED);
  13. addBaseColor(componentlibrary::SCHEME_BLUE);
  14. box.size = math::Vec(8, 8);
  15. bgColor = componentlibrary::SCHEME_BLACK_TRANSPARENT;
  16. }
  17. };
  18. PortWidget::PortWidget() {
  19. plugLight = new PlugLight;
  20. }
  21. PortWidget::~PortWidget() {
  22. // plugLight is not a child and is thus owned by the PortWidget, so we need to delete it here
  23. delete plugLight;
  24. // HACK
  25. if (module)
  26. APP->scene->rack->clearCablesOnPort(this);
  27. }
  28. void PortWidget::step() {
  29. if (!module)
  30. return;
  31. std::vector<float> values(3);
  32. for (int i = 0; i < 3; i++) {
  33. if (type == OUTPUT)
  34. values[i] = module->outputs[portId].plugLights[i].getBrightness();
  35. else
  36. values[i] = module->inputs[portId].plugLights[i].getBrightness();
  37. }
  38. plugLight->setBrightnesses(values);
  39. Widget::step();
  40. }
  41. void PortWidget::draw(const DrawArgs &args) {
  42. CableWidget *cw = APP->scene->rack->incompleteCable;
  43. if (cw) {
  44. // Dim the PortWidget if the active cable cannot plug into this PortWidget
  45. if (type == OUTPUT ? cw->outputPort : cw->inputPort)
  46. nvgGlobalAlpha(args.vg, 0.5);
  47. }
  48. Widget::draw(args);
  49. }
  50. void PortWidget::onButton(const event::Button &e) {
  51. OpaqueWidget::onButton(e);
  52. if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
  53. CableWidget *cw = APP->scene->rack->getTopCable(this);
  54. if (cw) {
  55. // history::CableRemove
  56. history::CableRemove *h = new history::CableRemove;
  57. h->setCable(cw);
  58. APP->history->push(h);
  59. APP->scene->rack->removeCable(cw);
  60. delete cw;
  61. }
  62. e.consume(this);
  63. }
  64. }
  65. void PortWidget::onEnter(const event::Enter &e) {
  66. hovered = true;
  67. e.consume(this);
  68. }
  69. void PortWidget::onLeave(const event::Leave &e) {
  70. hovered = false;
  71. }
  72. void PortWidget::onDragStart(const event::DragStart &e) {
  73. if (e.button != GLFW_MOUSE_BUTTON_LEFT)
  74. return;
  75. CableWidget *cw = NULL;
  76. if ((APP->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
  77. if (type == OUTPUT) {
  78. // Keep cable NULL. Will be created below
  79. }
  80. else {
  81. CableWidget *topCw = APP->scene->rack->getTopCable(this);
  82. if (topCw) {
  83. cw = new CableWidget;
  84. cw->setOutput(topCw->outputPort);
  85. }
  86. }
  87. }
  88. else {
  89. // Grab cable on top of stack
  90. cw = APP->scene->rack->getTopCable(this);
  91. if (cw) {
  92. // history::CableRemove
  93. history::CableRemove *h = new history::CableRemove;
  94. h->setCable(cw);
  95. APP->history->push(h);
  96. // Disconnect and reuse existing cable
  97. APP->scene->rack->removeCable(cw);
  98. if (type == OUTPUT)
  99. cw->setOutput(NULL);
  100. else
  101. cw->setInput(NULL);
  102. }
  103. }
  104. if (!cw) {
  105. // Create a new cable
  106. cw = new CableWidget;
  107. if (type == OUTPUT)
  108. cw->setOutput(this);
  109. else
  110. cw->setInput(this);
  111. }
  112. APP->scene->rack->setIncompleteCable(cw);
  113. e.consume(this);
  114. }
  115. void PortWidget::onDragEnd(const event::DragEnd &e) {
  116. CableWidget *cw = APP->scene->rack->releaseIncompleteCable();
  117. if (cw->isComplete()) {
  118. APP->scene->rack->addCable(cw);
  119. // history::CableAdd
  120. history::CableAdd *h = new history::CableAdd;
  121. h->setCable(cw);
  122. APP->history->push(h);
  123. }
  124. else {
  125. delete cw;
  126. }
  127. }
  128. void PortWidget::onDragDrop(const event::DragDrop &e) {
  129. // Reject ports if this is an input port and something is already plugged into it
  130. if (type == INPUT) {
  131. if (APP->scene->rack->getTopCable(this))
  132. return;
  133. }
  134. CableWidget *cw = APP->scene->rack->incompleteCable;
  135. if (cw) {
  136. cw->hoveredOutputPort = cw->hoveredInputPort = NULL;
  137. if (type == OUTPUT)
  138. cw->setOutput(this);
  139. else
  140. cw->setInput(this);
  141. }
  142. }
  143. void PortWidget::onDragEnter(const event::DragEnter &e) {
  144. // Reject ports if this is an input port and something is already plugged into it
  145. if (type == INPUT) {
  146. if (APP->scene->rack->getTopCable(this))
  147. return;
  148. }
  149. CableWidget *cw = APP->scene->rack->incompleteCable;
  150. if (cw) {
  151. if (type == OUTPUT)
  152. cw->hoveredOutputPort = this;
  153. else
  154. cw->hoveredInputPort = this;
  155. }
  156. e.consume(this);
  157. }
  158. void PortWidget::onDragLeave(const event::DragLeave &e) {
  159. PortWidget *originPort = dynamic_cast<PortWidget*>(e.origin);
  160. if (!originPort)
  161. return;
  162. CableWidget *cw = APP->scene->rack->incompleteCable;
  163. if (cw) {
  164. if (type == OUTPUT)
  165. cw->hoveredOutputPort = NULL;
  166. else
  167. cw->hoveredInputPort = NULL;
  168. }
  169. }
  170. } // namespace app
  171. } // namespace rack