iPlug2 - C++ Audio Plug-in Framework
IGraphicsImGui.cpp
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 #if defined IGRAPHICS_IMGUI
12 
13 #include "IPlugPlatform.h"
14 #include "IGraphicsImGui.h"
15 #include "IGraphics_select.h"
16 
17 #if defined IGRAPHICS_GL2
18  #include "imgui_impl_opengl2.h"
19 #elif defined IGRAPHICS_GL3 || defined IGRAPHICS_GLES2 || defined IGRAPHICS_GLES3
20  #include "imgui_impl_opengl3.h"
21 #else
22  #if defined OS_MAC || defined OS_IOS
23  #import <Metal/Metal.h>
24  #import <QuartzCore/QuartzCore.h>
25  #include "imgui_impl_metal.h"
26  #else
27  #error "ImGui is only supported on this platform using the OpenGL based backends"
28  #endif
29 #endif
30 
31 using namespace iplug;
32 using namespace igraphics;
33 
34 ImGuiRenderer::ImGuiRenderer(IGraphics* pGraphics, std::function<void(IGraphics*)> drawFunc, std::function<void()> setupFunc)
35 : mGraphics(pGraphics)
36 , mDrawFunc(drawFunc)
37 {
38  IMGUI_CHECKVERSION();
39  mCtx = ImGui::CreateContext();
40  ImGuiIO& io = ImGui::GetIO();
41 
42  if(setupFunc == nullptr)
43  {
44  io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
45  ImGui::StyleColorsDark();
46  }
47  else
48  setupFunc();
49 
50  // Setup back-end capabilities flags
51  io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
52  io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
53  io.BackendPlatformName = "imgui_impl_igraphics";
54 
55  io.KeyMap[ImGuiKey_Tab] = kVK_TAB;
56  io.KeyMap[ImGuiKey_LeftArrow] = kVK_LEFT;
57  io.KeyMap[ImGuiKey_RightArrow] = kVK_RIGHT;
58  io.KeyMap[ImGuiKey_UpArrow] = kVK_UP;
59  io.KeyMap[ImGuiKey_DownArrow] = kVK_DOWN;
60  io.KeyMap[ImGuiKey_PageUp] = kVK_PRIOR;
61  io.KeyMap[ImGuiKey_PageDown] = kVK_NEXT;
62  io.KeyMap[ImGuiKey_Home] = kVK_HOME;
63  io.KeyMap[ImGuiKey_End] = kVK_END;
64  io.KeyMap[ImGuiKey_Insert] = kVK_INSERT;
65  io.KeyMap[ImGuiKey_Delete] = kVK_DELETE;
66  io.KeyMap[ImGuiKey_Backspace] = kVK_BACK;
67  io.KeyMap[ImGuiKey_Space] = kVK_SPACE;
68  io.KeyMap[ImGuiKey_Enter] = kVK_RETURN;
69  io.KeyMap[ImGuiKey_Escape] = kVK_ESCAPE;
70  io.KeyMap[ImGuiKey_A] = 'A';
71  io.KeyMap[ImGuiKey_C] = 'C';
72  io.KeyMap[ImGuiKey_V] = 'V';
73  io.KeyMap[ImGuiKey_X] = 'X';
74  io.KeyMap[ImGuiKey_Y] = 'Y';
75  io.KeyMap[ImGuiKey_Z] = 'Z';
76 
77  // io.SetClipboardTextFn = [](void*, const char* str) -> void
78  // {
79  // };
80  //
81  // io.GetClipboardTextFn = [](void*) -> const char*
82  // {
83  // };
84 
85  Init();
86 }
87 
88 ImGuiRenderer::~ImGuiRenderer()
89 {
90  Destroy();
91  ImGui::DestroyContext(mCtx);
92  mCtx = nullptr;
93 }
94 
95 void ImGuiRenderer::DoFrame()
96 {
97  ImGui::SetCurrentContext(mCtx);
98  ImGuiIO &io = ImGui::GetIO();
99  io.DisplaySize.x = std::round(mGraphics->Width() * mGraphics->GetDrawScale());
100  io.DisplaySize.y = std::round(mGraphics->Height() * mGraphics->GetDrawScale());
101  float scale = (float) mGraphics->GetScreenScale();
102  io.DisplayFramebufferScale = ImVec2(scale, scale);
103  io.DeltaTime = 1.f / mGraphics->FPS();
104 
105  if (!(io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange))
106  {
107  ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
108  if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
109  {
110  mGraphics->HideMouseCursor();
111  }
112  else if (io.WantCaptureMouse)
113  {
114  switch(imgui_cursor)
115  {
116  case ImGuiMouseCursor_Arrow: mGraphics->SetMouseCursor(ECursor::ARROW); break;
117  case ImGuiMouseCursor_TextInput: mGraphics->SetMouseCursor(ECursor::IBEAM); break;
118  case ImGuiMouseCursor_ResizeAll: mGraphics->SetMouseCursor(ECursor::SIZEALL); break;
119  case ImGuiMouseCursor_ResizeNS: mGraphics->SetMouseCursor(ECursor::SIZENS); break;
120  case ImGuiMouseCursor_ResizeEW: mGraphics->SetMouseCursor(ECursor::SIZEWE); break;
121  case ImGuiMouseCursor_ResizeNESW: mGraphics->SetMouseCursor(ECursor::SIZENESW); break;
122  case ImGuiMouseCursor_ResizeNWSE: mGraphics->SetMouseCursor(ECursor::SIZENWSE); break;
123  case ImGuiMouseCursor_Hand: mGraphics->SetMouseCursor(ECursor::HAND); break;
124  }
125  mGraphics->HideMouseCursor(false);
126  }
127  }
128 
129  if (io.WantSetMousePos)
130  {
131  mGraphics->MoveMouseCursor(io.MousePos.x, io.MousePos.y);
132  }
133 
134  ImGui::SetCurrentContext(mCtx);
135  ImGui::NewFrame();
136 
137  if(mDrawFunc)
138  mDrawFunc(mGraphics);
139 
140  ImGui::Render();
141 }
142 
143 bool ImGuiRenderer::OnMouseDown(float x, float y, const IMouseMod &mod)
144 {
145  ImGui::SetCurrentContext(mCtx);
146  ImGuiIO &io = ImGui::GetIO();
147  io.MouseDown[0] = mod.L;
148  io.MouseDown[1] = mod.R;
149  return io.WantCaptureMouse;
150 }
151 
152 bool ImGuiRenderer::OnMouseUp(float x, float y, const IMouseMod &mod)
153 {
154  ImGui::SetCurrentContext(mCtx);
155  ImGuiIO &io = ImGui::GetIO();
156  io.MouseDown[0] = false;
157  io.MouseDown[1] = false;
158  return io.WantCaptureMouse;
159 }
160 
161 bool ImGuiRenderer::OnMouseWheel(float x, float y, const IMouseMod& mod, float delta)
162 {
163  ImGui::SetCurrentContext(mCtx);
164  ImGuiIO &io = ImGui::GetIO();
165  io.MouseWheel += (delta * 0.1f);
166  return io.WantCaptureMouse;
167 }
168 
169 void ImGuiRenderer::OnMouseMove(float x, float y, const IMouseMod& mod)
170 {
171  ImGui::SetCurrentContext(mCtx);
172  ImGuiIO &io = ImGui::GetIO();
173  io.MousePos = ImVec2(x * mGraphics->GetDrawScale(), y * mGraphics->GetDrawScale());
174 }
175 
176 bool ImGuiRenderer::OnKeyDown(float x, float y, const IKeyPress& keyPress)
177 {
178  ImGui::SetCurrentContext(mCtx);
179  ImGuiIO &io = ImGui::GetIO();
180 
181  if(keyPress.VK != kVK_BACK)
182  io.AddInputCharactersUTF8(keyPress.utf8);
183 
184  io.KeysDown[keyPress.VK] = true;
185 
186  io.KeyCtrl = keyPress.C;
187  io.KeyShift = keyPress.S;
188  io.KeyAlt = keyPress.A;
189 
190  return io.WantCaptureKeyboard;
191 }
192 
193 bool ImGuiRenderer::OnKeyUp(float x, float y, const IKeyPress& keyPress)
194 {
195  ImGui::SetCurrentContext(mCtx);
196  ImGuiIO &io = ImGui::GetIO();
197  io.KeysDown[keyPress.VK] = false;
198  return io.WantCaptureKeyboard;
199 }
200 
201 void ImGuiRenderer::Init()
202 {
203 #if defined IGRAPHICS_SKIA
204  #if defined IGRAPHICS_CPU // ImGui drawn via SKIA when !CPU
205  ImGui_ImplMetal_Init(MTLCreateSystemDefaultDevice());
206  #else
207  ImGuiIO& io = ImGui::GetIO();
208  int w, h;
209  unsigned char* pixels;
210  io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
211  SkImageInfo info = SkImageInfo::MakeA8(w, h);
212  SkPixmap pmap(info, pixels, info.minRowBytes());
213  SkMatrix localMatrix = SkMatrix::Scale(1.0f / w, 1.0f / h);
214  auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
215  auto fontShader = fontImage->makeShader(&localMatrix);
216  fFontPaint.setShader(fontShader);
217  fFontPaint.setColor(SK_ColorWHITE);
218  fFontPaint.setFilterQuality(kLow_SkFilterQuality);
219  io.Fonts->TexID = &fFontPaint;
220  #endif
221 #else
222  #if defined IGRAPHICS_GL2
223  ImGui_ImplOpenGL2_Init();
224  #elif defined IGRAPHICS_GL3
225  ImGui_ImplOpenGL3_Init();
226  #elif defined IGRAPHICS_GLES2 || defined IGRAPHICS_GLES3
227  const char* glsl_version = "#version 100";
228  //const char* glsl_version = "#version 300 es";
229  ImGui_ImplOpenGL3_Init(glsl_version);
230  #elif defined IGRAPHICS_METAL
231  ImGui_ImplMetal_Init(MTLCreateSystemDefaultDevice());
232  #endif
233 #endif
234 }
235 
236 void ImGuiRenderer::Destroy()
237 {
238  ImGui::SetCurrentContext(mCtx);
239 
240 #if defined IGRAPHICS_GL2
241  ImGui_ImplOpenGL2_Shutdown();
242 #elif defined IGRAPHICS_GL3 || defined IGRAPHICS_GLES2 || defined IGRAPHICS_GLES3
243  ImGui_ImplOpenGL3_Shutdown();
244 #elif defined IGRAPHICS_METAL
245  ImGui_ImplMetal_Shutdown();
246 #endif
247 }
248 
249 void ImGuiRenderer::NewFrame()
250 {
251  ImGui::SetCurrentContext(mCtx);
252 
253 #if defined IGRAPHICS_SKIA
254  ImGuiIO& io = ImGui::GetIO();
255  int w, h;
256  unsigned char* pixels;
257  io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
258  SkImageInfo info = SkImageInfo::MakeA8(w, h);
259  SkPixmap pmap(info, pixels, info.minRowBytes());
260  SkMatrix localMatrix = SkMatrix::Scale(1.0f / w, 1.0f / h);
261  auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
262  auto fontShader = fontImage->makeShader(&localMatrix);
263  fFontPaint.setShader(fontShader);
264  fFontPaint.setColor(SK_ColorWHITE);
265  fFontPaint.setFilterQuality(kLow_SkFilterQuality);
266  io.Fonts->TexID = &fFontPaint;
267  this->DoFrame();
268 #elif defined IGRAPHICS_GL2
269  ImGui_ImplOpenGL2_NewFrame();
270  this->DoFrame();
271  ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
272 #elif defined IGRAPHICS_GL3 || defined IGRAPHICS_GLES2 || defined IGRAPHICS_GLES3
273  ImGui_ImplOpenGL3_NewFrame();
274  this->DoFrame();
275 #else
276  #if defined IGRAPHICS_GL2
277  ImGui_ImplOpenGL2_NewFrame();
278  this->DoFrame();
279  ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
280  #elif defined IGRAPHICS_GL3 || defined IGRAPHICS_GLES2 || defined IGRAPHICS_GLES3
281  ImGui_ImplOpenGL3_NewFrame();
282  this->DoFrame();
283  ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
284  #else
285  //Metal rendering handled in IGRAPHICS_IMGUIVIEW
286  #endif
287 #endif
288 }
289 
290 #include "imgui.cpp"
291 #include "imgui_widgets.cpp"
292 #include "imgui_draw.cpp"
293 #include "imgui_demo.cpp"
294 #include "imgui_tables.cpp"
295 
296 #if defined IGRAPHICS_GL2
297  #include "imgui_impl_opengl2.cpp"
298 #elif defined IGRAPHICS_GL3 || defined IGRAPHICS_GLES2 || defined IGRAPHICS_GLES3
299  #include "imgui_impl_opengl3.cpp"
300 //#elif defined IGRAPHICS_METAL
301 // #include "imgui_impl_metal.mm"
302 #endif
303 
304 #endif //IGRAPHICS_IMGUI
Used to manage mouse modifiers i.e.
Used for choosing a drawing backend.
Include to get consistently named preprocessor macros for different platforms and logging functionali...
The lowest level base class of an IGraphics context.
Definition: IGraphics.h:86
void Init(const IRECT &r, YGFlexDirection direction=YGFlexDirectionRow, YGJustify justify=YGJustifyFlexStart, YGWrap wrap=YGWrapNoWrap, float padding=0.f, float margin=0.f)
Initialize the IFlexBox flex container.
Used for key press info, such as ASCII representation, virtual key (mapped to win32 codes) and modifi...
Definition: IPlugStructs.h:612