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.

135 lines
3.0KB

  1. #include "app/Knob.hpp"
  2. #include "app.hpp"
  3. #include "app/Scene.hpp"
  4. #include "random.hpp"
  5. #include "history.hpp"
  6. namespace rack {
  7. namespace app {
  8. static const float KNOB_SENSITIVITY = 0.0015f;
  9. void Knob::onHover(const event::Hover &e) {
  10. math::Vec c = box.size.div(2);
  11. float dist = e.pos.minus(c).norm();
  12. if (dist <= c.x) {
  13. ParamWidget::onHover(e);
  14. }
  15. }
  16. void Knob::onButton(const event::Button &e) {
  17. math::Vec c = box.size.div(2);
  18. float dist = e.pos.minus(c).norm();
  19. if (dist <= c.x) {
  20. ParamWidget::onButton(e);
  21. }
  22. }
  23. void Knob::onDragStart(const event::DragStart &e) {
  24. if (e.button != GLFW_MOUSE_BUTTON_LEFT)
  25. return;
  26. if (paramQuantity) {
  27. oldValue = paramQuantity->getSmoothValue();
  28. if (snap) {
  29. snapValue = paramQuantity->getValue();
  30. }
  31. }
  32. APP->window->cursorLock();
  33. }
  34. void Knob::onDragEnd(const event::DragEnd &e) {
  35. if (e.button != GLFW_MOUSE_BUTTON_LEFT)
  36. return;
  37. APP->window->cursorUnlock();
  38. if (paramQuantity) {
  39. float newValue = paramQuantity->getSmoothValue();
  40. if (oldValue != newValue) {
  41. // Push ParamChange history action
  42. history::ParamChange *h = new history::ParamChange;
  43. h->name = "move knob";
  44. h->moduleId = paramQuantity->module->id;
  45. h->paramId = paramQuantity->paramId;
  46. h->oldValue = oldValue;
  47. h->newValue = newValue;
  48. APP->history->push(h);
  49. }
  50. else {
  51. // Call Action if knob was not changed
  52. event::Action eAction;
  53. onAction(eAction);
  54. }
  55. }
  56. }
  57. void Knob::onDragMove(const event::DragMove &e) {
  58. if (e.button != GLFW_MOUSE_BUTTON_LEFT)
  59. return;
  60. if (paramQuantity) {
  61. float range;
  62. if (paramQuantity->isBounded()) {
  63. range = paramQuantity->getRange();
  64. }
  65. else {
  66. // Continuous encoders scale as if their limits are +/-1
  67. range = 2.f;
  68. }
  69. float delta = (horizontal ? e.mouseDelta.x : -e.mouseDelta.y);
  70. delta *= KNOB_SENSITIVITY;
  71. delta *= speed;
  72. delta *= range;
  73. // Drag slower if mod is held
  74. int mods = APP->window->getMods();
  75. if ((mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  76. delta /= 16.f;
  77. }
  78. // Drag even slower if mod+shift is held
  79. if ((mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
  80. delta /= 256.f;
  81. }
  82. if (snap) {
  83. snapValue += delta;
  84. snapValue = math::clamp(snapValue, paramQuantity->getMinValue(), paramQuantity->getMaxValue());
  85. paramQuantity->setValue(std::round(snapValue));
  86. }
  87. else if (smooth) {
  88. paramQuantity->setSmoothValue(paramQuantity->getSmoothValue() + delta);
  89. }
  90. else {
  91. paramQuantity->setValue(paramQuantity->getValue() + delta);
  92. }
  93. }
  94. ParamWidget::onDragMove(e);
  95. }
  96. void Knob::reset() {
  97. if (paramQuantity && paramQuantity->isBounded()) {
  98. paramQuantity->reset();
  99. oldValue = snapValue = paramQuantity->getValue();
  100. }
  101. }
  102. void Knob::randomize() {
  103. if (paramQuantity && paramQuantity->isBounded()) {
  104. float value = math::rescale(random::uniform(), 0.f, 1.f, paramQuantity->getMinValue(), paramQuantity->getMaxValue());
  105. if (snap)
  106. value = std::round(value);
  107. paramQuantity->setValue(value);
  108. oldValue = snapValue = paramQuantity->getValue();
  109. }
  110. }
  111. } // namespace app
  112. } // namespace rack