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

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