SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLImGui.cpp
Go to the documentation of this file.
1 /**
2  * \file SLImGui.cpp
3  * \brief Wrapper Class around the original OpenGL3 ImGui backend
4  * \date July 2024
5  * \authors Marcus Hudritsch
6  * \copyright http://opensource.org/licenses/GPL-3.0
7  * \remarks Please use clangformat to format the code. See more code style on
8  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
9 */
10 
11 #include "SLEnums.h"
12 #include "SLGLState.h"
13 #include "imgui.h"
14 #include "imgui_internal.h"
15 #include <SLSceneView.h>
16 #include <SLImGui.h>
17 #include <SLScene.h>
18 #include <SLFileStorage.h>
19 #include <GlobalTimer.h>
20 #include <cstddef>
21 #include <backends/imgui_impl_opengl3.h>
22 
23 //-----------------------------------------------------------------------------
26 //-----------------------------------------------------------------------------
27 SLImGui::SLImGui(cbOnImGuiBuild buildCB,
28  cbOnImGuiLoadConfig loadConfigCB,
29  cbOnImGuiSaveConfig saveConfigCB,
30  int dpi,
31  SLIOBuffer fontDataProp,
32  SLIOBuffer fontDataFixed)
33 {
34  _build = buildCB;
35  _saveConfig = saveConfigCB;
36  _fontPropDots = 13.0f;
37  _fontFixedDots = 16.0f;
38  _mouseWheel = 0.0f;
39  _mousePressed[0] = false;
40  _mousePressed[1] = false;
41  _mousePressed[2] = false;
42  _fontDataProp = fontDataProp;
43  _fontDataFixed = fontDataFixed;
44 
45  // Setup Dear ImGui context
46  IMGUI_CHECKVERSION();
47  ImGui::CreateContext();
48  ImGuiIO& io = ImGui::GetIO();
49  (void)io;
50  io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
51  io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
52  io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
53  io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
54  ImGui::StyleColorsDark();
55 
56  // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
57  ImGuiStyle& style = ImGui::GetStyle();
58  if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
59  {
60  style.WindowRounding = 0.0f;
61  style.Colors[ImGuiCol_WindowBg].w = 1.0f;
62  }
63 
64  // Setup Platform/Renderer backends
65  ImGui_ImplOpenGL3_Init(nullptr);
66 
67  // load config
68  if (loadConfigCB)
69  loadConfigCB(dpi);
70 
71  // load GUI fonts depending on the resolution
73 }
74 //-----------------------------------------------------------------------------
76 {
77  onClose();
78 }
79 //-----------------------------------------------------------------------------
80 //! Initializes OpenGL handles to zero and sets the ImGui key map
81 void SLImGui::init(const string& configPath)
82 {
83  _fontPropDots = 13.0f;
84  _fontFixedDots = 16.0f;
85  _mouseWheel = 0.0f;
86  _mousePressed[0] = false;
87  _mousePressed[1] = false;
88  _mousePressed[2] = false;
89  _configPath = configPath;
90 
91  ImGuiIO& io = ImGui::GetIO();
92  io.IniSavingRate = 1.0f;
93  io.IniFilename = NULL; // Disable ini config saving because we handle that ourselves
94  io.KeyMap[ImGuiKey_Tab] = K_tab;
95  io.KeyMap[ImGuiKey_LeftArrow] = K_left;
96  io.KeyMap[ImGuiKey_RightArrow] = K_right;
97  io.KeyMap[ImGuiKey_UpArrow] = K_up;
98  io.KeyMap[ImGuiKey_DownArrow] = K_down;
99  io.KeyMap[ImGuiKey_PageUp] = K_pageUp;
100  io.KeyMap[ImGuiKey_PageDown] = K_pageUp;
101  io.KeyMap[ImGuiKey_Home] = K_home;
102  io.KeyMap[ImGuiKey_End] = K_end;
103  io.KeyMap[ImGuiKey_Delete] = K_delete;
104  io.KeyMap[ImGuiKey_Backspace] = K_backspace;
105  io.KeyMap[ImGuiKey_Enter] = K_enter;
106  io.KeyMap[ImGuiKey_Escape] = K_esc;
107  io.KeyMap[ImGuiKey_Space] = K_space;
108  io.KeyMap[ImGuiKey_A] = 'A';
109  io.KeyMap[ImGuiKey_C] = 'C';
110  io.KeyMap[ImGuiKey_V] = 'V';
111  io.KeyMap[ImGuiKey_X] = 'X';
112  io.KeyMap[ImGuiKey_Y] = 'Y';
113  io.KeyMap[ImGuiKey_Z] = 'Z';
114 
115  // The screen size is set again in onResize
116  io.DisplaySize = ImVec2(0, 0);
117  io.DisplayFramebufferScale = ImVec2(1, 1);
118 
119 #if defined(SL_OS_ANDROID) || defined(SL_OS_MACIOS) || defined(SL_EMSCRIPTEN)
120  io.MouseDrawCursor = false;
121 #else
122  io.MouseDrawCursor = true;
123 #endif
124 
125  // Change default style to show the widget border
126  ImGuiStyle& style = ImGui::GetStyle();
127  style.FrameBorderSize = 1;
128 
129  // Load ImGui config from imgui.ini
130  SLstring iniFile = configPath + "imgui.ini";
131  if (SLFileStorage::exists(iniFile, IOK_config))
132  {
133  SLstring iniContents = SLFileStorage::readIntoString(iniFile,
134  IOK_config);
135  ImGui::LoadIniSettingsFromMemory(iniContents.c_str(),
136  iniContents.size());
137  }
138 }
139 //-----------------------------------------------------------------------------
140 //! Callback on closing the application
142 {
143  ImGui::SetCurrentContext(ImGui::GetCurrentContext());
144  if (_saveConfig)
145  _saveConfig();
146  ImGui_ImplOpenGL3_Shutdown();
147  ImGui::DestroyContext();
148 }
149 //-----------------------------------------------------------------------------
150 //! Loads the proportional and fixed size font depending on the passed DPI
151 void SLImGui::loadFonts(SLfloat fontPropDotsToLoad,
152  SLfloat fontFixedDotsToLoad)
153 {
154  _fontPropDots = fontPropDotsToLoad;
155  _fontFixedDots = fontFixedDotsToLoad;
156 
157  ImGuiIO& io = ImGui::GetIO();
158  io.Fonts->Clear();
159 
160  // Create copies of the font data because ImGUI takes ownerhip of the data.
161  SLIOBuffer fontDataProp = _fontDataProp.copy();
162  SLIOBuffer fontDataFixed = _fontDataFixed.copy();
163 
164  // Load proportional font for menu and text displays
165  io.Fonts->AddFontFromMemoryTTF(fontDataProp.data,
166  static_cast<int>(fontDataProp.size),
167  fontPropDotsToLoad);
168 
169  // Load fixed size font for statistics windows
170  io.Fonts->AddFontFromMemoryTTF(fontDataFixed.data,
171  static_cast<int>(fontDataFixed.size),
172  fontFixedDotsToLoad);
173  ImGui_ImplOpenGL3_DestroyDeviceObjects();
174  ImGui_ImplOpenGL3_CreateDeviceObjects();
175 }
176 //-----------------------------------------------------------------------------
177 //! Prints the compile errors in case of a GLSL compile failure
178 void SLImGui::printCompileErrors(SLint shaderHandle, const SLchar* src)
179 {
180 }
181 //-----------------------------------------------------------------------------
182 //! Inits a new frame for the ImGui system
184 {
188 
189  ImGui_ImplOpenGL3_NewFrame();
190 
191  ImGuiIO& io = ImGui::GetIO();
192 
193  // Setup time step
194  SLfloat nowSec = GlobalTimer::timeS();
195  io.DeltaTime = _timeSec > 0.0 ? nowSec - _timeSec : 1.0f / 60.0f;
196  if (io.DeltaTime < 0) io.DeltaTime = 1.0f / 60.0f;
197  _timeSec = nowSec;
198 
199  io.MouseWheel = _mouseWheel;
200  _mouseWheel = 0.0f;
201 
202  // Start the frame
203  ImGui::NewFrame();
204 
205  // Save ImGui config to imgui.ini
206  if (ImGui::GetIO().WantSaveIniSettings)
207  {
208  SLstring iniFile = _configPath + "imgui.ini";
209  size_t iniContentsSize;
210  const char* rawIniContents = ImGui::SaveIniSettingsToMemory(&iniContentsSize);
211  SLstring iniContents(rawIniContents, rawIniContents + iniContentsSize);
212  SLFileStorage::writeString(iniFile, IOK_config, iniContents);
213  ImGui::GetIO().WantSaveIniSettings = false;
214  }
215 
216  // Call the _build function. The whole UI is constructed here
217  // This function is provided by the top-level project.
218  // For the SLProject demo apps this _build function is implemented in the
219  // class SLDemoGui.
220  if (_build)
221  _build(s, sv);
222 }
223 //-----------------------------------------------------------------------------
224 //! Callback if window got resized
225 void SLImGui::onResize(const SLRecti& viewport)
226 {
227  SLGLState* stateGL = SLGLState::instance();
228  ImGuiIO& io = ImGui::GetIO();
229  io.DisplaySize = ImVec2((SLfloat)viewport.width, (SLfloat)viewport.height);
230  io.DisplayFramebufferScale = ImVec2(1, 1);
231 }
232 //-----------------------------------------------------------------------------
233 //! Callback for main rendering for the ImGui GUI system
234 void SLImGui::onPaint(const SLRecti& viewport)
235 {
236  ImGuiIO& io = ImGui::GetIO();
237  ImGui::Render();
238  ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
239 }
240 //-----------------------------------------------------------------------------
241 //! Callback on mouse button down event
243 {
244  ImGuiIO& io = ImGui::GetIO();
245  io.MousePos = ImVec2((SLfloat)x, (SLfloat)y);
246  if (button == MB_left) io.MouseDown[0] = true;
247  if (button == MB_right) io.MouseDown[1] = true;
248  if (button == MB_middle) io.MouseDown[2] = true;
249  // SL_LOG("D");
250 }
251 //-----------------------------------------------------------------------------
252 //! Callback on mouse button up event
254 {
255  ImGuiIO& io = ImGui::GetIO();
256  io.MousePos = ImVec2((SLfloat)x, (SLfloat)y);
257  if (button == MB_left) io.MouseDown[0] = false;
258  if (button == MB_right) io.MouseDown[1] = false;
259  if (button == MB_middle) io.MouseDown[2] = false;
260  // SL_LOG("U\n");
261 }
262 //-----------------------------------------------------------------------------
263 //! Updates the mouse cursor position
265 {
266  ImGui::GetIO().MousePos = ImVec2((SLfloat)xPos, (SLfloat)yPos);
267  // SL_LOG("M");
268 }
269 //-----------------------------------------------------------------------------
270 //! Callback for the mouse scroll movement
272 {
273  // Use fractional mouse wheel, 1.0 unit 5 lines.
274  _mouseWheel += yoffset;
275 }
276 //-----------------------------------------------------------------------------
277 //! Callback on key press event
279 {
280  ImGuiIO& io = ImGui::GetIO();
281  io.KeysDown[key] = true;
282  io.KeyCtrl = mod & K_ctrl ? true : false;
283  io.KeyShift = mod & K_shift ? true : false;
284  io.KeyAlt = mod & K_alt ? true : false;
285 }
286 //-----------------------------------------------------------------------------
287 //! Callback on key release event
289 {
290  ImGuiIO& io = ImGui::GetIO();
291  io.KeysDown[key] = false;
292  io.KeyCtrl = mod & K_ctrl ? true : false;
293  io.KeyShift = mod & K_shift ? true : false;
294  io.KeyAlt = mod & K_alt ? true : false;
295 }
296 //-----------------------------------------------------------------------------
297 //! Callback on character input
299 {
300  ImGuiIO& io = ImGui::GetIO();
301  if (c > 0 && c < 0x10000)
302  io.AddInputCharacter((unsigned short)c);
303 }
304 //-----------------------------------------------------------------------------
305 //! Renders an extra frame with the current mouse position
307  SLSceneView* sv,
308  SLint mouseX,
309  SLint mouseY)
310 {
311  // If ImGui _build function exists render the ImGui
312  if (_build)
313  {
314  ImGui::GetIO().MousePos = ImVec2((SLfloat)mouseX, (SLfloat)mouseY);
315  onInitNewFrame(s, sv);
316  onPaint(sv->viewportRect());
317  }
318 }
319 //-----------------------------------------------------------------------------
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
unsigned int SLuint
Definition: SL.h:171
char SLchar
Definition: SL.h:162
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_space
Definition: SLEnums.h:18
@ 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
typedef void(SL_STDCALL *cbOnImGuiBuild)(SLScene *s
Callback function typedef for ImGui build function.
Singleton class for global render state.
Wrapper Class around the external ImGui GUI-framework.
static float timeS()
Definition: GlobalTimer.cpp:20
Singleton class holding all OpenGL states.
Definition: SLGLState.h:71
static SLGLState * instance()
Public static instance getter for singleton pattern.
Definition: SLGLState.h:74
void onKeyRelease(SLKey key, SLKey mod) override
Callback on key release event.
Definition: SLImGui.cpp:288
void onMouseDown(SLMouseButton button, SLint x, SLint y) override
Callback on mouse button down event.
Definition: SLImGui.cpp:242
SLIOBuffer _fontDataFixed
Raw data of fixed size font file.
Definition: SLImGui.h:114
void loadFonts(SLfloat fontPropDots, SLfloat fontFixedDots)
Loads the proportional and fixed size font depending on the passed DPI.
Definition: SLImGui.cpp:151
void onMouseWheel(SLfloat yoffset) override
Callback for the mouse scroll movement.
Definition: SLImGui.cpp:271
static SLfloat fontPropDots
Default font size of proportional font.
Definition: SLImGui.h:91
~SLImGui() override
Definition: SLImGui.cpp:75
SLfloat _timeSec
Time in seconds.
Definition: SLImGui.h:106
void onPaint(const SLRecti &viewport) override
Callback for main rendering for the ImGui GUI system.
Definition: SLImGui.cpp:234
SLbool _mousePressed[3]
Mouse button press state.
Definition: SLImGui.h:109
void onCharInput(SLuint c) override
Callback on character input.
Definition: SLImGui.cpp:298
void onMouseUp(SLMouseButton button, SLint x, SLint y) override
Callback on mouse button up event.
Definition: SLImGui.cpp:253
void printCompileErrors(SLint shaderHandle, const SLchar *src)
Prints the compile errors in case of a GLSL compile failure.
Definition: SLImGui.cpp:178
void onMouseMove(SLint xPos, SLint yPos) override
Updates the mouse cursor position.
Definition: SLImGui.cpp:264
void onKeyPress(SLKey key, SLKey mod) override
Callback on key press event.
Definition: SLImGui.cpp:278
SLfloat _fontFixedDots
Active font size of fixed size font.
Definition: SLImGui.h:111
cbOnImGuiBuild _build
Definition: SLImGui.h:101
SLfloat _mouseWheel
Mouse wheel position.
Definition: SLImGui.h:108
SLstring _configPath
Path to config files.
Definition: SLImGui.h:112
void init(const string &configPath) override
Initializes OpenGL handles to zero and sets the ImGui key map.
Definition: SLImGui.cpp:81
void onClose() override
Callback on closing the application.
Definition: SLImGui.cpp:141
void onResize(const SLRecti &viewport) override
Callback if window got resized.
Definition: SLImGui.cpp:225
SLfloat _fontPropDots
Active font size of proportional font.
Definition: SLImGui.h:110
SLIOBuffer _fontDataProp
Raw data of proportional font file.
Definition: SLImGui.h:113
static SLfloat fontFixedDots
Default font size of fixed size font.
Definition: SLImGui.h:92
void onInitNewFrame(SLScene *s, SLSceneView *sv) override
Inits a new frame for the ImGui system.
Definition: SLImGui.cpp:183
void renderExtraFrame(SLScene *s, SLSceneView *sv, SLint mouseX, SLint mouseY) override
Renders an extra frame with the current mouse position.
Definition: SLImGui.cpp:306
cbOnImGuiSaveConfig _saveConfig
Definition: SLImGui.h:104
SLImGui(cbOnImGuiBuild buildCB, cbOnImGuiLoadConfig loadConfigCB, cbOnImGuiSaveConfig saveConfigCB, int dpi, SLIOBuffer fontDataProp, SLIOBuffer fontDataFixed)
Definition: SLImGui.cpp:27
T width
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
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