DISTRHO Plugin Framework
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.

256 lines
7.2KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2019 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include "DistrhoUI.hpp"
  17. START_NAMESPACE_DISTRHO
  18. /**
  19. We need the Color class from DGL.
  20. */
  21. using DGL_NAMESPACE::Color;
  22. /**
  23. Smooth meters a bit.
  24. */
  25. static const float kSmoothMultiplier = 3.0f;
  26. // -----------------------------------------------------------------------------------------------------------
  27. class ExampleUIMeters : public UI
  28. {
  29. public:
  30. ExampleUIMeters()
  31. : UI(128, 512),
  32. // default color is green
  33. fColor(93, 231, 61),
  34. // which is value 0
  35. fColorValue(0),
  36. // init meter values to 0
  37. fOutLeft(0.0f),
  38. fOutRight(0.0f)
  39. {
  40. setGeometryConstraints(32, 128, false);
  41. }
  42. protected:
  43. /* --------------------------------------------------------------------------------------------------------
  44. * DSP/Plugin Callbacks */
  45. /**
  46. A parameter has changed on the plugin side.
  47. This is called by the host to inform the UI about parameter changes.
  48. */
  49. void parameterChanged(uint32_t index, float value) override
  50. {
  51. switch (index)
  52. {
  53. case 0: // color
  54. updateColor(std::round(value));
  55. break;
  56. case 1: // out-left
  57. value = (fOutLeft * kSmoothMultiplier + value) / (kSmoothMultiplier + 1.0f);
  58. /**/ if (value < 0.001f) value = 0.0f;
  59. else if (value > 0.999f) value = 1.0f;
  60. if (fOutLeft != value)
  61. {
  62. fOutLeft = value;
  63. repaint();
  64. }
  65. break;
  66. case 2: // out-right
  67. value = (fOutRight * kSmoothMultiplier + value) / (kSmoothMultiplier + 1.0f);
  68. /**/ if (value < 0.001f) value = 0.0f;
  69. else if (value > 0.999f) value = 1.0f;
  70. if (fOutRight != value)
  71. {
  72. fOutRight = value;
  73. repaint();
  74. }
  75. break;
  76. }
  77. }
  78. /**
  79. A state has changed on the plugin side.
  80. This is called by the host to inform the UI about state changes.
  81. */
  82. void stateChanged(const char*, const char*) override
  83. {
  84. // nothing here
  85. }
  86. /* --------------------------------------------------------------------------------------------------------
  87. * Widget Callbacks */
  88. /**
  89. The NanoVG drawing function.
  90. */
  91. void onNanoDisplay() override
  92. {
  93. static const Color kColorBlack(0, 0, 0);
  94. static const Color kColorRed(255, 0, 0);
  95. static const Color kColorYellow(255, 255, 0);
  96. // get meter values
  97. const float outLeft(fOutLeft);
  98. const float outRight(fOutRight);
  99. // tell DSP side to reset meter values
  100. setState("reset", "");
  101. // useful vars
  102. const float halfWidth = static_cast<float>(getWidth())/2;
  103. const float redYellowHeight = static_cast<float>(getHeight())*0.2f;
  104. const float yellowBaseHeight = static_cast<float>(getHeight())*0.4f;
  105. const float baseBaseHeight = static_cast<float>(getHeight())*0.6f;
  106. // create gradients
  107. Paint fGradient1 = linearGradient(0.0f, 0.0f, 0.0f, redYellowHeight, kColorRed, kColorYellow);
  108. Paint fGradient2 = linearGradient(0.0f, redYellowHeight, 0.0f, yellowBaseHeight, kColorYellow, fColor);
  109. // paint left meter
  110. beginPath();
  111. rect(0.0f, 0.0f, halfWidth-1.0f, redYellowHeight);
  112. fillPaint(fGradient1);
  113. fill();
  114. closePath();
  115. beginPath();
  116. rect(0.0f, redYellowHeight-0.5f, halfWidth-1.0f, yellowBaseHeight);
  117. fillPaint(fGradient2);
  118. fill();
  119. closePath();
  120. beginPath();
  121. rect(0.0f, redYellowHeight+yellowBaseHeight-1.5f, halfWidth-1.0f, baseBaseHeight);
  122. fillColor(fColor);
  123. fill();
  124. closePath();
  125. // paint left black matching output level
  126. beginPath();
  127. rect(0.0f, 0.0f, halfWidth-1.0f, (1.0f-outLeft)*getHeight());
  128. fillColor(kColorBlack);
  129. fill();
  130. closePath();
  131. // paint right meter
  132. beginPath();
  133. rect(halfWidth+1.0f, 0.0f, halfWidth-2.0f, redYellowHeight);
  134. fillPaint(fGradient1);
  135. fill();
  136. closePath();
  137. beginPath();
  138. rect(halfWidth+1.0f, redYellowHeight-0.5f, halfWidth-2.0f, yellowBaseHeight);
  139. fillPaint(fGradient2);
  140. fill();
  141. closePath();
  142. beginPath();
  143. rect(halfWidth+1.0f, redYellowHeight+yellowBaseHeight-1.5f, halfWidth-2.0f, baseBaseHeight);
  144. fillColor(fColor);
  145. fill();
  146. closePath();
  147. // paint right black matching output level
  148. beginPath();
  149. rect(halfWidth+1.0f, 0.0f, halfWidth-2.0f, (1.0f-outRight)*getHeight());
  150. fillColor(kColorBlack);
  151. fill();
  152. closePath();
  153. }
  154. /**
  155. Mouse press event.
  156. This UI will change color when clicked.
  157. */
  158. bool onMouse(const MouseEvent& ev) override
  159. {
  160. // Test for left-clicked + pressed first.
  161. if (ev.button != 1 || ! ev.press)
  162. return false;
  163. const int newColor(fColorValue == 0 ? 1 : 0);
  164. updateColor(newColor);
  165. setParameterValue(0, newColor);
  166. return true;
  167. }
  168. // -------------------------------------------------------------------------------------------------------
  169. private:
  170. /**
  171. Color and its matching parameter value.
  172. */
  173. Color fColor;
  174. int fColorValue;
  175. /**
  176. Meter values.
  177. These are the parameter outputs from the DSP side.
  178. */
  179. float fOutLeft, fOutRight;
  180. /**
  181. Update color if needed.
  182. */
  183. void updateColor(const int color)
  184. {
  185. if (fColorValue == color)
  186. return;
  187. fColorValue = color;
  188. switch (color)
  189. {
  190. case METER_COLOR_GREEN:
  191. fColor = Color(93, 231, 61);
  192. break;
  193. case METER_COLOR_BLUE:
  194. fColor = Color(82, 238, 248);
  195. break;
  196. }
  197. repaint();
  198. }
  199. /**
  200. Set our UI class as non-copyable and add a leak detector just in case.
  201. */
  202. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExampleUIMeters)
  203. };
  204. /* ------------------------------------------------------------------------------------------------------------
  205. * UI entry point, called by DPF to create a new UI instance. */
  206. UI* createUI()
  207. {
  208. return new ExampleUIMeters();
  209. }
  210. // -----------------------------------------------------------------------------------------------------------
  211. END_NAMESPACE_DISTRHO