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.

222 lines
4.8KB

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