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.

76 lines
1.5KB

  1. #include <app/SvgKnob.hpp>
  2. namespace rack {
  3. namespace app {
  4. SvgKnob::SvgKnob() {
  5. fb = new widget::FramebufferWidget;
  6. addChild(fb);
  7. shadow = new CircularShadow;
  8. fb->addChild(shadow);
  9. shadow->box.size = math::Vec();
  10. tw = new widget::TransformWidget;
  11. fb->addChild(tw);
  12. sw = new widget::SvgWidget;
  13. tw->addChild(sw);
  14. }
  15. void SvgKnob::setSvg(std::shared_ptr<window::Svg> svg) {
  16. if (svg == sw->svg)
  17. return;
  18. sw->setSvg(svg);
  19. tw->box.size = sw->box.size;
  20. fb->box.size = sw->box.size;
  21. box.size = sw->box.size;
  22. shadow->box.size = sw->box.size;
  23. // Move shadow downward by 10%
  24. shadow->box.pos = math::Vec(0, sw->box.size.y * 0.10);
  25. // shadow->box = shadow->box.grow(math::Vec(2, 2));
  26. fb->setDirty();
  27. }
  28. void SvgKnob::onChange(const ChangeEvent& e) {
  29. float angle = 0.f;
  30. // Calculate angle from value
  31. engine::ParamQuantity* pq = getParamQuantity();
  32. if (pq) {
  33. float value = pq->getValue();
  34. if (!pq->isBounded()) {
  35. // Number of rotations equals value for unbounded range
  36. angle = value * (2 * M_PI);
  37. }
  38. else if (pq->getRange() == 0.f) {
  39. // Center angle for zero range
  40. angle = (minAngle + maxAngle) / 2.f;
  41. }
  42. else {
  43. // Proportional angle for finite range
  44. angle = math::rescale(value, pq->getMinValue(), pq->getMaxValue(), minAngle, maxAngle);
  45. }
  46. angle = std::fmod(angle, 2 * M_PI);
  47. }
  48. tw->identity();
  49. // Rotate SVG
  50. math::Vec center = sw->box.getCenter();
  51. tw->translate(center);
  52. tw->rotate(angle);
  53. tw->translate(center.neg());
  54. fb->setDirty();
  55. Knob::onChange(e);
  56. }
  57. } // namespace app
  58. } // namespace rack