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.

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