From 0d582dabf34e9e31f072b1ee5c353c18351b4424 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 14 Dec 2023 17:24:13 +0100 Subject: [PATCH 01/16] Fixed warning (amend 54c1bde) --- imgui_widgets.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5ad751d46..ac5455b05 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4111,7 +4111,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ ImGuiWindow* draw_window = window; ImVec2 inner_size = frame_size; - ImGuiItemStatusFlags item_status_flags = 0; ImGuiLastItemData item_data_backup; if (is_multiline) { @@ -4122,7 +4121,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ EndGroup(); return false; } - item_status_flags = g.LastItemData.StatusFlags; item_data_backup = g.LastItemData; window->DC.CursorPos = backup_pos; @@ -4162,7 +4160,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (!(flags & ImGuiInputTextFlags_MergedItem)) if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable)) return false; - item_status_flags = g.LastItemData.StatusFlags; } const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); if (hovered) From f59b54c6f436113991693e73831a8ed65183a13b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Dec 2023 18:23:53 +0100 Subject: [PATCH 02/16] Nav: Activation can also be performed with Keypad Enter. (#5606) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f4543da00..731ec4d5b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,7 @@ Other changes: speed asymetry when (incorrectly) attempting to scroll by non-integer amount. (#6677) - Nav, IO: SetNextFrameWantCaptureKeyboard(false) calls are not overrided back to true when navigation is enabled. SetNextFrameWantCaptureKeyboard() is always higher priority. (#6997) +- Nav: Activation can also be performed with Keypad Enter. (#5606) - Drag and Drop: Fixed drop target highlight on items temporarily pushing a widened clip rect (namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers all columns. (#7049, #4281, #3272) diff --git a/imgui.cpp b/imgui.cpp index a7a9cf98a..57498b8b1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11652,8 +11652,8 @@ static void ImGui::NavUpdate() { const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate)); const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, false)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, false))); - const bool input_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Enter)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput)); - const bool input_pressed = input_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Enter, false)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, false))); + const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_KeyPadEnter))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput)); + const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, false) || IsKeyPressed(ImGuiKey_KeyPadEnter, false))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, false))); if (g.ActiveId == 0 && activate_pressed) { g.NavActivateId = g.NavId; From e265610a0c4143b9abc64c50a3950ddcd0243622 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Dec 2023 18:36:01 +0100 Subject: [PATCH 03/16] Fixes for MSVC code analyzer. --- imgui.cpp | 2 +- imgui_demo.cpp | 2 +- imgui_widgets.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 57498b8b1..f6d3ccf2a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14280,7 +14280,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } }; #else - struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array + struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key >= 0 && key < 512 && GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array //Text("Legacy raw:"); for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key++) { if (io.KeysDown[key]) { SameLine(); Text("\"%s\" %d", GetKeyName(key), key); } } #endif Text("Keys down:"); for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !IsKeyDown(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); SameLine(); Text("(%.02f)", GetKeyData(key)->DownDuration); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 763e0a9e9..94972dd1a 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6098,7 +6098,7 @@ static void ShowDemoWindowInputs() struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } }; ImGuiKey start_key = ImGuiKey_NamedKey_BEGIN; #else - struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array + struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key >= 0 && key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array ImGuiKey start_key = (ImGuiKey)0; #endif ImGui::Text("Keys down:"); for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ac5455b05..8d486d48b 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3925,8 +3925,8 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im if (c < 0x20) { bool pass = false; - pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline)); // Note that an Enter KEY will emit \r and be ignored (we poll for KEY in InputText() code) - pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput)); + pass |= (c == '\n') && (flags & ImGuiInputTextFlags_Multiline) != 0; // Note that an Enter KEY will emit \r and be ignored (we poll for KEY in InputText() code) + pass |= (c == '\t') && (flags & ImGuiInputTextFlags_AllowTabInput) != 0; if (!pass) return false; apply_named_filters = false; // Override named filters below so newline and tabs can still be inserted. From 089ed3032359f7c83c0c608d500c518b359bf25f Mon Sep 17 00:00:00 2001 From: Kevin Coghlan Date: Mon, 18 Dec 2023 23:30:49 +0000 Subject: [PATCH 04/16] Replace usages of ImGuiKey_KeyPadEnter with ImGuiKey_KeypadEnter. (#7143) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f6d3ccf2a..51751da46 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11652,8 +11652,8 @@ static void ImGui::NavUpdate() { const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate)); const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, false)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, false))); - const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_KeyPadEnter))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput)); - const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, false) || IsKeyPressed(ImGuiKey_KeyPadEnter, false))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, false))); + const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_KeypadEnter))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput)); + const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, false) || IsKeyPressed(ImGuiKey_KeypadEnter, false))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, false))); if (g.ActiveId == 0 && activate_pressed) { g.NavActivateId = g.NavId; From 8764a1b7c4f8428e55da52d61f7a6d772bf01008 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 10:51:11 +0100 Subject: [PATCH 05/16] Backends: Vulkan: free FontCommandBuffer explicitely (not actually required in normal code path, unless ImGui_ImplVulkan_DestroyDeviceObjects is declared directly). (#7104) --- backends/imgui_impl_vulkan.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index d58a28cbb..0f36ba8ff 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1021,6 +1021,7 @@ void ImGui_ImplVulkan_DestroyDeviceObjects() ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator); ImGui_ImplVulkan_DestroyFontsTexture(); + if (bd->FontCommandBuffer) { vkFreeCommandBuffers(v->Device, bd->FontCommandPool, 1, &bd->FontCommandBuffer); bd->FontCommandBuffer = VK_NULL_HANDLE; } if (bd->FontCommandPool) { vkDestroyCommandPool(v->Device, bd->FontCommandPool, v->Allocator); bd->FontCommandPool = VK_NULL_HANDLE; } if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; } if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; } From 55073aa7a39c6d9485fa0c1dec854ec654e618d6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 11:22:43 +0100 Subject: [PATCH 06/16] Examples; SDL: added missing return values checks from SDL_CreateWindow() calls. (#7147) --- examples/example_sdl2_directx11/main.cpp | 6 ++++++ examples/example_sdl2_opengl2/main.cpp | 6 ++++++ examples/example_sdl2_opengl3/main.cpp | 6 ++++++ examples/example_sdl2_sdlrenderer2/main.cpp | 5 +++++ examples/example_sdl2_vulkan/main.cpp | 5 +++++ 5 files changed, 28 insertions(+) diff --git a/examples/example_sdl2_directx11/main.cpp b/examples/example_sdl2_directx11/main.cpp index 7c1660591..3275bafde 100644 --- a/examples/example_sdl2_directx11/main.cpp +++ b/examples/example_sdl2_directx11/main.cpp @@ -47,6 +47,12 @@ int main(int, char**) // Setup window SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } + SDL_SysWMinfo wmInfo; SDL_VERSION(&wmInfo.version); SDL_GetWindowWMInfo(window, &wmInfo); diff --git a/examples/example_sdl2_opengl2/main.cpp b/examples/example_sdl2_opengl2/main.cpp index e1451a619..efb28edbc 100644 --- a/examples/example_sdl2_opengl2/main.cpp +++ b/examples/example_sdl2_opengl2/main.cpp @@ -41,6 +41,12 @@ int main(int, char**) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } + SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, gl_context); SDL_GL_SetSwapInterval(1); // Enable vsync diff --git a/examples/example_sdl2_opengl3/main.cpp b/examples/example_sdl2_opengl3/main.cpp index 344f7452d..d748c1360 100644 --- a/examples/example_sdl2_opengl3/main.cpp +++ b/examples/example_sdl2_opengl3/main.cpp @@ -68,6 +68,12 @@ int main(int, char**) SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } + SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, gl_context); SDL_GL_SetSwapInterval(1); // Enable vsync diff --git a/examples/example_sdl2_sdlrenderer2/main.cpp b/examples/example_sdl2_sdlrenderer2/main.cpp index bc7603eeb..bfba8fa6a 100644 --- a/examples/example_sdl2_sdlrenderer2/main.cpp +++ b/examples/example_sdl2_sdlrenderer2/main.cpp @@ -38,6 +38,11 @@ int main(int, char**) // Create window with SDL_Renderer graphics context SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+SDL_Renderer example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); if (renderer == nullptr) { diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 3163446f3..bbd9eec42 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -385,6 +385,11 @@ int main(int, char**) // Create window with Vulkan graphics context SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } ImVector extensions; uint32_t extensions_count = 0; From 70f2aaff430b21fef083cc75b52d47debf2b7b41 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 14 Dec 2023 17:24:47 +0100 Subject: [PATCH 07/16] Nav: tabbing happen within FocusScope. ImGuiWindowFlags_NavFlattened make window inherit focus scope from parent. --- imgui.cpp | 9 +++++++-- imgui.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 51751da46..5af35dfb6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6420,7 +6420,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Add to focus scope stack // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() - PushFocusScope(window->ID); + if ((flags & ImGuiWindowFlags_NavFlattened) == 0) + PushFocusScope(window->ID); window->NavRootFocusScopeId = g.CurrentFocusScopeId; g.CurrentWindow = NULL; @@ -7061,7 +7062,8 @@ void ImGui::End() if (window->DC.CurrentColumns) EndColumns(); PopClipRect(); // Inner window clip rectangle - PopFocusScope(); + if ((window->Flags & ImGuiWindowFlags_NavFlattened) == 0) + PopFocusScope(); // Stop logging if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging @@ -9679,6 +9681,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu // If we crash on a NULL g.NavWindow we need to fix the bug elsewhere. if (!(g.LastItemData.InFlags & ImGuiItemFlags_NoNav)) { + // FIMXE-NAV: investigate changing the window tests into a simple 'if (g.NavFocusScopeId == g.CurrentFocusScopeId)' test. window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent); if (g.NavId == id || g.NavAnyRequest) if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) @@ -11310,6 +11313,8 @@ void ImGui::NavProcessItemForTabbingRequest(ImGuiID id, ImGuiItemFlags item_flag if ((move_flags & ImGuiNavMoveFlags_FocusApi) == 0) if (g.NavLayer != g.CurrentWindow->DC.NavLayerCurrent) return; + if (g.NavFocusScopeId != g.CurrentFocusScopeId) + return; // - Can always land on an item when using API call. // - Tabbing with _NavEnableKeyboard (space/enter/arrows): goes through every item. diff --git a/imgui.h b/imgui.h index 0b7be292d..dc3b50f3d 100644 --- a/imgui.h +++ b/imgui.h @@ -1009,7 +1009,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, // [Internal] - ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. + ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup() From b4c5a83cfe6c204bbff1f8cdabf3abbfea9130e5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 13:52:40 +0100 Subject: [PATCH 08/16] Commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. (#2625, #7143) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 1 + imgui.h | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 731ec4d5b..504a54427 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,7 @@ Breaking changes: Prefer using ImGuiListClipper which can return non-contiguous ranges. - Internals, Columns: commented out legacy ImGuiColumnsFlags_XXX symbols redirecting to ImGuiOldColumnsFlags_XXX, obsoleted from imgui_internal.h in 1.80. +- Commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. (#2625, #7143) Other changes: diff --git a/imgui.cpp b/imgui.cpp index 5af35dfb6..a455b28f0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -424,6 +424,7 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2023/12/19 (1.90.1) - commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. - 2023/11/06 (1.90.1) - removed CalcListClipping() marked obsolete in 1.86. Prefer using ImGuiListClipper which can return non-contiguous ranges. - 2023/11/05 (1.90.1) - imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls. - 2023/11/05 (1.90.1) - internals,columns: commented out legacy ImGuiColumnsFlags_XXX symbols redirecting to ImGuiOldColumnsFlags_XXX, obsoleted from imgui_internal.h in 1.80. diff --git a/imgui.h b/imgui.h index dc3b50f3d..44fab7dc0 100644 --- a/imgui.h +++ b/imgui.h @@ -1430,7 +1430,7 @@ enum ImGuiKey : int #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiKey_ModCtrl = ImGuiMod_Ctrl, ImGuiKey_ModShift = ImGuiMod_Shift, ImGuiKey_ModAlt = ImGuiMod_Alt, ImGuiKey_ModSuper = ImGuiMod_Super, // Renamed in 1.89 - ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter, // Renamed in 1.87 + //ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter, // Renamed in 1.87 #endif }; @@ -2148,7 +2148,7 @@ struct ImGuiIO IMGUI_API void ClearEventsQueue(); // Clear all incoming events. IMGUI_API void ClearInputKeys(); // Clear current keyboard/mouse/gamepad state + current frame text input buffer. Equivalent to releasing all keys/buttons. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - IMGUI_API void ClearInputCharacters(); // [Obsolete] Clear the current frame text input buffer. Now included within ClearInputKeys(). + IMGUI_API void ClearInputCharacters(); // [Obsoleted in 1.89.8] Clear the current frame text input buffer. Now included within ClearInputKeys(). #endif //------------------------------------------------------------------ From 22a7d241ff3bf03f031b07d0422ad66e455efe70 Mon Sep 17 00:00:00 2001 From: Pello Rao Date: Tue, 19 Dec 2023 15:52:44 +0100 Subject: [PATCH 09/16] Backends: GLFW, Emscripten: fixes for canvas resizing. (#6751) --- backends/imgui_impl_glfw.cpp | 47 +++++++++++++++++++ backends/imgui_impl_glfw.h | 5 ++ examples/example_emscripten_wgpu/main.cpp | 3 ++ .../example_glfw_opengl3/Makefile.emscripten | 2 +- examples/example_glfw_opengl3/main.cpp | 7 +++ 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index b3b91dc4a..1d981d9da 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) +// 2023-12-18: Emscripten: Change the size of the GLFW window according to the size of the canvas // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys. // 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609) // 2023-06-12: Accept glfwGetTime() not returning a monotonically increasing value. This seems to happens on some Windows setup when peripherals disconnect, and is likely to also happen on browser + Emscripten. (#6491) @@ -126,6 +127,9 @@ struct ImGui_ImplGlfw_Data ImVec2 LastValidMousePos; bool InstalledCallbacks; bool CallbacksChainForAllWindows; +#ifdef __EMSCRIPTEN__ + const char* CanvasSelector; +#endif // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. GLFWwindowfocusfun PrevUserCallbackWindowFocus; @@ -807,6 +811,49 @@ void ImGui_ImplGlfw_NewFrame() ImGui_ImplGlfw_UpdateGamepads(); } +#ifdef __EMSCRIPTEN__ +static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data) +{ + ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data *) user_data; + + double canvas_width, canvas_height; + emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height); + + glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height); + + return true; +} + +static EM_BOOL ImGui_ImplGlfw_OnFullscreenChange(int event_type, const EmscriptenFullscreenChangeEvent* event, void* user_data) +{ + ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data *) user_data; + + double canvas_width, canvas_height; + emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height); + + glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height); + + return true; +} + +/** + * @param canvas_selector A CSS selector, the event listener is applied to the first element that matches the query. + */ +void ImGui_ImplGlfw_SetEmscriptenCanvasSelector(const char *canvas_selector) +{ + IM_ASSERT(canvas_selector != nullptr); + ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); + IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?"); + bd->CanvasSelector = canvas_selector; + + emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, bd, false, ImGui_ImplGlfw_OnCanvasSizeChange); + emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, bd, false, ImGui_ImplGlfw_OnFullscreenChange); + + // Change the size of the GLFW window according to the size of the canvas + ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd); +} +#endif + //----------------------------------------------------------------------------- #if defined(__clang__) diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index b9a9a40a7..e008e5dea 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -30,6 +30,11 @@ IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool ins IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); +// Emscripten related initialization phase methods +#ifdef __EMSCRIPTEN__ +IMGUI_IMPL_API void ImGui_ImplGlfw_SetEmscriptenCanvasSelector(const char* canvas_selector); +#endif + // GLFW callbacks install // - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any. // - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks. diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index a2126bcd1..b04db9e79 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -26,6 +26,8 @@ static WGPUSwapChain wgpu_swap_chain = nullptr; static int wgpu_swap_chain_width = 0; static int wgpu_swap_chain_height = 0; +const char* canvas_selector = "#canvas"; + // Forward declarations static void MainLoopStep(void* window); static bool InitWGPU(); @@ -76,6 +78,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOther(window, true); + ImGui_ImplGlfw_SetEmscriptenCanvasSelector(canvas_selector); ImGui_ImplWGPU_Init(wgpu_device, 3, wgpu_preferred_fmt, WGPUTextureFormat_Undefined); // Load Fonts diff --git a/examples/example_glfw_opengl3/Makefile.emscripten b/examples/example_glfw_opengl3/Makefile.emscripten index 8ea4eacfc..bd972abff 100644 --- a/examples/example_glfw_opengl3/Makefile.emscripten +++ b/examples/example_glfw_opengl3/Makefile.emscripten @@ -59,7 +59,7 @@ endif CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends #CPPFLAGS += -g CPPFLAGS += -Wall -Wformat -Os $(EMS) -# LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html +LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html LDFLAGS += $(EMS) ##--------------------------------------------------------------------- diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index 212c7fb1a..f36eaf1fd 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -26,9 +26,13 @@ // This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details. #ifdef __EMSCRIPTEN__ +#include +#include #include "../libs/emscripten/emscripten_mainloop_stub.h" #endif +const char* canvas_selector = "#canvas"; + static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "GLFW Error %d: %s\n", error, description); @@ -84,6 +88,9 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOpenGL(window, true); +#ifdef __EMSCRIPTEN__ + ImGui_ImplGlfw_SetEmscriptenCanvasSelector(canvas_selector); +#endif ImGui_ImplOpenGL3_Init(glsl_version); // Load Fonts From 3cb805489b69680af5ad1ac5bc219ea69f12bbd2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 15:57:00 +0100 Subject: [PATCH 10/16] Backends: GLFW, Emscripten: fixes for canvas resizing, amends. (#6751) Amend 22a7d24 --- backends/imgui_impl_glfw.cpp | 25 ++++++++--------------- backends/imgui_impl_glfw.h | 2 +- docs/CHANGELOG.txt | 4 ++++ examples/example_emscripten_wgpu/main.cpp | 4 +--- examples/example_glfw_opengl3/main.cpp | 6 +----- 5 files changed, 16 insertions(+), 25 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 1d981d9da..60723d270 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -20,7 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2023-12-18: Emscripten: Change the size of the GLFW window according to the size of the canvas +// 2023-12-19: Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window. // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys. // 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609) // 2023-06-12: Accept glfwGetTime() not returning a monotonically increasing value. This seems to happens on some Windows setup when peripherals disconnect, and is likely to also happen on browser + Emscripten. (#6491) @@ -814,40 +814,33 @@ void ImGui_ImplGlfw_NewFrame() #ifdef __EMSCRIPTEN__ static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data) { - ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data *) user_data; - + ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data; double canvas_width, canvas_height; emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height); - glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height); - return true; } -static EM_BOOL ImGui_ImplGlfw_OnFullscreenChange(int event_type, const EmscriptenFullscreenChangeEvent* event, void* user_data) +static EM_BOOL ImGui_ImplEmscripten_FullscreenChangeCallback(int event_type, const EmscriptenFullscreenChangeEvent* event, void* user_data) { - ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data *) user_data; - + ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data; double canvas_width, canvas_height; emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height); - glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height); - return true; } -/** - * @param canvas_selector A CSS selector, the event listener is applied to the first element that matches the query. - */ -void ImGui_ImplGlfw_SetEmscriptenCanvasSelector(const char *canvas_selector) +// 'canvas_selector' is a CSS selector. The event listener is applied to the first element that matches the query. +// STRING MUST PERSIST FOR THE APPLICATION DURATION. PLEASE USE A STRING LITERAL OR ENSURE POINTER WILL STAY VALID. +void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { IM_ASSERT(canvas_selector != nullptr); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?"); - bd->CanvasSelector = canvas_selector; + bd->CanvasSelector = canvas_selector; emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, bd, false, ImGui_ImplGlfw_OnCanvasSizeChange); - emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, bd, false, ImGui_ImplGlfw_OnFullscreenChange); + emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, bd, false, ImGui_ImplEmscripten_FullscreenChangeCallback); // Change the size of the GLFW window according to the size of the canvas ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd); diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index e008e5dea..6a9acd05b 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -32,7 +32,7 @@ IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); // Emscripten related initialization phase methods #ifdef __EMSCRIPTEN__ -IMGUI_IMPL_API void ImGui_ImplGlfw_SetEmscriptenCanvasSelector(const char* canvas_selector); +IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector); #endif // GLFW callbacks install diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 504a54427..07115664d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -84,8 +84,12 @@ Other changes: like most printf implementations. (#7016, #3466, #6846) [@codefrog2002] - Misc: Renamed some defines in imstb_textedit.h to avoid conflicts when using unity/jumbo builds on a codebase where another copy of the library is used. +- Backends: GLFW, Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to + register canvas selector and auto-resize GLFW window. (#6751) [@Traveller23, @ypujante] - Backends: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075) [@FoonTheRaccoon] +- Examples: GLFW+Emscripten: Fixed examples not consistently resizing according to host canvas. + (#6751) [@Traveller23, @ypujante] ----------------------------------------------------------------------- diff --git a/examples/example_emscripten_wgpu/main.cpp b/examples/example_emscripten_wgpu/main.cpp index b04db9e79..590453c15 100644 --- a/examples/example_emscripten_wgpu/main.cpp +++ b/examples/example_emscripten_wgpu/main.cpp @@ -26,8 +26,6 @@ static WGPUSwapChain wgpu_swap_chain = nullptr; static int wgpu_swap_chain_width = 0; static int wgpu_swap_chain_height = 0; -const char* canvas_selector = "#canvas"; - // Forward declarations static void MainLoopStep(void* window); static bool InitWGPU(); @@ -78,7 +76,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOther(window, true); - ImGui_ImplGlfw_SetEmscriptenCanvasSelector(canvas_selector); + ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas"); ImGui_ImplWGPU_Init(wgpu_device, 3, wgpu_preferred_fmt, WGPUTextureFormat_Undefined); // Load Fonts diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp index f36eaf1fd..4438fa5bb 100644 --- a/examples/example_glfw_opengl3/main.cpp +++ b/examples/example_glfw_opengl3/main.cpp @@ -26,13 +26,9 @@ // This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details. #ifdef __EMSCRIPTEN__ -#include -#include #include "../libs/emscripten/emscripten_mainloop_stub.h" #endif -const char* canvas_selector = "#canvas"; - static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "GLFW Error %d: %s\n", error, description); @@ -89,7 +85,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForOpenGL(window, true); #ifdef __EMSCRIPTEN__ - ImGui_ImplGlfw_SetEmscriptenCanvasSelector(canvas_selector); + ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback("#canvas"); #endif ImGui_ImplOpenGL3_Init(glsl_version); From 33d426842dffe0e281518e693f0ed3eca33f917d Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 18:25:02 +0100 Subject: [PATCH 11/16] Backends: Vulkan: ImGui_ImplVulkan_CreateFontsTexture() calls vkQueueWaitIdle() instead of vkDeviceWaitIdle(). (#7148, #6943, #6715, #6327, #3743, #4618) --- backends/imgui_impl_vulkan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 0f36ba8ff..94e9a0f7c 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -784,7 +784,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture() err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE); check_vk_result(err); - err = vkDeviceWaitIdle(v->Device); + err = vkQueueWaitIdle(v->Queue); check_vk_result(err); vkDestroyBuffer(v->Device, upload_buffer, v->Allocator); From 0000739c086682e08f9260bda12b7d7961716122 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 20:32:09 +0100 Subject: [PATCH 12/16] Internals: Fixed function name typo. --- imgui.cpp | 6 +++--- imgui_internal.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a455b28f0..af1f23814 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7633,7 +7633,7 @@ void ImGui::SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const I window->HitTestHoleOffset = ImVec2ih(pos - window->Pos); } -void ImGui::SetWindowHiddendAndSkipItemsForCurrentFrame(ImGuiWindow* window) +void ImGui::SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window) { window->Hidden = window->SkipItems = true; window->HiddenFramesCanSkipItems = 1; @@ -10377,7 +10377,7 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext if (window->Active) { // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one. - SetWindowHiddendAndSkipItemsForCurrentFrame(window); + SetWindowHiddenAndSkipItemsForCurrentFrame(window); ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount); } ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize; @@ -12548,7 +12548,7 @@ bool ImGui::BeginTooltipHidden() { ImGuiContext& g = *GImGui; bool ret = Begin("##Tooltip_Hidden", NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize); - SetWindowHiddendAndSkipItemsForCurrentFrame(g.CurrentWindow); + SetWindowHiddenAndSkipItemsForCurrentFrame(g.CurrentWindow); return ret; } diff --git a/imgui_internal.h b/imgui_internal.h index 35c48616e..d796c4b7f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2909,7 +2909,7 @@ namespace ImGui IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size); - IMGUI_API void SetWindowHiddendAndSkipItemsForCurrentFrame(ImGuiWindow* window); + IMGUI_API void SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window); inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); } inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); } inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); } From 0bd6489721328ba28b2bb19088f988ca54a881da Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Dec 2023 20:50:17 +0100 Subject: [PATCH 13/16] DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: fixed multi-components width in tight space (#7120, #7121) + extra tweak color ColorEdit4() label. Amend 86512ea, 3464662 --- imgui.cpp | 4 ++-- imgui_widgets.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index af1f23814..d89e7e26c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9872,10 +9872,10 @@ void ImGui::PushMultiItemsWidths(int components, float w_full) for (int i = components - 1; i > 0; i--) { float next_split = IM_TRUNC(w_items * i / components); - window->DC.ItemWidthStack.push_back(prev_split - next_split); + window->DC.ItemWidthStack.push_back(ImMax(prev_split - next_split, 1.0f)); prev_split = next_split; } - window->DC.ItemWidth = prev_split; + window->DC.ItemWidth = ImMax(prev_split, 1.0f); g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 8d486d48b..abf1f0c18 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5128,8 +5128,6 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag const ImGuiStyle& style = g.Style; const float square_sz = GetFrameHeight(); const float w_full = CalcItemWidth(); - const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); - const float w_inputs = w_full - w_button; const char* label_display_end = FindRenderedTextEnd(label); g.NextItemData.ClearFlags(); @@ -5164,6 +5162,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0; const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0; const int components = alpha ? 4 : 3; + const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); + const float w_inputs = ImMax(w_full - w_button, 1.0f * components); // Convert to the formats we need float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f }; @@ -5211,7 +5211,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if (n > 0) SameLine(0, style.ItemInnerSpacing.x); float next_split = IM_TRUNC(w_items * (n + 1) / components); - SetNextItemWidth(next_split - prev_split); + SetNextItemWidth(ImMax(next_split - prev_split, 1.0f)); prev_split = next_split; // FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0. From 036a6c875ec590bc01a4809756b20bcc96181f74 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 20 Dec 2023 11:06:22 +0100 Subject: [PATCH 14/16] ColorEdit4: Further tweaks for very small sizes. (#7120, #7121) --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 07115664d..97ead430a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -72,6 +72,7 @@ Other changes: to allow passing through multiple widgets easily. (#3092, #5759, #787) - DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components width computation to better distribute the error. (#7120, #7121) [@Nahor] +- ColorEdit4: Layout tweaks for very small sizes. (#7120, #7121) - Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) - Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index abf1f0c18..99d0c6c25 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5127,8 +5127,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const float square_sz = GetFrameHeight(); - const float w_full = CalcItemWidth(); const char* label_display_end = FindRenderedTextEnd(label); + float w_full = CalcItemWidth(); g.NextItemData.ClearFlags(); BeginGroup(); @@ -5163,7 +5163,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0; const int components = alpha ? 4 : 3; const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); - const float w_inputs = ImMax(w_full - w_button, 1.0f * components); + const float w_inputs = ImMax(w_full - w_button, 1.0f); + w_full = w_inputs + w_button; // Convert to the formats we need float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f }; From 1e1013085b227aed162858d956a881c3637dd980 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 20 Dec 2023 15:46:26 +0100 Subject: [PATCH 15/16] Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 97ead430a..8a17ad099 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -76,6 +76,7 @@ Other changes: - Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical movements toward another parent BeginMenu() can keep the wrong child menu open. (#6671, #6926) - Debug Tools: Added DebugFlashStyleColor() to identify a style color. Added to Style Editor. +- Debug Tools: Debug Log: Hide its own clipper log to reduce noise in the output. - Misc: Added IMGUI_USER_H_FILENAME to change the path included when using IMGUI_INCLUDE_IMGUI_USER_H. (#7039) [@bryceberger] - Misc: Rework debug display of texture id in Metrics window to avoid compile-error when diff --git a/imgui.cpp b/imgui.cpp index d89e7e26c..b2c13fc58 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4787,7 +4787,7 @@ void ImGui::NewFrame() g.DebugLocateId = 0; if (g.DebugLogClipperAutoDisableFrames > 0 && --g.DebugLogClipperAutoDisableFrames == 0) { - DebugLog("(Auto-disabled ImGuiDebugLogFlags_EventClipper to avoid spamming)\n"); + DebugLog("(Debug Log: Auto-disabled ImGuiDebugLogFlags_EventClipper after 2 frames)\n"); g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper; } @@ -14939,6 +14939,9 @@ void ImGui::ShowDebugLogWindow(bool* p_open) SetClipboardText(g.DebugLogBuf.c_str()); BeginChild("##log", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Border, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); + const ImGuiDebugLogFlags backup_log_flags = g.DebugLogFlags; + g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper; + ImGuiListClipper clipper; clipper.Begin(g.DebugLogIndex.size()); while (clipper.Step()) @@ -14946,10 +14949,10 @@ void ImGui::ShowDebugLogWindow(bool* p_open) { const char* line_begin = g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no); const char* line_end = g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no); - TextUnformatted(line_begin, line_end); + TextUnformatted(line_begin, line_end); // Display line ImRect text_rect = g.LastItemData.Rect; if (IsItemHovered()) - for (const char* p = line_begin; p <= line_end - 10; p++) + for (const char* p = line_begin; p <= line_end - 10; p++) // Search for 0x???????? identifiers { ImGuiID id = 0; if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1) @@ -14962,6 +14965,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open) p += 10; } } + g.DebugLogFlags = backup_log_flags; if (GetScrollY() >= GetScrollMaxY()) SetScrollHereY(1.0f); EndChild(); From 8340a30d277db0831676eb1e1be7deed2d3ce294 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 20 Dec 2023 16:06:59 +0100 Subject: [PATCH 16/16] Debug: move debug assertion in post-clip code to reduce overhead. (#4796 and more). Amend c80179921 --- imgui.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b2c13fc58..dee32844f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9613,6 +9613,7 @@ void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx) // Advance cursor given item size for layout. // Register minimum needed size so it can extend the bounding box used for auto-fit calculation. // See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different. +// THIS IS IN THE PERFORMANCE CRITICAL PATH. void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) { ImGuiContext& g = *GImGui; @@ -9652,6 +9653,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) // Declare item bounding box for clipping and interaction. // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface // declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. +// THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN) bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags) { ImGuiContext& g = *GImGui; @@ -9666,11 +9668,11 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None; // Note: we don't copy 'g.NextItemData.SelectionUserData' to an hypothetical g.LastItemData.SelectionUserData: since the former is not cleared. - // Directional navigation processing if (id != 0) { KeepAliveID(id); + // Directional navigation processing // Runs prior to clipping early-out // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests @@ -9689,12 +9691,9 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) NavProcessItem(); } - - // [DEBUG] People keep stumbling on this problem and using "" as identifier in the root of a window instead of "##something". - // Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something". - // READ THE FAQ: https://dearimgui.com/faq - IM_ASSERT(id != window->ID && "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!"); } + + // Lightweight clear of SetNextItemXXX data. g.NextItemData.Flags = ImGuiNextItemDataFlags_None; g.NextItemData.ItemFlags = ImGuiItemFlags_None; @@ -9704,7 +9703,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu #endif // Clipping test - // (FIXME: This is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value) + // (this is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value) //const bool is_clipped = IsClippedEx(bb, id); //if (is_clipped) // return false; @@ -9716,12 +9715,20 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu // [DEBUG] #ifndef IMGUI_DISABLE_DEBUG_TOOLS - if (id != 0 && id == g.DebugLocateId) - DebugLocateItemResolveWithLastItem(); -#endif + if (id != 0) + { + if (id == g.DebugLocateId) + DebugLocateItemResolveWithLastItem(); + + // [DEBUG] People keep stumbling on this problem and using "" as identifier in the root of a window instead of "##something". + // Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something". + // READ THE FAQ: https://dearimgui.com/faq + IM_ASSERT(id != window->ID && "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!"); + } //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] //if ((g.LastItemData.InFlags & ImGuiItemFlags_NoNav) == 0) // window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG] +#endif // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) if (is_rect_visible)