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.

156 lines
4.0KB

  1. #include <app/RackScrollWidget.hpp>
  2. #include <app/Scene.hpp>
  3. #include <window.hpp>
  4. #include <app.hpp>
  5. #include <settings.hpp>
  6. namespace rack {
  7. namespace app {
  8. RackScrollWidget::RackScrollWidget() {
  9. zoomWidget = new widget::ZoomWidget;
  10. container->addChild(zoomWidget);
  11. rackWidget = new RackWidget;
  12. rackWidget->box.size = RACK_OFFSET.mult(2);
  13. zoomWidget->addChild(rackWidget);
  14. reset();
  15. }
  16. void RackScrollWidget::step() {
  17. // Clamp zoom
  18. settings::zoom = math::clamp(settings::zoom, -2.f, 2.f);
  19. // Compute zoom from exponential zoom
  20. float zoom = std::pow(2.f, settings::zoom);
  21. if (zoom != zoomWidget->zoom) {
  22. // Set offset based on zoomPos
  23. offset = offset.plus(zoomPos).div(zoomWidget->zoom).mult(zoom).minus(zoomPos);
  24. // Set zoom
  25. zoomWidget->setZoom(zoom);
  26. }
  27. zoomPos = box.size.div(2);
  28. // Compute module bounding box
  29. math::Rect moduleBox = rackWidget->moduleContainer->getChildrenBoundingBox();
  30. if (!moduleBox.size.isFinite())
  31. moduleBox = math::Rect(RACK_OFFSET, math::Vec(0, 0));
  32. // Expand moduleBox by half a screen size
  33. math::Rect scrollBox = moduleBox;
  34. scrollBox.pos = scrollBox.pos.mult(zoom);
  35. scrollBox.size = scrollBox.size.mult(zoom);
  36. scrollBox = scrollBox.grow(box.size.mult(0.6666));
  37. // Expand to the current viewport box so that moving modules (and thus changing the module bounding box) doesn't clamp the scroll offset.
  38. math::Rect viewportBox;
  39. viewportBox.pos = oldOffset;
  40. viewportBox.size = box.size;
  41. scrollBox = scrollBox.expand(viewportBox);
  42. // Reposition widgets
  43. zoomWidget->box = scrollBox;
  44. rackWidget->box.pos = scrollBox.pos.div(zoom).neg();
  45. // Scroll rack if dragging cable near the edge of the screen
  46. math::Vec pos = APP->window->mousePos;
  47. math::Rect viewport = getViewport(box.zeroPos());
  48. if (rackWidget->incompleteCable) {
  49. float margin = 20.0;
  50. float speed = 15.0;
  51. if (pos.x <= viewport.pos.x + margin)
  52. offset.x -= speed;
  53. if (pos.x >= viewport.pos.x + viewport.size.x - margin)
  54. offset.x += speed;
  55. if (pos.y <= viewport.pos.y + margin)
  56. offset.y -= speed;
  57. if (pos.y >= viewport.pos.y + viewport.size.y - margin)
  58. offset.y += speed;
  59. }
  60. ScrollWidget::step();
  61. oldOffset = offset;
  62. }
  63. void RackScrollWidget::draw(const DrawArgs& args) {
  64. // Hide scrollbars if full screen
  65. bool fullscreen = APP->window->isFullScreen();
  66. bool horizontalVisible;
  67. bool verticalVisible;
  68. if (fullscreen) {
  69. horizontalVisible = horizontalScrollBar->visible;
  70. verticalVisible = verticalScrollBar->visible;
  71. horizontalScrollBar->visible = false;
  72. verticalScrollBar->visible = false;
  73. }
  74. ScrollWidget::draw(args);
  75. if (fullscreen) {
  76. horizontalScrollBar->visible = horizontalVisible;
  77. verticalScrollBar->visible = verticalVisible;
  78. }
  79. }
  80. void RackScrollWidget::onHoverKey(const event::HoverKey& e) {
  81. ScrollWidget::onHoverKey(e);
  82. if (e.isConsumed())
  83. return;
  84. // Scroll with arrow keys
  85. float arrowSpeed = 30.0;
  86. if ((e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT))
  87. arrowSpeed /= 16.0;
  88. else if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL)
  89. arrowSpeed *= 4.0;
  90. else if ((e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT)
  91. arrowSpeed /= 4.0;
  92. if (e.action == RACK_HELD) {
  93. switch (e.key) {
  94. case GLFW_KEY_LEFT: {
  95. offset.x -= arrowSpeed;
  96. e.consume(this);
  97. } break;
  98. case GLFW_KEY_RIGHT: {
  99. offset.x += arrowSpeed;
  100. e.consume(this);
  101. } break;
  102. case GLFW_KEY_UP: {
  103. offset.y -= arrowSpeed;
  104. e.consume(this);
  105. } break;
  106. case GLFW_KEY_DOWN: {
  107. offset.y += arrowSpeed;
  108. e.consume(this);
  109. } break;
  110. }
  111. }
  112. }
  113. void RackScrollWidget::onHoverScroll(const event::HoverScroll& e) {
  114. if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  115. // Increase zoom
  116. float zoomDelta = e.scrollDelta.y / 50 / 4;
  117. if (settings::invertZoom)
  118. zoomDelta *= -1;
  119. settings::zoom += zoomDelta;
  120. zoomPos = e.pos;
  121. e.consume(this);
  122. return;
  123. }
  124. ScrollWidget::onHoverScroll(e);
  125. }
  126. void RackScrollWidget::reset() {
  127. offset = RACK_OFFSET.mult(zoomWidget->zoom);
  128. offset = offset.minus(math::Vec(30, 30));
  129. }
  130. } // namespace app
  131. } // namespace rack