DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

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