iPlug2 - C++ Audio Plug-in Framework
IShaderControl.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5 
6  See LICENSE.txt for more info.
7 
8  ==============================================================================
9 */
10 
11 #pragma once
12 
13 #ifndef IGRAPHICS_SKIA
14 #error This IControl only works with the Skia graphics backend
15 #endif
16 
22 #include "IControl.h"
23 #include "SkRuntimeEffect.h"
24 
25 BEGIN_IPLUG_NAMESPACE
26 BEGIN_IGRAPHICS_NAMESPACE
27 
29 class IShaderControl : public IControl
30 {
31 public:
32  enum EUniform
33  {
34  kTime,
35  kWidth,
36  kHeight,
37  kX,
38  kY,
39  kL,
40  kR,
41  kNumUniforms
42  };
43 
44  IShaderControl(const IRECT& bounds, const char* shaderStr = nullptr)
45  : IControl(bounds)
46  {
47  mText.mAlign = EAlign::Near;
48  mText.mVAlign = EVAlign::Top;
49 
50 // mTimer = std::unique_ptr<Timer>(Timer::Create([&](Timer& t) {
51 //
52 // SetDirty(false);
53 // }, 20));
54 
55 // SetActionFunction([&](IControl* pCaller) {
56 // SetAnimation([&](IControl* pCaller) {
57 // float p = pCaller->GetAnimationProgress();
58 // mUniforms[kTime] = p;
59 //
60 // if (p > 1.) {
61 // pCaller->OnEndAnimation();
62 // }
63 //
64 // }, 10000);
65 // });
66 
67  WDL_String err;
68 
69  SetShaderStr(shaderStr ? shaderStr :
70  R"(
71  uniform float uTime;
72  uniform float2 uDim;
73  uniform float2 uMouse;
74  uniform float2 uMouseBut;
75 
76  half4 main(float2 fragCoord) {
77  float2 pos = uMouse.xy/uDim.xy;
78  return half4(pos.x, pos.y, 1, 1);
79  }
80  )", err);
81 
82  if(err.GetLength())
83  DBGMSG("%s\n", err.Get());
84  }
85 
86  void Draw(IGraphics& g) override
87  {
88  if(mRTEffect)
89  DrawShader(g, GetShaderBounds());
90 
91 // WDL_String str;
92 // str.SetFormatted(32, "%i:%i", (int) mUniforms[kX], (int) mUniforms[kY]);
93 // g.DrawText(mText, str.Get(), mRECT);
94  }
95 
96  void OnMouseDown(float x, float y, const IMouseMod& mod) override
97  {
98  IRECT shaderBounds = GetShaderBounds();
99 
100  mUniforms[kX] = Clip(0.f, x - shaderBounds.L, shaderBounds.W());
101  mUniforms[kY] = Clip(0.f, y - shaderBounds.T, shaderBounds.H());
102  mUniforms[kL] = (float) mod.L ? 1.f : 0.f;
103  mUniforms[kR] = (float) mod.R ? 1.f : 0.f;
104  SetDirty(true);
105  }
106 
107  void OnMouseUp(float x, float y, const IMouseMod &mod) override
108  {
109  IRECT shaderBounds = GetShaderBounds();
110 
111  mUniforms[kX] = Clip(0.f, x - shaderBounds.L, shaderBounds.W());
112  mUniforms[kY] = Clip(0.f, y - shaderBounds.T, shaderBounds.H());
113  mUniforms[kL] = 0.f;
114  mUniforms[kR] = 0.f;
115  SetDirty(false);
116  }
117 
118  void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod &mod) override
119  {
120  IRECT shaderBounds = GetShaderBounds();
121  mUniforms[kX] = Clip(0.f, x - shaderBounds.L, shaderBounds.W());
122  mUniforms[kY] = Clip(0.f, y - shaderBounds.T, shaderBounds.H());
123  SetDirty(false);
124  }
125 
126  void OnResize() override
127  {
128  mUniforms[kWidth] = GetShaderBounds().W();
129  mUniforms[kHeight] = GetShaderBounds().H();
130  SetDirty(false);
131  }
132 
133  bool SetShaderStr(const char* str, WDL_String& error)
134  {
135  mShaderStr = SkString(str);
136 
137  auto [effect, errorText] = SkRuntimeEffect::Make(mShaderStr);
138 
139  if (!effect)
140  {
141  error.Set(errorText.c_str());
142  return false;
143  }
144 
145  mRTEffect = effect;
146 
147  auto inputs = SkData::MakeWithoutCopy(mUniforms.data(), mRTEffect->uniformSize());
148  auto shader = mRTEffect->makeShader(std::move(inputs), nullptr, 0, nullptr, false);
149  mPaint.setShader(std::move(shader));
150 
151  return true;
152  }
153 
154 private:
155  /* Override this method to only draw the shader in a sub region of the control's mRECT */
156  virtual IRECT GetShaderBounds() const
157  {
158  return mRECT;
159  }
160 
161  void DrawShader(IGraphics& g, const IRECT& r)
162  {
163  SkCanvas* canvas = static_cast<SkCanvas*>(g.GetDrawContext());
164  canvas->save();
165  canvas->translate(r.L, r.T);
166  canvas->drawRect({ 0, 0, r.W(), r.H() }, mPaint);
167  canvas->restore();
168  }
169 
170 // std::unique_ptr<Timer> mTimer;
171  SkPaint mPaint;
172  SkString mShaderStr;
173  sk_sp<SkRuntimeEffect> mRTEffect;
174  std::array<float, kNumUniforms> mUniforms {0.f};
175 };
176 
177 END_IGRAPHICS_NAMESPACE
178 END_IPLUG_NAMESPACE
void OnMouseUp(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse up event on this control.
This control allows you to draw to the UI via a shader written using the Skia shading language...
The lowest level base class of an IGraphics control.
Definition: IControl.h:42
Used to manage a rectangular area, independent of draw class/platform.
Used to manage mouse modifiers i.e.
This file contains the base IControl implementation, along with some base classes for specific types ...
void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod &mod) override
Implement this method to respond to a mouse drag event on this control.
float H() const
float W() const
IControl(const IRECT &bounds, int paramIdx=kNoParameter, IActionFunction actionFunc=nullptr)
Constructor.
Definition: IControl.cpp:81
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
The lowest level base class of an IGraphics context.
Definition: IGraphics.h:86
BEGIN_IPLUG_NAMESPACE T Clip(T x, T lo, T hi)
Clips the value x between lo and hi.
void Draw(IGraphics &g) override
Draw the control to the graphics context.
virtual void * GetDrawContext()=0
Gets a void pointer to underlying drawing context, for the IGraphics backend See draw class implement...
void OnResize() override
Called when IControl is constructed or resized using SetRect().
float L
Left side of the rectangle (X)
float T
Top of the rectangle (Y)
virtual void SetDirty(bool triggerAction=true, int valIdx=kNoValIdx)
Mark the control as dirty, i.e.
Definition: IControl.cpp:196