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.

281 lines
8.0KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2021 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. #include "Color.hpp"
  18. START_NAMESPACE_DISTRHO
  19. /**
  20. We need the Color class from DGL.
  21. */
  22. using DGL_NAMESPACE::Color;
  23. /**
  24. We need the rectangle class from DGL.
  25. */
  26. using DGL_NAMESPACE::Rectangle;
  27. // -----------------------------------------------------------------------------------------------------------
  28. class ExampleUIParameters : public UI
  29. {
  30. public:
  31. /* constructor */
  32. ExampleUIParameters()
  33. : UI(512, 512)
  34. {
  35. /**
  36. Initialize all our parameters to their defaults.
  37. In this example all default values are false, so we can simply zero them.
  38. */
  39. std::memset(fParamGrid, 0, sizeof(bool)*9);
  40. // TODO explain why this is here
  41. setGeometryConstraints(128, 128, true, false);
  42. }
  43. protected:
  44. /* --------------------------------------------------------------------------------------------------------
  45. * DSP/Plugin Callbacks */
  46. /**
  47. A parameter has changed on the plugin side.
  48. This is called by the host to inform the UI about parameter changes.
  49. */
  50. void parameterChanged(uint32_t index, float value) override
  51. {
  52. // update our grid state to match the plugin side
  53. fParamGrid[index] = (value > 0.5f);
  54. // trigger repaint
  55. repaint();
  56. }
  57. /**
  58. A program has been loaded on the plugin side.
  59. This is called by the host to inform the UI about program changes.
  60. */
  61. void programLoaded(uint32_t index) override
  62. {
  63. switch (index)
  64. {
  65. case 0:
  66. fParamGrid[0] = false;
  67. fParamGrid[1] = false;
  68. fParamGrid[2] = false;
  69. fParamGrid[3] = false;
  70. fParamGrid[4] = false;
  71. fParamGrid[5] = false;
  72. fParamGrid[6] = false;
  73. fParamGrid[7] = false;
  74. fParamGrid[8] = false;
  75. break;
  76. case 1:
  77. fParamGrid[0] = true;
  78. fParamGrid[1] = true;
  79. fParamGrid[2] = false;
  80. fParamGrid[3] = false;
  81. fParamGrid[4] = true;
  82. fParamGrid[5] = true;
  83. fParamGrid[6] = true;
  84. fParamGrid[7] = false;
  85. fParamGrid[8] = true;
  86. break;
  87. }
  88. repaint();
  89. }
  90. /* --------------------------------------------------------------------------------------------------------
  91. * Widget Callbacks */
  92. /**
  93. The OpenGL drawing function.
  94. This UI will draw a 3x3 grid, with on/off states according to plugin parameters.
  95. */
  96. void onDisplay() override
  97. {
  98. const GraphicsContext& context(getGraphicsContext());
  99. const uint width = getWidth();
  100. const uint height = getHeight();
  101. const uint minwh = std::min(width, height);
  102. const uint bgColor = getBackgroundColor();
  103. Rectangle<double> r;
  104. // if host doesn't respect aspect-ratio but supports ui background, draw out-of-bounds color from it
  105. if (width != height && bgColor != 0)
  106. {
  107. const int red = (bgColor >> 24) & 0xff;
  108. const int green = (bgColor >> 16) & 0xff;
  109. const int blue = (bgColor >> 8) & 0xff;
  110. Color(red, green, blue).setFor(context);
  111. if (width > height)
  112. {
  113. r.setPos(height, 0);
  114. r.setSize(width-height, height);
  115. }
  116. else
  117. {
  118. r.setPos(0, width);
  119. r.setSize(width, height-width);
  120. }
  121. r.draw(context);
  122. }
  123. r.setWidth(minwh/3 - 6);
  124. r.setHeight(minwh/3 - 6);
  125. // draw left, center and right columns
  126. for (int i=0; i<3; ++i)
  127. {
  128. r.setX(3 + i*minwh/3);
  129. // top
  130. r.setY(3);
  131. if (fParamGrid[0+i])
  132. Color(0.8f, 0.5f, 0.3f).setFor(context);
  133. else
  134. Color(0.3f, 0.5f, 0.8f).setFor(context);
  135. r.draw(context);
  136. // middle
  137. r.setY(3 + minwh/3);
  138. if (fParamGrid[3+i])
  139. Color(0.8f, 0.5f, 0.3f).setFor(context);
  140. else
  141. Color(0.3f, 0.5f, 0.8f).setFor(context);
  142. r.draw(context);
  143. // bottom
  144. r.setY(3 + minwh*2/3);
  145. if (fParamGrid[6+i])
  146. Color(0.8f, 0.5f, 0.3f).setFor(context);
  147. else
  148. Color(0.3f, 0.5f, 0.8f).setFor(context);
  149. r.draw(context);
  150. }
  151. }
  152. /**
  153. Mouse press event.
  154. This UI will de/activate blocks when you click them and reports it as a parameter change to the plugin.
  155. */
  156. bool onMouse(const MouseEvent& ev) override
  157. {
  158. // Test for left-clicked + pressed first.
  159. if (ev.button != 1 || ! ev.press)
  160. return false;
  161. const uint width = getWidth();
  162. const uint height = getHeight();
  163. const uint minwh = std::min(width, height);
  164. Rectangle<double> r;
  165. r.setWidth(minwh/3 - 6);
  166. r.setHeight(minwh/3 - 6);
  167. // handle left, center and right columns
  168. for (int i=0; i<3; ++i)
  169. {
  170. r.setX(3 + i*minwh/3);
  171. // top
  172. r.setY(3);
  173. if (r.contains(ev.pos))
  174. {
  175. // parameter index that this block applies to
  176. const uint32_t index = 0+i;
  177. // invert block state
  178. fParamGrid[index] = !fParamGrid[index];
  179. // report change to host (and thus plugin)
  180. setParameterValue(index, fParamGrid[index] ? 1.0f : 0.0f);
  181. // trigger repaint
  182. repaint();
  183. break;
  184. }
  185. // middle
  186. r.setY(3 + minwh/3);
  187. if (r.contains(ev.pos))
  188. {
  189. // same as before
  190. const uint32_t index = 3+i;
  191. fParamGrid[index] = !fParamGrid[index];
  192. setParameterValue(index, fParamGrid[index] ? 1.0f : 0.0f);
  193. repaint();
  194. break;
  195. }
  196. // bottom
  197. r.setY(3 + minwh*2/3);
  198. if (r.contains(ev.pos))
  199. {
  200. // same as before
  201. const uint32_t index = 6+i;
  202. fParamGrid[index] = !fParamGrid[index];
  203. setParameterValue(index, fParamGrid[index] ? 1.0f : 0.0f);
  204. repaint();
  205. break;
  206. }
  207. }
  208. return true;
  209. }
  210. // -------------------------------------------------------------------------------------------------------
  211. private:
  212. /**
  213. Our parameters used to display the grid on/off states.
  214. They match the parameters on the plugin side, but here we define them as booleans.
  215. */
  216. bool fParamGrid[9];
  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(ExampleUIParameters)
  221. };
  222. /* ------------------------------------------------------------------------------------------------------------
  223. * UI entry point, called by DPF to create a new UI instance. */
  224. UI* createUI()
  225. {
  226. return new ExampleUIParameters();
  227. }
  228. // -----------------------------------------------------------------------------------------------------------
  229. END_NAMESPACE_DISTRHO