iPlug2 - C++ Audio Plug-in Framework
Loading...
Searching...
No Matches
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
25BEGIN_IPLUG_NAMESPACE
26BEGIN_IGRAPHICS_NAMESPACE
27
30{
31public:
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
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);
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::MakeForShader(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
154private:
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
177END_IGRAPHICS_NAMESPACE
178END_IPLUG_NAMESPACE
This file contains the base IControl implementation, along with some base classes for specific types ...
The lowest level base class of an IGraphics control.
Definition: IControl.h:49
virtual void SetDirty(bool triggerAction=true, int valIdx=kNoValIdx)
Mark the control as dirty, i.e.
Definition: IControl.cpp:198
The lowest level base class of an IGraphics context.
Definition: IGraphics.h:86
virtual void * GetDrawContext()=0
Gets a void pointer to underlying drawing context, for the IGraphics backend See draw class implement...
This control allows you to draw to the UI via a shader written using the Skia shading language,...
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.
void OnMouseUp(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse up event on this control.
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
void OnResize() override
Called when IControl is constructed or resized using SetRect().
void Draw(IGraphics &g) override
Draw the control to the graphics context.
BEGIN_IPLUG_NAMESPACE T Clip(T x, T lo, T hi)
Clips the value x between lo and hi.
Used to manage mouse modifiers i.e.
Used to manage a rectangular area, independent of draw class/platform.
float W() const
float H() const