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.

176 lines
4.3KB

  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. struct PlugLight : MultiLightWidget {
  9. PlugLight() {
  10. addBaseColor(color::GREEN);
  11. addBaseColor(color::RED);
  12. box.size = math::Vec(8, 8);
  13. bgColor = color::BLACK_TRANSPARENT;
  14. }
  15. };
  16. PortWidget::PortWidget() {
  17. plugLight = new PlugLight;
  18. }
  19. PortWidget::~PortWidget() {
  20. // plugLight is not a child and is thus owned by the PortWidget, so we need to delete it here
  21. delete plugLight;
  22. // HACK
  23. if (module)
  24. app()->scene->rackWidget->cableContainer->clearPort(this);
  25. }
  26. void PortWidget::step() {
  27. if (!module)
  28. return;
  29. std::vector<float> values(2);
  30. if (type == OUTPUT) {
  31. values[0] = module->outputs[portId].plugLights[0].getBrightness();
  32. values[1] = module->outputs[portId].plugLights[1].getBrightness();
  33. }
  34. else {
  35. values[0] = module->inputs[portId].plugLights[0].getBrightness();
  36. values[1] = module->inputs[portId].plugLights[1].getBrightness();
  37. }
  38. plugLight->setValues(values);
  39. }
  40. void PortWidget::draw(NVGcontext *vg) {
  41. CableWidget *cw = app()->scene->rackWidget->cableContainer->incompleteCable;
  42. if (cw) {
  43. // Dim the PortWidget if the active cable cannot plug into this PortWidget
  44. if (type == OUTPUT ? cw->outputPort : cw->inputPort)
  45. nvgGlobalAlpha(vg, 0.5);
  46. }
  47. Widget::draw(vg);
  48. }
  49. void PortWidget::onButton(const event::Button &e) {
  50. if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {
  51. CableWidget *cw = app()->scene->rackWidget->cableContainer->getTopCable(this);
  52. if (cw) {
  53. // history::CableRemove
  54. history::CableRemove *h = new history::CableRemove;
  55. h->setCable(cw);
  56. app()->history->push(h);
  57. app()->scene->rackWidget->cableContainer->removeCable(cw);
  58. delete cw;
  59. }
  60. }
  61. e.consume(this);
  62. }
  63. void PortWidget::onDragStart(const event::DragStart &e) {
  64. CableWidget *cw = NULL;
  65. if (type == OUTPUT && (app()->window->getMods() & WINDOW_MOD_MASK) == WINDOW_MOD_CTRL) {
  66. // Keep cable NULL
  67. }
  68. else {
  69. // Grab cable on top of stack
  70. cw = app()->scene->rackWidget->cableContainer->getTopCable(this);
  71. }
  72. if (cw) {
  73. // history::CableRemove
  74. history::CableRemove *h = new history::CableRemove;
  75. h->setCable(cw);
  76. app()->history->push(h);
  77. // Disconnect and reuse existing cable
  78. app()->scene->rackWidget->cableContainer->removeCable(cw);
  79. if (type == OUTPUT)
  80. cw->setOutput(NULL);
  81. else
  82. cw->setInput(NULL);
  83. }
  84. else {
  85. // Create a new cable
  86. cw = new CableWidget;
  87. if (type == OUTPUT)
  88. cw->setOutput(this);
  89. else
  90. cw->setInput(this);
  91. }
  92. app()->scene->rackWidget->cableContainer->setIncompleteCable(cw);
  93. }
  94. void PortWidget::onDragEnd(const event::DragEnd &e) {
  95. // FIXME
  96. // If the source PortWidget is deleted, this will be called, removing the cable
  97. CableWidget *cw = app()->scene->rackWidget->cableContainer->releaseIncompleteCable();
  98. if (cw->isComplete()) {
  99. app()->scene->rackWidget->cableContainer->addCable(cw);
  100. // history::CableAdd
  101. history::CableAdd *h = new history::CableAdd;
  102. h->setCable(cw);
  103. app()->history->push(h);
  104. }
  105. else {
  106. delete cw;
  107. }
  108. }
  109. void PortWidget::onDragDrop(const event::DragDrop &e) {
  110. // Reject ports if this is an input port and something is already plugged into it
  111. if (type == INPUT) {
  112. if (app()->scene->rackWidget->cableContainer->getTopCable(this))
  113. return;
  114. }
  115. CableWidget *cw = app()->scene->rackWidget->cableContainer->incompleteCable;
  116. if (cw) {
  117. cw->hoveredOutputPort = cw->hoveredInputPort = NULL;
  118. if (type == OUTPUT)
  119. cw->setOutput(this);
  120. else
  121. cw->setInput(this);
  122. }
  123. }
  124. void PortWidget::onDragEnter(const event::DragEnter &e) {
  125. // Reject ports if this is an input port and something is already plugged into it
  126. if (type == INPUT) {
  127. if (app()->scene->rackWidget->cableContainer->getTopCable(this))
  128. return;
  129. }
  130. CableWidget *cw = app()->scene->rackWidget->cableContainer->incompleteCable;
  131. if (cw) {
  132. if (type == OUTPUT)
  133. cw->hoveredOutputPort = this;
  134. else
  135. cw->hoveredInputPort = this;
  136. }
  137. }
  138. void PortWidget::onDragLeave(const event::DragLeave &e) {
  139. PortWidget *originPort = dynamic_cast<PortWidget*>(e.origin);
  140. if (!originPort)
  141. return;
  142. CableWidget *cw = app()->scene->rackWidget->cableContainer->incompleteCable;
  143. if (cw) {
  144. if (type == OUTPUT)
  145. cw->hoveredOutputPort = NULL;
  146. else
  147. cw->hoveredInputPort = NULL;
  148. }
  149. }
  150. } // namespace rack