Skip to content

Commit afeaaed

Browse files
committed
update imgui-sdl2 binding code
1 parent a807c80 commit afeaaed

1 file changed

Lines changed: 69 additions & 36 deletions

File tree

src/core/PlatformSDL2.cpp

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,12 @@ static bool ImGui_ImplSdlGL3_Init(SDL_Window* window)
177177
// Create bgfx imgui objects
178178
GPImGui::Get()->imguiInit();
179179

180-
// Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array.
180+
// Setup back-end capabilities flags
181181
ImGuiIO& io = ImGui::GetIO();
182+
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
183+
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
184+
185+
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
182186
io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
183187
io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
184188
io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
@@ -212,6 +216,7 @@ static bool ImGui_ImplSdlGL3_Init(SDL_Window* window)
212216
g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
213217
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
214218
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
219+
g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
215220

216221
#ifdef _WIN32
217222
SDL_SysWMinfo wmInfo;
@@ -225,66 +230,94 @@ static bool ImGui_ImplSdlGL3_Init(SDL_Window* window)
225230
return true;
226231
}
227232

228-
static void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window)
233+
static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
229234
{
230235
ImGuiIO& io = ImGui::GetIO();
231236

232-
// Setup display size (every frame to accommodate for window resizing)
233-
int w, h;
234-
int display_w, display_h;
235-
SDL_GetWindowSize(window, &w, &h);
236-
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
237-
io.DisplaySize = ImVec2((float)w, (float)h);
238-
io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
239-
240-
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
241-
/*static Uint64 frequency = SDL_GetPerformanceFrequency();
242-
Uint64 current_time = SDL_GetPerformanceCounter();
243-
io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f);
244-
g_Time = current_time;*/
237+
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
238+
if (io.WantSetMousePos)
239+
SDL_WarpMouseInWindow(__window, (int)io.MousePos.x, (int)io.MousePos.y);
240+
else
241+
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
245242

246-
// Setup mouse inputs (we already got mouse wheel, keyboard keys & characters from our event handler)
247243
int mx, my;
248244
Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my);
249-
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
250245
io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
251246
io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
252247
io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
253248
g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false;
254249

255-
// We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016)
256-
#if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4)
257-
if ((SDL_GetWindowFlags(window) & (SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_MOUSE_CAPTURE)) != 0)
250+
#if SDL_HAS_CAPTURE_MOUSE && !defined(__EMSCRIPTEN__)
251+
SDL_Window* focused_window = SDL_GetKeyboardFocus();
252+
if (g_Window == focused_window)
253+
{
254+
// SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
255+
// The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
256+
int wx, wy;
257+
SDL_GetWindowPosition(focused_window, &wx, &wy);
258+
SDL_GetGlobalMouseState(&mx, &my);
259+
mx -= wx;
260+
my -= wy;
258261
io.MousePos = ImVec2((float)mx, (float)my);
259-
bool any_mouse_button_down = false;
260-
for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++)
261-
any_mouse_button_down |= io.MouseDown[n];
262-
if (any_mouse_button_down && (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE) == 0)
263-
SDL_CaptureMouse(SDL_TRUE);
264-
if (!any_mouse_button_down && (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE) != 0)
265-
SDL_CaptureMouse(SDL_FALSE);
262+
}
263+
264+
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
265+
// The function is only supported from SDL 2.0.4 (released Jan 2016)
266+
bool any_mouse_button_down = ImGui::IsAnyMouseDown();
267+
SDL_CaptureMouse(any_mouse_button_down ? SDL_TRUE : SDL_FALSE);
266268
#else
267-
if ((SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) != 0)
269+
if (SDL_GetWindowFlags(__window) & SDL_WINDOW_INPUT_FOCUS)
268270
io.MousePos = ImVec2((float)mx, (float)my);
269271
#endif
272+
}
273+
274+
static void ImGui_ImplSDL2_UpdateMouseCursor()
275+
{
276+
ImGuiIO& io = ImGui::GetIO();
277+
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
278+
return;
270279

271-
// Update OS/hardware mouse cursor if imgui isn't drawing a software cursor
272-
ImGuiMouseCursor cursor = ImGui::GetMouseCursor();
273-
if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None)
280+
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
281+
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
274282
{
275-
SDL_ShowCursor(0);
283+
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
284+
SDL_ShowCursor(SDL_FALSE);
276285
}
277286
else
278287
{
279-
SDL_SetCursor(g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
280-
SDL_ShowCursor(1);
288+
// Show OS mouse cursor
289+
SDL_SetCursor(g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
290+
SDL_ShowCursor(SDL_TRUE);
281291
}
292+
}
282293

283-
// fix issue when debugging (mouse was still captured by sdl and we cannot use it in debugger)
284-
SDL_CaptureMouse(SDL_FALSE);
294+
static void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window)
295+
{
296+
ImGuiIO& io = ImGui::GetIO();
297+
IM_ASSERT(io.Fonts->IsBuilt()); // Font atlas needs to be built, call renderer _NewFrame() function e.g. ImGui_ImplOpenGL3_NewFrame()
298+
299+
// Setup display size (every frame to accommodate for window resizing)
300+
int w, h;
301+
int display_w, display_h;
302+
SDL_GetWindowSize(window, &w, &h);
303+
SDL_GL_GetDrawableSize(window, &display_w, &display_h);
304+
io.DisplaySize = ImVec2((float)w, (float)h);
305+
io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
306+
307+
// Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
308+
static Uint64 frequency = SDL_GetPerformanceFrequency();
309+
Uint64 current_time = SDL_GetPerformanceCounter();
310+
io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f);
311+
g_Time = current_time;
312+
313+
ImGui_ImplSDL2_UpdateMousePosAndButtons();
314+
ImGui_ImplSDL2_UpdateMouseCursor();
285315

286316
// Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application.
287317
ImGui::NewFrame();
318+
319+
// fix issue when debugging (mouse was still captured by sdl and we cannot use it in debugger)
320+
//SDL_CaptureMouse(SDL_FALSE);
288321
}
289322

290323
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.

0 commit comments

Comments
 (0)