SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLGLImGui.cpp
Go to the documentation of this file.
1 /**
2  * \file gl/SLGLImGui.cpp
3  * \details Wrapper Class around the external ImGui GUI-framework
4  * See also: https://github.com/ocornut/imgui
5  * \date October 2015
6  * \authors Marcus Hudritsch
7  * \copyright http://opensource.org/licenses/GPL-3.0
8  * \remarks Please use clangformat to format the code. See more code style on
9  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
10 */
11 
12 #include <SLGLState.h>
13 #include <SLSceneView.h>
14 #include <SLGLImGui.h>
15 #include <SLScene.h>
16 #include <SLFileStorage.h>
17 #include <GlobalTimer.h>
18 #include <cstddef>
19 
20 //-----------------------------------------------------------------------------
23 //-----------------------------------------------------------------------------
24 SLGLImGui::SLGLImGui(cbOnImGuiBuild buildCB,
25  cbOnImGuiLoadConfig loadConfigCB,
26  cbOnImGuiSaveConfig saveConfigCB,
27  int dpi,
28  SLIOBuffer fontDataProp,
29  SLIOBuffer fontDataFixed)
30 {
31  _build = buildCB;
32  _saveConfig = saveConfigCB;
33  _fontTexture = 0;
34  _progHandle = 0;
35  _vertHandle = 0;
36  _fragHandle = 0;
37  _attribLocTex = 0;
40  _attribLocUV = 0;
41  _attribLocColor = 0;
42  _vboHandle = 0;
43  _vaoHandle = 0;
44  _elementsHandle = 0;
45  _fontPropDots = 13.0f;
46  _fontFixedDots = 16.0f;
47  _mouseWheel = 0.0f;
48  _mousePressed[0] = false;
49  _mousePressed[1] = false;
50  _mousePressed[2] = false;
51  _fontDataProp = fontDataProp;
52  _fontDataFixed = fontDataFixed;
53 
54  // create imgui context
55  ImGui::CreateContext();
56 
57  // set default style to get a good initial configuration
58  ImGui::StyleColorsDark();
59  ImGuiIO& io = ImGui::GetIO();
60  io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
61  // io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
62 
63  // load config
64  if (loadConfigCB)
65  loadConfigCB(dpi);
66 
67  // load GUI fonts depending on the resolution
69 
70  // Scale for proportional and fixed size fonts
71  SLfloat dpiScaleProp = (float)dpi / 120.0f;
72  SLfloat dpiScaleFixed = (float)dpi / 142.0f;
73 
74  // Default settings for the first time
75  SLGLImGui::fontPropDots = std::max(16.0f * dpiScaleProp, 16.0f);
76  SLGLImGui::fontFixedDots = std::max(13.0f * dpiScaleFixed, 13.0f);
77 }
78 //-----------------------------------------------------------------------------
80 {
81  if (_saveConfig)
82  _saveConfig();
83 
84  // Destroy imgui context after your last imgui call
85  ImGui::DestroyContext();
86 }
87 //-----------------------------------------------------------------------------
88 //! Initializes OpenGL handles to zero and sets the ImGui key map
89 void SLGLImGui::init(const string& configPath)
90 {
91  _fontTexture = 0;
92  _progHandle = 0;
93  _vertHandle = 0;
94  _fragHandle = 0;
95  _attribLocTex = 0;
98  _attribLocUV = 0;
99  _attribLocColor = 0;
100  _vboHandle = 0;
101  _vaoHandle = 0;
102  _elementsHandle = 0;
103  _fontPropDots = 13.0f;
104  _fontFixedDots = 16.0f;
105  _mouseWheel = 0.0f;
106  _mousePressed[0] = false;
107  _mousePressed[1] = false;
108  _mousePressed[2] = false;
109  _configPath = configPath;
110 
111  ImGuiIO& io = ImGui::GetIO();
112  io.IniSavingRate = 1.0f;
113  io.IniFilename = NULL; // Disable ini config saving because we handle that ourselves
114  io.KeyMap[ImGuiKey_Tab] = K_tab;
115  io.KeyMap[ImGuiKey_LeftArrow] = K_left;
116  io.KeyMap[ImGuiKey_RightArrow] = K_right;
117  io.KeyMap[ImGuiKey_UpArrow] = K_up;
118  io.KeyMap[ImGuiKey_DownArrow] = K_down;
119  io.KeyMap[ImGuiKey_PageUp] = K_pageUp;
120  io.KeyMap[ImGuiKey_PageDown] = K_pageUp;
121  io.KeyMap[ImGuiKey_Home] = K_home;
122  io.KeyMap[ImGuiKey_End] = K_end;
123  io.KeyMap[ImGuiKey_Delete] = K_delete;
124  io.KeyMap[ImGuiKey_Backspace] = K_backspace;
125  io.KeyMap[ImGuiKey_Enter] = K_enter;
126  io.KeyMap[ImGuiKey_Escape] = K_esc;
127  io.KeyMap[ImGuiKey_A] = 'A';
128  io.KeyMap[ImGuiKey_C] = 'C';
129  io.KeyMap[ImGuiKey_V] = 'V';
130  io.KeyMap[ImGuiKey_X] = 'X';
131  io.KeyMap[ImGuiKey_Y] = 'Y';
132  io.KeyMap[ImGuiKey_Z] = 'Z';
133 
134  // The screen size is set again in onResize
135  io.DisplaySize = ImVec2(0, 0);
136  io.DisplayFramebufferScale = ImVec2(1, 1);
137 
138 #if defined(SL_OS_ANDROID) || defined(SL_OS_MACIOS) || defined(SL_EMSCRIPTEN)
139  io.MouseDrawCursor = false;
140 #else
141  io.MouseDrawCursor = true;
142 #endif
143 
144  // Change default style to show the widget border
145  ImGuiStyle& style = ImGui::GetStyle();
146  style.FrameBorderSize = 1;
147 
148  // Load ImGui config from imgui.ini
149  SLstring iniFile = configPath + "imgui.ini";
150  if (SLFileStorage::exists(iniFile, IOK_config))
151  {
152  SLstring iniContents = SLFileStorage::readIntoString(iniFile,
153  IOK_config);
154  ImGui::LoadIniSettingsFromMemory(iniContents.c_str(),
155  iniContents.size());
156  }
157 }
158 //-----------------------------------------------------------------------------
159 //! Loads the proportional and fixed size font depending on the passed DPI
160 void SLGLImGui::loadFonts(SLfloat fontPropDotsToLoad,
161  SLfloat fontFixedDotsToLoad)
162 {
163  _fontPropDots = fontPropDotsToLoad;
164  _fontFixedDots = fontFixedDotsToLoad;
165 
166  ImGuiIO& io = ImGui::GetIO();
167  io.Fonts->Clear();
168 
169  // Create copies of the font data because ImGUI takes ownerhip of the data.
170  SLIOBuffer fontDataProp = _fontDataProp.copy();
171  SLIOBuffer fontDataFixed = _fontDataFixed.copy();
172 
173  // Load proportional font for menu and text displays
174  io.Fonts->AddFontFromMemoryTTF(fontDataProp.data,
175  static_cast<int>(fontDataProp.size),
176  fontPropDotsToLoad);
177 
178  // Load fixed size font for statistics windows
179  io.Fonts->AddFontFromMemoryTTF(fontDataFixed.data,
180  static_cast<int>(fontDataFixed.size),
181  fontFixedDotsToLoad);
182 
185 }
186 //-----------------------------------------------------------------------------
187 //! Creates all OpenGL objects for drawing the imGui
189 {
190  // Backup GL state
191  GLint last_texture = -1, last_array_buffer = -1, last_vertex_array = -1;
192  glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
193  glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
194  glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
195 
196  // Build version string as the first statement
197  SLGLState* state = SLGLState::instance();
198  SLstring verGLSL = state->glSLVersionNO();
199  SLstring vertex_shader = "#version " + verGLSL;
200  if (state->glIsES3()) vertex_shader += " es";
201  vertex_shader +=
202  "\n"
203  "#ifdef GL_ES\n"
204  "precision highp float;\n"
205  "#endif\n"
206  "\n"
207  "uniform mat4 ProjMtx;\n"
208  "in vec2 Position;\n"
209  "in vec2 UV;\n"
210  "in vec4 Color;\n"
211  "out vec2 Frag_UV;\n"
212  "out vec4 Frag_Color;\n"
213  "void main()\n"
214  "{\n"
215  " Frag_UV = UV;\n"
216  " Frag_Color = Color;\n"
217  " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
218  "}\n";
219 
220  SLstring fragment_shader = "#version " + verGLSL;
221  if (state->glIsES3()) fragment_shader += " es";
222  fragment_shader +=
223  "\n"
224  "#ifdef GL_ES\n"
225  "precision highp float;\n"
226  "#endif\n"
227  "\n"
228  "uniform sampler2D Texture;\n"
229  "in vec2 Frag_UV;\n"
230  "in vec4 Frag_Color;\n"
231  "out vec4 Out_Color;\n"
232  "void main()\n"
233  "{\n"
234  " Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
235  "}\n";
236 
237  _vertHandle = (SLint)glCreateShader(GL_VERTEX_SHADER);
238  _fragHandle = (SLint)glCreateShader(GL_FRAGMENT_SHADER);
239  const char* srcVert = vertex_shader.c_str();
240  const char* srcFrag = fragment_shader.c_str();
241  glShaderSource((SLuint)_vertHandle, 1, &srcVert, nullptr);
242  glShaderSource((SLuint)_fragHandle, 1, &srcFrag, nullptr);
243  glCompileShader((SLuint)_vertHandle);
245  glCompileShader((SLuint)_fragHandle);
247 
248  _progHandle = (SLint)glCreateProgram();
249  glAttachShader((SLuint)_progHandle, (SLuint)_vertHandle);
250  glAttachShader((SLuint)_progHandle, (SLuint)_fragHandle);
251  glLinkProgram((SLuint)_progHandle);
252  GET_GL_ERROR;
253 
254  _attribLocTex = glGetUniformLocation((SLuint)_progHandle, "Texture");
255  _attribLocProjMtx = glGetUniformLocation((SLuint)_progHandle, "ProjMtx");
256  _attribLocPosition = glGetAttribLocation((SLuint)_progHandle, "Position");
257  _attribLocUV = glGetAttribLocation((SLuint)_progHandle, "UV");
258  _attribLocColor = glGetAttribLocation((SLuint)_progHandle, "Color");
259  GET_GL_ERROR;
260 
261  glGenBuffers(1, &_vboHandle);
262  glGenBuffers(1, &_elementsHandle);
263 
264  glGenVertexArrays(1, &_vaoHandle);
265  glBindVertexArray(_vaoHandle);
266  glBindBuffer(GL_ARRAY_BUFFER, _vboHandle);
267  glEnableVertexAttribArray((SLuint)_attribLocPosition);
268  glEnableVertexAttribArray((SLuint)_attribLocUV);
269  glEnableVertexAttribArray((SLuint)_attribLocColor);
270 
271  GET_GL_ERROR;
272 
273  glVertexAttribPointer((SLuint)_attribLocPosition,
274  2,
275  GL_FLOAT,
276  GL_FALSE,
277  sizeof(ImDrawVert),
278  (GLvoid*)offsetof(ImDrawVert, pos));
279  glVertexAttribPointer((SLuint)_attribLocUV,
280  2,
281  GL_FLOAT,
282  GL_FALSE,
283  sizeof(ImDrawVert),
284  (GLvoid*)offsetof(ImDrawVert, uv));
285  glVertexAttribPointer((SLuint)_attribLocColor,
286  4,
287  GL_UNSIGNED_BYTE,
288  GL_TRUE,
289  sizeof(ImDrawVert),
290  (GLvoid*)offsetof(ImDrawVert, col));
291 
292  GET_GL_ERROR;
293 
294  // Build texture atlas
295  ImGuiIO& io = ImGui::GetIO();
296  SLuchar* pixels = nullptr;
297  int width = -1, height = -1;
298 
299  // Load as RGBA 32-bits (75% of the memory is wasted, but default font is
300  // so small) because it is more likely to be compatible with user's
301  // existing shaders. If your ImTextureId represent a higher-level concept
302  // than just a GL texture id, consider calling GetTexDataAsAlpha8()
303  // instead to save on GPU memory.
304  io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
305 
306  // Upload texture to graphics system
307  glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
308  glGenTextures(1, &_fontTexture);
309  glBindTexture(GL_TEXTURE_2D, _fontTexture);
310  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
311  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
312  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
313 
314  GET_GL_ERROR;
315 
316  // Store our identifier
317  io.Fonts->TexID = (void*)(intptr_t)_fontTexture;
318 
319  // Restore state
320  glBindTexture(GL_TEXTURE_2D, (SLuint)last_texture);
321 
322  // Restore modified GL state
323  glBindTexture(GL_TEXTURE_2D, (SLuint)last_texture);
324  glBindBuffer(GL_ARRAY_BUFFER, (SLuint)last_array_buffer);
325  glBindVertexArray((SLuint)last_vertex_array);
326 
327  GET_GL_ERROR;
328 }
329 //-----------------------------------------------------------------------------
330 //! Deletes all OpenGL objects for drawing the imGui
332 {
333 #ifdef SL_EMSCRIPTEN
334  // The WebGL context is apparently already destroyed when we call this function
335  return;
336 #endif
337 
338  if (_vaoHandle)
339  glDeleteVertexArrays(1, &_vaoHandle);
340  _vaoHandle = 0;
341 
342  if (_vboHandle)
343  glDeleteBuffers(1, &_vboHandle);
344  _vboHandle = 0;
345 
346  if (_elementsHandle)
347  glDeleteBuffers(1, &_elementsHandle);
348  _elementsHandle = 0;
349 
350  if (_progHandle && _vertHandle)
351  glDetachShader((SLuint)_progHandle,
353 
354  if (_vertHandle)
355  glDeleteShader((SLuint)_vertHandle);
356  _vertHandle = 0;
357 
358  if (_progHandle && _fragHandle)
359  glDetachShader((SLuint)_progHandle,
361 
362  if (_fragHandle)
363  glDeleteShader((SLuint)_fragHandle);
364  _fragHandle = 0;
365 
366  if (_progHandle)
367  glDeleteProgram((SLuint)_progHandle);
368  _progHandle = 0;
369 
370  if (_fontTexture)
371  {
372  glDeleteTextures(1, &_fontTexture);
373  ImGui::GetIO().Fonts->TexID = nullptr;
374  _fontTexture = 0;
375  }
376  GET_GL_ERROR;
377 }
378 //-----------------------------------------------------------------------------
379 //! Prints the compile errors in case of a GLSL compile failure
380 void SLGLImGui::printCompileErrors(SLint shaderHandle, const SLchar* src)
381 {
382  // Check compiler log
383  SLint compileSuccess = 0;
384  glGetShaderiv((SLuint)shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
385  if (compileSuccess == GL_FALSE)
386  {
387  GLchar log[512];
388  glGetShaderInfoLog((SLuint)shaderHandle,
389  sizeof(log),
390  nullptr,
391  &log[0]);
392  SL_LOG("*** COMPILER ERROR ***");
393  SL_LOG("%s\n---", log);
394  SL_LOG("%s", src);
395  }
396 }
397 //-----------------------------------------------------------------------------
398 //! Inits a new frame for the ImGui system
400 {
401  // If no _build function is provided there is no ImGui
402  // if (!_build) return;
403 
407 
408  if (!_fontTexture)
410 
411  ImGuiIO& io = ImGui::GetIO();
412 
413  // Setup time step
414  SLfloat nowSec = GlobalTimer::timeS();
415  io.DeltaTime = _timeSec > 0.0 ? nowSec - _timeSec : 1.0f / 60.0f;
416  if (io.DeltaTime < 0) io.DeltaTime = 1.0f / 60.0f;
417  _timeSec = nowSec;
418 
419  io.MouseWheel = _mouseWheel;
420  _mouseWheel = 0.0f;
421 
422  // Start the frame
423  ImGui::NewFrame();
424 
425  // Save ImGui config to imgui.ini
426  if (ImGui::GetIO().WantSaveIniSettings)
427  {
428  SLstring iniFile = _configPath + "imgui.ini";
429  size_t iniContentsSize;
430  const char* rawIniContents = ImGui::SaveIniSettingsToMemory(&iniContentsSize);
431  SLstring iniContents(rawIniContents, rawIniContents + iniContentsSize);
432  SLFileStorage::writeString(iniFile, IOK_config, iniContents);
433  ImGui::GetIO().WantSaveIniSettings = false;
434  }
435 
436  // Call the _build function. The whole UI is constructed here
437  // This function is provided by the top-level project.
438  // For the SLProject demo apps this _build function is implemented in the
439  // class SLDemoGui.
440  if (_build)
441  _build(s, sv);
442 }
443 //-----------------------------------------------------------------------------
444 //! Callback if window got resized
445 void SLGLImGui::onResize(const SLRecti& viewportRect)
446 {
447  ImGuiIO& io = ImGui::GetIO();
448  io.DisplaySize = ImVec2((SLfloat)viewportRect.width, (SLfloat)viewportRect.height);
449  io.DisplayFramebufferScale = ImVec2(1, 1);
450 }
451 //-----------------------------------------------------------------------------
452 //! Callback for main rendering for the ImGui GUI system
453 void SLGLImGui::onPaint(const SLRecti& viewportRect)
454 {
455  ImGui::Render();
456  ImDrawData* draw_data = ImGui::GetDrawData();
457 
458  ImGuiIO& io = ImGui::GetIO();
459 
460  // Avoid rendering when minimized, scale coordinates for retina displays
461  // (screen coordinates != framebuffer coordinates)
462  int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x);
463  int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y);
464  if (fb_width == 0 || fb_height == 0) return;
465  draw_data->ScaleClipRects(io.DisplayFramebufferScale);
466 
467  // Backup GL state
468  GLint last_active_texture = -1;
469  glGetIntegerv(GL_ACTIVE_TEXTURE, &last_active_texture);
470  glActiveTexture(GL_TEXTURE0);
471 
472  GLint last_program = -1;
473  glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
474  GLint last_texture = -1;
475  glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
476  GLint last_array_buffer = -1;
477  glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
478  GLint last_element_array_buffer = -1;
479  glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
480  GLint last_vertex_array = -1;
481  glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
482  GLint last_blend_src_rgb = -1;
483  glGetIntegerv(GL_BLEND_SRC_RGB, &last_blend_src_rgb);
484  GLint last_blend_dst_rgb = -1;
485  glGetIntegerv(GL_BLEND_DST_RGB, &last_blend_dst_rgb);
486  GLint last_blend_src_alpha = -1;
487  glGetIntegerv(GL_BLEND_SRC_ALPHA, &last_blend_src_alpha);
488  GLint last_blend_dst_alpha = -1;
489  glGetIntegerv(GL_BLEND_DST_ALPHA, &last_blend_dst_alpha);
490  GLint last_blend_equation_rgb = -1;
491  glGetIntegerv(GL_BLEND_EQUATION_RGB, &last_blend_equation_rgb);
492  GLint last_blend_equation_alpha = -1;
493  glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &last_blend_equation_alpha);
494  GLint last_viewport[4];
495  glGetIntegerv(GL_VIEWPORT, last_viewport);
496  GLint last_scissor_box[4];
497  glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
498 
499  GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
500  GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
501  GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
502  GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
503 
504  // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
505  glEnable(GL_BLEND);
506  glBlendEquation(GL_FUNC_ADD);
507  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
508  glDisable(GL_CULL_FACE);
509  glDisable(GL_DEPTH_TEST);
510  glEnable(GL_SCISSOR_TEST);
511 
512  // Setup viewport
513  if (viewportRect.isEmpty())
514  glViewport(0,
515  0,
516  (GLsizei)fb_width,
517  (GLsizei)fb_height);
518  else
519  glViewport((GLsizei)(viewportRect.x * io.DisplayFramebufferScale.x),
520  (GLsizei)(viewportRect.y * io.DisplayFramebufferScale.y),
521  (GLsizei)(viewportRect.width * io.DisplayFramebufferScale.x),
522  (GLsizei)(viewportRect.height * io.DisplayFramebufferScale.y));
523 
524  // Setup orthographic projection matrix
525  // clang-format off
526  const float ortho_projection[4][4] =
527  {
528  {2.0f / io.DisplaySize.x, 0.0f, 0.0f, 0.0f},
529  {0.0f, 2.0f / -io.DisplaySize.y, 0.0f, 0.0f},
530  {0.0f, 0.0f, -1.0f, 0.0f},
531  {-1.0f, 1.0f, 0.0f, 1.0f},
532  };
533  // clang-format on
534 
535  glUseProgram((SLuint)_progHandle);
536  glUniform1i(_attribLocTex, 0);
537  glUniformMatrix4fv(_attribLocProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
538  glBindVertexArray((SLuint)_vaoHandle);
539 
540  for (int n = 0; n < draw_data->CmdListsCount; n++)
541  {
542  const ImDrawList* cmd_list = draw_data->CmdLists[n];
543  const ImDrawIdx* idx_buffer_offset = nullptr;
544 
545  glBindBuffer(GL_ARRAY_BUFFER, _vboHandle);
546  glBufferData(GL_ARRAY_BUFFER,
547  (GLsizeiptr)cmd_list->VtxBuffer.Size * (GLsizeiptr)sizeof(ImDrawVert),
548  (const GLvoid*)cmd_list->VtxBuffer.Data,
549  GL_STREAM_DRAW);
550 
551  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _elementsHandle);
552  glBufferData(GL_ELEMENT_ARRAY_BUFFER,
553  (GLsizeiptr)cmd_list->IdxBuffer.Size * (GLsizeiptr)sizeof(ImDrawIdx),
554  (const GLvoid*)cmd_list->IdxBuffer.Data,
555  GL_STREAM_DRAW);
556 
557  for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
558  {
559  const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
560  if (pcmd->UserCallback)
561  {
562  pcmd->UserCallback(cmd_list, pcmd);
563  }
564  else
565  {
566  glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
567 
568  if (viewportRect.isEmpty())
569  glScissor((int)pcmd->ClipRect.x,
570  (int)(fb_height - pcmd->ClipRect.w),
571  (int)(pcmd->ClipRect.z - pcmd->ClipRect.x),
572  (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
573  else
574  glScissor((GLsizei)(viewportRect.x * io.DisplayFramebufferScale.x),
575  (GLsizei)(viewportRect.y * io.DisplayFramebufferScale.y),
576  (GLsizei)(viewportRect.width * io.DisplayFramebufferScale.x),
577  (GLsizei)(viewportRect.height * io.DisplayFramebufferScale.y));
578 
579  glDrawElements(GL_TRIANGLES,
580  (GLsizei)pcmd->ElemCount,
581  sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT,
582  idx_buffer_offset);
583  }
584  idx_buffer_offset += pcmd->ElemCount;
585  }
586  }
587 
588  // Restore modified GL state
589  glUseProgram((SLuint)last_program);
590  glBindTexture(GL_TEXTURE_2D, (SLuint)last_texture);
591  glActiveTexture((SLuint)last_active_texture);
592  glBindVertexArray((SLuint)last_vertex_array);
593  glBindBuffer(GL_ARRAY_BUFFER, (SLuint)last_array_buffer);
594  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (SLuint)last_element_array_buffer);
595  glBlendEquationSeparate((SLuint)last_blend_equation_rgb,
596  (SLuint)last_blend_equation_alpha);
597  glBlendFuncSeparate((SLuint)last_blend_src_rgb,
598  (SLuint)last_blend_dst_rgb,
599  (SLuint)last_blend_src_alpha,
600  (SLuint)last_blend_dst_alpha);
601  if (last_enable_blend)
602  glEnable(GL_BLEND);
603  else
604  glDisable(GL_BLEND);
605 
606  if (last_enable_cull_face)
607  glEnable(GL_CULL_FACE);
608  else
609  glDisable(GL_CULL_FACE);
610 
611  if (last_enable_depth_test)
612  glEnable(GL_DEPTH_TEST);
613  else
614  glDisable(GL_DEPTH_TEST);
615 
616  if (last_enable_scissor_test)
617  glEnable(GL_SCISSOR_TEST);
618  else
619  glDisable(GL_SCISSOR_TEST);
620 
621  glViewport(last_viewport[0],
622  last_viewport[1],
623  (GLsizei)last_viewport[2],
624  (GLsizei)last_viewport[3]);
625 
626  glScissor(last_scissor_box[0],
627  last_scissor_box[1],
628  (GLsizei)last_scissor_box[2],
629  (GLsizei)last_scissor_box[3]);
630 }
631 //-----------------------------------------------------------------------------
632 //! Callback on mouse button down event
634 {
635  ImGuiIO& io = ImGui::GetIO();
636  io.MousePos = ImVec2((SLfloat)x, (SLfloat)y);
637  if (button == MB_left) io.MouseDown[0] = true;
638  if (button == MB_right) io.MouseDown[1] = true;
639  if (button == MB_middle) io.MouseDown[2] = true;
640  // SL_LOG("D");
641 }
642 //-----------------------------------------------------------------------------
643 //! Callback on mouse button up event
645 {
646  ImGuiIO& io = ImGui::GetIO();
647  io.MousePos = ImVec2((SLfloat)x, (SLfloat)y);
648  if (button == MB_left) io.MouseDown[0] = false;
649  if (button == MB_right) io.MouseDown[1] = false;
650  if (button == MB_middle) io.MouseDown[2] = false;
651  // SL_LOG("U\n");
652 }
653 //-----------------------------------------------------------------------------
654 //! Updates the mouse cursor position
656 {
657  ImGui::GetIO().MousePos = ImVec2((SLfloat)xPos, (SLfloat)yPos);
658  // SL_LOG("M");
659 }
660 //-----------------------------------------------------------------------------
661 //! Callback for the mouse scroll movement
663 {
664  // Use fractional mouse wheel, 1.0 unit 5 lines.
665  _mouseWheel += yoffset;
666 }
667 //-----------------------------------------------------------------------------
668 //! Callback on key press event
670 {
671  ImGuiIO& io = ImGui::GetIO();
672  io.KeysDown[key] = true;
673  io.KeyCtrl = mod & K_ctrl ? true : false;
674  io.KeyShift = mod & K_shift ? true : false;
675  io.KeyAlt = mod & K_alt ? true : false;
676 }
677 //-----------------------------------------------------------------------------
678 //! Callback on key release event
680 {
681  ImGuiIO& io = ImGui::GetIO();
682  io.KeysDown[key] = false;
683  io.KeyCtrl = mod & K_ctrl ? true : false;
684  io.KeyShift = mod & K_shift ? true : false;
685  io.KeyAlt = mod & K_alt ? true : false;
686 }
687 //-----------------------------------------------------------------------------
688 //! Callback on character input
690 {
691  ImGuiIO& io = ImGui::GetIO();
692  if (c > 0 && c < 0x10000)
693  io.AddInputCharacter((unsigned short)c);
694 }
695 //-----------------------------------------------------------------------------
696 //! Callback on closing the application
698 {
700 }
701 //-----------------------------------------------------------------------------
702 //! Renders an extra frame with the current mouse position
704  SLSceneView* sv,
705  SLint mouseX,
706  SLint mouseY)
707 {
708  // If ImGui _build function exists render the ImGui
709  if (_build)
710  {
711  ImGui::GetIO().MousePos = ImVec2((SLfloat)mouseX, (SLfloat)mouseY);
712  onInitNewFrame(s, sv);
713  ImGui::Render();
714  onPaint(sv->viewportRect());
715  }
716 }
717 //-----------------------------------------------------------------------------
static SLint mouseX
Last mouse position x in pixels.
static SLint mouseY
Last mouse position y in pixels.
static SLint dpi
Dot per inch resolution of screen.
Definition: AppGLFW.cpp:41
float SLfloat
Definition: SL.h:173
#define SL_LOG(...)
Definition: SL.h:233
unsigned int SLuint
Definition: SL.h:171
char SLchar
Definition: SL.h:162
unsigned char SLuchar
Definition: SL.h:163
string SLstring
Definition: SL.h:158
int SLint
Definition: SL.h:170
SLMouseButton
Mouse button codes.
Definition: SLEnums.h:98
@ MB_left
Definition: SLEnums.h:100
@ MB_right
Definition: SLEnums.h:102
@ MB_middle
Definition: SLEnums.h:101
SLKey
Keyboard key codes enumeration.
Definition: SLEnums.h:16
@ K_down
Definition: SLEnums.h:25
@ K_delete
Definition: SLEnums.h:23
@ K_up
Definition: SLEnums.h:24
@ K_enter
Definition: SLEnums.h:20
@ K_esc
Definition: SLEnums.h:21
@ K_tab
Definition: SLEnums.h:19
@ K_shift
Definition: SLEnums.h:62
@ K_end
Definition: SLEnums.h:29
@ K_right
Definition: SLEnums.h:26
@ K_pageUp
Definition: SLEnums.h:31
@ K_ctrl
Definition: SLEnums.h:63
@ K_alt
Definition: SLEnums.h:64
@ K_left
Definition: SLEnums.h:27
@ K_backspace
Definition: SLEnums.h:22
@ K_home
Definition: SLEnums.h:28
@ IOK_config
Definition: SLFileStorage.h:44
void(SL_STDCALL * cbOnImGuiSaveConfig)()
Callback function typedef for ImGui save config function.
Definition: SLGLImGui.h:34
void(SL_STDCALL * cbOnImGuiLoadConfig)(int dpi)
Callback function typedef for ImGui load config function.
Definition: SLGLImGui.h:31
Singleton class for global render state.
#define GET_GL_ERROR
Definition: SLGLState.h:56
static float timeS()
Definition: GlobalTimer.cpp:20
void loadFonts(SLfloat fontPropDots, SLfloat fontFixedDots)
Loads the proportional and fixed size font depending on the passed DPI.
Definition: SLGLImGui.cpp:160
void printCompileErrors(SLint shaderHandle, const SLchar *src)
Prints the compile errors in case of a GLSL compile failure.
Definition: SLGLImGui.cpp:380
void onInitNewFrame(SLScene *s, SLSceneView *sv) override
Inits a new frame for the ImGui system.
Definition: SLGLImGui.cpp:399
void onMouseDown(SLMouseButton button, SLint x, SLint y) override
Callback on mouse button down event.
Definition: SLGLImGui.cpp:633
static SLfloat fontFixedDots
Default font size of fixed size font.
Definition: SLGLImGui.h:94
void onPaint(const SLRecti &viewport) override
Callback for main rendering for the ImGui GUI system.
Definition: SLGLImGui.cpp:453
SLint _attribLocProjMtx
OpenGL attribute location for ???
Definition: SLGLImGui.h:117
static SLfloat fontPropDots
Default font size of proportional font.
Definition: SLGLImGui.h:93
void init(const string &configPath) override
Initializes OpenGL handles to zero and sets the ImGui key map.
Definition: SLGLImGui.cpp:89
SLint _attribLocUV
OpenGL attribute location for texture coords.
Definition: SLGLImGui.h:119
void onClose() override
Callback on closing the application.
Definition: SLGLImGui.cpp:697
~SLGLImGui() override
Definition: SLGLImGui.cpp:79
SLuint _elementsHandle
OpenGL handle for vertex indexes.
Definition: SLGLImGui.h:123
void onCharInput(SLuint c) override
Callback on character input.
Definition: SLGLImGui.cpp:689
void renderExtraFrame(SLScene *s, SLSceneView *sv, SLint mouseX, SLint mouseY) override
Renders an extra frame with the current mouse position.
Definition: SLGLImGui.cpp:703
SLint _progHandle
OpenGL handle for shader program.
Definition: SLGLImGui.h:113
SLIOBuffer _fontDataProp
Raw data of proportional font file.
Definition: SLGLImGui.h:127
SLuint _vboHandle
OpenGL handle for vertex buffer object.
Definition: SLGLImGui.h:121
SLfloat _fontFixedDots
Active font size of fixed size font.
Definition: SLGLImGui.h:125
void onMouseWheel(SLfloat yoffset) override
Callback for the mouse scroll movement.
Definition: SLGLImGui.cpp:662
SLIOBuffer _fontDataFixed
Raw data of fixed size font file.
Definition: SLGLImGui.h:128
void onResize(const SLRecti &viewportRect) override
Callback if window got resized.
Definition: SLGLImGui.cpp:445
SLint _attribLocPosition
OpenGL attribute location for vertex pos.
Definition: SLGLImGui.h:118
SLint _fragHandle
OpenGL handle for fragment shader.
Definition: SLGLImGui.h:115
SLbool _mousePressed[3]
Mouse button press state.
Definition: SLGLImGui.h:111
SLstring _configPath
Path to config files.
Definition: SLGLImGui.h:126
void onMouseMove(SLint xPos, SLint yPos) override
Updates the mouse cursor position.
Definition: SLGLImGui.cpp:655
SLint _vertHandle
OpenGL handle for vertex shader.
Definition: SLGLImGui.h:114
void onKeyRelease(SLKey key, SLKey mod) override
Callback on key release event.
Definition: SLGLImGui.cpp:679
SLfloat _mouseWheel
Mouse wheel position.
Definition: SLGLImGui.h:110
SLfloat _fontPropDots
Active font size of proportional font.
Definition: SLGLImGui.h:124
void onMouseUp(SLMouseButton button, SLint x, SLint y) override
Callback on mouse button up event.
Definition: SLGLImGui.cpp:644
SLint _attribLocColor
OpenGL attribute location for color.
Definition: SLGLImGui.h:120
cbOnImGuiSaveConfig _saveConfig
Definition: SLGLImGui.h:106
SLfloat _timeSec
Time in seconds.
Definition: SLGLImGui.h:108
void deleteOpenGLObjects()
Deletes all OpenGL objects for drawing the imGui.
Definition: SLGLImGui.cpp:331
void onKeyPress(SLKey key, SLKey mod) override
Callback on key press event.
Definition: SLGLImGui.cpp:669
void createOpenGLObjects()
Creates all OpenGL objects for drawing the imGui.
Definition: SLGLImGui.cpp:188
SLGLImGui(cbOnImGuiBuild buildCB, cbOnImGuiLoadConfig loadConfigCB, cbOnImGuiSaveConfig saveConfigCB, int dpi, SLIOBuffer fontDataProp, SLIOBuffer fontDataFixed)
Definition: SLGLImGui.cpp:24
SLint _attribLocTex
OpenGL attribute location for texture.
Definition: SLGLImGui.h:116
SLuint _vaoHandle
OpenGL vertex array object handle.
Definition: SLGLImGui.h:122
cbOnImGuiBuild _build
Definition: SLGLImGui.h:103
SLuint _fontTexture
OpenGL texture id for font.
Definition: SLGLImGui.h:112
Singleton class holding all OpenGL states.
Definition: SLGLState.h:71
static SLGLState * instance()
Public static instance getter for singleton pattern.
Definition: SLGLState.h:74
SLbool glIsES3() const
Definition: SLGLState.h:136
SLstring glSLVersionNO()
Definition: SLGLState.h:133
T width
Definition: SLRect.h:29
T y
Definition: SLRect.h:29
SLbool isEmpty() const
Definition: SLRect.h:74
T x
Definition: SLRect.h:29
T height
Definition: SLRect.h:29
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
SLRecti viewportRect() const
Definition: SLSceneView.h:176
bool exists(std::string path, SLIOStreamKind kind)
Checks whether a given file exists.
std::string readIntoString(std::string path, SLIOStreamKind kind)
Reads an entire file into a string.
void writeString(std::string path, SLIOStreamKind kind, const std::string &string)
Writes a string to a file.
T mod(T a, T b)
Definition: Utils.h:250
void log(const char *tag, const char *format,...)
logs a formatted string platform independently
Definition: Utils.cpp:1103
Utility struct that holds a pointer and its length.
Definition: SLFileStorage.h:28
SLIOBuffer copy()
Creates a copy of the data in the buffer.
size_t size
Definition: SLFileStorage.h:30
unsigned char * data
Definition: SLFileStorage.h:29