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.

143 lines
3.6KB

  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, 0.25f, 2.f);
  19. // Round zoom to nearest percent
  20. float zoom = std::round(settings::zoom / 0.01) * 0.01;
  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. // DEBUG("%f %f %f %f", RECT_ARGS(args.clipBox));
  65. ScrollWidget::draw(args);
  66. }
  67. void RackScrollWidget::onHoverKey(const event::HoverKey &e) {
  68. ScrollWidget::onHoverKey(e);
  69. if (e.isConsumed())
  70. return;
  71. // Scroll with arrow keys
  72. float arrowSpeed = 30.0;
  73. if ((e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL |GLFW_MOD_SHIFT))
  74. arrowSpeed /= 16.0;
  75. else if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL)
  76. arrowSpeed *= 4.0;
  77. else if ((e.mods & RACK_MOD_MASK) == GLFW_MOD_SHIFT)
  78. arrowSpeed /= 4.0;
  79. if (e.action == RACK_HELD) {
  80. switch (e.key) {
  81. case GLFW_KEY_LEFT: {
  82. offset.x -= arrowSpeed;
  83. e.consume(this);
  84. } break;
  85. case GLFW_KEY_RIGHT: {
  86. offset.x += arrowSpeed;
  87. e.consume(this);
  88. } break;
  89. case GLFW_KEY_UP: {
  90. offset.y -= arrowSpeed;
  91. e.consume(this);
  92. } break;
  93. case GLFW_KEY_DOWN: {
  94. offset.y += arrowSpeed;
  95. e.consume(this);
  96. } break;
  97. }
  98. }
  99. }
  100. void RackScrollWidget::onHoverScroll(const event::HoverScroll &e) {
  101. if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  102. // Increase zoom
  103. float zoomDelta = e.scrollDelta.y / 50 / 4;
  104. if (settings::invertZoom)
  105. zoomDelta *= -1;
  106. settings::zoom *= std::pow(2, zoomDelta);
  107. zoomPos = e.pos;
  108. e.consume(this);
  109. return;
  110. }
  111. ScrollWidget::onHoverScroll(e);
  112. }
  113. void RackScrollWidget::reset() {
  114. offset = RACK_OFFSET.mult(zoomWidget->zoom);
  115. offset = offset.minus(math::Vec(30, 30));
  116. }
  117. } // namespace app
  118. } // namespace rack