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
4.6KB

  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. }
  68. void PortWidget::onLeave(const event::Leave& e) {
  69. hovered = false;
  70. }
  71. void PortWidget::onDragStart(const event::DragStart& e) {
  72. if (e.button != GLFW_MOUSE_BUTTON_LEFT)
  73. return;
  74. CableWidget* cw = NULL;
  75. if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  76. if (type == OUTPUT) {
  77. // Keep cable NULL. Will be created below
  78. }
  79. else {
  80. CableWidget* topCw = APP->scene->rack->getTopCable(this);
  81. if (topCw) {
  82. cw = new CableWidget;
  83. cw->setOutput(topCw->outputPort);
  84. }
  85. }
  86. }
  87. else {
  88. // Grab cable on top of stack
  89. cw = APP->scene->rack->getTopCable(this);
  90. if (cw) {
  91. // history::CableRemove
  92. history::CableRemove* h = new history::CableRemove;
  93. h->setCable(cw);
  94. APP->history->push(h);
  95. // Disconnect and reuse existing cable
  96. APP->scene->rack->removeCable(cw);
  97. if (type == OUTPUT)
  98. cw->setOutput(NULL);
  99. else
  100. cw->setInput(NULL);
  101. }
  102. }
  103. if (!cw) {
  104. // Create a new cable
  105. cw = new CableWidget;
  106. if (type == OUTPUT)
  107. cw->setOutput(this);
  108. else
  109. cw->setInput(this);
  110. }
  111. APP->scene->rack->setIncompleteCable(cw);
  112. }
  113. void PortWidget::onDragEnd(const event::DragEnd& e) {
  114. if (e.button != GLFW_MOUSE_BUTTON_LEFT)
  115. return;
  116. CableWidget* cw = APP->scene->rack->releaseIncompleteCable();
  117. if (!cw)
  118. return;
  119. if (cw->isComplete()) {
  120. APP->scene->rack->addCable(cw);
  121. // history::CableAdd
  122. history::CableAdd* h = new history::CableAdd;
  123. h->setCable(cw);
  124. APP->history->push(h);
  125. }
  126. else {
  127. delete cw;
  128. }
  129. }
  130. void PortWidget::onDragDrop(const event::DragDrop& e) {
  131. if (e.button != GLFW_MOUSE_BUTTON_LEFT)
  132. return;
  133. // Reject ports if this is an input port and something is already plugged into it
  134. if (type == INPUT) {
  135. if (APP->scene->rack->getTopCable(this))
  136. return;
  137. }
  138. CableWidget* cw = APP->scene->rack->incompleteCable;
  139. if (cw) {
  140. cw->hoveredOutputPort = cw->hoveredInputPort = NULL;
  141. if (type == OUTPUT)
  142. cw->setOutput(this);
  143. else
  144. cw->setInput(this);
  145. }
  146. }
  147. void PortWidget::onDragEnter(const event::DragEnter& e) {
  148. if (e.button != GLFW_MOUSE_BUTTON_LEFT)
  149. return;
  150. // Reject ports if this is an input port and something is already plugged into it
  151. if (type == INPUT) {
  152. if (APP->scene->rack->getTopCable(this))
  153. return;
  154. }
  155. CableWidget* cw = APP->scene->rack->incompleteCable;
  156. if (cw) {
  157. if (type == OUTPUT)
  158. cw->hoveredOutputPort = this;
  159. else
  160. cw->hoveredInputPort = this;
  161. }
  162. }
  163. void PortWidget::onDragLeave(const event::DragLeave& e) {
  164. if (e.button != GLFW_MOUSE_BUTTON_LEFT)
  165. return;
  166. PortWidget* originPort = dynamic_cast<PortWidget*>(e.origin);
  167. if (!originPort)
  168. return;
  169. CableWidget* cw = APP->scene->rack->incompleteCable;
  170. if (cw) {
  171. if (type == OUTPUT)
  172. cw->hoveredOutputPort = NULL;
  173. else
  174. cw->hoveredInputPort = NULL;
  175. }
  176. }
  177. } // namespace app
  178. } // namespace rack