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.4KB

  1. #pragma once
  2. #include <math.hpp>
  3. #include <random.hpp>
  4. namespace rack {
  5. /** A controller for manipulating a float value (which subclasses must store somehow) with limits and labels
  6. Often used as a decorator component for widget::Widgets that read or write a quantity.
  7. */
  8. struct Quantity {
  9. virtual ~Quantity() {}
  10. /** Sets the value directly.
  11. Override this to change the state of your subclass to represent the new value.
  12. */
  13. virtual void setValue(float value) {}
  14. /** Returns the value.
  15. Override this to return the state of your subclass.
  16. */
  17. virtual float getValue() {
  18. return 0.f;
  19. }
  20. /** Returns the minimum allowed value. */
  21. virtual float getMinValue() {
  22. return 0.f;
  23. }
  24. /** Returns the maximum allowed value. */
  25. virtual float getMaxValue() {
  26. return 1.f;
  27. }
  28. /** Returns the default value, for resetting. */
  29. virtual float getDefaultValue() {
  30. return 0.f;
  31. }
  32. /** Returns the value, possibly transformed for displaying.
  33. Useful for logarithmic scaling, multiplying by 100 for percentages, etc.
  34. */
  35. virtual float getDisplayValue() {
  36. return getValue();
  37. }
  38. /** Inversely transforms the display value and sets the value. */
  39. virtual void setDisplayValue(float displayValue) {
  40. setValue(displayValue);
  41. }
  42. /** The number of total decimal places for generating the display value string. */
  43. virtual int getDisplayPrecision();
  44. /** Returns a string representation of the display value. */
  45. virtual std::string getDisplayValueString();
  46. virtual void setDisplayValueString(std::string s);
  47. /** The name of the quantity. */
  48. virtual std::string getLabel() {
  49. return "";
  50. }
  51. /** The unit abbreviation of the quantity.
  52. Include an initial space character if you want a space after the number, e.g. "440 Hz". This allows space-less units, like "100%".
  53. */
  54. virtual std::string getUnit() {
  55. return "";
  56. }
  57. /** Returns a string representation of the quantity. */
  58. virtual std::string getString();
  59. // Helper methods
  60. /** Resets the value to the default value. */
  61. void reset() {
  62. setValue(getDefaultValue());
  63. }
  64. /** Sets the value to a uniform random value between the bounds. */
  65. void randomize() {
  66. if (isBounded())
  67. setScaledValue(random::uniform());
  68. }
  69. /** Checks whether the value is at the min value. */
  70. bool isMin() {
  71. return getValue() <= getMinValue();
  72. }
  73. /** Checks whether the value is at the max value. */
  74. bool isMax() {
  75. return getValue() >= getMaxValue();
  76. }
  77. /** Sets the value to the min value. */
  78. void setMin() {
  79. setValue(getMinValue());
  80. }
  81. /** Sets the value to the max value. */
  82. void setMax() {
  83. setValue(getMaxValue());
  84. }
  85. /** Sets value from the range 0 to 1. */
  86. void setScaledValue(float scaledValue) {
  87. setValue(math::rescale(scaledValue, 0.f, 1.f, getMinValue(), getMaxValue()));
  88. }
  89. /** Returns the value rescaled to the range 0 to 1. */
  90. float getScaledValue() {
  91. return math::rescale(getValue(), getMinValue(), getMaxValue(), 0.f, 1.f);
  92. }
  93. /** The difference between the max and min values. */
  94. float getRange() {
  95. return getMaxValue() - getMinValue();
  96. }
  97. /** Checks whether the bounds are finite. */
  98. bool isBounded() {
  99. return std::isfinite(getMinValue()) && std::isfinite(getMaxValue());
  100. }
  101. /** Adds an amount to the value. */
  102. void moveValue(float deltaValue) {
  103. setValue(getValue() + deltaValue);
  104. }
  105. /** Adds an amount to the value scaled to the range 0 to 1. */
  106. void moveScaledValue(float deltaScaledValue) {
  107. moveValue(deltaScaledValue * getRange());
  108. }
  109. };
  110. } // namespace rack