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.

276 lines
7.6KB

  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. // FIXME
  40. fNeedsRepaint(false)
  41. {
  42. setGeometryConstraints(32, 128, false);
  43. }
  44. protected:
  45. /* --------------------------------------------------------------------------------------------------------
  46. * DSP/Plugin Callbacks */
  47. /**
  48. A parameter has changed on the plugin side.
  49. This is called by the host to inform the UI about parameter changes.
  50. */
  51. void parameterChanged(uint32_t index, float value) override
  52. {
  53. switch (index)
  54. {
  55. case 0: // color
  56. updateColor(std::round(value));
  57. break;
  58. case 1: // out-left
  59. value = (fOutLeft * kSmoothMultiplier + value) / (kSmoothMultiplier + 1.0f);
  60. /**/ if (value < 0.001f) value = 0.0f;
  61. else if (value > 0.999f) value = 1.0f;
  62. if (fOutLeft != value)
  63. {
  64. fOutLeft = value;
  65. // FIXME
  66. // repaint();
  67. fNeedsRepaint = true;
  68. }
  69. break;
  70. case 2: // out-right
  71. value = (fOutRight * kSmoothMultiplier + value) / (kSmoothMultiplier + 1.0f);
  72. /**/ if (value < 0.001f) value = 0.0f;
  73. else if (value > 0.999f) value = 1.0f;
  74. if (fOutRight != value)
  75. {
  76. fOutRight = value;
  77. // FIXME
  78. // repaint();
  79. fNeedsRepaint = true;
  80. }
  81. break;
  82. }
  83. }
  84. /**
  85. A state has changed on the plugin side.
  86. This is called by the host to inform the UI about state changes.
  87. */
  88. void stateChanged(const char*, const char*) override
  89. {
  90. // nothing here
  91. }
  92. /* --------------------------------------------------------------------------------------------------------
  93. * Widget Callbacks */
  94. /**
  95. The NanoVG drawing function.
  96. */
  97. void onNanoDisplay() override
  98. {
  99. static const Color kColorBlack(0, 0, 0);
  100. static const Color kColorRed(255, 0, 0);
  101. static const Color kColorYellow(255, 255, 0);
  102. // get meter values
  103. const float outLeft(fOutLeft);
  104. const float outRight(fOutRight);
  105. // tell DSP side to reset meter values
  106. setState("reset", "");
  107. // useful vars
  108. const float halfWidth = static_cast<float>(getWidth())/2;
  109. const float redYellowHeight = static_cast<float>(getHeight())*0.2f;
  110. const float yellowBaseHeight = static_cast<float>(getHeight())*0.4f;
  111. const float baseBaseHeight = static_cast<float>(getHeight())*0.6f;
  112. // create gradients
  113. Paint fGradient1 = linearGradient(0.0f, 0.0f, 0.0f, redYellowHeight, kColorRed, kColorYellow);
  114. Paint fGradient2 = linearGradient(0.0f, redYellowHeight, 0.0f, yellowBaseHeight, kColorYellow, fColor);
  115. // paint left meter
  116. beginPath();
  117. rect(0.0f, 0.0f, halfWidth-1.0f, redYellowHeight);
  118. fillPaint(fGradient1);
  119. fill();
  120. closePath();
  121. beginPath();
  122. rect(0.0f, redYellowHeight-0.5f, halfWidth-1.0f, yellowBaseHeight);
  123. fillPaint(fGradient2);
  124. fill();
  125. closePath();
  126. beginPath();
  127. rect(0.0f, redYellowHeight+yellowBaseHeight-1.5f, halfWidth-1.0f, baseBaseHeight);
  128. fillColor(fColor);
  129. fill();
  130. closePath();
  131. // paint left black matching output level
  132. beginPath();
  133. rect(0.0f, 0.0f, halfWidth-1.0f, (1.0f-outLeft)*getHeight());
  134. fillColor(kColorBlack);
  135. fill();
  136. closePath();
  137. // paint right meter
  138. beginPath();
  139. rect(halfWidth+1.0f, 0.0f, halfWidth-2.0f, redYellowHeight);
  140. fillPaint(fGradient1);
  141. fill();
  142. closePath();
  143. beginPath();
  144. rect(halfWidth+1.0f, redYellowHeight-0.5f, halfWidth-2.0f, yellowBaseHeight);
  145. fillPaint(fGradient2);
  146. fill();
  147. closePath();
  148. beginPath();
  149. rect(halfWidth+1.0f, redYellowHeight+yellowBaseHeight-1.5f, halfWidth-2.0f, baseBaseHeight);
  150. fillColor(fColor);
  151. fill();
  152. closePath();
  153. // paint right black matching output level
  154. beginPath();
  155. rect(halfWidth+1.0f, 0.0f, halfWidth-2.0f, (1.0f-outRight)*getHeight());
  156. fillColor(kColorBlack);
  157. fill();
  158. closePath();
  159. }
  160. /**
  161. Mouse press event.
  162. This UI will change color when clicked.
  163. */
  164. bool onMouse(const MouseEvent& ev) override
  165. {
  166. // Test for left-clicked + pressed first.
  167. if (ev.button != 1 || ! ev.press)
  168. return false;
  169. const int newColor(fColorValue == 0 ? 1 : 0);
  170. updateColor(newColor);
  171. setParameterValue(0, newColor);
  172. return true;
  173. }
  174. void uiIdle() override
  175. {
  176. if (fNeedsRepaint)
  177. {
  178. fNeedsRepaint = false;
  179. repaint();
  180. }
  181. }
  182. // -------------------------------------------------------------------------------------------------------
  183. private:
  184. /**
  185. Color and its matching parameter value.
  186. */
  187. Color fColor;
  188. int fColorValue;
  189. /**
  190. Meter values.
  191. These are the parameter outputs from the DSP side.
  192. */
  193. float fOutLeft, fOutRight;
  194. // FIXME this shouldnt be needed!
  195. bool fNeedsRepaint;
  196. /**
  197. Update color if needed.
  198. */
  199. void updateColor(const int color)
  200. {
  201. if (fColorValue == color)
  202. return;
  203. fColorValue = color;
  204. switch (color)
  205. {
  206. case METER_COLOR_GREEN:
  207. fColor = Color(93, 231, 61);
  208. break;
  209. case METER_COLOR_BLUE:
  210. fColor = Color(82, 238, 248);
  211. break;
  212. }
  213. // FIXME
  214. // repaint();
  215. fNeedsRepaint = true;
  216. }
  217. /**
  218. Set our UI class as non-copyable and add a leak detector just in case.
  219. */
  220. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExampleUIMeters)
  221. };
  222. /* ------------------------------------------------------------------------------------------------------------
  223. * UI entry point, called by DPF to create a new UI instance. */
  224. UI* createUI()
  225. {
  226. return new ExampleUIMeters();
  227. }
  228. // -----------------------------------------------------------------------------------------------------------
  229. END_NAMESPACE_DISTRHO