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