From dcf54782d4be1070bab4821f06cdaf9181bfc528 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 31 Jul 2024 16:34:08 +0200 Subject: [PATCH 1/7] Version 1.91.WIP --- docs/CHANGELOG.txt | 9 +++++++++ imgui.cpp | 2 +- imgui.h | 6 +++--- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 18 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8c83dadff..877cd8584 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,15 @@ HOW TO UPDATE? and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. - Please report any issue! +----------------------------------------------------------------------- + VERSION 1.91.1 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking changes: + +Other changes: + + ----------------------------------------------------------------------- VERSION 1.91.0 (Released 2024-07-30) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 2c8611266..94c59e7ea 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 +// dear imgui, v1.91.1 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 05e48a175..5b22dfe71 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 +// dear imgui, v1.91.1 WIP // (headers) // Help: @@ -27,8 +27,8 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') -#define IMGUI_VERSION "1.91.0" -#define IMGUI_VERSION_NUM 19100 +#define IMGUI_VERSION "1.91.1 WIP" +#define IMGUI_VERSION_NUM 19101 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4d6c2bbf2..2800e9518 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 +// dear imgui, v1.91.1 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 57486a6e2..854ad4012 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 +// dear imgui, v1.91.1 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index ab43922ba..0e39b0874 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 +// dear imgui, v1.91.1 WIP // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 37dd70304..92c62949e 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 +// dear imgui, v1.91.1 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2aa24efe8..5ca9a9d3c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 +// dear imgui, v1.91.1 WIP // (widgets code) /* From 887478793b8f61c5385131d823dbb8ad8e8e900f Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 31 Jul 2024 16:55:17 +0200 Subject: [PATCH 2/7] Examples: SDL2 (all), SDL3 (all), Win32+OpenGL3: Rework examples main loop to handle minimization without burning CPU or GPU by running unthrottled code. (#7844) --- docs/CHANGELOG.txt | 4 ++++ examples/example_sdl2_directx11/main.cpp | 5 +++++ examples/example_sdl2_opengl2/main.cpp | 5 +++++ examples/example_sdl2_opengl3/main.cpp | 5 +++++ examples/example_sdl2_sdlrenderer2/main.cpp | 5 +++++ examples/example_sdl2_vulkan/main.cpp | 5 +++++ examples/example_sdl3_opengl3/main.cpp | 5 +++++ examples/example_sdl3_sdlrenderer3/main.cpp | 5 +++++ examples/example_win32_opengl3/main.cpp | 5 +++++ 9 files changed, 44 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 877cd8584..7c0eb2050 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,10 @@ Breaking changes: Other changes: +- Examples: SDL2 (all), SDL3 (all), Win32+OpenGL3: rework examples main loop to handle + minimization without burning CPU or GPU by running unthrottled code. (#7844) + + ----------------------------------------------------------------------- VERSION 1.91.0 (Released 2024-07-30) diff --git a/examples/example_sdl2_directx11/main.cpp b/examples/example_sdl2_directx11/main.cpp index 3275bafde..47c852d27 100644 --- a/examples/example_sdl2_directx11/main.cpp +++ b/examples/example_sdl2_directx11/main.cpp @@ -126,6 +126,11 @@ int main(int, char**) CreateRenderTarget(); } } + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + { + SDL_Delay(10); + continue; + } // Start the Dear ImGui frame ImGui_ImplDX11_NewFrame(); diff --git a/examples/example_sdl2_opengl2/main.cpp b/examples/example_sdl2_opengl2/main.cpp index efb28edbc..a70edd225 100644 --- a/examples/example_sdl2_opengl2/main.cpp +++ b/examples/example_sdl2_opengl2/main.cpp @@ -105,6 +105,11 @@ int main(int, char**) if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) done = true; } + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + { + SDL_Delay(10); + continue; + } // Start the Dear ImGui frame ImGui_ImplOpenGL2_NewFrame(); diff --git a/examples/example_sdl2_opengl3/main.cpp b/examples/example_sdl2_opengl3/main.cpp index d748c1360..2a4d7b9e7 100644 --- a/examples/example_sdl2_opengl3/main.cpp +++ b/examples/example_sdl2_opengl3/main.cpp @@ -140,6 +140,11 @@ int main(int, char**) if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) done = true; } + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + { + SDL_Delay(10); + continue; + } // Start the Dear ImGui frame ImGui_ImplOpenGL3_NewFrame(); diff --git a/examples/example_sdl2_sdlrenderer2/main.cpp b/examples/example_sdl2_sdlrenderer2/main.cpp index 8bb309920..b186b6268 100644 --- a/examples/example_sdl2_sdlrenderer2/main.cpp +++ b/examples/example_sdl2_sdlrenderer2/main.cpp @@ -107,6 +107,11 @@ int main(int, char**) if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) done = true; } + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + { + SDL_Delay(10); + continue; + } // Start the Dear ImGui frame ImGui_ImplSDLRenderer2_NewFrame(); diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index afcebf1b9..cb116b76e 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -492,6 +492,11 @@ int main(int, char**) if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) done = true; } + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + { + SDL_Delay(10); + continue; + } // Resize swap chain? int fb_width, fb_height; diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp index c4eee77d4..e6aba8809 100644 --- a/examples/example_sdl3_opengl3/main.cpp +++ b/examples/example_sdl3_opengl3/main.cpp @@ -136,6 +136,11 @@ int main(int, char**) if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window)) done = true; } + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + { + SDL_Delay(10); + continue; + } // Start the Dear ImGui frame ImGui_ImplOpenGL3_NewFrame(); diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 607d00b6b..951141548 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -111,6 +111,11 @@ int main(int, char**) if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window)) done = true; } + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + { + SDL_Delay(10); + continue; + } // Start the Dear ImGui frame ImGui_ImplSDLRenderer3_NewFrame(); diff --git a/examples/example_win32_opengl3/main.cpp b/examples/example_win32_opengl3/main.cpp index 594931dca..8ecd27a20 100644 --- a/examples/example_win32_opengl3/main.cpp +++ b/examples/example_win32_opengl3/main.cpp @@ -108,6 +108,11 @@ int main(int, char**) } if (done) break; + if (::IsIconic(hwnd)) + { + ::Sleep(10); + continue; + } // Start the Dear ImGui frame ImGui_ImplOpenGL3_NewFrame(); From 71ee2ce3673c8182871cb0b8554f9caf089a5334 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 31 Jul 2024 17:33:24 +0200 Subject: [PATCH 3/7] Examples: GLFW: rework examples main loop to handle minimization without burning CPU or GPU by running unthrottled code. (#7844) Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper. --- backends/imgui_impl_glfw.cpp | 14 ++++++++++++++ backends/imgui_impl_glfw.h | 3 +++ docs/CHANGELOG.txt | 6 ++++-- examples/example_glfw_opengl2/main.cpp | 5 +++++ examples/example_glfw_opengl3/main.cpp | 5 +++++ examples/example_glfw_vulkan/main.cpp | 5 +++++ 6 files changed, 36 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 305891624..df581537b 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-07-31: Added ImGui_ImplGlfw_Sleep() helper function for usage by our examples app, since GLFW doesn't provide one. // 2024-07-08: *BREAKING* Renamed ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback to ImGui_ImplGlfw_InstallEmscriptenCallbacks(), added GLFWWindow* parameter. // 2024-07-08: Emscripten: Added support for GLFW3 contrib port (GLFW 3.4.0 features + bug fixes): to enable, replace -sUSE_GLFW=3 with --use-port=contrib.glfw3 (requires emscripten 3.1.59+) (https://github.com/pongasoft/emscripten-glfw) // 2024-07-02: Emscripten: Added io.PlatformOpenInShellFn() handler for Emscripten versions. @@ -99,6 +100,9 @@ #endif #include // for glfwGetCocoaWindow() #endif +#ifndef _WIN32 +#include // for usleep() +#endif #ifdef __EMSCRIPTEN__ #include @@ -825,6 +829,16 @@ void ImGui_ImplGlfw_NewFrame() ImGui_ImplGlfw_UpdateGamepads(); } +// GLFW doesn't provide a portable sleep function +void ImGui_ImplGlfw_Sleep(int milliseconds) +{ +#ifdef _WIN32 + ::Sleep(milliseconds); +#else + usleep(milliseconds * 1000); +#endif +} + #ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3 static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data) { diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index c0eac1134..60b95bd99 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -57,4 +57,7 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event); +// GLFW helpers +IMGUI_IMPL_API void ImGui_ImplGlfw_Sleep(int milliseconds); + #endif // #ifndef IMGUI_DISABLE diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7c0eb2050..b265121e3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,8 +43,10 @@ Breaking changes: Other changes: -- Examples: SDL2 (all), SDL3 (all), Win32+OpenGL3: rework examples main loop to handle - minimization without burning CPU or GPU by running unthrottled code. (#7844) +- Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not + provide a way to do a portable sleep. (#7844) +- Examples: GLFW (all), SDL2 (all), SDL3 (all), Win32+OpenGL3: rework examples main loop + to handle minimization without burning CPU or GPU by running unthrottled code. (#7844) diff --git a/examples/example_glfw_opengl2/main.cpp b/examples/example_glfw_opengl2/main.cpp index 5e47b0008..1fcec2b2a 100644 --- a/examples/example_glfw_opengl2/main.cpp +++ b/examples/example_glfw_opengl2/main.cpp @@ -91,6 +91,11 @@ int main(int, char**) // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); + if (glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0) + { + ImGui_ImplGlfw_Sleep(10); + continue; + } // Start the Dear ImGui frame ImGui_ImplOpenGL2_NewFrame(); diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index 22ef79eb7..3afe251e3 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -127,6 +127,11 @@ int main(int, char**) // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); + if (glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0) + { + ImGui_ImplGlfw_Sleep(10); + continue; + } // Start the Dear ImGui frame ImGui_ImplOpenGL3_NewFrame(); diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index e1f099e3d..901b46c4c 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -494,6 +494,11 @@ int main(int, char**) g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } + if (glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0) + { + ImGui_ImplGlfw_Sleep(10); + continue; + } // Start the Dear ImGui frame ImGui_ImplVulkan_NewFrame(); From fd57b252ac1932760160947ca82b55b884f92600 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 31 Jul 2024 17:47:38 +0200 Subject: [PATCH 4/7] Examples: Fix for Emscripten. GLFW+WGPU: rework examples main loop to handle minimization. (#7844) Amend 8874787, 71ee2ce Amend ea39841f (emscripten_mainloop_stub.h) --- examples/example_glfw_wgpu/main.cpp | 5 +++++ examples/example_sdl3_sdlrenderer3/main.cpp | 3 +++ examples/libs/emscripten/emscripten_mainloop_stub.h | 7 ++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/examples/example_glfw_wgpu/main.cpp b/examples/example_glfw_wgpu/main.cpp index c5872bd85..f510987ed 100644 --- a/examples/example_glfw_wgpu/main.cpp +++ b/examples/example_glfw_wgpu/main.cpp @@ -151,6 +151,11 @@ int main(int, char**) // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); + if (glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0) + { + ImGui_ImplGlfw_Sleep(10); + continue; + } // React to changes in screen size int width, height; diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 951141548..6efd2754a 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -167,6 +167,9 @@ int main(int, char**) ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), renderer); SDL_RenderPresent(renderer); } +#ifdef __EMSCRIPTEN__ + EMSCRIPTEN_MAINLOOP_END; +#endif // Cleanup ImGui_ImplSDLRenderer3_Shutdown(); diff --git a/examples/libs/emscripten/emscripten_mainloop_stub.h b/examples/libs/emscripten/emscripten_mainloop_stub.h index 05cf60fed..8c4c48ecf 100644 --- a/examples/libs/emscripten/emscripten_mainloop_stub.h +++ b/examples/libs/emscripten/emscripten_mainloop_stub.h @@ -17,20 +17,21 @@ // - So the next logical step was to refactor all examples to follow that layout of using a "main loop" function. // This worked, but it made us lose all the nice things we had... -// Since only about 3 examples really need to run with Emscripten, here's our solution: +// Since only about 4 examples really need to run with Emscripten, here's our solution: // - Use some weird macros and capturing lambda to turn a loop in main() into a function. // - Hide all that crap in this file so it doesn't make our examples unusually ugly. // As a stance and principle of Dear ImGui development we don't use C++ headers and we don't // want to suggest to the newcomer that we would ever use C++ headers as this would affect // the initial judgment of many of our target audience. // - Technique is based on this idea: https://github.com/ocornut/imgui/pull/2492/ +// - The do { } while (0) is to allow our code calling continue in the main loop. #ifdef __EMSCRIPTEN__ #include #include static std::function MainLoopForEmscriptenP; static void MainLoopForEmscripten() { MainLoopForEmscriptenP(); } -#define EMSCRIPTEN_MAINLOOP_BEGIN MainLoopForEmscriptenP = [&]() -#define EMSCRIPTEN_MAINLOOP_END ; emscripten_set_main_loop(MainLoopForEmscripten, 0, true) +#define EMSCRIPTEN_MAINLOOP_BEGIN MainLoopForEmscriptenP = [&]() { do +#define EMSCRIPTEN_MAINLOOP_END while (0); }; emscripten_set_main_loop(MainLoopForEmscripten, 0, true) #else #define EMSCRIPTEN_MAINLOOP_BEGIN #define EMSCRIPTEN_MAINLOOP_END From 5e7dc72c926b489450e9ea82ea62fd3a6432d5aa Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Thu, 1 Aug 2024 00:04:34 +0200 Subject: [PATCH 5/7] Examples: SDL3: Update readme to use SDL3_DIR (#7846) --- examples/example_sdl3_opengl3/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/example_sdl3_opengl3/README.md b/examples/example_sdl3_opengl3/README.md index 5828e4bfc..a032f8752 100644 --- a/examples/example_sdl3_opengl3/README.md +++ b/examples/example_sdl3_opengl3/README.md @@ -9,11 +9,11 @@ Use the provided project file (.vcxproj). Add to solution (imgui_examples.sln) i Use build_win32.bat or directly: ``` -set SDL2_DIR=path_to_your_sdl3_folder -cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl3_opengl3.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL3.lib opengl32.lib /subsystem:console +set SDL3_DIR=path_to_your_sdl3_folder +cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL3_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl3_opengl3.exe /FoDebug/ /link /libpath:%SDL3_DIR%\lib\x86 SDL3.lib opengl32.lib /subsystem:console # ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries # or for 64-bit: -cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl3_opengl3.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL3.lib SDL2mainopengl32.lib /subsystem:console +cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL3_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl3_opengl3.exe /FoDebug/ /link /libpath:%SDL3_DIR%\lib\x64 SDL3.lib SDL2mainopengl32.lib /subsystem:console ``` ## Linux and similar Unixes From 2981a10c537cbc329e5b4e58af1e1a1146d55ea4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 1 Aug 2024 17:16:13 +0200 Subject: [PATCH 6/7] MultiSelect, TreeNode, Drag and Drop: fixed an issue where carrying a drag and drop payload over an already open tree node would select it. (#7850) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b265121e3..3f0d9c4ea 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,8 @@ Breaking changes: Other changes: +- MultiSelect, TreeNode, Drag and Drop: fixed an issue where carrying a drag and drop + payload over an already open tree node would incorrectly select it. (#7850) - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not provide a way to do a portable sleep. (#7844) - Examples: GLFW (all), SDL2 (all), SDL3 (all), Win32+OpenGL3: rework examples main loop diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5ca9a9d3c..0f0134b9d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6531,6 +6531,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l IM_ASSERT(button_flags & ImGuiButtonFlags_PressedOnDragDropHold); if (!is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again. toggled = true; + else + pressed = false; // Cancel press so it doesn't trigger selection. } if (g.NavId == id && g.NavMoveDir == ImGuiDir_Left && is_open) From 9f8f5e11455e87cce4ebdefa422661951701dfae Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 1 Aug 2024 17:28:47 +0200 Subject: [PATCH 7/7] MultiSelect+TreeNode: default open behavior is OpenOnDoubleClick + OpenOnArrow when used in a multi-select context without any OpenOnXXX flags set. (#7850) --- docs/CHANGELOG.txt | 4 +++- imgui.h | 4 ++-- imgui_internal.h | 1 + imgui_widgets.cpp | 14 +++++++------- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3f0d9c4ea..a495cd5d3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,8 +43,10 @@ Breaking changes: Other changes: -- MultiSelect, TreeNode, Drag and Drop: fixed an issue where carrying a drag and drop +- MultiSelect+TreeNode+Drag and Drop: fixed an issue where carrying a drag and drop payload over an already open tree node would incorrectly select it. (#7850) +- MultiSelect+TreeNode: default open behavior is OpenOnDoubleClick + OpenOnArrow + when used in a multi-select context without any OpenOnXXX flags set. (#7850) - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not provide a way to do a portable sleep. (#7844) - Examples: GLFW (all), SDL2 (all), SDL3 (all), Win32+OpenGL3: rework examples main loop diff --git a/imgui.h b/imgui.h index 5b22dfe71..6d4f51388 100644 --- a/imgui.h +++ b/imgui.h @@ -1177,8 +1177,8 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open - ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node - ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. + ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Open on double-click instead of simple click (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined. + ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Open when clicking on the arrow part (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined. ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag! ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding() before the node. diff --git a/imgui_internal.h b/imgui_internal.h index 0e39b0874..5b6d4c195 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -970,6 +970,7 @@ enum ImGuiTreeNodeFlagsPrivate_ { ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 28,// FIXME-WIP: Hard-coded for CollapsingHeader() ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, but reversed trees (#6517) + ImGuiTreeNodeFlags_OpenOnMask_ = ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_OpenOnArrow, }; enum ImGuiSeparatorFlags_ diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 0f0134b9d..11f1cdf60 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6475,6 +6475,10 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x; const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2); + const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0; + if (is_multi_select) // We absolutely need to distinguish open vs select so _OpenOnArrow comes by default + flags |= (flags & ImGuiTreeNodeFlags_OpenOnMask_) == 0 ? ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick : ImGuiTreeNodeFlags_OpenOnArrow; + // Open behaviors can be altered with the _OpenOnArrow and _OnOnDoubleClick flags. // Some alteration have subtle effects (e.g. toggle on MouseUp vs MouseDown events) due to requirements for multi-selection and drag and drop support. // - Single-click on label = Toggle on MouseUp (default, when _OpenOnArrow=0) @@ -6495,16 +6499,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const bool was_selected = selected; // Multi-selection support (header) - const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0; if (is_multi_select) { // Handle multi-select + alter button flags for it MultiSelectItemHeader(id, &selected, &button_flags); if (is_mouse_x_over_arrow) button_flags = (button_flags | ImGuiButtonFlags_PressedOnClick) & ~ImGuiButtonFlags_PressedOnClickRelease; - - // We absolutely need to distinguish open vs select so comes by default - flags |= ImGuiTreeNodeFlags_OpenOnArrow; } else { @@ -6519,12 +6519,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { if (pressed && g.DragDropHoldJustPressedId != id) { - if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id && !is_multi_select)) - toggled = true; + if ((flags & ImGuiTreeNodeFlags_OpenOnMask_) == 0 || (g.NavActivateId == id && !is_multi_select)) + toggled = true; // Single click if (flags & ImGuiTreeNodeFlags_OpenOnArrow) toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseClickedCount[0] == 2) - toggled = true; + toggled = true; // Double click } else if (pressed && g.DragDropHoldJustPressedId == id) {