From eb72b5a8eeefd41e845dadbb4758e6f341f3f4a9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jul 2024 10:49:22 +0200 Subject: [PATCH 001/548] Backends: SDL3: Update for API changes: SDL_GetGamepads() memory ownership change. (#7807) --- backends/imgui_impl_sdl3.cpp | 6 +++--- docs/CHANGELOG.txt | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 5cd852599604..05718d21cfb0 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -21,7 +21,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-07-18: Update for SDL3 api changes: SDL_GetClipboardText() string ownership change. (#7801) +// 2024-07-22: Update for SDL3 api changes: SDL_GetGamepads() memory ownership change. (#7807) +// 2024-07-18: Update for SDL3 api changes: SDL_GetClipboardText() memory ownership change. (#7801) // 2024-07-15: Update for SDL3 api changes: SDL_GetProperty() change to SDL_GetPointerProperty(). (#7794) // 2024-07-02: Update for SDL3 api changes: SDLK_x renames and SDLK_KP_x removals (#7761, #7762). // 2024-07-01: Update for SDL3 api changes: SDL_SetTextInputRect() changed to SDL_SetTextInputArea(). @@ -639,7 +640,7 @@ static void ImGui_ImplSDL3_UpdateGamepads() { ImGui_ImplSDL3_CloseGamepads(); int sdl_gamepads_count = 0; - SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count); + const SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count); for (int n = 0; n < sdl_gamepads_count; n++) if (SDL_Gamepad* gamepad = SDL_OpenGamepad(sdl_gamepads[n])) { @@ -647,7 +648,6 @@ static void ImGui_ImplSDL3_UpdateGamepads() if (bd->GamepadMode == ImGui_ImplSDL3_GamepadMode_AutoFirst) break; } - SDL_free(sdl_gamepads); bd->WantUpdateGamepadsList = false; } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2e620f79bbbd..49206df8e4dd 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -148,7 +148,8 @@ Other changes: struct description data that a real application would want to use. - Backends: Win32: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768, #4858, #2622) [@Aemony] -- Backends: SDL3: Update for API changes: SDL_GetClipboardText() string ownership change. (#7801) +- Backends: SDL3: Update for API changes: SDL_GetGamepads() memory ownership change. (#7807) +- Backends: SDL3: Update for API changes: SDL_GetClipboardText() memory ownership change. (#7801) - Backends: SDL3: Update for API changes: SDLK_x renames and SDLK_KP_x removals (#7761, #7762) - Backends: SDL3: Update for API changes: SDL_GetProperty() change to SDL_GetPointerProperty(). (#7794) [@wermipls] - Backends: SDL2,SDL3,OSX: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() rename. From da3633632191d52f40d4dc26184c3cd9c2a0d0a7 Mon Sep 17 00:00:00 2001 From: Thomas Stehle Date: Mon, 22 Jul 2024 10:52:53 +0200 Subject: [PATCH 002/548] TabBar, Style: added style option for the size of the Tab-Bar Overline (#7804) Amend 21bda2e. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 5 ++++- imgui.h | 4 +++- imgui_demo.cpp | 2 ++ imgui_widgets.cpp | 4 ++-- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 49206df8e4dd..22f2b5e229bb 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -139,6 +139,8 @@ Other changes: can use the clipper without knowing the amount of items beforehand. (#1311) In this situation, call ImGuiListClipper::SeekCursorForItem(items_count) as the end of your iteration loop to position the layout cursor correctly. This is done automatically if provided a count to Begin(). +- TabBar, Style: added style.TabBarOverlineSize / ImGuiStyleVar_TabBarOverlineSize to manipulate + thickness of the horizontal line over selectable tabs. [@DctrNoob] - Style: close button and collapse/window-menu button hover highlight made rectangular instead of round. - Debug Tools: Added IMGUI_DEBUG_LOG(), ImGui::DebugLog() in public API. (#5855) Debug log entries add a imgui frame counter prefix + are redirected to ShowDebugLogWindow() and diff --git a/imgui.cpp b/imgui.cpp index 6eb38f70875d..21b1cf14a0d6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1269,12 +1269,13 @@ ImGuiStyle::ImGuiStyle() TabBorderSize = 0.0f; // Thickness of border around tabs. TabMinWidthForCloseButton = 0.0f; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. TabBarBorderSize = 1.0f; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. + TabBarOverlineSize = 2.0f; // Thickness of tab-bar overline, which highlights the selected tab-bar. TableAngledHeadersAngle = 35.0f * (IM_PI / 180.0f); // Angle of angled headers (supported values range from -50 degrees to +50 degrees). TableAngledHeadersTextAlign = ImVec2(0.5f,0.0f);// Alignment of angled headers within the cell ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text. SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. - SeparatorTextBorderSize = 3.0f; // Thickkness of border in SeparatorText() + SeparatorTextBorderSize = 3.0f; // Thickness of border in SeparatorText() SeparatorTextAlign = ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center). SeparatorTextPadding = ImVec2(20.0f,3.f);// Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y. DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows. @@ -1321,6 +1322,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor) LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor); TabRounding = ImTrunc(TabRounding * scale_factor); TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImTrunc(TabMinWidthForCloseButton * scale_factor) : FLT_MAX; + TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor); SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor); DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor); DisplaySafeAreaPadding = ImTrunc(DisplaySafeAreaPadding * scale_factor); @@ -3274,6 +3276,7 @@ static const ImGuiDataVarInfo GStyleVarInfo[] = { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBorderSize) }, // ImGuiStyleVar_TabBorderSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarBorderSize) }, // ImGuiStyleVar_TabBarBorderSize + { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarOverlineSize) }, // ImGuiStyleVar_TabBarOverlineSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersAngle)}, // ImGuiStyleVar_TableAngledHeadersAngle { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign diff --git a/imgui.h b/imgui.h index 6c49460e104c..993906a00ca5 100644 --- a/imgui.h +++ b/imgui.h @@ -1711,6 +1711,7 @@ enum ImGuiStyleVar_ ImGuiStyleVar_TabRounding, // float TabRounding ImGuiStyleVar_TabBorderSize, // float TabBorderSize ImGuiStyleVar_TabBarBorderSize, // float TabBarBorderSize + ImGuiStyleVar_TabBarOverlineSize, // float TabBarOverlineSize ImGuiStyleVar_TableAngledHeadersAngle, // float TableAngledHeadersAngle ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign @@ -2154,12 +2155,13 @@ struct ImGuiStyle float TabBorderSize; // Thickness of border around tabs. float TabMinWidthForCloseButton; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. float TabBarBorderSize; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. + float TabBarOverlineSize; // Thickness of tab-bar overline, which highlights the selected tab-bar. float TableAngledHeadersAngle; // Angle of angled headers (supported values range from -50.0f degrees to +50.0f degrees). ImVec2 TableAngledHeadersTextAlign;// Alignment of angled headers within the cell ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered). ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. - float SeparatorTextBorderSize; // Thickkness of border in SeparatorText() + float SeparatorTextBorderSize; // Thickness of border in SeparatorText() ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center). ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y. ImVec2 DisplayWindowPadding; // Apply to regular windows: amount which we enforce to keep visible when moving near edges of your screen. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fb28e3d54d91..e43bdc2b30b6 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7633,6 +7633,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("TabBarBorderSize", &style.TabBarBorderSize, 0.0f, 2.0f, "%.0f"); + ImGui::SliderFloat("TabBarOverlineSize", &style.TabBarOverlineSize, 0.0f, 2.0f, "%.0f"); + ImGui::SameLine(); HelpMarker("Overline is only drawn over the selected tab when ImGuiTabBarFlags_DrawSelectedOverline is set."); ImGui::SeparatorText("Rounding"); ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f"); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 29635d3ebf4e..e41f2f3cdfd3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -9917,13 +9917,13 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImDrawList* display_draw_list = window->DrawList; const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabSelected : ImGuiCol_TabDimmedSelected) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabDimmed)); TabItemBackground(display_draw_list, bb, flags, tab_col); - if (tab_contents_visible && (tab_bar->Flags & ImGuiTabBarFlags_DrawSelectedOverline)) + if (tab_contents_visible && (tab_bar->Flags & ImGuiTabBarFlags_DrawSelectedOverline) && style.TabBarOverlineSize > 0.0f) { float x_offset = IM_TRUNC(0.4f * style.TabRounding); if (x_offset < 2.0f * g.CurrentDpiScale) x_offset = 0.0f; float y_offset = 1.0f * g.CurrentDpiScale; - display_draw_list->AddLine(bb.GetTL() + ImVec2(x_offset, y_offset), bb.GetTR() + ImVec2(-x_offset, y_offset), GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline), 2.0f * g.CurrentDpiScale); + display_draw_list->AddLine(bb.GetTL() + ImVec2(x_offset, y_offset), bb.GetTR() + ImVec2(-x_offset, y_offset), GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline), style.TabBarOverlineSize); } RenderNavHighlight(bb, id); From fd994943c2dd70978d3c89c98d03fe5124e6a503 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jul 2024 11:05:46 +0200 Subject: [PATCH 003/548] Added a comment hinting at how to set IMGUI_API for shared librairies on e.g. Linux, macOS (#7806) --- imconfig.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imconfig.h b/imconfig.h index 62365fb9bd0f..6e4c743d4ed9 100644 --- a/imconfig.h +++ b/imconfig.h @@ -21,10 +21,11 @@ //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. -// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() -// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. -//#define IMGUI_API __declspec( dllexport ) -//#define IMGUI_API __declspec( dllimport ) +// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() +// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. +//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export +//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import +//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names. //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS From c3dca77a19722d7ec0d2f7dfc1238b5166af2d46 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jul 2024 14:06:14 +0200 Subject: [PATCH 004/548] Demo: rework Property Editor. --- docs/CHANGELOG.txt | 3 +- imgui.cpp | 6 ++ imgui.h | 4 +- imgui_demo.cpp | 163 +++++++++++++++++++++++++-------------------- 4 files changed, 101 insertions(+), 75 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 22f2b5e229bb..aad367e505d0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -98,8 +98,7 @@ Other changes: - A helper ImGuiSelectionBasicStorage is provided to facilitate getting started in a typical app. - Documentation: - Wiki page https://github.com/ocornut/imgui/wiki/Multi-Select for API overview. - - Demo code. - - Headers are well commented. + - Demo code + headers are well commented. - Added BeginMultiSelect(), EndMultiSelect(), SetNextItemSelectionUserData(). - Added IsItemToggledSelection() for use if you need latest selection update during currnet iteration. - Added ImGuiMultiSelectIO and ImGuiSelectionRequest structures: diff --git a/imgui.cpp b/imgui.cpp index 21b1cf14a0d6..c7b83d849db8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15710,6 +15710,12 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "", (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); + if (flags & ImGuiWindowFlags_ChildWindow) + BulletText("ChildFlags: 0x%08X (%s%s%s%s..)", window->ChildFlags, + (window->ChildFlags & ImGuiChildFlags_Border) ? "Border " : "", + (window->ChildFlags & ImGuiChildFlags_ResizeX) ? "ResizeX " : "", + (window->ChildFlags & ImGuiChildFlags_ResizeY) ? "ResizeY " : "", + (window->ChildFlags & ImGuiChildFlags_NavFlattened) ? "NavFlattened " : ""); BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y, window->ScrollbarX ? "X" : "", window->ScrollbarY ? "Y" : ""); BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1); BulletText("Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems); diff --git a/imgui.h b/imgui.h index 993906a00ca5..0bf02b0466b2 100644 --- a/imgui.h +++ b/imgui.h @@ -1090,7 +1090,7 @@ enum ImGuiWindowFlags_ // Obsolete names #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call. + ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90.0: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call. ImGuiWindowFlags_NavFlattened = 1 << 31, // Obsoleted in 1.90.9: Use ImGuiChildFlags_NavFlattened in BeginChild() call. #endif }; @@ -1115,7 +1115,7 @@ enum ImGuiChildFlags_ ImGuiChildFlags_AutoResizeY = 1 << 5, // Enable auto-resizing height. Read "IMPORTANT: Size measurement" details above. ImGuiChildFlags_AlwaysAutoResize = 1 << 6, // Combined with AutoResizeX/AutoResizeY. Always measure size even when child is hidden, always return true, always disable clipping optimization! NOT RECOMMENDED. ImGuiChildFlags_FrameStyle = 1 << 7, // Style the child window like a framed item: use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding. - ImGuiChildFlags_NavFlattened = 1 << 8, // Share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. + ImGuiChildFlags_NavFlattened = 1 << 8, // [BETA] Share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. }; // Flags for ImGui::PushItemFlag() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e43bdc2b30b6..f91cc8532ed8 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -269,7 +269,7 @@ struct ExampleTreeNode // Leaf Data bool HasData = false; // All leaves have data - bool DataMyBool = false; + bool DataMyBool = true; int DataMyInt = 128; ImVec2 DataMyVec2 = ImVec2(0.0f, 3.141592f); }; @@ -304,6 +304,7 @@ static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, Exampl } // Create example tree data +// (this allocates _many_ more times than most other code in either Dear ImGui or others demo) static ExampleTreeNode* ExampleTree_CreateDemoTree() { static const char* root_names[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; @@ -8600,101 +8601,121 @@ static void ShowExampleAppLayout(bool* p_open) // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor() //----------------------------------------------------------------------------- // Some of the interactions are a bit lack-luster: -// - We would want the table scrolling window to use NavFlattened. // - We would want pressing validating or leaving the filter to somehow restore focus. // - We may want more advanced filtering (child nodes) and clipper support: both will need extra work. +// - We would want to customize some keyboard interactions to easily keyboard navigate between the tree and the properties. //----------------------------------------------------------------------------- struct ExampleAppPropertyEditor { ImGuiTextFilter Filter; + ExampleTreeNode* VisibleNode = NULL; void Draw(ExampleTreeNode* root_node) { - ImGui::SetNextItemWidth(-FLT_MIN); - ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip); - ImGui::PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true); - if (ImGui::InputTextWithHint("##Filter", "incl,-excl", Filter.InputBuf, IM_ARRAYSIZE(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll)) - Filter.Build(); - ImGui::PopItemFlag(); + // Left side: draw tree + // - Currently using a table to benefit from RowBg feature + // - Using ImGuiChildFlags_NavFlattened exhibit a bug where clicking on root window decoration sets focus to root window + if (ImGui::BeginChild("##tree", ImVec2(300, 0), ImGuiChildFlags_ResizeX | ImGuiChildFlags_Border)) + { + ImGui::SetNextItemWidth(-FLT_MIN); + ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip); + ImGui::PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true); + if (ImGui::InputTextWithHint("##Filter", "incl,-excl", Filter.InputBuf, IM_ARRAYSIZE(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll)) + Filter.Build(); + ImGui::PopItemFlag(); - ImGuiTableFlags table_flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg; - if (ImGui::BeginTable("##split", 2, table_flags)) + if (ImGui::BeginTable("##bg", 1, ImGuiTableFlags_RowBg)) + { + for (ExampleTreeNode* node : root_node->Childs) + if (Filter.PassFilter(node->Name)) // Filter root node + DrawTreeNode(node); + ImGui::EndTable(); + } + } + ImGui::EndChild(); + + // Right side: draw properties + ImGui::SameLine(); + + ImGui::BeginGroup(); // Lock X position + if (ExampleTreeNode* node = VisibleNode) { - ImGui::TableSetupColumn("Object", ImGuiTableColumnFlags_WidthStretch, 1.0f); - ImGui::TableSetupColumn("Contents", ImGuiTableColumnFlags_WidthStretch, 2.0f); // Default twice larger - //ImGui::TableSetupScrollFreeze(0, 1); - //ImGui::TableHeadersRow(); + ImGui::Text("%s", node->Name); + ImGui::TextDisabled("UID: 0x%08X", node->UID); + ImGui::Separator(); + if (ImGui::BeginTable("##properties", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY)) + { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 2.0f); // Default twice larger - for (ExampleTreeNode* node : root_node->Childs) - if (Filter.PassFilter(node->Name)) // Filter root node - DrawTreeNode(node); - ImGui::EndTable(); + if (node && node->HasData) + { + // In a typical application, the structure description would be derived from a data-driven system. + // - We try to mimic this with our ExampleMemberInfo structure and the ExampleTreeNodeMemberInfos[] array. + // - Limits and some details are hard-coded to simplify the demo. + for (const ExampleMemberInfo& field_desc : ExampleTreeNodeMemberInfos) + { + ImGui::TableNextRow(); + ImGui::PushID(field_desc.Name); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(field_desc.Name); + ImGui::TableNextColumn(); + void* field_ptr = (void*)(((unsigned char*)node) + field_desc.Offset); + switch (field_desc.DataType) + { + case ImGuiDataType_Bool: + { + IM_ASSERT(field_desc.DataCount == 1); + ImGui::Checkbox("##Editor", (bool*)field_ptr); + break; + } + case ImGuiDataType_S32: + { + int v_min = INT_MIN, v_max = INT_MAX; + ImGui::SetNextItemWidth(-FLT_MIN); + ImGui::DragScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, 1.0f, &v_min, &v_max); + break; + } + case ImGuiDataType_Float: + { + float v_min = 0.0f, v_max = 1.0f; + ImGui::SetNextItemWidth(-FLT_MIN); + ImGui::SliderScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, &v_min, &v_max); + break; + } + } + ImGui::PopID(); + } + } + ImGui::EndTable(); + } } + ImGui::EndGroup(); } void DrawTreeNode(ExampleTreeNode* node) { - // Object tree node - ImGui::PushID(node->UID); ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::AlignTextToFramePadding(); + ImGui::TableNextColumn(); + ImGui::PushID(node->UID); ImGuiTreeNodeFlags tree_flags = ImGuiTreeNodeFlags_None; - tree_flags |= ImGuiTreeNodeFlags_SpanAllColumns | ImGuiTreeNodeFlags_AllowOverlap; // Highlight whole row for visibility tree_flags |= ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; // Standard opening mode as we are likely to want to add selection afterwards tree_flags |= ImGuiTreeNodeFlags_NavLeftJumpsBackHere; // Left arrow support - bool node_open = ImGui::TreeNodeEx("##Object", tree_flags, "%s", node->Name); - ImGui::TableSetColumnIndex(1); - ImGui::TextDisabled("UID: 0x%08X", node->UID); - - // Display child and data + if (node == VisibleNode) + tree_flags |= ImGuiTreeNodeFlags_Selected; + if (node->Childs.Size == 0) + tree_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet; + if (node->DataMyBool == false) + ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]); + bool node_open = ImGui::TreeNodeEx("", tree_flags, "%s", node->Name); + if (node->DataMyBool == false) + ImGui::PopStyleColor(); + if (ImGui::IsItemFocused()) + VisibleNode = node; if (node_open) for (ExampleTreeNode* child : node->Childs) DrawTreeNode(child); - if (node_open && node->HasData) - { - // In a typical application, the structure description would be derived from a data-driven system. - // - We try to mimic this with our ExampleMemberInfo structure and the ExampleTreeNodeMemberInfos[] array. - // - Limits and some details are hard-coded to simplify the demo. - // - Text and Selectable are less high than framed widgets, using AlignTextToFramePadding() we add vertical spacing to make the selectable lines equal high. - for (const ExampleMemberInfo& field_desc : ExampleTreeNodeMemberInfos) - { - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - ImGui::AlignTextToFramePadding(); - ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop | ImGuiItemFlags_NoNav, true); - ImGui::Selectable(field_desc.Name, false, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap); - ImGui::PopItemFlag(); - ImGui::TableSetColumnIndex(1); - ImGui::PushID(field_desc.Name); - void* field_ptr = (void*)(((unsigned char*)node) + field_desc.Offset); - switch (field_desc.DataType) - { - case ImGuiDataType_Bool: - { - IM_ASSERT(field_desc.DataCount == 1); - ImGui::Checkbox("##Editor", (bool*)field_ptr); - break; - } - case ImGuiDataType_S32: - { - int v_min = INT_MIN, v_max = INT_MAX; - ImGui::SetNextItemWidth(-FLT_MIN); - ImGui::DragScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, 1.0f, &v_min, &v_max); - break; - } - case ImGuiDataType_Float: - { - float v_min = 0.0f, v_max = 1.0f; - ImGui::SetNextItemWidth(-FLT_MIN); - ImGui::SliderScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, &v_min, &v_max); - break; - } - } - ImGui::PopID(); - } - } if (node_open) ImGui::TreePop(); ImGui::PopID(); From 97ff9bd37038d2c00372eeb7438964e59cc53c7e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jul 2024 15:04:25 +0200 Subject: [PATCH 005/548] Nav: fixed c licking window decorations (e.g. resize borders) from losing focused item when within a child window using ImGuiChildFlags_NavFlattened. In essence, using ImGuiFocusRequestFlags_RestoreFocusedChild here is a way to reduce changes caused by FocusWindow(), but it could be done more neatly. See amended "nav_flattened" test. --- docs/CHANGELOG.txt | 2 ++ imgui.h | 2 +- imgui_widgets.cpp | 18 +++++++++++++++--- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index aad367e505d0..150c2b609402 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -134,6 +134,8 @@ Other changes: - Multi-Select (checkboxes) - Multi-Select (multiple scopes) - Multi-Select (advanced) +- Nav: fixed clicking window decorations (e.g. resize borders) from losing focused item when + within a child window using ImGuiChildFlags_NavFlattened. - Clipper: added SeekCursorForItem() function. When using ImGuiListClipper::Begin(INT_MAX) you can can use the clipper without knowing the amount of items beforehand. (#1311) In this situation, call ImGuiListClipper::SeekCursorForItem(items_count) as the end of your iteration diff --git a/imgui.h b/imgui.h index 0bf02b0466b2..fd0768a22b79 100644 --- a/imgui.h +++ b/imgui.h @@ -28,7 +28,7 @@ // 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 WIP" -#define IMGUI_VERSION_NUM 19097 +#define IMGUI_VERSION_NUM 19098 #define IMGUI_HAS_TABLE /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e41f2f3cdfd3..9a63a59bf9b3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -567,8 +567,14 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool SetActiveID(id, window); g.ActiveIdMouseButton = mouse_button_clicked; if (!(flags & ImGuiButtonFlags_NoNavFocus)) + { SetFocusID(id, window); - FocusWindow(window); + FocusWindow(window); + } + else + { + FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child + } } if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseClickedCount[mouse_button_clicked] == 2)) { @@ -577,10 +583,16 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool ClearActiveID(); else SetActiveID(id, window); // Hold on ID + g.ActiveIdMouseButton = mouse_button_clicked; if (!(flags & ImGuiButtonFlags_NoNavFocus)) + { SetFocusID(id, window); - g.ActiveIdMouseButton = mouse_button_clicked; - FocusWindow(window); + FocusWindow(window); + } + else + { + FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child + } } } if (flags & ImGuiButtonFlags_PressedOnRelease) From 605c8d711019dd6eb98e8e1fbfe1b844410dda52 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 22 Jul 2024 15:05:15 +0200 Subject: [PATCH 006/548] Demo: Property Editor: using ImGuiChildFlags_NavFlattened now that a bug is fixed. Fixed static analyzer. --- imgui_demo.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index f91cc8532ed8..7a3cdf0f40c0 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8615,8 +8615,7 @@ struct ExampleAppPropertyEditor { // Left side: draw tree // - Currently using a table to benefit from RowBg feature - // - Using ImGuiChildFlags_NavFlattened exhibit a bug where clicking on root window decoration sets focus to root window - if (ImGui::BeginChild("##tree", ImVec2(300, 0), ImGuiChildFlags_ResizeX | ImGuiChildFlags_Border)) + if (ImGui::BeginChild("##tree", ImVec2(300, 0), ImGuiChildFlags_ResizeX | ImGuiChildFlags_Border | ImGuiChildFlags_NavFlattened)) { ImGui::SetNextItemWidth(-FLT_MIN); ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip); @@ -8648,8 +8647,7 @@ struct ExampleAppPropertyEditor { ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 2.0f); // Default twice larger - - if (node && node->HasData) + if (node->HasData) { // In a typical application, the structure description would be derived from a data-driven system. // - We try to mimic this with our ExampleMemberInfo structure and the ExampleTreeNodeMemberInfos[] array. @@ -8714,10 +8712,11 @@ struct ExampleAppPropertyEditor if (ImGui::IsItemFocused()) VisibleNode = node; if (node_open) + { for (ExampleTreeNode* child : node->Childs) DrawTreeNode(child); - if (node_open) ImGui::TreePop(); + } ImGui::PopID(); } }; From fe09ebbe0a1c8bb5f39f326658faa6bde75bb568 Mon Sep 17 00:00:00 2001 From: Cyao <94928179+cheyao@users.noreply.github.com> Date: Mon, 22 Jul 2024 21:10:35 +0200 Subject: [PATCH 007/548] Backends: OpenGL3: Fixed unsupported option warning with apple clang (#7810) --- backends/imgui_impl_opengl3.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index bbe96c420fdd..7087a7c5706d 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -124,6 +124,7 @@ // Clang/GCC warnings with -Weverything #if defined(__clang__) #pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: ignore unknown flags #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness #pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used From 4d8c56c8133511b467bcba6483bc75b5a63ab985 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jul 2024 13:40:23 +0200 Subject: [PATCH 008/548] Internals, TreeNode: indent all render block into its own scope (aim is to add a is_visible test there later) --- imgui.cpp | 1 + imgui_widgets.cpp | 97 ++++++++++++++++++++++++----------------------- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c7b83d849db8..52fa2f16f26f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12048,6 +12048,7 @@ void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavM { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindow != NULL); + //IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequestSubmit: dir %c, window \"%s\"\n", "-WENS"[move_dir + 1], g.NavWindow->Name); if (move_flags & ImGuiNavMoveFlags_IsTabbing) move_flags |= ImGuiNavMoveFlags_AllowCurrentNavId; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 9a63a59bf9b3..70ff174c2e1c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6410,6 +6410,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags if ((flags & (ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanTextWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0) interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f); + // Compute open and multi-select states before ItemAdd() as it clear NextItem data. + bool is_open = TreeNodeUpdateNextOpen(storage_id, flags); + // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. const float backup_clip_rect_min_x = window->ClipRect.Min.x; const float backup_clip_rect_max_x = window->ClipRect.Max.x; @@ -6418,18 +6421,14 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags window->ClipRect.Min.x = window->ParentWorkRect.Min.x; window->ClipRect.Max.x = window->ParentWorkRect.Max.x; } - - // Compute open and multi-select states before ItemAdd() as it clear NextItem data. - bool is_open = TreeNodeUpdateNextOpen(storage_id, flags); - bool item_add = ItemAdd(interact_bb, id); - g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; - g.LastItemData.DisplayRect = frame_bb; - + const bool is_visible = ItemAdd(interact_bb, id); if (span_all_columns) { window->ClipRect.Min.x = backup_clip_rect_min_x; window->ClipRect.Max.x = backup_clip_rect_max_x; } + g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; + g.LastItemData.DisplayRect = frame_bb; // If a NavLeft request is happening and ImGuiTreeNodeFlags_NavLeftJumpsBackHere enabled: // Store data for the current depth to allow returning to this node from any child item. @@ -6444,7 +6443,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags } const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; - if (!item_add) + if (!is_visible) { if (store_tree_node_stack_data && is_open) TreeNodeStoreStackData(flags); // Call before TreePushOverrideID() @@ -6566,52 +6565,54 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection; // Render - const ImU32 text_col = GetColorU32(ImGuiCol_Text); - ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact; - if (is_multi_select) - nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle - if (display_frame) { - // Framed type - const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding); - RenderNavHighlight(frame_bb, id, nav_highlight_flags); - if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col); - else if (!is_leaf) - RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 1.0f); - else // Leaf without bullet, left-adjusted text - text_pos.x -= text_offset_x -padding.x; - if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton) - frame_bb.Max.x -= g.FontSize + style.FramePadding.x; - if (g.LogEnabled) - LogSetNextTextDecoration("###", "###"); - } - else - { - // Unframed typed for tree nodes - if (hovered || selected) + const ImU32 text_col = GetColorU32(ImGuiCol_Text); + ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact; + if (is_multi_select) + nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle + if (display_frame) { + // Framed type const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false); + RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding); + RenderNavHighlight(frame_bb, id, nav_highlight_flags); + if (flags & ImGuiTreeNodeFlags_Bullet) + RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col); + else if (!is_leaf) + RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 1.0f); + else // Leaf without bullet, left-adjusted text + text_pos.x -= text_offset_x - padding.x; + if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton) + frame_bb.Max.x -= g.FontSize + style.FramePadding.x; + if (g.LogEnabled) + LogSetNextTextDecoration("###", "###"); + } + else + { + // Unframed typed for tree nodes + if (hovered || selected) + { + const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); + RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false); + } + RenderNavHighlight(frame_bb, id, nav_highlight_flags); + if (flags & ImGuiTreeNodeFlags_Bullet) + RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col); + else if (!is_leaf) + RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 0.70f); + if (g.LogEnabled) + LogSetNextTextDecoration(">", NULL); } - RenderNavHighlight(frame_bb, id, nav_highlight_flags); - if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col); - else if (!is_leaf) - RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 0.70f); - if (g.LogEnabled) - LogSetNextTextDecoration(">", NULL); - } - if (span_all_columns) - TablePopBackgroundChannel(); + if (span_all_columns) + TablePopBackgroundChannel(); - // Label - if (display_frame) - RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); - else - RenderText(text_pos, label, label_end, false); + // Label + if (display_frame) + RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); + else + RenderText(text_pos, label, label_end, false); + } if (store_tree_node_stack_data && is_open) TreeNodeStoreStackData(flags); // Call before TreePushOverrideID() From 1230b4410cd0e0111dd85f7c20e2606208dc1a99 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jul 2024 14:11:26 +0200 Subject: [PATCH 009/548] Internals, TreeNode, Selectable: tweak span_all_columns paths for clarity. --- imgui_widgets.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 70ff174c2e1c..c01a894604f8 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6413,20 +6413,22 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags // Compute open and multi-select states before ItemAdd() as it clear NextItem data. bool is_open = TreeNodeUpdateNextOpen(storage_id, flags); - // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. - const float backup_clip_rect_min_x = window->ClipRect.Min.x; - const float backup_clip_rect_max_x = window->ClipRect.Max.x; + bool is_visible; if (span_all_columns) { + // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. + const float backup_clip_rect_min_x = window->ClipRect.Min.x; + const float backup_clip_rect_max_x = window->ClipRect.Max.x; window->ClipRect.Min.x = window->ParentWorkRect.Min.x; window->ClipRect.Max.x = window->ParentWorkRect.Max.x; - } - const bool is_visible = ItemAdd(interact_bb, id); - if (span_all_columns) - { + is_visible = ItemAdd(interact_bb, id); window->ClipRect.Min.x = backup_clip_rect_min_x; window->ClipRect.Max.x = backup_clip_rect_max_x; } + else + { + is_visible = ItemAdd(interact_bb, id); + } g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; g.LastItemData.DisplayRect = frame_bb; @@ -6796,23 +6798,24 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl } //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(0, 255, 0, 255)); } - // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. - const float backup_clip_rect_min_x = window->ClipRect.Min.x; - const float backup_clip_rect_max_x = window->ClipRect.Max.x; + const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0; + const ImGuiItemFlags extra_item_flags = disabled_item ? (ImGuiItemFlags)ImGuiItemFlags_Disabled : ImGuiItemFlags_None; + bool is_visible; if (span_all_columns) { + // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. + const float backup_clip_rect_min_x = window->ClipRect.Min.x; + const float backup_clip_rect_max_x = window->ClipRect.Max.x; window->ClipRect.Min.x = window->ParentWorkRect.Min.x; window->ClipRect.Max.x = window->ParentWorkRect.Max.x; - } - - const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0; - const bool is_visible = ItemAdd(bb, id, NULL, disabled_item ? (ImGuiItemFlags)ImGuiItemFlags_Disabled : ImGuiItemFlags_None); - - if (span_all_columns) - { + is_visible = ItemAdd(bb, id, NULL, extra_item_flags); window->ClipRect.Min.x = backup_clip_rect_min_x; window->ClipRect.Max.x = backup_clip_rect_max_x; } + else + { + is_visible = ItemAdd(bb, id, NULL, extra_item_flags); + } const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0; if (!is_visible) From 97c6f4047ccc01367e29f6852e9cecf1e157d26b Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jul 2024 14:16:41 +0200 Subject: [PATCH 010/548] CollapsingHeader: left-side outer extend matches right-side one (moved left by one pixel) Amend c3a348aa2 --- imgui_widgets.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c01a894604f8..068337e9c95e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6396,10 +6396,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags frame_bb.Max.y = window->DC.CursorPos.y + frame_height; if (display_frame) { - // Framed header expand a little outside the default padding, to the edge of InnerClipRect - // (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f) - frame_bb.Min.x -= IM_TRUNC(window->WindowPadding.x * 0.5f - 1.0f); - frame_bb.Max.x += IM_TRUNC(window->WindowPadding.x * 0.5f); + const float outer_extend = IM_TRUNC(window->WindowPadding.x * 0.5f); // Framed header expand a little outside of current limits + frame_bb.Min.x -= outer_extend; + frame_bb.Max.x += outer_extend; } ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y); @@ -6783,7 +6782,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl const ImVec2 text_max(min_x + size.x, pos.y + size.y); // Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable. - // FIXME: Not part of layout so not included in clipper calculation, but ItemSize currenty doesn't allow offsetting CursorPos. + // FIXME: Not part of layout so not included in clipper calculation, but ItemSize currently doesn't allow offsetting CursorPos. ImRect bb(min_x, pos.y, text_max.x, text_max.y); if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0) { From b67b375ae693072ba23963f7897057e76f3a7327 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jul 2024 15:28:03 +0200 Subject: [PATCH 011/548] Debug Log: fixed incorrect checkbox layout when partially clipped., doesn't parse 64-bits hex value as ImGuiID lookups. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 4 ++-- imgui_internal.h | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 150c2b609402..1247ef94ae71 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -147,6 +147,7 @@ Other changes: Debug log entries add a imgui frame counter prefix + are redirected to ShowDebugLogWindow() and other configurable locations. Always call IMGUI_DEBUG_LOG() for maximum stripping in caller code. - Debug Tools: Debug Log: Added "Configure Outputs.." button. (#5855) +- Debug Tools: Debug Log: Fixed incorrect checkbox layout when partially clipped. - Demo: Reworked "Property Editor" demo in a manner that more ressemble the tree data and struct description data that a real application would want to use. - Backends: Win32: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. diff --git a/imgui.cpp b/imgui.cpp index 52fa2f16f26f..7b922fdd7606 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15827,7 +15827,7 @@ static void SameLineOrWrap(const ImVec2& size) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImVec2 pos(window->DC.CursorPosPrevLine.x + g.Style.ItemSpacing.x, window->DC.CursorPosPrevLine.y); - if (window->ClipRect.Contains(ImRect(pos, pos + size))) + if (window->WorkRect.Contains(ImRect(pos, pos + size))) ImGui::SameLine(); } @@ -15921,7 +15921,7 @@ void ImGui::DebugTextUnformattedWithLocateItem(const char* line_begin, const cha for (const char* p = line_begin; p <= line_end - 10; p++) { ImGuiID id = 0; - if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1) + if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1 || ImCharIsXdigitA(p[10])) continue; ImVec2 p0 = CalcTextSize(line_begin, p); ImVec2 p1 = CalcTextSize(p, p + 10); diff --git a/imgui_internal.h b/imgui_internal.h index f2c5312eadac..b307adcde7a6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -388,6 +388,7 @@ IM_MSVC_RUNTIME_CHECKS_OFF static inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c &= ~32 : c; } static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; } static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } +static inline bool ImCharIsXdigitA(char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); } IM_MSVC_RUNTIME_CHECKS_RESTORE // Helpers: Formatting From e3da939b86f8cbf30a4d3e39b0cab2413c67dd03 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jul 2024 18:41:51 +0200 Subject: [PATCH 012/548] Groups, Tables: fixed EndGroup() failing to correctly capture current table occupied size. (#7543) See "layout_group_endtable" test. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 8 ++++---- imgui.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1247ef94ae71..fde5c5144e90 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -140,6 +140,7 @@ Other changes: can use the clipper without knowing the amount of items beforehand. (#1311) In this situation, call ImGuiListClipper::SeekCursorForItem(items_count) as the end of your iteration loop to position the layout cursor correctly. This is done automatically if provided a count to Begin(). +- Groups, Tables: fixed EndGroup() failing to correctly capture current table occupied size. (#7543) - TabBar, Style: added style.TabBarOverlineSize / ImGuiStyleVar_TabBarOverlineSize to manipulate thickness of the horizontal line over selectable tabs. [@DctrNoob] - Style: close button and collapse/window-menu button hover highlight made rectangular instead of round. diff --git a/imgui.cpp b/imgui.cpp index 7b922fdd7606..31f65a9d4a32 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10686,11 +10686,11 @@ void ImGui::EndGroup() if (window->DC.IsSetPos) ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); - ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos)); - + // Include LastItemData.Rect.Max as a workaround for e.g. EndTable() undershooting with CursorMaxPos report. (#7543) + ImRect group_bb(group_data.BackupCursorPos, ImMax(ImMax(window->DC.CursorMaxPos, g.LastItemData.Rect.Max), group_data.BackupCursorPos)); window->DC.CursorPos = group_data.BackupCursorPos; window->DC.CursorPosPrevLine = group_data.BackupCursorPosPrevLine; - window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos); + window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, group_bb.Max); window->DC.Indent = group_data.BackupIndent; window->DC.GroupOffset = group_data.BackupGroupOffset; window->DC.CurrLineSize = group_data.BackupCurrLineSize; @@ -10705,7 +10705,7 @@ void ImGui::EndGroup() return; } - window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. + window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. ItemSize(group_bb.GetSize()); ItemAdd(group_bb, 0, NULL, ImGuiItemFlags_NoTabStop); diff --git a/imgui.h b/imgui.h index fd0768a22b79..47626ad6fa59 100644 --- a/imgui.h +++ b/imgui.h @@ -28,7 +28,7 @@ // 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 WIP" -#define IMGUI_VERSION_NUM 19098 +#define IMGUI_VERSION_NUM 19099 #define IMGUI_HAS_TABLE /* From 79b77d91c98e36c1dd487516564cec716ddd94f1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jul 2024 18:43:54 +0200 Subject: [PATCH 013/548] MultiSelect: sequential SetRange merging not generally handled by box-select path, useful for others. --- imgui_internal.h | 3 ++- imgui_widgets.cpp | 35 ++++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index b307adcde7a6..85aaa19bc6fb 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1751,6 +1751,7 @@ struct IMGUI_API ImGuiMultiSelectTempData ImGuiMultiSelectFlags Flags; ImVec2 ScopeRectMin; ImVec2 BackupCursorMaxPos; + ImGuiSelectionUserData LastSubmittedItem; // Copy of last submitted item data, used to merge output ranges. ImGuiID BoxSelectId; ImGuiKeyChord KeyMods; ImS8 LoopRequestSetAll; // -1: no operation, 0: clear all, 1: select all. @@ -1760,7 +1761,6 @@ struct IMGUI_API ImGuiMultiSelectTempData bool NavIdPassedBy; bool RangeSrcPassedBy; // Set by the item that matches RangeSrcItem. bool RangeDstPassedBy; // Set by the item that matches NavJustMovedToId when IsSetRange is set. - ImGuiSelectionUserData BoxSelectLastitem; // Copy of last submitted item data, used to merge output ranges. ImGuiMultiSelectTempData() { Clear(); } void Clear() { size_t io_sz = sizeof(IO); ClearIO(); memset((void*)(&IO + 1), 0, sizeof(*this) - io_sz); } // Zero-clear except IO as we preserve IO.Requests[] buffer allocation. @@ -3408,6 +3408,7 @@ namespace ImGui // Multi-Select API IMGUI_API void MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags); IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed); + IMGUI_API void MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item); inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.ID == id && g.BoxSelectState.IsActive) ? &g.BoxSelectState : NULL; } inline ImGuiMultiSelectState* GetMultiSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return g.MultiSelectStorage.GetByKey(id); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 068337e9c95e..183c7fbe2873 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7069,7 +7069,7 @@ static int ImStrimatchlen(const char* s1, const char* s1_end, const char* s2) // When SingleCharMode is set: // - it is better to NOT display a tooltip of other on-screen display indicator. // - the index of the currently focused item is required. -// if your SetNextItemSelectionData() values are indices, you can obtain it from ImGuiMultiSelectIO::NavIdItem, otherwise from g.NavLastValidSelectionUserData. +// if your SetNextItemSelectionUserData() values are indices, you can obtain it from ImGuiMultiSelectIO::NavIdItem, otherwise from g.NavLastValidSelectionUserData. int ImGui::TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx) { if (req == NULL || req->SelectRequest == false) // Support NULL parameter so both calls can be done from same spot. @@ -7397,7 +7397,6 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel if (flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d)) { ms->BoxSelectId = GetID("##BoxSelect"); - ms->BoxSelectLastitem = ImGuiSelectionUserData_Invalid; if (BeginBoxSelect(window, ms->BoxSelectId, flags)) request_clear |= bs->RequestClear; } @@ -7432,6 +7431,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel ms->IO.Requests.push_back(req); } ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1; + ms->LastSubmittedItem = ImGuiSelectionUserData_Invalid; if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) DebugLogMultiSelectRequests("BeginMultiSelect", &ms->IO); @@ -7694,17 +7694,10 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed) else { selected = !selected; - ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, +1, item_data, item_data }; - // Merge continuous ranges (unless NoRangeSelect is set) - ImGuiSelectionRequest* prev = ms->IO.Requests.Size > 0 ? &ms->IO.Requests.Data[ms->IO.Requests.Size - 1] : NULL; - if (prev && prev->Type == ImGuiSelectionRequestType_SetRange && prev->RangeLastItem == ms->BoxSelectLastitem && prev->Selected == selected && (ms->Flags & ImGuiMultiSelectFlags_NoRangeSelect) == 0) - prev->RangeLastItem = item_data; // Merge span into same request - else - ms->IO.Requests.push_back(req); + MultiSelectAddSetRange(ms, selected, +1, item_data, item_data); } storage->LastSelectionSize = ImMax(storage->LastSelectionSize + 1, 1); } - ms->BoxSelectLastitem = item_data; } // Right-click handling. @@ -7804,9 +7797,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed) range_selected = selected; range_direction = +1; } - ImGuiSelectionUserData range_dst_item = item_data; - ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, range_selected, (ImS8)range_direction, (range_direction > 0) ? storage->RangeSrcItem : range_dst_item, (range_direction > 0) ? range_dst_item : storage->RangeSrcItem }; - ms->IO.Requests.push_back(req); + MultiSelectAddSetRange(ms, range_selected, range_direction, storage->RangeSrcItem, item_data); } // Update/store the selection state of the Source item (used by CTRL+SHIFT, when Source is unselected we perform a range unselect) @@ -7821,11 +7812,29 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed) } if (storage->NavIdItem == item_data) ms->NavIdPassedBy = true; + ms->LastSubmittedItem = item_data; *p_selected = selected; *p_pressed = pressed; } +void ImGui::MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item) +{ + // Merge contiguous spans into same request (unless NoRangeSelect is set which guarantees single-item ranges) + if (ms->IO.Requests.Size > 0 && first_item == last_item && (ms->Flags & ImGuiMultiSelectFlags_NoRangeSelect) == 0) + { + ImGuiSelectionRequest* prev = &ms->IO.Requests.Data[ms->IO.Requests.Size - 1]; + if (prev->Type == ImGuiSelectionRequestType_SetRange && prev->RangeLastItem == ms->LastSubmittedItem && prev->Selected == selected) + { + prev->RangeLastItem = last_item; + return; + } + } + + ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, (ImS8)range_dir, (range_dir > 0) ? first_item : last_item, (range_dir > 0) ? last_item : first_item }; + ms->IO.Requests.push_back(req); // Add new request +} + void ImGui::DebugNodeMultiSelectState(ImGuiMultiSelectState* storage) { #ifndef IMGUI_DISABLE_DEBUG_TOOLS From a285835ac4a293831852b0d5dd671401fd2c7412 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jul 2024 19:00:09 +0200 Subject: [PATCH 014/548] MultiSelect: add internal MultiSelectAddSetAll() helper. --- imgui_internal.h | 1 + imgui_widgets.cpp | 28 ++++++++++++---------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 85aaa19bc6fb..3bcca85004fd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3408,6 +3408,7 @@ namespace ImGui // Multi-Select API IMGUI_API void MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags); IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed); + IMGUI_API void MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected); IMGUI_API void MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item); inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.ID == id && g.BoxSelectState.IsActive) ? &g.BoxSelectState : NULL; } inline ImGuiMultiSelectState* GetMultiSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return g.MultiSelectStorage.GetByKey(id); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 183c7fbe2873..e9cf6f0f78f7 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7424,12 +7424,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel } if (request_clear || request_select_all) - { - ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, request_select_all, 0, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid }; - if (!request_select_all) - storage->LastSelectionSize = 0; - ms->IO.Requests.push_back(req); - } + MultiSelectAddSetAll(ms, request_select_all); ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1; ms->LastSubmittedItem = ImGuiSelectionUserData_Invalid; @@ -7496,11 +7491,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect() if (ms->Flags & ImGuiMultiSelectFlags_ClearOnClickVoid) if (IsMouseReleased(0) && IsMouseDragPastThreshold(0) == false && g.IO.KeyMods == ImGuiMod_None) - { - ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, false, 0, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid }; - ms->IO.Requests.resize(0); - ms->IO.Requests.push_back(req); - } + MultiSelectAddSetAll(ms, false); } // Courtesy nav wrapping helper flag @@ -7755,11 +7746,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed) else if ((input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Gamepad) && is_shift && !is_ctrl) request_clear = true; // With is_shift==false the RequestClear was done in BeginIO, not necessary to do again. if (request_clear) - { - ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, false, 0, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid }; - ms->IO.Requests.resize(0); - ms->IO.Requests.push_back(req); - } + MultiSelectAddSetAll(ms, false); } int range_direction; @@ -7818,6 +7805,15 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed) *p_pressed = pressed; } +void ImGui::MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected) +{ + ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, selected, 0, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid }; + ms->IO.Requests.resize(0); // Can always clear previous requests + ms->IO.Requests.push_back(req); // Add new request + if (selected == false) + ms->Storage->LastSelectionSize = 0; +} + void ImGui::MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item) { // Merge contiguous spans into same request (unless NoRangeSelect is set which guarantees single-item ranges) From 237165a9359518573f67cabf2e2f6d648f351244 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Jul 2024 19:14:54 +0200 Subject: [PATCH 015/548] MultiSelect: fixed an issue caused by previous commit. Amend a285835. Breaks box-select. --- imgui_widgets.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e9cf6f0f78f7..7739f3036b4f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7424,7 +7424,11 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel } if (request_clear || request_select_all) + { MultiSelectAddSetAll(ms, request_select_all); + if (!request_select_all) + storage->LastSelectionSize = 0; + } ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1; ms->LastSubmittedItem = ImGuiSelectionUserData_Invalid; @@ -7810,8 +7814,6 @@ void ImGui::MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected) ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, selected, 0, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid }; ms->IO.Requests.resize(0); // Can always clear previous requests ms->IO.Requests.push_back(req); // Add new request - if (selected == false) - ms->Storage->LastSelectionSize = 0; } void ImGui::MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item) From ed356dc181217439af31e5883fbe58906d0ec1cb Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jul 2024 14:46:25 +0200 Subject: [PATCH 016/548] MultiSelect: BoxSelect: fixed box-select from void setting nav id multiple times. --- imgui_internal.h | 1 + imgui_widgets.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index 3bcca85004fd..29420b6b60b8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1719,6 +1719,7 @@ struct ImGuiBoxSelectState bool IsActive; bool IsStarting; bool IsStartedFromVoid; // Starting click was not from an item. + bool IsStartedSetNavIdOnce; bool RequestClear; ImGuiKeyChord KeyMods : 16; // Latched key-mods for box-select logic. ImVec2 StartPosRel; // Start position in window-contents relative space (to support scrolling) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7739f3036b4f..1a11e3834986 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7161,6 +7161,7 @@ static void BoxSelectPreStartDrag(ImGuiID id, ImGuiSelectionUserData clicked_ite bs->ID = id; bs->IsStarting = true; // Consider starting box-select. bs->IsStartedFromVoid = (clicked_item == ImGuiSelectionUserData_Invalid); + bs->IsStartedSetNavIdOnce = bs->IsStartedFromVoid; bs->KeyMods = g.IO.KeyMods; bs->StartPosRel = bs->EndPosRel = ImGui::WindowPosAbsToRel(g.CurrentWindow, g.IO.MousePos); bs->ScrollAccum = ImVec2(0.0f, 0.0f); @@ -7682,9 +7683,10 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed) const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(g.LastItemData.Rect); if ((rect_overlap_curr && !rect_overlap_prev && !selected) || (rect_overlap_prev && !rect_overlap_curr)) { - if (storage->LastSelectionSize <= 0 && bs->IsStartedFromVoid) + if (storage->LastSelectionSize <= 0 && bs->IsStartedSetNavIdOnce) { pressed = true; // First item act as a pressed: code below will emit selection request and set NavId (whatever we emit here will be overridden anyway) + bs->IsStartedSetNavIdOnce = false; } else { From 55f54fa512f81885cafcd2c701dcff26c328b146 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jul 2024 15:10:04 +0200 Subject: [PATCH 017/548] Internals: comment out obsolete g.ActiveIdUsingNavInputMask obsoleted two years ago. (#4921, #4858, #787, #1599, #323) Use SetKeyOwner(ImGuiKey_Escape, g.ActiveId); instead. Amend 8b8a61bd --- imgui.cpp | 20 -------------------- imgui_internal.h | 9 ++------- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 31f65a9d4a32..9e93b8434b63 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4040,9 +4040,6 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) // (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet) g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingAllKeyboardKeys = false; -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - g.ActiveIdUsingNavInputMask = 0x00; -#endif } void ImGui::ClearActiveID() @@ -4806,24 +4803,7 @@ void ImGui::NewFrame() { g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingAllKeyboardKeys = false; -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - g.ActiveIdUsingNavInputMask = 0x00; -#endif - } - -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - if (g.ActiveId == 0) - g.ActiveIdUsingNavInputMask = 0; - else if (g.ActiveIdUsingNavInputMask != 0) - { - // If your custom widget code used: { g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel); } - // Since IMGUI_VERSION_NUM >= 18804 it should be: { SetKeyOwner(ImGuiKey_Escape, g.ActiveId); SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId); } - if (g.ActiveIdUsingNavInputMask & (1 << ImGuiNavInput_Cancel)) - SetKeyOwner(ImGuiKey_Escape, g.ActiveId); - if (g.ActiveIdUsingNavInputMask & ~(1 << ImGuiNavInput_Cancel)) - IM_ASSERT(0); // Other values unsupported } -#endif // Record when we have been stationary as this state is preserved while over same item. // FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values. diff --git a/imgui_internal.h b/imgui_internal.h index 29420b6b60b8..6fa1ee799e00 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2081,9 +2081,7 @@ struct ImGuiContext ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it) bool ActiveIdUsingAllKeyboardKeys; // Active widget will want to read all keyboard keys inputs. (this is a shortcut for not taking ownership of 100+ keys, frequently used by drag operations) ImGuiKeyChord DebugBreakInShortcutRouting; // Set to break in SetShortcutRouting()/Shortcut() calls. -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - ImU32 ActiveIdUsingNavInputMask; // If you used this. Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);' -#endif + //ImU32 ActiveIdUsingNavInputMask; // [OBSOLETE] Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes --> 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);' // Next window/item data ImGuiID CurrentFocusScopeId; // Value for currently appending items == g.FocusScopeStack.back(). Not to be mistaken with g.NavFocusScopeId. @@ -2395,9 +2393,6 @@ struct ImGuiContext ActiveIdUsingNavDirMask = 0x00; ActiveIdUsingAllKeyboardKeys = false; -#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO - ActiveIdUsingNavInputMask = 0x00; -#endif CurrentFocusScopeId = 0; CurrentItemFlags = ImGuiItemFlags_None; @@ -3196,7 +3191,7 @@ namespace ImGui //#endif // Basic Accessors - inline ImGuiItemStatusFlags GetItemStatusFlags(){ ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; } + inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; } inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.InFlags; } inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } From aad86b8756b7cde30fd70ac87e6325257e1a3e27 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jul 2024 15:50:30 +0200 Subject: [PATCH 018/548] Obsoleted GetWindowContentRegionMin() and GetWindowContentRegionMax(). You should never need those functions. You can do everything with GetCursorScreenPos() and GetContentRegionAvail(). --- docs/CHANGELOG.txt | 6 ++++++ imgui.cpp | 10 +++++++++- imgui.h | 13 +++++++------ imgui_demo.cpp | 2 +- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fde5c5144e90..42c2cea37f0a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,12 @@ Breaking changes: - new: io.PlatformSetImeDataFn(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); It is expected that for a vast majority of users this is automatically set by core library and/or platform backend so it won't have any effect. +- Obsoleted GetWindowContentRegionMin() and GetWindowContentRegionMax(). + You should never need those functions. Always use GetCursorScreenPos() and GetContentRegionAvail(). + Also consider that if you are using GetWindowPos() and GetCursorPos() you may also be making things + unnecessarily complicated. You can do everything with GetCursorScreenPos() and GetContentRegionAvail()!! + - GetWindowContentRegionMax().x - GetCursorPos().x --> GetContentRegionAvail().x + - GetWindowContentRegionMax().x + GetWindowPos().x --> GetCursorScreenPos().x + GetContentRegionAvail().x - Item flag changes: - Obsoleted PushButtonRepeat()/PopButtonRepeat() in favor of using new PushItemFlag()/PopItemFlag() with ImGuiItemFlags_ButtonRepeat. Kept inline redirecting functions (will obsolete). diff --git a/imgui.cpp b/imgui.cpp index 9e93b8434b63..626031514570 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -430,6 +430,11 @@ 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. + - 2024/07/25 (1.91.0) - obsoleted GetWindowContentRegionMin() and GetWindowContentRegionMax(). You should never need those functions. Always use GetCursorScreenPos() and GetContentRegionAvail(). + - instead of: GetWindowContentRegionMax().x - GetCursorPos().x + - you can use: GetContentRegionAvail().x + - instead of: GetWindowContentRegionMax().x + GetWindowPos().x + - you can use: GetCursorScreenPos().x + GetContentRegionAvail().x (from left edge of window) - 2024/07/15 (1.91.0) - renamed ImGuiSelectableFlags_DontClosePopups to ImGuiSelectableFlags_NoAutoClosePopups. (#1379, #1468, #2200, #4936, #5216, #7302, #7573) (internals: also renamed ImGuiItemFlags_SelectableDontClosePopup into ImGuiItemFlags_AutoClosePopups with inverted behaviors) - 2024/07/15 (1.91.0) - obsoleted PushButtonRepeat()/PopButtonRepeat() in favor of using new PushItemFlag(ImGuiItemFlags_ButtonRepeat, ...)/PopItemFlag(). @@ -10609,7 +10614,9 @@ ImVec2 ImGui::GetContentRegionAvail() return GetContentRegionMaxAbs() - window->DC.CursorPos; } -// In window space (not screen space!) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +// You should never need those functions. Always use GetCursorScreenPos() and GetContentRegionAvail()! +// They are bizarre local-coordinates which don't play well with scrolling. ImVec2 ImGui::GetWindowContentRegionMin() { ImGuiWindow* window = GImGui->CurrentWindow; @@ -10621,6 +10628,7 @@ ImVec2 ImGui::GetWindowContentRegionMax() ImGuiWindow* window = GImGui->CurrentWindow; return window->ContentRegionRect.Max - window->Pos; } +#endif // Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) // Groups are currently a mishmash of functionalities which should perhaps be clarified and separated. diff --git a/imgui.h b/imgui.h index 47626ad6fa59..26aed79bb829 100644 --- a/imgui.h +++ b/imgui.h @@ -392,10 +392,10 @@ namespace ImGui IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags=0); // is current window focused? or its root/child, depending on flags. see flags for options. IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags=0); // is current window hovered and hoverable (e.g. not blocked by a popup/modal)? See ImGuiHoveredFlags_ for options. IMPORTANT: If you are trying to check whether your mouse should be dispatched to Dear ImGui or to your underlying app, you should not use this function! Use the 'io.WantCaptureMouse' boolean for that! Refer to FAQ entry "How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?" for details. IMGUI_API ImDrawList* GetWindowDrawList(); // get draw list associated to the current window, to append your own drawing primitives - IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (note: it is unlikely you need to use this. Consider using current layout pos instead, GetCursorScreenPos()) - IMGUI_API ImVec2 GetWindowSize(); // get current window size (note: it is unlikely you need to use this. Consider using GetCursorScreenPos() and e.g. GetContentRegionAvail() instead) - IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x) - IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y) + IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (IT IS UNLIKELY YOU EVER NEED TO USE THIS. Consider always using GetCursorScreenPos() and GetContentRegionAvail() instead) + IMGUI_API ImVec2 GetWindowSize(); // get current window size (IT IS UNLIKELY YOU EVER NEED TO USE THIS. Consider always using GetCursorScreenPos() and GetContentRegionAvail() instead) + IMGUI_API float GetWindowWidth(); // get current window width (IT IS UNLIKELY YOU EVER NEED TO USE THIS). Shortcut for GetWindowSize().x. + IMGUI_API float GetWindowHeight(); // get current window height (IT IS UNLIKELY YOU EVER NEED TO USE THIS). Shortcut for GetWindowSize().y. // Window manipulation // - Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin). @@ -422,8 +422,6 @@ namespace ImGui // - Those functions are bound to be redesigned (they are confusing, incomplete and the Min/Max return values are in local window coordinates which increases confusion) IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates - IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min for the full window (roughly (0,0)-Scroll), in window coordinates - IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max for the full window (roughly (0,0)+Size-Scroll) where Size can be overridden with SetNextWindowContentSize(), in window coordinates // Windows Scrolling // - Any change of Scroll will be applied at the beginning of next frame in the first call to Begin(). @@ -473,6 +471,7 @@ namespace ImGui // - By "cursor" we mean the current output position. // - The typical widget behavior is to output themselves at the current cursor position, then move the cursor one line down. // - You can call SameLine() between widgets to undo the last carriage return and output at the right of the preceding widget. + // - YOU CAN DO 99% OF WHAT YOU NEED WITH ONLY GetCursorScreenPos() and GetContentRegionAvail(). // - Attention! We currently have inconsistencies between window-local and absolute positions we will aim to fix with future API: // - Absolute coordinate: GetCursorScreenPos(), SetCursorScreenPos(), all ImDrawList:: functions. -> this is the preferred way forward. // - Window-local coordinates: SameLine(), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), GetContentRegionMax(), GetWindowContentRegion*(), PushTextWrapPos() @@ -3504,6 +3503,8 @@ namespace ImGui static inline void PopButtonRepeat() { PopItemFlag(); } static inline void PushTabStop(bool tab_stop) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); } static inline void PopTabStop() { PopItemFlag(); } + IMGUI_API ImVec2 GetWindowContentRegionMin(); // Content boundaries min for the window (roughly (0,0)-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()! + IMGUI_API ImVec2 GetWindowContentRegionMax(); // Content boundaries max for the window (roughly (0,0)+Size-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()! // OBSOLETED in 1.90.0 (from September 2023) static inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags window_flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, window_flags); } static inline void EndChildFrame() { EndChild(); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7a3cdf0f40c0..8684bd0c6c3f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3918,7 +3918,7 @@ static void ShowDemoWindowLayout() ImGui::Text("Manual wrapping:"); ImGuiStyle& style = ImGui::GetStyle(); int buttons_count = 20; - float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x; + float window_visible_x2 = ImGui::GetCursorScreenPos().x + ImGui::GetContentRegionAvail().x; for (int n = 0; n < buttons_count; n++) { ImGui::PushID(n); From 055b2e80fbe1f13b81ef6e092381530eaf68fc36 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jul 2024 16:02:59 +0200 Subject: [PATCH 019/548] Moved everyone's best friend GetContentRegionAvail() to a more prominent position. --- imgui.cpp | 1 - imgui.h | 14 +++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 626031514570..ace1d02761a5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10315,7 +10315,6 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE // - GetContentRegionMax() // - GetContentRegionMaxAbs() [Internal] // - GetContentRegionAvail(), -// - GetWindowContentRegionMin(), GetWindowContentRegionMax() // - BeginGroup() // - EndGroup() // Also see in imgui_widgets: tab bars, and in imgui_tables: tables, columns. diff --git a/imgui.h b/imgui.h index 26aed79bb829..e98399371df9 100644 --- a/imgui.h +++ b/imgui.h @@ -417,12 +417,6 @@ namespace ImGui IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / top-most. use NULL to remove focus. - // Content region - // - Retrieve available space from a given point. GetContentRegionAvail() is frequently useful. - // - Those functions are bound to be redesigned (they are confusing, incomplete and the Min/Max return values are in local window coordinates which increases confusion) - IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() - IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates - // Windows Scrolling // - Any change of Scroll will be applied at the beginning of next frame in the first call to Begin(). // - You may instead use SetNextWindowScroll() prior to calling Begin() to avoid this delay, as an alternative to using SetScrollX()/SetScrollY(). @@ -474,10 +468,12 @@ namespace ImGui // - YOU CAN DO 99% OF WHAT YOU NEED WITH ONLY GetCursorScreenPos() and GetContentRegionAvail(). // - Attention! We currently have inconsistencies between window-local and absolute positions we will aim to fix with future API: // - Absolute coordinate: GetCursorScreenPos(), SetCursorScreenPos(), all ImDrawList:: functions. -> this is the preferred way forward. - // - Window-local coordinates: SameLine(), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), GetContentRegionMax(), GetWindowContentRegion*(), PushTextWrapPos() - // - GetCursorScreenPos() = GetCursorPos() + GetWindowPos(). GetWindowPos() is almost only ever useful to convert from window-local to absolute coordinates. - IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute coordinates (prefer using this, also more useful to work with ImDrawList API). + // - Window-local coordinates: SameLine(offset), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), GetContentRegionMax(), PushTextWrapPos() + // - GetCursorScreenPos() = GetCursorPos() + GetWindowPos(). GetWindowPos() is almost only ever useful to convert from window-local to absolute coordinates. Try not to use it. + IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute coordinates. THIS IS YOUR BEST FRIEND (prefer using this rather than GetCursorPos(), also more useful to work with ImDrawList API). IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute coordinates + IMGUI_API ImVec2 GetContentRegionAvail(); // available space from current position. THIS IS YOUR BEST FRIEND. + IMGUI_API ImVec2 GetContentRegionMax(); // [window-local] current content boundaries (e.g. window boundaries including scrolling, or current column boundaries) IMGUI_API ImVec2 GetCursorPos(); // [window-local] cursor position in window coordinates (relative to window position) IMGUI_API float GetCursorPosX(); // [window-local] " IMGUI_API float GetCursorPosY(); // [window-local] " From 4227402b2fe46a24663fd16efd042a8527d2bbed Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jul 2024 16:10:18 +0200 Subject: [PATCH 020/548] Internals: removed GetContentRegionMaxAbs() which was only meaningfully used in place of GetContentRegionAvail(). --- imgui.cpp | 36 ++++++++++++------------------------ imgui_internal.h | 1 - 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ace1d02761a5..40de62165b52 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10313,7 +10313,6 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE // - GetFrameHeight() // - GetFrameHeightWithSpacing() // - GetContentRegionMax() -// - GetContentRegionMaxAbs() [Internal] // - GetContentRegionAvail(), // - BeginGroup() // - EndGroup() @@ -10530,8 +10529,8 @@ float ImGui::CalcItemWidth() w = window->DC.ItemWidth; if (w < 0.0f) { - float region_max_x = GetContentRegionMaxAbs().x; - w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w); + float region_avail_x = GetContentRegionAvail().x; + w = ImMax(1.0f, region_avail_x + w); } w = IM_TRUNC(w); return w; @@ -10543,22 +10542,19 @@ float ImGui::CalcItemWidth() // The 4.0f here may be changed to match CalcItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable) ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - - ImVec2 region_max; + ImVec2 avail; if (size.x < 0.0f || size.y < 0.0f) - region_max = GetContentRegionMaxAbs(); + avail = GetContentRegionAvail(); if (size.x == 0.0f) size.x = default_w; else if (size.x < 0.0f) - size.x = ImMax(4.0f, region_max.x - window->DC.CursorPos.x + size.x); + size.x = ImMax(4.0f, avail.x + size.x); // <-- size.x is negative here so we are subtracting if (size.y == 0.0f) size.y = default_h; else if (size.y < 0.0f) - size.y = ImMax(4.0f, region_max.y - window->DC.CursorPos.y + size.y); + size.y = ImMax(4.0f, avail.y + size.y); // <-- size.y is negative here so we are subtracting return size; } @@ -10587,30 +10583,22 @@ float ImGui::GetFrameHeightWithSpacing() return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; } -// FIXME: All the Contents Region function are messy or misleading. WE WILL AIM TO OBSOLETE ALL OF THEM WITH A NEW "WORK RECT" API. Thanks for your patience! - -// FIXME: This is in window space (not screen space!). -ImVec2 ImGui::GetContentRegionMax() +ImVec2 ImGui::GetContentRegionAvail() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max; - return mx - window->Pos; + return mx - window->DC.CursorPos; } -// [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features. -ImVec2 ImGui::GetContentRegionMaxAbs() +// FIXME: All the Contents Region function are messy or misleading. WE WILL AIM TO OBSOLETE ALL OF THEM WITH A NEW "WORK RECT" API. Thanks for your patience! +// FIXME: This is in window space (not screen space!). +ImVec2 ImGui::GetContentRegionMax() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max; - return mx; -} - -ImVec2 ImGui::GetContentRegionAvail() -{ - ImGuiWindow* window = GImGui->CurrentWindow; - return GetContentRegionMaxAbs() - window->DC.CursorPos; + return mx - window->Pos; } #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS diff --git a/imgui_internal.h b/imgui_internal.h index 6fa1ee799e00..6cee078571d1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3217,7 +3217,6 @@ namespace ImGui IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API void PushMultiItemsWidths(int components, float width_full); - IMGUI_API ImVec2 GetContentRegionMaxAbs(); IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); // Parameter stacks (shared) From b20f62b162e5f1e44748eb768f6b126a25ec29de Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jul 2024 16:18:46 +0200 Subject: [PATCH 021/548] Obsoleted GetContentRegionMax(). --- docs/CHANGELOG.txt | 10 ++++++---- imgui.cpp | 19 +++++++++---------- imgui.h | 13 +++++++------ 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 42c2cea37f0a..eb98554ce524 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,12 +46,14 @@ Breaking changes: - new: io.PlatformSetImeDataFn(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); It is expected that for a vast majority of users this is automatically set by core library and/or platform backend so it won't have any effect. -- Obsoleted GetWindowContentRegionMin() and GetWindowContentRegionMax(). - You should never need those functions. Always use GetCursorScreenPos() and GetContentRegionAvail(). - Also consider that if you are using GetWindowPos() and GetCursorPos() you may also be making things - unnecessarily complicated. You can do everything with GetCursorScreenPos() and GetContentRegionAvail()!! +- Obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). + You should never need those functions! You can do everything in less a confusing manner by only + using GetCursorScreenPos() and GetContentRegionAvail(). Also always consider that if you are using + GetWindowPos() and GetCursorPos() you may also be making things unnecessarily complicated. + I repeat: You can do everything with GetCursorScreenPos() and GetContentRegionAvail()!! - GetWindowContentRegionMax().x - GetCursorPos().x --> GetContentRegionAvail().x - GetWindowContentRegionMax().x + GetWindowPos().x --> GetCursorScreenPos().x + GetContentRegionAvail().x + - GetContentRegionMax() --> GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos() // right edge in weird local coordinates - Item flag changes: - Obsoleted PushButtonRepeat()/PopButtonRepeat() in favor of using new PushItemFlag()/PopItemFlag() with ImGuiItemFlags_ButtonRepeat. Kept inline redirecting functions (will obsolete). diff --git a/imgui.cpp b/imgui.cpp index 40de62165b52..a74ae56c110f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -430,11 +430,14 @@ 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. - - 2024/07/25 (1.91.0) - obsoleted GetWindowContentRegionMin() and GetWindowContentRegionMax(). You should never need those functions. Always use GetCursorScreenPos() and GetContentRegionAvail(). + - 2024/07/25 (1.91.0) - obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). + you should never need those functions. you can do everything with GetCursorScreenPos() and GetContentRegionAvail() in a more simple way. - instead of: GetWindowContentRegionMax().x - GetCursorPos().x - you can use: GetContentRegionAvail().x - instead of: GetWindowContentRegionMax().x + GetWindowPos().x - you can use: GetCursorScreenPos().x + GetContentRegionAvail().x (from left edge of window) + - instead of: GetContentRegionMax() + - you cna use: GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos() // right edge in weird local coordinates - 2024/07/15 (1.91.0) - renamed ImGuiSelectableFlags_DontClosePopups to ImGuiSelectableFlags_NoAutoClosePopups. (#1379, #1468, #2200, #4936, #5216, #7302, #7573) (internals: also renamed ImGuiItemFlags_SelectableDontClosePopup into ImGuiItemFlags_AutoClosePopups with inverted behaviors) - 2024/07/15 (1.91.0) - obsoleted PushButtonRepeat()/PopButtonRepeat() in favor of using new PushItemFlag(ImGuiItemFlags_ButtonRepeat, ...)/PopItemFlag(). @@ -10591,19 +10594,15 @@ ImVec2 ImGui::GetContentRegionAvail() return mx - window->DC.CursorPos; } -// FIXME: All the Contents Region function are messy or misleading. WE WILL AIM TO OBSOLETE ALL OF THEM WITH A NEW "WORK RECT" API. Thanks for your patience! -// FIXME: This is in window space (not screen space!). +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + +// You should never need those functions. Always use GetCursorScreenPos() and GetContentRegionAvail()! +// They are bizarre local-coordinates which don't play well with scrolling. ImVec2 ImGui::GetContentRegionMax() { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max; - return mx - window->Pos; + return GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos(); } -#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -// You should never need those functions. Always use GetCursorScreenPos() and GetContentRegionAvail()! -// They are bizarre local-coordinates which don't play well with scrolling. ImVec2 ImGui::GetWindowContentRegionMin() { ImGuiWindow* window = GImGui->CurrentWindow; diff --git a/imgui.h b/imgui.h index e98399371df9..0686be2abf2f 100644 --- a/imgui.h +++ b/imgui.h @@ -468,19 +468,19 @@ namespace ImGui // - YOU CAN DO 99% OF WHAT YOU NEED WITH ONLY GetCursorScreenPos() and GetContentRegionAvail(). // - Attention! We currently have inconsistencies between window-local and absolute positions we will aim to fix with future API: // - Absolute coordinate: GetCursorScreenPos(), SetCursorScreenPos(), all ImDrawList:: functions. -> this is the preferred way forward. - // - Window-local coordinates: SameLine(offset), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), GetContentRegionMax(), PushTextWrapPos() + // - Window-local coordinates: SameLine(offset), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), PushTextWrapPos() + // - Window-local coordinates: GetContentRegionMax(), GetWindowContentRegionMin(), GetWindowContentRegionMax() --> all obsoleted. YOU DON'T NEED THEM. // - GetCursorScreenPos() = GetCursorPos() + GetWindowPos(). GetWindowPos() is almost only ever useful to convert from window-local to absolute coordinates. Try not to use it. - IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute coordinates. THIS IS YOUR BEST FRIEND (prefer using this rather than GetCursorPos(), also more useful to work with ImDrawList API). - IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute coordinates + IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position, absolute coordinates. THIS IS YOUR BEST FRIEND (prefer using this rather than GetCursorPos(), also more useful to work with ImDrawList API). + IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position, absolute coordinates. THIS IS YOUR BEST FRIEND. IMGUI_API ImVec2 GetContentRegionAvail(); // available space from current position. THIS IS YOUR BEST FRIEND. - IMGUI_API ImVec2 GetContentRegionMax(); // [window-local] current content boundaries (e.g. window boundaries including scrolling, or current column boundaries) - IMGUI_API ImVec2 GetCursorPos(); // [window-local] cursor position in window coordinates (relative to window position) + IMGUI_API ImVec2 GetCursorPos(); // [window-local] cursor position in window-local coordinates. This is not your best friend. IMGUI_API float GetCursorPosX(); // [window-local] " IMGUI_API float GetCursorPosY(); // [window-local] " IMGUI_API void SetCursorPos(const ImVec2& local_pos); // [window-local] " IMGUI_API void SetCursorPosX(float local_x); // [window-local] " IMGUI_API void SetCursorPosY(float local_y); // [window-local] " - IMGUI_API ImVec2 GetCursorStartPos(); // [window-local] initial cursor position, in window coordinates + IMGUI_API ImVec2 GetCursorStartPos(); // [window-local] initial cursor position, in window-local coordinates // Other layout functions IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. @@ -3499,6 +3499,7 @@ namespace ImGui static inline void PopButtonRepeat() { PopItemFlag(); } static inline void PushTabStop(bool tab_stop) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); } static inline void PopTabStop() { PopItemFlag(); } + IMGUI_API ImVec2 GetContentRegionMax(); // Content boundaries max (e.g. window boundaries including scrolling, or current column boundaries). You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()! IMGUI_API ImVec2 GetWindowContentRegionMin(); // Content boundaries min for the window (roughly (0,0)-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()! IMGUI_API ImVec2 GetWindowContentRegionMax(); // Content boundaries max for the window (roughly (0,0)+Size-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()! // OBSOLETED in 1.90.0 (from September 2023) From 3f9a90e2a3c5a4662e57b5b9dec3042d3b5715ff Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Jul 2024 16:59:34 +0200 Subject: [PATCH 022/548] Docs: added extraneous link to Getting Started section. --- backends/imgui_impl_allegro5.h | 1 + backends/imgui_impl_android.h | 1 + backends/imgui_impl_dx10.h | 1 + backends/imgui_impl_dx11.h | 1 + backends/imgui_impl_dx12.h | 2 ++ backends/imgui_impl_dx9.h | 1 + backends/imgui_impl_glfw.h | 1 + backends/imgui_impl_glut.h | 1 + backends/imgui_impl_metal.h | 2 ++ backends/imgui_impl_opengl2.h | 1 + backends/imgui_impl_opengl3.h | 2 +- backends/imgui_impl_osx.h | 2 ++ backends/imgui_impl_sdl2.h | 1 + backends/imgui_impl_sdl3.h | 1 + backends/imgui_impl_sdlrenderer2.h | 1 + backends/imgui_impl_sdlrenderer3.h | 1 + backends/imgui_impl_vulkan.h | 2 +- backends/imgui_impl_wgpu.h | 1 + backends/imgui_impl_win32.h | 1 + 19 files changed, 22 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_allegro5.h b/backends/imgui_impl_allegro5.h index 5b63654ef9c5..f1501eca8ff6 100644 --- a/backends/imgui_impl_allegro5.h +++ b/backends/imgui_impl_allegro5.h @@ -25,6 +25,7 @@ struct ALLEGRO_DISPLAY; union ALLEGRO_EVENT; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display); IMGUI_IMPL_API void ImGui_ImplAllegro5_Shutdown(); IMGUI_IMPL_API void ImGui_ImplAllegro5_NewFrame(); diff --git a/backends/imgui_impl_android.h b/backends/imgui_impl_android.h index 557bf0e09210..92a044db028a 100644 --- a/backends/imgui_impl_android.h +++ b/backends/imgui_impl_android.h @@ -28,6 +28,7 @@ struct ANativeWindow; struct AInputEvent; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplAndroid_Init(ANativeWindow* window); IMGUI_IMPL_API int32_t ImGui_ImplAndroid_HandleInputEvent(const AInputEvent* input_event); IMGUI_IMPL_API void ImGui_ImplAndroid_Shutdown(); diff --git a/backends/imgui_impl_dx10.h b/backends/imgui_impl_dx10.h index e7e798aa4969..95759737b590 100644 --- a/backends/imgui_impl_dx10.h +++ b/backends/imgui_impl_dx10.h @@ -19,6 +19,7 @@ struct ID3D10Device; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device); IMGUI_IMPL_API void ImGui_ImplDX10_Shutdown(); IMGUI_IMPL_API void ImGui_ImplDX10_NewFrame(); diff --git a/backends/imgui_impl_dx11.h b/backends/imgui_impl_dx11.h index 20887f370706..cde64ee961b8 100644 --- a/backends/imgui_impl_dx11.h +++ b/backends/imgui_impl_dx11.h @@ -20,6 +20,7 @@ struct ID3D11Device; struct ID3D11DeviceContext; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h index 8710910b4ce9..e1fd07d6d4e1 100644 --- a/backends/imgui_impl_dx12.h +++ b/backends/imgui_impl_dx12.h @@ -27,6 +27,8 @@ struct ID3D12GraphicsCommandList; struct D3D12_CPU_DESCRIPTOR_HANDLE; struct D3D12_GPU_DESCRIPTOR_HANDLE; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! + // cmd_list is the command list that the implementation will use to render imgui draw lists. // Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate // render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle. diff --git a/backends/imgui_impl_dx9.h b/backends/imgui_impl_dx9.h index 3965583bd867..df6a0a012479 100644 --- a/backends/imgui_impl_dx9.h +++ b/backends/imgui_impl_dx9.h @@ -19,6 +19,7 @@ struct IDirect3DDevice9; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device); IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown(); IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame(); diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index a30ed64cabce..c0eac1134a3b 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -24,6 +24,7 @@ struct GLFWwindow; struct GLFWmonitor; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks); diff --git a/backends/imgui_impl_glut.h b/backends/imgui_impl_glut.h index 062110edd62e..a7479e1d7480 100644 --- a/backends/imgui_impl_glut.h +++ b/backends/imgui_impl_glut.h @@ -26,6 +26,7 @@ #ifndef IMGUI_DISABLE #include "imgui.h" // IMGUI_IMPL_API +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplGLUT_Init(); IMGUI_IMPL_API void ImGui_ImplGLUT_InstallFuncs(); IMGUI_IMPL_API void ImGui_ImplGLUT_Shutdown(); diff --git a/backends/imgui_impl_metal.h b/backends/imgui_impl_metal.h index 53706d1f7160..2402c02c62c8 100644 --- a/backends/imgui_impl_metal.h +++ b/backends/imgui_impl_metal.h @@ -25,6 +25,7 @@ @class MTLRenderPassDescriptor; @protocol MTLDevice, MTLCommandBuffer, MTLRenderCommandEncoder; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplMetal_Init(id device); IMGUI_IMPL_API void ImGui_ImplMetal_Shutdown(); IMGUI_IMPL_API void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor); @@ -51,6 +52,7 @@ IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects(); #include #ifndef __OBJC__ +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplMetal_Init(MTL::Device* device); IMGUI_IMPL_API void ImGui_ImplMetal_Shutdown(); IMGUI_IMPL_API void ImGui_ImplMetal_NewFrame(MTL::RenderPassDescriptor* renderPassDescriptor); diff --git a/backends/imgui_impl_opengl2.h b/backends/imgui_impl_opengl2.h index 9c756c71d6b3..e7f7a58c1f0e 100644 --- a/backends/imgui_impl_opengl2.h +++ b/backends/imgui_impl_opengl2.h @@ -24,6 +24,7 @@ #include "imgui.h" // IMGUI_IMPL_API #ifndef IMGUI_DISABLE +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplOpenGL2_Init(); IMGUI_IMPL_API void ImGui_ImplOpenGL2_Shutdown(); IMGUI_IMPL_API void ImGui_ImplOpenGL2_NewFrame(); diff --git a/backends/imgui_impl_opengl3.h b/backends/imgui_impl_opengl3.h index d66a15ebf7d0..54545f957b91 100644 --- a/backends/imgui_impl_opengl3.h +++ b/backends/imgui_impl_opengl3.h @@ -29,7 +29,7 @@ #include "imgui.h" // IMGUI_IMPL_API #ifndef IMGUI_DISABLE -// Backend API +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr); IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index 4033ad93e8a7..28e1331285df 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -27,6 +27,7 @@ @class NSEvent; @class NSView; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplOSX_Init(NSView* _Nonnull view); IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown(); IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(NSView* _Nullable view); @@ -41,6 +42,7 @@ IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(NSView* _Nullable view); // #include #ifndef __OBJC__ +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplOSX_Init(void* _Nonnull view); IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown(); IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(void* _Nullable view); diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h index 7020a29e0605..e551e52a2853 100644 --- a/backends/imgui_impl_sdl2.h +++ b/backends/imgui_impl_sdl2.h @@ -27,6 +27,7 @@ struct SDL_Renderer; struct _SDL_GameController; typedef union SDL_Event SDL_Event; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window); diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h index f1c06db5d1ca..39b7839d8d4b 100644 --- a/backends/imgui_impl_sdl3.h +++ b/backends/imgui_impl_sdl3.h @@ -28,6 +28,7 @@ struct SDL_Renderer; struct SDL_Gamepad; typedef union SDL_Event SDL_Event; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForOpenGL(SDL_Window* window, void* sdl_gl_context); IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForVulkan(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForD3D(SDL_Window* window); diff --git a/backends/imgui_impl_sdlrenderer2.h b/backends/imgui_impl_sdlrenderer2.h index aee40524d327..c067eaeead19 100644 --- a/backends/imgui_impl_sdlrenderer2.h +++ b/backends/imgui_impl_sdlrenderer2.h @@ -25,6 +25,7 @@ struct SDL_Renderer; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplSDLRenderer2_Init(SDL_Renderer* renderer); IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDLRenderer2_NewFrame(); diff --git a/backends/imgui_impl_sdlrenderer3.h b/backends/imgui_impl_sdlrenderer3.h index 968ec08253a2..1a730208a87f 100644 --- a/backends/imgui_impl_sdlrenderer3.h +++ b/backends/imgui_impl_sdlrenderer3.h @@ -25,6 +25,7 @@ struct SDL_Renderer; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplSDLRenderer3_Init(SDL_Renderer* renderer); IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDLRenderer3_NewFrame(); diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index fb98bfbc4d6b..1c7f7695183f 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -98,7 +98,7 @@ struct ImGui_ImplVulkan_InitInfo VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory. }; -// Called by user code +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info); IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown(); IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame(); diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h index 2e19ea36ea9f..87d9580bf800 100644 --- a/backends/imgui_impl_wgpu.h +++ b/backends/imgui_impl_wgpu.h @@ -37,6 +37,7 @@ struct ImGui_ImplWGPU_InitInfo } }; +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info); IMGUI_IMPL_API void ImGui_ImplWGPU_Shutdown(); IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame(); diff --git a/backends/imgui_impl_win32.h b/backends/imgui_impl_win32.h index be562714242f..3ad1a7eaf181 100644 --- a/backends/imgui_impl_win32.h +++ b/backends/imgui_impl_win32.h @@ -20,6 +20,7 @@ #include "imgui.h" // IMGUI_IMPL_API #ifndef IMGUI_DISABLE +// Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd); IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); From b3ba6b30952961bb9ec5fc6f46361c72530ff67c Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Jul 2024 14:07:29 +0200 Subject: [PATCH 023/548] Added io.ConfigNavSwapGamepadButtons to swap Activate/Cancel (A<>B) buttons, to match the typical "Nintendo/Japanese consoles" button layout when using Gamepad navigation. (#787, #5723) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 1 + imgui.h | 1 + imgui_internal.h | 4 ++-- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index eb98554ce524..cdb1360297f3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -76,6 +76,8 @@ Other changes: - IO: added io.PlatformOpenInShellFn handler to open a link/folder/file in OS shell. (#7660) Default to use ShellExecute() under Windows, and system("") under Mac/Linux/etc. Added IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS to disable default implementation. +- IO: added io.ConfigNavSwapGamepadButtons to swap Activate/Cancel (A<>B) buttons, to match tye + typical "Nintendo/Japanese consoles" button layout when using Gamepad navigation. (#787, #5723) - Added PushItemFlag()/PopItemFlags(), ImGuiItemFlags to modify shared item flags: - Added ImGuiItemFlags_NoTabStop to disable tabbing through items. - Added ImGuiItemFlags_NoNav to disable any navigation and focus of items. (#787) diff --git a/imgui.cpp b/imgui.cpp index a74ae56c110f..db7964b8afcc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1376,6 +1376,7 @@ ImGuiIO::ImGuiIO() #else ConfigMacOSXBehaviors = false; #endif + ConfigNavSwapGamepadButtons = false; ConfigInputTrickleEventQueue = true; ConfigInputTextCursorBlink = true; ConfigInputTextEnterKeepActive = false; diff --git a/imgui.h b/imgui.h index 0686be2abf2f..09db7b1fe689 100644 --- a/imgui.h +++ b/imgui.h @@ -2225,6 +2225,7 @@ struct ImGuiIO // Miscellaneous options bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations. bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl. + bool ConfigNavSwapGamepadButtons; // = false // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout. bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates. bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only). diff --git a/imgui_internal.h b/imgui_internal.h index 6cee078571d1..0eaaa0f77dc5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1355,8 +1355,8 @@ typedef ImBitArray ImBitAr #define ImGuiKey_NavKeyboardTweakFast ImGuiMod_Shift #define ImGuiKey_NavGamepadTweakSlow ImGuiKey_GamepadL1 #define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1 -#define ImGuiKey_NavGamepadActivate ImGuiKey_GamepadFaceDown -#define ImGuiKey_NavGamepadCancel ImGuiKey_GamepadFaceRight +#define ImGuiKey_NavGamepadActivate (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceRight : ImGuiKey_GamepadFaceDown) +#define ImGuiKey_NavGamepadCancel (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceDown : ImGuiKey_GamepadFaceRight) #define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft #define ImGuiKey_NavGamepadInput ImGuiKey_GamepadFaceUp From 692bee5f2211952b8a732616b7714f95ca1ef639 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Jul 2024 15:14:37 +0200 Subject: [PATCH 024/548] Added GetID(int) variant for consistency. (#7111) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 5 +++++ imgui.h | 1 + 3 files changed, 7 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cdb1360297f3..f47d7d7d221e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -153,6 +153,7 @@ Other changes: - Groups, Tables: fixed EndGroup() failing to correctly capture current table occupied size. (#7543) - TabBar, Style: added style.TabBarOverlineSize / ImGuiStyleVar_TabBarOverlineSize to manipulate thickness of the horizontal line over selectable tabs. [@DctrNoob] +- Misc: added GetID(int) variant for consistency. (#7111) - Style: close button and collapse/window-menu button hover highlight made rectangular instead of round. - Debug Tools: Added IMGUI_DEBUG_LOG(), ImGui::DebugLog() in public API. (#5855) Debug log entries add a imgui frame counter prefix + are redirected to ShowDebugLogWindow() and diff --git a/imgui.cpp b/imgui.cpp index db7964b8afcc..8640eda1ac1e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8380,6 +8380,11 @@ ImGuiID ImGui::GetID(const void* ptr_id) return window->GetID(ptr_id); } +ImGuiID ImGui::GetID(int int_id) +{ + ImGuiWindow* window = GImGui->CurrentWindow; + return window->GetID(int_id); +} //----------------------------------------------------------------------------- // [SECTION] INPUTS //----------------------------------------------------------------------------- diff --git a/imgui.h b/imgui.h index 09db7b1fe689..db9e59dadd9d 100644 --- a/imgui.h +++ b/imgui.h @@ -517,6 +517,7 @@ namespace ImGui IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); IMGUI_API ImGuiID GetID(const void* ptr_id); + IMGUI_API ImGuiID GetID(int int_id); // Widgets: Text IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text. From d42fa46dc6b68863046c22467297933dbe39bb55 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Jul 2024 15:15:46 +0200 Subject: [PATCH 025/548] Misc micro-optimizations related to hot-path of dealing with a large clipped tree. Halved times by two in MSVC Debug x64. --- imgui.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8640eda1ac1e..6b545d67d50c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2583,12 +2583,11 @@ void ImGuiStorage::BuildSortByKey() { ImQsort(Data.Data, (size_t)Data.Size, sizeof(ImGuiStoragePair), PairComparerByID); } -IM_MSVC_RUNTIME_CHECKS_RESTORE int ImGuiStorage::GetInt(ImGuiID key, int default_val) const { ImGuiStoragePair* it = ImLowerBound(const_cast(Data.Data), const_cast(Data.Data + Data.Size), key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) return default_val; return it->val_i; } @@ -2601,7 +2600,7 @@ bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const { ImGuiStoragePair* it = ImLowerBound(const_cast(Data.Data), const_cast(Data.Data + Data.Size), key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) return default_val; return it->val_f; } @@ -2609,7 +2608,7 @@ float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const void* ImGuiStorage::GetVoidPtr(ImGuiID key) const { ImGuiStoragePair* it = ImLowerBound(const_cast(Data.Data), const_cast(Data.Data + Data.Size), key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) return NULL; return it->val_p; } @@ -2618,7 +2617,7 @@ void* ImGuiStorage::GetVoidPtr(ImGuiID key) const int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_i; } @@ -2631,7 +2630,7 @@ bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_f; } @@ -2639,7 +2638,7 @@ float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_p; } @@ -2648,7 +2647,7 @@ void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) void ImGuiStorage::SetInt(ImGuiID key, int val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) Data.insert(it, ImGuiStoragePair(key, val)); else it->val_i = val; @@ -2662,7 +2661,7 @@ void ImGuiStorage::SetBool(ImGuiID key, bool val) void ImGuiStorage::SetFloat(ImGuiID key, float val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) Data.insert(it, ImGuiStoragePair(key, val)); else it->val_f = val; @@ -2671,7 +2670,7 @@ void ImGuiStorage::SetFloat(ImGuiID key, float val) void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val) { ImGuiStoragePair* it = ImLowerBound(Data.Data, Data.Data + Data.Size, key); - if (it == Data.end() || it->key != key) + if (it == Data.Data + Data.Size || it->key != key) Data.insert(it, ImGuiStoragePair(key, val)); else it->val_p = val; @@ -2682,6 +2681,7 @@ void ImGuiStorage::SetAllInt(int v) for (int i = 0; i < Data.Size; i++) Data[i].val_i = v; } +IM_MSVC_RUNTIME_CHECKS_RESTORE //----------------------------------------------------------------------------- // [SECTION] ImGuiTextFilter @@ -2749,7 +2749,7 @@ void ImGuiTextFilter::Build() bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const { - if (Filters.empty()) + if (Filters.Size == 0) return true; if (text == NULL) @@ -8241,6 +8241,7 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) // This is one of the very rare legacy case where we use ImGuiWindow methods, // it should ideally be flattened at some point but it's been used a lots by widgets. +IM_MSVC_RUNTIME_CHECKS_OFF ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) { ImGuiID seed = IDStack.back(); @@ -8385,6 +8386,8 @@ ImGuiID ImGui::GetID(int int_id) ImGuiWindow* window = GImGui->CurrentWindow; return window->GetID(int_id); } +IM_MSVC_RUNTIME_CHECKS_RESTORE + //----------------------------------------------------------------------------- // [SECTION] INPUTS //----------------------------------------------------------------------------- From 79e83d6535291f41430d900c8d71d7fd0e9b47f0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Jul 2024 11:17:31 +0200 Subject: [PATCH 026/548] Docs: misc update. --- docs/BACKENDS.md | 38 +++++++++++++++++++------------------- docs/EXAMPLES.md | 45 ++++++--------------------------------------- docs/README.md | 6 +++--- 3 files changed, 28 insertions(+), 61 deletions(-) diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index 88a96a6bd9df..55a0983ddbc9 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -2,23 +2,10 @@ _(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/BACKE ## Dear ImGui: Backends -**The backends/ folder contains backends for popular platforms/graphics API, which you can use in -your application or engine to easily integrate Dear ImGui.** Each backend is typically self-contained in a pair of files: imgui_impl_XXXX.cpp + imgui_impl_XXXX.h. - -- The 'Platform' backends are in charge of: mouse/keyboard/gamepad inputs, cursor shape, timing, and windowing.
- e.g. Windows ([imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp)), GLFW ([imgui_impl_glfw.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp)), SDL2 ([imgui_impl_sdl2.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_sdl2.cpp)), etc. - -- The 'Renderer' backends are in charge of: creating atlas texture, and rendering imgui draw data.
- e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp)), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp)), etc. - -- For some high-level frameworks, a single backend usually handles both 'Platform' and 'Renderer' parts.
- e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)). If you end up creating a custom backend for your engine, you may want to do the same. - -An application usually combines one Platform backend + one Renderer backend + main Dear ImGui sources. -For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. There are 20+ examples in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details. - -**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.** +### Integrating backends +💡 The **[Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) wiki guide** has examples of how to integrate Dear ImGui into an existing application. +
The [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) documentation may also be worth a read. ### What are backends? @@ -38,7 +25,7 @@ Dear ImGui is highly portable and only requires a few things to run and render, - Optional: multi-viewports support. etc. -This is essentially what each backend is doing + obligatory portability cruft. Using default backends ensure you can get all those features including the ones that would be harder to implement on your side (e.g. multi-viewports support). +This is essentially what each backend is doing + obligatory portability cruft. Using standard backends ensure you can get all those features including the ones that would be harder to implement on your side (e.g. multi-viewports support). It is important to understand the difference between the core Dear ImGui library (files in the root folder) and the backends which we are describing here (backends/ folder). @@ -47,11 +34,24 @@ and the backends which we are describing here (backends/ folder). - You should be able to write backends for pretty much any platform and any 3D graphics API. e.g. you can get creative and use software rendering or render remotely on a different machine. +### Standard backends + +**The [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder contains backends for popular platforms/graphics API, which you can use in +your application or engine to easily integrate Dear ImGui.** Each backend is typically self-contained in a pair of files: imgui_impl_XXXX.cpp + imgui_impl_XXXX.h. + +- The 'Platform' backends are in charge of: mouse/keyboard/gamepad inputs, cursor shape, timing, and windowing.
+ e.g. Windows ([imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp)), GLFW ([imgui_impl_glfw.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp)), SDL2 ([imgui_impl_sdl2.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_sdl2.cpp)), etc. + +- The 'Renderer' backends are in charge of: creating atlas texture, and rendering imgui draw data.
+ e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp)), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp)), etc. -### Integrating a backend +- For some high-level frameworks, a single backend usually handles both 'Platform' and 'Renderer' parts.
+ e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)). If you end up creating a custom backend for your engine, you may want to do the same. -See "Getting Started" section of [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for more details. +An application usually combines one Platform backend + one Renderer backend + main Dear ImGui sources. +For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. There are 20+ examples in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details. +**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.** ### List of backends diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index 4aa69a671f5f..66ad24ef7f81 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -35,46 +35,13 @@ At shutdown: call ImGui::DestroyContext() ``` -Example (using [backends/imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp) + [backends/imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)): +Main resource: +- Read **[Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) wiki guide** for detailed examples of how to integrate Dear ImGui in an existing application. -```cpp -// Create a Dear ImGui context, setup some options -ImGui::CreateContext(); -ImGuiIO& io = ImGui::GetIO(); -io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable some options - -// Initialize Platform + Renderer backends (here: using imgui_impl_win32.cpp + imgui_impl_dx11.cpp) -ImGui_ImplWin32_Init(my_hwnd); -ImGui_ImplDX11_Init(my_d3d_device, my_d3d_device_context); - -// Application main loop -while (true) -{ - // Beginning of frame: update Renderer + Platform backend, start Dear ImGui frame - ImGui_ImplDX11_NewFrame(); - ImGui_ImplWin32_NewFrame(); - ImGui::NewFrame(); - - // Any application code here - ImGui::Text("Hello, world!"); - - // End of frame: render Dear ImGui - ImGui::Render(); - ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); - - // Swap - g_pSwapChain->Present(1, 0); -} - -// Shutdown -ImGui_ImplDX11_Shutdown(); -ImGui_ImplWin32_Shutdown(); -ImGui::DestroyContext(); -``` - -Please read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup Dear ImGui in your codebase. -Please read the comments and instruction at the top of each file. -Please read FAQ at https://www.dearimgui.com/faq +Additional resources: +- Read FAQ at https://www.dearimgui.com/faq +- Read 'PROGRAMMER GUIDE' section in imgui.cpp. +- Read the comments and instruction at the top of each file. If you are using any of the backends provided here, you can add the backends/imgui_impl_xxxx(.cpp,.h) files to your project and use as-in. Each imgui_impl_xxxx.cpp file comes with its own individual diff --git a/docs/README.md b/docs/README.md index 78cf2fea0e36..2c976341c709 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ Businesses: support continued development and maintenance via invoiced sponsorin
  _E-mail: contact @ dearimgui dot com_
Individuals: support continued development and maintenance [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WGHNC6MBFLZ2S). Also see [Funding](https://github.com/ocornut/imgui/wiki/Funding) page. -| [The Pitch](#the-pitch) - [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Integration](#integration) | +| [The Pitch](#the-pitch) - [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Getting Started & Integration](#getting-started--integration) | :----------------------------------------------------------: | | [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - **[Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding)** - [Credits](#credits) - [License](#license) | | [Wiki](https://github.com/ocornut/imgui/wiki) - [Extensions](https://github.com/ocornut/imgui/wiki/Useful-Extensions) - [Languages bindings & frameworks backends](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) | @@ -43,7 +43,7 @@ Dear ImGui is particularly suited to integration in game engines (for tooling), **Backends for a variety of graphics API and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui. -See the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide and [Integration](#integration) section of this document for more details. +See the [Getting Started & Integration](#getting-started--integration) section of this document for more details. After Dear ImGui is set up in your application, you can use it from \_anywhere\_ in your program loop: ```cpp @@ -114,7 +114,7 @@ You should be able to build the examples from sources. If you don't, let us know The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at a different scale and scale your style with `style.ScaleAllSizes()` (see [FAQ](https://www.dearimgui.com/faq)). -### Integration +### Getting Started & Integration See the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide for details. From 96460a8a12615f3138173996f7481cc86c70a9f1 Mon Sep 17 00:00:00 2001 From: Laurent Dufresne Date: Sun, 28 Jul 2024 09:51:20 +0200 Subject: [PATCH 027/548] InputText: Added '\' and '/' as word seperator. (#7824, #7704) Adding those seperators means that ctrl+(left|right)-arrows and ctrl+backspace will stop at slashes, which is more inline with how most software works and generally is very convenient when dealing with paths or urls. --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f47d7d7d221e..dca2d32599c2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -146,6 +146,7 @@ Other changes: - Multi-Select (advanced) - Nav: fixed clicking window decorations (e.g. resize borders) from losing focused item when within a child window using ImGuiChildFlags_NavFlattened. +- InputText: added '\' and '/' as word seperator. (#7824, #7704) [@reduf] - Clipper: added SeekCursorForItem() function. When using ImGuiListClipper::Begin(INT_MAX) you can can use the clipper without knowing the amount of items beforehand. (#1311) In this situation, call ImGuiListClipper::SeekCursorForItem(items_count) as the end of your iteration diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1a11e3834986..b1ee63ce5eca 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3897,7 +3897,7 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob static bool is_separator(unsigned int c) { - return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r' || c=='.' || c=='!'; + return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r' || c=='.' || c=='!' || c=='\\' || c=='/'; } static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) From c7b925609777aec45326791c5105a433b3e4e3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20H=C3=A9rilier?= Date: Fri, 26 Jul 2024 13:19:22 +0200 Subject: [PATCH 028/548] Selectable: added ImGuiSelectableFlags_Highlight flag to highlight items independently from the hovered state. (#7820) Demo: Make the Widget/List boxes show how to use forced highlighting. --- docs/CHANGELOG.txt | 2 ++ imgui.h | 1 + imgui_demo.cpp | 33 +++++++++++++++++++++------------ imgui_widgets.cpp | 7 ++++--- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index dca2d32599c2..2ac60cd72fa2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -147,6 +147,8 @@ Other changes: - Nav: fixed clicking window decorations (e.g. resize borders) from losing focused item when within a child window using ImGuiChildFlags_NavFlattened. - InputText: added '\' and '/' as word seperator. (#7824, #7704) [@reduf] +- Selectable: added ImGuiSelectableFlags_Highlight flag to highlight items independently from + the hovered state. (#7820) [@rerilier] - Clipper: added SeekCursorForItem() function. When using ImGuiListClipper::Begin(INT_MAX) you can can use the clipper without knowing the amount of items beforehand. (#1311) In this situation, call ImGuiListClipper::SeekCursorForItem(items_count) as the end of your iteration diff --git a/imgui.h b/imgui.h index db9e59dadd9d..de7a4d2bcd34 100644 --- a/imgui.h +++ b/imgui.h @@ -1228,6 +1228,7 @@ enum ImGuiSelectableFlags_ ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text ImGuiSelectableFlags_AllowOverlap = 1 << 4, // (WIP) Hit testing to allow subsequent widgets to overlap this one + ImGuiSelectableFlags_Highlight = 1 << 5, // Make the item be displayed as if it is hovered #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiSelectableFlags_DontClosePopups = ImGuiSelectableFlags_NoAutoClosePopups, // Renamed in 1.91.0 diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8684bd0c6c3f..0c61352d7aef 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1357,18 +1357,18 @@ static void ShowDemoWindowWidgets(DemoWindowData* demo_data) // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively // stored in the object itself, etc.) const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; - static int item_current_idx = 0; // Here we store our selection data as an index. + static int item_selected_idx = 0; // Here we store our selection data as an index. // Pass in the preview value visible before opening the combo (it could technically be different contents or not pulled from items[]) - const char* combo_preview_value = items[item_current_idx]; + const char* combo_preview_value = items[item_selected_idx]; if (ImGui::BeginCombo("combo 1", combo_preview_value, flags)) { for (int n = 0; n < IM_ARRAYSIZE(items); n++) { - const bool is_selected = (item_current_idx == n); + const bool is_selected = (item_selected_idx == n); if (ImGui::Selectable(items[n], is_selected)) - item_current_idx = n; + item_selected_idx = n; // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) if (is_selected) @@ -1410,14 +1410,22 @@ static void ShowDemoWindowWidgets(DemoWindowData* demo_data) // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively // stored in the object itself, etc.) const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; - static int item_current_idx = 0; // Here we store our selection data as an index. + static int item_selected_idx = 0; // Here we store our selected data as an index. + + static bool item_highlight = false; + int item_highlighted_idx = -1; // Here we store our highlighted data as an index. + ImGui::Checkbox("Highlight hovered item in second listbox", &item_highlight); + if (ImGui::BeginListBox("listbox 1")) { for (int n = 0; n < IM_ARRAYSIZE(items); n++) { - const bool is_selected = (item_current_idx == n); + const bool is_selected = (item_selected_idx == n); if (ImGui::Selectable(items[n], is_selected)) - item_current_idx = n; + item_selected_idx = n; + + if (item_highlight && ImGui::IsItemHovered()) + item_highlighted_idx = n; // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) if (is_selected) @@ -1433,9 +1441,10 @@ static void ShowDemoWindowWidgets(DemoWindowData* demo_data) { for (int n = 0; n < IM_ARRAYSIZE(items); n++) { - const bool is_selected = (item_current_idx == n); - if (ImGui::Selectable(items[n], is_selected)) - item_current_idx = n; + bool is_selected = (item_selected_idx == n); + ImGuiSelectableFlags flags = (item_highlighted_idx == n) ? ImGuiSelectableFlags_Highlight : 0; + if (ImGui::Selectable(items[n], is_selected, flags)) + item_selected_idx = n; // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) if (is_selected) @@ -1482,8 +1491,8 @@ static void ShowDemoWindowWidgets(DemoWindowData* demo_data) ImGui::TreePop(); } - IMGUI_DEMO_MARKER("Widgets/Selectables/In columns"); - if (ImGui::TreeNode("In columns")) + IMGUI_DEMO_MARKER("Widgets/Selectables/In Tables"); + if (ImGui::TreeNode("In Tables")) { static bool selected[10] = {}; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index b1ee63ce5eca..31ba7d5c71a3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6894,14 +6894,15 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // Render if (is_visible) { - if (hovered || selected) + const bool highlighted = hovered || (flags & ImGuiSelectableFlags_Highlight); + if (highlighted || selected) { // FIXME-MULTISELECT: Styling: Color for 'selected' elements? ImGuiCol_HeaderSelected ImU32 col; - if (selected && !hovered) + if (selected && !highlighted) col = GetColorU32(ImLerp(GetStyleColorVec4(ImGuiCol_Header), GetStyleColorVec4(ImGuiCol_HeaderHovered), 0.5f)); else - col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); + col = GetColorU32((held && highlighted) ? ImGuiCol_HeaderActive : highlighted ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(bb.Min, bb.Max, col, false, 0.0f); } if (g.NavId == id) From 249d5caedbe6e598958b4987141ce5a197703173 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Jul 2024 15:19:42 +0200 Subject: [PATCH 029/548] Tables: storing LastFrozenHeight for frozen requests that don't have actual freezing due to zero scrolling. (#7821, #5143) Amend 0b4a1a40 (ignore whitespace to view this patch easily) --- imgui_tables.cpp | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index ce6fed1eab44..9c8262ff8a97 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1996,34 +1996,37 @@ void ImGui::TableEndRow(ImGuiTable* table) // We need to do that in TableEndRow() instead of TableBeginRow() so the list clipper can mark end of row and // get the new cursor position. if (unfreeze_rows_request) + { for (int column_n = 0; column_n < table->ColumnsCount; column_n++) table->Columns[column_n].NavLayerCurrent = ImGuiNavLayer_Main; - if (unfreeze_rows_actual) - { - IM_ASSERT(table->IsUnfrozenRows == false); const float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y); - table->IsUnfrozenRows = true; table_instance->LastFrozenHeight = y0 - table->OuterRect.Min.y; - // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect - table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y); - table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y; - table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen; - IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y); - - float row_height = table->RowPosY2 - table->RowPosY1; - table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y; - table->RowPosY1 = table->RowPosY2 - row_height; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) + if (unfreeze_rows_actual) { - ImGuiTableColumn* column = &table->Columns[column_n]; - column->DrawChannelCurrent = column->DrawChannelUnfrozen; - column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y; - } + IM_ASSERT(table->IsUnfrozenRows == false); + table->IsUnfrozenRows = true; + + // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect + table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y); + table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y; + table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen; + IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y); + + float row_height = table->RowPosY2 - table->RowPosY1; + table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y; + table->RowPosY1 = table->RowPosY2 - row_height; + for (int column_n = 0; column_n < table->ColumnsCount; column_n++) + { + ImGuiTableColumn* column = &table->Columns[column_n]; + column->DrawChannelCurrent = column->DrawChannelUnfrozen; + column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y; + } - // Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y - SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect); - table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent); + // Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y + SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect); + table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent); + } } if (!(table->RowFlags & ImGuiTableRowFlags_Headers)) From b847c414372928b6b919bc93d573adb1ff950c47 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Jul 2024 15:23:24 +0200 Subject: [PATCH 030/548] MultiSelect: BoxSelect: fixed using in frozen table. (#7821, #5143) + added Demo. Amend 0b4a1a40 --- imgui_demo.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ imgui_internal.h | 2 +- imgui_widgets.cpp | 26 +++++++++++++++++++++----- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0c61352d7aef..eba615e128af 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3306,6 +3306,52 @@ static void ShowDemoWindowMultiSelect(DemoWindowData* demo_data) ImGui::TreePop(); } + // Demonstrate using the clipper with BeginMultiSelect()/EndMultiSelect() + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (in a table)"); + if (ImGui::TreeNode("Multi-Select (in a table)")) + { + static ImGuiSelectionBasicStorage selection; + + const int ITEMS_COUNT = 10000; + ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT); + if (ImGui::BeginTable("##Basket", 2, ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter)) + { + ImGui::TableSetupColumn("Object"); + ImGui::TableSetupColumn("Action"); + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableHeadersRow(); + + ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d; + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT); + selection.ApplyRequests(ms_io); + + ImGuiListClipper clipper; + clipper.Begin(ITEMS_COUNT); + if (ms_io->RangeSrcItem != -1) + clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped. + while (clipper.Step()) + { + for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++) + { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + char label[64]; + sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]); + bool item_is_selected = selection.Contains((ImGuiID)n); + ImGui::SetNextItemSelectionUserData(n); + ImGui::Selectable(label, item_is_selected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap); + ImGui::TableNextColumn(); + ImGui::SmallButton("hello"); + } + } + + ms_io = ImGui::EndMultiSelect(); + selection.ApplyRequests(ms_io); + ImGui::EndTable(); + } + ImGui::TreePop(); + } + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (checkboxes)"); if (ImGui::TreeNode("Multi-Select (checkboxes)")) { diff --git a/imgui_internal.h b/imgui_internal.h index 0eaaa0f77dc5..db10a9468983 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3397,7 +3397,7 @@ namespace ImGui IMGUI_API int TypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data); // Box-Select API - IMGUI_API bool BeginBoxSelect(ImGuiWindow* window, ImGuiID box_select_id, ImGuiMultiSelectFlags ms_flags); + IMGUI_API bool BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiID box_select_id, ImGuiMultiSelectFlags ms_flags); IMGUI_API void EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flags); // Multi-Select API diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 31ba7d5c71a3..970bb067b1be 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7221,7 +7221,7 @@ static void BoxSelectScrollWithMouseDrag(ImGuiBoxSelectState* bs, ImGuiWindow* w } } -bool ImGui::BeginBoxSelect(ImGuiWindow* window, ImGuiID box_select_id, ImGuiMultiSelectFlags ms_flags) +bool ImGui::BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiID box_select_id, ImGuiMultiSelectFlags ms_flags) { ImGuiContext& g = *GImGui; ImGuiBoxSelectState* bs = &g.BoxSelectState; @@ -7241,11 +7241,10 @@ bool ImGui::BeginBoxSelect(ImGuiWindow* window, ImGuiID box_select_id, ImGuiMult // Current frame absolute prev/current rectangles are used to toggle selection. // They are derived from positions relative to scrolling space. - const ImRect scope_rect = window->InnerClipRect; ImVec2 start_pos_abs = WindowPosRelToAbs(window, bs->StartPosRel); ImVec2 prev_end_pos_abs = WindowPosRelToAbs(window, bs->EndPosRel); // Clamped already ImVec2 curr_end_pos_abs = g.IO.MousePos; - if (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) // Box-select scrolling only happens with ScopeWindow + if (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) // Box-select scrolling only happens with ScopeWindow curr_end_pos_abs = ImClamp(curr_end_pos_abs, scope_rect.Min, scope_rect.Max); bs->BoxSelectRectPrev.Min = ImMin(start_pos_abs, prev_end_pos_abs); bs->BoxSelectRectPrev.Max = ImMax(start_pos_abs, prev_end_pos_abs); @@ -7299,6 +7298,7 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag // [SECTION] Widgets: Multi-Select support //------------------------------------------------------------------------- // - DebugLogMultiSelectRequests() [Internal] +// - CalcScopeRect() [Internal] // - BeginMultiSelect() // - EndMultiSelect() // - SetNextItemSelectionUserData() @@ -7317,6 +7317,22 @@ static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSe } } +static ImRect CalcScopeRect(ImGuiMultiSelectTempData* ms, ImGuiWindow* window) +{ + if (ms->Flags & ImGuiMultiSelectFlags_ScopeRect) + { + // Warning: this depends on CursorMaxPos so it means to be called by EndMultiSelect() only + return ImRect(ms->ScopeRectMin, ImMax(window->DC.CursorMaxPos, ms->ScopeRectMin)); + } + else + { + // Add inner table decoration (#7821) // FIXME: Why not baking in InnerClipRect? + ImRect scope_rect = window->InnerClipRect; + scope_rect.Min = ImMin(scope_rect.Min + ImVec2(window->DecoInnerSizeX1, window->DecoInnerSizeY1), scope_rect.Max); + return scope_rect; + } +} + // Return ImGuiMultiSelectIO structure. // Lifetime: don't hold on ImGuiMultiSelectIO* pointers over multiple frames or past any subsequent call to BeginMultiSelect() or EndMultiSelect(). // Passing 'selection_size' and 'items_count' parameters is currently optional. @@ -7399,7 +7415,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel if (flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d)) { ms->BoxSelectId = GetID("##BoxSelect"); - if (BeginBoxSelect(window, ms->BoxSelectId, flags)) + if (BeginBoxSelect(CalcScopeRect(ms, window), window, ms->BoxSelectId, flags)) request_clear |= bs->RequestClear; } @@ -7452,7 +7468,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect() IM_ASSERT(g.CurrentMultiSelect != NULL && storage->Window == g.CurrentWindow); IM_ASSERT(g.MultiSelectTempDataStacked > 0 && &g.MultiSelectTempData[g.MultiSelectTempDataStacked - 1] == g.CurrentMultiSelect); - const ImRect scope_rect = (ms->Flags & ImGuiMultiSelectFlags_ScopeRect) ? ImRect(ms->ScopeRectMin, ImMax(window->DC.CursorMaxPos, ms->ScopeRectMin)) : window->InnerClipRect; + ImRect scope_rect = CalcScopeRect(ms, window); if (ms->IsFocused) { // We currently don't allow user code to modify RangeSrcItem by writing to BeginIO's version, but that would be an easy change here. From df387049268775acb9b69438632a5f5fce58a674 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Jul 2024 22:08:06 +0200 Subject: [PATCH 031/548] Added SetNextItemStorageID() for tree nodes. (#7553, #6990, #3823, #1131) Undo/amend 7c6d4ff. --- docs/CHANGELOG.txt | 3 +++ imgui.h | 1 + imgui_internal.h | 4 +++- imgui_widgets.cpp | 25 ++++++++++++++++++------- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2ac60cd72fa2..9fbd8b4f255b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -147,6 +147,9 @@ Other changes: - Nav: fixed clicking window decorations (e.g. resize borders) from losing focused item when within a child window using ImGuiChildFlags_NavFlattened. - InputText: added '\' and '/' as word seperator. (#7824, #7704) [@reduf] +- TreeNode: added SetNextItemStorageID() to specify/override the identifier used for persisting + open/close storage. Useful if needing to often read/write from storage without manipulating + the ID stack. (#7553, #6990, #3823, #1131) - Selectable: added ImGuiSelectableFlags_Highlight flag to highlight items independently from the hovered state. (#7820) [@rerilier] - Clipper: added SeekCursorForItem() function. When using ImGuiListClipper::Begin(INT_MAX) you can diff --git a/imgui.h b/imgui.h index de7a4d2bcd34..898308bb5a81 100644 --- a/imgui.h +++ b/imgui.h @@ -661,6 +661,7 @@ namespace ImGui IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header. IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. + IMGUI_API void SetNextItemStorageID(ImGuiID storage_id); // set id to use for open/close storage (default to same as item id). // Widgets: Selectables // - A selectable highlights when hovered, and can display another color when selected. diff --git a/imgui_internal.h b/imgui_internal.h index db10a9468983..7e9b22607fa2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1215,6 +1215,7 @@ enum ImGuiNextItemDataFlags_ ImGuiNextItemDataFlags_HasOpen = 1 << 1, ImGuiNextItemDataFlags_HasShortcut = 1 << 2, ImGuiNextItemDataFlags_HasRefVal = 1 << 3, + ImGuiNextItemDataFlags_HasStorageID = 1 << 4, }; struct ImGuiNextItemData @@ -1230,6 +1231,7 @@ struct ImGuiNextItemData bool OpenVal; // Set by SetNextItemOpen() ImU8 OpenCond; // Set by SetNextItemOpen() ImGuiDataTypeStorage RefVal; // Not exposed yet, for ImGuiInputTextFlags_ParseEmptyAsRefVal + ImGuiID StorageId; // Set by SetNextItemStorageID() ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; } inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()! @@ -3546,7 +3548,7 @@ namespace ImGui IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f, ImU32 bg_col = 0); // Widgets: Tree Nodes - IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); + IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); IMGUI_API void TreePushOverrideID(ImGuiID id); IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id); IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 970bb067b1be..8e35df6628c1 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6226,7 +6226,7 @@ bool ImGui::TreeNode(const char* label) if (window->SkipItems) return false; ImGuiID id = window->GetID(label); - return TreeNodeBehavior(id, id, ImGuiTreeNodeFlags_None, label, NULL); + return TreeNodeBehavior(id, ImGuiTreeNodeFlags_None, label, NULL); } bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) @@ -6245,7 +6245,7 @@ bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) if (window->SkipItems) return false; ImGuiID id = window->GetID(label); - return TreeNodeBehavior(id, id, flags, label, NULL); + return TreeNodeBehavior(id, flags, label, NULL); } bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) @@ -6275,7 +6275,7 @@ bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char ImGuiID id = window->GetID(str_id); const char* label, *label_end; ImFormatStringToTempBufferV(&label, &label_end, fmt, args); - return TreeNodeBehavior(id, id, flags, label, label_end); + return TreeNodeBehavior(id, flags, label, label_end); } bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) @@ -6287,7 +6287,7 @@ bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char ImGuiID id = window->GetID(ptr_id); const char* label, *label_end; ImFormatStringToTempBufferV(&label, &label_end, fmt, args); - return TreeNodeBehavior(id, id, flags, label, label_end); + return TreeNodeBehavior(id, flags, label, label_end); } bool ImGui::TreeNodeGetOpen(ImGuiID storage_id) @@ -6367,7 +6367,7 @@ static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags) } // When using public API, currently 'id == storage_id' is always true, but we separate the values to facilitate advanced user code doing storage queries outside of UI loop. -bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) +bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -6410,6 +6410,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f); // Compute open and multi-select states before ItemAdd() as it clear NextItem data. + ImGuiID storage_id = (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasStorageID) ? g.NextItemData.StorageId : id; bool is_open = TreeNodeUpdateNextOpen(storage_id, flags); bool is_visible; @@ -6694,6 +6695,16 @@ void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond) g.NextItemData.OpenCond = (ImU8)(cond ? cond : ImGuiCond_Always); } +// Set next TreeNode/CollapsingHeader storage id. +void ImGui::SetNextItemStorageID(ImGuiID storage_id) +{ + ImGuiContext& g = *GImGui; + if (g.CurrentWindow->SkipItems) + return; + g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasStorageID; + g.NextItemData.StorageId = storage_id; +} + // CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). // This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) @@ -6702,7 +6713,7 @@ bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) if (window->SkipItems) return false; ImGuiID id = window->GetID(label); - return TreeNodeBehavior(id, id, flags | ImGuiTreeNodeFlags_CollapsingHeader, label); + return TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader, label); } // p_visible == NULL : regular collapsing header @@ -6722,7 +6733,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFl flags |= ImGuiTreeNodeFlags_CollapsingHeader; if (p_visible) flags |= ImGuiTreeNodeFlags_AllowOverlap | (ImGuiTreeNodeFlags)ImGuiTreeNodeFlags_ClipLabelForTrailingButton; - bool is_open = TreeNodeBehavior(id, id, flags, label); + bool is_open = TreeNodeBehavior(id, flags, label); if (p_visible != NULL) { // Create a small overlapping close button From c2a3d5e47b08d7900b0fc7a12f1761510022a4d8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 29 Jul 2024 22:34:34 +0200 Subject: [PATCH 032/548] Comments, minor tweaks to ImGuiTextFilter. --- docs/CHANGELOG.txt | 9 +++++---- imgui.cpp | 10 ++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9fbd8b4f255b..1c4bd71a12bf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,10 +50,11 @@ Breaking changes: You should never need those functions! You can do everything in less a confusing manner by only using GetCursorScreenPos() and GetContentRegionAvail(). Also always consider that if you are using GetWindowPos() and GetCursorPos() you may also be making things unnecessarily complicated. - I repeat: You can do everything with GetCursorScreenPos() and GetContentRegionAvail()!! - - GetWindowContentRegionMax().x - GetCursorPos().x --> GetContentRegionAvail().x - - GetWindowContentRegionMax().x + GetWindowPos().x --> GetCursorScreenPos().x + GetContentRegionAvail().x - - GetContentRegionMax() --> GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos() // right edge in weird local coordinates + I repeat: You can do everything with GetCursorScreenPos() and GetContentRegionAvail()! + - GetWindowContentRegionMax().x - GetCursorPos().x --> GetContentRegionAvail().x + - GetWindowContentRegionMax().x + GetWindowPos().x --> GetCursorScreenPos().x + GetContentRegionAvail().x // when called from left edge of window + - GetContentRegionMax() --> GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos() // right edge in local coordinates + - GetWindowContentRegionMax().x - GetWindowContentRegionMin().x --> GetContentRegionAvail() // when called from left edge of window - Item flag changes: - Obsoleted PushButtonRepeat()/PopButtonRepeat() in favor of using new PushItemFlag()/PopItemFlag() with ImGuiItemFlags_ButtonRepeat. Kept inline redirecting functions (will obsolete). diff --git a/imgui.cpp b/imgui.cpp index 6b545d67d50c..6bd0c052a7fa 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -435,9 +435,11 @@ CODE - instead of: GetWindowContentRegionMax().x - GetCursorPos().x - you can use: GetContentRegionAvail().x - instead of: GetWindowContentRegionMax().x + GetWindowPos().x - - you can use: GetCursorScreenPos().x + GetContentRegionAvail().x (from left edge of window) + - you can use: GetCursorScreenPos().x + GetContentRegionAvail().x // when called from left edge of window - instead of: GetContentRegionMax() - - you cna use: GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos() // right edge in weird local coordinates + - you can use: GetContentRegionAvail() + GetCursorScreenPos() - GetWindowPos() // right edge in local coordinates + - instead of: GetWindowContentRegionMax().x - GetWindowContentRegionMin().x + - you can use: GetContentRegionAvail() // when called from left edge of window - 2024/07/15 (1.91.0) - renamed ImGuiSelectableFlags_DontClosePopups to ImGuiSelectableFlags_NoAutoClosePopups. (#1379, #1468, #2200, #4936, #5216, #7302, #7573) (internals: also renamed ImGuiItemFlags_SelectableDontClosePopup into ImGuiItemFlags_AutoClosePopups with inverted behaviors) - 2024/07/15 (1.91.0) - obsoleted PushButtonRepeat()/PopButtonRepeat() in favor of using new PushItemFlag(ImGuiItemFlags_ButtonRepeat, ...)/PopItemFlag(). @@ -2753,11 +2755,11 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const return true; if (text == NULL) - text = ""; + text = text_end = ""; for (const ImGuiTextRange& f : Filters) { - if (f.empty()) + if (f.b == f.e) continue; if (f.b[0] == '-') { From ce3a8d7c79f2490b7db1a55f19030654f9a6f600 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 21 Aug 2023 11:26:19 +0200 Subject: [PATCH 033/548] Demo: MultiSelect: added tree demo. (#6990, #3823, #1861) --- imgui_demo.cpp | 160 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 158 insertions(+), 2 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index eba615e128af..08798e181f34 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -262,13 +262,14 @@ void* GImGuiDemoMarkerCallbackUserData = NULL; struct ExampleTreeNode { // Tree structure - char Name[28]; + char Name[28] = ""; int UID = 0; ExampleTreeNode* Parent = NULL; ImVector Childs; + unsigned short IndexInParent = 0; // Maintaining this allows us to implement linear traversal more easily // Leaf Data - bool HasData = false; // All leaves have data + bool HasData = false; // All leaves have data bool DataMyBool = true; int DataMyInt = 128; ImVec2 DataMyVec2 = ImVec2(0.0f, 3.141592f); @@ -298,6 +299,7 @@ static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, Exampl snprintf(node->Name, IM_ARRAYSIZE(node->Name), "%s", name); node->UID = uid; node->Parent = parent; + node->IndexInParent = parent ? (unsigned short)parent->Childs.Size : 0; if (parent) parent->Childs.push_back(node); return node; @@ -3442,6 +3444,160 @@ static void ShowDemoWindowMultiSelect(DemoWindowData* demo_data) ImGui::TreePop(); } + // Demonstrate supporting multiple-selection in a tree. + // - We don't use linear indices for selection user data, but our ExampleTreeNode* pointer directly! + // This showcase how SetNextItemSelectionUserData() never assume indices! + // - The difficulty here is to "interpolate" from RangeSrcItem to RangeDstItem in the SetAll/SetRange request. + // We want this interpolation to match what the user sees: in visible order, skipping closed nodes. + // This is implemented by our TreeGetNextNodeInVisibleOrder() user-space helper. + // - Important: In a real codebase aiming to implement full-featured selectable tree with custom filtering, you + // are more likely to build an array mapping sequential indices to visible tree nodes, since your + // filtering/search + clipping process will benefit from it. Having this will make this interpolation much easier. + // - Consider this a prototype: we are working toward simplifying some of it. + IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (trees)"); + if (ImGui::TreeNode("Multi-Select (trees)")) + { + HelpMarker( + "This is rather advanced and experimental. If you are getting started with multi-select," + "please don't start by looking at how to use it for a tree!\n\n" + "Future versions will try to simplify and formalize some of this."); + + struct ExampleTreeFuncs + { + static void DrawNode(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection) + { + ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; + tree_node_flags |= ImGuiTreeNodeFlags_NavLeftJumpsBackHere; // Enable pressing left to jump to parent + if (node->Childs.Size == 0) + tree_node_flags |= ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_Leaf; + if (selection->Contains((ImGuiID)node->UID)) + tree_node_flags |= ImGuiTreeNodeFlags_Selected; + + // Using SetNextItemStorageID() to specify storage id, so we can easily peek into + // the storage holding open/close stage, using our TreeNodeGetOpen/TreeNodeSetOpen() functions. + ImGui::SetNextItemSelectionUserData((ImGuiSelectionUserData)(intptr_t)node); + ImGui::SetNextItemStorageID((ImGuiID)node->UID); + if (ImGui::TreeNodeEx(node->Name, tree_node_flags)) + { + for (ExampleTreeNode* child : node->Childs) + DrawNode(child, selection); + ImGui::TreePop(); + } + else if (ImGui::IsItemToggledOpen()) + { + TreeCloseAndUnselectChildNodes(node, selection); + } + } + + static bool TreeNodeGetOpen(ExampleTreeNode* node) + { + return ImGui::GetStateStorage()->GetBool((ImGuiID)node->UID); + } + + static void TreeNodeSetOpen(ExampleTreeNode* node, bool open) + { + ImGui::GetStateStorage()->SetBool((ImGuiID)node->UID, open); + } + + // When closing a node: 1) close and unselect all child nodes, 2) select parent if any child was selected. + // FIXME: This is currently handled by user logic but I'm hoping to eventually provide tree node + // features to do this automatically, e.g. a ImGuiTreeNodeFlags_AutoCloseChildNodes etc. + static int TreeCloseAndUnselectChildNodes(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection, int depth = 0) + { + // Recursive close (the test for depth == 0 is because we call this on a node that was just closed!) + int unselected_count = selection->Contains((ImGuiID)node->UID) ? 1 : 0; + if (depth == 0 || TreeNodeGetOpen(node)) + { + for (ExampleTreeNode* child : node->Childs) + unselected_count += TreeCloseAndUnselectChildNodes(child, selection, depth + 1); + TreeNodeSetOpen(node, false); + } + + // Select root node if any of its child was selected, otherwise unselect + selection->SetItemSelected((ImGuiID)node->UID, (depth == 0 && unselected_count > 0)); + return unselected_count; + } + + // Apply multi-selection requests + static void ApplySelectionRequests(ImGuiMultiSelectIO* ms_io, ExampleTreeNode* tree, ImGuiSelectionBasicStorage* selection) + { + for (ImGuiSelectionRequest& req : ms_io->Requests) + { + if (req.Type == ImGuiSelectionRequestType_SetAll) + { + if (req.Selected) + TreeSetAllInOpenNodes(tree, selection, req.Selected); + else + selection->Clear(); + } + else if (req.Type == ImGuiSelectionRequestType_SetRange) + { + ExampleTreeNode* first_node = (ExampleTreeNode*)(intptr_t)req.RangeFirstItem; + ExampleTreeNode* last_node = (ExampleTreeNode*)(intptr_t)req.RangeLastItem; + for (ExampleTreeNode* node = first_node; node != NULL; node = TreeGetNextNodeInVisibleOrder(node, last_node)) + selection->SetItemSelected((ImGuiID)node->UID, req.Selected); + } + } + } + + static void TreeSetAllInOpenNodes(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection, bool selected) + { + if (node->Parent != NULL) // Root node isn't visible nor selectable in our scheme + selection->SetItemSelected((ImGuiID)node->UID, selected); + if (node->Parent == NULL || TreeNodeGetOpen(node)) + for (ExampleTreeNode* child : node->Childs) + TreeSetAllInOpenNodes(child, selection, selected); + } + + // Interpolate in *user-visible order* AND only *over opened nodes*. + // If you have a sequential mapping tables (e.g. generated after a filter/search pass) this would be simpler. + // Here the tricks are that: + // - we store/maintain ExampleTreeNode::IndexInParent which allows implementing a linear iterator easily, without searches, without recursion. + // this could be replaced by a search in parent, aka 'int index_in_parent = curr_node->Parent->Childs.find_index(curr_node)' + // which would only be called when crossing from child to a parent, aka not too much. + // - we call SetNextItemStorageID() before our TreeNode() calls with an ID which doesn't relate to UI stack, + // making it easier to call TreeNodeGetOpen()/TreeNodeSetOpen() from any location. + static ExampleTreeNode* TreeGetNextNodeInVisibleOrder(ExampleTreeNode* curr_node, ExampleTreeNode* last_node) + { + // Reached last node + if (curr_node == last_node) + return NULL; + + // Recurse into childs. Query storage to tell if the node is open. + if (curr_node->Childs.Size > 0 && TreeNodeGetOpen(curr_node)) + return curr_node->Childs[0]; + + // Next sibling, then into our own parent + while (curr_node->Parent != NULL) + { + if (curr_node->IndexInParent + 1 < curr_node->Parent->Childs.Size) + return curr_node->Parent->Childs[curr_node->IndexInParent + 1]; + curr_node = curr_node->Parent; + } + return NULL; + } + + }; // ExampleTreeFuncs + + static ImGuiSelectionBasicStorage selection; + static ExampleTreeNode* tree = ExampleTree_CreateDemoTree(); // Create tree once + ImGui::Text("Selection size: %d", selection.Size); + + if (ImGui::BeginChild("##Tree", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) + { + ImGuiMultiSelectFlags ms_flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect2d; + ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ms_flags, selection.Size, -1); + ExampleTreeFuncs::ApplySelectionRequests(ms_io, tree, &selection); + for (ExampleTreeNode* node : tree->Childs) + ExampleTreeFuncs::DrawNode(node, &selection); + ms_io = ImGui::EndMultiSelect(); + ExampleTreeFuncs::ApplySelectionRequests(ms_io, tree, &selection); + } + ImGui::EndChild(); + + ImGui::TreePop(); + } + // Advanced demonstration of BeginMultiSelect() // - Showcase clipping. // - Showcase deletion. From 1f634f1d94e16feb3d0b15ad79e8bc44cccc184d Mon Sep 17 00:00:00 2001 From: SPeak Date: Tue, 30 Jul 2024 05:55:02 +0800 Subject: [PATCH 034/548] Eaxmples: Android: Fix build failed issue. (#7832) set android:exported to true (IntentFilter) Signed-off-by: Sunrisepeak --- .../android/app/src/main/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_android_opengl3/android/app/src/main/AndroidManifest.xml b/examples/example_android_opengl3/android/app/src/main/AndroidManifest.xml index a87b95b4f8f1..5a1e2d9e59f9 100644 --- a/examples/example_android_opengl3/android/app/src/main/AndroidManifest.xml +++ b/examples/example_android_opengl3/android/app/src/main/AndroidManifest.xml @@ -11,7 +11,7 @@ android:name="imgui.example.android.MainActivity" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:configChanges="orientation|keyboardHidden|screenSize" - android:exported="false"> + android:exported="true"> From 1b44e4044491b96c7bc30989f8d8c356bc57bada Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 30 Jul 2024 11:44:13 +0200 Subject: [PATCH 035/548] Demo: re-use tree data. Fix property editor vertical alignment. Tweak recent memory allocation monitor. --- imgui.cpp | 7 +++- imgui_demo.cpp | 93 +++++++++++++++++++++++++++----------------------- 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6bd0c052a7fa..97ee6fe1a725 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15070,7 +15070,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) for (int n = buf_size - 1; n >= 0; n--) { ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[(info->LastEntriesIdx - n + buf_size) % buf_size]; - BulletText("Frame %06d: %+3d ( %2d malloc, %2d free )%s", entry->FrameCount, entry->AllocCount - entry->FreeCount, entry->AllocCount, entry->FreeCount, (n == 0) ? " (most recent)" : ""); + BulletText("Frame %06d: %+3d ( %2d alloc, %2d free )", entry->FrameCount, entry->AllocCount - entry->FreeCount, entry->AllocCount, entry->FreeCount); + if (n == 0) + { + SameLine(); + Text("<- %d frames ago", g.FrameCount - entry->FrameCount); + } } TreePop(); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 08798e181f34..a5f7408c2dcf 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -199,6 +199,7 @@ Index of this file: #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) // Forward Declarations +struct ImGuiDemoWindowData; static void ShowExampleAppMainMenuBar(); static void ShowExampleAppAssetsBrowser(bool* p_open); static void ShowExampleAppConsole(bool* p_open); @@ -206,7 +207,7 @@ static void ShowExampleAppCustomRendering(bool* p_open); static void ShowExampleAppDocuments(bool* p_open); static void ShowExampleAppLog(bool* p_open); static void ShowExampleAppLayout(bool* p_open); -static void ShowExampleAppPropertyEditor(bool* p_open); +static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data); static void ShowExampleAppSimpleOverlay(bool* p_open); static void ShowExampleAppAutoResize(bool* p_open); static void ShowExampleAppConstrainedResize(bool* p_open); @@ -217,10 +218,9 @@ static void ShowExampleMenuFile(); // We split the contents of the big ShowDemoWindow() function into smaller functions // (because the link time of very large functions tends to grow non-linearly) -struct DemoWindowData; -static void ShowDemoWindowMenuBar(DemoWindowData* demo_data); -static void ShowDemoWindowWidgets(DemoWindowData* demo_data); -static void ShowDemoWindowMultiSelect(DemoWindowData* demo_data); +static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data); +static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data); +static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data); static void ShowDemoWindowLayout(); static void ShowDemoWindowPopups(); static void ShowDemoWindowTables(); @@ -309,13 +309,14 @@ static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, Exampl // (this allocates _many_ more times than most other code in either Dear ImGui or others demo) static ExampleTreeNode* ExampleTree_CreateDemoTree() { - static const char* root_names[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; + static const char* root_names[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pear", "Pineapple", "Strawberry", "Watermelon" }; char name_buf[32]; int uid = 0; ExampleTreeNode* node_L0 = ExampleTree_CreateNode("", ++uid, NULL); - for (int idx_L0 = 0; idx_L0 < IM_ARRAYSIZE(root_names) * 2; idx_L0++) + const int root_items_multiplier = 2; + for (int idx_L0 = 0; idx_L0 < IM_ARRAYSIZE(root_names) * root_items_multiplier; idx_L0++) { - snprintf(name_buf, 32, "%s %d", root_names[idx_L0 / 2], idx_L0 % 2); + snprintf(name_buf, 32, "%s %d", root_names[idx_L0 / root_items_multiplier], idx_L0 % root_items_multiplier); ExampleTreeNode* node_L1 = ExampleTree_CreateNode(name_buf, ++uid, node_L0); const int number_of_childs = (int)strlen(node_L1->Name); for (int idx_L1 = 0; idx_L1 < number_of_childs; idx_L1++) @@ -338,7 +339,8 @@ static ExampleTreeNode* ExampleTree_CreateDemoTree() // [SECTION] Demo Window / ShowDemoWindow() //----------------------------------------------------------------------------- -struct DemoWindowData +// Data to be shared accross different functions of the demo. +struct ImGuiDemoWindowData { // Examples Apps (accessible from the "Examples" menu) bool ShowMainMenuBar = false; @@ -362,6 +364,9 @@ struct DemoWindowData bool ShowIDStackTool = false; bool ShowStyleEditor = false; bool ShowAbout = false; + + // Other data + ExampleTreeNode* DemoTree = NULL; }; // Demonstrate most Dear ImGui features (this is big function!) @@ -377,32 +382,32 @@ void ImGui::ShowDemoWindow(bool* p_open) IMGUI_CHECKVERSION(); // Stored data - static DemoWindowData demo; + static ImGuiDemoWindowData demo_data; // Examples Apps (accessible from the "Examples" menu) - if (demo.ShowMainMenuBar) { ShowExampleAppMainMenuBar(); } - if (demo.ShowAppDocuments) { ShowExampleAppDocuments(&demo.ShowAppDocuments); } - if (demo.ShowAppAssetsBrowser) { ShowExampleAppAssetsBrowser(&demo.ShowAppAssetsBrowser); } - if (demo.ShowAppConsole) { ShowExampleAppConsole(&demo.ShowAppConsole); } - if (demo.ShowAppCustomRendering) { ShowExampleAppCustomRendering(&demo.ShowAppCustomRendering); } - if (demo.ShowAppLog) { ShowExampleAppLog(&demo.ShowAppLog); } - if (demo.ShowAppLayout) { ShowExampleAppLayout(&demo.ShowAppLayout); } - if (demo.ShowAppPropertyEditor) { ShowExampleAppPropertyEditor(&demo.ShowAppPropertyEditor); } - if (demo.ShowAppSimpleOverlay) { ShowExampleAppSimpleOverlay(&demo.ShowAppSimpleOverlay); } - if (demo.ShowAppAutoResize) { ShowExampleAppAutoResize(&demo.ShowAppAutoResize); } - if (demo.ShowAppConstrainedResize) { ShowExampleAppConstrainedResize(&demo.ShowAppConstrainedResize); } - if (demo.ShowAppFullscreen) { ShowExampleAppFullscreen(&demo.ShowAppFullscreen); } - if (demo.ShowAppLongText) { ShowExampleAppLongText(&demo.ShowAppLongText); } - if (demo.ShowAppWindowTitles) { ShowExampleAppWindowTitles(&demo.ShowAppWindowTitles); } + if (demo_data.ShowMainMenuBar) { ShowExampleAppMainMenuBar(); } + if (demo_data.ShowAppDocuments) { ShowExampleAppDocuments(&demo_data.ShowAppDocuments); } + if (demo_data.ShowAppAssetsBrowser) { ShowExampleAppAssetsBrowser(&demo_data.ShowAppAssetsBrowser); } + if (demo_data.ShowAppConsole) { ShowExampleAppConsole(&demo_data.ShowAppConsole); } + if (demo_data.ShowAppCustomRendering) { ShowExampleAppCustomRendering(&demo_data.ShowAppCustomRendering); } + if (demo_data.ShowAppLog) { ShowExampleAppLog(&demo_data.ShowAppLog); } + if (demo_data.ShowAppLayout) { ShowExampleAppLayout(&demo_data.ShowAppLayout); } + if (demo_data.ShowAppPropertyEditor) { ShowExampleAppPropertyEditor(&demo_data.ShowAppPropertyEditor, &demo_data); } + if (demo_data.ShowAppSimpleOverlay) { ShowExampleAppSimpleOverlay(&demo_data.ShowAppSimpleOverlay); } + if (demo_data.ShowAppAutoResize) { ShowExampleAppAutoResize(&demo_data.ShowAppAutoResize); } + if (demo_data.ShowAppConstrainedResize) { ShowExampleAppConstrainedResize(&demo_data.ShowAppConstrainedResize); } + if (demo_data.ShowAppFullscreen) { ShowExampleAppFullscreen(&demo_data.ShowAppFullscreen); } + if (demo_data.ShowAppLongText) { ShowExampleAppLongText(&demo_data.ShowAppLongText); } + if (demo_data.ShowAppWindowTitles) { ShowExampleAppWindowTitles(&demo_data.ShowAppWindowTitles); } // Dear ImGui Tools (accessible from the "Tools" menu) - if (demo.ShowMetrics) { ImGui::ShowMetricsWindow(&demo.ShowMetrics); } - if (demo.ShowDebugLog) { ImGui::ShowDebugLogWindow(&demo.ShowDebugLog); } - if (demo.ShowIDStackTool) { ImGui::ShowIDStackToolWindow(&demo.ShowIDStackTool); } - if (demo.ShowAbout) { ImGui::ShowAboutWindow(&demo.ShowAbout); } - if (demo.ShowStyleEditor) + if (demo_data.ShowMetrics) { ImGui::ShowMetricsWindow(&demo_data.ShowMetrics); } + if (demo_data.ShowDebugLog) { ImGui::ShowDebugLogWindow(&demo_data.ShowDebugLog); } + if (demo_data.ShowIDStackTool) { ImGui::ShowIDStackToolWindow(&demo_data.ShowIDStackTool); } + if (demo_data.ShowAbout) { ImGui::ShowAboutWindow(&demo_data.ShowAbout); } + if (demo_data.ShowStyleEditor) { - ImGui::Begin("Dear ImGui Style Editor", &demo.ShowStyleEditor); + ImGui::Begin("Dear ImGui Style Editor", &demo_data.ShowStyleEditor); ImGui::ShowStyleEditor(); ImGui::End(); } @@ -452,7 +457,7 @@ void ImGui::ShowDemoWindow(bool* p_open) //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f); // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align) // Menu Bar - ShowDemoWindowMenuBar(&demo); + ShowDemoWindowMenuBar(&demo_data); ImGui::Text("dear imgui says hello! (%s) (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM); ImGui::Spacing(); @@ -573,7 +578,7 @@ void ImGui::ShowDemoWindow(bool* p_open) IMGUI_DEMO_MARKER("Configuration/Style"); if (ImGui::TreeNode("Style")) { - ImGui::Checkbox("Style Editor", &demo.ShowStyleEditor); + ImGui::Checkbox("Style Editor", &demo_data.ShowStyleEditor); ImGui::SameLine(); HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function."); ImGui::TreePop(); @@ -621,7 +626,7 @@ void ImGui::ShowDemoWindow(bool* p_open) } // All demo contents - ShowDemoWindowWidgets(&demo); + ShowDemoWindowWidgets(&demo_data); ShowDemoWindowLayout(); ShowDemoWindowPopups(); ShowDemoWindowTables(); @@ -636,7 +641,7 @@ void ImGui::ShowDemoWindow(bool* p_open) // [SECTION] ShowDemoWindowMenuBar() //----------------------------------------------------------------------------- -static void ShowDemoWindowMenuBar(DemoWindowData* demo_data) +static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data) { IMGUI_DEMO_MARKER("Menu"); if (ImGui::BeginMenuBar()) @@ -701,7 +706,7 @@ static void ShowDemoWindowMenuBar(DemoWindowData* demo_data) // [SECTION] ShowDemoWindowWidgets() //----------------------------------------------------------------------------- -static void ShowDemoWindowWidgets(DemoWindowData* demo_data) +static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) { IMGUI_DEMO_MARKER("Widgets"); //ImGui::SetNextItemOpen(true, ImGuiCond_Once); @@ -3098,7 +3103,7 @@ struct ExampleDualListBox // Also read: https://github.com/ocornut/imgui/wiki/Multi-Select //----------------------------------------------------------------------------- -static void ShowDemoWindowMultiSelect(DemoWindowData* demo_data) +static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data) { IMGUI_DEMO_MARKER("Widgets/Selection State & Multi-Select"); if (ImGui::TreeNode("Selection State & Multi-Select")) @@ -3580,11 +3585,13 @@ static void ShowDemoWindowMultiSelect(DemoWindowData* demo_data) }; // ExampleTreeFuncs static ImGuiSelectionBasicStorage selection; - static ExampleTreeNode* tree = ExampleTree_CreateDemoTree(); // Create tree once + if (demo_data->DemoTree == NULL) + demo_data->DemoTree = ExampleTree_CreateDemoTree(); // Create tree once ImGui::Text("Selection size: %d", selection.Size); if (ImGui::BeginChild("##Tree", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY)) { + ExampleTreeNode* tree = demo_data->DemoTree; ImGuiMultiSelectFlags ms_flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect2d; ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ms_flags, selection.Size, -1); ExampleTreeFuncs::ApplySelectionRequests(ms_io, tree, &selection); @@ -4597,8 +4604,8 @@ static void ShowDemoWindowLayout() ImGui::TreePop(); } - IMGUI_DEMO_MARKER("Layout/Clipping"); - if (ImGui::TreeNode("Clipping")) + IMGUI_DEMO_MARKER("Layout/Text Clipping"); + if (ImGui::TreeNode("Text Clipping")) { static ImVec2 size(100.0f, 100.0f); static ImVec2 offset(30.0f, 30.0f); @@ -8868,6 +8875,7 @@ struct ExampleAppPropertyEditor ImGui::TableNextRow(); ImGui::PushID(field_desc.Name); ImGui::TableNextColumn(); + ImGui::AlignTextToFramePadding(); ImGui::TextUnformatted(field_desc.Name); ImGui::TableNextColumn(); void* field_ptr = (void*)(((unsigned char*)node) + field_desc.Offset); @@ -8933,7 +8941,7 @@ struct ExampleAppPropertyEditor }; // Demonstrate creating a simple property editor. -static void ShowExampleAppPropertyEditor(bool* p_open) +static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data) { ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver); if (!ImGui::Begin("Example: Property editor", p_open)) @@ -8944,8 +8952,9 @@ static void ShowExampleAppPropertyEditor(bool* p_open) IMGUI_DEMO_MARKER("Examples/Property Editor"); static ExampleAppPropertyEditor property_editor; - static ExampleTreeNode* tree_data = ExampleTree_CreateDemoTree(); - property_editor.Draw(tree_data); + if (demo_data->DemoTree == NULL) + demo_data->DemoTree = ExampleTree_CreateDemoTree(); + property_editor.Draw(demo_data->DemoTree); ImGui::End(); } From ec9a4ef487acde06cf1840b1b13310a6c0ba7d62 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 30 Jul 2024 12:22:29 +0200 Subject: [PATCH 036/548] Clipper: accept that no item have been submitted if in indeterminate Begin(INT_MAX) mode. (#1311, #3823) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 97ee6fe1a725..728fc083238e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3062,7 +3062,8 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y); if (affected_by_floating_point_precision) clipper->ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries. - + if (clipper->ItemsHeight == 0.0f && clipper->ItemsCount == INT_MAX) // Accept that no item have been submitted if in indeterminate mode. + return false; IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!"); calc_clipping = true; // If item height had to be calculated, calculate clipping afterwards. } From 8199457a7d9e453f8d3d9cadc14683fb54a858b5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 30 Jul 2024 14:49:07 +0200 Subject: [PATCH 037/548] Version 1.91.0 --- docs/CHANGELOG.txt | 110 ++++++++++++++++++++++++--------------------- imgui.cpp | 4 +- imgui.h | 22 ++++----- imgui_demo.cpp | 4 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 78 insertions(+), 70 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1c4bd71a12bf..8c83dadff52a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,9 +36,11 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.91.0 WIP (In Progress) + VERSION 1.91.0 (Released 2024-07-30) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.0 + Breaking changes: - IO, IME: renamed platform IME hook and added explicit context for consistency and future-proofness. @@ -46,7 +48,7 @@ Breaking changes: - new: io.PlatformSetImeDataFn(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); It is expected that for a vast majority of users this is automatically set by core library and/or platform backend so it won't have any effect. -- Obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). +- Obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). (#7838) You should never need those functions! You can do everything in less a confusing manner by only using GetCursorScreenPos() and GetContentRegionAvail(). Also always consider that if you are using GetWindowPos() and GetCursorPos() you may also be making things unnecessarily complicated. @@ -69,32 +71,24 @@ Breaking changes: - Commented out obsolete ImGuiModFlags_XXX values (renamed to ImGuiMod_XXX in 1.89). (#4921, #456) - ImGuiModFlags_Ctrl -> ImGuiMod_Ctrl, ImGuiModFlags_Shift -> ImGuiMod_Shift etc. - Backends: GLFW+Emscripten: Renamed ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to - ImGui_ImplGlfw_InstallEmscriptenCallbacks(), with additional GLFWWindow* parameter. (#7647) [@ypujante] + ImGui_ImplGlfw_InstallEmscriptenCallbacks(), with an additional GLFWWindow* parameter. (#7647) [@ypujante] Other changes: - Added TextLink(), TextLinkOpenURL() hyperlink widgets. (#7660) - IO: added io.PlatformOpenInShellFn handler to open a link/folder/file in OS shell. (#7660) - Default to use ShellExecute() under Windows, and system("") under Mac/Linux/etc. - Added IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS to disable default implementation. -- IO: added io.ConfigNavSwapGamepadButtons to swap Activate/Cancel (A<>B) buttons, to match tye + Added IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS to disable default Windows/Linux/Mac implementations. +- IO: added io.ConfigNavSwapGamepadButtons to swap Activate/Cancel (A<>B) buttons, to match the typical "Nintendo/Japanese consoles" button layout when using Gamepad navigation. (#787, #5723) - Added PushItemFlag()/PopItemFlags(), ImGuiItemFlags to modify shared item flags: - - Added ImGuiItemFlags_NoTabStop to disable tabbing through items. - - Added ImGuiItemFlags_NoNav to disable any navigation and focus of items. (#787) - - Added ImGuiItemFlags_NoNavDefaultFocus to disable item being default focus. (#787) - - Added ImGuiItemFlags_ButtonRepeat to enable repeat on any button-like behavior. - - Added ImGuiItemFlags_AutoClosePopups to disable menu items/selection auto closing parent popups. - Disabling this was previously possible for Selectable() via a direct flag but not for MenuItem(). - (#1379, #1468, #2200, #4936, #5216, #7302, #7573) - - This was mostly all previously in imgui_internal.h. -- Inputs: added SetItemKeyOwner(ImGuiKey key) in public API. This is a simplified version of a more - complete set of function available in imgui_internal.h. One common use-case for this is to allow - your items to disable standard inputs behaviors such as Tab or Alt handling, Mouse Wheel scrolling, - etc. (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641) - // Hovering or activating the button will disable mouse wheel default behavior to scroll - InvisibleButton(...); - SetItemKeyOwner(ImGuiKey_MouseWheelY); + - Added ImGuiItemFlags_NoTabStop to disable tabbing through items. + - Added ImGuiItemFlags_NoNav to disable any navigation and focus of items. (#787) + - Added ImGuiItemFlags_NoNavDefaultFocus to disable item being default focus. (#787) + - Added ImGuiItemFlags_ButtonRepeat to enable repeat on any button-like behavior. + - Added ImGuiItemFlags_AutoClosePopups to disable menu items/selection auto closing parent popups. + Disabling this was previously possible for Selectable() via a direct flag but not for MenuItem(). + (#1379, #1468, #2200, #4936, #5216, #7302, #7573) + - This was mostly all previously in imgui_internal.h. - Multi-Select: added multi-select API and demos. (#1861, #6518) - This system implements standard multi-selection idioms (CTRL+mouse click, CTRL+keyboard moves, SHIFT+mouse click, SHIFT+keyboard moves, etc.) with support for clipper (not submitting non-visible @@ -103,15 +97,16 @@ Other changes: This is designed to allow all kinds of selection storage you may use in your application (e.g. set/map/hash, intrusive selection, interval trees, up to you). - The supported widgets are Selectable(), Checkbox(). TreeNode() is also technically supported but... - using this correctly is more complicated (you need some sort of linear/random access to your tree, + using this correctly is more complicated. You need some sort of linear/random access to your tree, which is suited to advanced trees setups already implementing filters and clipper. - We will work toward simplifying and demoing this later. - - A helper ImGuiSelectionBasicStorage is provided to facilitate getting started in a typical app. + We will work toward simplifying our existing demo for trees. + - A helper ImGuiSelectionBasicStorage is provided to facilitate getting started in a typical app + (likely to suit a majority of users). - Documentation: - Wiki page https://github.com/ocornut/imgui/wiki/Multi-Select for API overview. - Demo code + headers are well commented. - Added BeginMultiSelect(), EndMultiSelect(), SetNextItemSelectionUserData(). - - Added IsItemToggledSelection() for use if you need latest selection update during currnet iteration. + - Added IsItemToggledSelection() for use if you need latest selection update during current iteration. - Added ImGuiMultiSelectIO and ImGuiSelectionRequest structures: - BeginMultiSelect() and EndMultiSelect() return a ImGuiMultiSelectIO structure, which is mostly an array of ImGuiSelectionRequest actions (clear, select all, set range, etc.) @@ -142,12 +137,23 @@ Other changes: - Multi-Select (with clipper) - Multi-Select (with deletion) - Multi-Select (dual list box) (#6648) + - Multi-Select (in a table) - Multi-Select (checkboxes) - Multi-Select (multiple scopes) + - Multi-Select (tiled assert browser) + - Multi-Select (trees) (#1861) - Multi-Select (advanced) +- Inputs: added SetItemKeyOwner(ImGuiKey key) in public API. + This is a simplified version of a more complete set of function available in imgui_internal.h. + One common use-case for this is to allow your widgets to disable standard inputs behaviors such + as Tab or Alt handling, Mouse Wheel scrolling, etc. + (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641) + // Hovering or activating the button will disable mouse wheel default behavior to scroll + InvisibleButton(...); + SetItemKeyOwner(ImGuiKey_MouseWheelY); - Nav: fixed clicking window decorations (e.g. resize borders) from losing focused item when within a child window using ImGuiChildFlags_NavFlattened. -- InputText: added '\' and '/' as word seperator. (#7824, #7704) [@reduf] +- InputText: added '\' and '/' as word separator. (#7824, #7704) [@reduf] - TreeNode: added SetNextItemStorageID() to specify/override the identifier used for persisting open/close storage. Useful if needing to often read/write from storage without manipulating the ID stack. (#7553, #6990, #3823, #1131) @@ -155,35 +161,37 @@ Other changes: the hovered state. (#7820) [@rerilier] - Clipper: added SeekCursorForItem() function. When using ImGuiListClipper::Begin(INT_MAX) you can can use the clipper without knowing the amount of items beforehand. (#1311) - In this situation, call ImGuiListClipper::SeekCursorForItem(items_count) as the end of your iteration + In this situation, call ImGuiListClipper::SeekCursorForItem(items_count) at the end of your iteration loop to position the layout cursor correctly. This is done automatically if provided a count to Begin(). - Groups, Tables: fixed EndGroup() failing to correctly capture current table occupied size. (#7543) -- TabBar, Style: added style.TabBarOverlineSize / ImGuiStyleVar_TabBarOverlineSize to manipulate - thickness of the horizontal line over selectable tabs. [@DctrNoob] -- Misc: added GetID(int) variant for consistency. (#7111) +- Style, TabBar: added style.TabBarOverlineSize / ImGuiStyleVar_TabBarOverlineSize to manipulate + thickness of the horizontal line over selected tabs. [@DctrNoob] - Style: close button and collapse/window-menu button hover highlight made rectangular instead of round. -- Debug Tools: Added IMGUI_DEBUG_LOG(), ImGui::DebugLog() in public API. (#5855) - Debug log entries add a imgui frame counter prefix + are redirected to ShowDebugLogWindow() and - other configurable locations. Always call IMGUI_DEBUG_LOG() for maximum stripping in caller code. -- Debug Tools: Debug Log: Added "Configure Outputs.." button. (#5855) -- Debug Tools: Debug Log: Fixed incorrect checkbox layout when partially clipped. -- Demo: Reworked "Property Editor" demo in a manner that more ressemble the tree data and +- Misc: added GetID(int) variant for consistency. (#7111) +- Debug Tools: + - Debug Log: Added IMGUI_DEBUG_LOG(), ImGui::DebugLog() in public API. (#5855) + Printed entries include imgui frame counter prefix + are redirected to ShowDebugLogWindow() and + other configurable locations. Always call IMGUI_DEBUG_LOG() for maximum stripping in caller code. + - Debug Log: Added "Configure Outputs.." button. (#5855) + - Debug Log: Fixed incorrect checkbox layout when partially clipped. +- Demo: Reworked "Property Editor" demo in a manner that more resemble the tree data and struct description data that a real application would want to use. -- Backends: Win32: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. - (#7768, #4858, #2622) [@Aemony] -- Backends: SDL3: Update for API changes: SDL_GetGamepads() memory ownership change. (#7807) -- Backends: SDL3: Update for API changes: SDL_GetClipboardText() memory ownership change. (#7801) -- Backends: SDL3: Update for API changes: SDLK_x renames and SDLK_KP_x removals (#7761, #7762) -- Backends: SDL3: Update for API changes: SDL_GetProperty() change to SDL_GetPointerProperty(). (#7794) [@wermipls] -- Backends: SDL2,SDL3,OSX: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() rename. -- Backends: GLFW,SDL2: Added io.PlatformOpenInShellFn handler for web/Emscripten versions. (#7660) - [@ypujante, @ocornut] -- Backends; GLFW+Emscripten: Added support for GLFW3 contrib port which fixes many of the things - not supported by the embedded GLFW: gamepad support, mouse cursor shapes, copy to clipboard, - workaround for Super/Meta key, different ways of resizing, multi-window (glfw/canvas) support. - (#7647) [@ypujante] -- Backends: GLFW+Emscripten: Fixed Emscripten warning when using mouse wheel on some setups - "Unable to preventDefault inside passive event listener". (#7647, #7600) [@ypujante] +- Backends: + - Backends: Win32: Fixed ImGuiMod_Super being mapped to VK_APPS instead of (VK_LWIN || VK_RWIN). + (#7768, #4858, #2622) [@Aemony] + - Backends: SDL3: Update for API changes: SDL_GetGamepads() memory ownership change. (#7807) + - Backends: SDL3: Update for API changes: SDL_GetClipboardText() memory ownership change. (#7801) + - Backends: SDL3: Update for API changes: SDLK_x renames and SDLK_KP_x removals (#7761, #7762) + - Backends: SDL3: Update for API changes: SDL_GetProperty() change to SDL_GetPointerProperty(). (#7794) [@wermipls] + - Backends: SDL2,SDL3,OSX: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() rename. + - Backends: GLFW,SDL2: Added io.PlatformOpenInShellFn handler for web/Emscripten versions. (#7660) + [@ypujante, @ocornut] + - Backends; GLFW+Emscripten: Added support for GLFW3 contrib port which fixes many of the things + not supported by the embedded GLFW: gamepad support, mouse cursor shapes, copy to clipboard, + workaround for Super/Meta key, different ways of resizing, multi-window (glfw/canvas) support. + (#7647) [@ypujante] + - Backends: GLFW+Emscripten: Fixed Emscripten warning when using mouse wheel on some setups + "Unable to preventDefault inside passive event listener". (#7647, #7600) [@ypujante] ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 728fc083238e..2c8611266046 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 WIP +// dear imgui, v1.91.0 // (main code and documentation) // Help: @@ -430,7 +430,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. - - 2024/07/25 (1.91.0) - obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). + - 2024/07/25 (1.91.0) - obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). (see #7838 on GitHub for more info) you should never need those functions. you can do everything with GetCursorScreenPos() and GetContentRegionAvail() in a more simple way. - instead of: GetWindowContentRegionMax().x - GetCursorPos().x - you can use: GetContentRegionAvail().x diff --git a/imgui.h b/imgui.h index 898308bb5a81..05e48a175821 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 WIP +// dear imgui, v1.91.0 // (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 WIP" -#define IMGUI_VERSION_NUM 19099 +#define IMGUI_VERSION "1.91.0" +#define IMGUI_VERSION_NUM 19100 #define IMGUI_HAS_TABLE /* @@ -480,7 +480,7 @@ namespace ImGui IMGUI_API void SetCursorPos(const ImVec2& local_pos); // [window-local] " IMGUI_API void SetCursorPosX(float local_x); // [window-local] " IMGUI_API void SetCursorPosY(float local_y); // [window-local] " - IMGUI_API ImVec2 GetCursorStartPos(); // [window-local] initial cursor position, in window-local coordinates + IMGUI_API ImVec2 GetCursorStartPos(); // [window-local] initial cursor position, in window-local coordinates. Call GetCursorScreenPos() after Begin() to get the absolute coordinates version. // Other layout functions IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. @@ -669,12 +669,12 @@ namespace ImGui IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. - // Multi-selection system for Selectable(), Checkbox() functions* + // Multi-selection system for Selectable(), Checkbox(), TreeNode() functions [BETA] // - This enables standard multi-selection/range-selection idioms (CTRL+Mouse/Keyboard, SHIFT+Mouse/Keyboard, etc.) in a way that also allow a clipper to be used. // - ImGuiSelectionUserData is often used to store your item index within the current view (but may store something else). // - Read comments near ImGuiMultiSelectIO for instructions/details and see 'Demo->Widgets->Selection State & Multi-Select' for demo. - // - (*) TreeNode() is technically supported but... using this correctly is more complicate: you need some sort of linear/random access to your tree, - // which is suited to advanced trees setups already implementing filters and clipper. We will work toward simplifying and demoing this. + // - TreeNode() is technically supported but... using this correctly is more complicated. You need some sort of linear/random access to your tree, + // which is suited to advanced trees setups already implementing filters and clipper. We will work simplifying the current demo. // - 'selection_size' and 'items_count' parameters are optional and used by a few features. If they are costly for you to compute, you may avoid them. IMGUI_API ImGuiMultiSelectIO* BeginMultiSelect(ImGuiMultiSelectFlags flags, int selection_size = -1, int items_count = -1); IMGUI_API ImGuiMultiSelectIO* EndMultiSelect(); @@ -2781,10 +2781,10 @@ enum ImGuiMultiSelectFlags_ ImGuiMultiSelectFlags_SingleSelect = 1 << 0, // Disable selecting more than one item. This is available to allow single-selection code to share same code/logic if desired. It essentially disables the main purpose of BeginMultiSelect() tho! ImGuiMultiSelectFlags_NoSelectAll = 1 << 1, // Disable CTRL+A shortcut to select all. ImGuiMultiSelectFlags_NoRangeSelect = 1 << 2, // Disable Shift+selection mouse/keyboard support (useful for unordered 2D selection). With BoxSelect is also ensure contiguous SetRange requests are not combined into one. This allows not handling interpolation in SetRange requests. - ImGuiMultiSelectFlags_NoAutoSelect = 1 << 3, // Disable selecting items when navigating (useful for e.g. supporting range-select in a list of checkboxes) - ImGuiMultiSelectFlags_NoAutoClear = 1 << 4, // Disable clearing selection when navigating or selecting another one (generally used with ImGuiMultiSelectFlags_NoAutoSelect. useful for e.g. supporting range-select in a list of checkboxes) - ImGuiMultiSelectFlags_NoAutoClearOnReselect = 1 << 5, // Disable clearing selection when clicking/selecting an already selected item - ImGuiMultiSelectFlags_BoxSelect1d = 1 << 6, // Enable box-selection with same width and same x pos items (e.g. only full row Selectable()). Box-selection works better with little bit of spacing between items hit-box in order to be able to aim at empty space. + ImGuiMultiSelectFlags_NoAutoSelect = 1 << 3, // Disable selecting items when navigating (useful for e.g. supporting range-select in a list of checkboxes). + ImGuiMultiSelectFlags_NoAutoClear = 1 << 4, // Disable clearing selection when navigating or selecting another one (generally used with ImGuiMultiSelectFlags_NoAutoSelect. useful for e.g. supporting range-select in a list of checkboxes). + ImGuiMultiSelectFlags_NoAutoClearOnReselect = 1 << 5, // Disable clearing selection when clicking/selecting an already selected item. + ImGuiMultiSelectFlags_BoxSelect1d = 1 << 6, // Enable box-selection with same width and same x pos items (e.g. full row Selectable()). Box-selection works better with little bit of spacing between items hit-box in order to be able to aim at empty space. ImGuiMultiSelectFlags_BoxSelect2d = 1 << 7, // Enable box-selection with varying width or varying x pos items support (e.g. different width labels, or 2D layout/grid). This is slower: alters clipping logic so that e.g. horizontal movements will update selection of normally clipped items. ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting near edges of scope. ImGuiMultiSelectFlags_ClearOnEscape = 1 << 9, // Clear selection when pressing Escape while scope is focused. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a5f7408c2dcf..4d6c2bbf2918 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 WIP +// dear imgui, v1.91.0 // (demo code) // Help: @@ -3621,7 +3621,7 @@ static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data) static bool use_deletion = true; static bool use_drag_drop = true; static bool show_in_table = false; - static bool show_color_button = false; + static bool show_color_button = true; static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d; static WidgetType widget_type = WidgetType_Selectable; diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 69e4f854c561..57486a6e2ba3 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 WIP +// dear imgui, v1.91.0 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 7e9b22607fa2..ab43922ba2a8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 WIP +// dear imgui, v1.91.0 // (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 9c8262ff8a97..37dd703043bc 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 WIP +// dear imgui, v1.91.0 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 8e35df6628c1..2aa24efe8e97 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.0 WIP +// dear imgui, v1.91.0 // (widgets code) /* From dcf54782d4be1070bab4821f06cdaf9181bfc528 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 31 Jul 2024 16:34:08 +0200 Subject: [PATCH 038/548] 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 8c83dadff52a..877cd8584961 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 2c8611266046..94c59e7ea801 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 05e48a175821..5b22dfe71208 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 4d6c2bbf2918..2800e9518209 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 57486a6e2ba3..854ad401207f 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 ab43922ba2a8..0e39b08749c6 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 37dd703043bc..92c62949efe3 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 2aa24efe8e97..5ca9a9d3cc53 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 039/548] 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 877cd8584961..7c0eb205092b 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 3275bafde502..47c852d273a2 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 efb28edbc417..a70edd2258fa 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 d748c1360bb2..2a4d7b9e7d9a 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 8bb3099205ce..b186b6268ce3 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 afcebf1b913d..cb116b76eb29 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 c4eee77d4eac..e6aba880950d 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 607d00b6b7bd..951141548903 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 594931dca83b..8ecd27a20642 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 040/548] 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 3058916243a4..df581537b866 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 c0eac1134a3b..60b95bd99d46 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 7c0eb205092b..b265121e3584 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 5e47b000847e..1fcec2b2a7bb 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 22ef79eb7f3d..3afe251e3750 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 e1f099e3d3cb..901b46c4cfd7 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 041/548] 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 c5872bd85c7f..f510987ed829 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 951141548903..6efd2754ac75 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 05cf60fed739..8c4c48ecf0a9 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 042/548] 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 5828e4bfc711..a032f875213b 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 043/548] 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 b265121e3584..3f0d9c4ea348 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 5ca9a9d3cc53..0f0134b9d0d3 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 044/548] 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 3f0d9c4ea348..a495cd5d36c9 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 5b22dfe71208..6d4f51388a2c 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 0e39b08749c6..5b6d4c19551c 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 0f0134b9d0d3..11f1cdf601f9 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) { From 531364d72896f41c973730c2fbc0478da4ba64c6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 1 Aug 2024 22:26:12 +0200 Subject: [PATCH 045/548] Window refresh policy: fixed child window of skiprefresh windows not displaying. (#7797) Amend d4495446d. (#3515, #4763, #7556, #5116 , #4076, #2749, #2268) --- imgui.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 94c59e7ea801..edbf15069f2a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6531,6 +6531,17 @@ void ImGui::UpdateWindowSkipRefresh(ImGuiWindow* window) } } +static void SetWindowActiveForSkipRefresh(ImGuiWindow* window) +{ + window->Active = true; + for (ImGuiWindow* child : window->DC.ChildWindows) + if (!child->Hidden) + { + child->Active = child->SkipRefresh = true; + SetWindowActiveForSkipRefresh(child); + } +} + // When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing) // should be positioned behind that modal window, unless the window was created inside the modal begin-stack. // In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent. @@ -7233,7 +7244,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { // Skip refresh always mark active if (window->SkipRefresh) - window->Active = true; + SetWindowActiveForSkipRefresh(window); // Append SetCurrentWindow(window); From 6864a7f839ce78419d5db57a46c25c4216e9c712 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 1 Aug 2024 22:40:09 +0200 Subject: [PATCH 046/548] Window refresh policy: extend tests to any window in the begin stack. (#7797) --- imgui.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index edbf15069f2a..d1da2886e5e1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6522,10 +6522,12 @@ void ImGui::UpdateWindowSkipRefresh(ImGuiWindow* window) return; if (window->Hidden) // If was hidden (previous frame) return; - if ((g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnHover) && g.HoveredWindow && window->RootWindow == g.HoveredWindow->RootWindow) - return; - if ((g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnFocus) && g.NavWindow && window->RootWindow == g.NavWindow->RootWindow) - return; + if ((g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnHover) && g.HoveredWindow) + if (window->RootWindow == g.HoveredWindow->RootWindow || IsWindowWithinBeginStackOf(g.HoveredWindow->RootWindow, window)) + return; + if ((g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_RefreshOnFocus) && g.NavWindow) + if (window->RootWindow == g.NavWindow->RootWindow || IsWindowWithinBeginStackOf(g.NavWindow->RootWindow, window)) + return; window->DrawList = NULL; window->SkipRefresh = true; } From 8cc6eee295871bc8852c12372860a50b950d3f56 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 3 Aug 2024 15:25:47 +0200 Subject: [PATCH 047/548] Fonts: amend assert when glyph range data seems incorrect. (#7856) --- imgui_draw.cpp | 5 +++-- misc/freetype/imgui_freetype.cpp | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 854ad401207f..32cf64353213 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2815,8 +2815,9 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) { // Check for valid range. This may also help detect *some* dangling pointers, because a common - // user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent. - IM_ASSERT(src_range[0] <= src_range[1]); + // user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent, + // or to forget to zero-terminate the glyph range array. + IM_ASSERT(src_range[0] <= src_range[1] && "Invalid range: is your glyph range array persistent? it is zero-terminated?"); src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]); } dst_tmp.SrcCount++; diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 68e38ed95b88..d97605b25868 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -480,8 +480,9 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) { // Check for valid range. This may also help detect *some* dangling pointers, because a common - // user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent. - IM_ASSERT(src_range[0] <= src_range[1]); + // user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent, + // or to forget to zero-terminate the glyph range array. + IM_ASSERT(src_range[0] <= src_range[1] && "Invalid range: is your glyph range array persistent? it is zero-terminated?"); src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]); } dst_tmp.SrcCount++; From 4b654db9040851228857528b44e195e358868e9a Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Tue, 6 Aug 2024 20:27:23 +0200 Subject: [PATCH 048/548] CI: Build example_sdl2_sdlrenderer2 with msbuild (#7864) --- .github/workflows/build.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 48082d056392..b223d22619dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -123,6 +123,11 @@ jobs: run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release' if: github.event_name == 'workflow_run' + - name: Build Win32 example_sdl2_sdlrenderer2 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj /p:Platform=Win32 /p:Configuration=Release' + if: github.event_name == 'workflow_run' + - name: Build Win32 example_sdl2_vulkan shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release' @@ -168,6 +173,11 @@ jobs: shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release' + - name: Build x64 example_sdl2_sdlrenderer2 + shell: cmd + run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj /p:Platform=x64 /p:Configuration=Release' + if: github.event_name == 'workflow_run' + - name: Build x64 example_sdl2_vulkan shell: cmd run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release' From 3232070d3abaec531d75e060fab14a26cb36ab55 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 7 Aug 2024 12:47:03 +0200 Subject: [PATCH 049/548] Demo: Fixed truncation warning. (#7857) --- imgui_demo.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2800e9518209..264df8af40c0 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -310,23 +310,24 @@ static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, Exampl static ExampleTreeNode* ExampleTree_CreateDemoTree() { static const char* root_names[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pear", "Pineapple", "Strawberry", "Watermelon" }; - char name_buf[32]; + const size_t NAME_MAX_LEN = sizeof(ExampleTreeNode::Name); + char name_buf[NAME_MAX_LEN]; int uid = 0; ExampleTreeNode* node_L0 = ExampleTree_CreateNode("", ++uid, NULL); const int root_items_multiplier = 2; for (int idx_L0 = 0; idx_L0 < IM_ARRAYSIZE(root_names) * root_items_multiplier; idx_L0++) { - snprintf(name_buf, 32, "%s %d", root_names[idx_L0 / root_items_multiplier], idx_L0 % root_items_multiplier); + snprintf(name_buf, IM_ARRAYSIZE(name_buf), "%s %d", root_names[idx_L0 / root_items_multiplier], idx_L0 % root_items_multiplier); ExampleTreeNode* node_L1 = ExampleTree_CreateNode(name_buf, ++uid, node_L0); const int number_of_childs = (int)strlen(node_L1->Name); for (int idx_L1 = 0; idx_L1 < number_of_childs; idx_L1++) { - snprintf(name_buf, 32, "Child %d", idx_L1); + snprintf(name_buf, IM_ARRAYSIZE(name_buf), "Child %d", idx_L1); ExampleTreeNode* node_L2 = ExampleTree_CreateNode(name_buf, ++uid, node_L1); node_L2->HasData = true; if (idx_L1 == 0) { - snprintf(name_buf, 32, "Sub-child %d", 0); + snprintf(name_buf, IM_ARRAYSIZE(name_buf), "Sub-child %d", 0); ExampleTreeNode* node_L3 = ExampleTree_CreateNode(name_buf, ++uid, node_L2); node_L3->HasData = true; } From 45e7f7827a52462d83895d36c62d00e6eb33c266 Mon Sep 17 00:00:00 2001 From: lunarlattice <18731514+lunarlattice0@users.noreply.github.com> Date: Fri, 9 Aug 2024 03:27:38 -0700 Subject: [PATCH 050/548] Examples: SDL2+SDLRenderer: fixed return value. (#7876) --- examples/example_sdl2_sdlrenderer2/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_sdl2_sdlrenderer2/main.cpp b/examples/example_sdl2_sdlrenderer2/main.cpp index b186b6268ce3..31fa3f9bf7b6 100644 --- a/examples/example_sdl2_sdlrenderer2/main.cpp +++ b/examples/example_sdl2_sdlrenderer2/main.cpp @@ -47,7 +47,7 @@ int main(int, char**) if (renderer == nullptr) { SDL_Log("Error creating SDL_Renderer!"); - return 0; + return -1; } //SDL_RendererInfo info; //SDL_GetRendererInfo(renderer, &info); From 29fadad1939ab62adcc5cd9339db7a784de90120 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 13 Aug 2024 14:30:16 +0200 Subject: [PATCH 051/548] TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a495cd5d36c9..386d330c86de 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,7 @@ Other changes: 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) +- TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) - 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 11f1cdf601f9..d5c9fa0774a4 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1425,6 +1425,9 @@ bool ImGui::TextLink(const char* label) bool pressed = ButtonBehavior(bb, id, &hovered, &held); RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_None); + if (hovered) + SetMouseCursor(ImGuiMouseCursor_Hand); + ImVec4 text_colf = g.Style.Colors[ImGuiCol_TextLink]; ImVec4 line_colf = text_colf; { From 591a18a9c4bf421de05a0eee7e85dea25f64209d Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Fri, 2 Aug 2024 00:05:51 +0200 Subject: [PATCH 052/548] Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) --- backends/imgui_impl_sdl2.cpp | 12 ++++++++++++ backends/imgui_impl_sdl3.cpp | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 15db0a843a8f..2b115f360301 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -321,6 +321,8 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) { case SDL_MOUSEMOTION: { + if (event->motion.windowID != SDL_GetWindowID(bd->Window)) + return false; ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse); io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); @@ -328,6 +330,8 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) } case SDL_MOUSEWHEEL: { + if (event->wheel.windowID != SDL_GetWindowID(bd->Window)) + return false; //IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY); #if SDL_VERSION_ATLEAST(2,0,18) // If this fails to compile on Emscripten: update to latest Emscripten! float wheel_x = -event->wheel.preciseX; @@ -346,6 +350,8 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { + if (event->button.windowID != SDL_GetWindowID(bd->Window)) + return false; int mouse_button = -1; if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; } @@ -361,12 +367,16 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) } case SDL_TEXTINPUT: { + if (event->text.windowID != SDL_GetWindowID(bd->Window)) + return false; io.AddInputCharactersUTF8(event->text.text); return true; } case SDL_KEYDOWN: case SDL_KEYUP: { + if (event->key.windowID != SDL_GetWindowID(bd->Window)) + return false; ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod); ImGuiKey key = ImGui_ImplSDL2_KeyEventToImGuiKey(event->key.keysym.sym, event->key.keysym.scancode); io.AddKeyEvent(key, (event->type == SDL_KEYDOWN)); @@ -375,6 +385,8 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) } case SDL_WINDOWEVENT: { + if (event->window.windowID != SDL_GetWindowID(bd->Window)) + return false; // - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right. // - However we won't get a correct LEAVE event for a captured window. // - In some cases, when detaching a window from main viewport SDL may send SDL_WINDOWEVENT_ENTER one frame too late, diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 05718d21cfb0..a74a316d2983 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -307,6 +307,8 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) { case SDL_EVENT_MOUSE_MOTION: { + if (event->motion.windowID != SDL_GetWindowID(bd->Window)) + return false; ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse); io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); @@ -314,6 +316,8 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) } case SDL_EVENT_MOUSE_WHEEL: { + if (event->wheel.windowID != SDL_GetWindowID(bd->Window)) + return false; //IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY); float wheel_x = -event->wheel.x; float wheel_y = event->wheel.y; @@ -327,6 +331,8 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_UP: { + if (event->button.windowID != SDL_GetWindowID(bd->Window)) + return false; int mouse_button = -1; if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } if (event->button.button == SDL_BUTTON_RIGHT) { mouse_button = 1; } @@ -342,12 +348,16 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) } case SDL_EVENT_TEXT_INPUT: { + if (event->text.windowID != SDL_GetWindowID(bd->Window)) + return false; io.AddInputCharactersUTF8(event->text.text); return true; } case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: { + if (event->key.windowID != SDL_GetWindowID(bd->Window)) + return false; //IMGUI_DEBUG_LOG("SDL_EVENT_KEY_%d: key=%d, scancode=%d, mod=%X\n", (event->type == SDL_EVENT_KEY_DOWN) ? "DOWN" : "UP", event->key.key, event->key.scancode, event->key.mod); ImGui_ImplSDL3_UpdateKeyModifiers((SDL_Keymod)event->key.mod); ImGuiKey key = ImGui_ImplSDL3_KeyEventToImGuiKey(event->key.key, event->key.scancode); @@ -357,6 +367,8 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) } case SDL_EVENT_WINDOW_MOUSE_ENTER: { + if (event->window.windowID != SDL_GetWindowID(bd->Window)) + return false; bd->MouseWindowID = event->window.windowID; bd->MousePendingLeaveFrame = 0; return true; @@ -367,13 +379,19 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) // FIXME: Unconfirmed whether this is still needed with SDL3. case SDL_EVENT_WINDOW_MOUSE_LEAVE: { + if (event->window.windowID != SDL_GetWindowID(bd->Window)) + return false; bd->MousePendingLeaveFrame = ImGui::GetFrameCount() + 1; return true; } case SDL_EVENT_WINDOW_FOCUS_GAINED: + if (event->window.windowID != SDL_GetWindowID(bd->Window)) + return false; io.AddFocusEvent(true); return true; case SDL_EVENT_WINDOW_FOCUS_LOST: + if (event->window.windowID != SDL_GetWindowID(bd->Window)) + return false; io.AddFocusEvent(false); return true; case SDL_EVENT_GAMEPAD_ADDED: From 1b61d55079a66692207562c4d8d711527954f514 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Aug 2024 13:57:08 +0200 Subject: [PATCH 053/548] Backends: SDL2, SDL3: ignore events of other SDL windows, amends + wrapping into a function as it'll be convenient for multi-viewport check. (#7853) + Misc typo fix. --- backends/imgui_impl_sdl2.cpp | 21 +++++++++++++++------ backends/imgui_impl_sdl3.cpp | 34 +++++++++++++++++++++------------- docs/CHANGELOG.txt | 1 + imgui.h | 2 +- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 2b115f360301..9fff2ab56e02 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-08-19: ImGui_ImplSDL2_ProcessEvent() now ignores events intended for other SDL windows. (#7853) // 2024-07-02: Emscripten: Added io.PlatformOpenInShellFn() handler for Emscripten versions. // 2024-07-02: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() renaming in main library. // 2024-02-14: Inputs: Handle gamepad disconnection. Added ImGui_ImplSDL2_SetGamepadMode(). @@ -110,6 +111,7 @@ struct ImGui_ImplSDL2_Data { SDL_Window* Window; + Uint32 WindowID; SDL_Renderer* Renderer; Uint64 Time; char* ClipboardTextData; @@ -306,6 +308,12 @@ static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods) io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & KMOD_GUI) != 0); } +static ImGuiViewport* ImGui_ImplSDL2_GetViewportForWindowID(Uint32 window_id) +{ + ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); + return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : NULL; +} + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. @@ -321,7 +329,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) { case SDL_MOUSEMOTION: { - if (event->motion.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL2_GetViewportForWindowID(event->motion.windowID) == NULL) return false; ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse); @@ -330,7 +338,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) } case SDL_MOUSEWHEEL: { - if (event->wheel.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL2_GetViewportForWindowID(event->wheel.windowID) == NULL) return false; //IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY); #if SDL_VERSION_ATLEAST(2,0,18) // If this fails to compile on Emscripten: update to latest Emscripten! @@ -350,7 +358,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { - if (event->button.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL2_GetViewportForWindowID(event->button.windowID) == NULL) return false; int mouse_button = -1; if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } @@ -367,7 +375,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) } case SDL_TEXTINPUT: { - if (event->text.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL2_GetViewportForWindowID(event->text.windowID) == NULL) return false; io.AddInputCharactersUTF8(event->text.text); return true; @@ -375,7 +383,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) case SDL_KEYDOWN: case SDL_KEYUP: { - if (event->key.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL2_GetViewportForWindowID(event->key.windowID) == NULL) return false; ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod); ImGuiKey key = ImGui_ImplSDL2_KeyEventToImGuiKey(event->key.keysym.sym, event->key.keysym.scancode); @@ -385,7 +393,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) } case SDL_WINDOWEVENT: { - if (event->window.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL2_GetViewportForWindowID(event->window.windowID) == NULL) return false; // - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right. // - However we won't get a correct LEAVE event for a captured window. @@ -445,6 +453,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) bd->Window = window; + bd->WindowID = SDL_GetWindowID(window); bd->Renderer = renderer; bd->MouseCanUseGlobalState = mouse_can_use_global_state; diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index a74a316d2983..5a58c96882c1 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-08-19: ImGui_ImplSDL3_ProcessEvent() now ignores events intended for other SDL windows. (#7853) // 2024-07-22: Update for SDL3 api changes: SDL_GetGamepads() memory ownership change. (#7807) // 2024-07-18: Update for SDL3 api changes: SDL_GetClipboardText() memory ownership change. (#7801) // 2024-07-15: Update for SDL3 api changes: SDL_GetProperty() change to SDL_GetPointerProperty(). (#7794) @@ -80,6 +81,7 @@ struct ImGui_ImplSDL3_Data { SDL_Window* Window; + SDL_WindowID WindowID; SDL_Renderer* Renderer; Uint64 Time; char* ClipboardTextData; @@ -292,6 +294,13 @@ static void ImGui_ImplSDL3_UpdateKeyModifiers(SDL_Keymod sdl_key_mods) io.AddKeyEvent(ImGuiMod_Super, (sdl_key_mods & SDL_KMOD_GUI) != 0); } + +static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id) +{ + ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); + return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : NULL; +} + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. @@ -307,7 +316,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) { case SDL_EVENT_MOUSE_MOTION: { - if (event->motion.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL3_GetViewportForWindowID(event->motion.windowID) == NULL) return false; ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse); @@ -316,7 +325,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) } case SDL_EVENT_MOUSE_WHEEL: { - if (event->wheel.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL3_GetViewportForWindowID(event->wheel.windowID) == NULL) return false; //IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY); float wheel_x = -event->wheel.x; @@ -331,7 +340,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_UP: { - if (event->button.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL3_GetViewportForWindowID(event->button.windowID) == NULL) return false; int mouse_button = -1; if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; } @@ -348,7 +357,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) } case SDL_EVENT_TEXT_INPUT: { - if (event->text.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL3_GetViewportForWindowID(event->text.windowID) == NULL) return false; io.AddInputCharactersUTF8(event->text.text); return true; @@ -356,7 +365,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: { - if (event->key.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL3_GetViewportForWindowID(event->key.windowID) == NULL) return false; //IMGUI_DEBUG_LOG("SDL_EVENT_KEY_%d: key=%d, scancode=%d, mod=%X\n", (event->type == SDL_EVENT_KEY_DOWN) ? "DOWN" : "UP", event->key.key, event->key.scancode, event->key.mod); ImGui_ImplSDL3_UpdateKeyModifiers((SDL_Keymod)event->key.mod); @@ -367,7 +376,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) } case SDL_EVENT_WINDOW_MOUSE_ENTER: { - if (event->window.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == NULL) return false; bd->MouseWindowID = event->window.windowID; bd->MousePendingLeaveFrame = 0; @@ -379,21 +388,19 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) // FIXME: Unconfirmed whether this is still needed with SDL3. case SDL_EVENT_WINDOW_MOUSE_LEAVE: { - if (event->window.windowID != SDL_GetWindowID(bd->Window)) + if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == NULL) return false; bd->MousePendingLeaveFrame = ImGui::GetFrameCount() + 1; return true; } case SDL_EVENT_WINDOW_FOCUS_GAINED: - if (event->window.windowID != SDL_GetWindowID(bd->Window)) - return false; - io.AddFocusEvent(true); - return true; case SDL_EVENT_WINDOW_FOCUS_LOST: - if (event->window.windowID != SDL_GetWindowID(bd->Window)) + { + if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == NULL) return false; - io.AddFocusEvent(false); + io.AddFocusEvent(event->type == SDL_EVENT_WINDOW_FOCUS_GAINED); return true; + } case SDL_EVENT_GAMEPAD_ADDED: case SDL_EVENT_GAMEPAD_REMOVED: { @@ -441,6 +448,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) bd->Window = window; + bd->WindowID = SDL_GetWindowID(window); bd->Renderer = renderer; bd->MouseCanUseGlobalState = mouse_can_use_global_state; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 386d330c86de..e272b19ec4c0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,7 @@ Other changes: - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not provide a way to do a portable sleep. (#7844) +- Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut] - 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/imgui.h b/imgui.h index 6d4f51388a2c..9080bb1b5d5f 100644 --- a/imgui.h +++ b/imgui.h @@ -3385,7 +3385,7 @@ struct ImFontAtlas struct ImFont { // Members: Hot ~20/24 bytes (for CalcTextSize) - ImVector IndexAdvanceX; // 12-16 // out // // Sparse. Glyphs->AdvanceX in a directly indexable way (cache-friendly for CalcTextSize functions which only this this info, and are often bottleneck in large UI). + ImVector IndexAdvanceX; // 12-16 // out // // Sparse. Glyphs->AdvanceX in a directly indexable way (cache-friendly for CalcTextSize functions which only this info, and are often bottleneck in large UI). float FallbackAdvanceX; // 4 // out // = FallbackGlyph->AdvanceX float FontSize; // 4 // in // // Height of characters/line, set during loading (don't change after loading) From 2d99052d1d43bd17a72bce0531c605b30aa6bc0b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Aug 2024 14:07:25 +0200 Subject: [PATCH 054/548] Backends: SDL2, SDL3: storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. (#7853) This will be used to support filtering of events with multi-viewports. --- backends/imgui_impl_sdl2.cpp | 3 ++- backends/imgui_impl_sdl3.cpp | 6 ++++-- docs/CHANGELOG.txt | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 9fff2ab56e02..c4724969dfba 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-08-19: Storing SDL's Uint32 WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. // 2024-08-19: ImGui_ImplSDL2_ProcessEvent() now ignores events intended for other SDL windows. (#7853) // 2024-07-02: Emscripten: Added io.PlatformOpenInShellFn() handler for Emscripten versions. // 2024-07-02: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() renaming in main library. @@ -483,7 +484,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void // Set platform dependent data in viewport // Our mouse update function expect PlatformHandle to be filled for the main viewport ImGuiViewport* main_viewport = ImGui::GetMainViewport(); - main_viewport->PlatformHandle = (void*)window; + main_viewport->PlatformHandle = (void*)(intptr_t)bd->WindowID; main_viewport->PlatformHandleRaw = nullptr; SDL_SysWMinfo info; SDL_VERSION(&info.version); diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 5a58c96882c1..24627347bc5a 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-08-19: Storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. // 2024-08-19: ImGui_ImplSDL3_ProcessEvent() now ignores events intended for other SDL windows. (#7853) // 2024-07-22: Update for SDL3 api changes: SDL_GetGamepads() memory ownership change. (#7807) // 2024-07-18: Update for SDL3 api changes: SDL_GetClipboardText() memory ownership change. (#7801) @@ -133,7 +134,8 @@ static void ImGui_ImplSDL3_SetClipboardText(void*, const char* text) static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data) { ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); - SDL_Window* window = (SDL_Window*)viewport->PlatformHandle; + SDL_WindowID window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle; + SDL_Window* window = SDL_GetWindowFromID(window_id); if ((data->WantVisible == false || bd->ImeWindow != window) && bd->ImeWindow != NULL) { SDL_StopTextInput(bd->ImeWindow); @@ -413,7 +415,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) static void ImGui_ImplSDL3_SetupPlatformHandles(ImGuiViewport* viewport, SDL_Window* window) { - viewport->PlatformHandle = window; + viewport->PlatformHandle = (void*)(intptr_t)SDL_GetWindowID(window); viewport->PlatformHandleRaw = nullptr; #if defined(_WIN32) && !defined(__WINRT__) viewport->PlatformHandleRaw = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e272b19ec4c0..24f6c640cc05 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,7 @@ Other changes: - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not provide a way to do a portable sleep. (#7844) - Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut] +- Backends: SDL2, SDL3: storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. - 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) From 61313a75891c6cdb9ad313bd0f6e11eb6fde2c67 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Aug 2024 16:31:49 +0200 Subject: [PATCH 055/548] Docs: better promote IMGUI_DEFINE_MATH_OPERATORS. (#6164, #6137, #5966, #2832) --- imgui.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/imgui.h b/imgui.h index 9080bb1b5d5f..b531bebc6996 100644 --- a/imgui.h +++ b/imgui.h @@ -5,6 +5,7 @@ // - See links below. // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that. // - Read top of imgui.cpp for more details, links and comments. +// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4. // Resources: // - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md) @@ -280,8 +281,8 @@ typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); // Function signature for ImGui::SetAllocatorFunctions() // ImVec2: 2D vector used to store positions, sizes etc. [Compile-time configurable type] -// This is a frequently used type in the API. Consider using IM_VEC2_CLASS_EXTRA to create implicit cast from/to our preferred type. -// Add '#define IMGUI_DEFINE_MATH_OPERATORS' in your imconfig.h file to benefit from courtesy maths operators for those types. +// - This is a frequently used type in the API. Consider using IM_VEC2_CLASS_EXTRA to create implicit cast from/to our preferred type. +// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4. IM_MSVC_RUNTIME_CHECKS_OFF struct ImVec2 { @@ -2664,7 +2665,7 @@ struct ImGuiListClipper // Helpers: ImVec2/ImVec4 operators // - It is important that we are keeping those disabled by default so they don't leak in user space. // - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h) -// - You can use '#define IMGUI_DEFINE_MATH_OPERATORS' to import our operators, provided as a courtesy. +// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4. #ifdef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED IM_MSVC_RUNTIME_CHECKS_OFF From fabceaf03695ec0d8044d58b15460edd171cf7ea Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Aug 2024 18:28:56 +0200 Subject: [PATCH 056/548] Internals: renamed IsModKey() -> IsLRModKey() and GetModForModKey() -> GetModForLRModKey() to be more explicit. --- imgui.cpp | 12 ++++++------ imgui_internal.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d1da2886e5e1..74236c1a42c4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8407,7 +8407,7 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE //----------------------------------------------------------------------------- // [SECTION] INPUTS //----------------------------------------------------------------------------- -// - GetModForModKey() [Internal] +// - GetModForLRModKey() [Internal] // - FixupKeyChord() [Internal] // - GetKeyData() [Internal] // - GetKeyIndex() [Internal] @@ -8470,7 +8470,7 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE // - Shortcut() [Internal] //----------------------------------------------------------------------------- -static ImGuiKeyChord GetModForModKey(ImGuiKey key) +static ImGuiKeyChord GetModForLRModKey(ImGuiKey key) { if (key == ImGuiKey_LeftCtrl || key == ImGuiKey_RightCtrl) return ImGuiMod_Ctrl; @@ -8487,8 +8487,8 @@ ImGuiKeyChord ImGui::FixupKeyChord(ImGuiKeyChord key_chord) { // Add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified. ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); - if (IsModKey(key)) - key_chord |= GetModForModKey(key); + if (IsLRModKey(key)) + key_chord |= GetModForLRModKey(key); return key_chord; } @@ -8579,8 +8579,8 @@ const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord) ImGuiContext& g = *GImGui; const ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); - if (IsModKey(key)) - key_chord &= ~GetModForModKey(key); // Return "Ctrl+LeftShift" instead of "Ctrl+Shift+LeftShift" + if (IsLRModKey(key)) + key_chord &= ~GetModForLRModKey(key); // Return "Ctrl+LeftShift" instead of "Ctrl+Shift+LeftShift" ImFormatString(g.TempKeychordName, IM_ARRAYSIZE(g.TempKeychordName), "%s%s%s%s%s", (key_chord & ImGuiMod_Ctrl) ? "Ctrl+" : "", (key_chord & ImGuiMod_Shift) ? "Shift+" : "", diff --git a/imgui_internal.h b/imgui_internal.h index 5b6d4c19551c..339a4e3a6be1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3298,7 +3298,7 @@ namespace ImGui inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; } inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; } inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; } - inline bool IsModKey(ImGuiKey key) { return key >= ImGuiKey_LeftCtrl && key <= ImGuiKey_RightSuper; } + inline bool IsLRModKey(ImGuiKey key) { return key >= ImGuiKey_LeftCtrl && key <= ImGuiKey_RightSuper; } ImGuiKeyChord FixupKeyChord(ImGuiKeyChord key_chord); inline ImGuiKey ConvertSingleModFlagToKey(ImGuiKey key) { From 092c88dc7bdd6e736f0313fc366f7d20c18da519 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Aug 2024 19:02:27 +0200 Subject: [PATCH 057/548] IO: rework interleaved keys<>char trickling: only trickle for keys known to be likely to input characters. (#7889, #4921, #4858) Amend fa2b318d. Refer to regression test "inputs_io_inputqueue" amended for IMGUI_VERSION_NUM >= 19102 --- imgui.cpp | 26 +++++++++++++++++++------- imgui.h | 2 +- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 74236c1a42c4..ed79835423a7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8780,8 +8780,9 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput return 0; } -// We need this to filter some Shortcut() routes when an item e.g. an InputText() is active -// e.g. ImGuiKey_G won't be considered a shortcut when item is active, but ImGuiMod|ImGuiKey_G can be. +// - We need this to filter some Shortcut() routes when an item e.g. an InputText() is active +// e.g. ImGuiKey_G won't be considered a shortcut when item is active, but ImGuiMod|ImGuiKey_G can be. +// - This is also used by UpdateInputEvents() to avoid trickling in the most common case of e.g. pressing ImGuiKey_G also emitting a G character. static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord) { // Mimic 'ignore_char_inputs' logic in InputText() @@ -8795,6 +8796,8 @@ static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord) // Return true for A-Z, 0-9 and other keys associated to char inputs. Other keys such as F1-F12 won't be filtered. ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); + if (key == ImGuiKey_None) + return false; return g.KeysMayBeCharInput.TestBit(key); } @@ -9599,9 +9602,9 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs) // Only trickle chars<>key when working with InputText() // FIXME: InputText() could parse event trail? // FIXME: Could specialize chars<>keys trickling rules for control keys (those not typically associated to characters) - const bool trickle_interleaved_keys_and_text = (trickle_fast_inputs && g.WantTextInputNextFrame == 1); + const bool trickle_interleaved_nonchar_keys_and_text = (trickle_fast_inputs && g.WantTextInputNextFrame == 1); - bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_inputted = false; + bool mouse_moved = false, mouse_wheeled = false, key_changed = false, key_changed_nonchar = false, text_inputted = false; int mouse_button_changed = 0x00; ImBitArray key_changed_mask; @@ -9653,12 +9656,19 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs) IM_ASSERT(key != ImGuiKey_None); ImGuiKeyData* key_data = GetKeyData(key); const int key_data_index = (int)(key_data - g.IO.KeysData); - if (trickle_fast_inputs && key_data->Down != e->Key.Down && (key_changed_mask.TestBit(key_data_index) || text_inputted || mouse_button_changed != 0)) + if (trickle_fast_inputs && key_data->Down != e->Key.Down && (key_changed_mask.TestBit(key_data_index) || mouse_button_changed != 0)) + break; + + const bool key_is_potentially_for_char_input = IsKeyChordPotentiallyCharInput(GetMergedModsFromKeys() | key); + if (trickle_interleaved_nonchar_keys_and_text && (text_inputted && !key_is_potentially_for_char_input)) break; + key_data->Down = e->Key.Down; key_data->AnalogValue = e->Key.AnalogValue; key_changed = true; key_changed_mask.SetBit(key_data_index); + if (trickle_interleaved_nonchar_keys_and_text && !key_is_potentially_for_char_input) + key_changed_nonchar = true; // Allow legacy code using io.KeysDown[GetKeyIndex()] with new backends #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO @@ -9672,11 +9682,13 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs) if (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard) continue; // Trickling Rule: Stop processing queued events if keys/mouse have been interacted with - if (trickle_fast_inputs && ((key_changed && trickle_interleaved_keys_and_text) || mouse_button_changed != 0 || mouse_moved || mouse_wheeled)) + if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_moved || mouse_wheeled)) + break; + if (trickle_interleaved_nonchar_keys_and_text && key_changed_nonchar) break; unsigned int c = e->Text.Char; io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID); - if (trickle_interleaved_keys_and_text) + if (trickle_interleaved_nonchar_keys_and_text) text_inputted = true; } else if (e->Type == ImGuiInputEventType_Focus) diff --git a/imgui.h b/imgui.h index b531bebc6996..1d77591996fe 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.1 WIP" -#define IMGUI_VERSION_NUM 19101 +#define IMGUI_VERSION_NUM 19102 #define IMGUI_HAS_TABLE /* From ecb1962013d280499c047e4523ceabd4a223d629 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Aug 2024 19:10:03 +0200 Subject: [PATCH 058/548] IO, InputText: missing changelog entry (amend 092c88d) + readme note on missing features. --- docs/CHANGELOG.txt | 3 +++ docs/README.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 24f6c640cc05..40b651f422f7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,9 @@ Breaking changes: Other changes: +- IO, InputText: fixed an issue where typing text in a InputText() would defer character + processing by one frame, because of the trickling input queue. Reworked interleaved + keys<>char trickling to take account for keys known to input characters. (#7889, #4921, #4858) - 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 diff --git a/docs/README.md b/docs/README.md index 2c976341c709..a1807abac22a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -22,7 +22,7 @@ Businesses: support continued development and maintenance via invoiced sponsorin Dear ImGui is a **bloat-free graphical user interface library for C++**. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline-enabled application. It is fast, portable, renderer agnostic, and self-contained (no external dependencies). -Dear ImGui is designed to **enable fast iterations** and to **empower programmers** to create **content creation tools and visualization / debug tools** (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal and lacks certain features commonly found in more high-level libraries. +Dear ImGui is designed to **enable fast iterations** and to **empower programmers** to create **content creation tools and visualization / debug tools** (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal and lacks certain features commonly found in more high-level libraries. Among other things, full internationalization (right-to-left text, bidirectional text, text shaping etc.) and accessibility features are not supported. Dear ImGui is particularly suited to integration in game engines (for tooling), real-time 3D applications, fullscreen applications, embedded applications, or any applications on console platforms where operating system features are non-standard. From eb7201b9026a8812d02b3421b43b61c050b81151 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 20 Aug 2024 15:34:14 +0200 Subject: [PATCH 059/548] Fonts: Made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 21 ++++++++++++++++----- imgui.h | 1 + imgui_draw.cpp | 11 +++++++++-- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 40b651f422f7..dc30091c0d79 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,7 @@ Other changes: - MultiSelect+TreeNode: default open behavior is OpenOnDoubleClick + OpenOnArrow when used in a multi-select context without any OpenOnXXX flags set. (#7850) - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) +- Fonts: Made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not provide a way to do a portable sleep. (#7844) - Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut] diff --git a/imgui.cpp b/imgui.cpp index ed79835423a7..ed7522b27d2e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5068,6 +5068,8 @@ static void InitViewportDrawData(ImGuiViewportP* viewport) // - If the code here changes, may need to update code of functions like NextColumn() and PushColumnClipRect(): // some frequently called functions which to modify both channels and clipping simultaneously tend to use the // more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous updates of underlying ImDrawCmds. +// - This is analoguous to PushFont()/PopFont() in the sense that are a mixing a global stack and a window stack, +// which in the case of ClipRect is not so problematic but tends to be more restrictive for fonts. void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect) { ImGuiWindow* window = GetCurrentWindow(); @@ -7574,22 +7576,31 @@ void ImGui::SetCurrentFont(ImFont* font) g.DrawListSharedData.FontScale = g.FontScale; } +// Use ImDrawList::_SetTextureID(), making our shared g.FontStack[] authorative against window-local ImDrawList. +// - Whereas ImDrawList::PushTextureID()/PopTextureID() is not to be used across Begin() calls. +// - Note that we don't propagate current texture id when e.g. Begin()-ing into a new window, we never really did... +// - Some code paths never really fully worked with multiple atlas textures. +// - The right-ish solution may be to remove _SetTextureID() and make AddText/RenderText lazily call PushTextureID()/PopTextureID() +// the same way AddImage() does, but then all other primitives would also need to? I don't think we should tackle this problem +// because we have a concrete need and a test bed for multiple atlas textures. void ImGui::PushFont(ImFont* font) { ImGuiContext& g = *GImGui; - if (!font) + if (font == NULL) font = GetDefaultFont(); - SetCurrentFont(font); g.FontStack.push_back(font); - g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID); + SetCurrentFont(font); + g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID); } void ImGui::PopFont() { ImGuiContext& g = *GImGui; - g.CurrentWindow->DrawList->PopTextureID(); + IM_ASSERT(g.FontStack.Size > 0); g.FontStack.pop_back(); - SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back()); + ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back(); + SetCurrentFont(font); + g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID); } void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) diff --git a/imgui.h b/imgui.h index 1d77591996fe..b8aa340727d2 100644 --- a/imgui.h +++ b/imgui.h @@ -3152,6 +3152,7 @@ struct ImDrawList IMGUI_API void _OnChangedClipRect(); IMGUI_API void _OnChangedTextureID(); IMGUI_API void _OnChangedVtxOffset(); + IMGUI_API void _SetTextureID(ImTextureID texture_id); IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const; IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step); IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 32cf64353213..65d68708d3a0 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -526,7 +526,6 @@ void ImDrawList::_OnChangedClipRect() CmdBuffer.pop_back(); return; } - curr_cmd->ClipRect = _CmdHeader.ClipRect; } @@ -549,7 +548,6 @@ void ImDrawList::_OnChangedTextureID() CmdBuffer.pop_back(); return; } - curr_cmd->TextureId = _CmdHeader.TextureId; } @@ -625,6 +623,15 @@ void ImDrawList::PopTextureID() _OnChangedTextureID(); } +// This is used by ImGui::PushFont()/PopFont(). It works because we never use _TextureIdStack[] elsewhere than in PushTextureID()/PopTextureID(). +void ImDrawList::_SetTextureID(ImTextureID texture_id) +{ + if (_CmdHeader.TextureId == texture_id) + return; + _CmdHeader.TextureId = texture_id; + _OnChangedTextureID(); +} + // Reserve space for a number of vertices and indices. // You must finish filling your reserved data before calling PrimReserve() again, as it may reallocate or // submit the intermediate results. PrimUnreserve() can be used to release unused allocations. From e471206b0889948c436f144669beb9b8875110c8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 20 Aug 2024 17:54:42 +0200 Subject: [PATCH 060/548] Windows: adjust default ClipRect to better match rendering of thick borders. (#7887, #7888 + #3312, #7540, #3756, #6170, #6365) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 12 ++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index dc30091c0d79..d12bb58d1d01 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,9 @@ Other changes: - IO, InputText: fixed an issue where typing text in a InputText() would defer character processing by one frame, because of the trickling input queue. Reworked interleaved keys<>char trickling to take account for keys known to input characters. (#7889, #4921, #4858) +- Windows: adjust default ClipRect to better match rendering of thick borders (which are in + theory not supported). Compensate for the fact that borders are centered around the windows + edge rather than inner. (#7887, #7888 + #3312, #7540, #3756, #6170, #6365) - 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 diff --git a/imgui.cpp b/imgui.cpp index ed7522b27d2e..ede9f4b84753 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7066,10 +7066,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Affected by window/frame border size. Used by: // - Begin() initial clip rect float top_border_size = (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize); - window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + window->WindowBorderSize); - window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size); - window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - window->WindowBorderSize); - window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - window->WindowBorderSize); + + // Try to match the fact that our border is drawn centered over the window rectangle, rather than inner. + // This is why we do a *0.5f here. We don't currently even technically support large values for WindowBorderSize, + // see e.g #7887 #7888, but may do after we move the window border to become an inner border (and then we can remove the 0.5f here). + window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + window->WindowBorderSize * 0.5f); + window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size * 0.5f); + window->InnerClipRect.Max.x = ImFloor(window->InnerRect.Max.x - window->WindowBorderSize * 0.5f); + window->InnerClipRect.Max.y = ImFloor(window->InnerRect.Max.y - window->WindowBorderSize * 0.5f); window->InnerClipRect.ClipWithFull(host_rect); // Default item width. Make it proportional to window size if window manually resizes From 59e69dc6df758e59f318e38a8db5bc4c8a8164c1 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Wed, 21 Aug 2024 09:14:52 +0200 Subject: [PATCH 061/548] ImGuiSelectionBasicStorage constructor needs visibility (#7906) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index b8aa340727d2..c55f5dda6fad 100644 --- a/imgui.h +++ b/imgui.h @@ -2860,7 +2860,7 @@ struct ImGuiSelectionBasicStorage ImGuiStorage _Storage; // [Internal] Selection set. Think of this as similar to e.g. std::set. Prefer not accessing directly: iterate with GetNextSelectedItem(). // Methods - ImGuiSelectionBasicStorage(); + IMGUI_API ImGuiSelectionBasicStorage(); IMGUI_API void ApplyRequests(ImGuiMultiSelectIO* ms_io); // Apply selection requests coming from BeginMultiSelect() and EndMultiSelect() functions. It uses 'items_count' passed to BeginMultiSelect() IMGUI_API bool Contains(ImGuiID id) const; // Query if an item id is in selection. IMGUI_API void Clear(); // Clear selection From 8a946b69e98d819e9123963122d3b8b10df52e78 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 21 Aug 2024 13:25:45 +0200 Subject: [PATCH 062/548] InputText: allow callback to update buffer while in read-only mode (fix for imgui_memory_editor 0.54 in read-only mode). See https://github.com/ocornut/imgui_club/pull/46 --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d12bb58d1d01..228e84dd1f78 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,7 @@ Other changes: 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) +- InputText: allow callback to update buffer while in read-only mode. (imgui_club/#46) - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) - Fonts: Made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d5c9fa0774a4..5aa70bdc2b21 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4912,7 +4912,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); } if (buf_dirty) { - IM_ASSERT(!is_readonly); + // Callback may update buffer and thus set buf_dirty even in read-only mode. IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ? if (callback_data.BufTextLen > backup_current_text_length && is_resizable) From 521f84a3a9f21aa93d12a49823d589b560f899a5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 21 Aug 2024 14:26:53 +0200 Subject: [PATCH 063/548] InputText: fixed an issue programmatically refocusing a multi-line input which was just active. (#4761, #7870) Amend 66f0fb986, c5db276521 --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 228e84dd1f78..7b20e0033b57 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,7 @@ Other changes: - MultiSelect+TreeNode: default open behavior is OpenOnDoubleClick + OpenOnArrow when used in a multi-select context without any OpenOnXXX flags set. (#7850) - InputText: allow callback to update buffer while in read-only mode. (imgui_club/#46) +- InputText: fixed an issue programmatically refocusing a multi-line input which was just active. (#4761, #7870) - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) - Fonts: Made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5aa70bdc2b21..e8d5f968325b 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5194,7 +5194,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (is_multiline) { - // For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (ref issue #4761)... + // For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (see #4761, #7870)... Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y)); g.NextItemData.ItemFlags |= ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop; EndChild(); @@ -5203,7 +5203,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // ...and then we need to undo the group overriding last item data, which gets a bit messy as EndGroup() tries to forward scrollbar being active... // FIXME: This quite messy/tricky, should attempt to get rid of the child window. EndGroup(); - if (g.LastItemData.ID == 0) + if (g.LastItemData.ID == 0 || g.LastItemData.ID != GetWindowScrollbarID(draw_window, ImGuiAxis_Y)) { g.LastItemData.ID = id; g.LastItemData.InFlags = item_data_backup.InFlags; From bf75504d7a42ca9fc6f71fce558eca1f4a6f0201 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Aug 2024 13:46:54 +0200 Subject: [PATCH 064/548] Style: added PushStyleVarX(), PushStyleVarY() helpers to modify only one component of a ImVec2 var. + tweak existing function to early out on error. --- docs/CHANGELOG.txt | 3 ++- docs/TODO.txt | 1 - imgui.cpp | 48 ++++++++++++++++++++++++++++++++++++---------- imgui.h | 6 ++++-- imgui_demo.cpp | 10 +++++----- imgui_widgets.cpp | 6 +++--- 6 files changed, 52 insertions(+), 22 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7b20e0033b57..6ba4c4dadc0e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,7 +56,8 @@ Other changes: - InputText: allow callback to update buffer while in read-only mode. (imgui_club/#46) - InputText: fixed an issue programmatically refocusing a multi-line input which was just active. (#4761, #7870) - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) -- Fonts: Made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) +- Style: added PushStyleVarX(), PushStyleVarY() helpers to modify only one component of a ImVec2 var. +- Fonts: made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not provide a way to do a portable sleep. (#7844) - Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut] diff --git a/docs/TODO.txt b/docs/TODO.txt index eecce6b42cb0..cd992784dc01 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -194,7 +194,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - settings/persistence: helpers to make TreeNodeBehavior persist (even during dev!) - may need to store some semantic and/or data type in ImGuiStoragePair - style: better default styles. (#707) - - style: PushStyleVar: allow direct access to individual float X/Y elements. - style: add a highlighted text color (for headers, etc.) - style: border types: out-screen, in-screen, etc. (#447) - style: add window shadow (fading away from the window. Paint-style calculation of vertices alpha after drawlist would be easier) diff --git a/imgui.cpp b/imgui.cpp index ede9f4b84753..bb7e55c82906 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3309,28 +3309,56 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) { ImGuiContext& g = *GImGui; const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1) + if (var_info->Type != ImGuiDataType_Float || var_info->Count != 1) { - float* pvar = (float*)var_info->GetVarPtr(&g.Style); - g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar)); - *pvar = val; + IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); return; } - IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); + float* pvar = (float*)var_info->GetVarPtr(&g.Style); + g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar)); + *pvar = val; +} + +void ImGui::PushStyleVarX(ImGuiStyleVar idx, float val_x) +{ + ImGuiContext& g = *GImGui; + const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); + if (var_info->Type != ImGuiDataType_Float || var_info->Count != 2) + { + IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); + return; + } + ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style); + g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar)); + pvar->x = val_x; +} + +void ImGui::PushStyleVarY(ImGuiStyleVar idx, float val_y) +{ + ImGuiContext& g = *GImGui; + const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); + if (var_info->Type != ImGuiDataType_Float || var_info->Count != 2) + { + IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); + return; + } + ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style); + g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar)); + pvar->y = val_y; } void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) { ImGuiContext& g = *GImGui; const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2) + if (var_info->Type != ImGuiDataType_Float || var_info->Count != 2) { - ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style); - g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar)); - *pvar = val; + IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); return; } - IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); + ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style); + g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar)); + *pvar = val; } void ImGui::PopStyleVar(int count) diff --git a/imgui.h b/imgui.h index c55f5dda6fad..0289e798baec 100644 --- a/imgui.h +++ b/imgui.h @@ -438,8 +438,10 @@ namespace ImGui IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col); // modify a style color. always use this if you modify the style after NewFrame(). IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col); IMGUI_API void PopStyleColor(int count = 1); - IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); // modify a style float variable. always use this if you modify the style after NewFrame(). - IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); // modify a style ImVec2 variable. always use this if you modify the style after NewFrame(). + IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); // modify a style float variable. always use this if you modify the style after NewFrame()! + IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); // modify a style ImVec2 variable. " + IMGUI_API void PushStyleVarX(ImGuiStyleVar idx, float val_x); // modify X component of a style ImVec2 variable. " + IMGUI_API void PushStyleVarY(ImGuiStyleVar idx, float val_y); // modify Y component of a style ImVec2 variable. " IMGUI_API void PopStyleVar(int count = 1); IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); // modify specified shared item flag, e.g. PushItemFlag(ImGuiItemFlags_NoTabStop, true) IMGUI_API void PopItemFlag(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 264df8af40c0..ddc8f9b2a5d2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3677,7 +3677,7 @@ static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data) { ImVec2 color_button_sz(ImGui::GetFontSize(), ImGui::GetFontSize()); if (widget_type == WidgetType_TreeNode) - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f)); + ImGui::PushStyleVarY(ImGuiStyleVar_ItemSpacing, 0.0f); ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size); selection.ApplyRequests(ms_io); @@ -3693,7 +3693,7 @@ static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data) ImGui::BeginTable("##Split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoPadOuterX); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.70f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.30f); - //ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f)); + //ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacingY, 0.0f); } ImGuiListClipper clipper; @@ -5082,8 +5082,8 @@ const ImGuiTableSortSpecs* MyItem::s_current_sort_specs = NULL; static void PushStyleCompact() { ImGuiStyle& style = ImGui::GetStyle(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, (float)(int)(style.FramePadding.y * 0.60f))); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, (float)(int)(style.ItemSpacing.y * 0.60f))); + ImGui::PushStyleVarY(ImGuiStyleVar_FramePadding, (float)(int)(style.FramePadding.y * 0.60f)); + ImGui::PushStyleVarY(ImGuiStyleVar_ItemSpacing, (float)(int)(style.ItemSpacing.y * 0.60f)); } static void PopStyleCompact() @@ -6117,7 +6117,7 @@ static void ShowDemoWindowTables() for (int row = 0; row < 8; row++) { if ((row % 3) == 2) - ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(style.CellPadding.x, 20.0f)); + ImGui::PushStyleVarY(ImGuiStyleVar_CellPadding, 20.0f); ImGui::TableNextRow(ImGuiTableRowFlags_None); ImGui::TableNextColumn(); ImGui::Text("CellPadding.y = %.2f", style.CellPadding.y); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e8d5f968325b..36cc2d6d278c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1944,7 +1944,7 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx() ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove; - PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(g.Style.FramePadding.x, g.Style.WindowPadding.y)); // Horizontally align ourselves with the framed text + PushStyleVarX(ImGuiStyleVar_WindowPadding, g.Style.FramePadding.x); // Horizontally align ourselves with the framed text bool ret = Begin(name, NULL, window_flags); PopStyleVar(); if (!ret) @@ -8688,7 +8688,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() popup_pos = ImVec2(pos.x - 1.0f - IM_TRUNC(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight); window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f); - PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); + PushStyleVarX(ImGuiStyleVar_ItemSpacing, style.ItemSpacing.x * 2.0f); float w = label_size.x; ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, label_size.y)); @@ -8895,7 +8895,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut float w = label_size.x; window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f); ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); - PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); + PushStyleVarX(ImGuiStyleVar_ItemSpacing, style.ItemSpacing.x * 2.0f); pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f)); PopStyleVar(); if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) From 8e401047952fa7e1ea80f7c3d390f7203697583b Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Aug 2024 18:13:34 +0200 Subject: [PATCH 065/548] Backends: GLFW: passing null window to glfwGetClipboardString()/glfwSetClipboardString(). --- backends/imgui_impl_glfw.cpp | 9 ++++----- docs/CHANGELOG.txt | 2 ++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index df581537b866..73aae768d3b8 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -176,14 +176,14 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() } // Functions -static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) +static const char* ImGui_ImplGlfw_GetClipboardText(void*) { - return glfwGetClipboardString((GLFWwindow*)user_data); + return glfwGetClipboardString(NULL); } -static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) +static void ImGui_ImplGlfw_SetClipboardText(void*, const char* text) { - glfwSetClipboardString((GLFWwindow*)user_data, text); + glfwSetClipboardString(NULL, text); } static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key) @@ -588,7 +588,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; - io.ClipboardUserData = bd->Window; #ifdef __EMSCRIPTEN__ io.PlatformOpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplGlfw_EmscriptenOpenURL(url); return true; }; #endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6ba4c4dadc0e..1cfe8ef8ec38 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -62,6 +62,8 @@ Other changes: provide a way to do a portable sleep. (#7844) - Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut] - Backends: SDL2, SDL3: storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. +- Backends: GLFW: passing null window to glfwGetClipboardString()/glfwSetClipboardString() + since GLFW own tests are doing that and it seems unnecessary. - 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) From e6460722ea14f61b2eff6cbfdd6770d9e4874454 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Aug 2024 16:31:10 +0200 Subject: [PATCH 066/548] IO: Added GetPlatformIO(), ImGuiPlatformIO, currently empty. --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 16 ++++++++++++++-- imgui.h | 18 ++++++++++++++---- imgui_internal.h | 1 + 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1cfe8ef8ec38..4b02e8f360f4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,9 @@ Breaking changes: Other changes: +- IO: Added GetPlatformIO() and ImGuiPlatformIO, pulled from 'docking' branch, which + is a centralized spot to connect os/platform/renderer related functions. + Clipboard, IME and OpenInShell hooks are moved here. (#7660) - IO, InputText: fixed an issue where typing text in a InputText() would defer character processing by one frame, because of the trickling input queue. Reworked interleaved keys<>char trickling to take account for keys known to input characters. (#7889, #4921, #4858) diff --git a/imgui.cpp b/imgui.cpp index bb7e55c82906..9f4d38df7409 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -63,7 +63,7 @@ CODE // [SECTION] INCLUDES // [SECTION] FORWARD DECLARATIONS // [SECTION] CONTEXT AND MEMORY ALLOCATORS -// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) +// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO, ImGuiPlatformIO) // [SECTION] MISC HELPERS/UTILITIES (Geometry functions) // [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions) // [SECTION] MISC HELPERS/UTILITIES (File functions) @@ -1244,7 +1244,7 @@ static ImGuiMemFreeFunc GImAllocatorFreeFunc = FreeWrapper; static void* GImAllocatorUserData = NULL; //----------------------------------------------------------------------------- -// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) +// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO, ImGuiPlatformIO) //----------------------------------------------------------------------------- ImGuiStyle::ImGuiStyle() @@ -1762,6 +1762,12 @@ void ImGuiIO::AddFocusEvent(bool focused) g.InputEventsQueue.push_back(e); } +ImGuiPlatformIO::ImGuiPlatformIO() +{ + // Most fields are initialized with zero + memset(this, 0, sizeof(*this)); +} + //----------------------------------------------------------------------------- // [SECTION] MISC HELPERS/UTILITIES (Geometry functions) //----------------------------------------------------------------------------- @@ -4461,6 +4467,12 @@ ImGuiIO& ImGui::GetIO() return GImGui->IO; } +ImGuiPlatformIO& ImGui::GetPlatformIO() +{ + IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext()?"); + return GImGui->PlatformIO; +} + // Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame() ImDrawData* ImGui::GetDrawData() { diff --git a/imgui.h b/imgui.h index 0289e798baec..eaffc741760d 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.1 WIP" -#define IMGUI_VERSION_NUM 19102 +#define IMGUI_VERSION_NUM 19103 #define IMGUI_HAS_TABLE /* @@ -49,7 +49,7 @@ Index of this file: // [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData) // [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont) // [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport) -// [SECTION] Platform Dependent Interfaces (ImGuiPlatformImeData) +// [SECTION] ImGuiPlatformIO + other Platform Dependent Interfaces (ImGuiPlatformImeData) // [SECTION] Obsolete functions and types */ @@ -172,13 +172,14 @@ struct ImFontGlyph; // A single font glyph (code point + coordin struct ImFontGlyphRangesBuilder; // Helper to build glyph ranges from text/string data struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*OBSOLETE* please avoid using) struct ImGuiContext; // Dear ImGui context (opaque structure, unless including imgui_internal.h) -struct ImGuiIO; // Main configuration and I/O between your application and ImGui +struct ImGuiIO; // Main configuration and I/O between your application and ImGui (also see: ImGuiPlatformIO) struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use) struct ImGuiKeyData; // Storage for ImGuiIO and IsKeyDown(), IsKeyPressed() etc functions. struct ImGuiListClipper; // Helper to manually clip large list of items struct ImGuiMultiSelectIO; // Structure to interact with a BeginMultiSelect()/EndMultiSelect() block struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame struct ImGuiPayload; // User data payload for drag and drop operations +struct ImGuiPlatformIO; // Interface between platform/renderer backends and ImGui (e.g. Clipboard, IME hooks). Extends ImGuiIO. In docking branch, this gets extended to support multi-viewports. struct ImGuiPlatformImeData; // Platform IME data for io.PlatformSetImeDataFn() function. struct ImGuiSelectionBasicStorage; // Optional helper to store multi-selection state + apply multi-selection requests. struct ImGuiSelectionExternalStorage;//Optional helper to apply multi-selection requests to existing randomly accessible storage. @@ -325,7 +326,8 @@ namespace ImGui IMGUI_API void SetCurrentContext(ImGuiContext* ctx); // Main - IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags) + IMGUI_API ImGuiIO& GetIO(); // access the ImGuiIO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags) + IMGUI_API ImGuiPlatformIO& GetPlatformIO(); // access the ImGuiPlatformIO structure (mostly hooks/functions to connect to platform/renderer and OS Clipboard, IME etc.) IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleColor(), PushStyleVar() to modify style mid-frame! IMGUI_API void NewFrame(); // start a new Dear ImGui frame, you can submit any command from this point until Render()/EndFrame(). IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(). If you don't need to render data (skipping rendering) you may call EndFrame() without Render()... but you'll have wasted CPU already! If you don't need to render, better to not create any windows and not call NewFrame() at all! @@ -2196,6 +2198,8 @@ struct ImGuiStyle // - initialization: backends and user code writes to ImGuiIO. // - main loop: backends writes to ImGuiIO, user code and imgui code reads from ImGuiIO. //----------------------------------------------------------------------------- +// Also see ImGui::GetPlatformIO() and ImGuiPlatformIO struct for OS/platform related functions: clipboard, IME etc. +//----------------------------------------------------------------------------- // [Internal] Storage used by IsKeyDown(), IsKeyPressed() etc functions. // If prior to 1.87 you used io.KeysDownDuration[] (which was marked as internal), you should use GetKeyData(key)->DownDuration and *NOT* io.KeysData[key]->DownDuration. @@ -3483,6 +3487,12 @@ struct ImGuiViewport // [SECTION] Platform Dependent Interfaces //----------------------------------------------------------------------------- +// Access via ImGui::GetPlatformIO() +struct ImGuiPlatformIO +{ + IMGUI_API ImGuiPlatformIO(); +}; + // (Optional) Support for IME (Input Method Editor) via the io.PlatformSetImeDataFn() function. struct ImGuiPlatformImeData { diff --git a/imgui_internal.h b/imgui_internal.h index 339a4e3a6be1..29099cd04b09 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1994,6 +1994,7 @@ struct ImGuiContext bool Initialized; bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it. ImGuiIO IO; + ImGuiPlatformIO PlatformIO; ImGuiStyle Style; ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. From ba2f4a2cd56e33d99798b084dc4229efb2fa1140 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Aug 2024 16:42:57 +0200 Subject: [PATCH 067/548] IO: (BREAKING) moved GetIO().PlatformOpenInShellFn to GetPlatformIO(.Platform_OpenInShellFn. (#7660) --- backends/imgui_impl_glfw.cpp | 5 ++++- backends/imgui_impl_sdl2.cpp | 5 ++++- docs/CHANGELOG.txt | 5 +++++ imconfig.h | 2 +- imgui.cpp | 15 +++++++++------ imgui.h | 14 +++++++++----- imgui_widgets.cpp | 4 ++-- 7 files changed, 34 insertions(+), 16 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 73aae768d3b8..776396786139 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -20,6 +20,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-08-22: Follow up on function pointers moved from ImGuiIO to ImGuiPlatformIO: +// - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn // 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) @@ -586,10 +588,11 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw bd->Window = window; bd->Time = 0.0; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; #ifdef __EMSCRIPTEN__ - io.PlatformOpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplGlfw_EmscriptenOpenURL(url); return true; }; + platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplGlfw_EmscriptenOpenURL(url); return true; }; #endif // Create mouse cursors diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index c4724969dfba..d9ba69d16391 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-08-22: Follow up on function pointers moved from ImGuiIO to ImGuiPlatformIO: +// - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn // 2024-08-19: Storing SDL's Uint32 WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. // 2024-08-19: ImGui_ImplSDL2_ProcessEvent() now ignores events intended for other SDL windows. (#7853) // 2024-07-02: Emscripten: Added io.PlatformOpenInShellFn() handler for Emscripten versions. @@ -458,12 +460,13 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void bd->Renderer = renderer; bd->MouseCanUseGlobalState = mouse_can_use_global_state; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText; io.ClipboardUserData = nullptr; io.PlatformSetImeDataFn = ImGui_ImplSDL2_PlatformSetImeData; #ifdef __EMSCRIPTEN__ - io.PlatformOpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplSDL2_EmscriptenOpenURL(url); return true; }; + platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplSDL2_EmscriptenOpenURL(url); return true; }; #endif // Gamepad handling diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4b02e8f360f4..4cbeb025cb60 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,10 @@ HOW TO UPDATE? Breaking changes: +- IO: moved some functions from ImGuiIO to ImGuiPlatformIO: + - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn. (#7660) + - access those via GetPlatformIO() instead of GetIO(). + Other changes: - IO: Added GetPlatformIO() and ImGuiPlatformIO, pulled from 'docking' branch, which @@ -114,6 +118,7 @@ Other changes: - Added TextLink(), TextLinkOpenURL() hyperlink widgets. (#7660) - IO: added io.PlatformOpenInShellFn handler to open a link/folder/file in OS shell. (#7660) + (*EDIT* From next version 1.91.1 we moved this to platform_io.Platform_OpenInShellFn *EDIT**) Added IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS to disable default Windows/Linux/Mac implementations. - IO: added io.ConfigNavSwapGamepadButtons to swap Activate/Cancel (A<>B) buttons, to match the typical "Nintendo/Japanese consoles" button layout when using Gamepad navigation. (#787, #5723) diff --git a/imconfig.h b/imconfig.h index 6e4c743d4ed9..b8d55842b9bf 100644 --- a/imconfig.h +++ b/imconfig.h @@ -43,7 +43,7 @@ //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME). //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). -//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default io.PlatformOpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")). +//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")). //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) diff --git a/imgui.cpp b/imgui.cpp index 9f4d38df7409..d4eb59b9b44f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -430,6 +430,10 @@ 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. + - 2024/08/22 (1.91.1) - moved some functions from ImGuiIO to ImGuiPlatformIO structure: + - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn. (#7660) + - access those via GetPlatformIO() instead of GetIO(). + some were introduced very recently and often automatically setup by core library and backends, so for those we are exceptionally not maintaining a legacy redirection symbol. - 2024/07/25 (1.91.0) - obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). (see #7838 on GitHub for more info) you should never need those functions. you can do everything with GetCursorScreenPos() and GetContentRegionAvail() in a more simple way. - instead of: GetWindowContentRegionMax().x - GetCursorPos().x @@ -1144,7 +1148,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSetti static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx); static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text); static void PlatformSetImeDataFn_DefaultImpl(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); -static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext* ctx, const char* path); +static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext* ctx, const char* path); namespace ImGui { @@ -1393,7 +1397,6 @@ ImGuiIO::ImGuiIO() // Note: Initialize() will setup default clipboard/ime handlers. BackendPlatformName = BackendRendererName = NULL; BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL; - PlatformOpenInShellUserData = NULL; PlatformLocaleDecimalPoint = '.'; // Input (NB: we already have memset zero the entire structure!) @@ -3805,7 +3808,7 @@ void ImGui::Initialize() g.IO.GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations g.IO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; g.IO.ClipboardUserData = (void*)&g; // Default implementation use the ImGuiContext as user data (ideally those would be arguments to the function) - g.IO.PlatformOpenInShellFn = PlatformOpenInShellFn_DefaultImpl; + g.PlatformIO.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl; g.IO.PlatformSetImeDataFn = PlatformSetImeDataFn_DefaultImpl; // Create default viewport @@ -14477,14 +14480,14 @@ static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text #ifdef _MSC_VER #pragma comment(lib, "shell32") #endif -static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) +static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) { return (INT_PTR)::ShellExecuteA(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT) > 32; } #else #include #include -static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) +static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) { #if defined(__APPLE__) const char* args[] { "open", "--", path, NULL }; @@ -14508,7 +14511,7 @@ static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) } #endif #else -static bool PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char*) { return false; } +static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*, const char*) { return false; } #endif // Default shell handlers //----------------------------------------------------------------------------- diff --git a/imgui.h b/imgui.h index eaffc741760d..9a745dd901c1 100644 --- a/imgui.h +++ b/imgui.h @@ -2295,11 +2295,6 @@ struct ImGuiIO void (*SetClipboardTextFn)(void* user_data, const char* text); void* ClipboardUserData; - // Optional: Open link/folder/file in OS Shell - // (default to use ShellExecuteA() on Windows, system() on Linux/Mac) - bool (*PlatformOpenInShellFn)(ImGuiContext* ctx, const char* path); - void* PlatformOpenInShellUserData; - // Optional: Notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME on Windows) // (default to use native imm32 api on Windows) void (*PlatformSetImeDataFn)(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); @@ -3491,6 +3486,15 @@ struct ImGuiViewport struct ImGuiPlatformIO { IMGUI_API ImGuiPlatformIO(); + + //------------------------------------------------------------------ + // Inputs - Interface with OS/backends + //------------------------------------------------------------------ + + // Optional: Open link/folder/file in OS Shell + // (default to use ShellExecuteA() on Windows, system() on Linux/Mac) + bool (*Platform_OpenInShellFn)(ImGuiContext* ctx, const char* path); + void* Platform_OpenInShellUserData; }; // (Optional) Support for IME (Input Method Editor) via the io.PlatformSetImeDataFn() function. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 36cc2d6d278c..f064a5dd87c8 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1462,8 +1462,8 @@ void ImGui::TextLinkOpenURL(const char* label, const char* url) if (url == NULL) url = label; if (TextLink(label)) - if (g.IO.PlatformOpenInShellFn != NULL) - g.IO.PlatformOpenInShellFn(&g, url); + if (g.PlatformIO.Platform_OpenInShellFn != NULL) + g.PlatformIO.Platform_OpenInShellFn(&g, url); SetItemTooltip("%s", url); // It is more reassuring for user to _always_ display URL when we same as label if (BeginPopupContextItem()) { From 9ff60ae31d5d2328c0081ae17024d4057ad8a22a Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Aug 2024 16:55:14 +0200 Subject: [PATCH 068/548] IO: (BREAKING) moved GetIO().PlatformSetImeDataFn to GetPlatformIO(.Platform_SetImeDataFn. (#7660) --- backends/imgui_impl_osx.mm | 5 ++++- backends/imgui_impl_sdl2.cpp | 3 ++- backends/imgui_impl_sdl3.cpp | 5 ++++- docs/CHANGELOG.txt | 4 ++++ docs/FAQ.md | 2 +- imgui.cpp | 17 +++++++++-------- imgui.h | 13 +++++++------ imgui_internal.h | 2 +- 8 files changed, 32 insertions(+), 19 deletions(-) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index ab0e0ecc62fe..30f4ab24af11 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -29,6 +29,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-08-22: Follow up on function pointers moved from ImGuiIO to ImGuiPlatformIO: +// - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn // 2024-07-02: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() renaming in main library. // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F20 function keys. Stopped mapping F13 into PrintScreen. // 2023-04-09: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_Pen. @@ -465,7 +467,8 @@ bool ImGui_ImplOSX_Init(NSView* view) [view addSubview:bd->KeyEventResponder]; ImGui_ImplOSX_AddTrackingArea(view); - io.PlatformSetImeDataFn = [](ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Platform_SetImeDataFn = [](ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void { ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); if (data->WantVisible) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index d9ba69d16391..c30fe6d81f69 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -23,6 +23,7 @@ // (minor and older changes stripped away, please see git history for details) // 2024-08-22: Follow up on function pointers moved from ImGuiIO to ImGuiPlatformIO: // - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn +// - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn // 2024-08-19: Storing SDL's Uint32 WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. // 2024-08-19: ImGui_ImplSDL2_ProcessEvent() now ignores events intended for other SDL windows. (#7853) // 2024-07-02: Emscripten: Added io.PlatformOpenInShellFn() handler for Emscripten versions. @@ -464,7 +465,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText; io.ClipboardUserData = nullptr; - io.PlatformSetImeDataFn = ImGui_ImplSDL2_PlatformSetImeData; + platform_io.Platform_SetImeDataFn = ImGui_ImplSDL2_PlatformSetImeData; #ifdef __EMSCRIPTEN__ platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplSDL2_EmscriptenOpenURL(url); return true; }; #endif diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 24627347bc5a..37ab21c24ae8 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -21,6 +21,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-08-22: Follow up on function pointers moved from ImGuiIO to ImGuiPlatformIO: +// - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn // 2024-08-19: Storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. // 2024-08-19: ImGui_ImplSDL3_ProcessEvent() now ignores events intended for other SDL windows. (#7853) // 2024-07-22: Update for SDL3 api changes: SDL_GetGamepads() memory ownership change. (#7807) @@ -454,10 +456,11 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void bd->Renderer = renderer; bd->MouseCanUseGlobalState = mouse_can_use_global_state; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); io.SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText; io.ClipboardUserData = nullptr; - io.PlatformSetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData; + platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData; // Gamepad handling bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4cbeb025cb60..85e3cb04d771 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,7 +43,11 @@ Breaking changes: - IO: moved some functions from ImGuiIO to ImGuiPlatformIO: - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn. (#7660) + - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn. - access those via GetPlatformIO() instead of GetIO(). + (Because PlatformOpenInShellFn and PlatformSetImeDataFn were introduced very recently and + often automatically set by core library and backends, we are exceptionally not maintaining + a legacy redirection symbol for those two.) Other changes: diff --git a/docs/FAQ.md b/docs/FAQ.md index e120e8cd6797..d104c30bc577 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -639,7 +639,7 @@ The applications in examples/ are doing that. Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode). You may also use `MultiByteToWideChar()` or `ToUnicode()` to retrieve Unicode codepoints from MultiByte characters or keyboard state. Windows: if your language is relying on an Input Method Editor (IME), you can write your HWND to ImGui::GetMainViewport()->PlatformHandleRaw -for the default implementation of io.PlatformSetImeDataFn() to set your Microsoft IME position correctly. +for the default implementation of GetPlatformIO().Platform_SetImeDataFn() to set your Microsoft IME position correctly. ##### [Return to Index](#index) diff --git a/imgui.cpp b/imgui.cpp index d4eb59b9b44f..e7615b1c5f28 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -431,7 +431,8 @@ CODE You can read releases logs https://github.com/ocornut/imgui/releases for more details. - 2024/08/22 (1.91.1) - moved some functions from ImGuiIO to ImGuiPlatformIO structure: - - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn. (#7660) + - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn (#7660) + - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn - access those via GetPlatformIO() instead of GetIO(). some were introduced very recently and often automatically setup by core library and backends, so for those we are exceptionally not maintaining a legacy redirection symbol. - 2024/07/25 (1.91.0) - obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). (see #7838 on GitHub for more info) @@ -1147,7 +1148,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSetti // Platform Dependents default implementation for IO functions static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx); static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text); -static void PlatformSetImeDataFn_DefaultImpl(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); +static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext* ctx, const char* path); namespace ImGui @@ -3809,7 +3810,7 @@ void ImGui::Initialize() g.IO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; g.IO.ClipboardUserData = (void*)&g; // Default implementation use the ImGuiContext as user data (ideally those would be arguments to the function) g.PlatformIO.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl; - g.IO.PlatformSetImeDataFn = PlatformSetImeDataFn_DefaultImpl; + g.PlatformIO.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl; // Create default viewport ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)(); @@ -5226,11 +5227,11 @@ void ImGui::EndFrame() // Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) ImGuiPlatformImeData* ime_data = &g.PlatformImeData; - if (g.IO.PlatformSetImeDataFn != NULL && memcmp(ime_data, &g.PlatformImeDataPrev, sizeof(ImGuiPlatformImeData)) != 0) + if (g.PlatformIO.Platform_SetImeDataFn != NULL && memcmp(ime_data, &g.PlatformImeDataPrev, sizeof(ImGuiPlatformImeData)) != 0) { - IMGUI_DEBUG_LOG_IO("[io] Calling io.PlatformSetImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y); + IMGUI_DEBUG_LOG_IO("[io] Calling Platform_SetImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y); ImGuiViewport* viewport = GetMainViewport(); - g.IO.PlatformSetImeDataFn(&g, viewport, ime_data); + g.PlatformIO.Platform_SetImeDataFn(&g, viewport, ime_data); } // Hide implicit/fallback "Debug" window if it hasn't been used @@ -14524,7 +14525,7 @@ static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*, const char*) { ret #pragma comment(lib, "imm32") #endif -static void PlatformSetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data) +static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data) { // Notify OS Input Method Editor of text input position HWND hwnd = (HWND)viewport->PlatformHandleRaw; @@ -14550,7 +14551,7 @@ static void PlatformSetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport* viewp #else -static void PlatformSetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData*) {} +static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport*, ImGuiPlatformImeData*) {} #endif // Default IME handlers diff --git a/imgui.h b/imgui.h index 9a745dd901c1..0400abdcd236 100644 --- a/imgui.h +++ b/imgui.h @@ -2295,11 +2295,6 @@ struct ImGuiIO void (*SetClipboardTextFn)(void* user_data, const char* text); void* ClipboardUserData; - // Optional: Notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME on Windows) - // (default to use native imm32 api on Windows) - void (*PlatformSetImeDataFn)(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); - //void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data); // [Renamed to io.PlatformSetImeDataFn in 1.91.0] - // Optional: Platform locale ImWchar PlatformLocaleDecimalPoint; // '.' // [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point @@ -3495,9 +3490,15 @@ struct ImGuiPlatformIO // (default to use ShellExecuteA() on Windows, system() on Linux/Mac) bool (*Platform_OpenInShellFn)(ImGuiContext* ctx, const char* path); void* Platform_OpenInShellUserData; + + // Optional: Notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME on Windows) + // (default to use native imm32 api on Windows) + void (*Platform_SetImeDataFn)(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); + void* Platform_ImeUserData; + //void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data); // [Renamed to platform_io.PlatformSetImeDataFn in 1.91.1] }; -// (Optional) Support for IME (Input Method Editor) via the io.PlatformSetImeDataFn() function. +// (Optional) Support for IME (Input Method Editor) via the platform_io.Platform_SetImeDataFn() function. struct ImGuiPlatformImeData { bool WantVisible; // A widget wants the IME to be visible diff --git a/imgui_internal.h b/imgui_internal.h index 29099cd04b09..6bd2aa457810 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2275,7 +2275,7 @@ struct ImGuiContext // Platform support ImGuiPlatformImeData PlatformImeData; // Data updated by current frame - ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data. When changed we call the io.PlatformSetImeDataFn() handler. + ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data. When changed we call the platform_io.Platform_SetImeDataFn() handler. // Settings bool SettingsLoaded; From e54f240ea0aad351ee7971e2cb7afe8881120dde Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Aug 2024 17:18:16 +0200 Subject: [PATCH 069/548] IO: (BREAKING) moved io.PlatformLocaleDecimalPoint to platform_io.Platform_LocaleDecimalPoint. (#7389, #6719, #2278) --- docs/CHANGELOG.txt | 5 +++-- imgui.cpp | 7 ++++--- imgui.h | 7 ++++--- imgui_widgets.cpp | 4 ++-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 85e3cb04d771..a061e71c8e54 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,8 +42,9 @@ HOW TO UPDATE? Breaking changes: - IO: moved some functions from ImGuiIO to ImGuiPlatformIO: - - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn. (#7660) - - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn. + - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn. (#7660) + - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn. + - io.PlatformLocaleDecimalPoint -> platform_io.Platform_LocaleDecimalPoint. (#7389, #6719, #2278) - access those via GetPlatformIO() instead of GetIO(). (Because PlatformOpenInShellFn and PlatformSetImeDataFn were introduced very recently and often automatically set by core library and backends, we are exceptionally not maintaining diff --git a/imgui.cpp b/imgui.cpp index e7615b1c5f28..deed85399c5a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -431,8 +431,9 @@ CODE You can read releases logs https://github.com/ocornut/imgui/releases for more details. - 2024/08/22 (1.91.1) - moved some functions from ImGuiIO to ImGuiPlatformIO structure: - - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn (#7660) - - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn + - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn (#7660) + - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn + - io.PlatformLocaleDecimalPoint -> platform_io.Platform_LocaleDecimalPoint (#7389, #6719, #2278) - access those via GetPlatformIO() instead of GetIO(). some were introduced very recently and often automatically setup by core library and backends, so for those we are exceptionally not maintaining a legacy redirection symbol. - 2024/07/25 (1.91.0) - obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). (see #7838 on GitHub for more info) @@ -1398,7 +1399,6 @@ ImGuiIO::ImGuiIO() // Note: Initialize() will setup default clipboard/ime handlers. BackendPlatformName = BackendRendererName = NULL; BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL; - PlatformLocaleDecimalPoint = '.'; // Input (NB: we already have memset zero the entire structure!) MousePos = ImVec2(-FLT_MAX, -FLT_MAX); @@ -1770,6 +1770,7 @@ ImGuiPlatformIO::ImGuiPlatformIO() { // Most fields are initialized with zero memset(this, 0, sizeof(*this)); + Platform_LocaleDecimalPoint = '.'; } //----------------------------------------------------------------------------- diff --git a/imgui.h b/imgui.h index 0400abdcd236..a1ccfd73d13b 100644 --- a/imgui.h +++ b/imgui.h @@ -2295,9 +2295,6 @@ struct ImGuiIO void (*SetClipboardTextFn)(void* user_data, const char* text); void* ClipboardUserData; - // Optional: Platform locale - ImWchar PlatformLocaleDecimalPoint; // '.' // [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point - //------------------------------------------------------------------ // Input - Call before calling NewFrame() //------------------------------------------------------------------ @@ -3496,6 +3493,10 @@ struct ImGuiPlatformIO void (*Platform_SetImeDataFn)(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); void* Platform_ImeUserData; //void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data); // [Renamed to platform_io.PlatformSetImeDataFn in 1.91.1] + + // Optional: Platform locale + // [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point + ImWchar Platform_LocaleDecimalPoint; // '.' }; // (Optional) Support for IME (Input Method Editor) via the platform_io.Platform_SetImeDataFn() function. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f064a5dd87c8..f4625f2a7844 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4132,10 +4132,10 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im // The standard mandate that programs starts in the "C" locale where the decimal point is '.'. // We don't really intend to provide widespread support for it, but out of empathy for people stuck with using odd API, we support the bare minimum aka overriding the decimal point. // Change the default decimal_point with: - // ImGui::GetIO()->PlatformLocaleDecimalPoint = *localeconv()->decimal_point; + // ImGui::GetPlatformIO()->Platform_LocaleDecimalPoint = *localeconv()->decimal_point; // Users of non-default decimal point (in particular ',') may be affected by word-selection logic (is_word_boundary_from_right/is_word_boundary_from_left) functions. ImGuiContext& g = *ctx; - const unsigned c_decimal_point = (unsigned int)g.IO.PlatformLocaleDecimalPoint; + const unsigned c_decimal_point = (unsigned int)g.PlatformIO.Platform_LocaleDecimalPoint; if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint)) if (c == '.' || c == ',') c = c_decimal_point; From 214977e5fd1ba25d8c77824b2993450b63cdc075 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Aug 2024 17:50:10 +0200 Subject: [PATCH 070/548] IO: (BREAKING) moved io.GetClipboardTextFn, io.SetClipboardTextFn to platform_io.Platform_GetClipboardTextFn, platform_io.Platform_SetClipboardTextFn. --- backends/imgui_impl_allegro5.cpp | 13 +++++---- backends/imgui_impl_glfw.cpp | 4 ++- backends/imgui_impl_osx.mm | 10 ++++--- backends/imgui_impl_sdl2.cpp | 14 +++++---- backends/imgui_impl_sdl3.cpp | 13 +++++---- docs/CHANGELOG.txt | 18 +++++++++--- imgui.cpp | 49 +++++++++++++++++++------------- imgui.h | 20 +++++++++---- imgui_widgets.cpp | 2 +- 9 files changed, 90 insertions(+), 53 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index db366fa742b0..e41f021401d0 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -20,6 +20,9 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: +// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn +// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn // 2022-11-30: Renderer: Restoring using al_draw_indexed_prim() when Allegro version is >= 5.2.5. // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). @@ -291,7 +294,7 @@ void ImGui_ImplAllegro5_InvalidateDeviceObjects() } #if ALLEGRO_HAS_CLIPBOARD -static const char* ImGui_ImplAllegro5_GetClipboardText(void*) +static const char* ImGui_ImplAllegro5_GetClipboardText(ImGuiContext*) { ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); if (bd->ClipboardTextData) @@ -300,7 +303,7 @@ static const char* ImGui_ImplAllegro5_GetClipboardText(void*) return bd->ClipboardTextData; } -static void ImGui_ImplAllegro5_SetClipboardText(void*, const char* text) +static void ImGui_ImplAllegro5_SetClipboardText(ImGuiContext*, const char* text) { ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); al_set_clipboard_text(bd->Display, text); @@ -447,9 +450,9 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) bd->VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro)); #if ALLEGRO_HAS_CLIPBOARD - io.SetClipboardTextFn = ImGui_ImplAllegro5_SetClipboardText; - io.GetClipboardTextFn = ImGui_ImplAllegro5_GetClipboardText; - io.ClipboardUserData = nullptr; + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Platform_SetClipboardTextFn = ImGui_ImplAllegro5_SetClipboardText; + platform_io.Platform_GetClipboardTextFn = ImGui_ImplAllegro5_GetClipboardText; #endif return true; diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 776396786139..66b71c5e7c11 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -20,7 +20,9 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-08-22: Follow up on function pointers moved from ImGuiIO to ImGuiPlatformIO: +// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: +// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn +// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn // - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn // 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. diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 30f4ab24af11..870038d85084 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -29,7 +29,9 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-08-22: Follow up on function pointers moved from ImGuiIO to ImGuiPlatformIO: +// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: +// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn +// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn // - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn // 2024-07-02: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() renaming in main library. // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F20 function keys. Stopped mapping F13 into PrintScreen. @@ -395,6 +397,7 @@ IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(void* _Nullable view) { bool ImGui_ImplOSX_Init(NSView* view) { ImGuiIO& io = ImGui::GetIO(); + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); @@ -425,14 +428,14 @@ bool ImGui_ImplOSX_Init(NSView* view) // Note that imgui.cpp also include default OSX clipboard handlers which can be enabled // by adding '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h and adding '-framework ApplicationServices' to your linker command-line. // Since we are already in ObjC land here, it is easy for us to add a clipboard handler using the NSPasteboard api. - io.SetClipboardTextFn = [](void*, const char* str) -> void + platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* str) -> void { NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; [pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil]; [pasteboard setString:[NSString stringWithUTF8String:str] forType:NSPasteboardTypeString]; }; - io.GetClipboardTextFn = [](void*) -> const char* + platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) -> const char* { NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; NSString* available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:NSPasteboardTypeString]]; @@ -467,7 +470,6 @@ bool ImGui_ImplOSX_Init(NSView* view) [view addSubview:bd->KeyEventResponder]; ImGui_ImplOSX_AddTrackingArea(view); - ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); platform_io.Platform_SetImeDataFn = [](ImGuiContext*, ImGuiViewport* viewport, ImGuiPlatformImeData* data) -> void { ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index c30fe6d81f69..b1cc8c9e65c5 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,7 +21,9 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-08-22: Follow up on function pointers moved from ImGuiIO to ImGuiPlatformIO: +// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: +// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn +// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn // - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn // - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn // 2024-08-19: Storing SDL's Uint32 WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. @@ -146,7 +148,7 @@ static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData() } // Functions -static const char* ImGui_ImplSDL2_GetClipboardText(void*) +static const char* ImGui_ImplSDL2_GetClipboardText(ImGuiContext*) { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); if (bd->ClipboardTextData) @@ -155,7 +157,7 @@ static const char* ImGui_ImplSDL2_GetClipboardText(void*) return bd->ClipboardTextData; } -static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text) +static void ImGui_ImplSDL2_SetClipboardText(ImGuiContext*, const char* text) { SDL_SetClipboardText(text); } @@ -462,9 +464,9 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void bd->MouseCanUseGlobalState = mouse_can_use_global_state; ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText; - io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText; - io.ClipboardUserData = nullptr; + platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText; + platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText; + platform_io.Platform_ClipboardUserData = nullptr; platform_io.Platform_SetImeDataFn = ImGui_ImplSDL2_PlatformSetImeData; #ifdef __EMSCRIPTEN__ platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplSDL2_EmscriptenOpenURL(url); return true; }; diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 37ab21c24ae8..deb8c7925dc5 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -21,7 +21,9 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-08-22: Follow up on function pointers moved from ImGuiIO to ImGuiPlatformIO: +// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: +// - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn +// - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn // - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn // 2024-08-19: Storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. // 2024-08-19: ImGui_ImplSDL3_ProcessEvent() now ignores events intended for other SDL windows. (#7853) @@ -118,7 +120,7 @@ static ImGui_ImplSDL3_Data* ImGui_ImplSDL3_GetBackendData() } // Functions -static const char* ImGui_ImplSDL3_GetClipboardText(void*) +static const char* ImGui_ImplSDL3_GetClipboardText(ImGuiContext*) { ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); if (bd->ClipboardTextData) @@ -128,7 +130,7 @@ static const char* ImGui_ImplSDL3_GetClipboardText(void*) return bd->ClipboardTextData; } -static void ImGui_ImplSDL3_SetClipboardText(void*, const char* text) +static void ImGui_ImplSDL3_SetClipboardText(ImGuiContext*, const char* text) { SDL_SetClipboardText(text); } @@ -457,9 +459,8 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void bd->MouseCanUseGlobalState = mouse_can_use_global_state; ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - io.SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText; - io.GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText; - io.ClipboardUserData = nullptr; + platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText; + platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText; platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData; // Gamepad handling diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a061e71c8e54..25cd2b8c74fc 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,10 +41,18 @@ HOW TO UPDATE? Breaking changes: -- IO: moved some functions from ImGuiIO to ImGuiPlatformIO: - - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn. (#7660) - - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn. - - io.PlatformLocaleDecimalPoint -> platform_io.Platform_LocaleDecimalPoint. (#7389, #6719, #2278) +- IO: moved clipboard functions from ImGuiIO to ImGuiPlatformIO: + - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn + - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn + - in function signatures, changed 'void* user_data' to 'ImGuiContext* ctx' for consistency + with other functions. Pull your user data from platform_io.ClipboardUserData if used. + - as this is will affect all users of custom engines/backends, we are providing proper + legacy redirection (will obsolete). +- IO: moved other functions from ImGuiIO to ImGuiPlatformIO: + - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn (#7660) + - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn + - io.PlatformLocaleDecimalPoint -> platform_io.Platform_LocaleDecimalPoint (#7389, #6719, #2278) + - clipboard function signature changed: - access those via GetPlatformIO() instead of GetIO(). (Because PlatformOpenInShellFn and PlatformSetImeDataFn were introduced very recently and often automatically set by core library and backends, we are exceptionally not maintaining @@ -76,6 +84,8 @@ Other changes: - Backends: SDL2, SDL3: storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. - Backends: GLFW: passing null window to glfwGetClipboardString()/glfwSetClipboardString() since GLFW own tests are doing that and it seems unnecessary. +- Backends: SDL2, SDL3, GLFW, OSX, Allegro: update to set function handlers in ImGuiPlatformIO + instead of ImGuiIO. - 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/imgui.cpp b/imgui.cpp index deed85399c5a..381ffb259601 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -431,6 +431,8 @@ CODE You can read releases logs https://github.com/ocornut/imgui/releases for more details. - 2024/08/22 (1.91.1) - moved some functions from ImGuiIO to ImGuiPlatformIO structure: + - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn + changed 'void* user_data' to 'ImGuiContext* ctx'. Pull your user data from platform_io.ClipboardUserData. + - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn + same as above line. - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn (#7660) - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn - io.PlatformLocaleDecimalPoint -> platform_io.Platform_LocaleDecimalPoint (#7389, #6719, #2278) @@ -1146,9 +1148,9 @@ static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSetti static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*); static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf); -// Platform Dependents default implementation for IO functions -static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx); -static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text); +// Platform Dependents default implementation for ImGuiPlatformIO functions +static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx); +static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const char* text); static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext* ctx, ImGuiViewport* viewport, ImGuiPlatformImeData* data); static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext* ctx, const char* path); @@ -3806,10 +3808,9 @@ void ImGui::Initialize() // Setup default localization table LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_ARRAYSIZE(GLocalizationEntriesEnUS)); - // Setup default platform clipboard/IME handlers. - g.IO.GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations - g.IO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; - g.IO.ClipboardUserData = (void*)&g; // Default implementation use the ImGuiContext as user data (ideally those would be arguments to the function) + // Setup default ImGuiPlatformIO clipboard/IME handlers. + g.PlatformIO.Platform_GetClipboardTextFn = Platform_GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations + g.PlatformIO.Platform_SetClipboardTextFn = Platform_SetClipboardTextFn_DefaultImpl; g.PlatformIO.Platform_OpenInShellFn = Platform_OpenInShellFn_DefaultImpl; g.PlatformIO.Platform_SetImeDataFn = Platform_SetImeDataFn_DefaultImpl; @@ -4451,14 +4452,14 @@ void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr const char* ImGui::GetClipboardText() { ImGuiContext& g = *GImGui; - return g.IO.GetClipboardTextFn ? g.IO.GetClipboardTextFn(g.IO.ClipboardUserData) : ""; + return g.PlatformIO.Platform_GetClipboardTextFn ? g.PlatformIO.Platform_GetClipboardTextFn(&g) : ""; } void ImGui::SetClipboardText(const char* text) { ImGuiContext& g = *GImGui; - if (g.IO.SetClipboardTextFn) - g.IO.SetClipboardTextFn(g.IO.ClipboardUserData, text); + if (g.PlatformIO.Platform_SetClipboardTextFn != NULL) + g.PlatformIO.Platform_SetClipboardTextFn(&g, text); } const char* ImGui::GetVersion() @@ -10096,6 +10097,14 @@ static void ImGui::ErrorCheckNewFrameSanityChecks() if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && g.IO.BackendUsingLegacyKeyArrays == 1) IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); #endif + + // Remap legacy clipboard handlers (OBSOLETED in 1.91.1, August 2024) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + if (g.IO.GetClipboardTextFn != NULL && (g.PlatformIO.Platform_GetClipboardTextFn == NULL || g.PlatformIO.Platform_GetClipboardTextFn == Platform_GetClipboardTextFn_DefaultImpl)) + g.PlatformIO.Platform_GetClipboardTextFn = [](ImGuiContext* ctx) { return ctx->IO.GetClipboardTextFn(ctx->IO.ClipboardUserData); }; + if (g.IO.SetClipboardTextFn != NULL && (g.PlatformIO.Platform_SetClipboardTextFn == NULL || g.PlatformIO.Platform_SetClipboardTextFn == Platform_SetClipboardTextFn_DefaultImpl)) + g.PlatformIO.Platform_SetClipboardTextFn = [](ImGuiContext* ctx, const char* text) { return ctx->IO.SetClipboardTextFn(ctx->IO.ClipboardUserData, text); }; +#endif } static void ImGui::ErrorCheckEndFrameSanityChecks() @@ -14347,9 +14356,9 @@ static void ImGui::UpdateViewportsNewFrame() // Win32 clipboard implementation // We use g.ClipboardHandlerData for temporary storage to ensure it is freed on Shutdown() -static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx) +static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx) { - ImGuiContext& g = *(ImGuiContext*)user_data_ctx; + ImGuiContext& g = *ctx; g.ClipboardHandlerData.clear(); if (!::OpenClipboard(NULL)) return NULL; @@ -14370,7 +14379,7 @@ static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx) return g.ClipboardHandlerData.Data; } -static void SetClipboardTextFn_DefaultImpl(void*, const char* text) +static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext*, const char* text) { if (!::OpenClipboard(NULL)) return; @@ -14397,7 +14406,7 @@ static PasteboardRef main_clipboard = 0; // OSX clipboard implementation // If you enable this you will need to add '-framework ApplicationServices' to your linker command-line! -static void SetClipboardTextFn_DefaultImpl(void*, const char* text) +static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext*, const char* text) { if (!main_clipboard) PasteboardCreate(kPasteboardClipboard, &main_clipboard); @@ -14410,9 +14419,9 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) } } -static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx) +static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx) { - ImGuiContext& g = *(ImGuiContext*)user_data_ctx; + ImGuiContext& g = *ctx; if (!main_clipboard) PasteboardCreate(kPasteboardClipboard, &main_clipboard); PasteboardSynchronize(main_clipboard); @@ -14446,15 +14455,15 @@ static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx) #else // Local Dear ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers. -static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx) +static const char* Platform_GetClipboardTextFn_DefaultImpl(ImGuiContext* ctx) { - ImGuiContext& g = *(ImGuiContext*)user_data_ctx; + ImGuiContext& g = *ctx; return g.ClipboardHandlerData.empty() ? NULL : g.ClipboardHandlerData.begin(); } -static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text) +static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const char* text) { - ImGuiContext& g = *(ImGuiContext*)user_data_ctx; + ImGuiContext& g = *ctx; g.ClipboardHandlerData.clear(); const char* text_end = text + strlen(text); g.ClipboardHandlerData.resize((int)(text_end - text) + 1); diff --git a/imgui.h b/imgui.h index a1ccfd73d13b..2825cc60ccca 100644 --- a/imgui.h +++ b/imgui.h @@ -2289,12 +2289,6 @@ struct ImGuiIO void* BackendRendererUserData; // = NULL // User data for renderer backend void* BackendLanguageUserData; // = NULL // User data for non C++ programming language backend - // Optional: Access OS clipboard - // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) - const char* (*GetClipboardTextFn)(void* user_data); - void (*SetClipboardTextFn)(void* user_data, const char* text); - void* ClipboardUserData; - //------------------------------------------------------------------ // Input - Call before calling NewFrame() //------------------------------------------------------------------ @@ -2396,6 +2390,14 @@ struct ImGuiIO //void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning. #endif + // Legacy: before 1.91.1, clipboard functions were stored in ImGuiIO instead of ImGuiPlatformIO. + // As this is will affect all users of custom engines/backends, we are providing proper legacy redirection (will obsolete). +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + const char* (*GetClipboardTextFn)(void* user_data); + void (*SetClipboardTextFn)(void* user_data, const char* text); + void* ClipboardUserData; +#endif + IMGUI_API ImGuiIO(); }; @@ -3483,6 +3485,12 @@ struct ImGuiPlatformIO // Inputs - Interface with OS/backends //------------------------------------------------------------------ + // Optional: Access OS clipboard + // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) + const char* (*Platform_GetClipboardTextFn)(ImGuiContext* ctx); + void (*Platform_SetClipboardTextFn)(ImGuiContext* ctx, const char* text); + void* Platform_ClipboardUserData; + // Optional: Open link/folder/file in OS Shell // (default to use ShellExecuteA() on Windows, system() on Linux/Mac) bool (*Platform_OpenInShellFn)(ImGuiContext* ctx, const char* path); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f4625f2a7844..2d96ed909441 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4740,7 +4740,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ else if (is_cut || is_copy) { // Cut, Copy - if (io.SetClipboardTextFn) + if (g.PlatformIO.Platform_SetClipboardTextFn != NULL) { const int ib = state->HasSelection() ? ImMin(state->Stb.select_start, state->Stb.select_end) : 0; const int ie = state->HasSelection() ? ImMax(state->Stb.select_start, state->Stb.select_end) : state->CurLenW; From 5de7f69cbb9d52dc2cebb27261dfadcf0da3840d Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Aug 2024 19:53:49 +0200 Subject: [PATCH 071/548] (BREAKING) Commented out obsolete ImageButton(). (#5533, #4471, #2464, #1390) --- docs/CHANGELOG.txt | 5 +++++ docs/TODO.txt | 1 + imgui.cpp | 5 +++++ imgui.h | 4 ++-- imgui_widgets.cpp | 20 ++++++++------------ 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 25cd2b8c74fc..181cccfc1855 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,11 @@ Breaking changes: (Because PlatformOpenInShellFn and PlatformSetImeDataFn were introduced very recently and often automatically set by core library and backends, we are exceptionally not maintaining a legacy redirection symbol for those two.) +- Commented the old ImageButton() signature obsoleted in 1.89 (~August 2022). (#5533, #4471, #2464, #1390) + - old ImageButton() used ImTextureId as item id (created issue with e.g. multiple buttons in same scope, transient texture id values, opaque computation of ID) + - new ImageButton() requires an explicit 'const char* str_id' + - old ImageButton() had frame_padding' override argument. + - new ImageButton() always use style.FramePadding, which you can freely override with PushStyleVar()/PopStyleVar(). Other changes: diff --git a/docs/TODO.txt b/docs/TODO.txt index cd992784dc01..84a00bc6e92b 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -190,6 +190,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - tree node/opt: could avoid formatting when clipped (flag assuming we don't care about width/height, assume single line height? format only %s/%c to be able to count height?) - settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes? + - settings: facilitate extension lazily calling AddSettingsHandler() while running and still getting their data call the ReadXXX handlers immediately. - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437) - settings/persistence: helpers to make TreeNodeBehavior persist (even during dev!) - may need to store some semantic and/or data type in ImGuiStoragePair diff --git a/imgui.cpp b/imgui.cpp index 381ffb259601..457fc2031c86 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -438,6 +438,11 @@ CODE - io.PlatformLocaleDecimalPoint -> platform_io.Platform_LocaleDecimalPoint (#7389, #6719, #2278) - access those via GetPlatformIO() instead of GetIO(). some were introduced very recently and often automatically setup by core library and backends, so for those we are exceptionally not maintaining a legacy redirection symbol. + - commented the old ImageButton() signature obsoleted in 1.89 (~August 2022). As a reminder: + - old ImageButton() before 1.89 used ImTextureId as item id (created issue with e.g. multiple buttons in same scope, transient texture id values, opaque computation of ID) + - new ImageButton() since 1.89 requires an explicit 'const char* str_id' + - old ImageButton() before 1.89 had frame_padding' override argument. + - new ImageButton() since 1.89 always use style.FramePadding, which you can freely override with PushStyleVar()/PopStyleVar(). - 2024/07/25 (1.91.0) - obsoleted GetContentRegionMax(), GetWindowContentRegionMin() and GetWindowContentRegionMax(). (see #7838 on GitHub for more info) you should never need those functions. you can do everything with GetCursorScreenPos() and GetContentRegionAvail() in a more simple way. - instead of: GetWindowContentRegionMax().x - GetCursorPos().x diff --git a/imgui.h b/imgui.h index 2825cc60ccca..1aea4c8110c8 100644 --- a/imgui.h +++ b/imgui.h @@ -3547,13 +3547,13 @@ namespace ImGui // OBSOLETED in 1.89.4 (from March 2023) static inline void PushAllowKeyboardFocus(bool tab_stop) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); } static inline void PopAllowKeyboardFocus() { PopItemFlag(); } - // OBSOLETED in 1.89 (from August 2022) - IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Use new ImageButton() signature (explicit item id, regular FramePadding) // OBSOLETED in 1.87 (from February 2022 but more formally obsoleted April 2024) IMGUI_API ImGuiKey GetKeyIndex(ImGuiKey key); // Map ImGuiKey_* values into legacy native key index. == io.KeyMap[key]. When using a 1.87+ backend using io.AddKeyEvent(), calling GetKeyIndex() with ANY ImGuiKey_XXXX values will return the same value! //static inline ImGuiKey GetKeyIndex(ImGuiKey key) { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END); return key; } // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE) + //-- OBSOLETED in 1.89 (from August 2022) + //IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // --> Use new ImageButton() signature (explicit item id, regular FramePadding). Refer to code in 1.91 if you want to grab a copy of this version. //-- OBSOLETED in 1.88 (from May 2022) //static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value. //static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2d96ed909441..5b7898edd694 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1108,28 +1108,24 @@ bool ImGui::ImageButton(const char* str_id, ImTextureID user_texture_id, const I #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // Legacy API obsoleted in 1.89. Two differences with new ImageButton() -// - new ImageButton() requires an explicit 'const char* str_id' Old ImageButton() used opaque imTextureId (created issue with: multiple buttons with same image, transient texture id values, opaque computation of ID) -// - new ImageButton() always use style.FramePadding Old ImageButton() had an override argument. -// If you need to change padding with new ImageButton() you can use PushStyleVar(ImGuiStyleVar_FramePadding, value), consistent with other Button functions. +// - old ImageButton() used ImTextureId as item id (created issue with multiple buttons with same image, transient texture id values, opaque computation of ID) +// - new ImageButton() requires an explicit 'const char* str_id' +// - old ImageButton() had frame_padding' override argument. +// - new ImageButton() always use style.FramePadding. +/* bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col) { - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return false; - // Default to using texture ID as ID. User can still push string/integer prefixes. PushID((void*)(intptr_t)user_texture_id); - const ImGuiID id = window->GetID("#image"); - PopID(); - if (frame_padding >= 0) PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2((float)frame_padding, (float)frame_padding)); - bool ret = ImageButtonEx(id, user_texture_id, size, uv0, uv1, bg_col, tint_col); + bool ret = ImageButton("", user_texture_id, size, uv0, uv1, bg_col, tint_col); if (frame_padding >= 0) PopStyleVar(); + PopID(); return ret; } +*/ #endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS bool ImGui::Checkbox(const char* label, bool* v) From d15da2c47d98a8bf5a09219ea6d310710972f8bc Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 22 Aug 2024 20:27:50 +0200 Subject: [PATCH 072/548] Backends: GLFW: undo accidentally not committing use of Platform_SetClipboardTextFn as I was testing the legacy path (amend 214977e). --- backends/imgui_impl_glfw.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 66b71c5e7c11..ee230ee1b046 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -180,16 +180,6 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() } // Functions -static const char* ImGui_ImplGlfw_GetClipboardText(void*) -{ - return glfwGetClipboardString(NULL); -} - -static void ImGui_ImplGlfw_SetClipboardText(void*, const char* text) -{ - glfwSetClipboardString(NULL, text); -} - static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key) { switch (key) @@ -591,8 +581,8 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw bd->Time = 0.0; ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; - io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; + platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(NULL, text); }; + platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) { return glfwGetClipboardString(NULL); }; #ifdef __EMSCRIPTEN__ platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplGlfw_EmscriptenOpenURL(url); return true; }; #endif From d474ed7f78c505308a54c70dd51c24c6965f605f Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 23 Aug 2024 12:47:40 +0200 Subject: [PATCH 073/548] InputText: Internals: store Scroll.y as it seems sane to (internally) expose it in a way that's agnostic of our use of a child window (#7913, #383) --- imgui.h | 2 +- imgui_internal.h | 2 +- imgui_widgets.cpp | 20 ++++++++++++-------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/imgui.h b/imgui.h index 1aea4c8110c8..028adafb8285 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.1 WIP" -#define IMGUI_VERSION_NUM 19103 +#define IMGUI_VERSION_NUM 19104 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 6bd2aa457810..537f513293ce 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1121,7 +1121,7 @@ struct IMGUI_API ImGuiInputTextState ImVector InitialTextA; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered) bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument) int BufCapacityA; // end-user buffer capacity - float ScrollX; // horizontal scrolling/offset + ImVec2 Scroll; // horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y) ImStb::STB_TexteditState Stb; // state for stb_textedit.h float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5b7898edd694..63c4b21cdbf8 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4407,7 +4407,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } else { - state->ScrollX = 0.0f; + state->Scroll = ImVec2(0.0f, 0.0f); stb_textedit_initialize_state(&state->Stb, !is_multiline); } @@ -4459,6 +4459,10 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // FIXME: May be a problem to always steal Alt on OSX, would ideally still allow an uninterrupted Alt down-up to toggle menu if (is_osx) SetKeyOwner(ImGuiMod_Alt, id); + + // Expose scroll in a manner that is agnostic to us using a child window + if (is_multiline) + state->Scroll.y = draw_window->Scroll.y; } // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function) @@ -4522,7 +4526,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ g.ActiveIdAllowOverlap = !io.MouseDown[0]; // Edit in progress - const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX; + const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->Scroll.x; const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f)); if (select_all) @@ -5078,14 +5082,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ { const float scroll_increment_x = inner_size.x * 0.25f; const float visible_width = inner_size.x - style.FramePadding.x; - if (cursor_offset.x < state->ScrollX) - state->ScrollX = IM_TRUNC(ImMax(0.0f, cursor_offset.x - scroll_increment_x)); - else if (cursor_offset.x - visible_width >= state->ScrollX) - state->ScrollX = IM_TRUNC(cursor_offset.x - visible_width + scroll_increment_x); + if (cursor_offset.x < state->Scroll.x) + state->Scroll.x = IM_TRUNC(ImMax(0.0f, cursor_offset.x - scroll_increment_x)); + else if (cursor_offset.x - visible_width >= state->Scroll.x) + state->Scroll.x = IM_TRUNC(cursor_offset.x - visible_width + scroll_increment_x); } else { - state->ScrollX = 0.0f; + state->Scroll.y = 0.0f; } // Vertical scroll @@ -5106,7 +5110,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } // Draw selection - const ImVec2 draw_scroll = ImVec2(state->ScrollX, 0.0f); + const ImVec2 draw_scroll = ImVec2(state->Scroll.x, 0.0f); if (render_selection) { const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end); From ce484301c0f9c1aeedb5427b186ab7dd2dc4b9a3 Mon Sep 17 00:00:00 2001 From: Mark Jansen Date: Fri, 23 Aug 2024 14:12:18 +0200 Subject: [PATCH 074/548] CI: Add manual trigger for 'workflow_run' builds (#7865) --- .github/workflows/build.yml | 1 + .github/workflows/manual.yml | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 .github/workflows/manual.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b223d22619dd..4320a2025deb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,7 @@ on: # "scheduled" workflow, while maintaining ability to perform local CI builds. workflows: - scheduled + - manual branches: - master - docking diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml new file mode 100644 index 000000000000..3c472f1bf78d --- /dev/null +++ b/.github/workflows/manual.yml @@ -0,0 +1,12 @@ +# +# This is a dummy workflow used to trigger full builds manually. +# +name: manual + +on: workflow_dispatch + +jobs: + manual: + runs-on: ubuntu-latest + steps: + - run: exit 0 From 438f9e1a3e7f7d63d0d20b50cc199e5f714895f2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 23 Aug 2024 14:14:07 +0200 Subject: [PATCH 075/548] InputText: amend d474ed7 for static analysis. (#7913) --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 63c4b21cdbf8..c55e955001d9 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4461,7 +4461,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ SetKeyOwner(ImGuiMod_Alt, id); // Expose scroll in a manner that is agnostic to us using a child window - if (is_multiline) + if (is_multiline && state != NULL) state->Scroll.y = draw_window->Scroll.y; } From 088e6fc04715dde2969cd584073c5150521b148a Mon Sep 17 00:00:00 2001 From: BillKek <51540758+BillKek@users.noreply.github.com> Date: Thu, 22 Jun 2023 17:44:00 +0300 Subject: [PATCH 076/548] Examples: Win32+OpenGL3: added batch. file for msys2/mingw build. (#6544) --- examples/example_win32_opengl3/build_mingw.bat | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 examples/example_win32_opengl3/build_mingw.bat diff --git a/examples/example_win32_opengl3/build_mingw.bat b/examples/example_win32_opengl3/build_mingw.bat new file mode 100644 index 000000000000..7672185858d2 --- /dev/null +++ b/examples/example_win32_opengl3/build_mingw.bat @@ -0,0 +1,8 @@ +@REM Build for MINGW64 or 32 from MSYS2. +@set OUT_DIR=Debug +@set OUT_EXE=example_win32_opengl3 +@set INCLUDES=-I../.. -I../../backends +@set SOURCES=main.cpp ../../backends/imgui_impl_opengl3.cpp ../../backends/imgui_impl_win32.cpp ../../imgui*.cpp +@set LIBS=-lopengl32 -lgdi32 -ldwmapi +mkdir %OUT_DIR% +g++ -DUNICODE %INCLUDES% %SOURCES% -o %OUT_DIR%/%OUT_EXE%.exe --static -mwindows %LIBS% %LIBS% From 1e939fcc32af81c755c31edb9db3357f9fb50d19 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 23 Aug 2024 14:55:27 +0200 Subject: [PATCH 077/548] Tooltips, Drag and Drop: made it possible to override BeginTooltip() position while inside a drag and drop source or target. (#6973) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 181cccfc1855..692c48f1a56d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -81,6 +81,8 @@ Other changes: - InputText: allow callback to update buffer while in read-only mode. (imgui_club/#46) - InputText: fixed an issue programmatically refocusing a multi-line input which was just active. (#4761, #7870) - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) +- Tooltips, Drag and Drop: made it possible to override BeginTooltip() position while inside + a drag and drop source or target: a SetNextWindowPos() call won't be overriden. (#6973) - Style: added PushStyleVarX(), PushStyleVarY() helpers to modify only one component of a ImVec2 var. - Fonts: made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not diff --git a/imgui.cpp b/imgui.cpp index 457fc2031c86..17f19bc2208a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11096,7 +11096,8 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext // See FindBestWindowPosForPopup() for positionning logic of other tooltips (not drag and drop ones). //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding; ImVec2 tooltip_pos = g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET * g.Style.MouseCursorScale; - SetNextWindowPos(tooltip_pos); + if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0) + SetNextWindowPos(tooltip_pos); SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f); //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This would be nice but e.g ColorButton with checkboard has issue with transparent colors :( tooltip_flags |= ImGuiTooltipFlags_OverridePrevious; @@ -15937,7 +15938,7 @@ static void ShowDebugLogFlag(const char* name, ImGuiDebugLogFlags flags) void ImGui::ShowDebugLogWindow(bool* p_open) { ImGuiContext& g = *GImGui; - if (!(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)) + if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0) SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 12.0f), ImGuiCond_FirstUseEver); if (!Begin("Dear ImGui Debug Log", p_open) || GetCurrentWindow()->BeginCount > 1) { @@ -16254,7 +16255,7 @@ static int StackToolFormatLevelInfo(ImGuiIDStackTool* tool, int n, bool format_f void ImGui::ShowIDStackToolWindow(bool* p_open) { ImGuiContext& g = *GImGui; - if (!(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)) + if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0) SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver); if (!Begin("Dear ImGui ID Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1) { From 0b9adc2c799f5ed6b33fefd7cdb3c68d10751a29 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 23 Aug 2024 15:24:22 +0200 Subject: [PATCH 078/548] BeginChild: (BREAKING) renamed ImGuiChildFlags_Border to ImGuiChildFlags_Borders. Amend 7713c2925 + renamed similar argument in other functions. --- docs/CHANGELOG.txt | 4 ++++ imgui.cpp | 18 ++++++++++-------- imgui.h | 19 ++++++++++++------- imgui_demo.cpp | 36 ++++++++++++++++++------------------ imgui_internal.h | 2 +- imgui_tables.cpp | 4 ++-- imgui_widgets.cpp | 4 ++-- 7 files changed, 49 insertions(+), 38 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 692c48f1a56d..a05f91b8815e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,8 @@ HOW TO UPDATE? Breaking changes: +- BeginChild(): renamed ImGuiChildFlags_Border to ImGuiChildFlags_Borders for consistency. [@cfillion] + Kept inline redirection flag (will obsolete). - IO: moved clipboard functions from ImGuiIO to ImGuiPlatformIO: - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn @@ -845,6 +847,7 @@ Breaking changes: Before: BeginChild("Name", size, false) After: BeginChild("Name", size) or BeginChild("Name", 0) or BeginChild("Name", size, ImGuiChildFlags_None) Existing code will still work as 'ImGuiChildFlags_Border == true', but you are encouraged to update call sites. + **AMEND FROM THE FUTURE: from 1.91.1, 'ImGuiChildFlags_Border' is called 'ImGuiChildFlags_Borders'** - BeginChild(): Added child-flag ImGuiChildFlags_AlwaysUseWindowPadding as a replacement for the window-flag ImGuiWindowFlags_AlwaysUseWindowPadding: the feature only ever made sense for use with BeginChild() anyhow, passing it to Begin() had no effect. Now that we accept @@ -894,6 +897,7 @@ Other changes: child windows from the bottom/right border (toward layout direction). Resized child windows settings are saved and persistent in .ini file. (#1710) - BeginChild(): Added ImGuiChildFlags_Border as a replacement for 'bool border = true' parameter. + **AMEND FROM THE FUTURE: from 1.91.1, 'ImGuiChildFlags_Border' is called 'ImGuiChildFlags_Borders'** - BeginChild(): Added ImGuiChildFlags_AutoResizeX and ImGuiChildFlags_AutoResizeY to auto-resize on one axis, while generally providing a size on the other axis. (#1666, #1395, #1496, #1710) e.g. BeginChild("name", {-FLT_MIN, 0.0f}, ImGuiChildFlags_AutoResizeY); diff --git a/imgui.cpp b/imgui.cpp index 17f19bc2208a..fbf067879cec 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -430,6 +430,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. + - 2024/08/23 (1.91.1) - renamed ImGuiChildFlags_Border to ImGuiChildFlags_Borders for consistency. kept inline redirection flag. - 2024/08/22 (1.91.1) - moved some functions from ImGuiIO to ImGuiPlatformIO structure: - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn + changed 'void* user_data' to 'ImGuiContext* ctx'. Pull your user data from platform_io.ClipboardUserData. - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn + same as above line. @@ -514,6 +515,7 @@ CODE - new: BeginChild("Name", size, ImGuiChildFlags_Border) - old: BeginChild("Name", size, false) - new: BeginChild("Name", size) or BeginChild("Name", 0) or BeginChild("Name", size, ImGuiChildFlags_None) + **AMEND FROM THE FUTURE: from 1.91.1, 'ImGuiChildFlags_Border' is called 'ImGuiChildFlags_Borders'** - 2023/11/02 (1.90.0) - BeginChild: added child-flag ImGuiChildFlags_AlwaysUseWindowPadding as a replacement for the window-flag ImGuiWindowFlags_AlwaysUseWindowPadding: the feature only ever made sense for BeginChild() anyhow. - old: BeginChild("Name", size, 0, ImGuiWindowFlags_AlwaysUseWindowPadding); - new: BeginChild("Name", size, ImGuiChildFlags_AlwaysUseWindowPadding, 0); @@ -3637,13 +3639,13 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con } // Render a rectangle shaped with optional rounding and borders -void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding) +void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders, float rounding) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding); const float border_size = g.Style.FrameBorderSize; - if (border && border_size > 0.0f) + if (borders && border_size > 0.0f) { window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size); window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size); @@ -5623,7 +5625,7 @@ ImVec2 ImGui::GetItemRectSize() } // Prior to v1.90 2023/10/16, the BeginChild() function took a 'bool border = false' parameter instead of 'ImGuiChildFlags child_flags = 0'. -// ImGuiChildFlags_Border is defined as always == 1 in order to allow old code passing 'true'. Read comments in imgui.h for details! +// ImGuiChildFlags_Borders is defined as always == 1 in order to allow old code passing 'true'. Read comments in imgui.h for details! bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) { ImGuiID id = GetCurrentWindow()->GetID(str_id); @@ -5642,7 +5644,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I IM_ASSERT(id != 0); // Sanity check as it is likely that some user will accidentally pass ImGuiWindowFlags into the ImGuiChildFlags argument. - const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ = ImGuiChildFlags_Border | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_FrameStyle | ImGuiChildFlags_NavFlattened; + const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ = ImGuiChildFlags_Borders | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_FrameStyle | ImGuiChildFlags_NavFlattened; IM_UNUSED(ImGuiChildFlags_SupportedMask_); IM_ASSERT((child_flags & ~ImGuiChildFlags_SupportedMask_) == 0 && "Illegal ImGuiChildFlags value. Did you pass ImGuiWindowFlags values instead of ImGuiChildFlags?"); IM_ASSERT((window_flags & ImGuiWindowFlags_AlwaysAutoResize) == 0 && "Cannot specify ImGuiWindowFlags_AlwaysAutoResize for BeginChild(). Use ImGuiChildFlags_AlwaysAutoResize!"); @@ -5677,7 +5679,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I PushStyleVar(ImGuiStyleVar_ChildRounding, g.Style.FrameRounding); PushStyleVar(ImGuiStyleVar_ChildBorderSize, g.Style.FrameBorderSize); PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.FramePadding); - child_flags |= ImGuiChildFlags_Border | ImGuiChildFlags_AlwaysUseWindowPadding; + child_flags |= ImGuiChildFlags_Borders | ImGuiChildFlags_AlwaysUseWindowPadding; window_flags |= ImGuiWindowFlags_NoMove; } @@ -5707,7 +5709,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I // Set style const float backup_border_size = g.Style.ChildBorderSize; - if ((child_flags & ImGuiChildFlags_Border) == 0) + if ((child_flags & ImGuiChildFlags_Borders) == 0) g.Style.ChildBorderSize = 0.0f; // Begin into window @@ -15804,7 +15806,7 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); if (flags & ImGuiWindowFlags_ChildWindow) BulletText("ChildFlags: 0x%08X (%s%s%s%s..)", window->ChildFlags, - (window->ChildFlags & ImGuiChildFlags_Border) ? "Border " : "", + (window->ChildFlags & ImGuiChildFlags_Borders) ? "Borders " : "", (window->ChildFlags & ImGuiChildFlags_ResizeX) ? "ResizeX " : "", (window->ChildFlags & ImGuiChildFlags_ResizeY) ? "ResizeY " : "", (window->ChildFlags & ImGuiChildFlags_NavFlattened) ? "NavFlattened " : ""); @@ -15983,7 +15985,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open) EndPopup(); } - BeginChild("##log", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Border, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); + BeginChild("##log", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Borders, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); const ImGuiDebugLogFlags backup_log_flags = g.DebugLogFlags; g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper; diff --git a/imgui.h b/imgui.h index 028adafb8285..cc89955d0a43 100644 --- a/imgui.h +++ b/imgui.h @@ -369,10 +369,10 @@ namespace ImGui // Child Windows // - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child. // - Before 1.90 (November 2023), the "ImGuiChildFlags child_flags = 0" parameter was "bool border = false". - // This API is backward compatible with old code, as we guarantee that ImGuiChildFlags_Border == true. + // This API is backward compatible with old code, as we guarantee that ImGuiChildFlags_Borders == true. // Consider updating your old code: // BeginChild("Name", size, false) -> Begin("Name", size, 0); or Begin("Name", size, ImGuiChildFlags_None); - // BeginChild("Name", size, true) -> Begin("Name", size, ImGuiChildFlags_Border); + // BeginChild("Name", size, true) -> Begin("Name", size, ImGuiChildFlags_Borders); // - Manual sizing (each axis can use a different setting e.g. ImVec2(0.0f, 400.0f)): // == 0.0f: use remaining parent window size for this axis. // > 0.0f: use specified size for this axis. @@ -843,7 +843,7 @@ namespace ImGui // Legacy Columns API (prefer using Tables!) // - You can also use SameLine(pos_x) to mimic simplified columns. - IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); + IMGUI_API void Columns(int count = 1, const char* id = NULL, bool borders = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API int GetColumnIndex(); // get current column index IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column @@ -1098,7 +1098,7 @@ enum ImGuiWindowFlags_ }; // Flags for ImGui::BeginChild() -// (Legacy: bit 0 must always correspond to ImGuiChildFlags_Border to be backward compatible with old API using 'bool border = false'. +// (Legacy: bit 0 must always correspond to ImGuiChildFlags_Borders to be backward compatible with old API using 'bool border = false'. // About using AutoResizeX/AutoResizeY flags: // - May be combined with SetNextWindowSizeConstraints() to set a min/max size for each axis (see "Demo->Child->Auto-resize with Constraints"). // - Size measurement for a given axis is only performed when the child window is within visible boundaries, or is just appearing. @@ -1109,7 +1109,7 @@ enum ImGuiWindowFlags_ enum ImGuiChildFlags_ { ImGuiChildFlags_None = 0, - ImGuiChildFlags_Border = 1 << 0, // Show an outer border and enable WindowPadding. (IMPORTANT: this is always == 1 == true for legacy reason) + ImGuiChildFlags_Borders = 1 << 0, // Show an outer border and enable WindowPadding. (IMPORTANT: this is always == 1 == true for legacy reason) ImGuiChildFlags_AlwaysUseWindowPadding = 1 << 1, // Pad with style.WindowPadding even if no border are drawn (no padding by default for non-bordered child windows because it makes more sense) ImGuiChildFlags_ResizeX = 1 << 2, // Allow resize from right border (layout direction). Enable .ini saving (unless ImGuiWindowFlags_NoSavedSettings passed to window flags) ImGuiChildFlags_ResizeY = 1 << 3, // Allow resize from bottom border (layout direction). " @@ -1118,6 +1118,11 @@ enum ImGuiChildFlags_ ImGuiChildFlags_AlwaysAutoResize = 1 << 6, // Combined with AutoResizeX/AutoResizeY. Always measure size even when child is hidden, always return true, always disable clipping optimization! NOT RECOMMENDED. ImGuiChildFlags_FrameStyle = 1 << 7, // Style the child window like a framed item: use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding. ImGuiChildFlags_NavFlattened = 1 << 8, // [BETA] Share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. + + // Obsolete names +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + ImGuiChildFlags_Border = ImGuiChildFlags_Borders, // Renamed in 1.91.1 (August 2024) for consistency. +#endif }; // Flags for ImGui::PushItemFlag() @@ -3537,8 +3542,8 @@ namespace ImGui // OBSOLETED in 1.90.0 (from September 2023) static inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags window_flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, window_flags); } static inline void EndChildFrame() { EndChild(); } - //static inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags){ return BeginChild(str_id, size_arg, border ? ImGuiChildFlags_Border : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Border - //static inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, border ? ImGuiChildFlags_Border : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Border + //static inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags){ return BeginChild(str_id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders + //static inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders static inline void ShowStackToolWindow(bool* p_open = NULL) { ShowIDStackToolWindow(p_open); } IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1); IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ddc8f9b2a5d2..a729e45b223f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2762,7 +2762,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) static bool embed_all_inside_a_child_window = false; ImGui::Checkbox("Embed everything inside a child window for testing _RootWindow flag.", &embed_all_inside_a_child_window); if (embed_all_inside_a_child_window) - ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), ImGuiChildFlags_Border); + ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), ImGuiChildFlags_Borders); // Testing IsWindowFocused() function with its various flags. ImGui::BulletText( @@ -2810,7 +2810,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow), ImGui::IsWindowHovered(ImGuiHoveredFlags_Stationary)); - ImGui::BeginChild("child", ImVec2(0, 50), ImGuiChildFlags_Border); + ImGui::BeginChild("child", ImVec2(0, 50), ImGuiChildFlags_Borders); ImGui::Text("This is another child window for testing the _ChildWindows flag."); ImGui::EndChild(); if (embed_all_inside_a_child_window) @@ -3375,7 +3375,7 @@ static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data) ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear); ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d); // Cannot use ImGuiMultiSelectFlags_BoxSelect1d as checkboxes are varying width. - if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY)) + if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY)) { ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, -1, IM_ARRAYSIZE(items)); ImGuiSelectionExternalStorage storage_wrapper; @@ -3881,7 +3881,7 @@ static void ShowDemoWindowLayout() if (!disable_menu) window_flags |= ImGuiWindowFlags_MenuBar; ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f); - ImGui::BeginChild("ChildR", ImVec2(0, 260), ImGuiChildFlags_Border, window_flags); + ImGui::BeginChild("ChildR", ImVec2(0, 260), ImGuiChildFlags_Borders, window_flags); if (!disable_menu && ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("Menu")) @@ -3911,7 +3911,7 @@ static void ShowDemoWindowLayout() { HelpMarker("Drag bottom border to resize. Double-click bottom border to auto-fit to vertical contents."); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg)); - if (ImGui::BeginChild("ResizableChild", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY)) + if (ImGui::BeginChild("ResizableChild", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY)) for (int n = 0; n < 10; n++) ImGui::Text("Line %04d", n); ImGui::PopStyleColor(); @@ -3929,7 +3929,7 @@ static void ShowDemoWindowLayout() ImGui::DragInt("Max Height (in Lines)", &max_height_in_lines, 0.2f); ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 1), ImVec2(FLT_MAX, ImGui::GetTextLineHeightWithSpacing() * max_height_in_lines)); - if (ImGui::BeginChild("ConstrainedChild", ImVec2(-FLT_MIN, 0.0f), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) + if (ImGui::BeginChild("ConstrainedChild", ImVec2(-FLT_MIN, 0.0f), ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeY)) for (int n = 0; n < draw_lines; n++) ImGui::Text("Line %04d", n); ImGui::EndChild(); @@ -3947,11 +3947,11 @@ static void ShowDemoWindowLayout() { static int offset_x = 0; static bool override_bg_color = true; - static ImGuiChildFlags child_flags = ImGuiChildFlags_Border | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY; + static ImGuiChildFlags child_flags = ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY; ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000); ImGui::Checkbox("Override ChildBg color", &override_bg_color); - ImGui::CheckboxFlags("ImGuiChildFlags_Border", &child_flags, ImGuiChildFlags_Border); + ImGui::CheckboxFlags("ImGuiChildFlags_Borders", &child_flags, ImGuiChildFlags_Borders); ImGui::CheckboxFlags("ImGuiChildFlags_AlwaysUseWindowPadding", &child_flags, ImGuiChildFlags_AlwaysUseWindowPadding); ImGui::CheckboxFlags("ImGuiChildFlags_ResizeX", &child_flags, ImGuiChildFlags_ResizeX); ImGui::CheckboxFlags("ImGuiChildFlags_ResizeY", &child_flags, ImGuiChildFlags_ResizeY); @@ -4361,7 +4361,7 @@ static void ShowDemoWindowLayout() const ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0; const ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i); - const bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), ImGuiChildFlags_Border, child_flags); + const bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), ImGuiChildFlags_Borders, child_flags); if (ImGui::BeginMenuBar()) { ImGui::TextUnformatted("abc"); @@ -4408,7 +4408,7 @@ static void ShowDemoWindowLayout() float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f; ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0); ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i); - bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(-100, child_height), ImGuiChildFlags_Border, child_flags); + bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(-100, child_height), ImGuiChildFlags_Borders, child_flags); if (scroll_to_off) ImGui::SetScrollX(scroll_to_off_px); if (scroll_to_pos) @@ -4450,7 +4450,7 @@ static void ShowDemoWindowLayout() ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f)); ImVec2 scrolling_child_size = ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30); - ImGui::BeginChild("scrolling", scrolling_child_size, ImGuiChildFlags_Border, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::BeginChild("scrolling", scrolling_child_size, ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar); for (int line = 0; line < lines; line++) { // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine() @@ -4596,7 +4596,7 @@ static void ShowDemoWindowLayout() } if (show_child) { - ImGui::BeginChild("child", ImVec2(0, 0), ImGuiChildFlags_Border); + ImGui::BeginChild("child", ImVec2(0, 0), ImGuiChildFlags_Borders); ImGui::EndChild(); } ImGui::End(); @@ -7942,7 +7942,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) "Right-click to open edit options menu."); ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 10), ImVec2(FLT_MAX, FLT_MAX)); - ImGui::BeginChild("##colors", ImVec2(0, 0), ImGuiChildFlags_Border | ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); + ImGui::BeginChild("##colors", ImVec2(0, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); ImGui::PushItemWidth(ImGui::GetFontSize() * -12); for (int i = 0; i < ImGuiCol_COUNT; i++) { @@ -8176,7 +8176,7 @@ static void ShowExampleMenuFile() { static bool enabled = true; ImGui::MenuItem("Enabled", "", &enabled); - ImGui::BeginChild("child", ImVec2(0, 60), ImGuiChildFlags_Border); + ImGui::BeginChild("child", ImVec2(0, 60), ImGuiChildFlags_Borders); for (int i = 0; i < 10; i++) ImGui::Text("Scrolling Text %d", i); ImGui::EndChild(); @@ -8773,7 +8773,7 @@ static void ShowExampleAppLayout(bool* p_open) // Left static int selected = 0; { - ImGui::BeginChild("left pane", ImVec2(150, 0), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeX); + ImGui::BeginChild("left pane", ImVec2(150, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeX); for (int i = 0; i < 100; i++) { // FIXME: Good candidate to use ImGuiSelectableFlags_SelectOnNav @@ -8834,7 +8834,7 @@ struct ExampleAppPropertyEditor { // Left side: draw tree // - Currently using a table to benefit from RowBg feature - if (ImGui::BeginChild("##tree", ImVec2(300, 0), ImGuiChildFlags_ResizeX | ImGuiChildFlags_Border | ImGuiChildFlags_NavFlattened)) + if (ImGui::BeginChild("##tree", ImVec2(300, 0), ImGuiChildFlags_ResizeX | ImGuiChildFlags_Borders | ImGuiChildFlags_NavFlattened)) { ImGui::SetNextItemWidth(-FLT_MIN); ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip); @@ -9448,7 +9448,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) // To use a child window instead we could use, e.g: // ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); // Disable padding // ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(50, 50, 50, 255)); // Set a background color - // ImGui::BeginChild("canvas", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Border, ImGuiWindowFlags_NoMove); + // ImGui::BeginChild("canvas", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove); // ImGui::PopStyleColor(); // ImGui::PopStyleVar(); // [...] @@ -10100,7 +10100,7 @@ struct ExampleAssetsBrowser ImGuiIO& io = ImGui::GetIO(); ImGui::SetNextWindowContentSize(ImVec2(0.0f, LayoutOuterPadding + LayoutLineCount * (LayoutItemSize.x + LayoutItemSpacing))); - if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Border, ImGuiWindowFlags_NoMove)) + if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove)) { ImDrawList* draw_list = ImGui::GetWindowDrawList(); diff --git a/imgui_internal.h b/imgui_internal.h index 537f513293ce..884c85a190e0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3508,7 +3508,7 @@ namespace ImGui IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known); - IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); + IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0); IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_None); // Navigation highlight diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 92c62949efe3..3d757fd98c00 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -4428,12 +4428,12 @@ void ImGui::EndColumns() NavUpdateCurrentWindowIsScrollPushableX(); } -void ImGui::Columns(int columns_count, const char* id, bool border) +void ImGui::Columns(int columns_count, const char* id, bool borders) { ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); - ImGuiOldColumnFlags flags = (border ? 0 : ImGuiOldColumnFlags_NoBorder); + ImGuiOldColumnFlags flags = (borders ? 0 : ImGuiOldColumnFlags_NoBorder); //flags |= ImGuiOldColumnFlags_NoPreserveWidths; // NB: Legacy behavior ImGuiOldColumns* columns = window->DC.CurrentColumns; if (columns != NULL && columns->Count == columns_count && columns->Flags == flags) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c55e955001d9..ce80cfd872f1 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4312,7 +4312,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding); PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize); PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); // Ensure no clip rect so mouse hover can reach FramePadding edges - bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), ImGuiChildFlags_Border, ImGuiWindowFlags_NoMove); + bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove); g.NavActivateId = backup_activate_id; PopStyleVar(3); PopStyleColor(); @@ -5242,7 +5242,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state) Text("CurLenW: %d, CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenW, state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end); Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x); Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point); - if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 10), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY)) // Visualize undo state + if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 10), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY)) // Visualize undo state { PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); for (int n = 0; n < IMSTB_TEXTEDIT_UNDOSTATECOUNT; n++) From a131c3e6111952d0e8fd898763fe7cd3b2172ee3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 23 Aug 2024 18:24:44 +0200 Subject: [PATCH 079/548] Tables: revert a34071876 extending outer bottom/right border by 1, this is not the right solution. (#6765, #3752) --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a05f91b8815e..e4584d6867e9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -80,6 +80,8 @@ Other changes: 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) +- Tables: revert 1.90 extension of bottom-most and right-most outer border offset by one. + This is not the right solution. (#6765, #3752) - InputText: allow callback to update buffer while in read-only mode. (imgui_club/#46) - InputText: fixed an issue programmatically refocusing a multi-line input which was just active. (#4761, #7870) - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 3d757fd98c00..92ab79a7fa00 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -2743,7 +2743,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table) const ImU32 outer_col = table->BorderColorStrong; if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter) { - inner_drawlist->AddRect(outer_border.Min, outer_border.Max + ImVec2(1, 1), outer_col, 0.0f, 0, border_size); + inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, 0, border_size); } else if (table->Flags & ImGuiTableFlags_BordersOuterV) { From 864a2bf6b824f9c1329d8493386208d4b0fd311c Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 23 Aug 2024 19:12:54 +0200 Subject: [PATCH 080/548] Tables: another attempt at making contents not overlap the bottom and right border in a scrolling table. (#6765, #3752, #7428) --- docs/CHANGELOG.txt | 5 +++-- imgui_tables.cpp | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e4584d6867e9..d19e8f39e063 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -80,8 +80,9 @@ Other changes: 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) -- Tables: revert 1.90 extension of bottom-most and right-most outer border offset by one. - This is not the right solution. (#6765, #3752) +- Tables: fixes/revert a 1.90 change were outer border would be moved bottom and right + by an extra pixel + rework the change so that contents doesn't overlap the bottom and + right border in a scrolling table. (#6765, #3752, #7428) - InputText: allow callback to update buffer while in read-only mode. (imgui_club/#46) - InputText: fixed an issue programmatically refocusing a multi-line input which was just active. (#4761, #7870) - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 92ab79a7fa00..fd7e6da5722c 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -460,16 +460,27 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size; inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); - // Make left and top borders not overlap our contents by offsetting HostClipRect (#6765) + // Make borders not overlap our contents by offsetting HostClipRect (#6765, #7428, #3752) // (we normally shouldn't alter HostClipRect as we rely on TableMergeDrawChannels() expanding non-clipped column toward the // limits of that rectangle, in order for ImDrawListSplitter::Merge() to merge the draw commands. However since the overlap // problem only affect scrolling tables in this case we can get away with doing it without extra cost). if (inner_window != outer_window) { + // FIXME: Because inner_window's Scrollbar doesn't know about border size, since it's not encoded in window->WindowBorderSize, + // it already overlaps it and doesn't need an extra offset. Ideally we should be able to pass custom border size with + // different x/y values to BeginChild(). if (flags & ImGuiTableFlags_BordersOuterV) + { table->HostClipRect.Min.x = ImMin(table->HostClipRect.Min.x + TABLE_BORDER_SIZE, table->HostClipRect.Max.x); + if (inner_window->DecoOuterSizeX2 == 0.0f) + table->HostClipRect.Max.x = ImMax(table->HostClipRect.Max.x - TABLE_BORDER_SIZE, table->HostClipRect.Min.x); + } if (flags & ImGuiTableFlags_BordersOuterH) + { table->HostClipRect.Min.y = ImMin(table->HostClipRect.Min.y + TABLE_BORDER_SIZE, table->HostClipRect.Max.y); + if (inner_window->DecoOuterSizeY2 == 0.0f) + table->HostClipRect.Max.y = ImMax(table->HostClipRect.Max.y - TABLE_BORDER_SIZE, table->HostClipRect.Min.y); + } } // Padding and Spacing @@ -497,7 +508,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG table->InnerClipRect = (inner_window == outer_window) ? table->WorkRect : inner_window->ClipRect; table->InnerClipRect.ClipWith(table->WorkRect); // We need this to honor inner_width table->InnerClipRect.ClipWithFull(table->HostClipRect); - table->InnerClipRect.Max.y = (flags & ImGuiTableFlags_NoHostExtendY) ? ImMin(table->InnerClipRect.Max.y, inner_window->WorkRect.Max.y) : inner_window->ClipRect.Max.y; + table->InnerClipRect.Max.y = (flags & ImGuiTableFlags_NoHostExtendY) ? ImMin(table->InnerClipRect.Max.y, inner_window->WorkRect.Max.y) : table->HostClipRect.Max.y; table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow() @@ -1249,7 +1260,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (table->Flags & ImGuiTableFlags_NoClip) table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); else - inner_window->DrawList->PushClipRect(inner_window->ClipRect.Min, inner_window->ClipRect.Max, false); + inner_window->DrawList->PushClipRect(inner_window->InnerClipRect.Min, inner_window->InnerClipRect.Max, false); } // Process hit-testing on resizing borders. Actual size change will be applied in EndTable() From 1d88609043fd7a25df7f5f4acd7aa3cc4aaf8033 Mon Sep 17 00:00:00 2001 From: tanoxyz <36295026+tanoxyz@users.noreply.github.com> Date: Sun, 1 Sep 2024 11:40:48 +0200 Subject: [PATCH 081/548] Changed call from cosf to ImCos (#7939) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index fbf067879cec..2b4099966b13 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14757,7 +14757,7 @@ void ImGui::UpdateDebugToolFlashStyleColor() ImGuiContext& g = *GImGui; if (g.DebugFlashStyleColorTime <= 0.0f) return; - ColorConvertHSVtoRGB(cosf(g.DebugFlashStyleColorTime * 6.0f) * 0.5f + 0.5f, 0.5f, 0.5f, g.Style.Colors[g.DebugFlashStyleColorIdx].x, g.Style.Colors[g.DebugFlashStyleColorIdx].y, g.Style.Colors[g.DebugFlashStyleColorIdx].z); + ColorConvertHSVtoRGB(ImCos(g.DebugFlashStyleColorTime * 6.0f) * 0.5f + 0.5f, 0.5f, 0.5f, g.Style.Colors[g.DebugFlashStyleColorIdx].x, g.Style.Colors[g.DebugFlashStyleColorIdx].y, g.Style.Colors[g.DebugFlashStyleColorIdx].z); g.Style.Colors[g.DebugFlashStyleColorIdx].w = 1.0f; if ((g.DebugFlashStyleColorTime -= g.IO.DeltaTime) <= 0.0f) DebugFlashStyleColorStop(); From 28caa223567cef70c295d58ec23fefc6125e4bbe Mon Sep 17 00:00:00 2001 From: James Wrigley Date: Tue, 3 Sep 2024 00:50:20 +0200 Subject: [PATCH 082/548] Fix minor typo (#7943) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index cc89955d0a43..f6b7a7d0bd00 100644 --- a/imgui.h +++ b/imgui.h @@ -460,7 +460,7 @@ namespace ImGui // - Use the ShowStyleEditor() function to interactively see/edit the colors. IMGUI_API ImFont* GetFont(); // get current font IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied - IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API + IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a white pixel, useful to draw custom shapes via the ImDrawList API IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier, packed as a 32-bit value suitable for ImDrawList IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList IMGUI_API ImU32 GetColorU32(ImU32 col, float alpha_mul = 1.0f); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList From 4a06fe59b4d2dcd14ab9f79b7644ebad9a6d007a Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Sep 2024 15:32:40 +0200 Subject: [PATCH 083/548] Update FONTS.md (#7944) --- docs/FONTS.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/FONTS.md b/docs/FONTS.md index df8b610e5639..c451af61c0ba 100644 --- a/docs/FONTS.md +++ b/docs/FONTS.md @@ -50,7 +50,9 @@ All loaded fonts glyphs are rendered into a single texture atlas ahead of time. ### (4) Font atlas texture fails to upload to GPU. -This is often of byproduct of point 3. If you have large number of glyphs or multiple fonts, the texture may become too big for your graphics API. **The typical result of failing to upload a texture is if every glyph or everything appears as empty black or white rectangle.** Mind the fact that some graphics drivers have texture size limitation. If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours. +This is often of byproduct of point 3. If you have large number of glyphs or multiple fonts, the texture may become too big for your graphics API. **The typical result of failing to upload a texture is if every glyph or everything appears as empty white rectangles.** Mind the fact that some graphics drivers have texture size limitation. If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours. + +![empty squares](https://github.com/user-attachments/assets/68b50fb5-8b9d-4c38-baec-6ac384f06d26) Some solutions: - You may reduce oversampling, e.g. `font_config.OversampleH = 1`, this will half your texture size for a quality loss. @@ -60,6 +62,8 @@ Some solutions: - Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two. - Set `io.Fonts.TexDesiredWidth` to specify a texture width to reduce maximum texture height (see comment in `ImFontAtlas::Build()` function). +Future versions of Dear ImGui should solve this problem. + ##### [Return to Index](#index) --------------------------------------- From ee9e3a2ed66bd618ca17ebcba18088e4c9c64bd2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 23 Aug 2024 19:40:47 +0200 Subject: [PATCH 084/548] Tabs: avoid queuing a refocus when tab is already focused, which would have the side-effect of e.g. closing popup on a mouse release. (#7914) + Debug Log: add details about closed popups. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 3 +++ imgui_widgets.cpp | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d19e8f39e063..028f12d4cec2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -83,6 +83,8 @@ Other changes: - Tables: fixes/revert a 1.90 change were outer border would be moved bottom and right by an extra pixel + rework the change so that contents doesn't overlap the bottom and right border in a scrolling table. (#6765, #3752, #7428) +- Tabs: avoid queuing a refocus when tab is already focused, which would have the + side-effect of e.g. closing popup on a mouse release. (#7914) - InputText: allow callback to update buffer while in read-only mode. (imgui_club/#46) - InputText: fixed an issue programmatically refocusing a multi-line input which was just active. (#4761, #7870) - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) diff --git a/imgui.cpp b/imgui.cpp index 2b4099966b13..dfa74d994c4d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11370,6 +11370,9 @@ void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_ ImGuiContext& g = *GImGui; IMGUI_DEBUG_LOG_POPUP("[popup] ClosePopupToLevel(%d), restore_under=%d\n", remaining, restore_focus_to_window_under_popup); IM_ASSERT(remaining >= 0 && remaining < g.OpenPopupStack.Size); + if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) + for (int n = remaining; n < g.OpenPopupStack.Size; n++) + IMGUI_DEBUG_LOG_POPUP("[popup] - Closing PopupID 0x%08X Window \"%s\"\n", g.OpenPopupStack[n].PopupId, g.OpenPopupStack[n].Window ? g.OpenPopupStack[n].Window->Name : NULL); // Trim open popup stack ImGuiPopupData prev_popup = g.OpenPopupStack[remaining]; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ce80cfd872f1..436d81b0a544 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -9986,7 +9986,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget. const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup); - if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button) + if (tab_bar->SelectedTabId != tab->ID && hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button) TabBarQueueFocus(tab_bar, tab); if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton) From 6a7319543c4b0bfdf3b6b06ce8a14d762aba985e Mon Sep 17 00:00:00 2001 From: Matt Guerrette Date: Sun, 25 Aug 2024 13:07:10 -0400 Subject: [PATCH 085/548] Backends: SDL3: following SDL3 reverting their change, result of SDL_GetGamepads must be freed. (#7918, #7898, #7807) --- backends/imgui_impl_sdl3.cpp | 4 +++- docs/CHANGELOG.txt | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index deb8c7925dc5..0387b155c13a 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-09-03: Update for SDL3 api changes: SDL_GetGamepads() memory ownership revert. (#7918, #7898, #7807) // 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: // - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn // - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn @@ -672,7 +673,7 @@ static void ImGui_ImplSDL3_UpdateGamepads() { ImGui_ImplSDL3_CloseGamepads(); int sdl_gamepads_count = 0; - const SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count); + SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count); for (int n = 0; n < sdl_gamepads_count; n++) if (SDL_Gamepad* gamepad = SDL_OpenGamepad(sdl_gamepads[n])) { @@ -681,6 +682,7 @@ static void ImGui_ImplSDL3_UpdateGamepads() break; } bd->WantUpdateGamepadsList = false; + SDL_free(sdl_gamepads); } // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 028f12d4cec2..dbb0917ff8b4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -96,6 +96,8 @@ Other changes: provide a way to do a portable sleep. (#7844) - Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut] - Backends: SDL2, SDL3: storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. +- Backends: SDL3: Update for API changes: SDL_GetGamepads() memory ownership logic was reverted back + by SDL3 on July 27. (#7918, #7898, #7807) [@cheyao, @MattGuerrette] - Backends: GLFW: passing null window to glfwGetClipboardString()/glfwSetClipboardString() since GLFW own tests are doing that and it seems unnecessary. - Backends: SDL2, SDL3, GLFW, OSX, Allegro: update to set function handlers in ImGuiPlatformIO @@ -103,7 +105,7 @@ Other changes: - 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) - +Backends: SDL3: following SDL3 reverting their change, result of SDL_GetGamepads must be freed. (#7918, #7898) ----------------------------------------------------------------------- VERSION 1.91.0 (Released 2024-07-30) From 4832027eb6a313dedb4c4d0a04c6352a0e68e83f Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 Sep 2024 19:05:32 +0200 Subject: [PATCH 086/548] Examples: SDL3: Update for API changes: SDL_Init() returns 0 on failure. --- backends/imgui_impl_sdl3.cpp | 2 +- backends/imgui_impl_sdl3.h | 2 +- backends/imgui_impl_sdlrenderer3.cpp | 2 ++ backends/imgui_impl_sdlrenderer3.h | 2 ++ docs/CHANGELOG.txt | 27 ++++++++++++--------- examples/example_sdl3_opengl3/main.cpp | 2 +- examples/example_sdl3_sdlrenderer3/main.cpp | 2 +- 7 files changed, 23 insertions(+), 16 deletions(-) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 0387b155c13a..540b6931af0c 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -2,7 +2,7 @@ // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) // (Info: SDL3 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) -// (**IMPORTANT: SDL 3.0.0 is NOT YET RELEASED AND CURRENTLY HAS A FAST CHANGING API. THIS CODE BREAKS OFTEN**) +// (**IMPORTANT: SDL 3.0.0 is NOT YET RELEASED AND CURRENTLY HAS A FAST CHANGING API. THIS CODE BREAKS OFTEN AS SDL3 CHANGES.**) // Implemented features: // [X] Platform: Clipboard support. diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h index 39b7839d8d4b..880ba9615b18 100644 --- a/backends/imgui_impl_sdl3.h +++ b/backends/imgui_impl_sdl3.h @@ -2,7 +2,7 @@ // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) // (Info: SDL3 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) -// (**IMPORTANT: SDL 3.0.0 is NOT YET RELEASED AND CURRENTLY HAS A FAST CHANGING API. THIS CODE BREAKS OFTEN**) +// (**IMPORTANT: SDL 3.0.0 is NOT YET RELEASED AND CURRENTLY HAS A FAST CHANGING API. THIS CODE BREAKS OFTEN AS SDL3 CHANGES.**) // Implemented features: // [X] Platform: Clipboard support. diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp index 8ba262548d69..d3926c2fbf6a 100644 --- a/backends/imgui_impl_sdlrenderer3.cpp +++ b/backends/imgui_impl_sdlrenderer3.cpp @@ -1,6 +1,8 @@ // dear imgui: Renderer Backend for SDL_Renderer for SDL3 // (Requires: SDL 3.0.0+) +// (**IMPORTANT: SDL 3.0.0 is NOT YET RELEASED AND CURRENTLY HAS A FAST CHANGING API. THIS CODE BREAKS OFTEN AS SDL3 CHANGES.**) + // Note how SDL_Renderer is an _optional_ component of SDL3. // For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX. // If your application will want to render any non trivial amount of graphics other than UI, diff --git a/backends/imgui_impl_sdlrenderer3.h b/backends/imgui_impl_sdlrenderer3.h index 1a730208a87f..6c23deca9257 100644 --- a/backends/imgui_impl_sdlrenderer3.h +++ b/backends/imgui_impl_sdlrenderer3.h @@ -1,6 +1,8 @@ // dear imgui: Renderer Backend for SDL_Renderer for SDL3 // (Requires: SDL 3.0.0+) +// (**IMPORTANT: SDL 3.0.0 is NOT YET RELEASED AND CURRENTLY HAS A FAST CHANGING API. THIS CODE BREAKS OFTEN AS SDL3 CHANGES.**) + // Note how SDL_Renderer is an _optional_ component of SDL3. // For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX. // If your application will want to render any non trivial amount of graphics other than UI, diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index dbb0917ff8b4..9065b46ee594 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -92,18 +92,21 @@ Other changes: a drag and drop source or target: a SetNextWindowPos() call won't be overriden. (#6973) - Style: added PushStyleVarX(), PushStyleVarY() helpers to modify only one component of a ImVec2 var. - Fonts: made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) -- Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not - provide a way to do a portable sleep. (#7844) -- Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut] -- Backends: SDL2, SDL3: storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. -- Backends: SDL3: Update for API changes: SDL_GetGamepads() memory ownership logic was reverted back - by SDL3 on July 27. (#7918, #7898, #7807) [@cheyao, @MattGuerrette] -- Backends: GLFW: passing null window to glfwGetClipboardString()/glfwSetClipboardString() - since GLFW own tests are doing that and it seems unnecessary. -- Backends: SDL2, SDL3, GLFW, OSX, Allegro: update to set function handlers in ImGuiPlatformIO - instead of ImGuiIO. -- 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) +- Backends: + - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not + provide a way to do a portable sleep. (#7844) + - Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut] + - Backends: SDL2, SDL3: storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. + - Backends: SDL3: Update for API changes: SDL_GetGamepads() memory ownership logic was reverted back + by SDL3 on July 27. (#7918, #7898, #7807) [@cheyao, @MattGuerrette] + - Backends: GLFW: passing null window to glfwGetClipboardString()/glfwSetClipboardString() + since GLFW own tests are doing that and it seems unnecessary. + - Backends: SDL2, SDL3, GLFW, OSX, Allegro: update to set function handlers in ImGuiPlatformIO + instead of ImGuiIO. +- Examples: + - 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) + - Examples: SDL3: Update for API changes: SDL_Init() returns 0 on failure. Backends: SDL3: following SDL3 reverting their change, result of SDL_GetGamepads must be freed. (#7918, #7898) diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp index e6aba880950d..0ba09dc937cc 100644 --- a/examples/example_sdl3_opengl3/main.cpp +++ b/examples/example_sdl3_opengl3/main.cpp @@ -27,7 +27,7 @@ int main(int, char**) { // Setup SDL - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0) + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); return -1; diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 6efd2754ac75..ef98d752d5e9 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -25,7 +25,7 @@ int main(int, char**) { // Setup SDL - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0) + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); return -1; From 07be01767afd005372035e471f8ac6e85e200001 Mon Sep 17 00:00:00 2001 From: Yan Pujante Date: Fri, 23 Aug 2024 10:05:38 -0700 Subject: [PATCH 087/548] Demo: added emscripten version. (#7915) --- imgui_demo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a729e45b223f..fe38ebf2e6cc 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -116,6 +116,9 @@ Index of this file: #if !defined(_MSC_VER) || _MSC_VER >= 1800 #include // PRId64/PRIu64, not avail in some MinGW headers. #endif +#ifdef __EMSCRIPTEN__ +#include // __EMSCRIPTEN_major__ etc. +#endif // Visual Studio warnings #ifdef _MSC_VER @@ -7688,6 +7691,7 @@ void ImGui::ShowAboutWindow(bool* p_open) #endif #ifdef __EMSCRIPTEN__ ImGui::Text("define: __EMSCRIPTEN__"); + ImGui::Text("Emscripten: %d.%d.%d", __EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__); #endif ImGui::Separator(); ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL"); From 30dcdcbe736f551c0d7bc87ce5ed43edc835d7a2 Mon Sep 17 00:00:00 2001 From: Yan Pujante Date: Fri, 23 Aug 2024 09:56:02 -0700 Subject: [PATCH 088/548] Backends: GLFW: Emscripten: use OpenURL() when available and using EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3. Fixes popup blocked in some browsers. (#7915, #7660) --- backends/imgui_impl_glfw.cpp | 6 +++++- docs/CHANGELOG.txt | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index ee230ee1b046..06b5142a1cfc 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -560,7 +560,11 @@ void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows) } #ifdef __EMSCRIPTEN__ -EM_JS(void, ImGui_ImplGlfw_EmscriptenOpenURL, (char const* url), { url = url ? UTF8ToString(url) : null; if (url) window.open(url, '_blank'); }); +#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 3'4'0'20240817 +void ImGui_ImplGlfw_EmscriptenOpenURL(const char* url) { if (url) emscripten::glfw3::OpenURL(url); } +#else +EM_JS(void, ImGui_ImplGlfw_EmscriptenOpenURL, (const char* url), { url = url ? UTF8ToString(url) : null; if (url) window.open(url, '_blank'); }); +#endif #endif static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9065b46ee594..6bedd7173411 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -95,6 +95,8 @@ Other changes: - Backends: - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not provide a way to do a portable sleep. (#7844) + - Backends: GLFW+Emscripten: Use OpenURL() from GLFW3 contrib port when available and using + the contrib port instead of Emscripten own GLFW3 implementation. (#7647, #7915, #7660) [@ypujante] - Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut] - Backends: SDL2, SDL3: storing SDL_WindowID inside ImGuiViewport::PlatformHandle instead of SDL_Window*. - Backends: SDL3: Update for API changes: SDL_GetGamepads() memory ownership logic was reverted back @@ -103,6 +105,7 @@ Other changes: since GLFW own tests are doing that and it seems unnecessary. - Backends: SDL2, SDL3, GLFW, OSX, Allegro: update to set function handlers in ImGuiPlatformIO instead of ImGuiIO. + - Examples: - 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) @@ -262,7 +265,7 @@ Other changes: - Backends: SDL2,SDL3,OSX: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() rename. - Backends: GLFW,SDL2: Added io.PlatformOpenInShellFn handler for web/Emscripten versions. (#7660) [@ypujante, @ocornut] - - Backends; GLFW+Emscripten: Added support for GLFW3 contrib port which fixes many of the things + - Backends: GLFW+Emscripten: Added support for GLFW3 contrib port which fixes many of the things not supported by the embedded GLFW: gamepad support, mouse cursor shapes, copy to clipboard, workaround for Super/Meta key, different ways of resizing, multi-window (glfw/canvas) support. (#7647) [@ypujante] From a93f7db875cbda4abe50f3e347879508c8490be4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 Sep 2024 20:55:00 +0200 Subject: [PATCH 089/548] Misc merge/small stuff from docking to reduce drift. Among other things: - merged cfd23957 (#7940, #7823), also see ac64b6563 (#6716): moved above on 2023/08/14 in both branches. - moving the RenderDimmedBackgrounds() call, from f422e782, see 676497fe intently undoing ac64b65 -> confusing. (#6716) --- docs/CHANGELOG.txt | 3 --- imgui.cpp | 49 +++++++++++++++++++++++++--------------------- imgui.h | 4 ++-- imgui_internal.h | 24 ++++++++++++++--------- imgui_widgets.cpp | 4 ++-- 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6bedd7173411..22df64e0faad 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -105,14 +105,11 @@ Other changes: since GLFW own tests are doing that and it seems unnecessary. - Backends: SDL2, SDL3, GLFW, OSX, Allegro: update to set function handlers in ImGuiPlatformIO instead of ImGuiIO. - - Examples: - 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) - Examples: SDL3: Update for API changes: SDL_Init() returns 0 on failure. -Backends: SDL3: following SDL3 reverting their change, result of SDL_GetGamepads must be freed. (#7918, #7898) - ----------------------------------------------------------------------- VERSION 1.91.0 (Released 2024-07-30) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index dfa74d994c4d..deb006e0905a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1380,12 +1380,6 @@ ImGuiIO::ImGuiIO() FontAllowUserScaling = false; DisplayFramebufferScale = ImVec2(1.0f, 1.0f); - MouseDoubleClickTime = 0.30f; - MouseDoubleClickMaxDist = 6.0f; - MouseDragThreshold = 6.0f; - KeyRepeatDelay = 0.275f; - KeyRepeatRate = 0.050f; - // Miscellaneous options MouseDrawCursor = false; #ifdef __APPLE__ @@ -1404,6 +1398,13 @@ ImGuiIO::ImGuiIO() ConfigDebugBeginReturnValueOnce = false; ConfigDebugBeginReturnValueLoop = false; + // Inputs Behaviors + MouseDoubleClickTime = 0.30f; + MouseDoubleClickMaxDist = 6.0f; + MouseDragThreshold = 6.0f; + KeyRepeatDelay = 0.275f; + KeyRepeatRate = 0.050f; + // Platform Functions // Note: Initialize() will setup default clipboard/ime handlers. BackendPlatformName = BackendRendererName = NULL; @@ -4229,8 +4230,9 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) // Test if another item is active (e.g. being dragged) const ImGuiID id = g.LastItemData.ID; if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0) - if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId) - return false; + if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap) + if (g.ActiveId != window->MoveId) + return false; // Test if interactions on this window are blocked by an active popup or modal. // The ImGuiHoveredFlags_AllowWhenBlockedByPopup flag will be tested here. @@ -4242,7 +4244,8 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) return false; // Special handling for calling after Begin() which represent the title bar or tab. - // When the window is skipped/collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case. + // When the window is skipped/collapsed (SkipItems==true) that last item (always ->MoveId submitted by Begin) + // will never be overwritten so we need to detect the case. if (id == window->MoveId && window->WriteAccessed) return false; @@ -4640,9 +4643,10 @@ void ImGui::UpdateMouseMovingWindowEndFrame() StartMouseMovingWindow(g.HoveredWindow); //-V595 // Cancel moving if clicked outside of title bar - if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(root_window->Flags & ImGuiWindowFlags_NoTitleBar)) - if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0])) - g.MovingWindow = NULL; + if (g.IO.ConfigWindowsMoveFromTitleBarOnly) + if (!(root_window->Flags & ImGuiWindowFlags_NoTitleBar)) + if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0])) + g.MovingWindow = NULL; // Cancel moving if clicked over an item which was disabled or inhibited by popups (note that we know HoveredId == 0 already) if (g.HoveredIdIsDisabled) @@ -5200,7 +5204,7 @@ static void ImGui::RenderDimmedBackgrounds() } else if (dim_bg_for_window_list) { - // Draw dimming behind CTRL+Tab target window + // Draw dimming behind CTRL+Tab target window and behind CTRL+Tab UI window RenderDimmedBackgroundBehindWindow(g.NavWindowingTargetAnim, GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio)); // Draw border around CTRL+Tab target window @@ -5325,9 +5329,6 @@ void ImGui::Render() g.IO.MetricsRenderWindows = 0; CallContextHooks(&g, ImGuiContextHookType_RenderPre); - // Draw modal/window whitening backgrounds - RenderDimmedBackgrounds(); - // Add background ImDrawList (for each active viewport) for (ImGuiViewportP* viewport : g.Viewports) { @@ -5336,6 +5337,9 @@ void ImGui::Render() AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport)); } + // Draw modal/window whitening backgrounds + RenderDimmedBackgrounds(); + // Add ImDrawList to render ImGuiWindow* windows_to_render_top_most[2]; windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL; @@ -14335,10 +14339,11 @@ static void ImGui::UpdateViewportsNewFrame() for (ImGuiViewportP* viewport : g.Viewports) { - // Lock down space taken by menu bars and status bars, reset the offset for fucntions like BeginMainMenuBar() to alter them again. - viewport->WorkOffsetMin = viewport->BuildWorkOffsetMin; - viewport->WorkOffsetMax = viewport->BuildWorkOffsetMax; - viewport->BuildWorkOffsetMin = viewport->BuildWorkOffsetMax = ImVec2(0.0f, 0.0f); + // Lock down space taken by menu bars and status bars + // Setup initial value for functions like BeginMainMenuBar(), DockSpaceOverViewport() etc. + viewport->WorkInsetMin = viewport->BuildWorkInsetMin; + viewport->WorkInsetMax = viewport->BuildWorkInsetMax; + viewport->BuildWorkInsetMin = viewport->BuildWorkInsetMax = ImVec2(0.0f, 0.0f); viewport->UpdateWorkRect(); } } @@ -15762,9 +15767,9 @@ void ImGui::DebugNodeViewport(ImGuiViewportP* viewport) if (open) { ImGuiWindowFlags flags = viewport->Flags; - BulletText("Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Offset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f", + BulletText("Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Inset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f", viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y, - viewport->WorkOffsetMin.x, viewport->WorkOffsetMin.y, viewport->WorkOffsetMax.x, viewport->WorkOffsetMax.y); + viewport->WorkInsetMin.x, viewport->WorkInsetMin.y, viewport->WorkInsetMax.x, viewport->WorkInsetMax.y); BulletText("Flags: 0x%04X =%s%s%s", viewport->Flags, (flags & ImGuiViewportFlags_IsPlatformWindow) ? " IsPlatformWindow" : "", (flags & ImGuiViewportFlags_IsPlatformMonitor) ? " IsPlatformMonitor" : "", diff --git a/imgui.h b/imgui.h index f6b7a7d0bd00..3ded051f18c4 100644 --- a/imgui.h +++ b/imgui.h @@ -3447,7 +3447,7 @@ enum ImGuiViewportFlags_ ImGuiViewportFlags_None = 0, ImGuiViewportFlags_IsPlatformWindow = 1 << 0, // Represent a Platform Window ImGuiViewportFlags_IsPlatformMonitor = 1 << 1, // Represent a Platform Monitor (unused yet) - ImGuiViewportFlags_OwnedByApp = 1 << 2, // Platform Window: is created/managed by the application (rather than a dear imgui backend) + ImGuiViewportFlags_OwnedByApp = 1 << 2, // Platform Window: Is created/managed by the application (rather than a dear imgui backend) }; // - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows. @@ -3487,7 +3487,7 @@ struct ImGuiPlatformIO IMGUI_API ImGuiPlatformIO(); //------------------------------------------------------------------ - // Inputs - Interface with OS/backends + // Input - Interface with OS/backends //------------------------------------------------------------------ // Optional: Access OS clipboard diff --git a/imgui_internal.h b/imgui_internal.h index 884c85a190e0..70f7e4dca6dc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -94,6 +94,7 @@ Index of this file: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead +#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #endif // In 1.89.4, we moved the implementation of "courtesy maths operators" from imgui_internal.h in imgui.h @@ -1806,23 +1807,28 @@ struct ImGuiViewportP : public ImGuiViewport ImDrawList* BgFgDrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays. ImDrawData DrawDataP; ImDrawDataBuilder DrawDataBuilder; // Temporary data while building final ImDrawData - ImVec2 WorkOffsetMin; // Work Area: Offset from Pos to top-left corner of Work Area. Generally (0,0) or (0,+main_menu_bar_height). Work Area is Full Area but without menu-bars/status-bars (so WorkArea always fit inside Pos/Size!) - ImVec2 WorkOffsetMax; // Work Area: Offset from Pos+Size to bottom-right corner of Work Area. Generally (0,0) or (0,-status_bar_height). - ImVec2 BuildWorkOffsetMin; // Work Area: Offset being built during current frame. Generally >= 0.0f. - ImVec2 BuildWorkOffsetMax; // Work Area: Offset being built during current frame. Generally <= 0.0f. + + // Per-viewport work area + // - Insets are >= 0.0f values, distance from viewport corners to work area. + // - BeginMainMenuBar() and DockspaceOverViewport() tend to use work area to avoid stepping over existing contents. + // - Generally 'safeAreaInsets' in iOS land, 'DisplayCutout' in Android land. + ImVec2 WorkInsetMin; // Work Area inset locked for the frame. GetWorkRect() always fits within GetMainRect(). + ImVec2 WorkInsetMax; // " + ImVec2 BuildWorkInsetMin; // Work Area inset accumulator for current frame, to become next frame's WorkInset + ImVec2 BuildWorkInsetMax; // " ImGuiViewportP() { BgFgDrawListsLastFrame[0] = BgFgDrawListsLastFrame[1] = -1; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; } ~ImGuiViewportP() { if (BgFgDrawLists[0]) IM_DELETE(BgFgDrawLists[0]); if (BgFgDrawLists[1]) IM_DELETE(BgFgDrawLists[1]); } // Calculate work rect pos/size given a set of offset (we have 1 pair of offset for rect locked from last frame data, and 1 pair for currently building rect) - ImVec2 CalcWorkRectPos(const ImVec2& off_min) const { return ImVec2(Pos.x + off_min.x, Pos.y + off_min.y); } - ImVec2 CalcWorkRectSize(const ImVec2& off_min, const ImVec2& off_max) const { return ImVec2(ImMax(0.0f, Size.x - off_min.x + off_max.x), ImMax(0.0f, Size.y - off_min.y + off_max.y)); } - void UpdateWorkRect() { WorkPos = CalcWorkRectPos(WorkOffsetMin); WorkSize = CalcWorkRectSize(WorkOffsetMin, WorkOffsetMax); } // Update public fields + ImVec2 CalcWorkRectPos(const ImVec2& inset_min) const { return ImVec2(Pos.x + inset_min.x, Pos.y + inset_min.y); } + ImVec2 CalcWorkRectSize(const ImVec2& inset_min, const ImVec2& inset_max) const { return ImVec2(ImMax(0.0f, Size.x - inset_min.x - inset_max.x), ImMax(0.0f, Size.y - inset_min.y - inset_max.y)); } + void UpdateWorkRect() { WorkPos = CalcWorkRectPos(WorkInsetMin); WorkSize = CalcWorkRectSize(WorkInsetMin, WorkInsetMax); } // Update public fields // Helpers to retrieve ImRect (we don't need to store BuildWorkRect as every access tend to change it, hence the code asymmetry) ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); } - ImRect GetBuildWorkRect() const { ImVec2 pos = CalcWorkRectPos(BuildWorkOffsetMin); ImVec2 size = CalcWorkRectSize(BuildWorkOffsetMin, BuildWorkOffsetMax); return ImRect(pos.x, pos.y, pos.x + size.x, pos.y + size.y); } + ImRect GetBuildWorkRect() const { ImVec2 pos = CalcWorkRectPos(BuildWorkInsetMin); ImVec2 size = CalcWorkRectSize(BuildWorkInsetMin, BuildWorkInsetMax); return ImRect(pos.x, pos.y, pos.x + size.x, pos.y + size.y); } }; //----------------------------------------------------------------------------- @@ -2612,7 +2618,7 @@ struct IMGUI_API ImGuiWindow ImVec2 WindowPadding; // Window padding at the time of Begin(). float WindowRounding; // Window rounding at the time of Begin(). May be clamped lower to avoid rendering artifacts with title bar, menu bar etc. float WindowBorderSize; // Window border size at the time of Begin(). - float TitleBarHeight, MenuBarHeight; + float TitleBarHeight, MenuBarHeight; // Note that those used to be function before 2024/05/28. If you have old code calling TitleBarHeight() you can change it to TitleBarHeight. float DecoOuterSizeX1, DecoOuterSizeY1; // Left/Up offsets. Sum of non-scrolling outer decorations (X1 generally == 0.0f. Y1 generally = TitleBarHeight + MenuBarHeight). Locked during Begin(). float DecoOuterSizeX2, DecoOuterSizeY2; // Right/Down offsets (X2 generally == ScrollbarSize.x, Y2 == ScrollbarSizes.y). float DecoInnerSizeX1, DecoInnerSizeY1; // Applied AFTER/OVER InnerRect. Specialized for Tables as they use specialized form of clipping and frozen rows/columns are inside InnerRect (and not part of regular decoration sizes). diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 436d81b0a544..b550e8d84337 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8557,9 +8557,9 @@ bool ImGui::BeginViewportSideBar(const char* name, ImGuiViewport* viewport_p, Im // Report our size into work area (for next frame) using actual window size if (dir == ImGuiDir_Up || dir == ImGuiDir_Left) - viewport->BuildWorkOffsetMin[axis] += axis_size; + viewport->BuildWorkInsetMin[axis] += axis_size; else if (dir == ImGuiDir_Down || dir == ImGuiDir_Right) - viewport->BuildWorkOffsetMax[axis] -= axis_size; + viewport->BuildWorkInsetMax[axis] += axis_size; } window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; From f99febfd6fa16d44ca73832d20a9367d433783d7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 Sep 2024 21:19:25 +0200 Subject: [PATCH 090/548] Made BeginItemTooltip() and IsItemHovered() with delay flag infer an implicit ID using Pos only. (#7945, #1485, #143) Perhaps a better approach would be to: store last non-zero ID + count successive zero ID and combine then. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 12 +++++++++++- imgui.h | 2 +- imgui_internal.h | 3 ++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 22df64e0faad..066a61f0244a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -76,6 +76,8 @@ Other changes: - Windows: adjust default ClipRect to better match rendering of thick borders (which are in theory not supported). Compensate for the fact that borders are centered around the windows edge rather than inner. (#7887, #7888 + #3312, #7540, #3756, #6170, #6365) +- Made BeginItemTooltip() and IsItemHovered() with delay flag infer an implicit ID (for + ID-less items such as Text element) in a way that works when item resizes. (#7945, #1485) - 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 diff --git a/imgui.cpp b/imgui.cpp index deb006e0905a..767dbf70d254 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4261,7 +4261,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) const float delay = CalcDelayFromHoveredFlags(flags); if (delay > 0.0f || (flags & ImGuiHoveredFlags_Stationary)) { - ImGuiID hover_delay_id = (g.LastItemData.ID != 0) ? g.LastItemData.ID : window->GetIDFromRectangle(g.LastItemData.Rect); + ImGuiID hover_delay_id = (g.LastItemData.ID != 0) ? g.LastItemData.ID : window->GetIDFromPos(g.LastItemData.Rect.Min); if ((flags & ImGuiHoveredFlags_NoSharedDelay) && (g.HoverItemDelayIdPreviousFrame != hover_delay_id)) g.HoverItemDelayTimer = 0.0f; g.HoverItemDelayId = hover_delay_id; @@ -8367,6 +8367,16 @@ ImGuiID ImGuiWindow::GetID(int n) } // This is only used in rare/specific situations to manufacture an ID out of nowhere. +// FIXME: Consider instead storing last non-zero ID + count of successive zero-ID, and combine those? +ImGuiID ImGuiWindow::GetIDFromPos(const ImVec2& p_abs) +{ + ImGuiID seed = IDStack.back(); + ImVec2 p_rel = ImGui::WindowPosAbsToRel(this, p_abs); + ImGuiID id = ImHashData(&p_rel, sizeof(p_rel), seed); + return id; +} + +// " ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs) { ImGuiID seed = IDStack.back(); diff --git a/imgui.h b/imgui.h index 3ded051f18c4..f7b1f3a29582 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.1 WIP" -#define IMGUI_VERSION_NUM 19104 +#define IMGUI_VERSION_NUM 19105 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 70f7e4dca6dc..59d8af7ebb5f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2715,6 +2715,7 @@ struct IMGUI_API ImGuiWindow ImGuiID GetID(const char* str, const char* str_end = NULL); ImGuiID GetID(const void* ptr); ImGuiID GetID(int n); + ImGuiID GetIDFromPos(const ImVec2& p_abs); ImGuiID GetIDFromRectangle(const ImRect& r_abs); // We don't use g.FontSize because the window may be != g.CurrentWindow. @@ -3124,8 +3125,8 @@ namespace ImGui inline void SetWindowParentWindowForFocusRoute(ImGuiWindow* window, ImGuiWindow* parent_window) { window->ParentWindowForFocusRoute = parent_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); } inline ImVec2 WindowPosAbsToRel(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x - off.x, p.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); } // Windows: Display Order and Focus Order IMGUI_API void FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags = 0); From afb15e9795888a704ca2c8d0eba6ae4dbd7ded11 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 Sep 2024 21:49:35 +0200 Subject: [PATCH 091/548] PlotHistogram, PlotLines: register item ID in a more idiomatic manner. (#7935, #3072) --- docs/CHANGELOG.txt | 2 ++ imgui_demo.cpp | 5 +++++ imgui_widgets.cpp | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 066a61f0244a..54b3e8cca014 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -92,6 +92,8 @@ Other changes: - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) - Tooltips, Drag and Drop: made it possible to override BeginTooltip() position while inside a drag and drop source or target: a SetNextWindowPos() call won't be overriden. (#6973) +- PlotHistogram, PlotLines: register item ID in a more idiomatic manner, fixes preventing + e.g. GetItemID() and other ID-based helper to work. (#7935, #3072) - Style: added PushStyleVarX(), PushStyleVarY() helpers to modify only one component of a ImVec2 var. - Fonts: made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) - Backends: diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fe38ebf2e6cc..b83cf2987d34 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2004,6 +2004,10 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); ImGui::Separator(); + ImGui::Text("Need better plotting and graphing? Consider using ImPlot:"); + ImGui::TextLinkOpenURL("https://github.com/epezent/implot"); + ImGui::Separator(); + ImGui::TreePop(); } @@ -6448,6 +6452,7 @@ static void ShowDemoWindowTables() ImGui::CheckboxFlags("_ScrollX", &table_flags, ImGuiTableFlags_ScrollX); ImGui::CheckboxFlags("_ScrollY", &table_flags, ImGuiTableFlags_ScrollY); ImGui::CheckboxFlags("_Resizable", &table_flags, ImGuiTableFlags_Resizable); + ImGui::CheckboxFlags("_Sortable", &table_flags, ImGuiTableFlags_Sortable); ImGui::CheckboxFlags("_NoBordersInBody", &table_flags, ImGuiTableFlags_NoBordersInBody); ImGui::CheckboxFlags("_HighlightHoveredColumn", &table_flags, ImGuiTableFlags_HighlightHoveredColumn); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index b550e8d84337..99992a71736e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8224,7 +8224,7 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0)); ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, 0, &frame_bb)) + if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_NoNav)) return -1; const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); From 776813416b5af283280250c08cc45af53fed066c Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 Sep 2024 21:55:26 +0200 Subject: [PATCH 092/548] PlotHistogram, PlotLines: use ButtonBehavior() to be idiomatic. (#7935, #3072) --- docs/CHANGELOG.txt | 4 ++-- imgui_widgets.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 54b3e8cca014..d76a04042636 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -92,8 +92,8 @@ Other changes: - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) - Tooltips, Drag and Drop: made it possible to override BeginTooltip() position while inside a drag and drop source or target: a SetNextWindowPos() call won't be overriden. (#6973) -- PlotHistogram, PlotLines: register item ID in a more idiomatic manner, fixes preventing - e.g. GetItemID() and other ID-based helper to work. (#7935, #3072) +- PlotHistogram, PlotLines: register item ID and use button behavior in a more idiomatic manner, + fixes preventing e.g. GetItemID() and other ID-based helper to work. (#7935, #3072) - Style: added PushStyleVarX(), PushStyleVarY() helpers to modify only one component of a ImVec2 var. - Fonts: made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) - Backends: diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 99992a71736e..fd52c93cdfcd 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8226,7 +8226,8 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_NoNav)) return -1; - const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); + bool hovered; + ButtonBehavior(frame_bb, id, &hovered, NULL); // Determine scale from values if not specified if (scale_min == FLT_MAX || scale_max == FLT_MAX) From 722a2a12fb2dc32d01fe28f226ec2d2e4e908498 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 4 Sep 2024 14:41:22 +0200 Subject: [PATCH 093/548] Tables: comments. (#7937) --- imgui.h | 2 +- imgui_demo.cpp | 7 ++++++- imgui_tables.cpp | 9 +++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/imgui.h b/imgui.h index f7b1f3a29582..cfee0fcc7130 100644 --- a/imgui.h +++ b/imgui.h @@ -1948,7 +1948,7 @@ enum ImGuiTableColumnFlags_ ImGuiTableColumnFlags_NoSort = 1 << 9, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table). ImGuiTableColumnFlags_NoSortAscending = 1 << 10, // Disable ability to sort in the ascending direction. ImGuiTableColumnFlags_NoSortDescending = 1 << 11, // Disable ability to sort in the descending direction. - ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, // TableHeadersRow() will not submit horizontal label for this column. Convenient for some small columns. Name will still appear in context menu or in angled headers. + ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, // TableHeadersRow() will submit an empty label for this column. Convenient for some small columns. Name will still appear in context menu or in angled headers. You may append into this cell by calling TableSetColumnIndex() right after the TableHeadersRow() call. ImGuiTableColumnFlags_NoHeaderWidth = 1 << 13, // Disable header text width contribution to automatic column width. ImGuiTableColumnFlags_PreferSortAscending = 1 << 14, // Make the initial sort direction Ascending when first sorting on this column (default). ImGuiTableColumnFlags_PreferSortDescending = 1 << 15, // Make the initial sort direction Descending when first sorting on this column. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b83cf2987d34..5c9bcd3b41bf 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6403,7 +6403,11 @@ static void ShowDemoWindowTables() // FIXME: It would be nice to actually demonstrate full-featured selection using those checkbox. static bool column_selected[3] = {}; - // Instead of calling TableHeadersRow() we'll submit custom headers ourselves + // Instead of calling TableHeadersRow() we'll submit custom headers ourselves. + // (A different approach is also possible: + // - Specify ImGuiTableColumnFlags_NoHeaderLabel in some TableSetupColumn() call. + // - Call TableHeadersRow() normally. This will submit TableHeader() with no name. + // - Then call TableSetColumnIndex() to position yourself in the column and submit your stuff e.g. Checkbox().) ImGui::TableNextRow(ImGuiTableRowFlags_Headers); for (int column = 0; column < COLUMNS_COUNT; column++) { @@ -6418,6 +6422,7 @@ static void ShowDemoWindowTables() ImGui::PopID(); } + // Submit table contents for (int row = 0; row < 5; row++) { ImGui::TableNextRow(); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index fd7e6da5722c..69d1322bd974 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3018,7 +3018,8 @@ float ImGui::TableGetHeaderAngledMaxLabelWidth() // The intent is that advanced users willing to create customized headers would not need to use this helper // and can create their own! For example: TableHeader() may be preceded by Checkbox() or other custom widgets. // See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this. -// This code is constructed to not make much use of internal functions, as it is intended to be a template to copy. +// This code is intentionally written to not make much use of internal functions, to give you better direction +// if you need to write your own. // FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public. void ImGui::TableHeadersRow() { @@ -3026,7 +3027,8 @@ void ImGui::TableHeadersRow() ImGuiTable* table = g.CurrentTable; IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); - // Layout if not already done (this is automatically done by TableNextRow, we do it here solely to facilitate stepping in debugger as it is frequent to step in TableUpdateLayout) + // Call layout if not already done. This is automatically done by TableNextRow: we do it here _only_ to make + // it easier to debug-step in TableUpdateLayout(). Your own version of this function doesn't need this. if (!table->IsLayoutLocked) TableUpdateLayout(table); @@ -3043,8 +3045,7 @@ void ImGui::TableHeadersRow() if (!TableSetColumnIndex(column_n)) continue; - // Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them) - // In your own code you may omit the PushID/PopID all-together, provided you know they won't collide. + // Push an id to allow empty/unnamed headers. This is also idiomatic as it ensure there is a consistent ID path to access columns (for e.g. automation) const char* name = (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_NoHeaderLabel) ? "" : TableGetColumnName(column_n); PushID(column_n); TableHeader(name); From 8dd33839f026ddd154c550b72f21a70746e6cab5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 4 Sep 2024 15:15:48 +0200 Subject: [PATCH 094/548] Tables: fixed an issue detecting hovering column/row when using multiple synched instances layed out at different X positions. (#7933) Was reading ClipRect from last frame. --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d76a04042636..95745581aa02 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -85,6 +85,8 @@ Other changes: - Tables: fixes/revert a 1.90 change were outer border would be moved bottom and right by an extra pixel + rework the change so that contents doesn't overlap the bottom and right border in a scrolling table. (#6765, #3752, #7428) +- Tables: fixed an issue detecting hovering column/row when using multiple synched instances, + layed out at different X positions. (#7932) - Tabs: avoid queuing a refocus when tab is already focused, which would have the side-effect of e.g. closing popup on a mouse release. (#7914) - InputText: allow callback to update buffer while in read-only mode. (imgui_club/#46) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 69d1322bd974..9ee70fc50f0f 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1070,10 +1070,6 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) continue; } - // Detect hovered column - if (is_hovering_table && mouse_skewed_x >= column->ClipRect.Min.x && mouse_skewed_x < column->ClipRect.Max.x) - table->HoveredColumnBody = (ImGuiTableColumnIdx)column_n; - // Lock start position column->MinX = offset_x; @@ -1128,8 +1124,13 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) column->Flags |= ImGuiTableColumnFlags_IsVisible; if (column->SortOrder != -1) column->Flags |= ImGuiTableColumnFlags_IsSorted; - if (table->HoveredColumnBody == column_n) + + // Detect hovered column + if (is_hovering_table && mouse_skewed_x >= column->ClipRect.Min.x && mouse_skewed_x < column->ClipRect.Max.x) + { column->Flags |= ImGuiTableColumnFlags_IsHovered; + table->HoveredColumnBody = (ImGuiTableColumnIdx)column_n; + } // Alignment // FIXME-TABLE: This align based on the whole column width, not per-cell, and therefore isn't useful in From f75cf62d2f36a66fcdc7be7161a3798bea926509 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 4 Sep 2024 15:31:39 +0200 Subject: [PATCH 095/548] Tables: fixed resizing columns when using multiple synched instances that are layed out at different X positions. (#7933) TableGetMaxColumnWidth() was using MinX from previous column. Storing info in column. Still incorrect interleaved data for multi-instances but it covers majority of use cases. --- docs/CHANGELOG.txt | 4 ++-- imgui_internal.h | 3 ++- imgui_tables.cpp | 10 +++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 95745581aa02..4c2537a8c1c3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -85,8 +85,8 @@ Other changes: - Tables: fixes/revert a 1.90 change were outer border would be moved bottom and right by an extra pixel + rework the change so that contents doesn't overlap the bottom and right border in a scrolling table. (#6765, #3752, #7428) -- Tables: fixed an issue detecting hovering column/row when using multiple synched instances, - layed out at different X positions. (#7932) +- Tables: fixed an issue resizing columns or querying hovered column/row when using multiple + synched instances that are layed out at different X positions. (#7933) - Tabs: avoid queuing a refocus when tab is already focused, which would have the side-effect of e.g. closing popup on a mouse release. (#7914) - InputText: allow callback to update buffer while in read-only mode. (imgui_club/#46) diff --git a/imgui_internal.h b/imgui_internal.h index 59d8af7ebb5f..cb7923c64e16 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2827,6 +2827,7 @@ struct ImGuiTableColumn float MaxX; float WidthRequest; // Master width absolute value when !(Flags & _WidthStretch). When Stretch this is derived every frame from StretchWeight in TableUpdateLayout() float WidthAuto; // Automatic width + float WidthMax; // Maximum width (FIXME: overwritten by each instance) float StretchWeight; // Master width weight when (Flags & _WidthStretch). Often around ~1.0f initially. float InitStretchWeightOrWidth; // Value passed to TableSetupColumn(). For Width it is a content width (_without padding_). ImRect ClipRect; // Clipping rectangle for the column @@ -3470,7 +3471,7 @@ namespace ImGui IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n); IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n); IMGUI_API ImGuiID TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no = 0); - IMGUI_API float TableGetMaxColumnWidth(const ImGuiTable* table, int column_n); + IMGUI_API float TableCalcMaxColumnWidth(const ImGuiTable* table, int column_n); IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n); IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table); IMGUI_API void TableRemove(ImGuiTable* table); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 9ee70fc50f0f..aaa40de81c43 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1074,8 +1074,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) column->MinX = offset_x; // Lock width based on start position and minimum/maximum width for this position - float max_width = TableGetMaxColumnWidth(table, column_n); - column->WidthGiven = ImMin(column->WidthGiven, max_width); + column->WidthMax = TableCalcMaxColumnWidth(table, column_n); + column->WidthGiven = ImMin(column->WidthGiven, column->WidthMax); column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, table->MinColumnWidth)); column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f; @@ -2207,8 +2207,8 @@ void ImGui::TableEndCell(ImGuiTable* table) // Note that actual columns widths are computed in TableUpdateLayout(). //------------------------------------------------------------------------- -// Maximum column content width given current layout. Use column->MinX so this value on a per-column basis. -float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n) +// Maximum column content width given current layout. Use column->MinX so this value differs on a per-column basis. +float ImGui::TableCalcMaxColumnWidth(const ImGuiTable* table, int column_n) { const ImGuiTableColumn* column = &table->Columns[column_n]; float max_width = FLT_MAX; @@ -2270,7 +2270,7 @@ void ImGui::TableSetColumnWidth(int column_n, float width) // Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded) IM_ASSERT(table->MinColumnWidth > 0.0f); const float min_width = table->MinColumnWidth; - const float max_width = ImMax(min_width, TableGetMaxColumnWidth(table, column_n)); + const float max_width = ImMax(min_width, column_0->WidthMax); // Don't use TableCalcMaxColumnWidth() here as it would rely on MinX from last instance (#7933) column_0_width = ImClamp(column_0_width, min_width, max_width); if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width) return; From 1dfbb100d6ca6e7d813102e979c07f66a56546bb Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 4 Sep 2024 16:17:30 +0200 Subject: [PATCH 096/548] Version 1.91.1 --- docs/CHANGELOG.txt | 24 +++++++++++++----------- 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, 22 insertions(+), 20 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4c2537a8c1c3..d7fec4cff617 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,9 +36,11 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.91.1 WIP (In Progress) + VERSION 1.91.1 (Released 2024-09-04) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.1 + Breaking changes: - BeginChild(): renamed ImGuiChildFlags_Border to ImGuiChildFlags_Borders for consistency. [@cfillion] @@ -54,7 +56,6 @@ Breaking changes: - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn (#7660) - io.PlatformSetImeDataFn -> platform_io.Platform_SetImeDataFn - io.PlatformLocaleDecimalPoint -> platform_io.Platform_LocaleDecimalPoint (#7389, #6719, #2278) - - clipboard function signature changed: - access those via GetPlatformIO() instead of GetIO(). (Because PlatformOpenInShellFn and PlatformSetImeDataFn were introduced very recently and often automatically set by core library and backends, we are exceptionally not maintaining @@ -63,14 +64,14 @@ Breaking changes: - old ImageButton() used ImTextureId as item id (created issue with e.g. multiple buttons in same scope, transient texture id values, opaque computation of ID) - new ImageButton() requires an explicit 'const char* str_id' - old ImageButton() had frame_padding' override argument. - - new ImageButton() always use style.FramePadding, which you can freely override with PushStyleVar()/PopStyleVar(). + - new ImageButton() always use style.FramePadding, which you can modify using PushStyleVar()/PopStyleVar(). Other changes: - IO: Added GetPlatformIO() and ImGuiPlatformIO, pulled from 'docking' branch, which is a centralized spot to connect os/platform/renderer related functions. Clipboard, IME and OpenInShell hooks are moved here. (#7660) -- IO, InputText: fixed an issue where typing text in a InputText() would defer character +- IO, InputText: fixed an issue where typing text in an InputText() would defer character processing by one frame, because of the trickling input queue. Reworked interleaved keys<>char trickling to take account for keys known to input characters. (#7889, #4921, #4858) - Windows: adjust default ClipRect to better match rendering of thick borders (which are in @@ -78,10 +79,10 @@ Other changes: edge rather than inner. (#7887, #7888 + #3312, #7540, #3756, #6170, #6365) - Made BeginItemTooltip() and IsItemHovered() with delay flag infer an implicit ID (for ID-less items such as Text element) in a way that works when item resizes. (#7945, #1485) -- 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) +- MultiSelect+TreeNode+Drag and Drop: fixed an issue where carrying a drag and drop payload + over an already open tree node using multi-select would incorrectly select it. (#7850) +- MultiSelect+TreeNode: default open behavior is _OpenOnDoubleClick + _OpenOnArrow when + used in a multi-select context without any ImGuiTreeNode_OpenOnXXX flags set. (#7850) - Tables: fixes/revert a 1.90 change were outer border would be moved bottom and right by an extra pixel + rework the change so that contents doesn't overlap the bottom and right border in a scrolling table. (#6765, #3752, #7428) @@ -93,11 +94,12 @@ Other changes: - InputText: fixed an issue programmatically refocusing a multi-line input which was just active. (#4761, #7870) - TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660) - Tooltips, Drag and Drop: made it possible to override BeginTooltip() position while inside - a drag and drop source or target: a SetNextWindowPos() call won't be overriden. (#6973) + a drag and drop source or target: a SetNextWindowPos() call won't be overridden. (#6973) - PlotHistogram, PlotLines: register item ID and use button behavior in a more idiomatic manner, fixes preventing e.g. GetItemID() and other ID-based helper to work. (#7935, #3072) -- Style: added PushStyleVarX(), PushStyleVarY() helpers to modify only one component of a ImVec2 var. -- Fonts: made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903) +- Style: added PushStyleVarX(), PushStyleVarY() helpers to conveniently modify only + one component of a ImVec2 var. +- Fonts: made it possible to use PushFont()/PopFont() calls across Begin() calls. (#3224, #3875, #6398, #7903) - Backends: - Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not provide a way to do a portable sleep. (#7844) diff --git a/imgui.cpp b/imgui.cpp index 767dbf70d254..ac76ddd194ff 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 WIP +// dear imgui, v1.91.1 // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index cfee0fcc7130..a6766e2d625b 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 WIP +// dear imgui, v1.91.1 // (headers) // Help: @@ -28,8 +28,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.1 WIP" -#define IMGUI_VERSION_NUM 19105 +#define IMGUI_VERSION "1.91.1" +#define IMGUI_VERSION_NUM 19110 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5c9bcd3b41bf..9ca73806d032 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 WIP +// dear imgui, v1.91.1 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 65d68708d3a0..e033c357c9d1 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 WIP +// dear imgui, v1.91.1 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index cb7923c64e16..a99cb2652e19 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 WIP +// dear imgui, v1.91.1 // (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 aaa40de81c43..5685c2aced44 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 WIP +// dear imgui, v1.91.1 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index fd52c93cdfcd..7f2b127116d4 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 WIP +// dear imgui, v1.91.1 // (widgets code) /* From 41eebc87a06d15979ed0088a4f5ec5673ccc2f6c Mon Sep 17 00:00:00 2001 From: CrackedMatter <81803926+CrackedMatter@users.noreply.github.com> Date: Thu, 5 Sep 2024 12:04:28 +0200 Subject: [PATCH 097/548] Fixed C++26 invalid enum operation (#7954) --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7f2b127116d4..b9e2ca2ce4e4 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5196,7 +5196,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ { // For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (see #4761, #7870)... Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y)); - g.NextItemData.ItemFlags |= ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop; + g.NextItemData.ItemFlags |= (ImGuiItemFlags)ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop; EndChild(); item_data_backup.StatusFlags |= (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredWindow); From e3cb016328468e5902127777fc08b0c249039aaa Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 5 Sep 2024 15:15:49 +0200 Subject: [PATCH 098/548] CI: upgrade Ubuntu version to get newer Clang. Add C++26 build test. (#7954) --- .github/workflows/build.yml | 17 ++++++++++++++--- examples/example_null/Makefile | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4320a2025deb..4539ecbf6947 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -218,7 +218,7 @@ jobs: run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx12/example_win32_directx12.vcxproj /p:Platform=x64 /p:Configuration=Release' Linux: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -433,6 +433,17 @@ jobs: EOF clang++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp + - name: Build example_null (single file build, c++26) + run: | + cat > example_single_file.cpp <<'EOF' + + #define IMGUI_IMPLEMENTATION + #include "misc/single_file/imgui_single_file.h" + #include "examples/example_null/main.cpp" + + EOF + clang++ -I. -std=c++26 -Wall -Wformat -o example_single_file example_single_file.cpp + - name: Build example_null (without c++ runtime) run: | cat > example_single_file.cpp <<'EOF' @@ -481,7 +492,7 @@ jobs: xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_ios CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO Emscripten: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -508,7 +519,7 @@ jobs: make -C examples/example_glfw_wgpu -f Makefile.emscripten Android: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 diff --git a/examples/example_null/Makefile b/examples/example_null/Makefile index 9ceb353493b1..4a67cecd85fc 100644 --- a/examples/example_null/Makefile +++ b/examples/example_null/Makefile @@ -1,6 +1,6 @@ # # Cross Platform Makefile -# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X +# Compatible with MSYS2/MINGW, Ubuntu 14.04.1+ and Mac OS X # # Important: This is a "null backend" application, with no visible output or interaction! # This is used for testing purpose and continuous integration, and has little use for end-user. From 943fd216ecadedd4ca59bb3ec56730c73bb9295c Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 5 Sep 2024 15:19:04 +0200 Subject: [PATCH 099/548] CI: Amend e3cb016. --- .github/workflows/build.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4539ecbf6947..7c7f7471f536 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -324,6 +324,18 @@ jobs: EOF g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp + - name: Build example_null (with C++26) + run: | + cat > example_single_file.cpp <<'EOF' + + #define IMGUI_DISABLE_OBSOLETE_KEYIO + #define IMGUI_IMPLEMENTATION + #include "misc/single_file/imgui_single_file.h" + #include "examples/example_null/main.cpp" + + EOF + g++ -I. -std=c++26 -Wall -Wformat -o example_single_file example_single_file.cpp + - name: Build example_null (with IMGUI_DISABLE_DEMO_WINDOWS and IMGUI_DISABLE_DEBUG_TOOLS) run: | cat > example_single_file.cpp <<'EOF' @@ -433,7 +445,7 @@ jobs: EOF clang++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp - - name: Build example_null (single file build, c++26) + - name: Build example_null (single file build, c++20) run: | cat > example_single_file.cpp <<'EOF' @@ -442,7 +454,7 @@ jobs: #include "examples/example_null/main.cpp" EOF - clang++ -I. -std=c++26 -Wall -Wformat -o example_single_file example_single_file.cpp + clang++ -I. -std=c++20 -Wall -Wformat -o example_single_file example_single_file.cpp - name: Build example_null (without c++ runtime) run: | From 4a1a38f7ed0ab89aa506dcba346e90d698d1a8d2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 5 Sep 2024 15:28:41 +0200 Subject: [PATCH 100/548] CI: Amend 943fd21. --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7c7f7471f536..702e281bf1ee 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -324,7 +324,7 @@ jobs: EOF g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp - - name: Build example_null (with C++26) + - name: Build example_null (with C++20) run: | cat > example_single_file.cpp <<'EOF' @@ -334,7 +334,7 @@ jobs: #include "examples/example_null/main.cpp" EOF - g++ -I. -std=c++26 -Wall -Wformat -o example_single_file example_single_file.cpp + g++ -I. -std=c++20 -Wall -Wformat -o example_single_file example_single_file.cpp - name: Build example_null (with IMGUI_DISABLE_DEMO_WINDOWS and IMGUI_DISABLE_DEBUG_TOOLS) run: | From d0b742efdee1d09ff0e87a8a1419e08f7f84174c Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 5 Sep 2024 15:30:29 +0200 Subject: [PATCH 101/548] CI: build with Clang C++26 on Linux. (#7954) --- .github/workflows/build.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 702e281bf1ee..1d43da032a6a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -393,6 +393,18 @@ jobs: EOF g++ -I. -std=c++11 -Wall -Wformat -o example_single_file example_single_file.cpp + - name: Build example_null (C++26, Clang) + run: | + cat > example_single_file.cpp <<'EOF' + + #define IMGUI_IMPLEMENTATION + #define IMGUI_DISABLE_DEMO_WINDOWS + #include "misc/single_file/imgui_single_file.h" + #include "examples/example_null/main.cpp" + + EOF + clang++ -I. -std=c++26 -Wall -Wformat -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp + - name: Build example_null (without c++ runtime, Clang) run: | cat > example_single_file.cpp <<'EOF' From 193c1e2366857dbfdbc3dd98c5b95f47b881f122 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 5 Sep 2024 20:03:23 +0200 Subject: [PATCH 102/548] Version 1.91.2 WIP --- docs/CHANGELOG.txt | 8 ++++++++ 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, 17 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d7fec4cff617..0136b45a700d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -35,6 +35,14 @@ 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.2 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking changes: + +Other changes: + ----------------------------------------------------------------------- VERSION 1.91.1 (Released 2024-09-04) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index ac76ddd194ff..6706135e3863 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 +// dear imgui, v1.91.2 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index a6766e2d625b..0eeba4af0c82 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 +// dear imgui, v1.91.2 WIP // (headers) // Help: @@ -28,8 +28,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.1" -#define IMGUI_VERSION_NUM 19110 +#define IMGUI_VERSION "1.91.2 WIP" +#define IMGUI_VERSION_NUM 19111 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9ca73806d032..aabb220d6ab6 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 +// dear imgui, v1.91.2 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e033c357c9d1..a681059bbdbc 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 +// dear imgui, v1.91.2 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index a99cb2652e19..a0b1109046e9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 +// dear imgui, v1.91.2 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 5685c2aced44..f247ed6d3931 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 +// dear imgui, v1.91.2 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index b9e2ca2ce4e4..3b0fcc52f9d0 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.1 +// dear imgui, v1.91.2 WIP // (widgets code) /* From d16cb171c6667c6b7e8d0bd89389a968492c14ce Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 5 Sep 2024 20:16:37 +0200 Subject: [PATCH 103/548] Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439, extend #370, #369) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0136b45a700d..f425dc60e9ff 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,8 @@ Breaking changes: Other changes: +- Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439) + ----------------------------------------------------------------------- VERSION 1.91.1 (Released 2024-09-04) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 6706135e3863..fd018802af94 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -13182,9 +13182,11 @@ static void ImGui::NavUpdateWindowing() // Keyboard: Press and Release ALT to toggle menu layer const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt }; + bool windowing_toggle_layer_start = false; for (ImGuiKey windowing_toggle_key : windowing_toggle_keys) if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, 0, ImGuiKeyOwner_NoOwner)) { + windowing_toggle_layer_start = true; g.NavWindowingToggleLayer = true; g.NavWindowingToggleKey = windowing_toggle_key; g.NavInputSource = ImGuiInputSource_Keyboard; @@ -13198,7 +13200,9 @@ static void ImGui::NavUpdateWindowing() // We cancel toggling nav layer if an owner has claimed the key. if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper) g.NavWindowingToggleLayer = false; - if (TestKeyOwner(g.NavWindowingToggleKey, ImGuiKeyOwner_NoOwner) == false || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_NoOwner) == false) + else if (windowing_toggle_layer_start == false && g.LastKeyboardKeyPressTime == g.Time) + g.NavWindowingToggleLayer = false; + else if (TestKeyOwner(g.NavWindowingToggleKey, ImGuiKeyOwner_NoOwner) == false || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_NoOwner) == false) g.NavWindowingToggleLayer = false; // Apply layer toggle on Alt release From a5cf4fe374d491c882974d492a05117ef4bcc102 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 5 Sep 2024 20:45:07 +0200 Subject: [PATCH 104/548] InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. --- docs/CHANGELOG.txt | 1 + imgui_widgets.cpp | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f425dc60e9ff..82c7a60b62dc 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -44,6 +44,7 @@ Breaking changes: Other changes: - Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439) +- InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. ----------------------------------------------------------------------- VERSION 1.91.1 (Released 2024-09-04) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3b0fcc52f9d0..2f998a649aa7 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3894,9 +3894,18 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob r->num_chars = (int)(text_remaining - (text + line_start_idx)); } -static bool is_separator(unsigned int c) +static bool ImCharIsSeparatorW(unsigned int c) { - return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r' || c=='.' || c=='!' || c=='\\' || c=='/'; + static const unsigned int separator_list[] = + { + ',', 0x3001, '.', 0x3002, ';', 0xFF1B, '(', 0xFF08, ')', 0xFF09, '{', 0xFF5B, '}', 0xFF5D, + '[', 0x300C, ']', 0x300D, '|', 0xFF5C, '!', 0xFF01, '\\', 0xFFE5, '/', 0x30FB, 0xFF0F, + '\n', '\r', + }; + for (unsigned int separator : separator_list) + if (c == separator) + return true; + return false; } static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) @@ -3906,9 +3915,9 @@ static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) return 0; bool prev_white = ImCharIsBlankW(obj->TextW[idx - 1]); - bool prev_separ = is_separator(obj->TextW[idx - 1]); + bool prev_separ = ImCharIsSeparatorW(obj->TextW[idx - 1]); bool curr_white = ImCharIsBlankW(obj->TextW[idx]); - bool curr_separ = is_separator(obj->TextW[idx]); + bool curr_separ = ImCharIsSeparatorW(obj->TextW[idx]); return ((prev_white || prev_separ) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ); } static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) @@ -3917,9 +3926,9 @@ static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) return 0; bool prev_white = ImCharIsBlankW(obj->TextW[idx]); - bool prev_separ = is_separator(obj->TextW[idx]); + bool prev_separ = ImCharIsSeparatorW(obj->TextW[idx]); bool curr_white = ImCharIsBlankW(obj->TextW[idx - 1]); - bool curr_separ = is_separator(obj->TextW[idx - 1]); + bool curr_separ = ImCharIsSeparatorW(obj->TextW[idx - 1]); return ((prev_white) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ); } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } From a2366f902249107f1533a85d3d1f93ec193f52f0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 6 Sep 2024 11:38:48 +0200 Subject: [PATCH 105/548] TextLinkOpenURL: display a verb in front the link. Update Gallery & other links. (#7885, #7660) --- docs/BACKENDS.md | 2 +- docs/CHANGELOG.txt | 1 + docs/FAQ.md | 10 +++++----- docs/README.md | 6 +++--- imgui.cpp | 7 ++++--- imgui.h | 2 +- imgui_internal.h | 1 + imgui_widgets.cpp | 2 +- 8 files changed, 17 insertions(+), 14 deletions(-) diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index 55a0983ddbc9..de5cd6697bad 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -135,7 +135,7 @@ Generally: It is unlikely you will add value to your project by creating your own backend. Also: -The [multi-viewports feature](https://github.com/ocornut/imgui/issues/1542) of the 'docking' branch allows +The [multi-viewports feature](https://github.com/ocornut/imgui/wiki/Multi-Viewports) of the 'docking' branch allows Dear ImGui windows to be seamlessly detached from the main application window. This is achieved using an extra layer to the Platform and Renderer backends, which allows Dear ImGui to communicate platform-specific requests such as: "create an additional OS window", "create a render context", "get the OS position of this diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 82c7a60b62dc..70b7424e96ad 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,7 @@ Other changes: - Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439) - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. +- TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660) ----------------------------------------------------------------------- VERSION 1.91.1 (Released 2024-09-04) diff --git a/docs/FAQ.md b/docs/FAQ.md index d104c30bc577..d53a5a099cc5 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -77,9 +77,9 @@ or view this file with any Markdown viewer. ### Q: Which version should I get? I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. -You may use the [docking](https://github.com/ocornut/imgui/tree/docking) branch which includes: -- [Docking features](https://github.com/ocornut/imgui/issues/2109) -- [Multi-viewport features](https://github.com/ocornut/imgui/issues/1542) +You may use the ['docking'](https://github.com/ocornut/imgui/tree/docking) branch which includes: +- [Docking features](https://github.com/ocornut/imgui/wiki/Docking) +- [Multi-viewport features](https://github.com/ocornut/imgui/wiki/Multi-Viewports) Many projects are using this branch and it is kept in sync with master regularly. @@ -654,7 +654,7 @@ You may take a look at: - [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding) -- [Gallery](https://github.com/ocornut/imgui/issues/7503) +- [Gallery](https://github.com/ocornut/imgui/issues?q=label%3Agallery) ##### [Return to Index](#index) @@ -700,7 +700,7 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci - Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md). - If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt), and see how you want to help and can help! - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere, etc. -You may post screenshots or links in the [gallery threads](https://github.com/ocornut/imgui/issues/7503). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and helps other teams and programmers with taking decisions. +You may post screenshots or links in the [gallery threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and helps other teams and programmers with taking decisions. - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete PR. ##### [Return to Index](#index) diff --git a/docs/README.md b/docs/README.md index a1807abac22a..0968727f19c1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -141,7 +141,7 @@ Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas. Examples projects using Dear ImGui: [Tracy](https://github.com/wolfpld/tracy) (profiler), [ImHex](https://github.com/WerWolv/ImHex) (hex editor/data analysis), [RemedyBG](https://remedybg.itch.io/remedybg) (debugger) and [hundreds of others](https://github.com/ocornut/imgui/wiki/Software-using-Dear-ImGui). -For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/7503)! +For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery)! For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page. @@ -170,11 +170,11 @@ Private support is available for paying business customers (E-mail: _contact @ d **Which version should I get?** -We occasionally tag [Releases](https://github.com/ocornut/imgui/releases) (with nice releases notes) but it is generally safe and recommended to sync to latest `master` or `docking` branch. The library is fairly stable and regressions tend to be fixed fast when reported. Advanced users may want to use the `docking` branch with [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) features. This branch is kept in sync with master regularly. +We occasionally tag [Releases](https://github.com/ocornut/imgui/releases) (with nice releases notes) but it is generally safe and recommended to sync to latest `master` or `docking` branch. The library is fairly stable and regressions tend to be fixed fast when reported. Advanced users may want to use the `docking` branch with [Multi-Viewport](https://github.com/ocornut/imgui/wiki/Multi-Viewports) and [Docking](https://github.com/ocornut/imgui/wiki/Docking) features. This branch is kept in sync with master regularly. **Who uses Dear ImGui?** -See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues/7503)! +See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Funding & Sponsors](https://github.com/ocornut/imgui/wiki/Funding), and [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also, see the [Gallery Threads](https://github.com/ocornut/imgui/issues?q=label%3Agallery)! How to help ----------- diff --git a/imgui.cpp b/imgui.cpp index fd018802af94..1d9d8b899efe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10,7 +10,7 @@ // - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md) // - Homepage ................... https://github.com/ocornut/imgui // - Releases & changelog ....... https://github.com/ocornut/imgui/releases -// - Gallery .................... https://github.com/ocornut/imgui/issues/7503 (please post your screenshots/video there!) +// - Gallery .................... https://github.com/ocornut/imgui/issues?q=label%3Agallery (please post your screenshots/video there!) // - Wiki ....................... https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started (how to integrate in an existing app by adding ~25 lines of code) // - Third-party Extensions https://github.com/ocornut/imgui/wiki/Useful-Extensions (ImPlot & many more) @@ -3780,7 +3780,7 @@ void ImGui::DestroyContext(ImGuiContext* ctx) IM_DELETE(ctx); } -// IMPORTANT: ###xxx suffixes must be same in ALL languages to allow for automation. +// IMPORTANT: interactive elements requires a fixed ###xxx suffix, it must be same in ALL languages to allow for automation. static const ImGuiLocEntry GLocalizationEntriesEnUS[] = { { ImGuiLocKey_VersionStr, "Dear ImGui " IMGUI_VERSION " (" IM_STRINGIFY(IMGUI_VERSION_NUM) ")" }, @@ -3791,7 +3791,8 @@ static const ImGuiLocEntry GLocalizationEntriesEnUS[] = { ImGuiLocKey_WindowingMainMenuBar, "(Main menu bar)" }, { ImGuiLocKey_WindowingPopup, "(Popup)" }, { ImGuiLocKey_WindowingUntitled, "(Untitled)" }, - { ImGuiLocKey_CopyLink, "Copy Link###CopyLink" }, + { ImGuiLocKey_OpenLink_s, "Open '%s'" }, + { ImGuiLocKey_CopyLink, "Copy Link###CopyLink" }, }; void ImGui::Initialize() diff --git a/imgui.h b/imgui.h index 0eeba4af0c82..0394967ee164 100644 --- a/imgui.h +++ b/imgui.h @@ -11,7 +11,7 @@ // - FAQ ........................ https://dearimgui.com/faq (in repository as docs/FAQ.md) // - Homepage ................... https://github.com/ocornut/imgui // - Releases & changelog ....... https://github.com/ocornut/imgui/releases -// - Gallery .................... https://github.com/ocornut/imgui/issues/7503 (please post your screenshots/video there!) +// - Gallery .................... https://github.com/ocornut/imgui/issues?q=label%3Agallery (please post your screenshots/video there!) // - Wiki ....................... https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started (how to integrate in an existing app by adding ~25 lines of code) // - Third-party Extensions https://github.com/ocornut/imgui/wiki/Useful-Extensions (ImPlot & many more) diff --git a/imgui_internal.h b/imgui_internal.h index a0b1109046e9..5d23ebfef4fe 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1882,6 +1882,7 @@ enum ImGuiLocKey : int ImGuiLocKey_WindowingMainMenuBar, ImGuiLocKey_WindowingPopup, ImGuiLocKey_WindowingUntitled, + ImGuiLocKey_OpenLink_s, ImGuiLocKey_CopyLink, ImGuiLocKey_COUNT }; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2f998a649aa7..7b86fb8bef9a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1460,7 +1460,7 @@ void ImGui::TextLinkOpenURL(const char* label, const char* url) if (TextLink(label)) if (g.PlatformIO.Platform_OpenInShellFn != NULL) g.PlatformIO.Platform_OpenInShellFn(&g, url); - SetItemTooltip("%s", url); // It is more reassuring for user to _always_ display URL when we same as label + SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when we same as label if (BeginPopupContextItem()) { if (MenuItem(LocalizeGetMsg(ImGuiLocKey_CopyLink))) From 21d03edcb0cdad9e870f94f55ebb1d6deb54bc30 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 9 Sep 2024 16:22:55 +0200 Subject: [PATCH 106/548] InputText: renamed namespace from stb_texture structure and added an indirection. --- imgui_internal.h | 27 +++++++------- imgui_widgets.cpp | 90 +++++++++++++++++++++++++++-------------------- 2 files changed, 66 insertions(+), 51 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 5d23ebfef4fe..ab7cbc1f3bf3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -216,6 +216,8 @@ namespace ImStb } // namespace ImStb +typedef ImStb::STB_TexteditState ImStbTexteditState; + //----------------------------------------------------------------------------- // [SECTION] Macros //----------------------------------------------------------------------------- @@ -1110,11 +1112,13 @@ struct IMGUI_API ImGuiInputTextDeactivatedState ImGuiInputTextDeactivatedState() { memset(this, 0, sizeof(*this)); } void ClearFreeMemory() { ID = 0; TextA.clear(); } }; + // Internal state of the currently focused/edited text input box // For a given item ID, access with ImGui::GetInputTextState() struct IMGUI_API ImGuiInputTextState { ImGuiContext* Ctx; // parent UI context (needs to be set explicitly by parent). + ImStbTexteditState* Stb; // State for stb_textedit.h ImGuiID ID; // widget id owning the text state int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not. ImVector TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. @@ -1123,7 +1127,7 @@ struct IMGUI_API ImGuiInputTextState bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument) int BufCapacityA; // end-user buffer capacity ImVec2 Scroll; // horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y) - ImStb::STB_TexteditState Stb; // state for stb_textedit.h + float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!) bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection @@ -1133,22 +1137,21 @@ struct IMGUI_API ImGuiInputTextState int ReloadSelectionStart; // POSITIONS ARE IN IMWCHAR units *NOT* UTF-8 this is why this is not exposed yet. int ReloadSelectionEnd; - ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } + ImGuiInputTextState(); + ~ImGuiInputTextState(); void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); } void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); } - int GetUndoAvailCount() const { return Stb.undostate.undo_point; } - int GetRedoAvailCount() const { return IMSTB_TEXTEDIT_UNDOSTATECOUNT - Stb.undostate.redo_point; } void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation // Cursor & Selection void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking - void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); } - bool HasSelection() const { return Stb.select_start != Stb.select_end; } - void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; } - int GetCursorPos() const { return Stb.cursor; } - int GetSelectionStart() const { return Stb.select_start; } - int GetSelectionEnd() const { return Stb.select_end; } - void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } + void CursorClamp() { Stb->cursor = ImMin(Stb->cursor, CurLenW); Stb->select_start = ImMin(Stb->select_start, CurLenW); Stb->select_end = ImMin(Stb->select_end, CurLenW); } + bool HasSelection() const { return Stb->select_start != Stb->select_end; } + void ClearSelection() { Stb->select_start = Stb->select_end = Stb->cursor; } + int GetCursorPos() const { return Stb->cursor; } + int GetSelectionStart() const { return Stb->select_start; } + int GetSelectionEnd() const { return Stb->select_end; } + void SelectAll() { Stb->select_start = 0; Stb->cursor = Stb->select_end = CurLenW; Stb->has_preferred_x = 0; } // Reload user buf (WIP #2890) // If you modify underlying user-passed const char* while active you need to call this (InputText V2 may lift this) @@ -1156,7 +1159,7 @@ struct IMGUI_API ImGuiInputTextState // if (ImGuiInputTextState* state = ImGui::GetInputTextState(id)) // id may be ImGui::GetItemID() is last item // state->ReloadUserBufAndSelectAll(); void ReloadUserBufAndSelectAll() { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; } - void ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb.select_start; ReloadSelectionEnd = Stb.select_end; } + void ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb->select_start; ReloadSelectionEnd = Stb->select_end; } void ReloadUserBufAndMoveToEnd() { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; } }; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7b86fb8bef9a..f359277273f8 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4029,9 +4029,21 @@ static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* st } // namespace ImStb +// We added an extra indirection where 'Stb' is heap-allocated, in order facilitate the work of bindings generators. +ImGuiInputTextState::ImGuiInputTextState() +{ + memset(this, 0, sizeof(*this)); + Stb = IM_NEW(ImStbTexteditState); +} + +ImGuiInputTextState::~ImGuiInputTextState() +{ + IM_DELETE(Stb); +} + void ImGuiInputTextState::OnKeyPressed(int key) { - stb_textedit_key(this, &Stb, key); + stb_textedit_key(this, Stb, key); CursorFollow = true; CursorAnimReset(); } @@ -4229,7 +4241,7 @@ static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* st const int insert_len = new_last_diff - first_diff + 1; const int delete_len = old_last_diff - first_diff + 1; if (insert_len > 0 || delete_len > 0) - if (IMSTB_TEXTEDIT_CHARTYPE* p = stb_text_createundo(&state->Stb.undostate, first_diff, delete_len, insert_len)) + if (IMSTB_TEXTEDIT_CHARTYPE* p = stb_text_createundo(&state->Stb->undostate, first_diff, delete_len, insert_len)) for (int i = 0; i < delete_len; i++) p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i); } @@ -4371,7 +4383,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; const bool init_reload_from_user_buf = (state != NULL && state->ReloadUserBuf); - const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); // state != NULL means its our state. + const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state. const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav); const bool init_state = (init_make_active || user_scroll_active); if ((init_state && g.ActiveId != id) || init_changed_specs || init_reload_from_user_buf) @@ -4417,13 +4429,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ else { state->Scroll = ImVec2(0.0f, 0.0f); - stb_textedit_initialize_state(&state->Stb, !is_multiline); + stb_textedit_initialize_state(state->Stb, !is_multiline); } if (init_reload_from_user_buf) { - state->Stb.select_start = state->ReloadSelectionStart; - state->Stb.cursor = state->Stb.select_end = state->ReloadSelectionEnd; + state->Stb->select_start = state->ReloadSelectionStart; + state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd; state->CursorClamp(); } else if (!is_multiline) @@ -4437,7 +4449,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } if (flags & ImGuiInputTextFlags_AlwaysOverwrite) - state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863) + state->Stb->insert_mode = 1; // stb field name is indeed incorrect (see #2863) } const bool is_osx = io.ConfigMacOSXBehaviors; @@ -4545,34 +4557,34 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } else if (hovered && io.MouseClickedCount[0] >= 2 && !io.KeyShift) { - stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); + stb_textedit_click(state, state->Stb, mouse_x, mouse_y); const int multiclick_count = (io.MouseClickedCount[0] - 2); if ((multiclick_count % 2) == 0) { // Double-click: Select word // We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant: // FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS) - const bool is_bol = (state->Stb.cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor - 1) == '\n'; - if (STB_TEXT_HAS_SELECTION(&state->Stb) || !is_bol) + const bool is_bol = (state->Stb->cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb->cursor - 1) == '\n'; + if (STB_TEXT_HAS_SELECTION(state->Stb) || !is_bol) state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT); //state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); - if (!STB_TEXT_HAS_SELECTION(&state->Stb)) - ImStb::stb_textedit_prep_selection_at_cursor(&state->Stb); - state->Stb.cursor = ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state->Stb.cursor); - state->Stb.select_end = state->Stb.cursor; - ImStb::stb_textedit_clamp(state, &state->Stb); + if (!STB_TEXT_HAS_SELECTION(state->Stb)) + ImStb::stb_textedit_prep_selection_at_cursor(state->Stb); + state->Stb->cursor = ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state->Stb->cursor); + state->Stb->select_end = state->Stb->cursor; + ImStb::stb_textedit_clamp(state, state->Stb); } else { // Triple-click: Select line - const bool is_eol = ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor) == '\n'; + const bool is_eol = ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb->cursor) == '\n'; state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART); state->OnKeyPressed(STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT); state->OnKeyPressed(STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT); if (!is_eol && is_multiline) { - ImSwap(state->Stb.select_start, state->Stb.select_end); - state->Stb.cursor = state->Stb.select_end; + ImSwap(state->Stb->select_start, state->Stb->select_end); + state->Stb->cursor = state->Stb->select_end; } state->CursorFollow = false; } @@ -4583,15 +4595,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (hovered) { if (io.KeyShift) - stb_textedit_drag(state, &state->Stb, mouse_x, mouse_y); + stb_textedit_drag(state, state->Stb, mouse_x, mouse_y); else - stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); + stb_textedit_click(state, state->Stb, mouse_x, mouse_y); state->CursorAnimReset(); } } else if (io.MouseDown[0] && !state->SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)) { - stb_textedit_drag(state, &state->Stb, mouse_x, mouse_y); + stb_textedit_drag(state, state->Stb, mouse_x, mouse_y); state->CursorAnimReset(); state->CursorFollow = true; } @@ -4644,7 +4656,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ IM_ASSERT(state != NULL); const int row_count_per_page = ImMax((int)((inner_size.y - style.FramePadding.y) / g.FontSize), 1); - state->Stb.row_count_per_page = row_count_per_page; + state->Stb->row_count_per_page = row_count_per_page; const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl @@ -4751,8 +4763,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Cut, Copy if (g.PlatformIO.Platform_SetClipboardTextFn != NULL) { - const int ib = state->HasSelection() ? ImMin(state->Stb.select_start, state->Stb.select_end) : 0; - const int ie = state->HasSelection() ? ImMax(state->Stb.select_start, state->Stb.select_end) : state->CurLenW; + const int ib = state->HasSelection() ? ImMin(state->Stb->select_start, state->Stb->select_end) : 0; + const int ie = state->HasSelection() ? ImMax(state->Stb->select_start, state->Stb->select_end) : state->CurLenW; const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1; char* clipboard_data = (char*)IM_ALLOC(clipboard_data_len * sizeof(char)); ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie); @@ -4764,7 +4776,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (!state->HasSelection()) state->SelectAll(); state->CursorFollow = true; - stb_textedit_cut(state, &state->Stb); + stb_textedit_cut(state, state->Stb); } } else if (is_paste) @@ -4786,7 +4798,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ clipboard_filtered[clipboard_filtered_len] = 0; if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation { - stb_textedit_paste(state, &state->Stb, clipboard_filtered, clipboard_filtered_len); + stb_textedit_paste(state, state->Stb, clipboard_filtered, clipboard_filtered_len); state->CursorFollow = true; } MemFree(clipboard_filtered); @@ -4813,7 +4825,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ apply_new_text_length = 0; value_changed = true; IMSTB_TEXTEDIT_CHARTYPE empty_string; - stb_textedit_replace(state, &state->Stb, &empty_string, 0); + stb_textedit_replace(state, state->Stb, &empty_string, 0); } else if (strcmp(buf, state->InitialTextA.Data) != 0) { @@ -4828,7 +4840,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ w_text.resize(ImTextCountCharsFromUtf8(apply_new_text, apply_new_text + apply_new_text_length) + 1); ImTextStrFromUtf8(w_text.Data, w_text.Size, apply_new_text, apply_new_text + apply_new_text_length); } - stb_textedit_replace(state, &state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0); + stb_textedit_replace(state, state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0); } } @@ -4903,9 +4915,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188) ImWchar* text = state->TextW.Data; - const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + state->Stb.cursor); - const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_start); - const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_end); + const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + state->Stb->cursor); + const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + state->Stb->select_start); + const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + state->Stb->select_end); // Call user code callback(&callback_data); @@ -4916,9 +4928,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ IM_ASSERT(callback_data.BufSize == state->BufCapacityA); IM_ASSERT(callback_data.Flags == flags); const bool buf_dirty = callback_data.BufDirty; - if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; } - if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb.select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb.cursor : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); } - if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); } + if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb->cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; } + if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb->select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb->cursor : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); } + if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb->select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb->select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); } if (buf_dirty) { // Callback may update buffer and thus set buf_dirty even in read-only mode. @@ -5040,13 +5052,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ int searches_remaining = 0; if (render_cursor) { - searches_input_ptr[0] = text_begin + state->Stb.cursor; + searches_input_ptr[0] = text_begin + state->Stb->cursor; searches_result_line_no[0] = -1; searches_remaining++; } if (render_selection) { - searches_input_ptr[1] = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end); + searches_input_ptr[1] = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end); searches_result_line_no[1] = -1; searches_remaining++; } @@ -5122,8 +5134,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const ImVec2 draw_scroll = ImVec2(state->Scroll.x, 0.0f); if (render_selection) { - const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end); - const ImWchar* text_selected_end = text_begin + ImMax(state->Stb.select_start, state->Stb.select_end); + const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end); + const ImWchar* text_selected_end = text_begin + ImMax(state->Stb->select_start, state->Stb->select_end); ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests. float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection. @@ -5244,7 +5256,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state) { #ifndef IMGUI_DISABLE_DEBUG_TOOLS ImGuiContext& g = *GImGui; - ImStb::STB_TexteditState* stb_state = &state->Stb; + ImStb::STB_TexteditState* stb_state = state->Stb; ImStb::StbUndoState* undo_state = &stb_state->undostate; Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId); DebugLocateItemOnHover(state->ID); From ca5701d45807ff7bdc71ccb85d9f1030cc8e917d Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 9 Sep 2024 16:29:47 +0200 Subject: [PATCH 107/548] InputText: moved all ImGuiInputTextState functions to not be inline. --- imgui.h | 2 +- imgui_internal.h | 24 +++++++++++------------- imgui_widgets.cpp | 13 +++++++++++++ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/imgui.h b/imgui.h index 0394967ee164..18efaff42419 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.2 WIP" -#define IMGUI_VERSION_NUM 19111 +#define IMGUI_VERSION_NUM 19112 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index ab7cbc1f3bf3..7748f07036f0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1127,7 +1127,6 @@ struct IMGUI_API ImGuiInputTextState bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument) int BufCapacityA; // end-user buffer capacity ImVec2 Scroll; // horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y) - float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!) bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection @@ -1144,24 +1143,23 @@ struct IMGUI_API ImGuiInputTextState void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation // Cursor & Selection - void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking - void CursorClamp() { Stb->cursor = ImMin(Stb->cursor, CurLenW); Stb->select_start = ImMin(Stb->select_start, CurLenW); Stb->select_end = ImMin(Stb->select_end, CurLenW); } - bool HasSelection() const { return Stb->select_start != Stb->select_end; } - void ClearSelection() { Stb->select_start = Stb->select_end = Stb->cursor; } - int GetCursorPos() const { return Stb->cursor; } - int GetSelectionStart() const { return Stb->select_start; } - int GetSelectionEnd() const { return Stb->select_end; } - void SelectAll() { Stb->select_start = 0; Stb->cursor = Stb->select_end = CurLenW; Stb->has_preferred_x = 0; } + void CursorAnimReset(); + void CursorClamp(); + bool HasSelection() const; + void ClearSelection(); + int GetCursorPos() const; + int GetSelectionStart() const; + int GetSelectionEnd() const; + void SelectAll(); // Reload user buf (WIP #2890) // If you modify underlying user-passed const char* while active you need to call this (InputText V2 may lift this) // strcpy(my_buf, "hello"); // if (ImGuiInputTextState* state = ImGui::GetInputTextState(id)) // id may be ImGui::GetItemID() is last item // state->ReloadUserBufAndSelectAll(); - void ReloadUserBufAndSelectAll() { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; } - void ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb->select_start; ReloadSelectionEnd = Stb->select_end; } - void ReloadUserBufAndMoveToEnd() { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; } - + void ReloadUserBufAndSelectAll(); + void ReloadUserBufAndKeepSelection(); + void ReloadUserBufAndMoveToEnd(); }; enum ImGuiWindowRefreshFlags_ diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f359277273f8..877dbd1084d1 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4048,6 +4048,19 @@ void ImGuiInputTextState::OnKeyPressed(int key) CursorAnimReset(); } +// Those functions are not inlined in imgui_internal.h, allowing us to hide ImStbTexteditState from that header. +void ImGuiInputTextState::CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking +void ImGuiInputTextState::CursorClamp() { Stb->cursor = ImMin(Stb->cursor, CurLenW); Stb->select_start = ImMin(Stb->select_start, CurLenW); Stb->select_end = ImMin(Stb->select_end, CurLenW); } +bool ImGuiInputTextState::HasSelection() const { return Stb->select_start != Stb->select_end; } +void ImGuiInputTextState::ClearSelection() { Stb->select_start = Stb->select_end = Stb->cursor; } +int ImGuiInputTextState::GetCursorPos() const { return Stb->cursor; } +int ImGuiInputTextState::GetSelectionStart() const { return Stb->select_start; } +int ImGuiInputTextState::GetSelectionEnd() const { return Stb->select_end; } +void ImGuiInputTextState::SelectAll() { Stb->select_start = 0; Stb->cursor = Stb->select_end = CurLenW; Stb->has_preferred_x = 0; } +void ImGuiInputTextState::ReloadUserBufAndSelectAll() { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; } +void ImGuiInputTextState::ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb->select_start; ReloadSelectionEnd = Stb->select_end; } +void ImGuiInputTextState::ReloadUserBufAndMoveToEnd() { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; } + ImGuiInputTextCallbackData::ImGuiInputTextCallbackData() { memset(this, 0, sizeof(*this)); From 15cb7d61f98de0bcde9fb3ddfdcb25fdccc8b7c7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 9 Sep 2024 16:52:16 +0200 Subject: [PATCH 108/548] InputText: moved imstb_textedit.h include to imgui_widgets.cpp --- imgui_internal.h | 31 +++++++++++-------------------- imgui_widgets.cpp | 6 ++++++ imstb_textedit.h | 3 ++- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 7748f07036f0..1aa94ff3b25e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -198,26 +198,6 @@ typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...); extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer #endif -//------------------------------------------------------------------------- -// [SECTION] STB libraries includes -//------------------------------------------------------------------------- - -namespace ImStb -{ - -#undef IMSTB_TEXTEDIT_STRING -#undef IMSTB_TEXTEDIT_CHARTYPE -#define IMSTB_TEXTEDIT_STRING ImGuiInputTextState -#define IMSTB_TEXTEDIT_CHARTYPE ImWchar -#define IMSTB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f) -#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99 -#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999 -#include "imstb_textedit.h" - -} // namespace ImStb - -typedef ImStb::STB_TexteditState ImStbTexteditState; - //----------------------------------------------------------------------------- // [SECTION] Macros //----------------------------------------------------------------------------- @@ -1113,6 +1093,17 @@ struct IMGUI_API ImGuiInputTextDeactivatedState void ClearFreeMemory() { ID = 0; TextA.clear(); } }; +// Forward declare imstb_textedit.h structure + make its main configuration define accessible +#undef IMSTB_TEXTEDIT_STRING +#undef IMSTB_TEXTEDIT_CHARTYPE +#define IMSTB_TEXTEDIT_STRING ImGuiInputTextState +#define IMSTB_TEXTEDIT_CHARTYPE ImWchar +#define IMSTB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f) +#define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99 +#define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999 +namespace ImStb { struct STB_TexteditState; } +typedef ImStb::STB_TexteditState ImStbTexteditState; + // Internal state of the currently focused/edited text input box // For a given item ID, access with ImGui::GetInputTextState() struct IMGUI_API ImGuiInputTextState diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 877dbd1084d1..10cdf342840e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3786,6 +3786,7 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f //------------------------------------------------------------------------- // [SECTION] Widgets: InputText, InputTextMultiline, InputTextWithHint //------------------------------------------------------------------------- +// - imstb_textedit.h include // - InputText() // - InputTextWithHint() // - InputTextMultiline() @@ -3796,6 +3797,11 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f // - DebugNodeInputTextState() [Internal] //------------------------------------------------------------------------- +namespace ImStb +{ +#include "imstb_textedit.h" +} + bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) { IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() diff --git a/imstb_textedit.h b/imstb_textedit.h index 783054ab953e..faaf518f402b 100644 --- a/imstb_textedit.h +++ b/imstb_textedit.h @@ -3,6 +3,7 @@ // Those changes would need to be pushed into nothings/stb: // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783) +// - Added name to struct or it may be forward declared in our code. // Grep for [DEAR IMGUI] to find the changes. // - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_* @@ -318,7 +319,7 @@ typedef struct int undo_char_point, redo_char_point; } StbUndoState; -typedef struct +typedef struct STB_TexteditState { ///////////////////// // From 4236bc088fd360a02064652069ed9bf04f013507 Mon Sep 17 00:00:00 2001 From: scribam Date: Sun, 8 Sep 2024 12:19:51 +0200 Subject: [PATCH 109/548] Backends: SDL2: use SDL_Vulkan_GetDrawableSize with Vulkan instead of SDL_GL_GetDrawableSize. (#7967, #3190) --- backends/imgui_impl_sdl2.cpp | 8 ++++++++ docs/CHANGELOG.txt | 1 + 2 files changed, 9 insertions(+) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index b1cc8c9e65c5..027dff9f2fd5 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-09-09: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) // 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: // - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn // - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn @@ -112,6 +113,9 @@ #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0 #endif #define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) +#if SDL_HAS_VULKAN +extern "C" { extern DECLSPEC void SDLCALL SDL_Vulkan_GetDrawableSize(SDL_Window* window, int* w, int* h); } +#endif // SDL Data struct ImGui_ImplSDL2_Data @@ -760,6 +764,10 @@ void ImGui_ImplSDL2_NewFrame() w = h = 0; if (bd->Renderer != nullptr) SDL_GetRendererOutputSize(bd->Renderer, &display_w, &display_h); +#if SDL_HAS_VULKAN + else if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_VULKAN) + SDL_Vulkan_GetDrawableSize(bd->Window, &display_w, &display_h); +#endif else SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h); io.DisplaySize = ImVec2((float)w, (float)h); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 70b7424e96ad..d915d9510b92 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,7 @@ Other changes: - Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439) - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. - TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660) +- Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam] ----------------------------------------------------------------------- VERSION 1.91.1 (Released 2024-09-04) From a8eec244056b8880f459d2073333fca4da5a917a Mon Sep 17 00:00:00 2001 From: Pascal Thomet Date: Mon, 9 Sep 2024 21:07:10 +0200 Subject: [PATCH 110/548] Demo: fix some id conflicts. (#7961) --- imgui_demo.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index aabb220d6ab6..65204951311c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -547,7 +547,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Checkbox("io.ConfigDebugIsDebuggerPresent", &io.ConfigDebugIsDebuggerPresent); ImGui::SameLine(); HelpMarker("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application."); ImGui::BeginDisabled(); - ImGui::Checkbox("io.ConfigDebugBeginReturnValueOnce", &io.ConfigDebugBeginReturnValueOnce); // . + ImGui::Checkbox("io.ConfigDebugBeginReturnValueOnce", &io.ConfigDebugBeginReturnValueOnce); ImGui::EndDisabled(); ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover."); ImGui::Checkbox("io.ConfigDebugBeginReturnValueLoop", &io.ConfigDebugBeginReturnValueLoop); @@ -2000,8 +2000,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::SameLine(); ImGui::SliderInt("Sample count", &display_count, 1, 400); float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw; - ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); - ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); + ImGui::PlotLines("Lines##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); + ImGui::PlotHistogram("Histogram##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); ImGui::Separator(); ImGui::Text("Need better plotting and graphing? Consider using ImPlot:"); @@ -2596,6 +2596,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Drag to reorder items (simple)"); if (ImGui::TreeNode("Drag to reorder items (simple)")) { + // FIXME: temporary ID Conflict during reordering as a same item may be submitting twice. + // Simple reordering HelpMarker( "We don't use the drag and drop api at all here! " @@ -4225,7 +4227,7 @@ static void ShowDemoWindowLayout() // down by FramePadding.y ahead of time) ImGui::AlignTextToFramePadding(); ImGui::Text("OK Blahblah"); ImGui::SameLine(); - ImGui::Button("Some framed item"); ImGui::SameLine(); + ImGui::Button("Some framed item##2"); ImGui::SameLine(); HelpMarker("We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y"); // SmallButton() uses the same vertical padding as Text @@ -7148,12 +7150,14 @@ static void ShowDemoWindowColumns() { if (h_borders && ImGui::GetColumnIndex() == 0) ImGui::Separator(); + ImGui::PushID(i); ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i); ImGui::Text("Width %.2f", ImGui::GetColumnWidth()); ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x); ImGui::Text("Offset %.2f", ImGui::GetColumnOffset()); ImGui::Text("Long text that is likely to clip"); ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f)); + ImGui::PopID(); ImGui::NextColumn(); } ImGui::Columns(1); From 67cd4ead6505b3386d4ef9c713c98546e86e26ca Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 10 Sep 2024 15:28:40 +0200 Subject: [PATCH 111/548] Added io.ConfigDebugHighlightIdConflicts debug feature! (#7961, #7669) Also #74, #96, #480, #501, #647, #654, #719, #843, #894, #1057, #1173, #1390, #1414, #1556, #1768, #2041, #2116, #2330, #2475, #2562, #2667, #2807, #2885, #3102, #3375, #3526, #3964, #4008, #4070, #4158, #4172, #4199, #4375, #4395, #4471, #4548, #4612, #4631, #4657, #4796, #5210, #5303, #5360, #5393, #5533, #5692, #5707, #5729, #5773, #5787, #5884, #6046, #6093, #6186, #6223, #6364, #6387, #6567, #6692, #6724, #6939, #6984, #7246, #7270, #7375, #7421, #7434, #7472, #7581, #7724, #7926, #7937 and probably more.. Tagging to increase visibility! --- docs/CHANGELOG.txt | 19 +++++++++++++++++++ docs/FAQ.md | 5 +++-- imgui.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ imgui.h | 11 ++++++++++- imgui_demo.cpp | 18 ++++++++++++++---- imgui_internal.h | 4 ++++ imgui_widgets.cpp | 3 +++ 7 files changed, 95 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d915d9510b92..35c4c6743d34 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,25 @@ Breaking changes: Other changes: +- Added io.ConfigDebugHighlightIdConflicts debug feature! (#7961, #7669) + THIS DETECTS THE MOST COMMON USER ERROR BY FIRST-TIME DEAR IMGUI PROGRAMMERS! + - The tool detects when multiple items are sharing the same identifier, due to not + using PushID/PopID in loops, or not using ID stack facilities such as "##" suffixes. + Very frequently it happens when using empty "" labels. + - When hovering an item with a conflicting ID, all visible items with the same ID will + be highlighted and an explanatory tooltip is made visible. + - The feature may be disabled and is exposed in Demo->Tools menu. + - I've been wanting to add this tool for a long time, but was stalled by finding a way to + not make it spammy + make it practically zero cost. After @pthom made various proposals to + solve the same problem (thanks for pushing me!), I decided it was time to finish it. + - Added ImGuiItemFlags_AllowDuplicateId to use with PushItemFlag/PopItemFlag() if for some + reason you intend to have duplicate identifiers. + - (#74, #96, #480, #501, #647, #654, #719, #843, #894, #1057, #1173, #1390, #1414, #1556, #1768, + #2041, #2116, #2330, #2475, #2562, #2667, #2807, #2885, #3102, #3375, #3526, #3964, #4008, + #4070, #4158, #4172, #4199, #4375, #4395, #4471, #4548, #4612, #4631, #4657, #4796, #5210, + #5303, #5360, #5393, #5533, #5692, #5707, #5729, #5773, #5787, #5884, #6046, #6093, #6186, + #6223, #6364, #6387, #6567, #6692, #6724, #6939, #6984, #7246, #7270, #7375, #7421, #7434, + #7472, #7581, #7724, #7926, #7937 and probably more..) - Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439) - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow. - TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660) diff --git a/docs/FAQ.md b/docs/FAQ.md index d53a5a099cc5..4e2a42576352 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -204,10 +204,11 @@ ctx->RSSetScissorRects(1, &r); ### Q: How can I have multiple widgets with the same label? ### Q: How can I have multiple windows with the same label? -**USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE:** +**USING THE SAME LABEL+ID IS THE MOST COMMON USER MISTAKE!** +
**USING AN EMPTY LABEL IS THE SAME AS USING THE SAME LABEL AS YOUR PARENT WIDGET!** - + - +
 ImGui::Begin("Incorrect!");
diff --git a/imgui.cpp b/imgui.cpp
index 1d9d8b899efe..e6cf5ca45ac9 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1395,6 +1395,8 @@ ImGuiIO::ImGuiIO()
     ConfigWindowsResizeFromEdges = true;
     ConfigWindowsMoveFromTitleBarOnly = false;
     ConfigMemoryCompactTimer = 60.0f;
+    ConfigDebugIsDebuggerPresent = false;
+    ConfigDebugHighlightIdConflicts = true;
     ConfigDebugBeginReturnValueOnce = false;
     ConfigDebugBeginReturnValueLoop = false;
 
@@ -4290,6 +4292,17 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
 {
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
+
+    // Detect ID conflicts
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
+    if (id != 0 && g.HoveredIdPreviousFrame == id && (item_flags & ImGuiItemFlags_AllowDuplicateId) == 0)
+    {
+        g.HoveredIdPreviousFrameItemCount++;
+        if (g.DebugDrawIdConflicts == id)
+            window->DrawList->AddRect(bb.Min - ImVec2(1,1), bb.Max + ImVec2(1,1), IM_COL32(255, 0, 0, 255), 0.0f, ImDrawFlags_None, 2.0f);
+    }
+#endif
+
     if (g.HoveredWindow != window)
         return false;
     if (!IsMouseHoveringRect(bb.Min, bb.Max))
@@ -4833,6 +4846,11 @@ void ImGui::NewFrame()
     if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId)
         KeepAliveID(g.DragDropPayload.SourceId);
 
+    // [DEBUG]
+    g.DebugDrawIdConflicts = 0;
+    if (g.IO.ConfigDebugHighlightIdConflicts && g.HoveredIdPreviousFrameItemCount > 1)
+        g.DebugDrawIdConflicts = g.HoveredIdPreviousFrame;
+
     // Update HoveredId data
     if (!g.HoveredIdPreviousFrame)
         g.HoveredIdTimer = 0.0f;
@@ -4843,6 +4861,7 @@ void ImGui::NewFrame()
     if (g.HoveredId && g.ActiveId != g.HoveredId)
         g.HoveredIdNotActiveTimer += g.IO.DeltaTime;
     g.HoveredIdPreviousFrame = g.HoveredId;
+    g.HoveredIdPreviousFrameItemCount = 0;
     g.HoveredId = 0;
     g.HoveredIdAllowOverlap = false;
     g.HoveredIdIsDisabled = false;
@@ -5235,6 +5254,29 @@ void ImGui::EndFrame()
         return;
     IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?");
 
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
+    if (g.DebugDrawIdConflicts != 0)
+    {
+        PushStyleColor(ImGuiCol_PopupBg, ImLerp(g.Style.Colors[ImGuiCol_PopupBg], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.10f));
+        if (g.DebugItemPickerActive == false && BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
+        {
+            SeparatorText("MESSAGE FROM DEAR IMGUI");
+            Text("Programmer error: %d visible items with conflicting ID!", g.HoveredIdPreviousFrameItemCount);
+            BulletText("Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
+            BulletText("Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
+            BulletText("Press F1 to open \"FAQ -> About the ID Stack System\" and read details.");
+            BulletText("Press CTRL+P to activate Item Picker and debug-break in item call-stack.");
+            BulletText("Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
+            EndTooltip();
+        }
+        PopStyleColor();
+        if (Shortcut(ImGuiMod_Ctrl | ImGuiKey_P, ImGuiInputFlags_RouteGlobal))
+            DebugStartItemPicker();
+        if (Shortcut(ImGuiKey_F1, ImGuiInputFlags_RouteGlobal) && g.PlatformIO.Platform_OpenInShellFn != NULL)
+            g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
+    }
+#endif
+
     CallContextHooks(&g, ImGuiContextHookType_EndFramePre);
 
     ErrorCheckEndFrameSanityChecks();
diff --git a/imgui.h b/imgui.h
index 18efaff42419..ebb156d4b5ac 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.2 WIP"
-#define IMGUI_VERSION_NUM   19112
+#define IMGUI_VERSION_NUM   19113
 #define IMGUI_HAS_TABLE
 
 /*
@@ -1135,6 +1135,7 @@ enum ImGuiItemFlags_
     ImGuiItemFlags_NoNavDefaultFocus        = 1 << 2,   // false    // Disable item being a candidate for default focus (e.g. used by title bar items).
     ImGuiItemFlags_ButtonRepeat             = 1 << 3,   // false    // Any button-like behavior will have repeat mode enabled (based on io.KeyRepeatDelay and io.KeyRepeatRate values). Note that you can also call IsItemActive() after any button to tell if it is being held.
     ImGuiItemFlags_AutoClosePopups          = 1 << 4,   // true     // MenuItem()/Selectable() automatically close their parent popup window.
+    ImGuiItemFlags_AllowDuplicateId         = 1 << 5,   // false    // Allow submitting an item with the same identifier as an item already submitted this frame without triggering a warning tooltip if io.ConfigDebugHighlightIdConflicts is set.
 };
 
 // Flags for ImGui::InputText()
@@ -2231,6 +2232,7 @@ struct ImGuiIO
     const char* LogFilename;                    // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified).
     void*       UserData;                       // = NULL           // Store your own data.
 
+    // Font system
     ImFontAtlas*Fonts;                          //            // Font atlas: load, rasterize and pack one or more fonts into a single texture.
     float       FontGlobalScale;                // = 1.0f           // Global scale all fonts
     bool        FontAllowUserScaling;           // = false          // Allow user scaling text of individual window with CTRL+Wheel.
@@ -2238,6 +2240,7 @@ struct ImGuiIO
     ImVec2      DisplayFramebufferScale;        // = (1, 1)         // For retina display or other situations where window coordinates are different from framebuffer coordinates. This generally ends up in ImDrawData::FramebufferScale.
 
     // Miscellaneous options
+    // (you can visualize and interact with all options in 'Demo->Configuration')
     bool        MouseDrawCursor;                // = false          // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
     bool        ConfigMacOSXBehaviors;          // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
     bool        ConfigNavSwapGamepadButtons;    // = false          // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
@@ -2267,6 +2270,12 @@ struct ImGuiIO
     //   e.g. io.ConfigDebugIsDebuggerPresent = ::IsDebuggerPresent() on Win32, or refer to ImOsIsDebuggerPresent() imgui_test_engine/imgui_te_utils.cpp for a Unix compatible version).
     bool        ConfigDebugIsDebuggerPresent;   // = false          // Enable various tools calling IM_DEBUG_BREAK().
 
+    // Tools to detect code submitting items with conflicting/duplicate IDs
+    // - Code should use PushID()/PopID() in loops, or append "##xx" to same-label identifiers.
+    // - Empty label e.g. Button("") == same ID as parent widget/node. Use Button("##xx") instead!
+    // - See FAQ https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-about-the-id-stack-system
+    bool        ConfigDebugHighlightIdConflicts;// = true           // Highlight and show an error message when multiple items have conflicting identifiers.
+
     // Tools to test correct Begin/End and BeginChild/EndChild behaviors.
     // - Presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX()
     // - This is inconsistent with other BeginXXX functions and create confusion for many users.
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 65204951311c..8c9745dfbfce 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -546,6 +546,8 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::SeparatorText("Debug");
             ImGui::Checkbox("io.ConfigDebugIsDebuggerPresent", &io.ConfigDebugIsDebuggerPresent);
             ImGui::SameLine(); HelpMarker("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.");
+            ImGui::Checkbox("io.ConfigDebugHighlightIdConflicts", &io.ConfigDebugHighlightIdConflicts);
+            ImGui::SameLine(); HelpMarker("Highlight and show an error message when multiple items have conflicting identifiers.");
             ImGui::BeginDisabled();
             ImGui::Checkbox("io.ConfigDebugBeginReturnValueOnce", &io.ConfigDebugBeginReturnValueOnce);
             ImGui::EndDisabled();
@@ -684,6 +686,7 @@ static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
         if (ImGui::BeginMenu("Tools"))
         {
             IMGUI_DEMO_MARKER("Menu/Tools");
+            ImGuiIO& io = ImGui::GetIO();
 #ifndef IMGUI_DISABLE_DEBUG_TOOLS
             const bool has_debug_tools = true;
 #else
@@ -692,14 +695,16 @@ static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
             ImGui::MenuItem("Metrics/Debugger", NULL, &demo_data->ShowMetrics, has_debug_tools);
             ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools);
             ImGui::MenuItem("ID Stack Tool", NULL, &demo_data->ShowIDStackTool, has_debug_tools);
-            ImGui::MenuItem("Style Editor", NULL, &demo_data->ShowStyleEditor);
-            bool is_debugger_present = ImGui::GetIO().ConfigDebugIsDebuggerPresent;
+            bool is_debugger_present = io.ConfigDebugIsDebuggerPresent;
             if (ImGui::MenuItem("Item Picker", NULL, false, has_debug_tools && is_debugger_present))
                 ImGui::DebugStartItemPicker();
             if (!is_debugger_present)
                 ImGui::SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable the menu option to avoid casual users crashing the application.\n\nYou can however always access the Item Picker in Metrics->Tools.");
-            ImGui::Separator();
+            ImGui::MenuItem("Style Editor", NULL, &demo_data->ShowStyleEditor);
             ImGui::MenuItem("About Dear ImGui", NULL, &demo_data->ShowAbout);
+
+            ImGui::SeparatorText("Debug Options");
+            ImGui::MenuItem("Highlight ID Conflicts", NULL, &io.ConfigDebugHighlightIdConflicts, has_debug_tools);
             ImGui::EndMenu();
         }
         ImGui::EndMenuBar();
@@ -2596,7 +2601,10 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
         IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Drag to reorder items (simple)");
         if (ImGui::TreeNode("Drag to reorder items (simple)"))
         {
-            // FIXME: temporary ID Conflict during reordering as a same item may be submitting twice.
+            // FIXME: there is temporary (usually single-frame) ID Conflict during reordering as a same item may be submitting twice.
+            // This code was always slightly faulty but in a way which was not easily noticeable.
+            // Until we fix this, enable ImGuiItemFlags_AllowDuplicateId to disable detecting the issue.
+            ImGui::PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true);
 
             // Simple reordering
             HelpMarker(
@@ -2619,6 +2627,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
                     }
                 }
             }
+
+            ImGui::PopItemFlag();
             ImGui::TreePop();
         }
 
diff --git a/imgui_internal.h b/imgui_internal.h
index 1aa94ff3b25e..04dfba3b300f 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2042,9 +2042,11 @@ struct ImGuiContext
     ImVec2                  WheelingAxisAvg;
 
     // Item/widgets state and tracking information
+    ImGuiID                 DebugDrawIdConflicts;               // Set when we detect multiple items with the same identifier
     ImGuiID                 DebugHookIdInfo;                    // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
     ImGuiID                 HoveredId;                          // Hovered widget, filled during the frame
     ImGuiID                 HoveredIdPreviousFrame;
+    int                     HoveredIdPreviousFrameItemCount;    // Count numbers of items using the same ID as last frame's hovered id
     float                   HoveredIdTimer;                     // Measure contiguous hovering time
     float                   HoveredIdNotActiveTimer;            // Measure contiguous hovering time where the item has not been active
     bool                    HoveredIdAllowOverlap;
@@ -2365,8 +2367,10 @@ struct ImGuiContext
         WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1;
         WheelingWindowReleaseTimer = 0.0f;
 
+        DebugDrawIdConflicts = 0;
         DebugHookIdInfo = 0;
         HoveredId = HoveredIdPreviousFrame = 0;
+        HoveredIdPreviousFrameItemCount = 0;
         HoveredIdAllowOverlap = false;
         HoveredIdIsDisabled = false;
         HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 10cdf342840e..33af0686e831 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3551,6 +3551,8 @@ int ImParseFormatPrecision(const char* fmt, int default_precision)
 
 // Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets)
 // FIXME: Facilitate using this in variety of other situations.
+// FIXME: Among other things, setting ImGuiItemFlags_AllowDuplicateId in LastItemData is currently correct but
+// the expected relationship between TempInputXXX functions and LastItemData is a little fishy.
 bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags)
 {
     // On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id.
@@ -3561,6 +3563,7 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
         ClearActiveID();
 
     g.CurrentWindow->DC.CursorPos = bb.Min;
+    g.LastItemData.InFlags |= ImGuiItemFlags_AllowDuplicateId;
     bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_MergedItem);
     if (init)
     {

From abd07f6d30736c00fba899d41043a78a5de0f765 Mon Sep 17 00:00:00 2001
From: alektron 
Date: Tue, 27 Aug 2024 01:37:50 +0200
Subject: [PATCH 112/548] InputText: added native support for UTF-8 text
 editing and god rid of the wchar buffer. (#7925)

WIP (requires subsequent commits for fixes)
---
 imgui.cpp         |   2 +-
 imgui_internal.h  |  11 +-
 imgui_widgets.cpp | 278 +++++++++++++++++++++++++---------------------
 imstb_textedit.h  |  54 +++++----
 4 files changed, 189 insertions(+), 156 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index e6cf5ca45ac9..71b1b10110ef 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1975,7 +1975,7 @@ const char* ImStreolRange(const char* str, const char* str_end)
     return p ? p : str_end;
 }
 
-const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line
+const char* ImStrbol(const char* buf_mid_line, const char* buf_begin) // find beginning-of-line
 {
     while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
         buf_mid_line--;
diff --git a/imgui_internal.h b/imgui_internal.h
index 04dfba3b300f..ec4c069eb085 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -366,7 +366,7 @@ IMGUI_API const char*   ImStristr(const char* haystack, const char* haystack_end
 IMGUI_API void          ImStrTrimBlanks(char* str);                                         // Remove leading and trailing blanks from a buffer.
 IMGUI_API const char*   ImStrSkipBlank(const char* str);                                    // Find first non-blank character.
 IMGUI_API int           ImStrlenW(const ImWchar* str);                                      // Computer string length (ImWchar string)
-IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin);   // Find beginning-of-line (ImWchar string)
+IMGUI_API const char*   ImStrbol(const char* buf_mid_line, const char* buf_begin);          // Find beginning-of-line
 IM_MSVC_RUNTIME_CHECKS_OFF
 static inline char      ImToUpper(char c)               { return (c >= 'a' && c <= 'z') ? c &= ~32 : c; }
 static inline bool      ImCharIsBlankA(char c)          { return c == ' ' || c == '\t'; }
@@ -1097,7 +1097,7 @@ struct IMGUI_API ImGuiInputTextDeactivatedState
 #undef IMSTB_TEXTEDIT_STRING
 #undef IMSTB_TEXTEDIT_CHARTYPE
 #define IMSTB_TEXTEDIT_STRING             ImGuiInputTextState
-#define IMSTB_TEXTEDIT_CHARTYPE           ImWchar
+#define IMSTB_TEXTEDIT_CHARTYPE           char
 #define IMSTB_TEXTEDIT_GETWIDTH_NEWLINE   (-1.0f)
 #define IMSTB_TEXTEDIT_UNDOSTATECOUNT     99
 #define IMSTB_TEXTEDIT_UNDOCHARCOUNT      999
@@ -1111,8 +1111,7 @@ struct IMGUI_API ImGuiInputTextState
     ImGuiContext*           Ctx;                    // parent UI context (needs to be set explicitly by parent).
     ImStbTexteditState*     Stb;                    // State for stb_textedit.h
     ImGuiID                 ID;                     // widget id owning the text state
-    int                     CurLenW, CurLenA;       // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not.
-    ImVector       TextW;                  // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
+    int                     CurLenA;                // UTF-8 length of the string in TextA (in bytes)
     ImVector          TextA;                  // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity.
     ImVector          InitialTextA;           // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
     bool                    TextAIsValid;           // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument)
@@ -1129,8 +1128,8 @@ struct IMGUI_API ImGuiInputTextState
 
     ImGuiInputTextState();
     ~ImGuiInputTextState();
-    void        ClearText()                 { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); }
-    void        ClearFreeMemory()           { TextW.clear(); TextA.clear(); InitialTextA.clear(); }
+    void        ClearText()                 { CurLenA = 0; TextA[0] = 0; CursorClamp(); }
+    void        ClearFreeMemory()           { TextA.clear(); InitialTextA.clear(); }
     void        OnKeyPressed(int key);      // Cannot be inline because we call in code in stb_textedit.h implementation
 
     // Cursor & Selection
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 33af0686e831..5a8721c78d91 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -128,7 +128,7 @@ static const ImU64          IM_U64_MAX = (2ULL * 9223372036854775807LL + 1);
 // For InputTextEx()
 static bool     InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, bool input_source_is_clipboard = false);
 static int      InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
-static ImVec2   InputTextCalcTextSizeW(ImGuiContext* ctx, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);
+static ImVec2   InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, const char* text_end, const char** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);
 
 //-------------------------------------------------------------------------
 // [SECTION] Widgets: Text, etc.
@@ -3836,7 +3836,7 @@ static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char**
     return line_count;
 }
 
-static ImVec2 InputTextCalcTextSizeW(ImGuiContext* ctx, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line)
+static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, const char* text_end, const char** remaining, ImVec2* out_offset, bool stop_on_new_line)
 {
     ImGuiContext& g = *ctx;
     ImFont* font = g.Font;
@@ -3846,10 +3846,11 @@ static ImVec2 InputTextCalcTextSizeW(ImGuiContext* ctx, const ImWchar* text_begi
     ImVec2 text_size = ImVec2(0, 0);
     float line_width = 0.0f;
 
-    const ImWchar* s = text_begin;
+    const char* s = text_begin;
     while (s < text_end)
     {
-        unsigned int c = (unsigned int)(*s++);
+        unsigned int c;
+        s += ImTextCharFromUtf8(&c, s, text_end);
         if (c == '\n')
         {
             text_size.x = ImMax(text_size.x, line_width);
@@ -3885,22 +3886,21 @@ static ImVec2 InputTextCalcTextSizeW(ImGuiContext* ctx, const ImWchar* text_begi
 namespace ImStb
 {
 
-static int     STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj)                             { return obj->CurLenW; }
-static ImWchar STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx <= obj->CurLenW); return obj->TextW[idx]; }
-static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance(c) * g.FontScale; }
+static int     STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj)                             { return obj->CurLenA; }
+static char    STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx <= obj->CurLenA); return obj->TextA[idx]; }
+static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->TextA.Size); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
 static int     STB_TEXTEDIT_KEYTOTEXT(int key)                                                    { return key >= 0x200000 ? 0 : key; }
-static ImWchar STB_TEXTEDIT_NEWLINE = '\n';
+static char    STB_TEXTEDIT_NEWLINE = '\n';
 static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
 {
-    const ImWchar* text = obj->TextW.Data;
-    const ImWchar* text_remaining = NULL;
-    const ImVec2 size = InputTextCalcTextSizeW(obj->Ctx, text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true);
+    const char* text_remaining = NULL;
+    const ImVec2 size = InputTextCalcTextSize(obj->Ctx, obj->TextA.Data + line_start_idx, obj->TextA.Data + obj->CurLenA, &text_remaining, NULL, true);
     r->x0 = 0.0f;
     r->x1 = size.x;
     r->baseline_y_delta = size.y;
     r->ymin = 0.0f;
     r->ymax = size.y;
-    r->num_chars = (int)(text_remaining - (text + line_start_idx));
+    r->num_chars = (int)(text_remaining - (obj->TextA.Data + line_start_idx));
 }
 
 static bool ImCharIsSeparatorW(unsigned int c)
@@ -3923,10 +3923,14 @@ static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
     if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
         return 0;
 
-    bool prev_white = ImCharIsBlankW(obj->TextW[idx - 1]);
-    bool prev_separ = ImCharIsSeparatorW(obj->TextW[idx - 1]);
-    bool curr_white = ImCharIsBlankW(obj->TextW[idx]);
-    bool curr_separ = ImCharIsSeparatorW(obj->TextW[idx]);
+    const char* prevPtr = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, obj->TextA.Data + idx);
+    unsigned int curr; ImTextCharFromUtf8(&curr, obj->TextA.Data + idx, obj->TextA.Data + obj->TextA.Size);
+    unsigned int prev; ImTextCharFromUtf8(&prev, prevPtr, obj->TextA.Data + obj->TextA.Size);
+
+    bool prev_white = ImCharIsBlankW(prev);
+    bool prev_separ = ImCharIsSeparatorW(prev);
+    bool curr_white = ImCharIsBlankW(curr);
+    bool curr_separ = ImCharIsSeparatorW(curr);
     return ((prev_white || prev_separ) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
 }
 static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
@@ -3934,63 +3938,108 @@ static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
     if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
         return 0;
 
-    bool prev_white = ImCharIsBlankW(obj->TextW[idx]);
-    bool prev_separ = ImCharIsSeparatorW(obj->TextW[idx]);
-    bool curr_white = ImCharIsBlankW(obj->TextW[idx - 1]);
-    bool curr_separ = ImCharIsSeparatorW(obj->TextW[idx - 1]);
+    const char* prevPtr = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, obj->TextA.Data + idx);
+    unsigned int prev; ImTextCharFromUtf8(&prev, obj->TextA.Data + idx, obj->TextA.Data + obj->TextA.Size);
+    unsigned int curr; ImTextCharFromUtf8(&curr, prevPtr, obj->TextA.Data + obj->TextA.Size);
+
+    bool prev_white = ImCharIsBlankW(prev);
+    bool prev_separ = ImCharIsSeparatorW(prev);
+    bool curr_white = ImCharIsBlankW(curr);
+    bool curr_separ = ImCharIsSeparatorW(curr);
     return ((prev_white) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
 }
 static int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx)   { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
-static int  STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx)   { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
-static int  STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx)   { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
+static int  STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx)   { idx++; int len = obj->CurLenA; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
+static int  STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx)   { idx++; int len = obj->CurLenA; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
 static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx)  { ImGuiContext& g = *obj->Ctx; if (g.IO.ConfigMacOSXBehaviors) return STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx); else return STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx); }
 #define STB_TEXTEDIT_MOVEWORDLEFT   STB_TEXTEDIT_MOVEWORDLEFT_IMPL  // They need to be #define for stb_textedit.h
 #define STB_TEXTEDIT_MOVEWORDRIGHT  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
+#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX  IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL
+#define IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX  IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX_IMPL
+
+static int IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
+{
+    unsigned int c;
+    return idx + ImTextCharFromUtf8(&c, obj->TextA.Data + idx, obj->TextA.Data + obj->TextA.Size);
+}
+
+static int CountLeadingHighBits(unsigned char b)
+{
+    for (int i = 0; i < (int)sizeof(b) * 8; i++)
+    {
+        bool set = (b >> (7 - i)) & 1;
+        if (!set)
+            return i;
+    }
+
+    return sizeof(b) * 8;
+}
+
+static int IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
+{
+    //Backwards check/count for UTF-8 multi byte sequence
+    int num_seq_bytes = 0;
+    for (int i = idx - 1; i >= 0; i -= 1)
+    {
+        bool is_seq_byte = (obj->TextA.Data[i] & 0x80) == 0x80 && (obj->TextA.Data[i] & 0x40) == 0;
+        num_seq_bytes += is_seq_byte;
+        if (!is_seq_byte)
+        {
+            if (num_seq_bytes > 0)
+            {
+                char initial_byte = obj->TextA.Data[i];
+                char num_leading_bits = (char)CountLeadingHighBits(initial_byte);
+                bool is_multi_byte_seq = num_leading_bits == num_seq_bytes + 1;
+                if (is_multi_byte_seq)
+                {
+                    return idx - (num_seq_bytes + 1);
+                }
+            }
+            break;
+        }
+    }
+    return idx - 1;
+}
 
 static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
 {
-    ImWchar* dst = obj->TextW.Data + pos;
+    char* dst = obj->TextA.Data + pos;
 
-    // We maintain our buffer length in both UTF-8 and wchar formats
     obj->Edited = true;
-    obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n);
-    obj->CurLenW -= n;
+    obj->CurLenA -= n;
 
     // Offset remaining text (FIXME-OPT: Use memmove)
-    const ImWchar* src = obj->TextW.Data + pos + n;
-    while (ImWchar c = *src++)
+    const char* src = obj->TextA.Data + pos + n;
+    while (char c = *src++)
         *dst++ = c;
     *dst = '\0';
 }
 
-static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ImWchar* new_text, int new_text_len)
+static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len)
 {
     const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
-    const int text_len = obj->CurLenW;
+    const int text_len = obj->CurLenA;
     IM_ASSERT(pos <= text_len);
 
-    const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);
-    if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA))
+    if (!is_resizable && (new_text_len + obj->CurLenA + 1 > obj->BufCapacityA))
         return false;
 
     // Grow internal buffer if needed
-    if (new_text_len + text_len + 1 > obj->TextW.Size)
+    if (new_text_len + text_len + 1 > obj->TextA.Size)
     {
         if (!is_resizable)
             return false;
-        IM_ASSERT(text_len < obj->TextW.Size);
-        obj->TextW.resize(text_len + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1);
+        obj->TextA.resize(text_len + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1);
     }
 
-    ImWchar* text = obj->TextW.Data;
+    char* text = obj->TextA.Data;
     if (pos != text_len)
-        memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar));
-    memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar));
+        memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos));
+    memcpy(text + pos, new_text, (size_t)new_text_len);
 
     obj->Edited = true;
-    obj->CurLenW += new_text_len;
-    obj->CurLenA += new_text_len_utf8;
-    obj->TextW[obj->CurLenW] = '\0';
+    obj->CurLenA += new_text_len;
+    obj->TextA[obj->CurLenA] = '\0';
 
     return true;
 }
@@ -4022,8 +4071,8 @@ static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const Im
 // the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?)
 static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
 {
-    stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len);
-    ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW);
+    stb_text_makeundo_replace(str, state, 0, str->CurLenA, text_len);
+    ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenA);
     state->cursor = state->select_start = state->select_end = 0;
     if (text_len <= 0)
         return;
@@ -4052,20 +4101,25 @@ ImGuiInputTextState::~ImGuiInputTextState()
 
 void ImGuiInputTextState::OnKeyPressed(int key)
 {
-    stb_textedit_key(this, Stb, key);
+    //We prematurely convert the key to a UTF8 byte sequence, even for keys where that doesn't even make sense (e.g. arrow keys).
+    //Not optimal but stb_textedit_key will only use the UTF8 values for valid character keys anyways.
+    //The changes we had to make to stb_textedit_key make it very much UTF8 specific which is not too great.
+    char utf8[5];
+    ImTextCharToUtf8(utf8, key);
+    stb_textedit_key(this, Stb, key, utf8, (int)strlen(utf8));
     CursorFollow = true;
     CursorAnimReset();
 }
 
 // Those functions are not inlined in imgui_internal.h, allowing us to hide ImStbTexteditState from that header.
 void ImGuiInputTextState::CursorAnimReset()                 { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
-void ImGuiInputTextState::CursorClamp()                     { Stb->cursor = ImMin(Stb->cursor, CurLenW); Stb->select_start = ImMin(Stb->select_start, CurLenW); Stb->select_end = ImMin(Stb->select_end, CurLenW); }
+void ImGuiInputTextState::CursorClamp()                     { Stb->cursor = ImMin(Stb->cursor, CurLenA); Stb->select_start = ImMin(Stb->select_start, CurLenA); Stb->select_end = ImMin(Stb->select_end, CurLenA); }
 bool ImGuiInputTextState::HasSelection() const              { return Stb->select_start != Stb->select_end; }
 void ImGuiInputTextState::ClearSelection()                  { Stb->select_start = Stb->select_end = Stb->cursor; }
 int  ImGuiInputTextState::GetCursorPos() const              { return Stb->cursor; }
 int  ImGuiInputTextState::GetSelectionStart() const         { return Stb->select_start; }
 int  ImGuiInputTextState::GetSelectionEnd() const           { return Stb->select_end; }
-void ImGuiInputTextState::SelectAll()                       { Stb->select_start = 0; Stb->cursor = Stb->select_end = CurLenW; Stb->has_preferred_x = 0; }
+void ImGuiInputTextState::SelectAll()                       { Stb->select_start = 0; Stb->cursor = Stb->select_end = CurLenA; Stb->has_preferred_x = 0; }
 void ImGuiInputTextState::ReloadUserBufAndSelectAll()       { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; }
 void ImGuiInputTextState::ReloadUserBufAndKeepSelection()   { ReloadUserBuf = true; ReloadSelectionStart = Stb->select_start; ReloadSelectionEnd = Stb->select_end; }
 void ImGuiInputTextState::ReloadUserBufAndMoveToEnd()       { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; }
@@ -4238,26 +4292,21 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im
 // FIXME: Ideally we should transition toward (1) making InsertChars()/DeleteChars() update undo-stack (2) discourage (and keep reconcile) or obsolete (and remove reconcile) accessing buffer directly.
 static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* state, const char* new_buf_a, int new_length_a)
 {
-    ImGuiContext& g = *GImGui;
-    const ImWchar* old_buf = state->TextW.Data;
-    const int old_length = state->CurLenW;
-    const int new_length = ImTextCountCharsFromUtf8(new_buf_a, new_buf_a + new_length_a);
-    g.TempBuffer.reserve_discard((new_length + 1) * sizeof(ImWchar));
-    ImWchar* new_buf = (ImWchar*)(void*)g.TempBuffer.Data;
-    ImTextStrFromUtf8(new_buf, new_length + 1, new_buf_a, new_buf_a + new_length_a);
-
-    const int shorter_length = ImMin(old_length, new_length);
+    const char* old_buf = state->TextA.Data;
+    const int old_length = state->CurLenA;
+
+    const int shorter_length = ImMin(old_length, new_length_a);
     int first_diff;
     for (first_diff = 0; first_diff < shorter_length; first_diff++)
-        if (old_buf[first_diff] != new_buf[first_diff])
+        if (old_buf[first_diff] != new_buf_a[first_diff])
             break;
-    if (first_diff == old_length && first_diff == new_length)
+    if (first_diff == old_length && first_diff == new_length_a)
         return;
 
-    int old_last_diff = old_length - 1;
-    int new_last_diff = new_length - 1;
+    int old_last_diff = old_length   - 1;
+    int new_last_diff = new_length_a - 1;
     for (; old_last_diff >= first_diff && new_last_diff >= first_diff; old_last_diff--, new_last_diff--)
-        if (old_buf[old_last_diff] != new_buf[new_last_diff])
+        if (old_buf[old_last_diff] != new_buf_a[new_last_diff])
             break;
 
     const int insert_len = new_last_diff - first_diff + 1;
@@ -4434,13 +4483,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             recycle_state = false;
 
         // Start edition
-        const char* buf_end = NULL;
         state->ID = id;
-        state->TextW.resize(buf_size + 1);          // wchar count <= UTF-8 count. we use +1 to make sure that .Data is always pointing to at least an empty string.
-        state->TextA.resize(0);
-        state->TextAIsValid = false;                // TextA is not valid yet (we will display buf until then)
-        state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, buf_size, buf, NULL, &buf_end);
-        state->CurLenA = (int)(buf_end - buf);      // We can't get the result from ImStrncpy() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
+        state->TextA.resize(buf_size + 1);          // we use +1 to make sure that .Data is always pointing to at least an empty string.
+        state->TextAIsValid = true;
+        state->CurLenA = (int)strlen(buf);
+        memcpy(state->TextA.Data, buf, state->CurLenA + 1);
 
         if (recycle_state)
         {
@@ -4522,18 +4569,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     bool value_changed = false;
     bool validated = false;
 
-    // When read-only we always use the live data passed to the function
-    // FIXME-OPT: Because our selection/cursor code currently needs the wide text we need to convert it when active, which is not ideal :(
-    if (is_readonly && state != NULL && (render_cursor || render_selection))
-    {
-        const char* buf_end = NULL;
-        state->TextW.resize(buf_size + 1);
-        state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, buf, NULL, &buf_end);
-        state->CurLenA = (int)(buf_end - buf);
-        state->CursorClamp();
-        render_selection &= state->HasSelection();
-    }
-
     // Select the buffer to render.
     const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state && state->TextAIsValid;
     const bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
@@ -4786,12 +4821,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             if (g.PlatformIO.Platform_SetClipboardTextFn != NULL)
             {
                 const int ib = state->HasSelection() ? ImMin(state->Stb->select_start, state->Stb->select_end) : 0;
-                const int ie = state->HasSelection() ? ImMax(state->Stb->select_start, state->Stb->select_end) : state->CurLenW;
-                const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1;
-                char* clipboard_data = (char*)IM_ALLOC(clipboard_data_len * sizeof(char));
-                ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie);
-                SetClipboardText(clipboard_data);
-                MemFree(clipboard_data);
+                const int ie = state->HasSelection() ? ImMax(state->Stb->select_start, state->Stb->select_end) : state->CurLenA;
+
+                char backup = state->TextA.Data[ie];
+                state->TextA.Data[ie] = 0; // A bit of a hack since SetClipboardText only takes null terminated strings
+                SetClipboardText(state->TextA.Data + ib);
+                state->TextA.Data[ie] = backup;
             }
             if (is_cut)
             {
@@ -4807,15 +4842,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             {
                 // Filter pasted buffer
                 const int clipboard_len = (int)strlen(clipboard);
-                ImWchar* clipboard_filtered = (ImWchar*)IM_ALLOC((clipboard_len + 1) * sizeof(ImWchar));
+                char* clipboard_filtered = (char*)IM_ALLOC((clipboard_len + 1));
                 int clipboard_filtered_len = 0;
                 for (const char* s = clipboard; *s != 0; )
                 {
                     unsigned int c;
-                    s += ImTextCharFromUtf8(&c, s, NULL);
+                    int len = ImTextCharFromUtf8(&c, s, NULL);
                     if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, true))
                         continue;
-                    clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;
+                    memcpy(clipboard_filtered + clipboard_filtered_len, s, len);
+                    clipboard_filtered_len += len;
+                    s += len;
                 }
                 clipboard_filtered[clipboard_filtered_len] = 0;
                 if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation
@@ -4851,29 +4888,16 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             }
             else if (strcmp(buf, state->InitialTextA.Data) != 0)
             {
-                // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents.
-                // Push records into the undo stack so we can CTRL+Z the revert operation itself
                 apply_new_text = state->InitialTextA.Data;
                 apply_new_text_length = state->InitialTextA.Size - 1;
+
+                // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents.
+                // Push records into the undo stack so we can CTRL+Z the revert operation itself
                 value_changed = true;
-                ImVector w_text;
-                if (apply_new_text_length > 0)
-                {
-                    w_text.resize(ImTextCountCharsFromUtf8(apply_new_text, apply_new_text + apply_new_text_length) + 1);
-                    ImTextStrFromUtf8(w_text.Data, w_text.Size, apply_new_text, apply_new_text + apply_new_text_length);
-                }
-                stb_textedit_replace(state, state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0);
+                stb_textedit_replace(state, state->Stb, state->InitialTextA.Data, state->InitialTextA.Size - 1);
             }
         }
 
-        // Apply ASCII value
-        if (!is_readonly)
-        {
-            state->TextAIsValid = true;
-            state->TextA.resize(state->TextW.Size * 4 + 1);
-            ImTextStrToUtf8(state->TextA.Data, state->TextA.Size, state->TextW.Data, NULL);
-        }
-
         // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer
         // before clearing ActiveId, even though strictly speaking it wasn't modified on this frame.
         // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail.
@@ -4935,11 +4959,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                     callback_data.BufSize = state->BufCapacityA;
                     callback_data.BufDirty = false;
 
-                    // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188)
-                    ImWchar* text = state->TextW.Data;
-                    const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + state->Stb->cursor);
-                    const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + state->Stb->select_start);
-                    const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + state->Stb->select_end);
+                    const int utf8_cursor_pos = callback_data.CursorPos = state->Stb->cursor;
+                    const int utf8_selection_start = callback_data.SelectionStart = state->Stb->select_start;
+                    const int utf8_selection_end = state->Stb->select_end;
 
                     // Call user code
                     callback(&callback_data);
@@ -4950,17 +4972,18 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                     IM_ASSERT(callback_data.BufSize == state->BufCapacityA);
                     IM_ASSERT(callback_data.Flags == flags);
                     const bool buf_dirty = callback_data.BufDirty;
-                    if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty)            { state->Stb->cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; }
-                    if (callback_data.SelectionStart != utf8_selection_start || buf_dirty)  { state->Stb->select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb->cursor : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); }
-                    if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty)      { state->Stb->select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb->select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
+                    if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty)            { state->Stb->cursor = callback_data.CursorPos; state->CursorFollow = true; }
+                    if (callback_data.SelectionStart != utf8_selection_start || buf_dirty)  { state->Stb->select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb->cursor : callback_data.SelectionStart; }
+                    if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty)      { state->Stb->select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb->select_start : callback_data.SelectionEnd; }
                     if (buf_dirty)
                     {
                         // Callback may update buffer and thus set buf_dirty even in read-only mode.
                         IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
                         InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ?
                         if (callback_data.BufTextLen > backup_current_text_length && is_resizable)
-                            state->TextW.resize(state->TextW.Size + (callback_data.BufTextLen - backup_current_text_length)); // Worse case scenario resize
-                        state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, callback_data.Buf, NULL);
+                            state->TextA.resize(state->TextA.Size + (callback_data.BufTextLen - backup_current_text_length)); // Worse case scenario resize
+
+                        memcpy(state->TextA.Data, callback_data.Buf, callback_data.BufTextLen);
                         state->CurLenA = callback_data.BufTextLen;  // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
                         state->CursorAnimReset();
                     }
@@ -5064,12 +5087,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         // - Measure text height (for scrollbar)
         // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
         // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
-        const ImWchar* text_begin = state->TextW.Data;
+        const char* text_begin = state->TextA.Data;
         ImVec2 cursor_offset, select_start_offset;
 
         {
             // Find lines numbers straddling 'cursor' (slot 0) and 'select_start' (slot 1) positions.
-            const ImWchar* searches_input_ptr[2] = { NULL, NULL };
+            const char* searches_input_ptr[2] = { NULL, NULL };
             int searches_result_line_no[2] = { -1000, -1000 };
             int searches_remaining = 0;
             if (render_cursor)
@@ -5090,7 +5113,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             searches_remaining += is_multiline ? 1 : 0;
             int line_count = 0;
             //for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++)  // FIXME-OPT: Could use this when wchar_t are 16-bit
-            for (const ImWchar* s = text_begin; *s != 0; s++)
+            for (const char* s = text_begin; *s != 0; s++)
                 if (*s == '\n')
                 {
                     line_count++;
@@ -5104,11 +5127,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                 searches_result_line_no[1] = line_count;
 
             // Calculate 2d position by finding the beginning of the line and measuring distance
-            cursor_offset.x = InputTextCalcTextSizeW(&g, ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
+            cursor_offset.x = InputTextCalcTextSize(&g, ImStrbol(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
             cursor_offset.y = searches_result_line_no[0] * g.FontSize;
             if (searches_result_line_no[1] >= 0)
             {
-                select_start_offset.x = InputTextCalcTextSizeW(&g, ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
+                select_start_offset.x = InputTextCalcTextSize(&g, ImStrbol(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
                 select_start_offset.y = searches_result_line_no[1] * g.FontSize;
             }
 
@@ -5156,14 +5179,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         const ImVec2 draw_scroll = ImVec2(state->Scroll.x, 0.0f);
         if (render_selection)
         {
-            const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end);
-            const ImWchar* text_selected_end = text_begin + ImMax(state->Stb->select_start, state->Stb->select_end);
+            const char* text_selected_begin = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end);
+            const char* text_selected_end = text_begin + ImMax(state->Stb->select_start, state->Stb->select_end);
 
             ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests.
             float bg_offy_up = is_multiline ? 0.0f : -1.0f;    // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection.
             float bg_offy_dn = is_multiline ? 0.0f : 2.0f;
             ImVec2 rect_pos = draw_pos + select_start_offset - draw_scroll;
-            for (const ImWchar* p = text_selected_begin; p < text_selected_end; )
+            for (const char* p = text_selected_begin; p < text_selected_end; )
             {
                 if (rect_pos.y > clip_rect.w + g.FontSize)
                     break;
@@ -5177,7 +5200,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                 }
                 else
                 {
-                    ImVec2 rect_size = InputTextCalcTextSizeW(&g, p, text_selected_end, &p, NULL, true);
+                    ImVec2 rect_size = InputTextCalcTextSize(&g, p, text_selected_end, &p, NULL, true);
                     if (rect_size.x <= 0.0f) rect_size.x = IM_TRUNC(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
                     ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn));
                     rect.ClipWith(clip_rect);
@@ -5282,7 +5305,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
     ImStb::StbUndoState* undo_state = &stb_state->undostate;
     Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId);
     DebugLocateItemOnHover(state->ID);
-    Text("CurLenW: %d, CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenW, state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end);
+    Text("CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end);
     Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x);
     Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point);
     if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 10), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY)) // Visualize undo state
@@ -5294,11 +5317,8 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
             const char undo_rec_type = (n < undo_state->undo_point) ? 'u' : (n >= undo_state->redo_point) ? 'r' : ' ';
             if (undo_rec_type == ' ')
                 BeginDisabled();
-            char buf[64] = "";
-            if (undo_rec_type != ' ' && undo_rec->char_storage != -1)
-                ImTextStrToUtf8(buf, IM_ARRAYSIZE(buf), undo_state->undo_char + undo_rec->char_storage, undo_state->undo_char + undo_rec->char_storage + undo_rec->insert_length);
-            Text("%c [%02d] where %03d, insert %03d, delete %03d, char_storage %03d \"%s\"",
-                undo_rec_type, n, undo_rec->where, undo_rec->insert_length, undo_rec->delete_length, undo_rec->char_storage, buf);
+            Text("%c [%02d] where %03d, insert %03d, delete %03d, char_storage %03d \"%.*s\"",
+                undo_rec_type, n, undo_rec->where, undo_rec->insert_length, undo_rec->delete_length, undo_rec->char_storage, undo_rec->insert_length, undo_state->undo_char + undo_rec->char_storage);
             if (undo_rec_type == ' ')
                 EndDisabled();
         }
diff --git a/imstb_textedit.h b/imstb_textedit.h
index faaf518f402b..28508607b4b4 100644
--- a/imstb_textedit.h
+++ b/imstb_textedit.h
@@ -4,6 +4,7 @@
 // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
 // - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
 // - Added name to struct or it may be forward declared in our code.
+// - Added UTF8 support https://github.com/nothings/stb/issues/188
 // Grep for [DEAR IMGUI] to find the changes.
 // - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
 
@@ -439,13 +440,13 @@ static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y)
    if (x < r.x1) {
       // search characters in row for one that straddles 'x'
       prev_x = r.x0;
-      for (k=0; k < r.num_chars; ++k) {
+      for (k=0; k < r.num_chars; k = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k) - i) {
          float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
          if (x < prev_x+w) {
             if (x < prev_x+w/2)
                return k+i;
             else
-               return k+i+1;
+               return IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, i + k);
          }
          prev_x += w;
       }
@@ -564,7 +565,7 @@ static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING
 
    // now scan to find xpos
    find->x = r.x0;
-   for (i=0; first+i < n; ++i)
+   for (i=0; first+i < n; i = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, first + i) - first)
       find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
 }
 
@@ -641,6 +642,17 @@ static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditSt
    }
 }
 
+//[DEAR IMGUI]
+//Functions must be implemented for UTF8 support
+//Code in this file that uses them, is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
+//There is not necessarily a '[DEAR IMGUI]' at the usage sites
+#ifndef IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX
+#define IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX(obj, idx) idx - 1
+#endif
+#ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
+#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) idx + 1
+#endif
+
 #ifdef STB_TEXTEDIT_IS_SPACE
 static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx )
 {
@@ -722,15 +734,16 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
 #endif
 
 // API key: process a keyboard input
-static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
+//[DEAR IMGUI] In addition to the key we also pass in the decoded UTF8 byte sequence, if it is a character key.
+//This is a bit ugly and only makes sense for UTF8. One could think of other solutions that wouldn't make this function so UTF8 specific.
+//If the idea is to push the changes upstream to stb_textedit it might be worth thinking about but since this is just for [DEAR IMGUI], it might not be worth the complication
+static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key, const IMSTB_TEXTEDIT_CHARTYPE* decoded, int decoded_size)
 {
 retry:
    switch (key) {
       default: {
          int c = STB_TEXTEDIT_KEYTOTEXT(key);
          if (c > 0) {
-            IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE) c;
-
             // can't add newline in single-line mode
             if (c == '\n' && state->single_line)
                break;
@@ -738,15 +751,15 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
             if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
                stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
                STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
-               if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
-                  ++state->cursor;
+               if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, decoded, decoded_size)) {
+                  state->cursor += decoded_size;
                   state->has_preferred_x = 0;
                }
             } else {
                stb_textedit_delete_selection(str,state); // implicitly clamps
-               if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
-                  stb_text_makeundo_insert(state, state->cursor, 1);
-                  ++state->cursor;
+               if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, decoded, decoded_size)) {
+                  stb_text_makeundo_insert(state, state->cursor, decoded_size);
+                  state->cursor += decoded_size;
                   state->has_preferred_x = 0;
                }
             }
@@ -776,7 +789,7 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
             stb_textedit_move_to_first(state);
          else
             if (state->cursor > 0)
-               --state->cursor;
+               state->cursor = IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX(str, state->cursor);
          state->has_preferred_x = 0;
          break;
 
@@ -785,7 +798,7 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
          if (STB_TEXT_HAS_SELECTION(state))
             stb_textedit_move_to_last(str, state);
          else
-            ++state->cursor;
+            state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
          stb_textedit_clamp(str, state);
          state->has_preferred_x = 0;
          break;
@@ -795,7 +808,7 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
          stb_textedit_prep_selection_at_cursor(state);
          // move selection left
          if (state->select_end > 0)
-            --state->select_end;
+            state->select_end = IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX(str, state->select_end);
          state->cursor = state->select_end;
          state->has_preferred_x = 0;
          break;
@@ -845,7 +858,7 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
       case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
          stb_textedit_prep_selection_at_cursor(state);
          // move selection right
-         ++state->select_end;
+         state->select_end = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->select_end);
          stb_textedit_clamp(str, state);
          state->cursor = state->select_end;
          state->has_preferred_x = 0;
@@ -901,7 +914,7 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
                x += dx;
                if (x > goal_x)
                   break;
-               ++state->cursor;
+               state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
             }
             stb_textedit_clamp(str, state);
 
@@ -963,7 +976,7 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
                x += dx;
                if (x > goal_x)
                   break;
-               ++state->cursor;
+               state->cursor = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor);
             }
             stb_textedit_clamp(str, state);
 
@@ -991,7 +1004,7 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
          else {
             int n = STB_TEXTEDIT_STRINGLEN(str);
             if (state->cursor < n)
-               stb_textedit_delete(str, state, state->cursor, 1);
+               stb_textedit_delete(str, state, state->cursor, IMSTB_TEXTEDIT_GETNEXTCHARINDEX(str, state->cursor) - state->cursor);
          }
          state->has_preferred_x = 0;
          break;
@@ -1003,8 +1016,9 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
          else {
             stb_textedit_clamp(str, state);
             if (state->cursor > 0) {
-               stb_textedit_delete(str, state, state->cursor-1, 1);
-               --state->cursor;
+               int prev = IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX(str, state->cursor);
+               stb_textedit_delete(str, state, prev, state->cursor - prev);
+               state->cursor = prev;
             }
          }
          state->has_preferred_x = 0;

From d1b7817959245230e0ef24f8c9886c0e6d0d1396 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 5 Sep 2024 15:25:30 +0200
Subject: [PATCH 113/548] InputText: amends: renames, coding style. (#7925)

---
 imgui.h           |  2 +-
 imgui_internal.h  |  1 -
 imgui_widgets.cpp | 17 ++++++++---------
 imstb_textedit.h  | 22 +++++++++++-----------
 4 files changed, 20 insertions(+), 22 deletions(-)

diff --git a/imgui.h b/imgui.h
index ebb156d4b5ac..095c250025e4 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.2 WIP"
-#define IMGUI_VERSION_NUM   19113
+#define IMGUI_VERSION_NUM   19114
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index ec4c069eb085..4dfcfce9af16 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1114,7 +1114,6 @@ struct IMGUI_API ImGuiInputTextState
     int                     CurLenA;                // UTF-8 length of the string in TextA (in bytes)
     ImVector          TextA;                  // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity.
     ImVector          InitialTextA;           // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
-    bool                    TextAIsValid;           // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument)
     int                     BufCapacityA;           // end-user buffer capacity
     ImVec2                  Scroll;                 // horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y)
     float                   CursorAnim;             // timer for cursor blink, reset on every user action so the cursor reappears immediately
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 5a8721c78d91..64e70140754a 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3952,10 +3952,10 @@ static int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx)
 static int  STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx)   { idx++; int len = obj->CurLenA; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
 static int  STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx)   { idx++; int len = obj->CurLenA; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
 static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx)  { ImGuiContext& g = *obj->Ctx; if (g.IO.ConfigMacOSXBehaviors) return STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx); else return STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx); }
-#define STB_TEXTEDIT_MOVEWORDLEFT   STB_TEXTEDIT_MOVEWORDLEFT_IMPL  // They need to be #define for stb_textedit.h
-#define STB_TEXTEDIT_MOVEWORDRIGHT  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
+#define STB_TEXTEDIT_MOVEWORDLEFT       STB_TEXTEDIT_MOVEWORDLEFT_IMPL  // They need to be #define for stb_textedit.h
+#define STB_TEXTEDIT_MOVEWORDRIGHT      STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
 #define IMSTB_TEXTEDIT_GETNEXTCHARINDEX  IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL
-#define IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX  IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX_IMPL
+#define IMSTB_TEXTEDIT_GETPREVCHARINDEX  IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL
 
 static int IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
 {
@@ -3975,9 +3975,9 @@ static int CountLeadingHighBits(unsigned char b)
     return sizeof(b) * 8;
 }
 
-static int IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
+static int IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
 {
-    //Backwards check/count for UTF-8 multi byte sequence
+    // Backwards check/count for UTF-8 multi byte sequence
     int num_seq_bytes = 0;
     for (int i = idx - 1; i >= 0; i -= 1)
     {
@@ -4479,13 +4479,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         // Preserve cursor position and undo/redo stack if we come back to same widget
         // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
         bool recycle_state = (state->ID == id && !init_changed_specs && !init_reload_from_user_buf);
-        if (recycle_state && (state->CurLenA != buf_len || (state->TextAIsValid && strncmp(state->TextA.Data, buf, buf_len) != 0)))
+        if (recycle_state && (state->CurLenA != buf_len || (strncmp(state->TextA.Data, buf, buf_len) != 0)))
             recycle_state = false;
 
         // Start edition
         state->ID = id;
         state->TextA.resize(buf_size + 1);          // we use +1 to make sure that .Data is always pointing to at least an empty string.
-        state->TextAIsValid = true;
         state->CurLenA = (int)strlen(buf);
         memcpy(state->TextA.Data, buf, state->CurLenA + 1);
 
@@ -4570,7 +4569,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     bool validated = false;
 
     // Select the buffer to render.
-    const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state && state->TextAIsValid;
+    const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state;
     const bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
 
     // Password pushes a temporary font with only a fallback glyph
@@ -4842,7 +4841,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             {
                 // Filter pasted buffer
                 const int clipboard_len = (int)strlen(clipboard);
-                char* clipboard_filtered = (char*)IM_ALLOC((clipboard_len + 1));
+                char* clipboard_filtered = (char*)IM_ALLOC(clipboard_len + 1);
                 int clipboard_filtered_len = 0;
                 for (const char* s = clipboard; *s != 0; )
                 {
diff --git a/imstb_textedit.h b/imstb_textedit.h
index 28508607b4b4..22122c08b614 100644
--- a/imstb_textedit.h
+++ b/imstb_textedit.h
@@ -4,7 +4,7 @@
 // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
 // - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783)
 // - Added name to struct or it may be forward declared in our code.
-// - Added UTF8 support https://github.com/nothings/stb/issues/188
+// - Added UTF-8 support (see https://github.com/nothings/stb/issues/188 + https://github.com/ocornut/imgui/pull/7925)
 // Grep for [DEAR IMGUI] to find the changes.
 // - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_*
 
@@ -642,15 +642,15 @@ static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditSt
    }
 }
 
-//[DEAR IMGUI]
-//Functions must be implemented for UTF8 support
-//Code in this file that uses them, is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
-//There is not necessarily a '[DEAR IMGUI]' at the usage sites
-#ifndef IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX
-#define IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX(obj, idx) idx - 1
+// [DEAR IMGUI]
+// Functions must be implemented for UTF8 support
+// Code in this file that uses those functions is modified for [DEAR IMGUI] and deviates from the original stb_textedit.
+// There is not necessarily a '[DEAR IMGUI]' at the usage sites.
+#ifndef IMSTB_TEXTEDIT_GETPREVCHARINDEX
+#define IMSTB_TEXTEDIT_GETPREVCHARINDEX(obj, idx) (idx - 1)
 #endif
 #ifndef IMSTB_TEXTEDIT_GETNEXTCHARINDEX
-#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) idx + 1
+#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx) (idx + 1)
 #endif
 
 #ifdef STB_TEXTEDIT_IS_SPACE
@@ -789,7 +789,7 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
             stb_textedit_move_to_first(state);
          else
             if (state->cursor > 0)
-               state->cursor = IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX(str, state->cursor);
+               state->cursor = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
          state->has_preferred_x = 0;
          break;
 
@@ -808,7 +808,7 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
          stb_textedit_prep_selection_at_cursor(state);
          // move selection left
          if (state->select_end > 0)
-            state->select_end = IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX(str, state->select_end);
+            state->select_end = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->select_end);
          state->cursor = state->select_end;
          state->has_preferred_x = 0;
          break;
@@ -1016,7 +1016,7 @@ static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *stat
          else {
             stb_textedit_clamp(str, state);
             if (state->cursor > 0) {
-               int prev = IMSTB_TEXTEDIT_GETPREVIOUSCHARINDEX(str, state->cursor);
+               int prev = IMSTB_TEXTEDIT_GETPREVCHARINDEX(str, state->cursor);
                stb_textedit_delete(str, state, prev, state->cursor - prev);
                state->cursor = prev;
             }

From 1674fe96ff57e4540b6c1860e61aa7fcc06642fe Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 5 Sep 2024 16:31:41 +0200
Subject: [PATCH 114/548] InputText: amends: add stb_textedit_text() api.
 (#7925)

It seems sensible to push this change in stb_textedit repo eventually.
---
 imgui_internal.h  |  1 +
 imgui_widgets.cpp | 23 +++++++++++-------
 imstb_textedit.h  | 61 ++++++++++++++++++++++++++++-------------------
 3 files changed, 52 insertions(+), 33 deletions(-)

diff --git a/imgui_internal.h b/imgui_internal.h
index 4dfcfce9af16..e6f3f8ec56b0 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1130,6 +1130,7 @@ struct IMGUI_API ImGuiInputTextState
     void        ClearText()                 { CurLenA = 0; TextA[0] = 0; CursorClamp(); }
     void        ClearFreeMemory()           { TextA.clear(); InitialTextA.clear(); }
     void        OnKeyPressed(int key);      // Cannot be inline because we call in code in stb_textedit.h implementation
+    void        OnCharPressed(unsigned int c);
 
     // Cursor & Selection
     void        CursorAnimReset();
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 64e70140754a..f355631199f1 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3889,7 +3889,6 @@ namespace ImStb
 static int     STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj)                             { return obj->CurLenA; }
 static char    STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx <= obj->CurLenA); return obj->TextA[idx]; }
 static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->TextA.Size); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
-static int     STB_TEXTEDIT_KEYTOTEXT(int key)                                                    { return key >= 0x200000 ? 0 : key; }
 static char    STB_TEXTEDIT_NEWLINE = '\n';
 static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
 {
@@ -4101,12 +4100,18 @@ ImGuiInputTextState::~ImGuiInputTextState()
 
 void ImGuiInputTextState::OnKeyPressed(int key)
 {
-    //We prematurely convert the key to a UTF8 byte sequence, even for keys where that doesn't even make sense (e.g. arrow keys).
-    //Not optimal but stb_textedit_key will only use the UTF8 values for valid character keys anyways.
-    //The changes we had to make to stb_textedit_key make it very much UTF8 specific which is not too great.
+    stb_textedit_key(this, Stb, key);
+    CursorFollow = true;
+    CursorAnimReset();
+}
+
+void ImGuiInputTextState::OnCharPressed(unsigned int c)
+{
+    // Convert the key to a UTF8 byte sequence.
+    // The changes we had to make to stb_textedit_key made it very much UTF-8 specific which is not too great.
     char utf8[5];
-    ImTextCharToUtf8(utf8, key);
-    stb_textedit_key(this, Stb, key, utf8, (int)strlen(utf8));
+    ImTextCharToUtf8(utf8, c);
+    stb_textedit_text(this, Stb, utf8, (int)strlen(utf8));
     CursorFollow = true;
     CursorAnimReset();
 }
@@ -4674,7 +4679,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             {
                 unsigned int c = '\t'; // Insert TAB
                 if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
-                    state->OnKeyPressed((int)c);
+                    state->OnCharPressed(c);
             }
             // FIXME: Implement Shift+Tab
             /*
@@ -4697,7 +4702,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                     if (c == '\t') // Skip Tab, see above.
                         continue;
                     if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
-                        state->OnKeyPressed((int)c);
+                        state->OnCharPressed(c);
                 }
 
             // Consume characters
@@ -4781,7 +4786,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             {
                 unsigned int c = '\n'; // Insert new line
                 if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
-                    state->OnKeyPressed((int)c);
+                    state->OnCharPressed(c);
             }
         }
         else if (is_cancel)
diff --git a/imstb_textedit.h b/imstb_textedit.h
index 22122c08b614..b7a761c85381 100644
--- a/imstb_textedit.h
+++ b/imstb_textedit.h
@@ -211,6 +211,7 @@
 //    int  stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
 //    int  stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
 //    void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
+//    void stb_textedit_text(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int text_len)
 //
 //    Each of these functions potentially updates the string and updates the
 //    state.
@@ -245,7 +246,12 @@
 //          various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
 //          set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
 //          clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
-//          anything other type you wante before including.
+//          anything other type you want before including.
+//          if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are
+//          transformed into text and stb_textedit_text() is automatically called.
+//
+//      text: [DEAR IMGUI] added 2024-09
+//          call this to text inputs sent to the textfield.
 //
 //
 //   When rendering, you can read the cursor position and selection state from
@@ -733,37 +739,44 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
 #define STB_TEXTEDIT_KEYTYPE int
 #endif
 
+// [DEAR IMGUI] Added stb_textedit_text(), extracted out and called by stb_textedit_key() for backward compatibility.
+static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
+{
+   // can't add newline in single-line mode
+   if (text[0] == '\n' && state->single_line)
+      return;
+
+   if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
+      stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
+      STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
+      if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
+         state->cursor += text_len;
+         state->has_preferred_x = 0;
+      }
+   }
+   else {
+      stb_textedit_delete_selection(str, state); // implicitly clamps
+      if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
+         stb_text_makeundo_insert(state, state->cursor, text_len);
+         state->cursor += text_len;
+         state->has_preferred_x = 0;
+      }
+   }
+}
+
 // API key: process a keyboard input
-//[DEAR IMGUI] In addition to the key we also pass in the decoded UTF8 byte sequence, if it is a character key.
-//This is a bit ugly and only makes sense for UTF8. One could think of other solutions that wouldn't make this function so UTF8 specific.
-//If the idea is to push the changes upstream to stb_textedit it might be worth thinking about but since this is just for [DEAR IMGUI], it might not be worth the complication
-static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key, const IMSTB_TEXTEDIT_CHARTYPE* decoded, int decoded_size)
+static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
 {
 retry:
    switch (key) {
       default: {
+#ifdef STB_TEXTEDIT_KEYTOTEXT
          int c = STB_TEXTEDIT_KEYTOTEXT(key);
          if (c > 0) {
-            // can't add newline in single-line mode
-            if (c == '\n' && state->single_line)
-               break;
-
-            if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
-               stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
-               STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
-               if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, decoded, decoded_size)) {
-                  state->cursor += decoded_size;
-                  state->has_preferred_x = 0;
-               }
-            } else {
-               stb_textedit_delete_selection(str,state); // implicitly clamps
-               if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, decoded, decoded_size)) {
-                  stb_text_makeundo_insert(state, state->cursor, decoded_size);
-                  state->cursor += decoded_size;
-                  state->has_preferred_x = 0;
-               }
-            }
+            IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c;
+            stb_textedit_text(str, state, &ch, 1);
          }
+#endif
          break;
       }
 

From e240bc151a3650be8af0ea9d426d4fb44914c7e0 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 5 Sep 2024 16:29:30 +0200
Subject: [PATCH 115/548] InputText: amends: add note about
 STB_TEXTEDIT_GETCHAR. tweak InputTextCalcTextSize() to use similar
 debug-friendly logic as ImFont:CalcTextSizeA(). misc small tidying up.
 (#7925)

---
 imgui_widgets.cpp | 51 ++++++++++++++++++++++++++++-------------------
 1 file changed, 31 insertions(+), 20 deletions(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index f355631199f1..6d701d03be60 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3836,6 +3836,7 @@ static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char**
     return line_count;
 }
 
+// FIXME: Ideally we'd share code with ImFont::CalcTextSizeA()
 static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, const char* text_end, const char** remaining, ImVec2* out_offset, bool stop_on_new_line)
 {
     ImGuiContext& g = *ctx;
@@ -3849,8 +3850,12 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
     const char* s = text_begin;
     while (s < text_end)
     {
-        unsigned int c;
-        s += ImTextCharFromUtf8(&c, s, text_end);
+        unsigned int c = (unsigned int)*s;
+        if (c < 0x80)
+            s += 1;
+        else
+            s += ImTextCharFromUtf8(&c, s, text_end);
+
         if (c == '\n')
         {
             text_size.x = ImMax(text_size.x, line_width);
@@ -3863,7 +3868,7 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
         if (c == '\r')
             continue;
 
-        const float char_width = font->GetCharAdvance((ImWchar)c) * scale;
+        const float char_width = ((int)c < font->IndexAdvanceX.Size ? font->IndexAdvanceX.Data[c] : font->FallbackAdvanceX) * scale;
         line_width += char_width;
     }
 
@@ -3883,23 +3888,27 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
 }
 
 // Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar)
+// With our UTF-8 use of stb_textedit:
+// - STB_TEXTEDIT_GETCHAR is nothing more than a a "GETBYTE". It's only used to compare to ascii or to copy blocks of text so we are fine.
+// - One exception is the STB_TEXTEDIT_IS_SPACE feature which would expect a full char in order to handle full-width space such as 0x3000 (see ImCharIsBlankW).
+// - ...but we don't use that feature.
 namespace ImStb
 {
-
 static int     STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj)                             { return obj->CurLenA; }
 static char    STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx <= obj->CurLenA); return obj->TextA[idx]; }
 static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->TextA.Size); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
 static char    STB_TEXTEDIT_NEWLINE = '\n';
 static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
 {
+    const char* text = obj->TextA.Data;
     const char* text_remaining = NULL;
-    const ImVec2 size = InputTextCalcTextSize(obj->Ctx, obj->TextA.Data + line_start_idx, obj->TextA.Data + obj->CurLenA, &text_remaining, NULL, true);
+    const ImVec2 size = InputTextCalcTextSize(obj->Ctx, text + line_start_idx, text + obj->CurLenA, &text_remaining, NULL, true);
     r->x0 = 0.0f;
     r->x1 = size.x;
     r->baseline_y_delta = size.y;
     r->ymin = 0.0f;
     r->ymax = size.y;
-    r->num_chars = (int)(text_remaining - (obj->TextA.Data + line_start_idx));
+    r->num_chars = (int)(text_remaining - (text + line_start_idx));
 }
 
 static bool ImCharIsSeparatorW(unsigned int c)
@@ -3922,14 +3931,15 @@ static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
     if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
         return 0;
 
-    const char* prevPtr = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, obj->TextA.Data + idx);
-    unsigned int curr; ImTextCharFromUtf8(&curr, obj->TextA.Data + idx, obj->TextA.Data + obj->TextA.Size);
-    unsigned int prev; ImTextCharFromUtf8(&prev, prevPtr, obj->TextA.Data + obj->TextA.Size);
+    const char* curr_p = obj->TextA.Data + idx;
+    const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, curr_p);
+    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, curr_p, obj->TextA.Data + obj->TextA.Size);
+    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, prev_p, obj->TextA.Data + obj->TextA.Size);
 
-    bool prev_white = ImCharIsBlankW(prev);
-    bool prev_separ = ImCharIsSeparatorW(prev);
-    bool curr_white = ImCharIsBlankW(curr);
-    bool curr_separ = ImCharIsSeparatorW(curr);
+    bool prev_white = ImCharIsBlankW(prev_c);
+    bool prev_separ = ImCharIsSeparatorW(prev_c);
+    bool curr_white = ImCharIsBlankW(curr_c);
+    bool curr_separ = ImCharIsSeparatorW(curr_c);
     return ((prev_white || prev_separ) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
 }
 static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
@@ -3937,14 +3947,15 @@ static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
     if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
         return 0;
 
-    const char* prevPtr = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, obj->TextA.Data + idx);
-    unsigned int prev; ImTextCharFromUtf8(&prev, obj->TextA.Data + idx, obj->TextA.Data + obj->TextA.Size);
-    unsigned int curr; ImTextCharFromUtf8(&curr, prevPtr, obj->TextA.Data + obj->TextA.Size);
+    const char* curr_p = obj->TextA.Data + idx;
+    const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, curr_p);
+    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, curr_p, obj->TextA.Data + obj->TextA.Size);
+    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, prev_p, obj->TextA.Data + obj->TextA.Size);
 
-    bool prev_white = ImCharIsBlankW(prev);
-    bool prev_separ = ImCharIsSeparatorW(prev);
-    bool curr_white = ImCharIsBlankW(curr);
-    bool curr_separ = ImCharIsSeparatorW(curr);
+    bool prev_white = ImCharIsBlankW(prev_c);
+    bool prev_separ = ImCharIsSeparatorW(prev_c);
+    bool curr_white = ImCharIsBlankW(curr_c);
+    bool curr_separ = ImCharIsSeparatorW(curr_c);
     return ((prev_white) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
 }
 static int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx)   { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }

From 3d1e593b5b1c6842001a5cf9db1845c93df07689 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 5 Sep 2024 19:56:12 +0200
Subject: [PATCH 116/548] InputText: amends: fixed next/prev word
 implementation. (#7925)

+ replace IMSTB_TEXTEDIT_GETPREVCHARINDEX code with ImTextFindPreviousUtf8Codepoint().
---
 imgui_widgets.cpp | 85 ++++++++++++++++++++++-------------------------
 1 file changed, 39 insertions(+), 46 deletions(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 6d701d03be60..24d1fda7e98f 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3911,6 +3911,25 @@ static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob
     r->num_chars = (int)(text_remaining - (text + line_start_idx));
 }
 
+#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX  IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL
+#define IMSTB_TEXTEDIT_GETPREVCHARINDEX  IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL
+
+static int IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
+{
+    if (idx >= obj->CurLenA)
+        return obj->CurLenA + 1;
+    unsigned int c;
+    return idx + ImTextCharFromUtf8(&c, obj->TextA.Data + idx, obj->TextA.Data + obj->TextA.Size);
+}
+
+static int IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
+{
+    if (idx <= 0)
+        return -1;
+    const char* p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, obj->TextA.Data + idx);
+    return (int)(p - obj->TextA.Data);
+}
+
 static bool ImCharIsSeparatorW(unsigned int c)
 {
     static const unsigned int separator_list[] =
@@ -3958,58 +3977,32 @@ static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
     bool curr_separ = ImCharIsSeparatorW(curr_c);
     return ((prev_white) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ);
 }
-static int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx)   { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
-static int  STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx)   { idx++; int len = obj->CurLenA; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
-static int  STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx)   { idx++; int len = obj->CurLenA; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
-static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx)  { ImGuiContext& g = *obj->Ctx; if (g.IO.ConfigMacOSXBehaviors) return STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx); else return STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx); }
-#define STB_TEXTEDIT_MOVEWORDLEFT       STB_TEXTEDIT_MOVEWORDLEFT_IMPL  // They need to be #define for stb_textedit.h
-#define STB_TEXTEDIT_MOVEWORDRIGHT      STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
-#define IMSTB_TEXTEDIT_GETNEXTCHARINDEX  IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL
-#define IMSTB_TEXTEDIT_GETPREVCHARINDEX  IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL
-
-static int IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
+static int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx)
 {
-    unsigned int c;
-    return idx + ImTextCharFromUtf8(&c, obj->TextA.Data + idx, obj->TextA.Data + obj->TextA.Size);
+    idx = IMSTB_TEXTEDIT_GETPREVCHARINDEX(obj, idx);
+    while (idx >= 0 && !is_word_boundary_from_right(obj, idx))
+        idx = IMSTB_TEXTEDIT_GETPREVCHARINDEX(obj, idx);
+    return idx < 0 ? 0 : idx;
 }
-
-static int CountLeadingHighBits(unsigned char b)
+static int  STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx)
 {
-    for (int i = 0; i < (int)sizeof(b) * 8; i++)
-    {
-        bool set = (b >> (7 - i)) & 1;
-        if (!set)
-            return i;
-    }
-
-    return sizeof(b) * 8;
+    int len = obj->CurLenA;
+    idx = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx);
+    while (idx < len && !is_word_boundary_from_left(obj, idx))
+        idx = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx);
+    return idx > len ? len : idx;
 }
-
-static int IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
+static int  STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx)
 {
-    // Backwards check/count for UTF-8 multi byte sequence
-    int num_seq_bytes = 0;
-    for (int i = idx - 1; i >= 0; i -= 1)
-    {
-        bool is_seq_byte = (obj->TextA.Data[i] & 0x80) == 0x80 && (obj->TextA.Data[i] & 0x40) == 0;
-        num_seq_bytes += is_seq_byte;
-        if (!is_seq_byte)
-        {
-            if (num_seq_bytes > 0)
-            {
-                char initial_byte = obj->TextA.Data[i];
-                char num_leading_bits = (char)CountLeadingHighBits(initial_byte);
-                bool is_multi_byte_seq = num_leading_bits == num_seq_bytes + 1;
-                if (is_multi_byte_seq)
-                {
-                    return idx - (num_seq_bytes + 1);
-                }
-            }
-            break;
-        }
-    }
-    return idx - 1;
+    idx = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx);
+    int len = obj->CurLenA;
+    while (idx < len && !is_word_boundary_from_right(obj, idx))
+        idx = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx);
+    return idx > len ? len : idx;
 }
+static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx)  { ImGuiContext& g = *obj->Ctx; if (g.IO.ConfigMacOSXBehaviors) return STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx); else return STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx); }
+#define STB_TEXTEDIT_MOVEWORDLEFT       STB_TEXTEDIT_MOVEWORDLEFT_IMPL  // They need to be #define for stb_textedit.h
+#define STB_TEXTEDIT_MOVEWORDRIGHT      STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
 
 static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
 {

From 19accb14a9e52f515624485ef8ea6eba8dbab7c3 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 11 Sep 2024 12:57:54 +0200
Subject: [PATCH 117/548] InputText: amends: fixed undo-stack reconcile. fixed
 metrics crash. fixes character filtering. (#7925)

Refer to imgui_test_suite for tests.
---
 imgui_internal.h  |  3 ++-
 imgui_widgets.cpp | 31 ++++++++++++++++---------------
 2 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/imgui_internal.h b/imgui_internal.h
index e6f3f8ec56b0..b54848635b27 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1112,8 +1112,9 @@ struct IMGUI_API ImGuiInputTextState
     ImStbTexteditState*     Stb;                    // State for stb_textedit.h
     ImGuiID                 ID;                     // widget id owning the text state
     int                     CurLenA;                // UTF-8 length of the string in TextA (in bytes)
-    ImVector          TextA;                  // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity.
+    ImVector          TextA;                  // main UTF8 buffer.
     ImVector          InitialTextA;           // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
+    ImVector          CallbackTextBackup;     // temporary storage for callback to support automatic reconcile of undo-stack
     int                     BufCapacityA;           // end-user buffer capacity
     ImVec2                  Scroll;                 // horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y)
     float                   CursorAnim;             // timer for cursor blink, reset on every user action so the cursor reappears immediately
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 24d1fda7e98f..b5c69e73eb06 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4301,8 +4301,8 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im
 // FIXME: Ideally we should transition toward (1) making InsertChars()/DeleteChars() update undo-stack (2) discourage (and keep reconcile) or obsolete (and remove reconcile) accessing buffer directly.
 static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* state, const char* new_buf_a, int new_length_a)
 {
-    const char* old_buf = state->TextA.Data;
-    const int old_length = state->CurLenA;
+    const char* old_buf = state->CallbackTextBackup.Data;
+    const int old_length = state->CallbackTextBackup.Size - 1;
 
     const int shorter_length = ImMin(old_length, new_length_a);
     int first_diff;
@@ -4323,7 +4323,7 @@ static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* st
     if (insert_len > 0 || delete_len > 0)
         if (IMSTB_TEXTEDIT_CHARTYPE* p = stb_text_createundo(&state->Stb->undostate, first_diff, delete_len, insert_len))
             for (int i = 0; i < delete_len; i++)
-                p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i);
+                p[i] = old_buf[first_diff + i];
 }
 
 // As InputText() retain textual data and we currently provide a path for user to not retain it (via local variables)
@@ -4598,11 +4598,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     }
 
     // Process mouse inputs and character inputs
-    int backup_current_text_length = 0;
     if (g.ActiveId == id)
     {
         IM_ASSERT(state != NULL);
-        backup_current_text_length = state->CurLenA;
         state->Edited = false;
         state->BufCapacityA = buf_size;
         state->Flags = flags;
@@ -4856,11 +4854,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                 {
                     unsigned int c;
                     int len = ImTextCharFromUtf8(&c, s, NULL);
+                    s += len;
                     if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, true))
                         continue;
-                    memcpy(clipboard_filtered + clipboard_filtered_len, s, len);
+                    memcpy(clipboard_filtered + clipboard_filtered_len, s - len, len);
                     clipboard_filtered_len += len;
-                    s += len;
                 }
                 clipboard_filtered[clipboard_filtered_len] = 0;
                 if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation
@@ -4960,6 +4958,10 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                     callback_data.Flags = flags;
                     callback_data.UserData = callback_user_data;
 
+                    // FIXME-OPT: Undo stack reconcile needs a backup of the data until we rework API, see #7925
+                    state->CallbackTextBackup.resize(state->CurLenA + 1);
+                    memcpy(state->CallbackTextBackup.Data, state->TextA.Data, state->CurLenA + 1);
+
                     char* callback_buf = is_readonly ? buf : state->TextA.Data;
                     callback_data.EventKey = event_key;
                     callback_data.Buf = callback_buf;
@@ -4988,11 +4990,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                         // Callback may update buffer and thus set buf_dirty even in read-only mode.
                         IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
                         InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ?
-                        if (callback_data.BufTextLen > backup_current_text_length && is_resizable)
-                            state->TextA.resize(state->TextA.Size + (callback_data.BufTextLen - backup_current_text_length)); // Worse case scenario resize
-
-                        memcpy(state->TextA.Data, callback_data.Buf, callback_data.BufTextLen);
                         state->CurLenA = callback_data.BufTextLen;  // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
+                        state->TextA.Size = state->CurLenA + 1;
                         state->CursorAnimReset();
                     }
                 }
@@ -5024,9 +5023,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     // Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
     if (apply_new_text != NULL)
     {
-        // We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size
-        // of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used
-        // without any storage on user's side.
+        //// We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size
+        //// of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used
+        //// without any storage on user's side.
         IM_ASSERT(apply_new_text_length >= 0);
         if (is_resizable)
         {
@@ -5325,8 +5324,10 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
             const char undo_rec_type = (n < undo_state->undo_point) ? 'u' : (n >= undo_state->redo_point) ? 'r' : ' ';
             if (undo_rec_type == ' ')
                 BeginDisabled();
+            const int buf_preview_len = (undo_rec_type != ' ' && undo_rec->char_storage != -1) ? undo_rec->insert_length : 0;
+            const char* buf_preview_str = undo_state->undo_char + undo_rec->char_storage;
             Text("%c [%02d] where %03d, insert %03d, delete %03d, char_storage %03d \"%.*s\"",
-                undo_rec_type, n, undo_rec->where, undo_rec->insert_length, undo_rec->delete_length, undo_rec->char_storage, undo_rec->insert_length, undo_state->undo_char + undo_rec->char_storage);
+                undo_rec_type, n, undo_rec->where, undo_rec->insert_length, undo_rec->delete_length, undo_rec->char_storage, buf_preview_len, buf_preview_str);
             if (undo_rec_type == ' ')
                 EndDisabled();
         }

From 8807b01b28883dfbf7b971a4aa6c1199e4dea827 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 11 Sep 2024 14:15:23 +0200
Subject: [PATCH 118/548] InputText: amends: now can use memchr()/strchr() for
 line counting. Much faster! (#7925)

---
 docs/CHANGELOG.txt |  4 ++++
 docs/TODO.txt      |  1 -
 imgui_widgets.cpp  | 24 ++++++++++--------------
 3 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 35c4c6743d34..1611bf59b9a8 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -63,6 +63,10 @@ Other changes:
      #6223, #6364, #6387, #6567, #6692, #6724, #6939, #6984, #7246, #7270, #7375, #7421, #7434,
      #7472, #7581, #7724, #7926, #7937 and probably more..)
 - Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439)
+- InputText: internal refactoring to simplify and optimize the code. The ImWchar buffer has been
+  removed. Simplifications allowed to implement new optimizations for handling very large text buffers
+  (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
+  This is the first step toward more refactorig. (#7925) [@alektron, @ocornut]
 - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
 - TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660)
 - Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam]
diff --git a/docs/TODO.txt b/docs/TODO.txt
index 84a00bc6e92b..ddceb3b3d9bb 100644
--- a/docs/TODO.txt
+++ b/docs/TODO.txt
@@ -65,7 +65,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
  - selectable: generic BeginSelectable()/EndSelectable() mechanism. (work out alongside range-select branch)
  - selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)
 
- - input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile. (WIP branch)
  - input text: preserve scrolling when unfocused?
  - input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
  - input text: expose CursorPos in char filter event (#816)
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index b5c69e73eb06..94e1abff6028 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -5119,14 +5119,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.
             searches_remaining += is_multiline ? 1 : 0;
             int line_count = 0;
-            //for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++)  // FIXME-OPT: Could use this when wchar_t are 16-bit
-            for (const char* s = text_begin; *s != 0; s++)
-                if (*s == '\n')
-                {
-                    line_count++;
-                    if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; }
-                    if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; if (--searches_remaining <= 0) break; }
-                }
+            for (const char* s = text_begin; (s = strchr(s, '\n')) != NULL; s++) // FIXME-OPT: memchr() would be faster?
+            {
+                line_count++;
+                if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; }
+                if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; if (--searches_remaining <= 0) break; }
+            }
             line_count++;
             if (searches_result_line_no[0] == -1)
                 searches_result_line_no[0] = line_count;
@@ -5199,11 +5197,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                     break;
                 if (rect_pos.y < clip_rect.y)
                 {
-                    //p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p);  // FIXME-OPT: Could use this when wchar_t are 16-bit
-                    //p = p ? p + 1 : text_selected_end;
-                    while (p < text_selected_end)
-                        if (*p++ == '\n')
-                            break;
+                    p = (const char*)memchr((void*)p, '\n', text_selected_end - p);
+                    p = p ? p + 1 : text_selected_end;
                 }
                 else
                 {
@@ -5213,13 +5208,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                     rect.ClipWith(clip_rect);
                     if (rect.Overlaps(clip_rect))
                         draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
+                    rect_pos.x = draw_pos.x - draw_scroll.x;
                 }
-                rect_pos.x = draw_pos.x - draw_scroll.x;
                 rect_pos.y += g.FontSize;
             }
         }
 
         // We test for 'buf_display_max_length' as a way to avoid some pathological cases (e.g. single-line 1 MB string) which would make ImDrawList crash.
+        // FIXME-OPT: Multiline could submit a smaller amount of contents to AddText() since we already iterated through it.
         if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
         {
             ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);

From dc6346b763e4c92fe57887ee1cb4fe557517d4fa Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 12 Sep 2024 19:22:09 +0200
Subject: [PATCH 119/548] Fonts: fixed ellipsis "..." rendering width
 miscalculation bug introduced in 1.91.0. (#7976)

Amend 0f63d3e9
---
 docs/CHANGELOG.txt | 1 +
 imgui.cpp          | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 1611bf59b9a8..28b3cae269cf 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -68,6 +68,7 @@ Other changes:
   (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
   This is the first step toward more refactorig. (#7925) [@alektron, @ocornut]
 - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
+- Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos]
 - TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660)
 - Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam]
 
diff --git a/imgui.cpp b/imgui.cpp
index 71b1b10110ef..3c2fd665873d 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4007,7 +4007,7 @@ static void SetCurrentWindow(ImGuiWindow* window)
     if (window)
     {
         g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
-        g.FontScale = g.FontSize / g.Font->FontSize;
+        g.FontScale = g.DrawListSharedData.FontScale = g.FontSize / g.Font->FontSize;
         ImGui::NavUpdateCurrentWindowIsScrollPushableX();
     }
 }

From 52a6ab44b1f0387922ec802ad909cf32a5283f24 Mon Sep 17 00:00:00 2001
From: David Briscoe <43559+idbrii@users.noreply.github.com>
Date: Thu, 12 Sep 2024 10:24:37 -0700
Subject: [PATCH 120/548] Doc: Fix typo. (#7974)

---
 imgui.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/imgui.cpp b/imgui.cpp
index 3c2fd665873d..59a918e8643a 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -9046,7 +9046,7 @@ bool ImGui::IsKeyPressed(ImGuiKey key, bool repeat)
     return IsKeyPressed(key, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
 }
 
-// Important: unless legacy IsKeyPressed(ImGuiKey, bool repeat=true) which DEFAULT to repeat, this requires EXPLICIT repeat.
+// Important: unlike legacy IsKeyPressed(ImGuiKey, bool repeat=true) which DEFAULT to repeat, this requires EXPLICIT repeat.
 bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiInputFlags flags, ImGuiID owner_id)
 {
     const ImGuiKeyData* key_data = GetKeyData(key);

From ac2ad79812e8f17ed4d76b8645c3f10e385018c8 Mon Sep 17 00:00:00 2001
From: Yan Pujante 
Date: Sat, 7 Sep 2024 10:22:45 -0700
Subject: [PATCH 121/548] Backends: GLFW+Emscripten: use OSX behaviors
 automatically when using contrib glfw port. (#7965, #7915)

---
 backends/imgui_impl_glfw.cpp              | 22 +++++++++++++++++++++-
 docs/CHANGELOG.txt                        |  2 ++
 examples/example_glfw_wgpu/CMakeLists.txt |  1 -
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp
index 06b5142a1cfc..9c6722f7826f 100644
--- a/backends/imgui_impl_glfw.cpp
+++ b/backends/imgui_impl_glfw.cpp
@@ -18,6 +18,11 @@
 // - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
 // - Introduction, links and more at the top of imgui.cpp
 
+// About Emscripten support:
+// - Emscripten provides its own GLFW (3.2.1) implementation (syntax: "-sUSE_GLFW=3"), but Joystick is broken and several features are not supported (multiple windows, clipboard, timer, etc.)
+// - A third-party Emscripten GLFW (3.4.0) implementation (syntax: "--use-port=contrib.glfw3") fixes the Joystick issue and implements all relevant features for the browser.
+// See https://github.com/pongasoft/emscripten-glfw/blob/master/docs/Comparison.md for details.
+
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
 //  2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
@@ -560,7 +565,7 @@ void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows)
 }
 
 #ifdef __EMSCRIPTEN__
-#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 3'4'0'20240817
+#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 34020240817
 void ImGui_ImplGlfw_EmscriptenOpenURL(const char* url) { if (url) emscripten::glfw3::OpenURL(url); }
 #else
 EM_JS(void, ImGui_ImplGlfw_EmscriptenOpenURL, (const char* url), { url = url ? UTF8ToString(url) : null; if (url) window.open(url, '_blank'); });
@@ -639,6 +644,21 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
     ::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc);
 #endif
 
+    // Emscripten: the same application can run on various platforms, so we detect the Apple platform at runtime
+    // to override io.ConfigMacOSXBehaviors from its default (which is always false in Emscripten).
+#if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 34020240817
+    if (emscripten::glfw3::IsRuntimePlatformApple())
+    {
+        ImGui::GetIO().ConfigMacOSXBehaviors = true;
+
+        // Due to how the browser (poorly) handles the Meta Key, this line essentially disables repeats when used.
+        // This means that Meta + V only registers a single key-press, even if the keys are held.
+        // This is a compromise for dealing with this issue in ImGui since ImGui implements key repeat itself.
+        // See https://github.com/pongasoft/emscripten-glfw/blob/v3.4.0.20240817/docs/Usage.md#the-problem-of-the-super-key
+        emscripten::glfw3::SetSuperPlusKeyTimeouts(10, 10);
+    }
+#endif
+
     bd->ClientApi = client_api;
     return true;
 }
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 28b3cae269cf..2189f258461c 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -71,6 +71,8 @@ Other changes:
 - Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos]
 - TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660)
 - Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam]
+- Backends: GLFW+Emscripten: use OSX behaviors automatically when using contrib glfw port. (#7965, #7915)
+  [@ypujante]
 
 -----------------------------------------------------------------------
  VERSION 1.91.1 (Released 2024-09-04)
diff --git a/examples/example_glfw_wgpu/CMakeLists.txt b/examples/example_glfw_wgpu/CMakeLists.txt
index 77b492fdc278..6be95af44aeb 100644
--- a/examples/example_glfw_wgpu/CMakeLists.txt
+++ b/examples/example_glfw_wgpu/CMakeLists.txt
@@ -91,7 +91,6 @@ if(EMSCRIPTEN)
   if("${IMGUI_EMSCRIPTEN_GLFW3}" STREQUAL "--use-port=contrib.glfw3")
     target_compile_options(example_glfw_wgpu PUBLIC
         "${IMGUI_EMSCRIPTEN_GLFW3}"
-        "-DEMSCRIPTEN_USE_PORT_CONTRIB_GLFW3" # unnecessary beyond emscripten 3.1.59
     )
   endif()
   message(STATUS "Using ${IMGUI_EMSCRIPTEN_GLFW3} GLFW implementation")

From 6dcb7be35f8e9b54d4a3e3c75a97ab09589e4f38 Mon Sep 17 00:00:00 2001
From: Yan Pujante 
Date: Sat, 7 Sep 2024 10:23:20 -0700
Subject: [PATCH 122/548] CI: amend build tests for emscripten (#7965)

+ Backends: GLFW: minor preemptive fix.
---
 .github/workflows/build.yml  | 16 +++++++++++++++-
 backends/imgui_impl_glfw.cpp |  2 ++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 1d43da032a6a..f95ff43c8a9c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -527,6 +527,7 @@ jobs:
         emsdk-master/emsdk update
         emsdk-master/emsdk install latest
         emsdk-master/emsdk activate latest
+        sudo apt-get install build-essential
 
     - name: Build example_sdl2_opengl3 with Emscripten
       run: |
@@ -535,13 +536,26 @@ jobs:
         popd
         make -C examples/example_sdl2_opengl3 -f Makefile.emscripten
 
-    - name: Build example_glfw_wgpu
+    # This build compiles example_glfw_wgpu using Makefile.emscripten and Emscripten GLFW built-in implementation (-sUSE_GLFW=3)
+    # This ensures 2 things: the make build works, and the GLFW built-in implementation is tested
+    - name: Build example_glfw_wgpu with Emscripten/Makefile
       run: |
         pushd emsdk-master
         source ./emsdk_env.sh
         popd
         make -C examples/example_glfw_wgpu -f Makefile.emscripten
 
+    # This build compiles example_glfw_wgpu using CMakeLists.txt and Emscripten GLFW contrib port (--use-port=contrib.glfw3)
+    # This ensures 2 things: the CMake build works, and the GLFW contrib port is tested
+    - name: Build example_glfw_wgpu with Emscripten/CMake
+      run: |
+        pushd emsdk-master
+        source ./emsdk_env.sh
+        popd
+        emcc -v
+        emcmake cmake -B build -DCMAKE_BUILD_TYPE=Release examples/example_glfw_wgpu
+        cmake --build build
+
   Android:
     runs-on: ubuntu-24.04
     steps:
diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp
index 9c6722f7826f..30afaf4f0eeb 100644
--- a/backends/imgui_impl_glfw.cpp
+++ b/backends/imgui_impl_glfw.cpp
@@ -646,6 +646,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
 
     // Emscripten: the same application can run on various platforms, so we detect the Apple platform at runtime
     // to override io.ConfigMacOSXBehaviors from its default (which is always false in Emscripten).
+#ifdef __EMSCRIPTEN__
 #if EMSCRIPTEN_USE_PORT_CONTRIB_GLFW3 >= 34020240817
     if (emscripten::glfw3::IsRuntimePlatformApple())
     {
@@ -657,6 +658,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
         // See https://github.com/pongasoft/emscripten-glfw/blob/v3.4.0.20240817/docs/Usage.md#the-problem-of-the-super-key
         emscripten::glfw3::SetSuperPlusKeyTimeouts(10, 10);
     }
+#endif
 #endif
 
     bd->ClientApi = client_api;

From 4d00bf8add44155a4f6b489538bd77d6214a4432 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 12 Sep 2024 23:13:32 +0200
Subject: [PATCH 123/548] MultiSelect+Tables: fixed an issue where box-select
 would skip items while drag-scrolling in a table with outer borders. (#7970,
 #7821).

See "widgets_multiselect_boxselect_2" test.
---
 docs/CHANGELOG.txt | 2 ++
 imgui_widgets.cpp  | 7 ++++++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 2189f258461c..903af40c37be 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -63,6 +63,8 @@ Other changes:
      #6223, #6364, #6387, #6567, #6692, #6724, #6939, #6984, #7246, #7270, #7375, #7421, #7434,
      #7472, #7581, #7724, #7926, #7937 and probably more..)
 - Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439)
+- MultiSelect+Tables: fixed an issue where box-select would skip items while drag-scrolling
+  in a table with outer borders. (#7970, #7821).
 - InputText: internal refactoring to simplify and optimize the code. The ImWchar buffer has been
   removed. Simplifications allowed to implement new optimizations for handling very large text buffers
   (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 94e1abff6028..14c5af3e44df 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -7403,6 +7403,7 @@ static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSe
 
 static ImRect CalcScopeRect(ImGuiMultiSelectTempData* ms, ImGuiWindow* window)
 {
+    ImGuiContext& g = *GImGui;
     if (ms->Flags & ImGuiMultiSelectFlags_ScopeRect)
     {
         // Warning: this depends on CursorMaxPos so it means to be called by EndMultiSelect() only
@@ -7410,8 +7411,12 @@ static ImRect CalcScopeRect(ImGuiMultiSelectTempData* ms, ImGuiWindow* window)
     }
     else
     {
-        // Add inner table decoration (#7821) // FIXME: Why not baking in InnerClipRect?
+        // When a table, pull HostClipRect, which allows us to predict ClipRect before first row/layout is performed. (#7970)
         ImRect scope_rect = window->InnerClipRect;
+        if (g.CurrentTable != NULL)
+            scope_rect = g.CurrentTable->HostClipRect;
+
+        // Add inner table decoration (#7821) // FIXME: Why not baking in InnerClipRect?
         scope_rect.Min = ImMin(scope_rect.Min + ImVec2(window->DecoInnerSizeX1, window->DecoInnerSizeY1), scope_rect.Max);
         return scope_rect;
     }

From dab63231d888f4a39c4d5729e14296c30cef2bc7 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 16 Sep 2024 11:19:05 +0200
Subject: [PATCH 124/548] Misc: Made it accepted to call SetMouseCursor() with
 any out-of-bound value, as a way to allow hacking in custom cursors if
 desirable.

---
 docs/CHANGELOG.txt |  2 ++
 imgui.cpp          | 10 +++++++---
 imgui_demo.cpp     |  3 ++-
 imgui_tables.cpp   |  2 +-
 imgui_widgets.cpp  |  2 +-
 5 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 903af40c37be..b91d55530c0e 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -70,6 +70,8 @@ Other changes:
   (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
   This is the first step toward more refactorig. (#7925) [@alektron, @ocornut]
 - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
+- Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow
+  hacking in custom cursors if desirable.
 - Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos]
 - TextLinkOpenURL(): modified tooltip to display a verb "Open 'xxxx'". (#7885, #7660)
 - Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam]
diff --git a/imgui.cpp b/imgui.cpp
index 59a918e8643a..bdeda3fe7dd5 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3702,7 +3702,8 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
 void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow)
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT);
+    if (mouse_cursor <= ImGuiMouseCursor_None || mouse_cursor >= ImGuiMouseCursor_COUNT) // We intentionally accept out of bound values.
+        mouse_cursor = ImGuiMouseCursor_Arrow;
     ImFontAtlas* font_atlas = g.DrawListSharedData.Font->ContainerAtlas;
     for (ImGuiViewportP* viewport : g.Viewports)
     {
@@ -6198,7 +6199,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
         ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
         //GetForegroundDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255));
         if (hovered || held)
-            g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
+            SetMouseCursor((resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE);
 
         if (held && g.IO.MouseDoubleClicked[0])
         {
@@ -6244,7 +6245,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
         if (hovered && g.HoveredIdTimer <= WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER)
             hovered = false;
         if (hovered || held)
-            g.MouseCursor = (axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS;
+            SetMouseCursor((axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS);
         if (held && g.IO.MouseDoubleClicked[0])
         {
             // Double-clicking bottom or right border auto-fit on this axis
@@ -9296,6 +9297,9 @@ ImGuiMouseCursor ImGui::GetMouseCursor()
     return g.MouseCursor;
 }
 
+// We intentionally accept values of ImGuiMouseCursor that are outside our bounds, in case users needs to hack-in a custom cursor value.
+// Custom cursors may be handled by custom backends. If you are using a standard backend and want to hack in a custom cursor, you may
+// handle it before the backend _NewFrame() call and temporarily set ImGuiConfigFlags_NoMouseCursorChange during the backend _NewFrame() call.
 void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
 {
     ImGuiContext& g = *GImGui;
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 8c9745dfbfce..cc21099a8872 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -7490,7 +7490,8 @@ static void ShowDemoWindowInputs()
             IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
 
             ImGuiMouseCursor current = ImGui::GetMouseCursor();
-            ImGui::Text("Current mouse cursor = %d: %s", current, mouse_cursors_names[current]);
+            const char* cursor_name = (current >= ImGuiMouseCursor_Arrow) && (current < ImGuiMouseCursor_COUNT) ? mouse_cursors_names[current] : "N/A";
+            ImGui::Text("Current mouse cursor = %d: %s", current, cursor_name);
             ImGui::BeginDisabled(true);
             ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &io.BackendFlags, ImGuiBackendFlags_HasMouseCursors);
             ImGui::EndDisabled();
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index f247ed6d3931..9a6e06a2d743 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -4409,7 +4409,7 @@ void ImGui::EndColumns()
             {
                 ButtonBehavior(column_hit_rect, column_id, &hovered, &held);
                 if (hovered || held)
-                    g.MouseCursor = ImGuiMouseCursor_ResizeEW;
+                    SetMouseCursor(ImGuiMouseCursor_ResizeEW);
                 if (held && !(column->Flags & ImGuiOldColumnFlags_NoResize))
                     dragging_column = n;
             }
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 14c5af3e44df..3576d31fa7b3 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4438,7 +4438,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     }
     const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
     if (hovered)
-        g.MouseCursor = ImGuiMouseCursor_TextInput;
+        SetMouseCursor(ImGuiMouseCursor_TextInput);
 
     // We are only allowed to access the state if we are already the active widget.
     ImGuiInputTextState* state = GetInputTextState(id);

From 510b6adc9bb0cfea012f513e358f3df962fe91b7 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 16 Sep 2024 12:09:02 +0200
Subject: [PATCH 125/548] CI: disable month-long PVS Studio warning about
 expiring licence.

---
 .github/workflows/static-analysis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
index 69df5cdf8031..99b058c91a2b 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -42,5 +42,5 @@ jobs:
           fi
           cd examples/example_null
           pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1
-          pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
+          pvs-studio-analyzer analyze --disableLicenseExpirationCheck -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
           plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log

From b53d91a4c40b69ec1d7e95e44863c8c921ed2f11 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 16 Sep 2024 14:15:43 +0200
Subject: [PATCH 126/548] InputText: optimization for large text: using
 memchr() instead of strchr() shaves 0.2 ms on 865k multi-line text case.
 Approximately 20%. (#7925)

---
 docs/CHANGELOG.txt | 2 +-
 imgui_widgets.cpp  | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index b91d55530c0e..069b603884ef 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -68,7 +68,7 @@ Other changes:
 - InputText: internal refactoring to simplify and optimize the code. The ImWchar buffer has been
   removed. Simplifications allowed to implement new optimizations for handling very large text buffers
   (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
-  This is the first step toward more refactorig. (#7925) [@alektron, @ocornut]
+  This is the first step toward more refactoring. (#7925) [@alektron, @ocornut]
 - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
 - Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow
   hacking in custom cursors if desirable.
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 3576d31fa7b3..64156b40d3ff 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -5095,6 +5095,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
         // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
         const char* text_begin = state->TextA.Data;
+        const char* text_end = text_begin + state->CurLenA;
         ImVec2 cursor_offset, select_start_offset;
 
         {
@@ -5119,7 +5120,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.
             searches_remaining += is_multiline ? 1 : 0;
             int line_count = 0;
-            for (const char* s = text_begin; (s = strchr(s, '\n')) != NULL; s++) // FIXME-OPT: memchr() would be faster?
+            for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++)
             {
                 line_count++;
                 if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; }

From aef07aea27472b9a678967404d06ea7ab6d71fb9 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 16 Sep 2024 14:36:25 +0200
Subject: [PATCH 127/548] InputText: minor tidying up of selection search loop
 (no need to imply it runs in single line mode)

---
 imgui_widgets.cpp | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 64156b40d3ff..26f617806066 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -5100,33 +5100,30 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
 
         {
             // Find lines numbers straddling 'cursor' (slot 0) and 'select_start' (slot 1) positions.
-            const char* searches_input_ptr[2] = { NULL, NULL };
             int searches_result_line_no[2] = { -1000, -1000 };
-            int searches_remaining = 0;
+            const char* searches_input_ptr[2] = { NULL, NULL };
             if (render_cursor)
             {
                 searches_input_ptr[0] = text_begin + state->Stb->cursor;
                 searches_result_line_no[0] = -1;
-                searches_remaining++;
             }
             if (render_selection)
             {
                 searches_input_ptr[1] = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end);
                 searches_result_line_no[1] = -1;
-                searches_remaining++;
             }
 
-            // Iterate all lines to find our line numbers
-            // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.
-            searches_remaining += is_multiline ? 1 : 0;
-            int line_count = 0;
-            for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++)
+            // Count lines and find line number for cursor and selection ends
+            int line_count = 1;
+            if (is_multiline)
             {
-                line_count++;
-                if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; }
-                if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; if (--searches_remaining <= 0) break; }
+                for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++)
+                {
+                    if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; }
+                    if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; }
+                    line_count++;
+                }
             }
-            line_count++;
             if (searches_result_line_no[0] == -1)
                 searches_result_line_no[0] = line_count;
             if (searches_result_line_no[1] == -1)

From 7ac50bf77d08aaf569acc00feacd7eb44785f241 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 16 Sep 2024 14:42:58 +0200
Subject: [PATCH 128/548] InputText: more tidying up of selection search loop.

---
 imgui_widgets.cpp | 40 ++++++++++++++++------------------------
 1 file changed, 16 insertions(+), 24 deletions(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 26f617806066..c5ee2734a9b0 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -5099,19 +5099,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         ImVec2 cursor_offset, select_start_offset;
 
         {
-            // Find lines numbers straddling 'cursor' (slot 0) and 'select_start' (slot 1) positions.
-            int searches_result_line_no[2] = { -1000, -1000 };
-            const char* searches_input_ptr[2] = { NULL, NULL };
-            if (render_cursor)
-            {
-                searches_input_ptr[0] = text_begin + state->Stb->cursor;
-                searches_result_line_no[0] = -1;
-            }
-            if (render_selection)
-            {
-                searches_input_ptr[1] = text_begin + ImMin(state->Stb->select_start, state->Stb->select_end);
-                searches_result_line_no[1] = -1;
-            }
+            // Find lines numbers straddling cursor and selection min position
+            int cursor_line_no = render_cursor ? -1 : -1000;
+            int selmin_line_no = render_selection ? -1 : -1000;
+            const char* cursor_ptr = render_cursor ? text_begin + state->Stb->cursor : NULL;
+            const char* selmin_ptr = render_selection ? text_begin + ImMin(state->Stb->select_start, state->Stb->select_end) : NULL;
 
             // Count lines and find line number for cursor and selection ends
             int line_count = 1;
@@ -5119,23 +5111,23 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             {
                 for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++)
                 {
-                    if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; }
-                    if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; }
+                    if (cursor_line_no == -1 && s >= cursor_ptr) { cursor_line_no = line_count; }
+                    if (selmin_line_no == -1 && s >= selmin_ptr) { selmin_line_no = line_count; }
                     line_count++;
                 }
             }
-            if (searches_result_line_no[0] == -1)
-                searches_result_line_no[0] = line_count;
-            if (searches_result_line_no[1] == -1)
-                searches_result_line_no[1] = line_count;
+            if (cursor_line_no == -1)
+                cursor_line_no = line_count;
+            if (selmin_line_no == -1)
+                selmin_line_no = line_count;
 
             // Calculate 2d position by finding the beginning of the line and measuring distance
-            cursor_offset.x = InputTextCalcTextSize(&g, ImStrbol(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
-            cursor_offset.y = searches_result_line_no[0] * g.FontSize;
-            if (searches_result_line_no[1] >= 0)
+            cursor_offset.x = InputTextCalcTextSize(&g, ImStrbol(cursor_ptr, text_begin), cursor_ptr).x;
+            cursor_offset.y = cursor_line_no * g.FontSize;
+            if (selmin_line_no >= 0)
             {
-                select_start_offset.x = InputTextCalcTextSize(&g, ImStrbol(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
-                select_start_offset.y = searches_result_line_no[1] * g.FontSize;
+                select_start_offset.x = InputTextCalcTextSize(&g, ImStrbol(selmin_ptr, text_begin), selmin_ptr).x;
+                select_start_offset.y = selmin_line_no * g.FontSize;
             }
 
             // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224)

From 4925695ae882f628d149ebcc8bd17471dd2c3efb Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 16 Sep 2024 14:52:42 +0200
Subject: [PATCH 129/548] InputText: optimize
 InputTextCalcTextLenAndLineCount() for inactive multiline path. (#7925)

---
 imgui_widgets.cpp | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index c5ee2734a9b0..4156ce8af80e 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3822,16 +3822,22 @@ bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, si
     return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
 }
 
+// This is only used in the path where the multiline widget is inactivate.
 static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
 {
     int line_count = 0;
     const char* s = text_begin;
-    while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding
-        if (c == '\n')
-            line_count++;
-    s--;
-    if (s[0] != '\n' && s[0] != '\r')
+    while (true)
+    {
+        const char* s_eol = strchr(s, '\n');
         line_count++;
+        if (s_eol == NULL)
+        {
+            s = s + strlen(s);
+            break;
+        }
+        s = s_eol + 1;
+    }
     *out_text_end = s;
     return line_count;
 }

From 1ac162f2b083819663fe12b7217c40abdaf501cb Mon Sep 17 00:00:00 2001
From: Aaron C Gaudette 
Date: Mon, 16 Sep 2024 16:07:02 +0200
Subject: [PATCH 130/548] Backends: WGPU: add
 IMGUI_IMPL_WEBGPU_BACKEND_DAWN/IMGUI_IMPL_WEBGPU_BACKEND_WGPU to support more
 targets. (#7977, #7969, #6602, #6188, #7523)

---
 backends/imgui_impl_wgpu.cpp              | 29 +++++++++++++++++++++++
 backends/imgui_impl_wgpu.h                |  7 ++++++
 docs/CHANGELOG.txt                        |  2 ++
 examples/example_glfw_wgpu/CMakeLists.txt |  5 ++++
 4 files changed, 43 insertions(+)

diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp
index bf741e1a476f..503ac8efdcd9 100644
--- a/backends/imgui_impl_wgpu.cpp
+++ b/backends/imgui_impl_wgpu.cpp
@@ -16,6 +16,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-09-16: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU define to handle ever-changing native implementations. (#7977)
 //  2024-01-22: Added configurable PipelineMultisampleState struct. (#7240)
 //  2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes.
 //  2024-01-22: Fixed pipeline layout leak. (#7245)
@@ -35,6 +36,18 @@
 //  2021-02-18: Change blending equation to preserve alpha in output buffer.
 //  2021-01-28: Initial version.
 
+// When targeting native platforms (i.e. NOT emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN
+// or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
+#ifndef __EMSCRIPTEN__
+    #if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
+    #error exactly one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be defined!
+    #endif
+#else
+    #if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
+    #error neither IMGUI_IMPL_WEBGPU_BACKEND_DAWN nor IMGUI_IMPL_WEBGPU_BACKEND_WGPU may be defined if targeting emscripten!
+    #endif
+#endif
+
 #include "imgui.h"
 #ifndef IMGUI_DISABLE
 #include "imgui_impl_wgpu.h"
@@ -245,7 +258,11 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
     ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
 
     WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
+#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
+    wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
+#else
     wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
+#endif
     wgsl_desc.code = wgsl_source;
 
     WGPUShaderModuleDescriptor desc = {};
@@ -660,7 +677,11 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
     // Create depth-stencil State
     WGPUDepthStencilState depth_stencil_state = {};
     depth_stencil_state.format = bd->depthStencilFormat;
+#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
+    depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False;
+#else
     depth_stencil_state.depthWriteEnabled = false;
+#endif
     depth_stencil_state.depthCompare = WGPUCompareFunction_Always;
     depth_stencil_state.stencilFront.compare = WGPUCompareFunction_Always;
     depth_stencil_state.stencilFront.failOp = WGPUStencilOperation_Keep;
@@ -730,7 +751,15 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info)
     // Setup backend capabilities flags
     ImGui_ImplWGPU_Data* bd = IM_NEW(ImGui_ImplWGPU_Data)();
     io.BackendRendererUserData = (void*)bd;
+#if defined(__EMSCRIPTEN__)
+    io.BackendRendererName = "imgui_impl_webgpu_emscripten";
+#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN)
+    io.BackendRendererName = "imgui_impl_webgpu_dawn";
+#elif defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)
+    io.BackendRendererName = "imgui_impl_webgpu_wgpu";
+#else
     io.BackendRendererName = "imgui_impl_webgpu";
+#endif
     io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;  // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
 
     bd->initInfo = *init_info;
diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h
index 87d9580bf800..e6835dee94c8 100644
--- a/backends/imgui_impl_wgpu.h
+++ b/backends/imgui_impl_wgpu.h
@@ -2,6 +2,13 @@
 // This needs to be used along with a Platform Binding (e.g. GLFW)
 // (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
 
+// Important note to dawn and/or wgpu users: when targeting native platforms (i.e. NOT emscripten),
+// one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided.
+// Add #define to your imconfig.h file, or as a compilation flag in your build system.
+// This requirement will be removed once WebGPU stabilizes and backends converge on a unified interface.
+//#define IMGUI_IMPL_WEBGPU_BACKEND_DAWN
+//#define IMGUI_IMPL_WEBGPU_BACKEND_WGPU
+
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 069b603884ef..95df895c4c43 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -77,6 +77,8 @@ Other changes:
 - Backends: SDL2: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) [@scribam]
 - Backends: GLFW+Emscripten: use OSX behaviors automatically when using contrib glfw port. (#7965, #7915)
   [@ypujante]
+- Backends: WebGPU: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU
+  defines to handle ever-changing native implementations. (#7977, #7969, #6602, #6188, #7523) [@acgaudette]
 
 -----------------------------------------------------------------------
  VERSION 1.91.1 (Released 2024-09-04)
diff --git a/examples/example_glfw_wgpu/CMakeLists.txt b/examples/example_glfw_wgpu/CMakeLists.txt
index 6be95af44aeb..8e164e48847f 100644
--- a/examples/example_glfw_wgpu/CMakeLists.txt
+++ b/examples/example_glfw_wgpu/CMakeLists.txt
@@ -79,6 +79,11 @@ add_executable(example_glfw_wgpu
   ${IMGUI_DIR}/imgui_tables.cpp
   ${IMGUI_DIR}/imgui_widgets.cpp
 )
+IF(NOT EMSCRIPTEN)
+  target_compile_definitions(example_glfw_wgpu PUBLIC
+    "IMGUI_IMPL_WEBGPU_BACKEND_DAWN"
+  )
+endif()
 target_include_directories(example_glfw_wgpu PUBLIC
   ${IMGUI_DIR}
   ${IMGUI_DIR}/backends

From 08b1496b7e566eecf1b870bce1eed57522c6593c Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 16 Sep 2024 17:22:31 +0200
Subject: [PATCH 131/548] Backends: Win32: fixed an issue where a viewport
 destroyed while clicking would hog mouse tracking and temporary lead to
 incorrect update of HoveredWindow. (#7971)

# Conflicts:
#	backends/imgui_impl_win32.cpp
#	docs/CHANGELOG.txt
---
 backends/imgui_impl_win32.cpp | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp
index 0e48d86362fb..758e70d01a54 100644
--- a/backends/imgui_impl_win32.cpp
+++ b/backends/imgui_impl_win32.cpp
@@ -107,7 +107,7 @@ struct ImGui_ImplWin32_Data
 {
     HWND                        hWnd;
     HWND                        MouseHwnd;
-    int                         MouseTrackedArea;   // 0: not tracked, 1: client are, 2: non-client area
+    int                         MouseTrackedArea;   // 0: not tracked, 1: client area, 2: non-client area
     int                         MouseButtonsDown;
     INT64                       Time;
     INT64                       TicksPerSecond;
@@ -629,6 +629,16 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
         }
         return 0;
     }
+    case WM_DESTROY:
+        if (bd->MouseHwnd == hwnd && bd->MouseTrackedArea != 0)
+        {
+            TRACKMOUSEEVENT tme_cancel = { sizeof(tme_cancel), TME_CANCEL, hwnd, 0 };
+            ::TrackMouseEvent(&tme_cancel);
+            bd->MouseHwnd = nullptr;
+            bd->MouseTrackedArea = 0;
+            io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
+        }
+        return 0;
     case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
     case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
     case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:

From 6ce26ef11d52d57845d0f06d84dcbfbc0f8d006b Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 17 Sep 2024 12:25:21 +0200
Subject: [PATCH 132/548] AddFont: added assert to better detect uninitialized
 struct. (#7993)

---
 imgui_draw.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index a681059bbdbc..79270f1a1fd6 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -2499,13 +2499,14 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
 {
     IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
     IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0);
-    IM_ASSERT(font_cfg->SizePixels > 0.0f);
+    IM_ASSERT(font_cfg->SizePixels > 0.0f && "Is ImFontConfig struct correctly initialized?");
+    IM_ASSERT(font_cfg->OversampleH > 0 && font_cfg->OversampleV > 0 && "Is ImFontConfig struct correctly initialized?");
 
     // Create new font
     if (!font_cfg->MergeMode)
         Fonts.push_back(IM_NEW(ImFont));
     else
-        IM_ASSERT(!Fonts.empty() && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.
+        IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.
 
     ConfigData.push_back(*font_cfg);
     ImFontConfig& new_font_cfg = ConfigData.back();

From 11fba027e506beca7a2a726b73577b5e8938d64d Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 17 Sep 2024 16:35:55 +0200
Subject: [PATCH 133/548] Tables: using table->InnerClipRect more consistently.
 Fixes an assertion with tables with borders when clipped by parent. (#6765,
 #3752, #7428)

---
 docs/CHANGELOG.txt | 1 +
 imgui_tables.cpp   | 8 ++++----
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 95df895c4c43..8d640533cc45 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -70,6 +70,7 @@ Other changes:
   (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
   This is the first step toward more refactoring. (#7925) [@alektron, @ocornut]
 - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
+- Tables: fixes an assertion with tables with borders when clipped by parent. (#6765, #3752, #7428)
 - Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow
   hacking in custom cursors if desirable.
 - Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos]
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index 9a6e06a2d743..e82e8777fed1 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1261,7 +1261,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
     if (table->Flags & ImGuiTableFlags_NoClip)
         table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
     else
-        inner_window->DrawList->PushClipRect(inner_window->InnerClipRect.Min, inner_window->InnerClipRect.Max, false);
+        inner_window->DrawList->PushClipRect(inner_window->InnerClipRect.Min, inner_window->InnerClipRect.Max, false); // FIXME: use table->InnerClipRect?
 }
 
 // Process hit-testing on resizing borders. Actual size change will be applied in EndTable()
@@ -2011,7 +2011,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
     {
         for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
             table->Columns[column_n].NavLayerCurrent = ImGuiNavLayer_Main;
-        const float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y);
+        const float y0 = ImMax(table->RowPosY2 + 1, table->InnerClipRect.Min.y);
         table_instance->LastFrozenHeight = y0 - table->OuterRect.Min.y;
 
         if (unfreeze_rows_actual)
@@ -2020,8 +2020,8 @@ void ImGui::TableEndRow(ImGuiTable* table)
             table->IsUnfrozenRows = true;
 
             // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
-            table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
-            table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y;
+            table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, table->InnerClipRect.Max.y);
+            table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = table->InnerClipRect.Max.y;
             table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen;
             IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y);
 

From 71714eab5367d2fa119e36be30148278e0d5974f Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 17 Sep 2024 18:09:02 +0200
Subject: [PATCH 134/548] Tables: fixed assertion related to inconsistent outer
 clipping when sizes are not rounded. (#7957)

---
 docs/CHANGELOG.txt | 3 ++-
 imgui.h            | 2 +-
 imgui_tables.cpp   | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 8d640533cc45..566e42608de1 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -70,7 +70,8 @@ Other changes:
   (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
   This is the first step toward more refactoring. (#7925) [@alektron, @ocornut]
 - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
-- Tables: fixes an assertion with tables with borders when clipped by parent. (#6765, #3752, #7428)
+- Tables: fixed assertion related to inconsistent outer clipping when sizes are not rounded. (#7957) [@eclbtownsend]
+- Tables: fixed assertion with tables with borders when clipped by parent. (#6765, #3752, #7428)
 - Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow
   hacking in custom cursors if desirable.
 - Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos]
diff --git a/imgui.h b/imgui.h
index 095c250025e4..854d210e167a 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.2 WIP"
-#define IMGUI_VERSION_NUM   19114
+#define IMGUI_VERSION_NUM   19115
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index e82e8777fed1..d9844586bd05 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -328,7 +328,7 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
     // - always performing the GetOrAddByKey() O(log N) query in g.Tables.Map[].
     const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0;
     const ImVec2 avail_size = GetContentRegionAvail();
-    const ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f);
+    const ImVec2 actual_outer_size = ImTrunc(CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f));
     const ImRect outer_rect(outer_window->DC.CursorPos, outer_window->DC.CursorPos + actual_outer_size);
     const bool outer_window_is_measuring_size = (outer_window->AutoFitFramesX > 0) || (outer_window->AutoFitFramesY > 0); // Doesn't apply to AlwaysAutoResize windows!
     if (use_child_window && IsClippedEx(outer_rect, 0) && !outer_window_is_measuring_size)

From dad9f45e3ed9968b7873f3ed4a41ac0339befafa Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 17 Sep 2024 18:27:31 +0200
Subject: [PATCH 135/548] Windows: fixed an issue where double-click to
 collapse could be triggered even while another item is active. (#7841, #7369)

---
 docs/CHANGELOG.txt | 2 ++
 imgui.cpp          | 5 +++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 566e42608de1..9e31a1011f4d 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -72,6 +72,8 @@ Other changes:
 - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
 - Tables: fixed assertion related to inconsistent outer clipping when sizes are not rounded. (#7957) [@eclbtownsend]
 - Tables: fixed assertion with tables with borders when clipped by parent. (#6765, #3752, #7428)
+- Windows: fixed an issue where double-click to collapse could be triggered even while another
+  item is active, if the item didn't use the left mouse button. (#7841)
 - Misc: Made it accepted to call SetMouseCursor() with any out-of-bound value, as a way to allow
   hacking in custom cursors if desirable.
 - Fonts: fixed ellipsis "..." rendering width miscalculation bug introduced in 1.91.0. (#7976) [@DDeimos]
diff --git a/imgui.cpp b/imgui.cpp
index bdeda3fe7dd5..369e582d74a1 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -6948,9 +6948,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
         // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing
         if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse))
         {
-            // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar.
+            // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed),
+            // so verify that we don't have items over the title bar.
             ImRect title_bar_rect = window->TitleBarRect();
-            if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
+            if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && g.ActiveId == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
                 if (g.IO.MouseClickedCount[0] == 2 && GetKeyOwner(ImGuiKey_MouseLeft) == ImGuiKeyOwner_NoOwner)
                     window->WantCollapseToggle = true;
             if (window->WantCollapseToggle)

From 6aade6912a107204d15ebe7171434ee21a91c629 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 17 Sep 2024 18:52:12 +0200
Subject: [PATCH 136/548] Inputs: SetNextItemShortcut() with
 ImGuiInputFlags_Tooltip doesn't show tooltip when item is active.

---
 docs/CHANGELOG.txt | 1 +
 imgui.cpp          | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 9e31a1011f4d..475daa5963fd 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -65,6 +65,7 @@ Other changes:
 - Nav: pressing any keyboard key while holding Alt disable toggling nav layer on Alt release. (#4439)
 - MultiSelect+Tables: fixed an issue where box-select would skip items while drag-scrolling
   in a table with outer borders. (#7970, #7821).
+- Inputs: SetNextItemShortcut() with ImGuiInputFlags_Tooltip doesn't show tooltip when item is active.
 - InputText: internal refactoring to simplify and optimize the code. The ImWchar buffer has been
   removed. Simplifications allowed to implement new optimizations for handling very large text buffers
   (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
diff --git a/imgui.cpp b/imgui.cpp
index 369e582d74a1..9dddb55c25cd 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4343,7 +4343,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
 
         // Display shortcut (only works with mouse)
         // (ImGuiItemStatusFlags_HasShortcut in LastItemData denotes we want a tooltip)
-        if (id == g.LastItemData.ID && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasShortcut))
+        if (id == g.LastItemData.ID && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasShortcut) && g.ActiveId != id)
             if (IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_DelayNormal))
                 SetTooltip("%s", GetKeyChordName(g.LastItemData.Shortcut));
     }

From e648dbb59d24c29a2e2ac964777822e96befd808 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 17 Sep 2024 20:34:54 +0200
Subject: [PATCH 137/548] Tables: fixed auto-width columns when using
 synced-instances of same table. (#7218)

Amend d3c3514a5
---
 docs/CHANGELOG.txt | 2 ++
 imgui_tables.cpp   | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 475daa5963fd..de022c1ae82d 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -71,6 +71,8 @@ Other changes:
   (e.g. in our testing, handling of a 1 MB text buffer is now 3 times faster in VS2022 Debug build).
   This is the first step toward more refactoring. (#7925) [@alektron, @ocornut]
 - InputText: added CJK double-width punctuation to list of separators considered for CTRL+Arrow.
+- Tables: fixed auto-width columns when using synced-instances of same table. The previous fix
+  done in v1.90.5 was incomplete. (#7218)
 - Tables: fixed assertion related to inconsistent outer clipping when sizes are not rounded. (#7957) [@eclbtownsend]
 - Tables: fixed assertion with tables with borders when clipped by parent. (#6765, #3752, #7428)
 - Windows: fixed an issue where double-click to collapse could be triggered even while another
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index d9844586bd05..c3fb531ef1f4 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -866,7 +866,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
 
         // Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping)
         // Combine width from regular rows + width from headers unless requested not to.
-        if (!column->IsPreserveWidthAuto)
+        if (!column->IsPreserveWidthAuto && table->InstanceCurrent == 0)
             column->WidthAuto = TableGetColumnWidthAuto(table, column);
 
         // Non-resizable columns keep their requested width (apply user value regardless of IsPreserveWidthAuto)

From f7ba6453980824aa4a7d096841576285efa7f6ec Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 17 Sep 2024 21:07:15 +0200
Subject: [PATCH 138/548] InputText: fixed not filling callback's SelectionEnd.
 (#7925)

Broken by abd07f6
---
 imgui_widgets.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 4156ce8af80e..27610228d24f 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4977,7 +4977,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
 
                     const int utf8_cursor_pos = callback_data.CursorPos = state->Stb->cursor;
                     const int utf8_selection_start = callback_data.SelectionStart = state->Stb->select_start;
-                    const int utf8_selection_end = state->Stb->select_end;
+                    const int utf8_selection_end = callback_data.SelectionEnd = state->Stb->select_end;
 
                     // Call user code
                     callback(&callback_data);

From cfae5ac71b903d8b5d04cce8f6329765e64af185 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 19 Sep 2024 14:09:45 +0200
Subject: [PATCH 139/548] Backends: make ImGui_ImplSDL2_KeyEventToImGuiKey(),
 ImGui_ImplSDL3_KeyEventToImGuiKey(), ImGui_ImplGlfw_KeyToImGuiKey(),
 ImGui_ImplWin32_KeyEventToImGuiKey(), ImGui_ImplAllegro5_KeyCodeToImGuiKey(),
 ImGui_ImplOSX_KeyCodeToImGuiKey(), non-static. (#7997)

Backends: Win32: Refactor ImGui_ImplWin32_KeyEventToImGuiKey() logic.
Ref #7672
---
 backends/imgui_impl_allegro5.cpp |  3 ++-
 backends/imgui_impl_glfw.cpp     | 10 +++++++---
 backends/imgui_impl_osx.mm       |  4 +++-
 backends/imgui_impl_sdl2.cpp     |  3 ++-
 backends/imgui_impl_sdl3.cpp     |  3 ++-
 backends/imgui_impl_win32.cpp    | 20 +++++++++-----------
 6 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp
index e41f021401d0..bf1019e2c952 100644
--- a/backends/imgui_impl_allegro5.cpp
+++ b/backends/imgui_impl_allegro5.cpp
@@ -310,7 +310,8 @@ static void ImGui_ImplAllegro5_SetClipboardText(ImGuiContext*, const char* text)
 }
 #endif
 
-static ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code)
+// Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code)
 {
     switch (key_code)
     {
diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp
index 30afaf4f0eeb..7134d3e55448 100644
--- a/backends/imgui_impl_glfw.cpp
+++ b/backends/imgui_impl_glfw.cpp
@@ -185,9 +185,12 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
 }
 
 // Functions
-static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key)
+
+// Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode)
 {
-    switch (key)
+    IM_UNUSED(scancode);
+    switch (keycode)
     {
         case GLFW_KEY_TAB: return ImGuiKey_Tab;
         case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow;
@@ -355,6 +358,7 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
     io.AddMouseWheelEvent((float)xoffset, (float)yoffset);
 }
 
+// FIXME: should this be baked into ImGui_ImplGlfw_KeyToImGuiKey()? then what about the values passed to io.SetKeyEventNativeData()?
 static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode)
 {
 #if GLFW_HAS_GETKEYNAME && !defined(EMSCRIPTEN_USE_EMBEDDED_GLFW3)
@@ -402,7 +406,7 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, i
     keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode);
 
     ImGuiIO& io = ImGui::GetIO();
-    ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode);
+    ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode, scancode);
     io.AddKeyEvent(imgui_key, (action == GLFW_PRESS));
     io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code)
 }
diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm
index 870038d85084..3115bf1c2144 100644
--- a/backends/imgui_impl_osx.mm
+++ b/backends/imgui_impl_osx.mm
@@ -259,7 +259,9 @@ - (void)onApplicationBecomeInactive:(NSNotification*)aNotification
 @end
 
 // Functions
-static ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code)
+
+// Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code)
 {
     switch (key_code)
     {
diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp
index 027dff9f2fd5..6d98a697eea0 100644
--- a/backends/imgui_impl_sdl2.cpp
+++ b/backends/imgui_impl_sdl2.cpp
@@ -180,7 +180,8 @@ static void ImGui_ImplSDL2_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImG
     }
 }
 
-static ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode)
+// Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode)
 {
     IM_UNUSED(scancode);
     switch (keycode)
diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp
index 540b6931af0c..6819f546dca9 100644
--- a/backends/imgui_impl_sdl3.cpp
+++ b/backends/imgui_impl_sdl3.cpp
@@ -159,7 +159,8 @@ static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* view
     }
 }
 
-static ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode)
+// Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode)
 {
     // Keypad doesn't have individual key values in SDL3
     switch (scancode)
diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp
index 758e70d01a54..0e9164efe521 100644
--- a/backends/imgui_impl_win32.cpp
+++ b/backends/imgui_impl_win32.cpp
@@ -419,12 +419,14 @@ void    ImGui_ImplWin32_NewFrame()
     ImGui_ImplWin32_UpdateGamepads();
 }
 
-// There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED, we assign it an arbitrary value to make code more readable (VK_ codes go up to 255)
-#define IM_VK_KEYPAD_ENTER      (VK_RETURN + 256)
-
 // Map VK_xxx to ImGuiKey_xxx.
-static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam)
+// Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam)
 {
+    // There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED.
+    if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED))
+        return ImGuiKey_KeypadEnter;
+
     switch (wParam)
     {
         case VK_TAB: return ImGuiKey_Tab;
@@ -473,7 +475,6 @@ static ImGuiKey ImGui_ImplWin32_VirtualKeyToImGuiKey(WPARAM wParam)
         case VK_MULTIPLY: return ImGuiKey_KeypadMultiply;
         case VK_SUBTRACT: return ImGuiKey_KeypadSubtract;
         case VK_ADD: return ImGuiKey_KeypadAdd;
-        case IM_VK_KEYPAD_ENTER: return ImGuiKey_KeypadEnter;
         case VK_LSHIFT: return ImGuiKey_LeftShift;
         case VK_LCONTROL: return ImGuiKey_LeftCtrl;
         case VK_LMENU: return ImGuiKey_LeftAlt;
@@ -692,12 +693,9 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
             // Submit modifiers
             ImGui_ImplWin32_UpdateKeyModifiers();
 
-            // Obtain virtual key code
-            // (keypad enter doesn't have its own... VK_RETURN with KF_EXTENDED flag means keypad enter, see IM_VK_KEYPAD_ENTER definition for details, it is mapped to ImGuiKey_KeyPadEnter.)
-            int vk = (int)wParam;
-            if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED))
-                vk = IM_VK_KEYPAD_ENTER;
-            const ImGuiKey key = ImGui_ImplWin32_VirtualKeyToImGuiKey(vk);
+            // Obtain virtual key code and convert to ImGuiKey
+            const ImGuiKey key = ImGui_ImplWin32_KeyEventToImGuiKey(wParam, lParam);
+            const int vk = (int)wParam;
             const int scancode = (int)LOBYTE(HIWORD(lParam));
 
             // Special behavior for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit the key down event.

From a9f72ab6818c3e55544378aa44c7659de7e5510f Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 19 Sep 2024 14:33:03 +0200
Subject: [PATCH 140/548] Version 1.91.2

---
 docs/CHANGELOG.txt | 6 +++---
 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, 12 insertions(+), 12 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index de022c1ae82d..6971e3e4a35e 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -36,10 +36,10 @@ HOW TO UPDATE?
 - Please report any issue!
 
 -----------------------------------------------------------------------
- VERSION 1.91.2 WIP (In Progress)
+ VERSION 1.91.2 (Released 2024-09-19)
 -----------------------------------------------------------------------
 
-Breaking changes:
+Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.2
 
 Other changes:
 
@@ -54,7 +54,7 @@ Other changes:
   - I've been wanting to add this tool for a long time, but was stalled by finding a way to
     not make it spammy + make it practically zero cost. After @pthom made various proposals to
     solve the same problem (thanks for pushing me!), I decided it was time to finish it.
-  - Added ImGuiItemFlags_AllowDuplicateId to use with PushItemFlag/PopItemFlag() if for some
+  - Added ImGuiItemFlags_AllowDuplicateId to use with PushItemFlag()/PopItemFlag() if for some
     reason you intend to have duplicate identifiers.
   - (#74, #96, #480, #501, #647, #654, #719, #843, #894, #1057, #1173, #1390, #1414, #1556, #1768,
      #2041, #2116, #2330, #2475, #2562, #2667, #2807, #2885, #3102, #3375, #3526, #3964, #4008,
diff --git a/imgui.cpp b/imgui.cpp
index 9dddb55c25cd..cfce32acaa34 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2 WIP
+// dear imgui, v1.91.2
 // (main code and documentation)
 
 // Help:
diff --git a/imgui.h b/imgui.h
index 854d210e167a..a75f32b34169 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2 WIP
+// dear imgui, v1.91.2
 // (headers)
 
 // Help:
@@ -28,8 +28,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.2 WIP"
-#define IMGUI_VERSION_NUM   19115
+#define IMGUI_VERSION       "1.91.2"
+#define IMGUI_VERSION_NUM   19120
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index cc21099a8872..ebcc64f9dd63 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2 WIP
+// dear imgui, v1.91.2
 // (demo code)
 
 // Help:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 79270f1a1fd6..80bef6fe0161 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2 WIP
+// dear imgui, v1.91.2
 // (drawing and font code)
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index b54848635b27..b50b965f66b7 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2 WIP
+// dear imgui, v1.91.2
 // (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 c3fb531ef1f4..023e3f32a5ef 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2 WIP
+// dear imgui, v1.91.2
 // (tables and columns code)
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 27610228d24f..348a3dce07f3 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2 WIP
+// dear imgui, v1.91.2
 // (widgets code)
 
 /*

From faca859043cf42fb31f74a435def167b64a52516 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 19 Sep 2024 15:51:06 +0200
Subject: [PATCH 141/548] Version 1.91.3 WIP

---
 docs/CHANGELOG.txt | 9 +++++++++
 imgui.cpp          | 3 ++-
 imgui.h            | 6 +++---
 imgui_demo.cpp     | 2 +-
 imgui_draw.cpp     | 2 +-
 imgui_internal.h   | 4 ++--
 imgui_tables.cpp   | 2 +-
 imgui_widgets.cpp  | 2 +-
 8 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 6971e3e4a35e..cd1c80d9c1e3 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.3 WIP (In Progress)
+-----------------------------------------------------------------------
+
+Breaking changes:
+
+Other changes:
+
+
 -----------------------------------------------------------------------
  VERSION 1.91.2 (Released 2024-09-19)
 -----------------------------------------------------------------------
diff --git a/imgui.cpp b/imgui.cpp
index cfce32acaa34..e82826792a85 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2
+// dear imgui, v1.91.3 WIP
 // (main code and documentation)
 
 // Help:
@@ -7736,6 +7736,7 @@ void ImGui::PopItemFlag()
 // - Feedback welcome at https://github.com/ocornut/imgui/issues/211
 // - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it.
 // - Optimized shortcuts instead of PushStyleVar() + PushItemFlag()
+// - Note: mixing up BeginDisabled() and PushItemFlag(ImGuiItemFlags_Disabled) is currently NOT SUPPORTED.
 void ImGui::BeginDisabled(bool disabled)
 {
     ImGuiContext& g = *GImGui;
diff --git a/imgui.h b/imgui.h
index a75f32b34169..a2aab8a63608 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2
+// dear imgui, v1.91.3 WIP
 // (headers)
 
 // Help:
@@ -28,8 +28,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.2"
-#define IMGUI_VERSION_NUM   19120
+#define IMGUI_VERSION       "1.91.3 WIP"
+#define IMGUI_VERSION_NUM   19121
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index ebcc64f9dd63..5eb64e4702cf 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2
+// dear imgui, v1.91.3 WIP
 // (demo code)
 
 // Help:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 80bef6fe0161..b7a00285feba 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2
+// dear imgui, v1.91.3 WIP
 // (drawing and font code)
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index b50b965f66b7..cb404645726a 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2
+// dear imgui, v1.91.3 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.
@@ -834,7 +834,7 @@ enum ImGuiDataTypePrivate_
 enum ImGuiItemFlagsPrivate_
 {
     // Controlled by user
-    ImGuiItemFlags_Disabled                 = 1 << 10, // false     // Disable interactions (DOES NOT affect visuals, see BeginDisabled()/EndDisabled() for full disable feature, and github #211).
+    ImGuiItemFlags_Disabled                 = 1 << 10, // false     // Disable interactions (DOES NOT affect visuals. DO NOT mix direct use of this with BeginDisabled(). See BeginDisabled()/EndDisabled() for full disable feature, and github #211).
     ImGuiItemFlags_ReadOnly                 = 1 << 11, // false     // [ALPHA] Allow hovering interactions but underlying value is not changed.
     ImGuiItemFlags_MixedValue               = 1 << 12, // false     // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
     ImGuiItemFlags_NoWindowHoverableCheck   = 1 << 13, // false     // Disable hoverable check in ItemHoverable()
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index 023e3f32a5ef..dc7f210986f2 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2
+// dear imgui, v1.91.3 WIP
 // (tables and columns code)
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 348a3dce07f3..f2c5b8a0ce73 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.2
+// dear imgui, v1.91.3 WIP
 // (widgets code)
 
 /*

From 0af2c4ef765ff37004f1ee6e4ee5a40429f68fb9 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 19 Sep 2024 16:02:23 +0200
Subject: [PATCH 142/548] Backends: SDL3: Update for API changes: SDL_bool
 removal. SDL_INIT_TIMER removal. (#7999)

---
 backends/imgui_impl_sdl3.cpp                | 2 +-
 backends/imgui_impl_sdlrenderer3.cpp        | 4 ++--
 docs/CHANGELOG.txt                          | 2 ++
 examples/example_sdl3_opengl3/main.cpp      | 2 +-
 examples/example_sdl3_sdlrenderer3/main.cpp | 2 +-
 5 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp
index 6819f546dca9..599d3fc445ab 100644
--- a/backends/imgui_impl_sdl3.cpp
+++ b/backends/imgui_impl_sdl3.cpp
@@ -564,7 +564,7 @@ static void ImGui_ImplSDL3_UpdateMouseData()
     // We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused (below)
 #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
     // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside
-    SDL_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE);
+    SDL_CaptureMouse(bd->MouseButtonsDown != 0);
     SDL_Window* focused_window = SDL_GetKeyboardFocus();
     const bool is_app_focused = (bd->Window == focused_window);
 #else
diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp
index d3926c2fbf6a..30f967bd3677 100644
--- a/backends/imgui_impl_sdlrenderer3.cpp
+++ b/backends/imgui_impl_sdlrenderer3.cpp
@@ -158,8 +158,8 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
         SDL_Rect    ClipRect;
     };
     BackupSDLRendererState old = {};
-    old.ViewportEnabled = SDL_RenderViewportSet(renderer) == SDL_TRUE;
-    old.ClipEnabled = SDL_RenderClipEnabled(renderer) == SDL_TRUE;
+    old.ViewportEnabled = SDL_RenderViewportSet(renderer);
+    old.ClipEnabled = SDL_RenderClipEnabled(renderer);
     SDL_GetRenderViewport(renderer, &old.Viewport);
     SDL_GetRenderClipRect(renderer, &old.ClipRect);
 
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index cd1c80d9c1e3..8c1a815e9302 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,8 @@ Breaking changes:
 
 Other changes:
 
+- Backends: SDL3: Update for API changes: SDL_bool removal. SDL_INIT_TIMER removal.
+
 
 -----------------------------------------------------------------------
  VERSION 1.91.2 (Released 2024-09-19)
diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp
index 0ba09dc937cc..e7f239f4769b 100644
--- a/examples/example_sdl3_opengl3/main.cpp
+++ b/examples/example_sdl3_opengl3/main.cpp
@@ -27,7 +27,7 @@
 int main(int, char**)
 {
     // Setup SDL
-    if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD))
+    if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
     {
         printf("Error: SDL_Init(): %s\n", SDL_GetError());
         return -1;
diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp
index ef98d752d5e9..4b9b86e9bd5a 100644
--- a/examples/example_sdl3_sdlrenderer3/main.cpp
+++ b/examples/example_sdl3_sdlrenderer3/main.cpp
@@ -25,7 +25,7 @@
 int main(int, char**)
 {
     // Setup SDL
-    if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD))
+    if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
     {
         printf("Error: SDL_Init(): %s\n", SDL_GetError());
         return -1;

From d0750ee4e7d9de2605ad3f2fe60f9089dd03a4c1 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 19 Sep 2024 16:13:21 +0200
Subject: [PATCH 143/548] Error check: clarified that carriage returns are
 emitted by our code. Added helper default callback. Comments. (#1651)

(doesn't affect test engine hook for it as trailing \n are trimmed anyhow)
---
 imgui.cpp        | 52 ++++++++++++++++++++++++++++++++----------------
 imgui_internal.h |  8 ++++++--
 2 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index e82826792a85..45f6ce36dae1 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -79,7 +79,7 @@ CODE
 // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
 // [SECTION] ID STACK
 // [SECTION] INPUTS
-// [SECTION] ERROR CHECKING
+// [SECTION] ERROR CHECKING, STATE RECOVERY
 // [SECTION] ITEM SUBMISSION
 // [SECTION] LAYOUT
 // [SECTION] SCROLLING
@@ -7734,7 +7734,8 @@ void ImGui::PopItemFlag()
 // - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled)
 // - Visually this is currently altering alpha, but it is expected that in a future styling system this would work differently.
 // - Feedback welcome at https://github.com/ocornut/imgui/issues/211
-// - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it.
+// - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions.
+//   (as a micro-optimisation if you can avoid calling BeginDisabled(false)/EndDisabled() tens of thousands of times by doing a local check, it won't hurt)
 // - Optimized shortcuts instead of PushStyleVar() + PushItemFlag()
 // - Note: mixing up BeginDisabled() and PushItemFlag(ImGuiItemFlags_Disabled) is currently NOT SUPPORTED.
 void ImGui::BeginDisabled(bool disabled)
@@ -10069,7 +10070,15 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own
 
 
 //-----------------------------------------------------------------------------
-// [SECTION] ERROR CHECKING
+// [SECTION] ERROR CHECKING, STATE RECOVERY
+//-----------------------------------------------------------------------------
+// - DebugCheckVersionAndDataLayout() (called via IMGUI_CHECKVERSION() macros)
+// - ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
+// - ErrorCheckNewFrameSanityChecks()
+// - ErrorCheckEndFrameSanityChecks()
+// - ErrorCheckEndFrameRecover()
+// - ErrorCheckEndWindowRecover()
+// - ImGuiStackSizes
 //-----------------------------------------------------------------------------
 
 // Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues.
@@ -10215,6 +10224,15 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
     IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!");
 }
 
+// Default implementation of ImGuiErrorLogCallback that pipe errors to DebugLog: appears in tty + Tools->DebugLog
+void    ImGui::ErrorLogCallbackToDebugLog(void*, const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    ImGui::DebugLogV(fmt, args);
+    va_end(args);
+}
+
 // Experimental recovery from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls.
 // Must be called during or before EndFrame().
 // This is generally flawed as we are not necessarily End/Popping things in the right order.
@@ -10235,12 +10253,12 @@ void    ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi
         }
         if (window->Flags & ImGuiWindowFlags_ChildWindow)
         {
-            if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'", window->Name);
+            if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'\n", window->Name);
             EndChild();
         }
         else
         {
-            if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'", window->Name);
+            if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'\n", window->Name);
             End();
         }
     }
@@ -10252,7 +10270,7 @@ void    ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
     ImGuiContext& g = *GImGui;
     while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow))
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'\n", g.CurrentTable->OuterWindow->Name);
         EndTable();
     }
 
@@ -10261,32 +10279,32 @@ void    ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
     IM_ASSERT(window != NULL);
     while (g.CurrentTabBar != NULL) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'\n", window->Name);
         EndTabBar();
     }
     while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window)
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing EndMultiSelect() in '%s'", window->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing EndMultiSelect() in '%s'\n", window->Name);
         EndMultiSelect();
     }
     while (window->DC.TreeDepth > 0)
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'\n", window->Name);
         TreePop();
     }
     while (g.GroupStack.Size > stack_sizes->SizeOfGroupStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'\n", window->Name);
         EndGroup();
     }
     while (window->IDStack.Size > 1)
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'\n", window->Name);
         PopID();
     }
     while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'\n", window->Name);
         if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
             EndDisabled();
         else
@@ -10297,27 +10315,27 @@ void    ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
     }
     while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(g.ColorStack.back().Col));
+        if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s\n", window->Name, GetStyleColorName(g.ColorStack.back().Col));
         PopStyleColor();
     }
     while (g.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'", window->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'\n", window->Name);
         PopItemFlag();
     }
     while (g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'\n", window->Name);
         PopStyleVar();
     }
     while (g.FontStack.Size > stack_sizes->SizeOfFontStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopFont() in '%s'", window->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing PopFont() in '%s'\n", window->Name);
         PopFont();
     }
     while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack + 1) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name);
+        if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'\n", window->Name);
         PopFocusScope();
     }
 }
diff --git a/imgui_internal.h b/imgui_internal.h
index cb404645726a..14b56e8a0f30 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1259,6 +1259,7 @@ struct ImGuiTreeNodeStackData
     ImRect                  NavRect;    // Used for nav landing
 };
 
+// sizeof() = 18
 struct IMGUI_API ImGuiStackSizes
 {
     short   SizeOfIDStack;
@@ -3606,11 +3607,14 @@ namespace ImGui
     IMGUI_API void          GcCompactTransientWindowBuffers(ImGuiWindow* window);
     IMGUI_API void          GcAwakeTransientWindowBuffers(ImGuiWindow* window);
 
-    // Debug Tools
-    IMGUI_API void          DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
+    // Error Checking, State Recovery
+    IMGUI_API void          ErrorLogCallbackToDebugLog(void* user_data, const char* fmt, ...);
     IMGUI_API void          ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
     IMGUI_API void          ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
     IMGUI_API void          ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
+
+    // Debug Tools
+    IMGUI_API void          DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
     IMGUI_API void          DebugDrawCursorPos(ImU32 col = IM_COL32(255, 0, 0, 255));
     IMGUI_API void          DebugDrawLineExtents(ImU32 col = IM_COL32(255, 0, 0, 255));
     IMGUI_API void          DebugDrawItemRect(ImU32 col = IM_COL32(255, 0, 0, 255));

From 4aeae5d71891bffe270f4bdd181796962d183bda Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 20 Sep 2024 17:27:51 +0200
Subject: [PATCH 144/548] Error check: fixed build when using
 IMGUI_DISABLE_DEBUG_TOOLS.

---
 imgui.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/imgui.cpp b/imgui.cpp
index 45f6ce36dae1..4b9daf9d2a74 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -10227,10 +10227,14 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
 // Default implementation of ImGuiErrorLogCallback that pipe errors to DebugLog: appears in tty + Tools->DebugLog
 void    ImGui::ErrorLogCallbackToDebugLog(void*, const char* fmt, ...)
 {
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
     va_list args;
     va_start(args, fmt);
-    ImGui::DebugLogV(fmt, args);
+    DebugLogV(fmt, args);
     va_end(args);
+#else
+    IM_UNUSED(fmt);
+#endif
 }
 
 // Experimental recovery from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls.

From a727332e7727a912586c2ded504a0be1eabfa5dc Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 20 Sep 2024 18:08:13 +0200
Subject: [PATCH 145/548] Scrollbar: Shift+Click always use absolute
 positionning scroll. (#8002, #7328)

---
 docs/CHANGELOG.txt | 2 ++
 imgui_widgets.cpp  | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 8c1a815e9302..99ca1f13476a 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,8 @@ Breaking changes:
 
 Other changes:
 
+- Scrollbar: Shift+Click always use absolute positionning scroll (which was the default
+  before 1.90.8). (#8002, #7328)
 - Backends: SDL3: Update for API changes: SDL_bool removal. SDL_INIT_TIMER removal.
 
 
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index f2c5b8a0ce73..e50452eb63dc 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1000,8 +1000,8 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
         if (g.ActiveIdIsJustActivated)
         {
             // On initial click calculate the distance between mouse and the center of the grab
-            g.ScrollbarSeekMode = (short)held_dir;
-            g.ScrollbarClickDeltaToGrabCenter = (g.ScrollbarSeekMode == 0.0f) ? clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f : 0.0f;
+            g.ScrollbarSeekMode = g.IO.KeyShift ? 0 : (short)held_dir;
+            g.ScrollbarClickDeltaToGrabCenter = (g.ScrollbarSeekMode == 0 && !g.IO.KeyShift) ? clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f : 0.0f;
         }
 
         // Apply scroll (p_scroll_v will generally point on one member of window->Scroll)

From fb410463e6a27c4486ac262c3f246543154a49e0 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 20 Sep 2024 18:40:32 +0200
Subject: [PATCH 146/548] Scrollbar: added io.ConfigScrollbarScrollByPage
 setting. (#8002, #7328)

---
 docs/CHANGELOG.txt | 5 +++--
 imgui.cpp          | 1 +
 imgui.h            | 1 +
 imgui_demo.cpp     | 2 ++
 imgui_internal.h   | 4 ++--
 imgui_widgets.cpp  | 7 ++++---
 6 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 99ca1f13476a..fac869de69a9 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,8 +43,9 @@ Breaking changes:
 
 Other changes:
 
-- Scrollbar: Shift+Click always use absolute positionning scroll (which was the default
-  before 1.90.8). (#8002, #7328)
+- Scrollbar: Shift+Click scroll to clicked location (pre-1.90.8 default). (#8002, #7328)
+- Scrollbar: added io.ConfigScrollbarScrollByPage setting (default to true). (#8002, #7328)
+  Set io.ConfigScrollbarScrollByPage=false to enforce always scrolling to clicked location.
 - Backends: SDL3: Update for API changes: SDL_bool removal. SDL_INIT_TIMER removal.
 
 
diff --git a/imgui.cpp b/imgui.cpp
index 4b9daf9d2a74..bbe78dc54ad4 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1394,6 +1394,7 @@ ImGuiIO::ImGuiIO()
     ConfigDragClickToInputText = false;
     ConfigWindowsResizeFromEdges = true;
     ConfigWindowsMoveFromTitleBarOnly = false;
+    ConfigScrollbarScrollByPage = true;
     ConfigMemoryCompactTimer = 60.0f;
     ConfigDebugIsDebuggerPresent = false;
     ConfigDebugHighlightIdConflicts = true;
diff --git a/imgui.h b/imgui.h
index a2aab8a63608..b97a4097e820 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2250,6 +2250,7 @@ struct ImGuiIO
     bool        ConfigDragClickToInputText;     // = false          // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
     bool        ConfigWindowsResizeFromEdges;   // = true           // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
     bool        ConfigWindowsMoveFromTitleBarOnly; // = false       // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
+    bool        ConfigScrollbarScrollByPage;    // = true           // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
     float       ConfigMemoryCompactTimer;       // = 60.0f          // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
 
     // Inputs Behaviors
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 5eb64e4702cf..c2d110dd15c9 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -539,6 +539,8 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
             ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
             ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
+            ImGui::Checkbox("io.ConfigScrollbarScrollByPage", &io.ConfigScrollbarScrollByPage);
+            ImGui::SameLine(); HelpMarker("Enable scrolling page by page when clicking outside the scrollbar grab.\nWhen disabled, always scroll to clicked location.\nWhen enabled, Shift+Click scrolls to clicked location.");
             ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);
             ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
             ImGui::Text("Also see Style->Rendering for rendering options.");
diff --git a/imgui_internal.h b/imgui_internal.h
index 14b56e8a0f30..664648427989 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2259,8 +2259,8 @@ struct ImGuiContext
     ImGuiComboPreviewData   ComboPreviewData;
     ImRect                  WindowResizeBorderExpectedRect;     // Expected border rect, switch to relative edit if moving
     bool                    WindowResizeRelativeMode;
-    short                   ScrollbarSeekMode;                  // 0: relative, -1/+1: prev/next page.
-    float                   ScrollbarClickDeltaToGrabCenter;    // Distance between mouse and center of grab box, normalized in parent space. Use storage?
+    short                   ScrollbarSeekMode;                  // 0: scroll to clicked location, -1/+1: prev/next page.
+    float                   ScrollbarClickDeltaToGrabCenter;    // When scrolling to mouse location: distance between mouse and center of grab box, normalized in parent space.
     float                   SliderGrabClickOffset;
     float                   SliderCurrentAccum;                 // Accumulated slider delta when using navigation controls.
     bool                    SliderCurrentAccumDirty;            // Has the accumulated slider delta changed since last time we tried to apply it?
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index e50452eb63dc..91328d211fed 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -999,9 +999,10 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
         const int held_dir = (clicked_v_norm < grab_v_norm) ? -1 : (clicked_v_norm > grab_v_norm + grab_h_norm) ? +1 : 0;
         if (g.ActiveIdIsJustActivated)
         {
-            // On initial click calculate the distance between mouse and the center of the grab
-            g.ScrollbarSeekMode = g.IO.KeyShift ? 0 : (short)held_dir;
-            g.ScrollbarClickDeltaToGrabCenter = (g.ScrollbarSeekMode == 0 && !g.IO.KeyShift) ? clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f : 0.0f;
+            // On initial click when held_dir == 0 (clicked over grab): calculate the distance between mouse and the center of the grab
+            const bool scroll_to_clicked_location = (g.IO.ConfigScrollbarScrollByPage == false || g.IO.KeyShift || held_dir == 0);
+            g.ScrollbarSeekMode = scroll_to_clicked_location ? 0 : (short)held_dir;
+            g.ScrollbarClickDeltaToGrabCenter = (held_dir == 0 && !g.IO.KeyShift) ? clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f : 0.0f;
         }
 
         // Apply scroll (p_scroll_v will generally point on one member of window->Scroll)

From 7f81fbc54261cd8579e3db8d2c5c7a0155dad58d Mon Sep 17 00:00:00 2001
From: Mark Sibly 
Date: Sun, 22 Sep 2024 16:05:28 +1200
Subject: [PATCH 147/548] Backends: WGPU: Fix new WGPUStringView breaks shader
 compilation. (#8009, #8010)

---
 backends/imgui_impl_wgpu.cpp | 6 ++++--
 docs/CHANGELOG.txt           | 3 ++-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp
index 503ac8efdcd9..4109e392eef5 100644
--- a/backends/imgui_impl_wgpu.cpp
+++ b/backends/imgui_impl_wgpu.cpp
@@ -257,13 +257,15 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
 {
     ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData();
 
-    WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
 #ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
+	WGPUShaderSourceWGSL wgsl_desc = {};
     wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL;
+	wgsl_desc.code = { wgsl_source, WGPU_STRLEN };
 #else
+	WGPUShaderModuleWGSLDescriptor wgsl_desc = {};
     wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
+	wgsl_desc.code = wgsl_source;
 #endif
-    wgsl_desc.code = wgsl_source;
 
     WGPUShaderModuleDescriptor desc = {};
     desc.nextInChain = reinterpret_cast(&wgsl_desc);
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index fac869de69a9..1d7232d9cc8e 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -47,7 +47,8 @@ Other changes:
 - Scrollbar: added io.ConfigScrollbarScrollByPage setting (default to true). (#8002, #7328)
   Set io.ConfigScrollbarScrollByPage=false to enforce always scrolling to clicked location.
 - Backends: SDL3: Update for API changes: SDL_bool removal. SDL_INIT_TIMER removal.
-
+- Backends: WebGPU: Fixed DAWN api change using WGPUStringView in WGPUShaderSourceWGSL.
+  (#8009, #8010) [@blitz-research]
 
 -----------------------------------------------------------------------
  VERSION 1.91.2 (Released 2024-09-19)

From bc77041b57893fb3d04d4df503b483bcc3884e3a Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 23 Sep 2024 16:44:16 +0200
Subject: [PATCH 148/548] Error Handling: fixed an issue
 ErrorCheckEndWindowRecover() when aborting in a child inside a tab bar.
 (#1651)

---
 imgui.cpp         | 5 ++---
 imgui_internal.h  | 3 ++-
 imgui_widgets.cpp | 1 +
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index bbe78dc54ad4..ae614f95d259 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -10242,7 +10242,6 @@ void    ImGui::ErrorLogCallbackToDebugLog(void*, const char* fmt, ...)
 // Must be called during or before EndFrame().
 // This is generally flawed as we are not necessarily End/Popping things in the right order.
 // FIXME: Can't recover from inside BeginTabItem/EndTabItem yet.
-// FIXME: Can't recover from interleaved BeginTabBar/Begin
 void    ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data)
 {
     // PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations"
@@ -10273,7 +10272,7 @@ void    ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi
 void    ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data)
 {
     ImGuiContext& g = *GImGui;
-    while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow))
+    while (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow)
     {
         if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'\n", g.CurrentTable->OuterWindow->Name);
         EndTable();
@@ -10282,7 +10281,7 @@ void    ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
     ImGuiWindow* window = g.CurrentWindow;
     ImGuiStackSizes* stack_sizes = &g.CurrentWindowStack.back().StackSizesOnBegin;
     IM_ASSERT(window != NULL);
-    while (g.CurrentTabBar != NULL) //-V1044
+    while (g.CurrentTabBar != NULL && g.CurrentTabBar->Window == window) //-V1044
     {
         if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'\n", window->Name);
         EndTabBar();
diff --git a/imgui_internal.h b/imgui_internal.h
index 664648427989..013e29b25fed 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2762,9 +2762,10 @@ struct ImGuiTabItem
     ImGuiTabItem()      { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; RequestedWidth = -1.0f; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; }
 };
 
-// Storage for a tab bar (sizeof() 152 bytes)
+// Storage for a tab bar (sizeof() 160 bytes)
 struct IMGUI_API ImGuiTabBar
 {
+    ImGuiWindow*        Window;
     ImVector Tabs;
     ImGuiTabBarFlags    Flags;
     ImGuiID             ID;                     // Zero for tab-bars used by docking
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 91328d211fed..59a912dbdb82 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -9146,6 +9146,7 @@ bool    ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
     // Add to stack
     g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar));
     g.CurrentTabBar = tab_bar;
+    tab_bar->Window = window;
 
     // Append with multiple BeginTabBar()/EndTabBar() pairs.
     tab_bar->BackupCursorPos = window->DC.CursorPos;

From 44a73be6eaf477b5c9a8b6957b789df6fa191a3e Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 24 Sep 2024 20:22:16 +0200
Subject: [PATCH 149/548] TestEngine: log calls don't need testing hook active.

Docs: tweak comments on BeginDisabled(false)/EndDisabled() pairs.
---
 imgui.cpp        | 5 ++---
 imgui.h          | 2 +-
 imgui_internal.h | 2 +-
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index ae614f95d259..cc0be6992c69 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -7735,9 +7735,8 @@ void ImGui::PopItemFlag()
 // - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled)
 // - Visually this is currently altering alpha, but it is expected that in a future styling system this would work differently.
 // - Feedback welcome at https://github.com/ocornut/imgui/issues/211
-// - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions.
-//   (as a micro-optimisation if you can avoid calling BeginDisabled(false)/EndDisabled() tens of thousands of times by doing a local check, it won't hurt)
-// - Optimized shortcuts instead of PushStyleVar() + PushItemFlag()
+// - BeginDisabled(false)/EndDisabled() essentially does nothing but is provided to facilitate use of boolean expressions.
+//   (as a micro-optimization: if you have tens of thousands of BeginDisabled(false)/EndDisabled() pairs, you might want to reformulate your code to avoid making those calls)
 // - Note: mixing up BeginDisabled() and PushItemFlag(ImGuiItemFlags_Disabled) is currently NOT SUPPORTED.
 void ImGui::BeginDisabled(bool disabled)
 {
diff --git a/imgui.h b/imgui.h
index b97a4097e820..f03b7aa1d152 100644
--- a/imgui.h
+++ b/imgui.h
@@ -888,7 +888,7 @@ namespace ImGui
     // - Disable all user interactions and dim items visuals (applying style.DisabledAlpha over current colors)
     // - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled)
     // - Tooltips windows by exception are opted out of disabling.
-    // - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it.
+    // - BeginDisabled(false)/EndDisabled() essentially does nothing but is provided to facilitate use of boolean expressions (as a micro-optimization: if you have tens of thousands of BeginDisabled(false)/EndDisabled() pairs, you might want to reformulate your code to avoid making those calls)
     IMGUI_API void          BeginDisabled(bool disabled = true);
     IMGUI_API void          EndDisabled();
 
diff --git a/imgui_internal.h b/imgui_internal.h
index 013e29b25fed..226d545eeb10 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -3703,7 +3703,7 @@ extern const char*  ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiI
 // In IMGUI_VERSION_NUM >= 18934: changed IMGUI_TEST_ENGINE_ITEM_ADD(bb,id) to IMGUI_TEST_ENGINE_ITEM_ADD(id,bb,item_data);
 #define IMGUI_TEST_ENGINE_ITEM_ADD(_ID,_BB,_ITEM_DATA)      if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _ID, _BB, _ITEM_DATA)    // Register item bounding box
 #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS)      if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS)    // Register item label and status flags (optional)
-#define IMGUI_TEST_ENGINE_LOG(_FMT,...)                     if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__)           // Custom log entry from user land into test log
+#define IMGUI_TEST_ENGINE_LOG(_FMT,...)                     ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__)                                      // Custom log entry from user land into test log
 #else
 #define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID)                 ((void)0)
 #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS)      ((void)g)

From 726aad8e0884b1502ebceb62254a5de73609cd2f Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 24 Sep 2024 20:24:51 +0200
Subject: [PATCH 150/548] Refactor: moved ImGuiContext contructor to imgui.cpp

---
 imgui.cpp        | 205 +++++++++++++++++++++++++++++++++++++++++++++++
 imgui_internal.h | 205 +----------------------------------------------
 2 files changed, 206 insertions(+), 204 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index cc0be6992c69..a0683e671796 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3799,6 +3799,211 @@ static const ImGuiLocEntry GLocalizationEntriesEnUS[] =
     { ImGuiLocKey_CopyLink,             "Copy Link###CopyLink"                  },
 };
 
+ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
+{
+    IO.Ctx = this;
+    InputTextState.Ctx = this;
+
+    Initialized = false;
+    FontAtlasOwnedByContext = shared_font_atlas ? false : true;
+    Font = NULL;
+    FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f;
+    IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
+    Time = 0.0f;
+    FrameCount = 0;
+    FrameCountEnded = FrameCountRendered = -1;
+    WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false;
+    GcCompactAll = false;
+    TestEngineHookItems = false;
+    TestEngine = NULL;
+    memset(ContextName, 0, sizeof(ContextName));
+
+    InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
+    InputEventsNextEventId = 1;
+
+    WindowsActiveCount = 0;
+    CurrentWindow = NULL;
+    HoveredWindow = NULL;
+    HoveredWindowUnderMovingWindow = NULL;
+    HoveredWindowBeforeClear = NULL;
+    MovingWindow = NULL;
+    WheelingWindow = NULL;
+    WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1;
+    WheelingWindowReleaseTimer = 0.0f;
+
+    DebugDrawIdConflicts = 0;
+    DebugHookIdInfo = 0;
+    HoveredId = HoveredIdPreviousFrame = 0;
+    HoveredIdPreviousFrameItemCount = 0;
+    HoveredIdAllowOverlap = false;
+    HoveredIdIsDisabled = false;
+    HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
+    ItemUnclipByLog = false;
+    ActiveId = 0;
+    ActiveIdIsAlive = 0;
+    ActiveIdTimer = 0.0f;
+    ActiveIdIsJustActivated = false;
+    ActiveIdAllowOverlap = false;
+    ActiveIdNoClearOnFocusLoss = false;
+    ActiveIdHasBeenPressedBefore = false;
+    ActiveIdHasBeenEditedBefore = false;
+    ActiveIdHasBeenEditedThisFrame = false;
+    ActiveIdFromShortcut = false;
+    ActiveIdClickOffset = ImVec2(-1, -1);
+    ActiveIdWindow = NULL;
+    ActiveIdSource = ImGuiInputSource_None;
+    ActiveIdMouseButton = -1;
+    ActiveIdPreviousFrame = 0;
+    ActiveIdPreviousFrameIsAlive = false;
+    ActiveIdPreviousFrameHasBeenEditedBefore = false;
+    ActiveIdPreviousFrameWindow = NULL;
+    LastActiveId = 0;
+    LastActiveIdTimer = 0.0f;
+
+    LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0;
+
+    ActiveIdUsingNavDirMask = 0x00;
+    ActiveIdUsingAllKeyboardKeys = false;
+
+    CurrentFocusScopeId = 0;
+    CurrentItemFlags = ImGuiItemFlags_None;
+    DebugShowGroupRects = false;
+
+    NavWindow = NULL;
+    NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
+    NavLayer = ImGuiNavLayer_Main;
+    NavNextActivateId = 0;
+    NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
+    NavHighlightActivatedId = 0;
+    NavHighlightActivatedTimer = 0.0f;
+    NavInputSource = ImGuiInputSource_Keyboard;
+    NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
+    NavIdIsAlive = false;
+    NavMousePosDirty = false;
+    NavDisableHighlight = true;
+    NavDisableMouseHover = false;
+
+    NavAnyRequest = false;
+    NavInitRequest = false;
+    NavInitRequestFromMove = false;
+    NavMoveSubmitted = false;
+    NavMoveScoringItems = false;
+    NavMoveForwardToNextFrame = false;
+    NavMoveFlags = ImGuiNavMoveFlags_None;
+    NavMoveScrollFlags = ImGuiScrollFlags_None;
+    NavMoveKeyMods = ImGuiMod_None;
+    NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
+    NavScoringDebugCount = 0;
+    NavTabbingDir = 0;
+    NavTabbingCounter = 0;
+
+    NavJustMovedFromFocusScopeId = NavJustMovedToId = NavJustMovedToFocusScopeId = 0;
+    NavJustMovedToKeyMods = ImGuiMod_None;
+    NavJustMovedToIsTabbing = false;
+    NavJustMovedToHasSelectionData = false;
+
+    // All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac...
+    // FIXME: Because this value is stored, it annoyingly interfere with toggling io.ConfigMacOSXBehaviors updating this..
+    ConfigNavWindowingKeyNext = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiKey_Tab);
+    ConfigNavWindowingKeyPrev = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab);
+    NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
+    NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
+    NavWindowingToggleLayer = false;
+    NavWindowingToggleKey = ImGuiKey_None;
+
+    DimBgRatio = 0.0f;
+
+    DragDropActive = DragDropWithinSource = DragDropWithinTarget = false;
+    DragDropSourceFlags = ImGuiDragDropFlags_None;
+    DragDropSourceFrameCount = -1;
+    DragDropMouseButton = -1;
+    DragDropTargetId = 0;
+    DragDropAcceptFlags = ImGuiDragDropFlags_None;
+    DragDropAcceptIdCurrRectSurface = 0.0f;
+    DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0;
+    DragDropAcceptFrameCount = -1;
+    DragDropHoldJustPressedId = 0;
+    memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
+
+    ClipperTempDataStacked = 0;
+
+    CurrentTable = NULL;
+    TablesTempDataStacked = 0;
+    CurrentTabBar = NULL;
+    CurrentMultiSelect = NULL;
+    MultiSelectTempDataStacked = 0;
+
+    HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0;
+    HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
+
+    MouseCursor = ImGuiMouseCursor_Arrow;
+    MouseStationaryTimer = 0.0f;
+
+    TempInputId = 0;
+    memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
+    BeginMenuDepth = BeginComboDepth = 0;
+    ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
+    ColorEditCurrentID = ColorEditSavedID = 0;
+    ColorEditSavedHue = ColorEditSavedSat = 0.0f;
+    ColorEditSavedColor = 0;
+    WindowResizeRelativeMode = false;
+    ScrollbarSeekMode = 0;
+    ScrollbarClickDeltaToGrabCenter = 0.0f;
+    SliderGrabClickOffset = 0.0f;
+    SliderCurrentAccum = 0.0f;
+    SliderCurrentAccumDirty = false;
+    DragCurrentAccumDirty = false;
+    DragCurrentAccum = 0.0f;
+    DragSpeedDefaultRatio = 1.0f / 100.0f;
+    DisabledAlphaBackup = 0.0f;
+    DisabledStackSize = 0;
+    LockMarkEdited = 0;
+    TooltipOverrideCount = 0;
+
+    PlatformImeData.InputPos = ImVec2(0.0f, 0.0f);
+    PlatformImeDataPrev.InputPos = ImVec2(-1.0f, -1.0f); // Different to ensure initial submission
+
+    SettingsLoaded = false;
+    SettingsDirtyTimer = 0.0f;
+    HookIdNext = 0;
+
+    memset(LocalizationTable, 0, sizeof(LocalizationTable));
+
+    LogEnabled = false;
+    LogType = ImGuiLogType_None;
+    LogNextPrefix = LogNextSuffix = NULL;
+    LogFile = NULL;
+    LogLinePosY = FLT_MAX;
+    LogLineFirstItem = false;
+    LogDepthRef = 0;
+    LogDepthToExpand = LogDepthToExpandDefault = 2;
+
+    DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY;
+    DebugLocateId = 0;
+    DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
+    DebugLogAutoDisableFrames = 0;
+    DebugLocateFrames = 0;
+    DebugBeginReturnValueCullDepth = -1;
+    DebugItemPickerActive = false;
+    DebugItemPickerMouseButton = ImGuiMouseButton_Left;
+    DebugItemPickerBreakId = 0;
+    DebugFlashStyleColorTime = 0.0f;
+    DebugFlashStyleColorIdx = ImGuiCol_COUNT;
+
+    // Same as DebugBreakClearData(). Those fields are scattered in their respective subsystem to stay in hot-data locations
+    DebugBreakInWindow = 0;
+    DebugBreakInTable = 0;
+    DebugBreakInLocateId = false;
+    DebugBreakKeyChord = ImGuiKey_Pause;
+    DebugBreakInShortcutRouting = ImGuiKey_None;
+
+    memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
+    FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
+    FramerateSecPerFrameAccum = 0.0f;
+    WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
+    memset(TempKeychordName, 0, sizeof(TempKeychordName));
+}
+
 void ImGui::Initialize()
 {
     ImGuiContext& g = *GImGui;
diff --git a/imgui_internal.h b/imgui_internal.h
index 226d545eeb10..e6ebec2c6f08 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2336,210 +2336,7 @@ struct ImGuiContext
     ImVector          TempBuffer;                         // Temporary text buffer
     char                    TempKeychordName[64];
 
-    ImGuiContext(ImFontAtlas* shared_font_atlas)
-    {
-        IO.Ctx = this;
-        InputTextState.Ctx = this;
-
-        Initialized = false;
-        FontAtlasOwnedByContext = shared_font_atlas ? false : true;
-        Font = NULL;
-        FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f;
-        IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
-        Time = 0.0f;
-        FrameCount = 0;
-        FrameCountEnded = FrameCountRendered = -1;
-        WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false;
-        GcCompactAll = false;
-        TestEngineHookItems = false;
-        TestEngine = NULL;
-        memset(ContextName, 0, sizeof(ContextName));
-
-        InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
-        InputEventsNextEventId = 1;
-
-        WindowsActiveCount = 0;
-        CurrentWindow = NULL;
-        HoveredWindow = NULL;
-        HoveredWindowUnderMovingWindow = NULL;
-        HoveredWindowBeforeClear = NULL;
-        MovingWindow = NULL;
-        WheelingWindow = NULL;
-        WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1;
-        WheelingWindowReleaseTimer = 0.0f;
-
-        DebugDrawIdConflicts = 0;
-        DebugHookIdInfo = 0;
-        HoveredId = HoveredIdPreviousFrame = 0;
-        HoveredIdPreviousFrameItemCount = 0;
-        HoveredIdAllowOverlap = false;
-        HoveredIdIsDisabled = false;
-        HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
-        ItemUnclipByLog = false;
-        ActiveId = 0;
-        ActiveIdIsAlive = 0;
-        ActiveIdTimer = 0.0f;
-        ActiveIdIsJustActivated = false;
-        ActiveIdAllowOverlap = false;
-        ActiveIdNoClearOnFocusLoss = false;
-        ActiveIdHasBeenPressedBefore = false;
-        ActiveIdHasBeenEditedBefore = false;
-        ActiveIdHasBeenEditedThisFrame = false;
-        ActiveIdFromShortcut = false;
-        ActiveIdClickOffset = ImVec2(-1, -1);
-        ActiveIdWindow = NULL;
-        ActiveIdSource = ImGuiInputSource_None;
-        ActiveIdMouseButton = -1;
-        ActiveIdPreviousFrame = 0;
-        ActiveIdPreviousFrameIsAlive = false;
-        ActiveIdPreviousFrameHasBeenEditedBefore = false;
-        ActiveIdPreviousFrameWindow = NULL;
-        LastActiveId = 0;
-        LastActiveIdTimer = 0.0f;
-
-        LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0;
-
-        ActiveIdUsingNavDirMask = 0x00;
-        ActiveIdUsingAllKeyboardKeys = false;
-
-        CurrentFocusScopeId = 0;
-        CurrentItemFlags = ImGuiItemFlags_None;
-        DebugShowGroupRects = false;
-
-        NavWindow = NULL;
-        NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
-        NavLayer = ImGuiNavLayer_Main;
-        NavNextActivateId = 0;
-        NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
-        NavHighlightActivatedId = 0;
-        NavHighlightActivatedTimer = 0.0f;
-        NavInputSource = ImGuiInputSource_Keyboard;
-        NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
-        NavIdIsAlive = false;
-        NavMousePosDirty = false;
-        NavDisableHighlight = true;
-        NavDisableMouseHover = false;
-
-        NavAnyRequest = false;
-        NavInitRequest = false;
-        NavInitRequestFromMove = false;
-        NavMoveSubmitted = false;
-        NavMoveScoringItems = false;
-        NavMoveForwardToNextFrame = false;
-        NavMoveFlags = ImGuiNavMoveFlags_None;
-        NavMoveScrollFlags = ImGuiScrollFlags_None;
-        NavMoveKeyMods = ImGuiMod_None;
-        NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
-        NavScoringDebugCount = 0;
-        NavTabbingDir = 0;
-        NavTabbingCounter = 0;
-
-        NavJustMovedFromFocusScopeId = NavJustMovedToId = NavJustMovedToFocusScopeId = 0;
-        NavJustMovedToKeyMods = ImGuiMod_None;
-        NavJustMovedToIsTabbing = false;
-        NavJustMovedToHasSelectionData = false;
-
-        // All platforms use Ctrl+Tab but Ctrl<>Super are swapped on Mac...
-        // FIXME: Because this value is stored, it annoyingly interfere with toggling io.ConfigMacOSXBehaviors updating this..
-        ConfigNavWindowingKeyNext = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiKey_Tab);
-        ConfigNavWindowingKeyPrev = IO.ConfigMacOSXBehaviors ? (ImGuiMod_Super | ImGuiMod_Shift | ImGuiKey_Tab) : (ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab);
-        NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
-        NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
-        NavWindowingToggleLayer = false;
-        NavWindowingToggleKey = ImGuiKey_None;
-
-        DimBgRatio = 0.0f;
-
-        DragDropActive = DragDropWithinSource = DragDropWithinTarget = false;
-        DragDropSourceFlags = ImGuiDragDropFlags_None;
-        DragDropSourceFrameCount = -1;
-        DragDropMouseButton = -1;
-        DragDropTargetId = 0;
-        DragDropAcceptFlags = ImGuiDragDropFlags_None;
-        DragDropAcceptIdCurrRectSurface = 0.0f;
-        DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0;
-        DragDropAcceptFrameCount = -1;
-        DragDropHoldJustPressedId = 0;
-        memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
-
-        ClipperTempDataStacked = 0;
-
-        CurrentTable = NULL;
-        TablesTempDataStacked = 0;
-        CurrentTabBar = NULL;
-        CurrentMultiSelect = NULL;
-        MultiSelectTempDataStacked = 0;
-
-        HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0;
-        HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f;
-
-        MouseCursor = ImGuiMouseCursor_Arrow;
-        MouseStationaryTimer = 0.0f;
-
-        TempInputId = 0;
-        memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
-        BeginMenuDepth = BeginComboDepth = 0;
-        ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
-        ColorEditCurrentID = ColorEditSavedID = 0;
-        ColorEditSavedHue = ColorEditSavedSat = 0.0f;
-        ColorEditSavedColor = 0;
-        WindowResizeRelativeMode = false;
-        ScrollbarSeekMode = 0;
-        ScrollbarClickDeltaToGrabCenter = 0.0f;
-        SliderGrabClickOffset = 0.0f;
-        SliderCurrentAccum = 0.0f;
-        SliderCurrentAccumDirty = false;
-        DragCurrentAccumDirty = false;
-        DragCurrentAccum = 0.0f;
-        DragSpeedDefaultRatio = 1.0f / 100.0f;
-        DisabledAlphaBackup = 0.0f;
-        DisabledStackSize = 0;
-        LockMarkEdited = 0;
-        TooltipOverrideCount = 0;
-
-        PlatformImeData.InputPos = ImVec2(0.0f, 0.0f);
-        PlatformImeDataPrev.InputPos = ImVec2(-1.0f, -1.0f); // Different to ensure initial submission
-
-        SettingsLoaded = false;
-        SettingsDirtyTimer = 0.0f;
-        HookIdNext = 0;
-
-        memset(LocalizationTable, 0, sizeof(LocalizationTable));
-
-        LogEnabled = false;
-        LogType = ImGuiLogType_None;
-        LogNextPrefix = LogNextSuffix = NULL;
-        LogFile = NULL;
-        LogLinePosY = FLT_MAX;
-        LogLineFirstItem = false;
-        LogDepthRef = 0;
-        LogDepthToExpand = LogDepthToExpandDefault = 2;
-
-        DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY;
-        DebugLocateId = 0;
-        DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
-        DebugLogAutoDisableFrames = 0;
-        DebugLocateFrames = 0;
-        DebugBeginReturnValueCullDepth = -1;
-        DebugItemPickerActive = false;
-        DebugItemPickerMouseButton = ImGuiMouseButton_Left;
-        DebugItemPickerBreakId = 0;
-        DebugFlashStyleColorTime = 0.0f;
-        DebugFlashStyleColorIdx = ImGuiCol_COUNT;
-
-        // Same as DebugBreakClearData(). Those fields are scattered in their respective subsystem to stay in hot-data locations
-        DebugBreakInWindow = 0;
-        DebugBreakInTable = 0;
-        DebugBreakInLocateId = false;
-        DebugBreakKeyChord = ImGuiKey_Pause;
-        DebugBreakInShortcutRouting = ImGuiKey_None;
-
-        memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
-        FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
-        FramerateSecPerFrameAccum = 0.0f;
-        WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
-        memset(TempKeychordName, 0, sizeof(TempKeychordName));
-    }
+    ImGuiContext(ImFontAtlas* shared_font_atlas);
 };
 
 //-----------------------------------------------------------------------------

From d0107f5da2343004cd0a9b23402d8620b8387e03 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 24 Sep 2024 21:53:25 +0200
Subject: [PATCH 151/548] Internals: misc tweaks to facilitate branch merging.

---
 imgui_internal.h | 45 ++++++++++++++++++++++++++-------------------
 1 file changed, 26 insertions(+), 19 deletions(-)

diff --git a/imgui_internal.h b/imgui_internal.h
index e6ebec2c6f08..93decabaf2bd 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -28,6 +28,7 @@ Index of this file:
 // [SECTION] Viewport support
 // [SECTION] Settings support
 // [SECTION] Localization support
+// [SECTION] Error handling, State recovery support
 // [SECTION] Metrics, Debug tools
 // [SECTION] Generic context hooks
 // [SECTION] ImGuiContext (main imgui context)
@@ -173,7 +174,7 @@ typedef int ImGuiLayoutType;            // -> enum ImGuiLayoutType_         // E
 // Flags
 typedef int ImGuiActivateFlags;         // -> enum ImGuiActivateFlags_      // Flags: for navigation/focus function (will be for ActivateItem() later)
 typedef int ImGuiDebugLogFlags;         // -> enum ImGuiDebugLogFlags_      // Flags: for ShowDebugLogWindow(), g.DebugLogFlags
-typedef int ImGuiFocusRequestFlags;     // -> enum ImGuiFocusRequestFlags_  // Flags: for FocusWindow();
+typedef int ImGuiFocusRequestFlags;     // -> enum ImGuiFocusRequestFlags_  // Flags: for FocusWindow()
 typedef int ImGuiItemStatusFlags;       // -> enum ImGuiItemStatusFlags_    // Flags: for g.LastItemData.StatusFlags
 typedef int ImGuiOldColumnFlags;        // -> enum ImGuiOldColumnFlags_     // Flags: for BeginColumns()
 typedef int ImGuiNavHighlightFlags;     // -> enum ImGuiNavHighlightFlags_  // Flags: for RenderNavHighlight()
@@ -187,8 +188,6 @@ typedef int ImGuiTooltipFlags;          // -> enum ImGuiTooltipFlags_       // F
 typedef int ImGuiTypingSelectFlags;     // -> enum ImGuiTypingSelectFlags_  // Flags: for GetTypingSelectRequest()
 typedef int ImGuiWindowRefreshFlags;    // -> enum ImGuiWindowRefreshFlags_ // Flags: for SetNextWindowRefreshPolicy()
 
-typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
-
 //-----------------------------------------------------------------------------
 // [SECTION] Context pointer
 // See implementation of this variable in imgui.cpp for comments and details.
@@ -239,12 +238,6 @@ extern IMGUI_API ImGuiContext* GImGui;  // Current implicit context pointer
 #define IM_ASSERT_PARANOID(_EXPR)
 #endif
 
-// Error handling
-// Down the line in some frameworks/languages we would like to have a way to redirect those to the programmer and recover from more faults.
-#ifndef IM_ASSERT_USER_ERROR
-#define IM_ASSERT_USER_ERROR(_EXP,_MSG) IM_ASSERT((_EXP) && _MSG)   // Recoverable User Error
-#endif
-
 // Misc Macros
 #define IM_PI                           3.14159265358979323846f
 #ifdef _WIN32
@@ -1886,6 +1879,17 @@ struct ImGuiLocEntry
     const char*     Text;
 };
 
+//-----------------------------------------------------------------------------
+// [SECTION] Error handling, State recovery support
+//-----------------------------------------------------------------------------
+
+// Macros used by Recoverable Error handling
+// Down the line in some frameworks/languages we would like to have a way to redirect those to the programmer and recover from more faults.
+#ifndef IM_ASSERT_USER_ERROR
+#define IM_ASSERT_USER_ERROR(_EXPR,_MSG)    IM_ASSERT((_EXPR) && _MSG)
+#endif
+
+typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
 
 //-----------------------------------------------------------------------------
 // [SECTION] Metrics, Debug Tools
@@ -1895,16 +1899,19 @@ enum ImGuiDebugLogFlags_
 {
     // Event types
     ImGuiDebugLogFlags_None                 = 0,
-    ImGuiDebugLogFlags_EventActiveId        = 1 << 0,
-    ImGuiDebugLogFlags_EventFocus           = 1 << 1,
-    ImGuiDebugLogFlags_EventPopup           = 1 << 2,
-    ImGuiDebugLogFlags_EventNav             = 1 << 3,
-    ImGuiDebugLogFlags_EventClipper         = 1 << 4,
-    ImGuiDebugLogFlags_EventSelection       = 1 << 5,
-    ImGuiDebugLogFlags_EventIO              = 1 << 6,
-    ImGuiDebugLogFlags_EventInputRouting    = 1 << 7,
-
-    ImGuiDebugLogFlags_EventMask_           = ImGuiDebugLogFlags_EventActiveId  | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventInputRouting,
+    ImGuiDebugLogFlags_EventError           = 1 << 0,   // Error submitted by IM_ASSERT_USER_ERROR()
+    ImGuiDebugLogFlags_EventActiveId        = 1 << 1,
+    ImGuiDebugLogFlags_EventFocus           = 1 << 2,
+    ImGuiDebugLogFlags_EventPopup           = 1 << 3,
+    ImGuiDebugLogFlags_EventNav             = 1 << 4,
+    ImGuiDebugLogFlags_EventClipper         = 1 << 5,
+    ImGuiDebugLogFlags_EventSelection       = 1 << 6,
+    ImGuiDebugLogFlags_EventIO              = 1 << 7,
+    ImGuiDebugLogFlags_EventInputRouting    = 1 << 8,
+    ImGuiDebugLogFlags_EventDocking         = 1 << 9,   // Unused in this branch
+    ImGuiDebugLogFlags_EventViewport        = 1 << 10,  // Unused in this branch
+
+    ImGuiDebugLogFlags_EventMask_           = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventInputRouting | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport,
     ImGuiDebugLogFlags_OutputToTTY          = 1 << 20,  // Also send output to TTY
     ImGuiDebugLogFlags_OutputToTestEngine   = 1 << 21,  // Also send output to Test Engine
 };

From 9644c5118357cd0c0ba0ea957b3328ff49cf6260 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 25 Sep 2024 18:59:08 +0200
Subject: [PATCH 152/548] Error handling: rework error tooltip logic (will be
 reused by upcoming feature). (#7961, #7669, #1651)

+ Comments
---
 imgui.cpp         | 85 ++++++++++++++++++++++++++++++++++-------------
 imgui_internal.h  |  9 ++++-
 imgui_widgets.cpp |  8 +++++
 3 files changed, 77 insertions(+), 25 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index a0683e671796..3833109bb898 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3978,6 +3978,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     LogDepthRef = 0;
     LogDepthToExpand = LogDepthToExpandDefault = 2;
 
+    DebugDrawIdConflictsCount = 0;
     DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY;
     DebugLocateId = 0;
     DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
@@ -5054,7 +5055,8 @@ void ImGui::NewFrame()
         KeepAliveID(g.DragDropPayload.SourceId);
 
     // [DEBUG]
-    g.DebugDrawIdConflicts = 0;
+    if (!g.IO.ConfigDebugHighlightIdConflicts || !g.IO.KeyCtrl) // Count is locked while holding CTRL
+        g.DebugDrawIdConflicts = 0;
     if (g.IO.ConfigDebugHighlightIdConflicts && g.HoveredIdPreviousFrameItemCount > 1)
         g.DebugDrawIdConflicts = g.HoveredIdPreviousFrame;
 
@@ -5461,32 +5463,10 @@ void ImGui::EndFrame()
         return;
     IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?");
 
-#ifndef IMGUI_DISABLE_DEBUG_TOOLS
-    if (g.DebugDrawIdConflicts != 0)
-    {
-        PushStyleColor(ImGuiCol_PopupBg, ImLerp(g.Style.Colors[ImGuiCol_PopupBg], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.10f));
-        if (g.DebugItemPickerActive == false && BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
-        {
-            SeparatorText("MESSAGE FROM DEAR IMGUI");
-            Text("Programmer error: %d visible items with conflicting ID!", g.HoveredIdPreviousFrameItemCount);
-            BulletText("Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
-            BulletText("Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
-            BulletText("Press F1 to open \"FAQ -> About the ID Stack System\" and read details.");
-            BulletText("Press CTRL+P to activate Item Picker and debug-break in item call-stack.");
-            BulletText("Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
-            EndTooltip();
-        }
-        PopStyleColor();
-        if (Shortcut(ImGuiMod_Ctrl | ImGuiKey_P, ImGuiInputFlags_RouteGlobal))
-            DebugStartItemPicker();
-        if (Shortcut(ImGuiKey_F1, ImGuiInputFlags_RouteGlobal) && g.PlatformIO.Platform_OpenInShellFn != NULL)
-            g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
-    }
-#endif
-
     CallContextHooks(&g, ImGuiContextHookType_EndFramePre);
 
     ErrorCheckEndFrameSanityChecks();
+    ErrorCheckEndFrameFinalizeErrorTooltip();
 
     // Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
     ImGuiPlatformImeData* ime_data = &g.PlatformImeData;
@@ -10587,6 +10567,63 @@ void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx)
     IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size   && "PushFocusScope/PopFocusScope Mismatch!");
 }
 
+void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
+{
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
+    ImGuiContext& g = *GImGui;
+    if (g.DebugDrawIdConflicts != 0 && g.IO.KeyCtrl == false)
+        g.DebugDrawIdConflictsCount = g.HoveredIdPreviousFrameItemCount;
+    if (g.DebugDrawIdConflicts != 0 && g.DebugItemPickerActive == false && BeginErrorTooltip())
+    {
+        Text("Programmer error: %d visible items with conflicting ID!", g.DebugDrawIdConflictsCount);
+        BulletText("Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
+        BulletText("Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
+        BulletText("Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
+        Separator();
+        Text("(Hold CTRL and: use");
+        SameLine();
+        if (SmallButton("Item Picker"))
+            DebugStartItemPicker();
+        SameLine();
+        Text("to break in item call-stack, or");
+        SameLine();
+        if (SmallButton("Open FAQ->About ID Stack System") && g.PlatformIO.Platform_OpenInShellFn != NULL)
+            g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
+        EndErrorTooltip();
+    }
+#endif
+}
+
+// Pseudo-tooltip. Follow mouse until CTRL is held. When CTRL is held we lock position, allowing to click it.
+bool ImGui::BeginErrorTooltip()
+{
+    ImGuiContext& g = *GImGui;
+    ImGuiWindow* window = FindWindowByName("##Tooltip_Error");
+    const bool use_locked_pos = (g.IO.KeyCtrl && window && window->WasActive);
+    PushStyleColor(ImGuiCol_PopupBg, ImLerp(g.Style.Colors[ImGuiCol_PopupBg], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.15f));
+    if (use_locked_pos)
+        SetNextWindowPos(g.ErrorTooltipLockedPos);
+    bool is_visible = Begin("##Tooltip_Error", NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize);
+    PopStyleColor();
+    if (is_visible && g.CurrentWindow->BeginCount == 1)
+    {
+        SeparatorText("MESSAGE FROM DEAR IMGUI");
+        BringWindowToDisplayFront(g.CurrentWindow);
+        BringWindowToFocusFront(g.CurrentWindow);
+        g.ErrorTooltipLockedPos = GetWindowPos();
+    }
+    else if (!is_visible)
+    {
+        End();
+    }
+    return is_visible;
+}
+
+void ImGui::EndErrorTooltip()
+{
+    End();
+}
+
 //-----------------------------------------------------------------------------
 // [SECTION] ITEM SUBMISSION
 //-----------------------------------------------------------------------------
diff --git a/imgui_internal.h b/imgui_internal.h
index 93decabaf2bd..37c182b555d8 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2312,8 +2312,12 @@ struct ImGuiContext
     int                     LogDepthToExpand;
     int                     LogDepthToExpandDefault;            // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call.
 
+    // Error handling
+    ImVec2                  ErrorTooltipLockedPos;
+
     // Debug Tools
     // (some of the highly frequently used data are interleaved in other structures above: DebugBreakXXX fields, DebugHookIdInfo, DebugLocateId etc.)
+    int                     DebugDrawIdConflictsCount;          // Locked count (preserved when holding CTRL)
     ImGuiDebugLogFlags      DebugLogFlags;
     ImGuiTextBuffer         DebugLogBuf;
     ImGuiTextIndex          DebugLogIndex;
@@ -3412,11 +3416,14 @@ namespace ImGui
     IMGUI_API void          GcCompactTransientWindowBuffers(ImGuiWindow* window);
     IMGUI_API void          GcAwakeTransientWindowBuffers(ImGuiWindow* window);
 
-    // Error Checking, State Recovery
+    // Error handling, State Recovery
     IMGUI_API void          ErrorLogCallbackToDebugLog(void* user_data, const char* fmt, ...);
     IMGUI_API void          ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
     IMGUI_API void          ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
     IMGUI_API void          ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
+    IMGUI_API void          ErrorCheckEndFrameFinalizeErrorTooltip();
+    IMGUI_API bool          BeginErrorTooltip();
+    IMGUI_API void          EndErrorTooltip();
 
     // Debug Tools
     IMGUI_API void          DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 59a912dbdb82..5641134ffca3 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -7391,6 +7391,7 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag
 static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSelectIO* io)
 {
     ImGuiContext& g = *GImGui;
+    IM_UNUSED(function);
     for (const ImGuiSelectionRequest& req : io->Requests)
     {
         if (req.Type == ImGuiSelectionRequestType_SetAll)    IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: SetAll %d (= %s)\n", function, req.Selected, req.Selected ? "SelectAll" : "Clear");
@@ -8157,6 +8158,13 @@ void ImGuiSelectionExternalStorage::ApplyRequests(ImGuiMultiSelectIO* ms_io)
 //-------------------------------------------------------------------------
 
 // This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
+// This handle some subtleties with capturing info from the label, but for 99% uses it could essentially be rewritten as:
+//    if (ImGui::BeginChild("...", ImVec2(ImGui::CalcItemWidth(), ImGui::GetTextLineHeight() * 7.5f), ImGuiChildFlags_FrameStyle))
+//        { .... }
+//    ImGui::EndChild();
+//    ImGui::SameLine();
+//    ImGui::AlignTextToFramePadding();
+//    ImGui::Text("Label");
 // Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty"
 // Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.25 * item_height).
 bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)

From 797101a882b3eebef6815685cb521e47b15b4255 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 26 Sep 2024 14:58:56 +0200
Subject: [PATCH 153/548] Windows: BeginChild(): made it possible to call
 SetNextWindowSize() on a child window using
 ImGuiChildFlags_ResizeX/ImGuiChildFlags_ResizeY. (#1710, #8020)

---
 docs/CHANGELOG.txt |  3 +++
 imgui.cpp          | 27 ++++++++++++++++++++++-----
 imgui.h            |  2 +-
 imgui_demo.cpp     |  3 +++
 4 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 1d7232d9cc8e..c7c0a47e2eec 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,9 @@ Breaking changes:
 
 Other changes:
 
+- Windows: BeginChild(): made it possible to call SetNextWindowSize() on a child window
+  using ImGuiChildFlags_ResizeX,ImGuiChildFlags_ResizeY in order to override its current
+  size. (#1710, #8020)
 - Scrollbar: Shift+Click scroll to clicked location (pre-1.90.8 default). (#8002, #7328)
 - Scrollbar: added io.ConfigScrollbarScrollByPage setting (default to true). (#8002, #7328)
   Set io.ConfigScrollbarScrollByPage=false to enforce always scrolling to clicked location.
diff --git a/imgui.cpp b/imgui.cpp
index 3833109bb898..f176aa855016 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -5917,18 +5917,35 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I
         window_flags |= ImGuiWindowFlags_NoMove;
     }
 
-    // Forward child flags
-    g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
-    g.NextWindowData.ChildFlags = child_flags;
-
     // Forward size
     // Important: Begin() has special processing to switch condition to ImGuiCond_FirstUseEver for a given axis when ImGuiChildFlags_ResizeXXX is set.
     // (the alternative would to store conditional flags per axis, which is possible but more code)
     const ImVec2 size_avail = GetContentRegionAvail();
     const ImVec2 size_default((child_flags & ImGuiChildFlags_AutoResizeX) ? 0.0f : size_avail.x, (child_flags & ImGuiChildFlags_AutoResizeY) ? 0.0f : size_avail.y);
-    const ImVec2 size = CalcItemSize(size_arg, size_default.x, size_default.y);
+    ImVec2 size = CalcItemSize(size_arg, size_default.x, size_default.y);
+
+    // A SetNextWindowSize() call always has priority (#8020)
+    // (since the code in Begin() never supported SizeVal==0.0f aka auto-resize via SetNextWindowSize() call, we don't support it here for now)
+    // FIXME: We only support ImGuiCond_Always in this path. Supporting other paths would requires to obtain window pointer.
+    if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) != 0 && (g.NextWindowData.SizeCond & ImGuiCond_Always) != 0)
+    {
+        if (g.NextWindowData.SizeVal.x > 0.0f)
+        {
+            size.x = g.NextWindowData.SizeVal.x;
+            child_flags &= ~ImGuiChildFlags_ResizeX;
+        }
+        if (g.NextWindowData.SizeVal.y > 0.0f)
+        {
+            size.y = g.NextWindowData.SizeVal.y;
+            child_flags &= ~ImGuiChildFlags_ResizeY;
+        }
+    }
     SetNextWindowSize(size);
 
+    // Forward child flags
+    g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
+    g.NextWindowData.ChildFlags = child_flags;
+
     // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value.
     // FIXME: 2023/11/14: commented out shorted version. We had an issue with multiple ### in child window path names, which the trailing hash helped workaround.
     // e.g. "ParentName###ParentIdentifier/ChildName###ChildIdentifier" would get hashed incorrectly by ImHashStr(), trailing _%08X somehow fixes it.
diff --git a/imgui.h b/imgui.h
index f03b7aa1d152..f86efc42829b 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.3 WIP"
-#define IMGUI_VERSION_NUM   19121
+#define IMGUI_VERSION_NUM   19122
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index c2d110dd15c9..8fb410d9b10a 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -3931,6 +3931,9 @@ static void ShowDemoWindowLayout()
         ImGui::SeparatorText("Manual-resize");
         {
             HelpMarker("Drag bottom border to resize. Double-click bottom border to auto-fit to vertical contents.");
+            //if (ImGui::Button("Set Height to 200"))
+            //    ImGui::SetNextWindowSize(ImVec2(-FLT_MIN, 200.0f));
+
             ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
             if (ImGui::BeginChild("ResizableChild", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY))
                 for (int n = 0; n < 10; n++)

From 26785fd873193770eb30fd716d44703cb94cf35b Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 27 Sep 2024 15:06:05 +0200
Subject: [PATCH 154/548] Internals: NewFrame: move the window reset loop
 higher up, namely before UpdateHoveredWindowAndCaptureFlags() ->
 FindHoveredWindowEx().

This allows using FindHoveredWindowEx() from anywhere in the frame.
---
 imgui.cpp | 35 ++++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index f176aa855016..0081a8aff954 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -5158,8 +5158,25 @@ void ImGui::NewFrame()
     // Update mouse input state
     UpdateMouseInputs();
 
+    // Mark all windows as not visible and compact unused memory.
+    IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
+    const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
+    for (ImGuiWindow* window : g.Windows)
+    {
+        window->WasActive = window->Active;
+        window->Active = false;
+        window->WriteAccessed = false;
+        window->BeginCountPreviousFrame = window->BeginCount;
+        window->BeginCount = 0;
+
+        // Garbage collect transient buffers of recently unused windows
+        if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
+            GcCompactTransientWindowBuffers(window);
+    }
+
     // Find hovered window
     // (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredWindowUnderMovingWindow on the mouse release frame)
+    // (currently needs to be done after the WasActive=Active loop and FindHoveredWindowEx uses ->Active)
     UpdateHoveredWindowAndCaptureFlags();
 
     // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering)
@@ -5181,22 +5198,6 @@ void ImGui::NewFrame()
     // Mouse wheel scrolling, scale
     UpdateMouseWheel();
 
-    // Mark all windows as not visible and compact unused memory.
-    IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
-    const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
-    for (ImGuiWindow* window : g.Windows)
-    {
-        window->WasActive = window->Active;
-        window->Active = false;
-        window->WriteAccessed = false;
-        window->BeginCountPreviousFrame = window->BeginCount;
-        window->BeginCount = 0;
-
-        // Garbage collect transient buffers of recently unused windows
-        if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
-            GcCompactTransientWindowBuffers(window);
-    }
-
     // Garbage collect transient buffers of recently unused tables
     for (int i = 0; i < g.TablesLastTimeActive.Size; i++)
         if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time)
@@ -5660,7 +5661,7 @@ void ImGui::FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_vi
     {
         ImGuiWindow* window = g.Windows[i];
         IM_MSVC_WARNING_SUPPRESS(28182); // [Static Analyzer] Dereferencing NULL pointer.
-        if (!window->Active || window->Hidden)
+        if (!window->WasActive || window->Hidden)
             continue;
         if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
             continue;

From 2360061520e7346688b05188eafe72dabac71cf1 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 24 Sep 2024 15:58:09 +0200
Subject: [PATCH 155/548] Error Handling, Debug Log: added
 IMGUI_DEBUG_LOG_ERROR() with special handling. (#5855, #1651, #5654)

---
 imgui.cpp        | 19 +++++++++++++++++--
 imgui_internal.h |  2 ++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 0081a8aff954..fbb4c4d8c982 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3979,8 +3979,9 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     LogDepthToExpand = LogDepthToExpandDefault = 2;
 
     DebugDrawIdConflictsCount = 0;
-    DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY;
+    DebugLogFlags = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_OutputToTTY;
     DebugLocateId = 0;
+    DebugLogSkippedErrors = 0;
     DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
     DebugLogAutoDisableFrames = 0;
     DebugLocateFrames = 0;
@@ -16281,12 +16282,24 @@ static void ShowDebugLogFlag(const char* name, ImGuiDebugLogFlags flags)
     ImGuiContext& g = *GImGui;
     ImVec2 size(ImGui::GetFrameHeight() + g.Style.ItemInnerSpacing.x + ImGui::CalcTextSize(name).x, ImGui::GetFrameHeight());
     SameLineOrWrap(size); // FIXME-LAYOUT: To be done automatically once we rework ItemSize/ItemAdd into ItemLayout.
+
+    bool highlight_errors = (flags == ImGuiDebugLogFlags_EventError && g.DebugLogSkippedErrors > 0);
+    if (highlight_errors)
+        ImGui::PushStyleColor(ImGuiCol_Text, ImLerp(g.Style.Colors[ImGuiCol_Text], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.30f));
     if (ImGui::CheckboxFlags(name, &g.DebugLogFlags, flags) && g.IO.KeyShift && (g.DebugLogFlags & flags) != 0)
     {
         g.DebugLogAutoDisableFrames = 2;
         g.DebugLogAutoDisableFlags |= flags;
     }
-    ImGui::SetItemTooltip("Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)");
+    if (highlight_errors)
+    {
+        ImGui::PopStyleColor();
+        ImGui::SetItemTooltip("%d past errors skipped.", g.DebugLogSkippedErrors);
+    }
+    else
+    {
+        ImGui::SetItemTooltip("Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)");
+    }
 }
 
 void ImGui::ShowDebugLogWindow(bool* p_open)
@@ -16304,6 +16317,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
     CheckboxFlags("All", &g.DebugLogFlags, all_enable_flags);
     SetItemTooltip("(except InputRouting which is spammy)");
 
+    ShowDebugLogFlag("Errors", ImGuiDebugLogFlags_EventError);
     ShowDebugLogFlag("ActiveId", ImGuiDebugLogFlags_EventActiveId);
     ShowDebugLogFlag("Clipper", ImGuiDebugLogFlags_EventClipper);
     ShowDebugLogFlag("Focus", ImGuiDebugLogFlags_EventFocus);
@@ -16317,6 +16331,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
     {
         g.DebugLogBuf.clear();
         g.DebugLogIndex.clear();
+        g.DebugLogSkippedErrors = 0;
     }
     SameLine();
     if (SmallButton("Copy"))
diff --git a/imgui_internal.h b/imgui_internal.h
index 37c182b555d8..e204d08808ca 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -217,6 +217,7 @@ extern IMGUI_API ImGuiContext* GImGui;  // Current implicit context pointer
 #else
 #define IMGUI_DEBUG_LOG(...)            ((void)0)
 #endif
+#define IMGUI_DEBUG_LOG_ERROR(...)      do { ImGuiContext& g2 = *GImGui; if (g2.DebugLogFlags & ImGuiDebugLogFlags_EventError) IMGUI_DEBUG_LOG(__VA_ARGS__); else g2.DebugLogSkippedErrors++; } while (0)
 #define IMGUI_DEBUG_LOG_ACTIVEID(...)   do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId)    IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
 #define IMGUI_DEBUG_LOG_FOCUS(...)      do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus)       IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
 #define IMGUI_DEBUG_LOG_POPUP(...)      do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup)       IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
@@ -2321,6 +2322,7 @@ struct ImGuiContext
     ImGuiDebugLogFlags      DebugLogFlags;
     ImGuiTextBuffer         DebugLogBuf;
     ImGuiTextIndex          DebugLogIndex;
+    int                     DebugLogSkippedErrors;
     ImGuiDebugLogFlags      DebugLogAutoDisableFlags;
     ImU8                    DebugLogAutoDisableFrames;
     ImU8                    DebugLocateFrames;                  // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above.

From 718a594b1e10cf51a0b6a85bdf39aec5d4929e77 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 24 Sep 2024 15:59:54 +0200
Subject: [PATCH 156/548] Error Handling: rewired asserts in PopID(),
 PopFont(), PopItemFlag(), EndDisabled(), PopTextWrapPos(), PopFocusScope(),
 PopItemWidth() to use IM_ASSERT_USER_ERROR().  (#1651, #5654)

---
 docs/CHANGELOG.txt |  2 ++
 imgui.cpp          | 58 +++++++++++++++++++++++++++++++++-------------
 2 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index c7c0a47e2eec..51ef272c59df 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,8 @@ Breaking changes:
 
 Other changes:
 
+- Error Handling: rewired asserts in PopID(), PopFont(), PopItemFlag(), EndDisabled(),
+  PopTextWrapPos(), PopFocusScope(), PopItemWidth() to use IM_ASSERT_USER_ERROR(). (#1651)
 - Windows: BeginChild(): made it possible to call SetNextWindowSize() on a child window
   using ImGuiChildFlags_ResizeX,ImGuiChildFlags_ResizeY in order to override its current
   size. (#1710, #8020)
diff --git a/imgui.cpp b/imgui.cpp
index fbb4c4d8c982..5b41fe37fb94 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3273,7 +3273,7 @@ void ImGui::PopStyleColor(int count)
     ImGuiContext& g = *GImGui;
     if (g.ColorStack.Size < count)
     {
-        IM_ASSERT_USER_ERROR(g.ColorStack.Size > count, "Calling PopStyleColor() too many times!");
+        IM_ASSERT_USER_ERROR(0, "Calling PopStyleColor() too many times!");
         count = g.ColorStack.Size;
     }
     while (count > 0)
@@ -3390,7 +3390,7 @@ void ImGui::PopStyleVar(int count)
     ImGuiContext& g = *GImGui;
     if (g.StyleVarStack.Size < count)
     {
-        IM_ASSERT_USER_ERROR(g.StyleVarStack.Size > count, "Calling PopStyleVar() too many times!");
+        IM_ASSERT_USER_ERROR(0, "Calling PopStyleVar() too many times!");
         count = g.StyleVarStack.Size;
     }
     while (count > 0)
@@ -7907,7 +7907,11 @@ void ImGui::PushFont(ImFont* font)
 void  ImGui::PopFont()
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(g.FontStack.Size > 0);
+    if (g.FontStack.Size <= 0)
+    {
+        IM_ASSERT_USER_ERROR(0, "Calling PopFont() too many times!");
+        return;
+    }
     g.FontStack.pop_back();
     ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
     SetCurrentFont(font);
@@ -7930,7 +7934,11 @@ void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
 void ImGui::PopItemFlag()
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(g.ItemFlagsStack.Size > 1); // Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack.
+    if (g.ItemFlagsStack.Size <= 1)
+    {
+        IM_ASSERT_USER_ERROR(0, "Calling PopItemFlag() too many times!");
+        return;
+    }
     g.ItemFlagsStack.pop_back();
     g.CurrentItemFlags = g.ItemFlagsStack.back();
 }
@@ -7960,7 +7968,11 @@ void ImGui::BeginDisabled(bool disabled)
 void ImGui::EndDisabled()
 {
     ImGuiContext& g = *GImGui;
-    IM_ASSERT(g.DisabledStackSize > 0);
+    if (g.DisabledStackSize <= 0)
+    {
+        IM_ASSERT_USER_ERROR(0, "Calling EndDisabled() too many times!");
+        return;
+    }
     g.DisabledStackSize--;
     bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
     //PopItemFlag();
@@ -7995,14 +8007,21 @@ void ImGui::EndDisabledOverrideReenable()
 
 void ImGui::PushTextWrapPos(float wrap_pos_x)
 {
-    ImGuiWindow* window = GetCurrentWindow();
+    ImGuiContext& g = *GImGui;
+    ImGuiWindow* window = g.CurrentWindow;
     window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos);
     window->DC.TextWrapPos = wrap_pos_x;
 }
 
 void ImGui::PopTextWrapPos()
 {
-    ImGuiWindow* window = GetCurrentWindow();
+    ImGuiContext& g = *GImGui;
+    ImGuiWindow* window = g.CurrentWindow;
+    if (window->DC.TextWrapPosStack.Size <= 0)
+    {
+        IM_ASSERT_USER_ERROR(0, "Calling PopTextWrapPos() too many times!");
+        return;
+    }
     window->DC.TextWrapPos = window->DC.TextWrapPosStack.back();
     window->DC.TextWrapPosStack.pop_back();
 }
@@ -8435,9 +8454,9 @@ void ImGui::PushFocusScope(ImGuiID id)
 void ImGui::PopFocusScope()
 {
     ImGuiContext& g = *GImGui;
-    if (g.FocusScopeStack.Size == 0)
+    if (g.FocusScopeStack.Size <= 0)
     {
-        IM_ASSERT_USER_ERROR(g.FocusScopeStack.Size > 0, "Calling PopFocusScope() too many times!");
+        IM_ASSERT_USER_ERROR(0, "Calling PopFocusScope() too many times!");
         return;
     }
     g.FocusScopeStack.pop_back();
@@ -8708,7 +8727,11 @@ ImGuiID ImGui::GetIDWithSeed(int n, ImGuiID seed)
 void ImGui::PopID()
 {
     ImGuiWindow* window = GImGui->CurrentWindow;
-    IM_ASSERT(window->IDStack.Size > 1); // Too many PopID(), or could be popping in a wrong/different window?
+    if (window->IDStack.Size <= 1)
+    {
+        IM_ASSERT_USER_ERROR(0, "Too many PopID(), or popping from wrong window?");
+        return;
+    }
     window->IDStack.pop_back();
 }
 
@@ -10424,6 +10447,8 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
             IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
         }
     }
+    if (g.CurrentWindowStack.Size >= 1)
+        IM_ASSERT(g.CurrentWindowStack[0].Window->IsFallbackWindow);
 
     IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!");
 }
@@ -10453,11 +10478,6 @@ void    ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi
     {
         ErrorCheckEndWindowRecover(log_callback, user_data);
         ImGuiWindow* window = g.CurrentWindow;
-        if (g.CurrentWindowStack.Size == 1)
-        {
-            IM_ASSERT(window->IsFallbackWindow);
-            break;
-        }
         if (window->Flags & ImGuiWindowFlags_ChildWindow)
         {
             if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'\n", window->Name);
@@ -10972,7 +10992,13 @@ void ImGui::PushMultiItemsWidths(int components, float w_full)
 
 void ImGui::PopItemWidth()
 {
-    ImGuiWindow* window = GetCurrentWindow();
+    ImGuiContext& g = *GImGui;
+    ImGuiWindow* window = g.CurrentWindow;
+    if (window->DC.ItemWidthStack.Size <= 0)
+    {
+        IM_ASSERT_USER_ERROR(0, "Calling PopTextWrapPos() too many times!");
+        return;
+    }
     window->DC.ItemWidth = window->DC.ItemWidthStack.back();
     window->DC.ItemWidthStack.pop_back();
 }

From 8776678a462ede913327ab5f3711fddcb2ecdb8a Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 24 Sep 2024 17:31:04 +0200
Subject: [PATCH 157/548] Error Handling: replaced log callback in recovery
 functions with calls to IM_ASSERT_USER_ERROR(). (#1651, #5654)

This commit is not meant to be functional as-is (it will break test engine recovery). This is mostly to reduce/remove noise from upcoming commits.
---
 imgui.cpp        | 79 +++++++++++++++++++++++-------------------------
 imgui_internal.h |  5 ++-
 2 files changed, 39 insertions(+), 45 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 5b41fe37fb94..cb84751f586e 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -8729,7 +8729,7 @@ void ImGui::PopID()
     ImGuiWindow* window = GImGui->CurrentWindow;
     if (window->IDStack.Size <= 1)
     {
-        IM_ASSERT_USER_ERROR(0, "Too many PopID(), or popping from wrong window?");
+        IM_ASSERT_USER_ERROR(0, "Calling PopID() too many times!");
         return;
     }
     window->IDStack.pop_back();
@@ -10415,14 +10415,13 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
 
 static void ImGui::ErrorCheckEndFrameSanityChecks()
 {
-    ImGuiContext& g = *GImGui;
-
     // Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame()
     // One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame().
     // It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will
     // send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs.
     // We silently accommodate for this case by ignoring the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0),
     // while still correctly asserting on mid-frame key press events.
+    ImGuiContext& g = *GImGui;
     const ImGuiKeyChord key_mods = GetMergedModsFromKeys();
     IM_ASSERT((key_mods == 0 || g.IO.KeyMods == key_mods) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
     IM_UNUSED(key_mods);
@@ -10453,85 +10452,80 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
     IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!");
 }
 
-// Default implementation of ImGuiErrorLogCallback that pipe errors to DebugLog: appears in tty + Tools->DebugLog
-void    ImGui::ErrorLogCallbackToDebugLog(void*, const char* fmt, ...)
-{
-#ifndef IMGUI_DISABLE_DEBUG_TOOLS
-    va_list args;
-    va_start(args, fmt);
-    DebugLogV(fmt, args);
-    va_end(args);
-#else
-    IM_UNUSED(fmt);
-#endif
-}
-
 // Experimental recovery from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls.
 // Must be called during or before EndFrame().
 // This is generally flawed as we are not necessarily End/Popping things in the right order.
 // FIXME: Can't recover from inside BeginTabItem/EndTabItem yet.
-void    ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data)
+void    ImGui::ErrorCheckEndFrameRecover()
 {
     // PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations"
     ImGuiContext& g = *GImGui;
     while (g.CurrentWindowStack.Size > 0) //-V1044
     {
-        ErrorCheckEndWindowRecover(log_callback, user_data);
+        ErrorCheckEndWindowRecover();
+        // Recap:
+        // - Begin()/BeginChild() return false to indicate the window is collapsed or fully clipped.
+        // - Always call a matching End() for each Begin() call, regardless of its return value!
+        // - Begin/End and BeginChild/EndChild logic is KNOWN TO BE INCONSISTENT WITH ALL OTHER BEGIN/END FUNCTIONS.
+        // - We will fix that in a future major update.
         ImGuiWindow* window = g.CurrentWindow;
         if (window->Flags & ImGuiWindowFlags_ChildWindow)
         {
-            if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'\n", window->Name);
+            IM_ASSERT_USER_ERROR(0, "Missing EndChild()");
             EndChild();
         }
         else
         {
-            if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'\n", window->Name);
+            IM_ASSERT_USER_ERROR(0, "Missing End()");
             End();
         }
     }
 }
 
 // Must be called before End()/EndChild()
-void    ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data)
+void    ImGui::ErrorCheckEndWindowRecover()
 {
     ImGuiContext& g = *GImGui;
     while (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow)
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'\n", g.CurrentTable->OuterWindow->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing EndTable()");
         EndTable();
     }
 
     ImGuiWindow* window = g.CurrentWindow;
-    ImGuiStackSizes* stack_sizes = &g.CurrentWindowStack.back().StackSizesOnBegin;
     IM_ASSERT(window != NULL);
+    ImGuiStackSizes* state_in = &g.CurrentWindowStack.back().StackSizesOnBegin;
+
+    // FIXME: Can't recover from inside BeginTabItem/EndTabItem yet.
     while (g.CurrentTabBar != NULL && g.CurrentTabBar->Window == window) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'\n", window->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing EndTabBar()");
         EndTabBar();
     }
     while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window)
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing EndMultiSelect() in '%s'\n", window->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing EndMultiSelect()");
         EndMultiSelect();
     }
     while (window->DC.TreeDepth > 0)
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'\n", window->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing TreePop()");
         TreePop();
     }
-    while (g.GroupStack.Size > stack_sizes->SizeOfGroupStack) //-V1044
+    while (g.GroupStack.Size > state_in->SizeOfGroupStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'\n", window->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing EndGroup()");
         EndGroup();
     }
+    IM_ASSERT(g.GroupStack.Size == state_in->SizeOfGroupStack);
     while (window->IDStack.Size > 1)
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'\n", window->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing PopID()");
         PopID();
     }
-    while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
+    while (g.DisabledStackSize > state_in->SizeOfDisabledStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'\n", window->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing EndDisabled()");
         if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
             EndDisabled();
         else
@@ -10540,29 +10534,30 @@ void    ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
             g.CurrentWindowStack.back().DisabledOverrideReenable = false;
         }
     }
-    while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
+    IM_ASSERT(g.DisabledStackSize == state_in->SizeOfDisabledStack);
+    while (g.ColorStack.Size > state_in->SizeOfColorStack)
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s\n", window->Name, GetStyleColorName(g.ColorStack.back().Col));
+        IM_ASSERT_USER_ERROR(0, "Missing PopStyleColor()");
         PopStyleColor();
     }
-    while (g.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack) //-V1044
+    while (g.ItemFlagsStack.Size > state_in->SizeOfItemFlagsStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'\n", window->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing PopItemFlag()");
         PopItemFlag();
     }
-    while (g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack) //-V1044
+    while (g.StyleVarStack.Size > state_in->SizeOfStyleVarStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'\n", window->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing PopStyleVar()");
         PopStyleVar();
     }
-    while (g.FontStack.Size > stack_sizes->SizeOfFontStack) //-V1044
+    while (g.FontStack.Size > state_in->SizeOfFontStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopFont() in '%s'\n", window->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing PopFont()");
         PopFont();
     }
-    while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack + 1) //-V1044
+    while (g.FocusScopeStack.Size > state_in->SizeOfFocusScopeStack) //-V1044
     {
-        if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'\n", window->Name);
+        IM_ASSERT_USER_ERROR(0, "Missing PopFocusScope()");
         PopFocusScope();
     }
 }
@@ -10996,7 +10991,7 @@ void ImGui::PopItemWidth()
     ImGuiWindow* window = g.CurrentWindow;
     if (window->DC.ItemWidthStack.Size <= 0)
     {
-        IM_ASSERT_USER_ERROR(0, "Calling PopTextWrapPos() too many times!");
+        IM_ASSERT_USER_ERROR(0, "Calling PopItemWidth() too many times!");
         return;
     }
     window->DC.ItemWidth = window->DC.ItemWidthStack.back();
diff --git a/imgui_internal.h b/imgui_internal.h
index e204d08808ca..a00a675bd191 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -3419,10 +3419,9 @@ namespace ImGui
     IMGUI_API void          GcAwakeTransientWindowBuffers(ImGuiWindow* window);
 
     // Error handling, State Recovery
-    IMGUI_API void          ErrorLogCallbackToDebugLog(void* user_data, const char* fmt, ...);
-    IMGUI_API void          ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
-    IMGUI_API void          ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
     IMGUI_API void          ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
+    IMGUI_API void          ErrorCheckEndFrameRecover();
+    IMGUI_API void          ErrorCheckEndWindowRecover();
     IMGUI_API void          ErrorCheckEndFrameFinalizeErrorTooltip();
     IMGUI_API bool          BeginErrorTooltip();
     IMGUI_API void          EndErrorTooltip();

From 30c29d291fbb4428055de676775ad591296a2bf2 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 24 Sep 2024 20:51:51 +0200
Subject: [PATCH 158/548] Error Handling: enabled experimental recovery
 systems. (#1651, #5654)

Setup a couple of features to configure them, including ways to display error tooltips instead of assserting.
---
 docs/CHANGELOG.txt |  18 ++++-
 imgui.cpp          | 194 ++++++++++++++++++++++++++++-----------------
 imgui.h            |  21 ++++-
 imgui_demo.cpp     |  16 ++++
 imgui_internal.h   |  44 ++++++----
 imgui_tables.cpp   |   2 +
 imgui_widgets.cpp  |   2 +-
 7 files changed, 202 insertions(+), 95 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 51ef272c59df..511901085940 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,8 +43,22 @@ Breaking changes:
 
 Other changes:
 
-- Error Handling: rewired asserts in PopID(), PopFont(), PopItemFlag(), EndDisabled(),
-  PopTextWrapPos(), PopFocusScope(), PopItemWidth() to use IM_ASSERT_USER_ERROR(). (#1651)
+- Error Handling: Enabled/improved error recovery systems. (#1651, #5654)
+  - Error recovery is not perfect nor guaranteed! It is a feature to ease development.
+  - Functions that support error recovery are using IM_ASSERT_USER_ERROR() instead of IM_ASSERT().
+  - You not are not supposed to rely on it in the course of a normal application run.
+  - Possible usage: facilitate recovery from errors triggered from a scripting language or
+    after specific exceptions handlers. Surface errors to programmers in less agressive ways.
+  - Always ensure that on programmers seats you have at minimum Asserts or Tooltips enabled
+    when making direct imgui API calls! Otherwise it would severely hinder your ability to
+    catch and correct mistakes!
+  - Added io.ConfigErrorRecovery to enable error recovery support.
+  - Added io.ConfigErrorRecoveryEnableAssert to assert on recoverable errors.
+  - Added io.ConfigErrorRecoveryEnableDebugLog to output to debug log on recoverable errors.
+  - Added io.ConfigErrorRecoveryEnableTooltip to enable displaying an error tooltip on recoverable errors.
+    The tooltip include a way to enable asserts if they were disabled.
+  - All options are enabled by default.
+  - Read https://github.com/ocornut/imgui/wiki/Error-Handling for a bit more details.
 - Windows: BeginChild(): made it possible to call SetNextWindowSize() on a child window
   using ImGuiChildFlags_ResizeX,ImGuiChildFlags_ResizeY in order to override its current
   size. (#1710, #8020)
diff --git a/imgui.cpp b/imgui.cpp
index cb84751f586e..306a730ce1b7 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1401,6 +1401,11 @@ ImGuiIO::ImGuiIO()
     ConfigDebugBeginReturnValueOnce = false;
     ConfigDebugBeginReturnValueLoop = false;
 
+    ConfigErrorRecovery = true;
+    ConfigErrorRecoveryEnableAssert = true;
+    ConfigErrorRecoveryEnableDebugLog = true;
+    ConfigErrorRecoveryEnableTooltip = true;
+
     // Inputs Behaviors
     MouseDoubleClickTime = 0.30f;
     MouseDoubleClickMaxDist = 6.0f;
@@ -3978,6 +3983,12 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     LogDepthRef = 0;
     LogDepthToExpand = LogDepthToExpandDefault = 2;
 
+    ErrorCallback = NULL;
+    ErrorCallbackUserData = NULL;
+    ErrorFirst = true;
+    ErrorCountCurrentFrame = 0;
+    StackSizesInBeginForCurrentWindow = NULL;
+
     DebugDrawIdConflictsCount = 0;
     DebugLogFlags = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_OutputToTTY;
     DebugLocateId = 0;
@@ -4211,6 +4222,7 @@ static void SetCurrentWindow(ImGuiWindow* window)
 {
     ImGuiContext& g = *GImGui;
     g.CurrentWindow = window;
+    g.StackSizesInBeginForCurrentWindow = g.CurrentWindow ? &g.CurrentWindowStack.back().StackSizesInBegin : NULL;
     g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
     g.CurrentDpiScale = 1.0f; // FIXME-DPI: WIP this is modified in docking
     if (window)
@@ -5249,6 +5261,10 @@ void ImGui::NewFrame()
     Begin("Debug##Default");
     IM_ASSERT(g.CurrentWindow->IsFallbackWindow == true);
 
+    // Store stack sizes
+    g.ErrorCountCurrentFrame = 0;
+    ErrorRecoveryStoreState(&g.StackSizesInNewFrame);
+
     // [DEBUG] When io.ConfigDebugBeginReturnValue is set, we make Begin()/BeginChild() return false at different level of the window-stack,
     // allowing to validate correct Begin/End behavior in user code.
 #ifndef IMGUI_DISABLE_DEBUG_TOOLS
@@ -5467,6 +5483,9 @@ void ImGui::EndFrame()
 
     CallContextHooks(&g, ImGuiContextHookType_EndFramePre);
 
+    // [EXPERIMENTAL] Recover from errors
+    if (g.IO.ConfigErrorRecovery)
+        ErrorRecoveryTryToRecoverState(&g.StackSizesInNewFrame);
     ErrorCheckEndFrameSanityChecks();
     ErrorCheckEndFrameFinalizeErrorTooltip();
 
@@ -6960,12 +6979,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
 
     // Add to stack
     g.CurrentWindow = window;
-    ImGuiWindowStackData window_stack_data;
+    g.CurrentWindowStack.resize(g.CurrentWindowStack.Size + 1);
+    ImGuiWindowStackData& window_stack_data = g.CurrentWindowStack.back();
     window_stack_data.Window = window;
     window_stack_data.ParentLastItemDataBackup = g.LastItemData;
-    window_stack_data.StackSizesOnBegin.SetToContextState(&g);
     window_stack_data.DisabledOverrideReenable = (flags & ImGuiWindowFlags_Tooltip) && (g.CurrentItemFlags & ImGuiItemFlags_Disabled);
-    g.CurrentWindowStack.push_back(window_stack_data);
+    ErrorRecoveryStoreState(&window_stack_data.StackSizesInBegin);
+    g.StackSizesInBeginForCurrentWindow = &window_stack_data.StackSizesInBegin;
     if (flags & ImGuiWindowFlags_ChildMenu)
         g.BeginMenuDepth++;
 
@@ -7693,7 +7713,11 @@ void ImGui::End()
         g.BeginMenuDepth--;
     if (window->Flags & ImGuiWindowFlags_Popup)
         g.BeginPopupStack.pop_back();
-    window_stack_data.StackSizesOnBegin.CompareWithContextState(&g);
+
+    // Error handling, state recovery
+    if (g.IO.ConfigErrorRecovery)
+        ErrorRecoveryTryToRecoverWindowState(&window_stack_data.StackSizesInBegin);
+
     g.CurrentWindowStack.pop_back();
     SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
 }
@@ -8454,7 +8478,7 @@ void ImGui::PushFocusScope(ImGuiID id)
 void ImGui::PopFocusScope()
 {
     ImGuiContext& g = *GImGui;
-    if (g.FocusScopeStack.Size <= 0)
+    if (g.FocusScopeStack.Size <= g.StackSizesInBeginForCurrentWindow->SizeOfFocusScopeStack)
     {
         IM_ASSERT_USER_ERROR(0, "Calling PopFocusScope() too many times!");
         return;
@@ -10303,9 +10327,10 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own
 // - ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
 // - ErrorCheckNewFrameSanityChecks()
 // - ErrorCheckEndFrameSanityChecks()
-// - ErrorCheckEndFrameRecover()
-// - ErrorCheckEndWindowRecover()
-// - ImGuiStackSizes
+// - ErrorRecoveryStoreState()
+// - ErrorRecoveryTryToRecoverState()
+// - ErrorRecoveryTryToRecoverWindowState()
+// - ErrorLog()
 //-----------------------------------------------------------------------------
 
 // Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues.
@@ -10404,6 +10429,10 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
         IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
 #endif
 
+    // Error handling: we do not accept 100% silent recovery! Please contact me if you feel this is getting in your way.
+    if (g.IO.ConfigErrorRecovery)
+        IM_ASSERT(g.IO.ConfigErrorRecoveryEnableAssert || g.IO.ConfigErrorRecoveryEnableDebugLog || g.IO.ConfigErrorRecoveryEnableTooltip || g.ErrorCallback != NULL);
+
     // Remap legacy clipboard handlers (OBSOLETED in 1.91.1, August 2024)
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
     if (g.IO.GetClipboardTextFn != NULL && (g.PlatformIO.Platform_GetClipboardTextFn == NULL || g.PlatformIO.Platform_GetClipboardTextFn == Platform_GetClipboardTextFn_DefaultImpl))
@@ -10426,43 +10455,35 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
     IM_ASSERT((key_mods == 0 || g.IO.KeyMods == key_mods) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
     IM_UNUSED(key_mods);
 
-    // [EXPERIMENTAL] Recover from errors: You may call this yourself before EndFrame().
-    //ErrorCheckEndFrameRecover();
-
-    // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you
-    // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API).
-    if (g.CurrentWindowStack.Size != 1)
-    {
-        if (g.CurrentWindowStack.Size > 1)
-        {
-            ImGuiWindow* window = g.CurrentWindowStack.back().Window; // <-- This window was not Ended!
-            IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
-            IM_UNUSED(window);
-            while (g.CurrentWindowStack.Size > 1)
-                End();
-        }
-        else
-        {
-            IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
-        }
-    }
-    if (g.CurrentWindowStack.Size >= 1)
-        IM_ASSERT(g.CurrentWindowStack[0].Window->IsFallbackWindow);
+    IM_ASSERT(g.CurrentWindowStack.Size == 1);
+    IM_ASSERT(g.CurrentWindowStack[0].Window->IsFallbackWindow);
+}
 
-    IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!");
+// Save current stack sizes. Called e.g. by NewFrame() and by Begin() but may be called for manual recovery.
+void ImGui::ErrorRecoveryStoreState(ImGuiErrorRecoveryState* state_out)
+{
+    ImGuiContext& g = *GImGui;
+    state_out->SizeOfWindowStack = (short)g.CurrentWindowStack.Size;
+    state_out->SizeOfIDStack = (short)g.CurrentWindow->IDStack.Size;
+    state_out->SizeOfColorStack = (short)g.ColorStack.Size;
+    state_out->SizeOfStyleVarStack = (short)g.StyleVarStack.Size;
+    state_out->SizeOfFontStack = (short)g.FontStack.Size;
+    state_out->SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size;
+    state_out->SizeOfGroupStack = (short)g.GroupStack.Size;
+    state_out->SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size;
+    state_out->SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size;
+    state_out->SizeOfDisabledStack = (short)g.DisabledStackSize;
 }
 
-// Experimental recovery from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls.
-// Must be called during or before EndFrame().
-// This is generally flawed as we are not necessarily End/Popping things in the right order.
-// FIXME: Can't recover from inside BeginTabItem/EndTabItem yet.
-void    ImGui::ErrorCheckEndFrameRecover()
+// Chosen name "Try to recover" over e.g. "Restore" to suggest this is not a 100% guaranteed recovery.
+// Called by e.g. EndFrame() but may be called for manual recovery.
+// Attempt to recover full window stack.
+void ImGui::ErrorRecoveryTryToRecoverState(const ImGuiErrorRecoveryState* state_in)
 {
     // PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations"
     ImGuiContext& g = *GImGui;
-    while (g.CurrentWindowStack.Size > 0) //-V1044
+    while (g.CurrentWindowStack.Size > state_in->SizeOfWindowStack) //-V1044
     {
-        ErrorCheckEndWindowRecover();
         // Recap:
         // - Begin()/BeginChild() return false to indicate the window is collapsed or fully clipped.
         // - Always call a matching End() for each Begin() call, regardless of its return value!
@@ -10480,12 +10501,17 @@ void    ImGui::ErrorCheckEndFrameRecover()
             End();
         }
     }
+    if (g.CurrentWindowStack.Size == state_in->SizeOfWindowStack)
+        ErrorRecoveryTryToRecoverWindowState(state_in);
 }
 
-// Must be called before End()/EndChild()
-void    ImGui::ErrorCheckEndWindowRecover()
+// Called by e.g. End() but may be called for manual recovery.
+// Read '// Error Handling [BETA]' block in imgui_internal.h for details.
+// Attempt to recover from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls.
+void    ImGui::ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryState* state_in)
 {
     ImGuiContext& g = *GImGui;
+
     while (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow)
     {
         IM_ASSERT_USER_ERROR(0, "Missing EndTable()");
@@ -10493,8 +10519,6 @@ void    ImGui::ErrorCheckEndWindowRecover()
     }
 
     ImGuiWindow* window = g.CurrentWindow;
-    IM_ASSERT(window != NULL);
-    ImGuiStackSizes* state_in = &g.CurrentWindowStack.back().StackSizesOnBegin;
 
     // FIXME: Can't recover from inside BeginTabItem/EndTabItem yet.
     while (g.CurrentTabBar != NULL && g.CurrentTabBar->Window == window) //-V1044
@@ -10560,45 +10584,52 @@ void    ImGui::ErrorCheckEndWindowRecover()
         IM_ASSERT_USER_ERROR(0, "Missing PopFocusScope()");
         PopFocusScope();
     }
+    //IM_ASSERT(g.FocusScopeStack.Size == state_in->SizeOfFocusScopeStack);
 }
 
-// Save current stack sizes for later compare
-void ImGuiStackSizes::SetToContextState(ImGuiContext* ctx)
+bool    ImGui::ErrorLog(const char* msg)
 {
-    ImGuiContext& g = *ctx;
-    ImGuiWindow* window = g.CurrentWindow;
-    SizeOfIDStack = (short)window->IDStack.Size;
-    SizeOfColorStack = (short)g.ColorStack.Size;
-    SizeOfStyleVarStack = (short)g.StyleVarStack.Size;
-    SizeOfFontStack = (short)g.FontStack.Size;
-    SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size;
-    SizeOfGroupStack = (short)g.GroupStack.Size;
-    SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size;
-    SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size;
-    SizeOfDisabledStack = (short)g.DisabledStackSize;
-}
+    ImGuiContext& g = *GImGui;
 
-// Compare to detect usage errors
-void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx)
-{
-    ImGuiContext& g = *ctx;
+    // Output to debug log
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
     ImGuiWindow* window = g.CurrentWindow;
-    IM_UNUSED(window);
 
-    // Window stacks
-    // NOT checking: DC.ItemWidth, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
-    IM_ASSERT(SizeOfIDStack         == window->IDStack.Size     && "PushID/PopID or TreeNode/TreePop Mismatch!");
+    if (g.IO.ConfigErrorRecoveryEnableDebugLog)
+    {
+        if (g.ErrorFirst)
+            IMGUI_DEBUG_LOG_ERROR("[imgui-error] (current settings: Assert=%d, Log=%d, Tooltip=%d)\n",
+                g.IO.ConfigErrorRecoveryEnableAssert, g.IO.ConfigErrorRecoveryEnableDebugLog, g.IO.ConfigErrorRecoveryEnableTooltip);
+        IMGUI_DEBUG_LOG_ERROR("[imgui-error] In window '%s': %s\n", window ? window->Name : "NULL", msg);
+    }
+    g.ErrorFirst = false;
+
+    // Output to tooltip
+    if (g.IO.ConfigErrorRecoveryEnableTooltip)
+    {
+        if (BeginErrorTooltip())
+        {
+            if (g.ErrorCountCurrentFrame < 20)
+            {
+                Text("In window '%s': %s", window ? window->Name : "NULL", msg);
+                if (window && (!window->IsFallbackWindow || window->WasActive))
+                    GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 0, 0, 255));
+            }
+            if (g.ErrorCountCurrentFrame == 20)
+                Text("(and more errors)");
+            // EndFrame() will amend debug buttons to this window, after all errors have been submitted.
+            EndErrorTooltip();
+        }
+        g.ErrorCountCurrentFrame++;
+    }
+#endif
+
+    // Output to callback
+    if (g.ErrorCallback != NULL)
+        g.ErrorCallback(&g, g.ErrorCallbackUserData, msg);
 
-    // Global stacks
-    // For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them.
-    IM_ASSERT(SizeOfGroupStack      == g.GroupStack.Size        && "BeginGroup/EndGroup Mismatch!");
-    IM_ASSERT(SizeOfBeginPopupStack == g.BeginPopupStack.Size   && "BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!");
-    IM_ASSERT(SizeOfDisabledStack   == g.DisabledStackSize      && "BeginDisabled/EndDisabled Mismatch!");
-    IM_ASSERT(SizeOfItemFlagsStack  >= g.ItemFlagsStack.Size    && "PushItemFlag/PopItemFlag Mismatch!");
-    IM_ASSERT(SizeOfColorStack      >= g.ColorStack.Size        && "PushStyleColor/PopStyleColor Mismatch!");
-    IM_ASSERT(SizeOfStyleVarStack   >= g.StyleVarStack.Size     && "PushStyleVar/PopStyleVar Mismatch!");
-    IM_ASSERT(SizeOfFontStack       >= g.FontStack.Size         && "PushFont/PopFont Mismatch!");
-    IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size   && "PushFocusScope/PopFocusScope Mismatch!");
+    // Return whether we should assert
+    return g.IO.ConfigErrorRecoveryEnableAssert;
 }
 
 void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
@@ -10625,6 +10656,21 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
             g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
         EndErrorTooltip();
     }
+
+    if (g.ErrorCountCurrentFrame > 0 && BeginErrorTooltip()) // Amend at end of frame
+    {
+        Separator();
+        Text("(Hold CTRL and:");
+        SameLine();
+        if (SmallButton("Enable Asserts"))
+            g.IO.ConfigErrorRecoveryEnableAssert = true;
+        //SameLine();
+        //if (SmallButton("Hide Error Tooltips"))
+        //    g.IO.ConfigErrorRecoveryEnableTooltip = false; // Too dangerous
+        SameLine(0, 0);
+        Text(")");
+        EndErrorTooltip();
+    }
 #endif
 }
 
diff --git a/imgui.h b/imgui.h
index f86efc42829b..4ab39be3fc45 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.3 WIP"
-#define IMGUI_VERSION_NUM   19122
+#define IMGUI_VERSION_NUM   19123
 #define IMGUI_HAS_TABLE
 
 /*
@@ -2265,6 +2265,23 @@ struct ImGuiIO
     // Debug options
     //------------------------------------------------------------------
 
+    // Options to configure how we handle recoverable errors [EXPERIMENTAL]
+    // - Error recovery is not perfect nor guaranteed! It is a feature to ease development.
+    // - Functions that support error recovery are using IM_ASSERT_USER_ERROR() instead of IM_ASSERT().
+    // - You not are not supposed to rely on it in the course of a normal application run.
+    // - Possible usage: facilitate recovery from errors triggered from a scripting language or after specific exceptions handlers.
+    // - Always ensure that on programmers seat you have at minimum Asserts or Tooltips enabled when making direct imgui API calls!
+    //   Otherwise it would severely hinder your ability to catch and correct mistakes!
+    // Read https://github.com/ocornut/imgui/wiki/Error-Handling for details about typical usage scenarios:
+    // - Programmer seats: keep asserts (default), or disable asserts and keep error tooltips (new and nice!)
+    // - Non-programmer seats: maybe disable asserts, but make sure errors are resurfaced (visible log entries, use callback etc.)
+    // - Recovery after error from scripting language: record stack sizes before running script, disable assert, trigger breakpoint from ErrorCallback, recover with ErrorRecoveryTryToRecoverState(), restore settings.
+    // - Recovery after an exception handler:  record stack sizes before try {} block, disable assert, set log callback, recover with ErrorRecoveryTryToRecoverState(), restore settings.
+    bool        ConfigErrorRecovery;                // = true       // Enable error recovery support. Some errors won't be detected and lead to direct crashes if recovery is disabled.
+    bool        ConfigErrorRecoveryEnableAssert;    // = true       // Enable asserts on recoverable error. By default call IM_ASSERT() when returning from a failing IM_ASSERT_USER_ERROR()
+    bool        ConfigErrorRecoveryEnableDebugLog;  // = true       // Enable debug log output on recoverable errors.
+    bool        ConfigErrorRecoveryEnableTooltip;   // = true       // Enable tooltip on recoverable errors. The tooltip include a way to enable asserts if they were disabled.
+
     // Option to enable various debug tools showing buttons that will call the IM_DEBUG_BREAK() macro.
     // - The Item Picker tool will be available regardless of this being enabled, in order to maximize its discoverability.
     // - Requires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.
@@ -2293,7 +2310,7 @@ struct ImGuiIO
     bool        ConfigDebugIniSettings;         // = false          // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower)
 
     //------------------------------------------------------------------
-    // Platform Functions
+    // Platform Identifiers
     // (the imgui_impl_xxxx backend files are setting those up for you)
     //------------------------------------------------------------------
 
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 8fb410d9b10a..60d94465797d 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -545,6 +545,22 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
             ImGui::Text("Also see Style->Rendering for rendering options.");
 
+            // Read https://github.com/ocornut/imgui/wiki/Error-Handling
+            ImGui::SeparatorText("Error Handling");
+            ImGui::Checkbox("io.ConfigErrorRecovery", &io.ConfigErrorRecovery);
+            ImGui::SameLine(); HelpMarker(
+                "Options to configure how we handle recoverable errors.\n"
+                "- Error recovery is not perfect nor guaranteed! It is a feature to ease development.\n"
+                "- You not are not supposed to rely on it in the course of a normal application run.\n"
+                "- Possible usage: facilitate recovery from errors triggered from a scripting language or after specific exceptions handlers.\n"
+                "- Always ensure that on programmers seat you have at minimum Asserts or Tooltips enabled when making direct imgui API call!"
+                "Otherwise it would severely hinder your ability to catch and correct mistakes!");
+            ImGui::Checkbox("io.ConfigErrorRecoveryEnableAssert", &io.ConfigErrorRecoveryEnableAssert);
+            ImGui::Checkbox("io.ConfigErrorRecoveryEnableDebugLog", &io.ConfigErrorRecoveryEnableDebugLog);
+            ImGui::Checkbox("io.ConfigErrorRecoveryEnableTooltip", &io.ConfigErrorRecoveryEnableTooltip);
+            if (!io.ConfigErrorRecoveryEnableAssert && !io.ConfigErrorRecoveryEnableDebugLog && !io.ConfigErrorRecoveryEnableTooltip)
+                io.ConfigErrorRecoveryEnableAssert = io.ConfigErrorRecoveryEnableDebugLog = io.ConfigErrorRecoveryEnableTooltip = true;
+
             ImGui::SeparatorText("Debug");
             ImGui::Checkbox("io.ConfigDebugIsDebuggerPresent", &io.ConfigDebugIsDebuggerPresent);
             ImGui::SameLine(); HelpMarker("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.");
diff --git a/imgui_internal.h b/imgui_internal.h
index a00a675bd191..52664a1c5ab0 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -132,6 +132,7 @@ struct ImGuiContext;                // Main Dear ImGui context
 struct ImGuiContextHook;            // Hook for extensions like ImGuiTestEngine
 struct ImGuiDataVarInfo;            // Variable information (e.g. to access style variables from an enum)
 struct ImGuiDataTypeInfo;           // Type information associated to a ImGuiDataType enum
+struct ImGuiErrorRecoveryState;     // Storage of stack sizes for error handling and recovery
 struct ImGuiGroupData;              // Stacked storage data for BeginGroup()/EndGroup()
 struct ImGuiInputTextState;         // Internal state of the currently focused/edited text input box
 struct ImGuiInputTextDeactivateData;// Short term storage to backup text of a deactivating InputText() while another is stealing active id
@@ -148,7 +149,6 @@ struct ImGuiOldColumnData;          // Storage data for a single column for lega
 struct ImGuiOldColumns;             // Storage data for a columns set for legacy Columns() api
 struct ImGuiPopupData;              // Storage for current popup stack
 struct ImGuiSettingsHandler;        // Storage for one type registered in the .ini file
-struct ImGuiStackSizes;             // Storage of stack sizes for debugging/asserting
 struct ImGuiStyleMod;               // Stacked style modifier, backup of modified data so we can restore it
 struct ImGuiTabBar;                 // Storage for a tab bar
 struct ImGuiTabItem;                // Storage for a tab item (within a tab bar)
@@ -1253,9 +1253,10 @@ struct ImGuiTreeNodeStackData
     ImRect                  NavRect;    // Used for nav landing
 };
 
-// sizeof() = 18
-struct IMGUI_API ImGuiStackSizes
+// sizeof() = 20
+struct IMGUI_API ImGuiErrorRecoveryState
 {
+    short   SizeOfWindowStack;
     short   SizeOfIDStack;
     short   SizeOfColorStack;
     short   SizeOfStyleVarStack;
@@ -1266,18 +1267,16 @@ struct IMGUI_API ImGuiStackSizes
     short   SizeOfBeginPopupStack;
     short   SizeOfDisabledStack;
 
-    ImGuiStackSizes() { memset(this, 0, sizeof(*this)); }
-    void SetToContextState(ImGuiContext* ctx);
-    void CompareWithContextState(ImGuiContext* ctx);
+    ImGuiErrorRecoveryState() { memset(this, 0, sizeof(*this)); }
 };
 
 // Data saved for each window pushed into the stack
 struct ImGuiWindowStackData
 {
-    ImGuiWindow*        Window;
-    ImGuiLastItemData   ParentLastItemDataBackup;
-    ImGuiStackSizes     StackSizesOnBegin;          // Store size of various stacks for asserting
-    bool                DisabledOverrideReenable;   // Non-child window override disabled flag
+    ImGuiWindow*            Window;
+    ImGuiLastItemData       ParentLastItemDataBackup;
+    ImGuiErrorRecoveryState StackSizesInBegin;          // Store size of various stacks for asserting
+    bool                    DisabledOverrideReenable;   // Non-child window override disabled flag
 };
 
 struct ImGuiShrinkWidthItem
@@ -1885,12 +1884,17 @@ struct ImGuiLocEntry
 //-----------------------------------------------------------------------------
 
 // Macros used by Recoverable Error handling
-// Down the line in some frameworks/languages we would like to have a way to redirect those to the programmer and recover from more faults.
+// - Only dispatch error if _EXPR: evaluate as assert (similar to an assert macro).
+// - The message will always be a string literal, in order to increase likelihood of being display by an assert handler.
+// - The intent is that you may rewire this macro to dispatch dynamically:
+//   - On programmers machines, when debugger is attached, on direct imgui API usage error: always assert!
+//   - On exception recovery and script language recovery: you may decide to error log.
 #ifndef IM_ASSERT_USER_ERROR
-#define IM_ASSERT_USER_ERROR(_EXPR,_MSG)    IM_ASSERT((_EXPR) && _MSG)
+#define IM_ASSERT_USER_ERROR(_EXPR,_MSG)    do { if (!(_EXPR) && ImGui::ErrorLog(_MSG)) { IM_ASSERT((_EXPR) && _MSG); } } while (0)    // Recoverable User Error
 #endif
 
-typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
+
+typedef void    (*ImGuiErrorCallback)(ImGuiContext* ctx, void* user_data, const char* msg); // Function signature for g.ErrorCallback
 
 //-----------------------------------------------------------------------------
 // [SECTION] Metrics, Debug Tools
@@ -2313,8 +2317,14 @@ struct ImGuiContext
     int                     LogDepthToExpand;
     int                     LogDepthToExpandDefault;            // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call.
 
-    // Error handling
+    // Error Handling
+    ImGuiErrorCallback      ErrorCallback;                      // = NULL. May be exposed in public API eventually.
+    void*                   ErrorCallbackUserData;              // = NULL
     ImVec2                  ErrorTooltipLockedPos;
+    bool                    ErrorFirst;
+    int                     ErrorCountCurrentFrame;             // [Internal] Number of errors submitted this frame.
+    ImGuiErrorRecoveryState StackSizesInNewFrame;               // [Internal]
+    ImGuiErrorRecoveryState*StackSizesInBeginForCurrentWindow;  // [Internal]
 
     // Debug Tools
     // (some of the highly frequently used data are interleaved in other structures above: DebugBreakXXX fields, DebugHookIdInfo, DebugLocateId etc.)
@@ -3419,9 +3429,11 @@ namespace ImGui
     IMGUI_API void          GcAwakeTransientWindowBuffers(ImGuiWindow* window);
 
     // Error handling, State Recovery
+    IMGUI_API bool          ErrorLog(const char* msg);
+    IMGUI_API void          ErrorRecoveryStoreState(ImGuiErrorRecoveryState* state_out);
+    IMGUI_API void          ErrorRecoveryTryToRecoverState(const ImGuiErrorRecoveryState* state_in);
+    IMGUI_API void          ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryState* state_in);
     IMGUI_API void          ErrorCheckUsingSetCursorPosToExtendParentBoundaries();
-    IMGUI_API void          ErrorCheckEndFrameRecover();
-    IMGUI_API void          ErrorCheckEndWindowRecover();
     IMGUI_API void          ErrorCheckEndFrameFinalizeErrorTooltip();
     IMGUI_API bool          BeginErrorTooltip();
     IMGUI_API void          EndErrorTooltip();
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index dc7f210986f2..4a6fbed7cb25 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1484,7 +1484,9 @@ void    ImGui::EndTable()
     {
         short backup_nav_layers_active_mask = inner_window->DC.NavLayersActiveMask;
         inner_window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main; // So empty table don't appear to navigate differently.
+        g.CurrentTable = NULL; // To avoid error recovery recursing
         EndChild();
+        g.CurrentTable = table;
         inner_window->DC.NavLayersActiveMask = backup_nav_layers_active_mask;
     }
     else
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 5641134ffca3..22ff7a9e5578 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -7551,7 +7551,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
     ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect;
     ImGuiMultiSelectState* storage = ms->Storage;
     ImGuiWindow* window = g.CurrentWindow;
-    IM_ASSERT(ms->FocusScopeId == g.CurrentFocusScopeId);
+    IM_ASSERT_USER_ERROR(ms->FocusScopeId == g.CurrentFocusScopeId, "EndMultiSelect() FocusScope mismatch!");
     IM_ASSERT(g.CurrentMultiSelect != NULL && storage->Window == g.CurrentWindow);
     IM_ASSERT(g.MultiSelectTempDataStacked > 0 && &g.MultiSelectTempData[g.MultiSelectTempDataStacked - 1] == g.CurrentMultiSelect);
 

From 199a44e31e20f7620fc1d67b69107b3c2a8eda8a Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 26 Sep 2024 17:51:46 +0200
Subject: [PATCH 159/548] Error Handling: fixed not rewinding to recorded tree
 and id stack size (#1651)

---
 imgui.cpp        | 5 +++--
 imgui_internal.h | 1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 306a730ce1b7..5379248c8f95 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -10465,6 +10465,7 @@ void ImGui::ErrorRecoveryStoreState(ImGuiErrorRecoveryState* state_out)
     ImGuiContext& g = *GImGui;
     state_out->SizeOfWindowStack = (short)g.CurrentWindowStack.Size;
     state_out->SizeOfIDStack = (short)g.CurrentWindow->IDStack.Size;
+    state_out->SizeOfTreeStack = (short)g.CurrentWindow->DC.TreeDepth; // NOT g.TreeNodeStack.Size which is a partial stack!
     state_out->SizeOfColorStack = (short)g.ColorStack.Size;
     state_out->SizeOfStyleVarStack = (short)g.StyleVarStack.Size;
     state_out->SizeOfFontStack = (short)g.FontStack.Size;
@@ -10531,7 +10532,7 @@ void    ImGui::ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryStat
         IM_ASSERT_USER_ERROR(0, "Missing EndMultiSelect()");
         EndMultiSelect();
     }
-    while (window->DC.TreeDepth > 0)
+    while (window->DC.TreeDepth > state_in->SizeOfTreeStack) //-V1044
     {
         IM_ASSERT_USER_ERROR(0, "Missing TreePop()");
         TreePop();
@@ -10542,7 +10543,7 @@ void    ImGui::ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryStat
         EndGroup();
     }
     IM_ASSERT(g.GroupStack.Size == state_in->SizeOfGroupStack);
-    while (window->IDStack.Size > 1)
+    while (window->IDStack.Size > state_in->SizeOfIDStack) //-V1044
     {
         IM_ASSERT_USER_ERROR(0, "Missing PopID()");
         PopID();
diff --git a/imgui_internal.h b/imgui_internal.h
index 52664a1c5ab0..cb9071478667 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1258,6 +1258,7 @@ struct IMGUI_API ImGuiErrorRecoveryState
 {
     short   SizeOfWindowStack;
     short   SizeOfIDStack;
+    short   SizeOfTreeStack;
     short   SizeOfColorStack;
     short   SizeOfStyleVarStack;
     short   SizeOfFontStack;

From ba14c70b020038bd580ab72da5181f03df4eb872 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 27 Sep 2024 19:23:41 +0200
Subject: [PATCH 160/548] Comments. Fixed warnings.

---
 imgui.cpp        | 2 ++
 imgui_demo.cpp   | 5 ++++-
 imgui_internal.h | 9 ++++-----
 3 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 5379248c8f95..0bfbff945dc5 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -10452,6 +10452,8 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
     // while still correctly asserting on mid-frame key press events.
     ImGuiContext& g = *GImGui;
     const ImGuiKeyChord key_mods = GetMergedModsFromKeys();
+    IM_UNUSED(g);
+    IM_UNUSED(key_mods);
     IM_ASSERT((key_mods == 0 || g.IO.KeyMods == key_mods) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
     IM_UNUSED(key_mods);
 
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 60d94465797d..feaee3be9eb2 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -545,8 +545,9 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
             ImGui::Text("Also see Style->Rendering for rendering options.");
 
-            // Read https://github.com/ocornut/imgui/wiki/Error-Handling
+            // Also read: https://github.com/ocornut/imgui/wiki/Error-Handling
             ImGui::SeparatorText("Error Handling");
+
             ImGui::Checkbox("io.ConfigErrorRecovery", &io.ConfigErrorRecovery);
             ImGui::SameLine(); HelpMarker(
                 "Options to configure how we handle recoverable errors.\n"
@@ -561,6 +562,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
             if (!io.ConfigErrorRecoveryEnableAssert && !io.ConfigErrorRecoveryEnableDebugLog && !io.ConfigErrorRecoveryEnableTooltip)
                 io.ConfigErrorRecoveryEnableAssert = io.ConfigErrorRecoveryEnableDebugLog = io.ConfigErrorRecoveryEnableTooltip = true;
 
+            // Also read: https://github.com/ocornut/imgui/wiki/Debug-Tools
             ImGui::SeparatorText("Debug");
             ImGui::Checkbox("io.ConfigDebugIsDebuggerPresent", &io.ConfigDebugIsDebuggerPresent);
             ImGui::SameLine(); HelpMarker("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.");
@@ -595,6 +597,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos",       &io.BackendFlags, ImGuiBackendFlags_HasSetMousePos);
             ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &io.BackendFlags, ImGuiBackendFlags_RendererHasVtxOffset);
             ImGui::EndDisabled();
+
             ImGui::TreePop();
             ImGui::Spacing();
         }
diff --git a/imgui_internal.h b/imgui_internal.h
index cb9071478667..80bba6903771 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1887,15 +1887,14 @@ struct ImGuiLocEntry
 // Macros used by Recoverable Error handling
 // - Only dispatch error if _EXPR: evaluate as assert (similar to an assert macro).
 // - The message will always be a string literal, in order to increase likelihood of being display by an assert handler.
-// - The intent is that you may rewire this macro to dispatch dynamically:
-//   - On programmers machines, when debugger is attached, on direct imgui API usage error: always assert!
-//   - On exception recovery and script language recovery: you may decide to error log.
+// - See 'Demo->Configuration->Error Handling' and ImGuiIO definitions for details on error handling.
+// - Read https://github.com/ocornut/imgui/wiki/Error-Handling for details on error handling.
 #ifndef IM_ASSERT_USER_ERROR
 #define IM_ASSERT_USER_ERROR(_EXPR,_MSG)    do { if (!(_EXPR) && ImGui::ErrorLog(_MSG)) { IM_ASSERT((_EXPR) && _MSG); } } while (0)    // Recoverable User Error
 #endif
 
-
-typedef void    (*ImGuiErrorCallback)(ImGuiContext* ctx, void* user_data, const char* msg); // Function signature for g.ErrorCallback
+// The error callback is currently not public, as it is expected that only advanced users will rely on it.
+typedef void (*ImGuiErrorCallback)(ImGuiContext* ctx, void* user_data, const char* msg); // Function signature for g.ErrorCallback
 
 //-----------------------------------------------------------------------------
 // [SECTION] Metrics, Debug Tools

From 29cff2be06860cadbc7557cc64f29159468213e2 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Sat, 28 Sep 2024 16:54:45 +0200
Subject: [PATCH 161/548] Silence PVS Studio static analyzer false positives.

---
 imgui.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 0bfbff945dc5..5af8a024fd5b 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -10515,7 +10515,7 @@ void    ImGui::ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryStat
 {
     ImGuiContext& g = *GImGui;
 
-    while (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow)
+    while (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow) //-V1044
     {
         IM_ASSERT_USER_ERROR(0, "Missing EndTable()");
         EndTable();
@@ -10529,7 +10529,7 @@ void    ImGui::ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryStat
         IM_ASSERT_USER_ERROR(0, "Missing EndTabBar()");
         EndTabBar();
     }
-    while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window)
+    while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window) //-V1044
     {
         IM_ASSERT_USER_ERROR(0, "Missing EndMultiSelect()");
         EndMultiSelect();
@@ -10562,7 +10562,7 @@ void    ImGui::ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryStat
         }
     }
     IM_ASSERT(g.DisabledStackSize == state_in->SizeOfDisabledStack);
-    while (g.ColorStack.Size > state_in->SizeOfColorStack)
+    while (g.ColorStack.Size > state_in->SizeOfColorStack) //-V1044
     {
         IM_ASSERT_USER_ERROR(0, "Missing PopStyleColor()");
         PopStyleColor();

From 03f007d4cd106ef5ce16a40a2f24147ddb48674c Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 30 Sep 2024 12:04:48 +0200
Subject: [PATCH 162/548] Comments (#1651)

---
 docs/CHANGELOG.txt |  8 +++++++-
 imgui.cpp          |  2 +-
 imgui.h            | 18 ++++++++++--------
 3 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 511901085940..db13bc9b1375 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -44,9 +44,15 @@ Breaking changes:
 Other changes:
 
 - Error Handling: Enabled/improved error recovery systems. (#1651, #5654)
+  - Error recovery is provided as a way to facilitate:
+    - Recovery after a programming error. Native code or scripting language (the later
+      tends to facilitate iterating on code while running).
+    - Recovery after running an exception handler or any error processing which may skip code
+      after an error has been detected.
   - Error recovery is not perfect nor guaranteed! It is a feature to ease development.
+    You not are not supposed to rely on it in the course of a normal application run.
   - Functions that support error recovery are using IM_ASSERT_USER_ERROR() instead of IM_ASSERT().
-  - You not are not supposed to rely on it in the course of a normal application run.
+  - By design, we do not allow error recovery to be 100% silent. One of the options needs to be enabled!
   - Possible usage: facilitate recovery from errors triggered from a scripting language or
     after specific exceptions handlers. Surface errors to programmers in less agressive ways.
   - Always ensure that on programmers seats you have at minimum Asserts or Tooltips enabled
diff --git a/imgui.cpp b/imgui.cpp
index 5af8a024fd5b..5f0c8281b641 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -15240,7 +15240,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
     DebugBreakClearData();
 
     // Basic info
-    Text("Dear ImGui %s", GetVersion());
+    Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
     if (g.ContextName[0] != 0)
     {
         SameLine();
diff --git a/imgui.h b/imgui.h
index 4ab39be3fc45..59ea4baacf3a 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2265,18 +2265,20 @@ struct ImGuiIO
     // Debug options
     //------------------------------------------------------------------
 
-    // Options to configure how we handle recoverable errors [EXPERIMENTAL]
+    // Options to configure Error Handling and how we handle recoverable errors [EXPERIMENTAL]
+    // - Error recovery is provided as a way to facilitate:
+    //    - Recovery after a programming error (native code or scripting language - the later tends to facilitate iterating on code while running).
+    //    - Recovery after running an exception handler or any error processing which may skip code after an error has been detected.
     // - Error recovery is not perfect nor guaranteed! It is a feature to ease development.
+    //   You not are not supposed to rely on it in the course of a normal application run.
     // - Functions that support error recovery are using IM_ASSERT_USER_ERROR() instead of IM_ASSERT().
-    // - You not are not supposed to rely on it in the course of a normal application run.
-    // - Possible usage: facilitate recovery from errors triggered from a scripting language or after specific exceptions handlers.
-    // - Always ensure that on programmers seat you have at minimum Asserts or Tooltips enabled when making direct imgui API calls!
+    // - By design, we do NOT allow error recovery to be 100% silent. One of the three options needs to be checked!
+    // - Always ensure that on programmers seats you have at minimum Asserts or Tooltips enabled when making direct imgui API calls!
     //   Otherwise it would severely hinder your ability to catch and correct mistakes!
-    // Read https://github.com/ocornut/imgui/wiki/Error-Handling for details about typical usage scenarios:
+    // Read https://github.com/ocornut/imgui/wiki/Error-Handling for details.
     // - Programmer seats: keep asserts (default), or disable asserts and keep error tooltips (new and nice!)
-    // - Non-programmer seats: maybe disable asserts, but make sure errors are resurfaced (visible log entries, use callback etc.)
-    // - Recovery after error from scripting language: record stack sizes before running script, disable assert, trigger breakpoint from ErrorCallback, recover with ErrorRecoveryTryToRecoverState(), restore settings.
-    // - Recovery after an exception handler:  record stack sizes before try {} block, disable assert, set log callback, recover with ErrorRecoveryTryToRecoverState(), restore settings.
+    // - Non-programmer seats: maybe disable asserts, but make sure errors are resurfaced (tooltips, visible log entries, use callback etc.)
+    // - Recovery after error/exception: record stack sizes with ErrorRecoveryStoreState(), disable assert, set log callback (to e.g. trigger high-level breakpoint), recover with ErrorRecoveryTryToRecoverState(), restore settings.
     bool        ConfigErrorRecovery;                // = true       // Enable error recovery support. Some errors won't be detected and lead to direct crashes if recovery is disabled.
     bool        ConfigErrorRecoveryEnableAssert;    // = true       // Enable asserts on recoverable error. By default call IM_ASSERT() when returning from a failing IM_ASSERT_USER_ERROR()
     bool        ConfigErrorRecoveryEnableDebugLog;  // = true       // Enable debug log output on recoverable errors.

From 655fcf82870a8ecdf51aced1d6f685bce373a38e Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 30 Sep 2024 19:36:58 +0200
Subject: [PATCH 163/548] TabBar: added TabBarQueueFocus() by name for
 non-docking tab bars. (#8029, #6681)

---
 imgui_internal.h  | 1 +
 imgui_widgets.cpp | 7 +++++++
 2 files changed, 8 insertions(+)

diff --git a/imgui_internal.h b/imgui_internal.h
index 80bba6903771..113b05426cff 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -3318,6 +3318,7 @@ namespace ImGui
     IMGUI_API void          TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
     IMGUI_API void          TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
     IMGUI_API void          TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
+    IMGUI_API void          TabBarQueueFocus(ImGuiTabBar* tab_bar, const char* tab_name);
     IMGUI_API void          TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset);
     IMGUI_API void          TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, ImVec2 mouse_pos);
     IMGUI_API bool          TabBarProcessReorder(ImGuiTabBar* tab_bar);
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 22ff7a9e5578..46c418356766 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -9627,6 +9627,13 @@ void ImGui::TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
     tab_bar->NextSelectedTabId = tab->ID;
 }
 
+void ImGui::TabBarQueueFocus(ImGuiTabBar* tab_bar, const char* tab_name)
+{
+    IM_ASSERT((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0); // Only supported for manual/explicit tab bars
+    ImGuiID tab_id = TabBarCalcTabID(tab_bar, tab_name);
+    tab_bar->NextSelectedTabId = tab_id;
+}
+
 void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset)
 {
     IM_ASSERT(offset != 0);

From 004f03945f3c09b89078af8e31e59875de37d107 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 30 Sep 2024 20:01:06 +0200
Subject: [PATCH 164/548] TabBar: added TabBarQueueFocus() by name for
 non-docking tab bars. (#8029, #6681)

Amend 655fcf8
---
 imgui_widgets.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 46c418356766..9192dbcba8bc 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -9630,7 +9630,7 @@ void ImGui::TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
 void ImGui::TabBarQueueFocus(ImGuiTabBar* tab_bar, const char* tab_name)
 {
     IM_ASSERT((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0); // Only supported for manual/explicit tab bars
-    ImGuiID tab_id = TabBarCalcTabID(tab_bar, tab_name);
+    ImGuiID tab_id = TabBarCalcTabID(tab_bar, tab_name, NULL);
     tab_bar->NextSelectedTabId = tab_id;
 }
 

From f0575411c0137c3524fa40fad63d8eb24b8558ee Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 2 Oct 2024 15:23:54 +0200
Subject: [PATCH 165/548] Tooltips, Drag and Drop: Fixed an issue where the
 fallback drag and drop payload tooltip appeared during drag and drop release.

E.g. it would otherwise appear when releasing a color button payload.
---
 docs/CHANGELOG.txt | 2 ++
 imgui.cpp          | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index db13bc9b1375..f9fb7586626f 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -71,6 +71,8 @@ Other changes:
 - Scrollbar: Shift+Click scroll to clicked location (pre-1.90.8 default). (#8002, #7328)
 - Scrollbar: added io.ConfigScrollbarScrollByPage setting (default to true). (#8002, #7328)
   Set io.ConfigScrollbarScrollByPage=false to enforce always scrolling to clicked location.
+- Tooltips, Drag and Drop: Fixed an issue where the fallback drag and drop payload tooltip
+  appeared during drag and drop release.
 - Backends: SDL3: Update for API changes: SDL_bool removal. SDL_INIT_TIMER removal.
 - Backends: WebGPU: Fixed DAWN api change using WGPUStringView in WGPUShaderSourceWGSL.
   (#8009, #8010) [@blitz-research]
diff --git a/imgui.cpp b/imgui.cpp
index 5f0c8281b641..059a7ec56779 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -5521,7 +5521,7 @@ void ImGui::EndFrame()
     // in the BeginDragDropSource() block of the dragged item, you can submit them from a safe single spot
     // (e.g. end of your item loop, or before EndFrame) by reading payload data.
     // In the typical case, the contents of drag tooltip should be possible to infer solely from payload data.
-    if (g.DragDropActive && g.DragDropSourceFrameCount < g.FrameCount && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
+    if (g.DragDropActive && g.DragDropSourceFrameCount + 1 < g.FrameCount && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
     {
         g.DragDropWithinSource = true;
         SetTooltip("...");

From 014b722963f3ca2184b594439d6184ece4078de0 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 2 Oct 2024 18:26:02 +0200
Subject: [PATCH 166/548] Tooltips, Drag and Drop: Stabilized name of drag and
 drop tooltip window. (#8036)

---
 docs/CHANGELOG.txt |  3 +++
 imgui.cpp          | 28 +++++++++++++++++-----------
 imgui.h            |  2 +-
 imgui_internal.h   |  1 +
 4 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index f9fb7586626f..489d010d8fd8 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -73,6 +73,9 @@ Other changes:
   Set io.ConfigScrollbarScrollByPage=false to enforce always scrolling to clicked location.
 - Tooltips, Drag and Drop: Fixed an issue where the fallback drag and drop payload tooltip
   appeared during drag and drop release.
+- Tooltips, Drag and Drop: Stabilized name of drag and drop tooltip window so that
+  transitioning from an item tooltip to a drag tooltip doesn't leak window auto-sizing
+  info from one to the other. (#8036)
 - Backends: SDL3: Update for API changes: SDL_bool removal. SDL_INIT_TIMER removal.
 - Backends: WebGPU: Fixed DAWN api change using WGPUStringView in WGPUShaderSourceWGSL.
   (#8009, #8010) [@blitz-research]
diff --git a/imgui.cpp b/imgui.cpp
index 059a7ec56779..eae120fd72b6 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3964,6 +3964,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     DisabledStackSize = 0;
     LockMarkEdited = 0;
     TooltipOverrideCount = 0;
+    TooltipPreviousWindow = NULL;
 
     PlatformImeData.InputPos = ImVec2(0.0f, 0.0f);
     PlatformImeDataPrev.InputPos = ImVec2(-1.0f, -1.0f); // Different to ensure initial submission
@@ -5152,6 +5153,7 @@ void ImGui::NewFrame()
     g.DragDropWithinSource = false;
     g.DragDropWithinTarget = false;
     g.DragDropHoldJustPressedId = 0;
+    g.TooltipPreviousWindow = NULL;
 
     // Close popups on focus lost (currently wip/opt-in)
     //if (g.IO.AppFocusLost)
@@ -7549,6 +7551,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
         // Clear hit test shape every frame
         window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0;
 
+        if (flags & ImGuiWindowFlags_Tooltip)
+            g.TooltipPreviousWindow = window;
+
         // Pressing CTRL+C while holding on a window copy its content to the clipboard
         // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope.
         // Maybe we can support CTRL+C on every element?
@@ -11504,7 +11509,8 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext
 {
     ImGuiContext& g = *GImGui;
 
-    if (g.DragDropWithinSource || g.DragDropWithinTarget)
+    const bool is_dragdrop_tooltip = g.DragDropWithinSource || g.DragDropWithinTarget;
+    if (is_dragdrop_tooltip)
     {
         // Drag and Drop tooltips are positioning differently than other tooltips:
         // - offset visibility to increase visibility around mouse.
@@ -11520,16 +11526,16 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext
         tooltip_flags |= ImGuiTooltipFlags_OverridePrevious;
     }
 
-    char window_name[16];
-    ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount);
-    if (tooltip_flags & ImGuiTooltipFlags_OverridePrevious)
-        if (ImGuiWindow* window = FindWindowByName(window_name))
-            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.
-                SetWindowHiddenAndSkipItemsForCurrentFrame(window);
-                ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount);
-            }
+    const char* window_name_template = is_dragdrop_tooltip ? "##Tooltip_DragDrop_%02d" : "##Tooltip_%02d";
+    char window_name[32];
+    ImFormatString(window_name, IM_ARRAYSIZE(window_name), window_name_template, g.TooltipOverrideCount);
+    if ((tooltip_flags & ImGuiTooltipFlags_OverridePrevious) && g.TooltipPreviousWindow != NULL && g.TooltipPreviousWindow->Active)
+    {
+        // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one.
+        //IMGUI_DEBUG_LOG("[tooltip] '%s' already active, using +1 for this frame\n", window_name);
+        SetWindowHiddenAndSkipItemsForCurrentFrame(g.TooltipPreviousWindow);
+        ImFormatString(window_name, IM_ARRAYSIZE(window_name), window_name_template, ++g.TooltipOverrideCount);
+    }
     ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize;
     Begin(window_name, NULL, flags | extra_window_flags);
     // 2023-03-09: Added bool return value to the API, but currently always returning true.
diff --git a/imgui.h b/imgui.h
index 59ea4baacf3a..0eebcafb3a14 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.3 WIP"
-#define IMGUI_VERSION_NUM   19123
+#define IMGUI_VERSION_NUM   19124
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index 113b05426cff..044ff18c23d2 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2283,6 +2283,7 @@ struct ImGuiContext
     short                   DisabledStackSize;
     short                   LockMarkEdited;
     short                   TooltipOverrideCount;
+    ImGuiWindow*            TooltipPreviousWindow;              // Window of last tooltip submitted during the frame
     ImVector          ClipboardHandlerData;               // If no custom clipboard handler is defined
     ImVector       MenusIdSubmittedThisFrame;          // A list of menu IDs that were rendered at least once
     ImGuiTypingSelectState  TypingSelectState;                  // State for GetTypingSelectRequest()

From 5109a77f6974bc993bb5cc2f69951f12ba7c59c2 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 2 Oct 2024 18:39:17 +0200
Subject: [PATCH 167/548] Tooltips: Tooltips triggered from touch inputs are
 positionned above the item. (#8036)

---
 docs/CHANGELOG.txt |  1 +
 imgui.cpp          | 31 +++++++++++++++++++++++++------
 2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 489d010d8fd8..34cba0c1a9fa 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -76,6 +76,7 @@ Other changes:
 - Tooltips, Drag and Drop: Stabilized name of drag and drop tooltip window so that
   transitioning from an item tooltip to a drag tooltip doesn't leak window auto-sizing
   info from one to the other. (#8036)
+- Tooltips: Tooltips triggered from touch inputs are positionned above the item. (#8036)
 - Backends: SDL3: Update for API changes: SDL_bool removal. SDL_INIT_TIMER removal.
 - Backends: WebGPU: Fixed DAWN api change using WGPUStringView in WGPUShaderSourceWGSL.
   (#8009, #8010) [@blitz-research]
diff --git a/imgui.cpp b/imgui.cpp
index eae120fd72b6..91250b23d411 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1136,7 +1136,9 @@ static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f;    // Reduc
 static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER    = 0.70f;    // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved.
 
 // Tooltip offset
-static const ImVec2 TOOLTIP_DEFAULT_OFFSET = ImVec2(16, 10);            // Multiplied by g.Style.MouseCursorScale
+static const ImVec2 TOOLTIP_DEFAULT_OFFSET_MOUSE = ImVec2(16, 10);      // Multiplied by g.Style.MouseCursorScale
+static const ImVec2 TOOLTIP_DEFAULT_OFFSET_TOUCH = ImVec2(0, -20);      // Multiplied by g.Style.MouseCursorScale
+static const ImVec2 TOOLTIP_DEFAULT_PIVOT_TOUCH = ImVec2(0.5f, 1.0f);   // Multiplied by g.Style.MouseCursorScale
 
 //-------------------------------------------------------------------------
 // [SECTION] FORWARD DECLARATIONS
@@ -11518,9 +11520,14 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext
         // We call SetNextWindowPos() to enforce position and disable clamping.
         // See FindBestWindowPosForPopup() for positionning logic of other tooltips (not drag and drop ones).
         //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding;
-        ImVec2 tooltip_pos = g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET * g.Style.MouseCursorScale;
+        const bool is_touchscreen = (g.IO.MouseSource == ImGuiMouseSource_TouchScreen);
         if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0)
-            SetNextWindowPos(tooltip_pos);
+        {
+            ImVec2 tooltip_pos = is_touchscreen ? (g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_TOUCH * g.Style.MouseCursorScale) : (g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_MOUSE * g.Style.MouseCursorScale);
+            ImVec2 tooltip_pivot = is_touchscreen ? TOOLTIP_DEFAULT_PIVOT_TOUCH : ImVec2(0.0f, 0.0f);
+            SetNextWindowPos(tooltip_pos, ImGuiCond_None, tooltip_pivot);
+        }
+
         SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f);
         //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This would be nice but e.g ColorButton with checkboard has issue with transparent colors :(
         tooltip_flags |= ImGuiTooltipFlags_OverridePrevious;
@@ -12126,18 +12133,30 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
     if (window->Flags & ImGuiWindowFlags_Tooltip)
     {
         // Position tooltip (always follows mouse + clamp within outer boundaries)
-        // Note that drag and drop tooltips are NOT using this path: BeginTooltipEx() manually sets their position.
-        // In theory we could handle both cases in same location, but requires a bit of shuffling as drag and drop tooltips are calling SetWindowPos() leading to 'window_pos_set_by_api' being set in Begin()
+        // FIXME:
+        // - Too many paths. One problem is that FindBestWindowPosForPopupEx() doesn't allow passing a suggested position (so touch screen path doesn't use it by default).
+        // - Drag and drop tooltips are not using this path either: BeginTooltipEx() manually sets their position.
+        // - Require some tidying up. In theory we could handle both cases in same location, but requires a bit of shuffling
+        //   as drag and drop tooltips are calling SetNextWindowPos() leading to 'window_pos_set_by_api' being set in Begin().
         IM_ASSERT(g.CurrentWindow == window);
         const float scale = g.Style.MouseCursorScale;
         const ImVec2 ref_pos = NavCalcPreferredRefPos();
-        const ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET * scale;
+
+        if (g.IO.MouseSource == ImGuiMouseSource_TouchScreen)
+        {
+            ImVec2 tooltip_pos = g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_TOUCH * scale - (TOOLTIP_DEFAULT_PIVOT_TOUCH * window->Size);
+            if (r_outer.Contains(ImRect(tooltip_pos, tooltip_pos + window->Size)))
+                return tooltip_pos;
+        }
+
+        ImVec2 tooltip_pos = g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_MOUSE * scale;
         ImRect r_avoid;
         if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos))
             r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
         else
             r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
         //GetForegroundDrawList()->AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255, 0, 255, 255));
+
         return FindBestWindowPosForPopupEx(tooltip_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip);
     }
     IM_ASSERT(0);

From b3c87475a5a93a04d453d6b7144427d9d8ea6b5b Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 3 Oct 2024 16:17:45 +0200
Subject: [PATCH 168/548] Drags, Slider: added ImGuiSliderFlags_ClampOnInput,
 ImGuiSliderFlags_ClampZeroRange. (#7968, #3361, #76)

---
 docs/CHANGELOG.txt | 14 ++++++++++++++
 imgui.cpp          |  3 +++
 imgui.h            | 27 +++++++++++++--------------
 imgui_demo.cpp     |  7 ++++++-
 imgui_internal.h   |  1 +
 imgui_widgets.cpp  | 28 +++++++++++++++++++++-------
 6 files changed, 58 insertions(+), 22 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 34cba0c1a9fa..20142608c194 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -41,6 +41,13 @@ HOW TO UPDATE?
 
 Breaking changes:
 
+- Drags: treat v_min==v_max as a valid clamping range when != 0.0f. Zero is still a special
+  value due to legacy reasons, unless using ImGuiSliderFlags_ClampZeroRange. (#7968, #3361, #76)
+- Drags: extended behavior of ImGuiSliderFlags_AlwaysClamp to include _ClampZeroRange.
+  It considers v_min==v_max==0.0f as a valid clamping range (aka edits not allowed).
+  Although unlikely, it you wish to only clamp on text input but want v_min==v_max==0.0f
+  to mean unclamped drags, you can use _ClampOnInput instead of _AlwaysClamp. (#7968, #3361, #76)
+
 Other changes:
 
 - Error Handling: Enabled/improved error recovery systems. (#1651, #5654)
@@ -71,6 +78,13 @@ Other changes:
 - Scrollbar: Shift+Click scroll to clicked location (pre-1.90.8 default). (#8002, #7328)
 - Scrollbar: added io.ConfigScrollbarScrollByPage setting (default to true). (#8002, #7328)
   Set io.ConfigScrollbarScrollByPage=false to enforce always scrolling to clicked location.
+- Drags: ImGuiSliderFlags_AlwaysClamp split into two distinct flags: (#7968, #3361, #76)
+  - ImGuiSliderFlags_AlwaysClamp = ImGuiSliderFlags_ClampOnInput + ImGuiSliderFlags_ClampZeroRange.
+  - Previously _AlwaysClamp only did the equivalent of _ClampOnInput.
+  - Added ImGuiSliderFlags_ClampOnInput which is now a subset of AlwaysClamp.
+    (note that it was the old name of AlwaysClamp, but we are reintroducing that name).
+  - Added ImGuiSliderFlags_ClampZeroRange to enforce clamping even when v_min==v_max==0.0f
+    in drag functions. Sliders are not affected.
 - Tooltips, Drag and Drop: Fixed an issue where the fallback drag and drop payload tooltip
   appeared during drag and drop release.
 - Tooltips, Drag and Drop: Stabilized name of drag and drop tooltip window so that
diff --git a/imgui.cpp b/imgui.cpp
index 91250b23d411..2ae59486d55a 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -430,6 +430,9 @@ 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.
 
+ - 2024/10/03 (1.91.3) - drags: treat v_min==v_max as a valid clamping range when != 0.0f. Zero is a still special value due to legacy reasons, unless using ImGuiSliderFlags_ClampZeroRange. (#7968, #3361, #76)
+                       - drags: extended behavior of ImGuiSliderFlags_AlwaysClamp to include _ClampZeroRange. It considers v_min==v_max==0.0f as a valid clamping range (aka edits not allowed).
+                         although unlikely, it you wish to only clamp on text input but want v_min==v_max==0.0f to mean unclamped drags, you can use _ClampOnInput instead of _AlwaysClamp. (#7968, #3361, #76)
  - 2024/08/23 (1.91.1) - renamed ImGuiChildFlags_Border to ImGuiChildFlags_Borders for consistency. kept inline redirection flag.
  - 2024/08/22 (1.91.1) - moved some functions from ImGuiIO to ImGuiPlatformIO structure:
                             - io.GetClipboardTextFn         -> platform_io.Platform_GetClipboardTextFn + changed 'void* user_data' to 'ImGuiContext* ctx'. Pull your user data from platform_io.ClipboardUserData.
diff --git a/imgui.h b/imgui.h
index 0eebcafb3a14..5c362a6a2aa0 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.3 WIP"
-#define IMGUI_VERSION_NUM   19124
+#define IMGUI_VERSION_NUM   19125
 #define IMGUI_HAS_TABLE
 
 /*
@@ -1788,19 +1788,18 @@ enum ImGuiColorEditFlags_
 
 // Flags for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
 // We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them.
-// (Those are per-item flags. There are shared flags in ImGuiIO: io.ConfigDragClickToInputText)
+// (Those are per-item flags. There is shared behavior flag too: ImGuiIO: io.ConfigDragClickToInputText)
 enum ImGuiSliderFlags_
 {
-    ImGuiSliderFlags_None                   = 0,
-    ImGuiSliderFlags_AlwaysClamp            = 1 << 4,       // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.
-    ImGuiSliderFlags_Logarithmic            = 1 << 5,       // Make the widget logarithmic (linear otherwise). Consider using ImGuiSliderFlags_NoRoundToFormat with this if using a format-string with small amount of digits.
-    ImGuiSliderFlags_NoRoundToFormat        = 1 << 6,       // Disable rounding underlying value to match precision of the display format string (e.g. %.3f values are rounded to those 3 digits).
-    ImGuiSliderFlags_NoInput                = 1 << 7,       // Disable CTRL+Click or Enter key allowing to input text directly into the widget.
-    ImGuiSliderFlags_WrapAround             = 1 << 8,       // Enable wrapping around from max to min and from min to max (only supported by DragXXX() functions for now.
-    ImGuiSliderFlags_InvalidMask_           = 0x7000000F,   // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed.
-
-    // Obsolete names
-    //ImGuiSliderFlags_ClampOnInput = ImGuiSliderFlags_AlwaysClamp, // [renamed in 1.79]
+    ImGuiSliderFlags_None               = 0,
+    ImGuiSliderFlags_Logarithmic        = 1 << 5,       // Make the widget logarithmic (linear otherwise). Consider using ImGuiSliderFlags_NoRoundToFormat with this if using a format-string with small amount of digits.
+    ImGuiSliderFlags_NoRoundToFormat    = 1 << 6,       // Disable rounding underlying value to match precision of the display format string (e.g. %.3f values are rounded to those 3 digits).
+    ImGuiSliderFlags_NoInput            = 1 << 7,       // Disable CTRL+Click or Enter key allowing to input text directly into the widget.
+    ImGuiSliderFlags_WrapAround         = 1 << 8,       // Enable wrapping around from max to min and from min to max. Only supported by DragXXX() functions for now.
+    ImGuiSliderFlags_ClampOnInput       = 1 << 9,       // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.
+    ImGuiSliderFlags_ClampZeroRange     = 1 << 10,      // Clamp even if min==max==0.0f. Otherwise due to legacy reason DragXXX functions don't clamp with those values. When your clamping limits are dynamic you almost always want to use it.
+    ImGuiSliderFlags_AlwaysClamp        = ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_ClampZeroRange,
+    ImGuiSliderFlags_InvalidMask_       = 0x7000000F,   // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed.
 };
 
 // Identify a mouse button.
@@ -3170,8 +3169,8 @@ struct ImDrawList
     //inline  void  AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024)
     //inline  void  AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0) { AddEllipseFilled(center, ImVec2(radius_x, radius_y), col, rot, num_segments); }                        // OBSOLETED in 1.90.5 (Mar 2024)
     //inline  void  PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments = 0) { PathEllipticalArcTo(center, ImVec2(radius_x, radius_y), rot, a_min, a_max, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024)
-    //inline  void  AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); } // OBSOLETED in 1.80 (Jan 2021)
-    //inline  void  PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); } // OBSOLETED in 1.80 (Jan 2021)
+    //inline  void  AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); }                         // OBSOLETED in 1.80 (Jan 2021)
+    //inline  void  PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); }                                                                                // OBSOLETED in 1.80 (Jan 2021)
 
     // [Internal helpers]
     IMGUI_API void  _ResetForNewFrame();
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index feaee3be9eb2..dc2f4d39b7f1 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -2265,7 +2265,10 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
         // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same!
         static ImGuiSliderFlags flags = ImGuiSliderFlags_None;
         ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", &flags, ImGuiSliderFlags_AlwaysClamp);
-        ImGui::SameLine(); HelpMarker("Always clamp value to min/max bounds (if any) when input manually with CTRL+Click.");
+        ImGui::CheckboxFlags("ImGuiSliderFlags_ClampOnInput", &flags, ImGuiSliderFlags_ClampOnInput);
+        ImGui::SameLine(); HelpMarker("Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.");
+        ImGui::CheckboxFlags("ImGuiSliderFlags_ClampZeroRange", &flags, ImGuiSliderFlags_ClampZeroRange);
+        ImGui::SameLine(); HelpMarker("Clamp even if min==max==0.0f. Otherwise DragXXX functions don't clamp.");
         ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", &flags, ImGuiSliderFlags_Logarithmic);
         ImGui::SameLine(); HelpMarker("Enable logarithmic editing (more precision for small values).");
         ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", &flags, ImGuiSliderFlags_NoRoundToFormat);
@@ -2283,6 +2286,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
         ImGui::DragFloat("DragFloat (0 -> +inf)", &drag_f, 0.005f, 0.0f, FLT_MAX, "%.3f", flags);
         ImGui::DragFloat("DragFloat (-inf -> 1)", &drag_f, 0.005f, -FLT_MAX, 1.0f, "%.3f", flags);
         ImGui::DragFloat("DragFloat (-inf -> +inf)", &drag_f, 0.005f, -FLT_MAX, +FLT_MAX, "%.3f", flags);
+        //ImGui::DragFloat("DragFloat (0 -> 0)", &drag_f, 0.005f, 0.0f, 0.0f, "%.3f", flags);           // To test ClampZeroRange
+        //ImGui::DragFloat("DragFloat (100 -> 100)", &drag_f, 0.005f, 100.0f, 100.0f, "%.3f", flags);
         ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags);
 
         // Sliders
diff --git a/imgui_internal.h b/imgui_internal.h
index 044ff18c23d2..f8b4d9d21ba9 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -3402,6 +3402,7 @@ namespace ImGui
     IMGUI_API bool          DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format, void* p_data_when_empty = NULL);
     IMGUI_API int           DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2);
     IMGUI_API bool          DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max);
+    IMGUI_API bool          DataTypeIsZero(ImGuiDataType data_type, const void* p_data);
 
     // InputText
     IMGUI_API bool          InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 9192dbcba8bc..891fcad23a1a 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -2351,6 +2351,12 @@ bool ImGui::DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_m
     return false;
 }
 
+bool ImGui::DataTypeIsZero(ImGuiDataType data_type, const void* p_data)
+{
+    ImGuiContext& g = *GImGui;
+    return DataTypeCompare(data_type, p_data, &g.DataTypeZeroValue) == 0;
+}
+
 static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
 {
     static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f };
@@ -2409,7 +2415,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
 {
     ImGuiContext& g = *GImGui;
     const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
-    const bool is_bounded = (v_min < v_max);
+    const bool is_bounded = (v_min < v_max) || ((v_min == v_max) && (v_min != 0.0f || (flags & ImGuiSliderFlags_ClampZeroRange)));
     const bool is_wrapped = is_bounded && (flags & ImGuiSliderFlags_WrapAround);
     const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0;
     const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
@@ -2632,9 +2638,17 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
 
     if (temp_input_is_active)
     {
-        // Only clamp CTRL+Click input when ImGuiSliderFlags_AlwaysClamp is set
-        const bool is_clamp_input = (flags & ImGuiSliderFlags_AlwaysClamp) != 0 && (p_min == NULL || p_max == NULL || DataTypeCompare(data_type, p_min, p_max) < 0);
-        return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL);
+        // Only clamp CTRL+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
+        bool clamp_enabled = false;
+        if ((flags & ImGuiSliderFlags_ClampOnInput) && (p_min != NULL || p_max != NULL))
+        {
+            const int clamp_range_dir = (p_min != NULL && p_max != NULL) ? DataTypeCompare(data_type, p_min, p_max) : 0; // -1 when *p_min < *p_max, == 0 when *p_min == *p_max
+            if (p_min == NULL || p_max == NULL || clamp_range_dir < 0)
+                clamp_enabled = true;
+            else if ((p_min != NULL && p_max != NULL) && clamp_range_dir == 0)
+                clamp_enabled = DataTypeIsZero(data_type, p_min) ? ((flags & ImGuiSliderFlags_ClampZeroRange) != 0) : true;
+        }
+        return TempInputScalar(frame_bb, id, label, data_type, p_data, format, clamp_enabled ? p_min : NULL, clamp_enabled ? p_max : NULL);
     }
 
     // Draw frame
@@ -3214,9 +3228,9 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
 
     if (temp_input_is_active)
     {
-        // Only clamp CTRL+Click input when ImGuiSliderFlags_AlwaysClamp is set
-        const bool is_clamp_input = (flags & ImGuiSliderFlags_AlwaysClamp) != 0;
-        return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL);
+        // Only clamp CTRL+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
+        const bool clamp_enabled = (flags & ImGuiSliderFlags_ClampOnInput) != 0;
+        return TempInputScalar(frame_bb, id, label, data_type, p_data, format, clamp_enabled ? p_min : NULL, clamp_enabled ? p_max : NULL);
     }
 
     // Draw frame

From 3d399bcecabc5c260073e700cbd674cc36b6e6ab Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 3 Oct 2024 16:49:38 +0200
Subject: [PATCH 169/548] Docs: amend docs to explain case of using multiple
 overlayed ButtonBehavior(). (#8030, #7961, #7669)

---
 docs/CHANGELOG.txt |  8 ++++++++
 imgui.cpp          |  7 +++++--
 imgui_widgets.cpp  | 11 ++++++++---
 3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 20142608c194..d800975c4a8f 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -101,6 +101,14 @@ Other changes:
 
 Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.2
 
+Breaking changes:
+
+ - Internals: using multiple overlayed ButtonBehavior() with same ID will now have the
+   io.ConfigDebugHighlightIdConflicts=true feature emit a warning. (#8030)
+   It was one of the rare case where using same ID is legal. Workarounds:
+   - use single ButtonBehavior() call with multiple _MouseButton flags
+   - or surround the calls with PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()
+
 Other changes:
 
 - Added io.ConfigDebugHighlightIdConflicts debug feature! (#7961, #7669)
diff --git a/imgui.cpp b/imgui.cpp
index 2ae59486d55a..9faec405ca4e 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -433,6 +433,8 @@ CODE
  - 2024/10/03 (1.91.3) - drags: treat v_min==v_max as a valid clamping range when != 0.0f. Zero is a still special value due to legacy reasons, unless using ImGuiSliderFlags_ClampZeroRange. (#7968, #3361, #76)
                        - drags: extended behavior of ImGuiSliderFlags_AlwaysClamp to include _ClampZeroRange. It considers v_min==v_max==0.0f as a valid clamping range (aka edits not allowed).
                          although unlikely, it you wish to only clamp on text input but want v_min==v_max==0.0f to mean unclamped drags, you can use _ClampOnInput instead of _AlwaysClamp. (#7968, #3361, #76)
+ - 2024/09/10 (1.91.2) - internals: using multiple overlayed ButtonBehavior() with same ID will now have io.ConfigDebugHighlightIdConflicts=true feature emit a warning. (#8030)
+                         it was one of the rare case where using same ID is legal. workarounds: (1) use single ButtonBehavior() call with multiple _MouseButton flags, or (2) surround the calls with PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()
  - 2024/08/23 (1.91.1) - renamed ImGuiChildFlags_Border to ImGuiChildFlags_Borders for consistency. kept inline redirection flag.
  - 2024/08/22 (1.91.1) - moved some functions from ImGuiIO to ImGuiPlatformIO structure:
                             - io.GetClipboardTextFn         -> platform_io.Platform_GetClipboardTextFn + changed 'void* user_data' to 'ImGuiContext* ctx'. Pull your user data from platform_io.ClipboardUserData.
@@ -10656,9 +10658,10 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
         Text("Programmer error: %d visible items with conflicting ID!", g.DebugDrawIdConflictsCount);
         BulletText("Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
         BulletText("Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
+        //BulletText("Code intending to use duplicate ID may use e.g. PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()"); // Not making this too visible for fear of it being abused.
         BulletText("Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
         Separator();
-        Text("(Hold CTRL and: use");
+        Text("(Hold CTRL to: use");
         SameLine();
         if (SmallButton("Item Picker"))
             DebugStartItemPicker();
@@ -10673,7 +10676,7 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
     if (g.ErrorCountCurrentFrame > 0 && BeginErrorTooltip()) // Amend at end of frame
     {
         Separator();
-        Text("(Hold CTRL and:");
+        Text("(Hold CTRL to:");
         SameLine();
         if (SmallButton("Enable Asserts"))
             g.IO.ConfigErrorRecoveryEnableAssert = true;
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 891fcad23a1a..1e24b4ebcef7 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -482,9 +482,14 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
 //   Frame N + RepeatDelay + RepeatRate*N   true                     true              -                   true
 //-------------------------------------------------------------------------------------------------------------------------------------------------
 
-// FIXME: For refactor we could output flags, incl mouse hovered vs nav keyboard vs nav triggered etc.
-// And better standardize how widgets use 'GetColor32((held && hovered) ? ... : hovered ? ...)' vs 'GetColor32(held ? ... : hovered ? ...);'
-// For mouse feedback we typically prefer the 'held && hovered' test, but for nav feedback not always. Outputting hovered=true on Activation may be misleading.
+// - FIXME: For refactor we could output flags, incl mouse hovered vs nav keyboard vs nav triggered etc.
+//   And better standardize how widgets use 'GetColor32((held && hovered) ? ... : hovered ? ...)' vs 'GetColor32(held ? ... : hovered ? ...);'
+//   For mouse feedback we typically prefer the 'held && hovered' test, but for nav feedback not always. Outputting hovered=true on Activation may be misleading.
+// - Since v1.91.2 (Sept 2024) we included io.ConfigDebugHighlightIdConflicts feature.
+//   One idiom which was previously valid which will now emit a warning is when using multiple overlayed ButtonBehavior()
+//   with same ID and different MouseButton (see #8030). You can fix it by:
+//       (1) switching to use a single ButtonBehavior() with multiple _MouseButton flags.
+//    or (2) surrounding those calls with PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()
 bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)
 {
     ImGuiContext& g = *GImGui;

From 8db126188df82282c193f894c5e5ba390869c836 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 3 Oct 2024 17:32:05 +0200
Subject: [PATCH 170/548] Fixed static analyser warning. Amend b3c8747

---
 imgui_widgets.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 1e24b4ebcef7..8f16f6ec0064 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -2650,7 +2650,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
             const int clamp_range_dir = (p_min != NULL && p_max != NULL) ? DataTypeCompare(data_type, p_min, p_max) : 0; // -1 when *p_min < *p_max, == 0 when *p_min == *p_max
             if (p_min == NULL || p_max == NULL || clamp_range_dir < 0)
                 clamp_enabled = true;
-            else if ((p_min != NULL && p_max != NULL) && clamp_range_dir == 0)
+            else if (clamp_range_dir == 0)
                 clamp_enabled = DataTypeIsZero(data_type, p_min) ? ((flags & ImGuiSliderFlags_ClampZeroRange) != 0) : true;
         }
         return TempInputScalar(frame_bb, id, label, data_type, p_data, format, clamp_enabled ? p_min : NULL, clamp_enabled ? p_max : NULL);

From cb16568fca5297512ff6a8f3b877f461c4323fbe Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 4 Oct 2024 14:06:33 +0200
Subject: [PATCH 171/548] Version 1.91.3

---
 docs/CHANGELOG.txt | 10 ++++++----
 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, 15 insertions(+), 13 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index d800975c4a8f..8c91d13004b2 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -36,9 +36,11 @@ HOW TO UPDATE?
 - Please report any issue!
 
 -----------------------------------------------------------------------
- VERSION 1.91.3 WIP (In Progress)
+ VERSION 1.91.3 (Released 2024-10-04)
 -----------------------------------------------------------------------
 
+Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.3
+
 Breaking changes:
 
 - Drags: treat v_min==v_max as a valid clamping range when != 0.0f. Zero is still a special
@@ -61,7 +63,7 @@ Other changes:
   - Functions that support error recovery are using IM_ASSERT_USER_ERROR() instead of IM_ASSERT().
   - By design, we do not allow error recovery to be 100% silent. One of the options needs to be enabled!
   - Possible usage: facilitate recovery from errors triggered from a scripting language or
-    after specific exceptions handlers. Surface errors to programmers in less agressive ways.
+    after specific exceptions handlers. Surface errors to programmers in less aggressive ways.
   - Always ensure that on programmers seats you have at minimum Asserts or Tooltips enabled
     when making direct imgui API calls! Otherwise it would severely hinder your ability to
     catch and correct mistakes!
@@ -78,7 +80,7 @@ Other changes:
 - Scrollbar: Shift+Click scroll to clicked location (pre-1.90.8 default). (#8002, #7328)
 - Scrollbar: added io.ConfigScrollbarScrollByPage setting (default to true). (#8002, #7328)
   Set io.ConfigScrollbarScrollByPage=false to enforce always scrolling to clicked location.
-- Drags: ImGuiSliderFlags_AlwaysClamp split into two distinct flags: (#7968, #3361, #76)
+- Drags: split ImGuiSliderFlags_AlwaysClamp into two distinct flags: (#7968, #3361, #76)
   - ImGuiSliderFlags_AlwaysClamp = ImGuiSliderFlags_ClampOnInput + ImGuiSliderFlags_ClampZeroRange.
   - Previously _AlwaysClamp only did the equivalent of _ClampOnInput.
   - Added ImGuiSliderFlags_ClampOnInput which is now a subset of AlwaysClamp.
@@ -90,7 +92,7 @@ Other changes:
 - Tooltips, Drag and Drop: Stabilized name of drag and drop tooltip window so that
   transitioning from an item tooltip to a drag tooltip doesn't leak window auto-sizing
   info from one to the other. (#8036)
-- Tooltips: Tooltips triggered from touch inputs are positionned above the item. (#8036)
+- Tooltips: Tooltips triggered from touch inputs are positioned above the item. (#8036)
 - Backends: SDL3: Update for API changes: SDL_bool removal. SDL_INIT_TIMER removal.
 - Backends: WebGPU: Fixed DAWN api change using WGPUStringView in WGPUShaderSourceWGSL.
   (#8009, #8010) [@blitz-research]
diff --git a/imgui.cpp b/imgui.cpp
index 9faec405ca4e..3bbaf018f182 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3 WIP
+// dear imgui, v1.91.3
 // (main code and documentation)
 
 // Help:
diff --git a/imgui.h b/imgui.h
index 5c362a6a2aa0..77ca8e04f7f0 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3 WIP
+// dear imgui, v1.91.3
 // (headers)
 
 // Help:
@@ -28,8 +28,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.3 WIP"
-#define IMGUI_VERSION_NUM   19125
+#define IMGUI_VERSION       "1.91.3"
+#define IMGUI_VERSION_NUM   19130
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index dc2f4d39b7f1..8df1755fb94b 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3 WIP
+// dear imgui, v1.91.3
 // (demo code)
 
 // Help:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index b7a00285feba..8084e53c3006 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3 WIP
+// dear imgui, v1.91.3
 // (drawing and font code)
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index f8b4d9d21ba9..9f47ecd21a0e 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3 WIP
+// dear imgui, v1.91.3
 // (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 4a6fbed7cb25..64126f41da46 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3 WIP
+// dear imgui, v1.91.3
 // (tables and columns code)
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 8f16f6ec0064..322c0846c9b0 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3 WIP
+// dear imgui, v1.91.3
 // (widgets code)
 
 /*

From 1dde20ff4a1ae645bda31f3ee983733994d2f6fc Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 7 Oct 2024 17:39:28 +0200
Subject: [PATCH 172/548] Version 1.91.4 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 8c91d13004b2..b5f526809774 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.4 WIP
+-----------------------------------------------------------------------
+
+Breaking changes:
+
+Other changes:
+
+
 -----------------------------------------------------------------------
  VERSION 1.91.3 (Released 2024-10-04)
 -----------------------------------------------------------------------
diff --git a/imgui.cpp b/imgui.cpp
index 3bbaf018f182..2d7edc43e390 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3
+// dear imgui, v1.91.4 WIP
 // (main code and documentation)
 
 // Help:
diff --git a/imgui.h b/imgui.h
index 77ca8e04f7f0..49ad70cee4f5 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3
+// dear imgui, v1.91.4 WIP
 // (headers)
 
 // Help:
@@ -28,8 +28,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.3"
-#define IMGUI_VERSION_NUM   19130
+#define IMGUI_VERSION       "1.91.4 WIP"
+#define IMGUI_VERSION_NUM   19131
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 8df1755fb94b..a85e28e54ff9 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3
+// dear imgui, v1.91.4 WIP
 // (demo code)
 
 // Help:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 8084e53c3006..b69bc789f88f 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3
+// dear imgui, v1.91.4 WIP
 // (drawing and font code)
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index 9f47ecd21a0e..05378c3d9b9b 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3
+// dear imgui, v1.91.4 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 64126f41da46..491566d7af9e 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3
+// dear imgui, v1.91.4 WIP
 // (tables and columns code)
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 322c0846c9b0..baaf4f4e7e5f 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.3
+// dear imgui, v1.91.4 WIP
 // (widgets code)
 
 /*

From 9bd5d8a24051a370bc8331f85e71d0b78c73687d Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 7 Oct 2024 17:52:57 +0200
Subject: [PATCH 173/548] Backends: misc renaming of locals. Use 'draw_list'
 instead of 'cmd_list'. Avoid using 'ctx'.

This is likely to trigger merging issues. If it does, best to always get "theirs" and rename in there.
---
 backends/imgui_impl_allegro5.cpp     |  28 ++---
 backends/imgui_impl_dx10.cpp         | 126 +++++++++++------------
 backends/imgui_impl_dx11.cpp         | 140 ++++++++++++-------------
 backends/imgui_impl_dx12.cpp         |  56 +++++-----
 backends/imgui_impl_dx12.h           |   3 +-
 backends/imgui_impl_dx9.cpp          | 148 ++++++++++++++-------------
 backends/imgui_impl_metal.mm         |  16 +--
 backends/imgui_impl_opengl2.cpp      |  12 +--
 backends/imgui_impl_opengl3.cpp      |  20 ++--
 backends/imgui_impl_sdlrenderer2.cpp |  14 +--
 backends/imgui_impl_sdlrenderer3.cpp |  14 +--
 backends/imgui_impl_vulkan.cpp       |  22 ++--
 backends/imgui_impl_wgpu.cpp         |  22 ++--
 13 files changed, 314 insertions(+), 307 deletions(-)

diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp
index bf1019e2c952..9c25716231c6 100644
--- a/backends/imgui_impl_allegro5.cpp
+++ b/backends/imgui_impl_allegro5.cpp
@@ -149,14 +149,14 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
     // Render command lists
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
 
         ImVector& vertices = bd->BufVertices;
 #if ALLEGRO_HAS_DRAW_INDEXED_PRIM
-        vertices.resize(cmd_list->VtxBuffer.Size);
-        for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
+        vertices.resize(draw_list->VtxBuffer.Size);
+        for (int i = 0; i < draw_list->VtxBuffer.Size; i++)
         {
-            const ImDrawVert* src_v = &cmd_list->VtxBuffer[i];
+            const ImDrawVert* src_v = &draw_list->VtxBuffer[i];
             ImDrawVertAllegro* dst_v = &vertices[i];
             DRAW_VERT_IMGUI_TO_ALLEGRO(dst_v, src_v);
         }
@@ -166,21 +166,21 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
             // FIXME-OPT: Allegro doesn't support 16-bit indices.
             // You can '#define ImDrawIdx int' in imconfig.h to request Dear ImGui to output 32-bit indices.
             // Otherwise, we convert them from 16-bit to 32-bit at runtime here, which works perfectly but is a little wasteful.
-            bd->BufIndices.resize(cmd_list->IdxBuffer.Size);
-            for (int i = 0; i < cmd_list->IdxBuffer.Size; ++i)
-                bd->BufIndices[i] = (int)cmd_list->IdxBuffer.Data[i];
+            bd->BufIndices.resize(draw_list->IdxBuffer.Size);
+            for (int i = 0; i < draw_list->IdxBuffer.Size; ++i)
+                bd->BufIndices[i] = (int)draw_list->IdxBuffer.Data[i];
             indices = bd->BufIndices.Data;
         }
         else if (sizeof(ImDrawIdx) == 4)
         {
-            indices = (const int*)cmd_list->IdxBuffer.Data;
+            indices = (const int*)draw_list->IdxBuffer.Data;
         }
 #else
         // Allegro's implementation of al_draw_indexed_prim() for DX9 was broken until 5.2.5. Unindex buffers ourselves while converting vertex format.
-        vertices.resize(cmd_list->IdxBuffer.Size);
-        for (int i = 0; i < cmd_list->IdxBuffer.Size; i++)
+        vertices.resize(draw_list->IdxBuffer.Size);
+        for (int i = 0; i < draw_list->IdxBuffer.Size; i++)
         {
-            const ImDrawVert* src_v = &cmd_list->VtxBuffer[cmd_list->IdxBuffer[i]];
+            const ImDrawVert* src_v = &draw_list->VtxBuffer[draw_list->IdxBuffer[i]];
             ImDrawVertAllegro* dst_v = &vertices[i];
             DRAW_VERT_IMGUI_TO_ALLEGRO(dst_v, src_v);
         }
@@ -188,9 +188,9 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
 
         // Render command lists
         ImVec2 clip_off = draw_data->DisplayPos;
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback)
             {
                 // User callback, registered via ImDrawList::AddCallback()
@@ -198,7 +198,7 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
                     ImGui_ImplAllegro5_SetupRenderState(draw_data);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp
index 9691b49fdff4..96932c3aff23 100644
--- a/backends/imgui_impl_dx10.cpp
+++ b/backends/imgui_impl_dx10.cpp
@@ -80,7 +80,7 @@ static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData()
 }
 
 // Functions
-static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx)
+static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* device)
 {
     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
 
@@ -92,26 +92,26 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
     vp.MinDepth = 0.0f;
     vp.MaxDepth = 1.0f;
     vp.TopLeftX = vp.TopLeftY = 0;
-    ctx->RSSetViewports(1, &vp);
+    device->RSSetViewports(1, &vp);
 
     // Bind shader and vertex buffers
     unsigned int stride = sizeof(ImDrawVert);
     unsigned int offset = 0;
-    ctx->IASetInputLayout(bd->pInputLayout);
-    ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
-    ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
-    ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
-    ctx->VSSetShader(bd->pVertexShader);
-    ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
-    ctx->PSSetShader(bd->pPixelShader);
-    ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
-    ctx->GSSetShader(nullptr);
+    device->IASetInputLayout(bd->pInputLayout);
+    device->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
+    device->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
+    device->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+    device->VSSetShader(bd->pVertexShader);
+    device->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
+    device->PSSetShader(bd->pPixelShader);
+    device->PSSetSamplers(0, 1, &bd->pFontSampler);
+    device->GSSetShader(nullptr);
 
     // Setup render state
     const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
-    ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
-    ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
-    ctx->RSSetState(bd->pRasterizerState);
+    device->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
+    device->OMSetDepthStencilState(bd->pDepthStencilState, 0);
+    device->RSSetState(bd->pRasterizerState);
 }
 
 // Render function
@@ -122,7 +122,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
         return;
 
     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
-    ID3D10Device* ctx = bd->pd3dDevice;
+    ID3D10Device* device = bd->pd3dDevice;
 
     // Create and grow vertex/index buffers if needed
     if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
@@ -136,7 +136,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
         desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
         desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
         desc.MiscFlags = 0;
-        if (ctx->CreateBuffer(&desc, nullptr, &bd->pVB) < 0)
+        if (device->CreateBuffer(&desc, nullptr, &bd->pVB) < 0)
             return;
     }
 
@@ -150,7 +150,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
         desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
         desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
         desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
-        if (ctx->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
+        if (device->CreateBuffer(&desc, nullptr, &bd->pIB) < 0)
             return;
     }
 
@@ -161,11 +161,11 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
     bd->pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
-        memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
-        vtx_dst += cmd_list->VtxBuffer.Size;
-        idx_dst += cmd_list->IdxBuffer.Size;
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
+        memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+        vtx_dst += draw_list->VtxBuffer.Size;
+        idx_dst += draw_list->IdxBuffer.Size;
     }
     bd->pVB->Unmap();
     bd->pIB->Unmap();
@@ -217,24 +217,24 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
     };
     BACKUP_DX10_STATE old = {};
     old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
-    ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
-    ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
-    ctx->RSGetState(&old.RS);
-    ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
-    ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
-    ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
-    ctx->PSGetSamplers(0, 1, &old.PSSampler);
-    ctx->PSGetShader(&old.PS);
-    ctx->VSGetShader(&old.VS);
-    ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
-    ctx->GSGetShader(&old.GS);
-    ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
-    ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
-    ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
-    ctx->IAGetInputLayout(&old.InputLayout);
+    device->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
+    device->RSGetViewports(&old.ViewportsCount, old.Viewports);
+    device->RSGetState(&old.RS);
+    device->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
+    device->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
+    device->PSGetShaderResources(0, 1, &old.PSShaderResource);
+    device->PSGetSamplers(0, 1, &old.PSSampler);
+    device->PSGetShader(&old.PS);
+    device->VSGetShader(&old.VS);
+    device->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
+    device->GSGetShader(&old.GS);
+    device->IAGetPrimitiveTopology(&old.PrimitiveTopology);
+    device->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
+    device->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
+    device->IAGetInputLayout(&old.InputLayout);
 
     // Setup desired DX state
-    ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
+    ImGui_ImplDX10_SetupRenderState(draw_data, device);
 
     // Render command lists
     // (Because we merged all buffers into a single one, we maintain our own offset into them)
@@ -243,18 +243,18 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
     ImVec2 clip_off = draw_data->DisplayPos;
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback)
             {
                 // User callback, registered via ImDrawList::AddCallback()
                 // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
-                    ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
+                    ImGui_ImplDX10_SetupRenderState(draw_data, device);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
@@ -266,34 +266,34 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
 
                 // Apply scissor/clipping rectangle
                 const D3D10_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
-                ctx->RSSetScissorRects(1, &r);
+                device->RSSetScissorRects(1, &r);
 
                 // Bind texture, Draw
                 ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->GetTexID();
-                ctx->PSSetShaderResources(0, 1, &texture_srv);
-                ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
+                device->PSSetShaderResources(0, 1, &texture_srv);
+                device->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
             }
         }
-        global_idx_offset += cmd_list->IdxBuffer.Size;
-        global_vtx_offset += cmd_list->VtxBuffer.Size;
+        global_idx_offset += draw_list->IdxBuffer.Size;
+        global_vtx_offset += draw_list->VtxBuffer.Size;
     }
 
     // Restore modified DX state
-    ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
-    ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
-    ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
-    ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
-    ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
-    ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
-    ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
-    ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release();
-    ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release();
-    ctx->GSSetShader(old.GS); if (old.GS) old.GS->Release();
-    ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
-    ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
-    ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
-    ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
-    ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
+    device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
+    device->RSSetViewports(old.ViewportsCount, old.Viewports);
+    device->RSSetState(old.RS); if (old.RS) old.RS->Release();
+    device->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
+    device->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
+    device->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
+    device->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
+    device->PSSetShader(old.PS); if (old.PS) old.PS->Release();
+    device->VSSetShader(old.VS); if (old.VS) old.VS->Release();
+    device->GSSetShader(old.GS); if (old.GS) old.GS->Release();
+    device->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
+    device->IASetPrimitiveTopology(old.PrimitiveTopology);
+    device->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
+    device->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
+    device->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
 }
 
 static void ImGui_ImplDX10_CreateFontsTexture()
diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp
index 167bda67380d..f656bbc55fbe 100644
--- a/backends/imgui_impl_dx11.cpp
+++ b/backends/imgui_impl_dx11.cpp
@@ -81,7 +81,7 @@ static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
 }
 
 // Functions
-static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
+static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* device_ctx)
 {
     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
 
@@ -93,29 +93,29 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC
     vp.MinDepth = 0.0f;
     vp.MaxDepth = 1.0f;
     vp.TopLeftX = vp.TopLeftY = 0;
-    ctx->RSSetViewports(1, &vp);
+    device_ctx->RSSetViewports(1, &vp);
 
     // Setup shader and vertex buffers
     unsigned int stride = sizeof(ImDrawVert);
     unsigned int offset = 0;
-    ctx->IASetInputLayout(bd->pInputLayout);
-    ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
-    ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
-    ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
-    ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
-    ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
-    ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
-    ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
-    ctx->GSSetShader(nullptr, nullptr, 0);
-    ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
-    ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
-    ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
+    device_ctx->IASetInputLayout(bd->pInputLayout);
+    device_ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
+    device_ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
+    device_ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+    device_ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
+    device_ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
+    device_ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
+    device_ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
+    device_ctx->GSSetShader(nullptr, nullptr, 0);
+    device_ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
+    device_ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
+    device_ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
 
     // Setup blend state
     const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
-    ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
-    ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
-    ctx->RSSetState(bd->pRasterizerState);
+    device_ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
+    device_ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
+    device_ctx->RSSetState(bd->pRasterizerState);
 }
 
 // Render function
@@ -126,7 +126,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
         return;
 
     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
-    ID3D11DeviceContext* ctx = bd->pd3dDeviceContext;
+    ID3D11DeviceContext* device = bd->pd3dDeviceContext;
 
     // Create and grow vertex/index buffers if needed
     if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
@@ -159,28 +159,28 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
 
     // Upload vertex/index data into a single contiguous GPU buffer
     D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
-    if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
+    if (device->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
         return;
-    if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
+    if (device->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
         return;
     ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
     ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
-        memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
-        vtx_dst += cmd_list->VtxBuffer.Size;
-        idx_dst += cmd_list->IdxBuffer.Size;
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
+        memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+        vtx_dst += draw_list->VtxBuffer.Size;
+        idx_dst += draw_list->IdxBuffer.Size;
     }
-    ctx->Unmap(bd->pVB, 0);
-    ctx->Unmap(bd->pIB, 0);
+    device->Unmap(bd->pVB, 0);
+    device->Unmap(bd->pIB, 0);
 
     // Setup orthographic projection matrix into our constant buffer
     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
     {
         D3D11_MAPPED_SUBRESOURCE mapped_resource;
-        if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
+        if (device->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
             return;
         VERTEX_CONSTANT_BUFFER_DX11* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX11*)mapped_resource.pData;
         float L = draw_data->DisplayPos.x;
@@ -195,7 +195,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
             { (R+L)/(L-R),  (T+B)/(B-T),    0.5f,       1.0f },
         };
         memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
-        ctx->Unmap(bd->pVertexConstantBuffer, 0);
+        device->Unmap(bd->pVertexConstantBuffer, 0);
     }
 
     // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
@@ -225,26 +225,26 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
     };
     BACKUP_DX11_STATE old = {};
     old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
-    ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
-    ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
-    ctx->RSGetState(&old.RS);
-    ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
-    ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
-    ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
-    ctx->PSGetSamplers(0, 1, &old.PSSampler);
+    device->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
+    device->RSGetViewports(&old.ViewportsCount, old.Viewports);
+    device->RSGetState(&old.RS);
+    device->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
+    device->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
+    device->PSGetShaderResources(0, 1, &old.PSShaderResource);
+    device->PSGetSamplers(0, 1, &old.PSSampler);
     old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256;
-    ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
-    ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
-    ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
-    ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount);
+    device->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
+    device->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
+    device->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
+    device->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount);
 
-    ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
-    ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
-    ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
-    ctx->IAGetInputLayout(&old.InputLayout);
+    device->IAGetPrimitiveTopology(&old.PrimitiveTopology);
+    device->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
+    device->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
+    device->IAGetInputLayout(&old.InputLayout);
 
     // Setup desired DX state
-    ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
+    ImGui_ImplDX11_SetupRenderState(draw_data, device);
 
     // Render command lists
     // (Because we merged all buffers into a single one, we maintain our own offset into them)
@@ -253,18 +253,18 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
     ImVec2 clip_off = draw_data->DisplayPos;
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback != nullptr)
             {
                 // User callback, registered via ImDrawList::AddCallback()
                 // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
-                    ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
+                    ImGui_ImplDX11_SetupRenderState(draw_data, device);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
@@ -276,36 +276,36 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
 
                 // Apply scissor/clipping rectangle
                 const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
-                ctx->RSSetScissorRects(1, &r);
+                device->RSSetScissorRects(1, &r);
 
                 // Bind texture, Draw
                 ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
-                ctx->PSSetShaderResources(0, 1, &texture_srv);
-                ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
+                device->PSSetShaderResources(0, 1, &texture_srv);
+                device->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
             }
         }
-        global_idx_offset += cmd_list->IdxBuffer.Size;
-        global_vtx_offset += cmd_list->VtxBuffer.Size;
+        global_idx_offset += draw_list->IdxBuffer.Size;
+        global_vtx_offset += draw_list->VtxBuffer.Size;
     }
 
     // Restore modified DX state
-    ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
-    ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
-    ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
-    ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
-    ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
-    ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
-    ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
-    ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
+    device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
+    device->RSSetViewports(old.ViewportsCount, old.Viewports);
+    device->RSSetState(old.RS); if (old.RS) old.RS->Release();
+    device->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
+    device->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
+    device->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
+    device->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
+    device->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
     for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
-    ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
-    ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
-    ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release();
+    device->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
+    device->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
+    device->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release();
     for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
-    ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
-    ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
-    ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
-    ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
+    device->IASetPrimitiveTopology(old.PrimitiveTopology);
+    device->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
+    device->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
+    device->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
 }
 
 static void ImGui_ImplDX11_CreateFontsTexture()
diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index 32f1622cd46d..c63503cc04de 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -95,7 +95,7 @@ struct VERTEX_CONSTANT_BUFFER_DX12
 };
 
 // Functions
-static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, ImGui_ImplDX12_RenderBuffers* fr)
+static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list, ImGui_ImplDX12_RenderBuffers* fr)
 {
     ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
 
@@ -125,7 +125,7 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic
     vp.MinDepth = 0.0f;
     vp.MaxDepth = 1.0f;
     vp.TopLeftX = vp.TopLeftY = 0.0f;
-    ctx->RSSetViewports(1, &vp);
+    command_list->RSSetViewports(1, &vp);
 
     // Bind shader and vertex buffers
     unsigned int stride = sizeof(ImDrawVert);
@@ -135,21 +135,21 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic
     vbv.BufferLocation = fr->VertexBuffer->GetGPUVirtualAddress() + offset;
     vbv.SizeInBytes = fr->VertexBufferSize * stride;
     vbv.StrideInBytes = stride;
-    ctx->IASetVertexBuffers(0, 1, &vbv);
+    command_list->IASetVertexBuffers(0, 1, &vbv);
     D3D12_INDEX_BUFFER_VIEW ibv;
     memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW));
     ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress();
     ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx);
     ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
-    ctx->IASetIndexBuffer(&ibv);
-    ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
-    ctx->SetPipelineState(bd->pPipelineState);
-    ctx->SetGraphicsRootSignature(bd->pRootSignature);
-    ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
+    command_list->IASetIndexBuffer(&ibv);
+    command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+    command_list->SetPipelineState(bd->pPipelineState);
+    command_list->SetGraphicsRootSignature(bd->pRootSignature);
+    command_list->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
 
     // Setup blend factor
     const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
-    ctx->OMSetBlendFactor(blend_factor);
+    command_list->OMSetBlendFactor(blend_factor);
 }
 
 template
@@ -161,7 +161,7 @@ static inline void SafeRelease(T*& res)
 }
 
 // Render function
-void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx)
+void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* command_list)
 {
     // Avoid rendering when minimized
     if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
@@ -233,17 +233,17 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
     ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource;
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
-        memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
-        vtx_dst += cmd_list->VtxBuffer.Size;
-        idx_dst += cmd_list->IdxBuffer.Size;
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
+        memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+        vtx_dst += draw_list->VtxBuffer.Size;
+        idx_dst += draw_list->IdxBuffer.Size;
     }
     fr->VertexBuffer->Unmap(0, &range);
     fr->IndexBuffer->Unmap(0, &range);
 
     // Setup desired DX state
-    ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr);
+    ImGui_ImplDX12_SetupRenderState(draw_data, command_list, fr);
 
     // Render command lists
     // (Because we merged all buffers into a single one, we maintain our own offset into them)
@@ -252,18 +252,18 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
     ImVec2 clip_off = draw_data->DisplayPos;
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback != nullptr)
             {
                 // User callback, registered via ImDrawList::AddCallback()
                 // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
-                    ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr);
+                    ImGui_ImplDX12_SetupRenderState(draw_data, command_list, fr);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
@@ -273,17 +273,19 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
                 if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
                     continue;
 
-                // Apply Scissor/clipping rectangle, Bind texture, Draw
+                // Apply scissor/clipping rectangle
                 const D3D12_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
+                command_list->RSSetScissorRects(1, &r);
+
+                // Bind texture, Draw
                 D3D12_GPU_DESCRIPTOR_HANDLE texture_handle = {};
                 texture_handle.ptr = (UINT64)pcmd->GetTexID();
-                ctx->SetGraphicsRootDescriptorTable(1, texture_handle);
-                ctx->RSSetScissorRects(1, &r);
-                ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
+                command_list->SetGraphicsRootDescriptorTable(1, texture_handle);
+                command_list->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
             }
         }
-        global_idx_offset += cmd_list->IdxBuffer.Size;
-        global_vtx_offset += cmd_list->VtxBuffer.Size;
+        global_idx_offset += draw_list->IdxBuffer.Size;
+        global_vtx_offset += draw_list->VtxBuffer.Size;
     }
 }
 
diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h
index e1fd07d6d4e1..08c0a12559bc 100644
--- a/backends/imgui_impl_dx12.h
+++ b/backends/imgui_impl_dx12.h
@@ -29,8 +29,7 @@ struct D3D12_GPU_DESCRIPTOR_HANDLE;
 
 // Follow "Getting Started" link and check examples/ folder to learn about using backends!
 
-// cmd_list is the command list that the implementation will use to render imgui draw lists.
-// Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate
+// Before calling the render function, caller must prepare the command list by resetting it and setting the appropriate
 // render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle.
 // font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture.
 IMGUI_IMPL_API bool     ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp
index 3eff9ab5da9f..24bd5d3b32d1 100644
--- a/backends/imgui_impl_dx9.cpp
+++ b/backends/imgui_impl_dx9.cpp
@@ -88,41 +88,43 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
     vp.Height = (DWORD)draw_data->DisplaySize.y;
     vp.MinZ = 0.0f;
     vp.MaxZ = 1.0f;
-    bd->pd3dDevice->SetViewport(&vp);
+
+    LPDIRECT3DDEVICE9 device = bd->pd3dDevice;
+    device->SetViewport(&vp);
 
     // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient), bilinear sampling.
-    bd->pd3dDevice->SetPixelShader(nullptr);
-    bd->pd3dDevice->SetVertexShader(nullptr);
-    bd->pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
-    bd->pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
-    bd->pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
-    bd->pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
-    bd->pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
-    bd->pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
-    bd->pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
-    bd->pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
-    bd->pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
-    bd->pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
-    bd->pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
-    bd->pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
-    bd->pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
-    bd->pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
-    bd->pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
-    bd->pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
-    bd->pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
-    bd->pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
-    bd->pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
-    bd->pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
-    bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
-    bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
-    bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
-    bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
-    bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
-    bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
-    bd->pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
-    bd->pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
-    bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
-    bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device->SetPixelShader(nullptr);
+    device->SetVertexShader(nullptr);
+    device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+    device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
+    device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+    device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+    device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+    device->SetRenderState(D3DRS_ZENABLE, FALSE);
+    device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+    device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+    device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+    device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+    device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+    device->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
+    device->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
+    device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
+    device->SetRenderState(D3DRS_FOGENABLE, FALSE);
+    device->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
+    device->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
+    device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+    device->SetRenderState(D3DRS_CLIPPING, TRUE);
+    device->SetRenderState(D3DRS_LIGHTING, FALSE);
+    device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+    device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+    device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+    device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+    device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+    device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
+    device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+    device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
 
     // Setup orthographic projection matrix
     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
@@ -140,9 +142,9 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
             0.0f,         0.0f,         0.5f,  0.0f,
             (L+R)/(L-R),  (T+B)/(B-T),  0.5f,  1.0f
         } } };
-        bd->pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
-        bd->pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
-        bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection);
+        device->SetTransform(D3DTS_WORLD, &mat_identity);
+        device->SetTransform(D3DTS_VIEW, &mat_identity);
+        device->SetTransform(D3DTS_PROJECTION, &mat_projection);
     }
 }
 
@@ -153,51 +155,53 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
     if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
         return;
 
-    // Create and grow buffers if needed
     ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
+    LPDIRECT3DDEVICE9 device = bd->pd3dDevice;
+
+    // Create and grow buffers if needed
     if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
     {
         if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
         bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
-        if (bd->pd3dDevice->CreateVertexBuffer(bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, nullptr) < 0)
+        if (device->CreateVertexBuffer(bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, nullptr) < 0)
             return;
     }
     if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
     {
         if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
         bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
-        if (bd->pd3dDevice->CreateIndexBuffer(bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
+        if (device->CreateIndexBuffer(bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
             return;
     }
 
     // Backup the DX9 state
-    IDirect3DStateBlock9* d3d9_state_block = nullptr;
-    if (bd->pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
+    IDirect3DStateBlock9* state_block = nullptr;
+    if (device->CreateStateBlock(D3DSBT_ALL, &state_block) < 0)
         return;
-    if (d3d9_state_block->Capture() < 0)
+    if (state_block->Capture() < 0)
     {
-        d3d9_state_block->Release();
+        state_block->Release();
         return;
     }
 
     // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
     D3DMATRIX last_world, last_view, last_projection;
-    bd->pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
-    bd->pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
-    bd->pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
+    device->GetTransform(D3DTS_WORLD, &last_world);
+    device->GetTransform(D3DTS_VIEW, &last_view);
+    device->GetTransform(D3DTS_PROJECTION, &last_projection);
 
     // Allocate buffers
     CUSTOMVERTEX* vtx_dst;
     ImDrawIdx* idx_dst;
     if (bd->pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
     {
-        d3d9_state_block->Release();
+        state_block->Release();
         return;
     }
     if (bd->pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
     {
         bd->pVB->Unlock();
-        d3d9_state_block->Release();
+        state_block->Release();
         return;
     }
 
@@ -207,9 +211,9 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
     //  2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data;
-        for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        const ImDrawVert* vtx_src = draw_list->VtxBuffer.Data;
+        for (int i = 0; i < draw_list->VtxBuffer.Size; i++)
         {
             vtx_dst->pos[0] = vtx_src->pos.x;
             vtx_dst->pos[1] = vtx_src->pos.y;
@@ -220,14 +224,14 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
             vtx_dst++;
             vtx_src++;
         }
-        memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
-        idx_dst += cmd_list->IdxBuffer.Size;
+        memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+        idx_dst += draw_list->IdxBuffer.Size;
     }
     bd->pVB->Unlock();
     bd->pIB->Unlock();
-    bd->pd3dDevice->SetStreamSource(0, bd->pVB, 0, sizeof(CUSTOMVERTEX));
-    bd->pd3dDevice->SetIndices(bd->pIB);
-    bd->pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
+    device->SetStreamSource(0, bd->pVB, 0, sizeof(CUSTOMVERTEX));
+    device->SetIndices(bd->pIB);
+    device->SetFVF(D3DFVF_CUSTOMVERTEX);
 
     // Setup desired DX state
     ImGui_ImplDX9_SetupRenderState(draw_data);
@@ -239,10 +243,10 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
     ImVec2 clip_off = draw_data->DisplayPos;
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback != nullptr)
             {
                 // User callback, registered via ImDrawList::AddCallback()
@@ -250,7 +254,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
                     ImGui_ImplDX9_SetupRenderState(draw_data);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
@@ -260,26 +264,28 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
                 if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
                     continue;
 
-                // Apply Scissor/clipping rectangle, Bind texture, Draw
+                // Apply scissor/clipping rectangle
                 const RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
+                device->SetScissorRect(&r);
+
+                // Bind texture, Draw
                 const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID();
-                bd->pd3dDevice->SetTexture(0, texture);
-                bd->pd3dDevice->SetScissorRect(&r);
-                bd->pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
+                device->SetTexture(0, texture);
+                device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)draw_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
             }
         }
-        global_idx_offset += cmd_list->IdxBuffer.Size;
-        global_vtx_offset += cmd_list->VtxBuffer.Size;
+        global_idx_offset += draw_list->IdxBuffer.Size;
+        global_vtx_offset += draw_list->VtxBuffer.Size;
     }
 
     // Restore the DX9 transform
-    bd->pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
-    bd->pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
-    bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection);
+    device->SetTransform(D3DTS_WORLD, &last_world);
+    device->SetTransform(D3DTS_VIEW, &last_view);
+    device->SetTransform(D3DTS_PROJECTION, &last_projection);
 
     // Restore the DX9 state
-    d3d9_state_block->Apply();
-    d3d9_state_block->Release();
+    state_block->Apply();
+    state_block->Release();
 }
 
 bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm
index f9fd1087e849..818961048abb 100644
--- a/backends/imgui_impl_metal.mm
+++ b/backends/imgui_impl_metal.mm
@@ -246,14 +246,14 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData, id c
     size_t indexBufferOffset = 0;
     for (int n = 0; n < drawData->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = drawData->CmdLists[n];
+        const ImDrawList* draw_list = drawData->CmdLists[n];
 
-        memcpy((char*)vertexBuffer.buffer.contents + vertexBufferOffset, cmd_list->VtxBuffer.Data, (size_t)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
-        memcpy((char*)indexBuffer.buffer.contents + indexBufferOffset, cmd_list->IdxBuffer.Data, (size_t)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+        memcpy((char*)vertexBuffer.buffer.contents + vertexBufferOffset, draw_list->VtxBuffer.Data, (size_t)draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
+        memcpy((char*)indexBuffer.buffer.contents + indexBufferOffset, draw_list->IdxBuffer.Data, (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
 
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback)
             {
                 // User callback, registered via ImDrawList::AddCallback()
@@ -261,7 +261,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData, id c
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
                     ImGui_ImplMetal_SetupRenderState(drawData, commandBuffer, commandEncoder, renderPipelineState, vertexBuffer, vertexBufferOffset);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
@@ -302,8 +302,8 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData, id c
             }
         }
 
-        vertexBufferOffset += (size_t)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
-        indexBufferOffset += (size_t)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx);
+        vertexBufferOffset += (size_t)draw_list->VtxBuffer.Size * sizeof(ImDrawVert);
+        indexBufferOffset += (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx);
     }
 
     [commandBuffer addCompletedHandler:^(id)
diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp
index 7f1ea325aa87..0e69f18b28f3 100644
--- a/backends/imgui_impl_opengl2.cpp
+++ b/backends/imgui_impl_opengl2.cpp
@@ -192,16 +192,16 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
     // Render command lists
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
-        const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
+        const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
         glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, pos)));
         glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, uv)));
         glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + offsetof(ImDrawVert, col)));
 
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback)
             {
                 // User callback, registered via ImDrawList::AddCallback()
@@ -209,7 +209,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
                     ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp
index 7087a7c5706d..fef6ed7611c9 100644
--- a/backends/imgui_impl_opengl3.cpp
+++ b/backends/imgui_impl_opengl3.cpp
@@ -550,7 +550,7 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
     // Render command lists
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
 
         // Upload vertex/index buffers
         // - OpenGL drivers are in a very sorry state nowadays....
@@ -560,8 +560,8 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
         // - We are now back to using exclusively glBufferData(). So bd->UseBufferSubData IS ALWAYS FALSE in this code.
         //   We are keeping the old code path for a while in case people finding new issues may want to test the bd->UseBufferSubData path.
         // - See https://github.com/ocornut/imgui/issues/4468 and please report any corruption issues.
-        const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
-        const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
+        const GLsizeiptr vtx_buffer_size = (GLsizeiptr)draw_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
+        const GLsizeiptr idx_buffer_size = (GLsizeiptr)draw_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
         if (bd->UseBufferSubData)
         {
             if (bd->VertexBufferSize < vtx_buffer_size)
@@ -574,18 +574,18 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
                 bd->IndexBufferSize = idx_buffer_size;
                 GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, nullptr, GL_STREAM_DRAW));
             }
-            GL_CALL(glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data));
-            GL_CALL(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data));
+            GL_CALL(glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)draw_list->VtxBuffer.Data));
+            GL_CALL(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)draw_list->IdxBuffer.Data));
         }
         else
         {
-            GL_CALL(glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW));
-            GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW));
+            GL_CALL(glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)draw_list->VtxBuffer.Data, GL_STREAM_DRAW));
+            GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)draw_list->IdxBuffer.Data, GL_STREAM_DRAW));
         }
 
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback != nullptr)
             {
                 // User callback, registered via ImDrawList::AddCallback()
@@ -593,7 +593,7 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
                     ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp
index 3d538dfe78c5..8203c6cafbc6 100644
--- a/backends/imgui_impl_sdlrenderer2.cpp
+++ b/backends/imgui_impl_sdlrenderer2.cpp
@@ -148,13 +148,13 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
     ImGui_ImplSDLRenderer2_SetupRenderState(renderer);
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
-        const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
+        const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
 
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback)
             {
                 // User callback, registered via ImDrawList::AddCallback()
@@ -162,7 +162,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
                     ImGui_ImplSDLRenderer2_SetupRenderState(renderer);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
@@ -193,7 +193,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
                     xy, (int)sizeof(ImDrawVert),
                     color, (int)sizeof(ImDrawVert),
                     uv, (int)sizeof(ImDrawVert),
-                    cmd_list->VtxBuffer.Size - pcmd->VtxOffset,
+                    draw_list->VtxBuffer.Size - pcmd->VtxOffset,
                     idx_buffer + pcmd->IdxOffset, pcmd->ElemCount, sizeof(ImDrawIdx));
             }
         }
diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp
index 30f967bd3677..9397a6467e42 100644
--- a/backends/imgui_impl_sdlrenderer3.cpp
+++ b/backends/imgui_impl_sdlrenderer3.cpp
@@ -171,13 +171,13 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
     ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
-        const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
+        const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
 
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback)
             {
                 // User callback, registered via ImDrawList::AddCallback()
@@ -185,7 +185,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
                     ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
@@ -212,7 +212,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
                     xy, (int)sizeof(ImDrawVert),
                     color, (int)sizeof(ImDrawVert),
                     uv, (int)sizeof(ImDrawVert),
-                    cmd_list->VtxBuffer.Size - pcmd->VtxOffset,
+                    draw_list->VtxBuffer.Size - pcmd->VtxOffset,
                     idx_buffer + pcmd->IdxOffset, pcmd->ElemCount, sizeof(ImDrawIdx));
             }
         }
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index 3b757eb6670c..a0df9edfb01d 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -518,11 +518,11 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
         check_vk_result(err);
         for (int n = 0; n < draw_data->CmdListsCount; n++)
         {
-            const ImDrawList* cmd_list = draw_data->CmdLists[n];
-            memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
-            memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
-            vtx_dst += cmd_list->VtxBuffer.Size;
-            idx_dst += cmd_list->IdxBuffer.Size;
+            const ImDrawList* draw_list = draw_data->CmdLists[n];
+            memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
+            memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+            vtx_dst += draw_list->VtxBuffer.Size;
+            idx_dst += draw_list->IdxBuffer.Size;
         }
         VkMappedMemoryRange range[2] = {};
         range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
@@ -550,10 +550,10 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
     int global_idx_offset = 0;
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback != nullptr)
             {
                 // User callback, registered via ImDrawList::AddCallback()
@@ -561,7 +561,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
                     ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
@@ -599,8 +599,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
                 vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
             }
         }
-        global_idx_offset += cmd_list->IdxBuffer.Size;
-        global_vtx_offset += cmd_list->VtxBuffer.Size;
+        global_idx_offset += draw_list->IdxBuffer.Size;
+        global_vtx_offset += draw_list->VtxBuffer.Size;
     }
 
     // Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp
index 4109e392eef5..9f75364d5a13 100644
--- a/backends/imgui_impl_wgpu.cpp
+++ b/backends/imgui_impl_wgpu.cpp
@@ -425,11 +425,11 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
     ImDrawIdx* idx_dst = (ImDrawIdx*)fr->IndexBufferHost;
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
-        memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
-        vtx_dst += cmd_list->VtxBuffer.Size;
-        idx_dst += cmd_list->IdxBuffer.Size;
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert));
+        memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+        vtx_dst += draw_list->VtxBuffer.Size;
+        idx_dst += draw_list->IdxBuffer.Size;
     }
     int64_t vb_write_size = MEMALIGN((char*)vtx_dst - (char*)fr->VertexBufferHost, 4);
     int64_t ib_write_size = MEMALIGN((char*)idx_dst - (char*)fr->IndexBufferHost, 4);
@@ -447,10 +447,10 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
     ImVec2 clip_off = draw_data->DisplayPos;
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
-        const ImDrawList* cmd_list = draw_data->CmdLists[n];
-        for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+        const ImDrawList* draw_list = draw_data->CmdLists[n];
+        for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
         {
-            const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+            const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback != nullptr)
             {
                 // User callback, registered via ImDrawList::AddCallback()
@@ -458,7 +458,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
                 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
                     ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
                 else
-                    pcmd->UserCallback(cmd_list, pcmd);
+                    pcmd->UserCallback(draw_list, pcmd);
             }
             else
             {
@@ -494,8 +494,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
                 wgpuRenderPassEncoderDrawIndexed(pass_encoder, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
             }
         }
-        global_idx_offset += cmd_list->IdxBuffer.Size;
-        global_vtx_offset += cmd_list->VtxBuffer.Size;
+        global_idx_offset += draw_list->IdxBuffer.Size;
+        global_vtx_offset += draw_list->VtxBuffer.Size;
     }
 }
 

From e94f95d82b94b36dfd0a3b217787ab7cb638d01a Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 7 Oct 2024 21:00:07 +0200
Subject: [PATCH 174/548] Backends: DX11, DX12, Vulkan, WGPU: Expose some
 backend-specific render state usable for callbacks. (#6969, #5834, #7468,
 #3590)

---
 backends/imgui_impl_dx11.cpp   | 11 +++++++++++
 backends/imgui_impl_dx11.h     | 12 ++++++++++++
 backends/imgui_impl_dx12.cpp   | 10 ++++++++++
 backends/imgui_impl_dx12.h     | 10 ++++++++++
 backends/imgui_impl_vulkan.cpp | 11 +++++++++++
 backends/imgui_impl_vulkan.h   | 31 +++++++++++++++++++++----------
 backends/imgui_impl_wgpu.cpp   | 10 ++++++++++
 backends/imgui_impl_wgpu.h     | 10 ++++++++++
 docs/CHANGELOG.txt             |  6 ++++++
 imgui.h                        |  9 ++++++++-
 10 files changed, 109 insertions(+), 11 deletions(-)

diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp
index f656bbc55fbe..4ee774085bf0 100644
--- a/backends/imgui_impl_dx11.cpp
+++ b/backends/imgui_impl_dx11.cpp
@@ -4,6 +4,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -15,6 +16,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: DirectX11: Expose selected render state in ImGui_ImplDX11_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 //  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
 //  2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
@@ -246,6 +248,14 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
     // Setup desired DX state
     ImGui_ImplDX11_SetupRenderState(draw_data, device);
 
+    // Setup render state structure (for callbacks and custom texture bindings)
+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
+    ImGui_ImplDX11_RenderState render_state;
+    render_state.Device = bd->pd3dDevice;
+    render_state.DeviceContext = bd->pd3dDeviceContext;
+    render_state.SamplerDefault = bd->pFontSampler;
+    platform_io.Renderer_RenderState = &render_state;
+
     // Render command lists
     // (Because we merged all buffers into a single one, we maintain our own offset into them)
     int global_idx_offset = 0;
@@ -287,6 +297,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
         global_idx_offset += draw_list->IdxBuffer.Size;
         global_vtx_offset += draw_list->VtxBuffer.Size;
     }
+    platform_io.Renderer_RenderState = NULL;
 
     // Restore modified DX state
     device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
diff --git a/backends/imgui_impl_dx11.h b/backends/imgui_impl_dx11.h
index cde64ee961b8..cb79633c3386 100644
--- a/backends/imgui_impl_dx11.h
+++ b/backends/imgui_impl_dx11.h
@@ -4,6 +4,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -19,6 +20,7 @@
 
 struct ID3D11Device;
 struct ID3D11DeviceContext;
+struct ID3D11SamplerState;
 
 // Follow "Getting Started" link and check examples/ folder to learn about using backends!
 IMGUI_IMPL_API bool     ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
@@ -30,4 +32,14 @@ IMGUI_IMPL_API void     ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
 IMGUI_IMPL_API void     ImGui_ImplDX11_InvalidateDeviceObjects();
 IMGUI_IMPL_API bool     ImGui_ImplDX11_CreateDeviceObjects();
 
+// [BETA] Selected render state data shared with callbacks.
+// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplDX11_RenderDrawData() call.
+// (Please open an issue if you feel you need access to more data)
+struct ImGui_ImplDX11_RenderState
+{
+    ID3D11Device*           Device;
+    ID3D11DeviceContext*    DeviceContext;
+    ID3D11SamplerState*     SamplerDefault;
+};
+
 #endif // #ifndef IMGUI_DISABLE
diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index c63503cc04de..376ab7a6831c 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -4,6 +4,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
 
 // Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
 // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
@@ -23,6 +24,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: DirectX12: Expose selected render state in ImGui_ImplDX12_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 //  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
 //  2021-05-19: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
@@ -245,6 +247,13 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
     // Setup desired DX state
     ImGui_ImplDX12_SetupRenderState(draw_data, command_list, fr);
 
+    // Setup render state structure (for callbacks and custom texture bindings)
+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
+    ImGui_ImplDX12_RenderState render_state;
+    render_state.Device = bd->pd3dDevice;
+    render_state.CommandList = command_list;
+    platform_io.Renderer_RenderState = &render_state;
+
     // Render command lists
     // (Because we merged all buffers into a single one, we maintain our own offset into them)
     int global_vtx_offset = 0;
@@ -287,6 +296,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
         global_idx_offset += draw_list->IdxBuffer.Size;
         global_vtx_offset += draw_list->VtxBuffer.Size;
     }
+    platform_io.Renderer_RenderState = NULL;
 }
 
 static void ImGui_ImplDX12_CreateFontsTexture()
diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h
index 08c0a12559bc..bee7454fab33 100644
--- a/backends/imgui_impl_dx12.h
+++ b/backends/imgui_impl_dx12.h
@@ -4,6 +4,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
 
 // Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
 // See imgui_impl_dx12.cpp file for details.
@@ -42,4 +43,13 @@ IMGUI_IMPL_API void     ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3
 IMGUI_IMPL_API void     ImGui_ImplDX12_InvalidateDeviceObjects();
 IMGUI_IMPL_API bool     ImGui_ImplDX12_CreateDeviceObjects();
 
+// [BETA] Selected render state data shared with callbacks.
+// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplDX12_RenderDrawData() call.
+// (Please open an issue if you feel you need access to more data)
+struct ImGui_ImplDX12_RenderState
+{
+    ID3D12Device*               Device;
+    ID3D12GraphicsCommandList*  CommandList;
+};
+
 #endif // #ifndef IMGUI_DISABLE
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index a0df9edfb01d..f3f560607ec8 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -4,6 +4,7 @@
 // Implemented features:
 //  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
 
 // Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
 // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
@@ -33,6 +34,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
 //  2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering.
 //  2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure.
@@ -540,6 +542,14 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
     // Setup desired Vulkan state
     ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
 
+    // Setup render state structure (for callbacks and custom texture bindings)
+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
+    ImGui_ImplVulkan_RenderState render_state;
+    render_state.CommandBuffer = command_buffer;
+    render_state.Pipeline = pipeline;
+    render_state.PipelineLayout = bd->PipelineLayout;
+    platform_io.Renderer_RenderState = &render_state;
+
     // Will project scissor/clipping rectangles into framebuffer space
     ImVec2 clip_off = draw_data->DisplayPos;         // (0,0) unless using multi-viewports
     ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
@@ -602,6 +612,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
         global_idx_offset += draw_list->IdxBuffer.Size;
         global_vtx_offset += draw_list->VtxBuffer.Size;
     }
+    platform_io.Renderer_RenderState = NULL;
 
     // Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
     // Our last values will leak into user/application rendering IF:
diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h
index 1c7f7695183f..a834d7d7a572 100644
--- a/backends/imgui_impl_vulkan.h
+++ b/backends/imgui_impl_vulkan.h
@@ -4,6 +4,7 @@
 // Implemented features:
 //  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
 
 // Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
 // See imgui_impl_vulkan.cpp file for details.
@@ -99,23 +100,33 @@ struct ImGui_ImplVulkan_InitInfo
 };
 
 // Follow "Getting Started" link and check examples/ folder to learn about using backends!
-IMGUI_IMPL_API bool         ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info);
-IMGUI_IMPL_API void         ImGui_ImplVulkan_Shutdown();
-IMGUI_IMPL_API void         ImGui_ImplVulkan_NewFrame();
-IMGUI_IMPL_API void         ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
-IMGUI_IMPL_API bool         ImGui_ImplVulkan_CreateFontsTexture();
-IMGUI_IMPL_API void         ImGui_ImplVulkan_DestroyFontsTexture();
-IMGUI_IMPL_API void         ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
+IMGUI_IMPL_API bool             ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info);
+IMGUI_IMPL_API void             ImGui_ImplVulkan_Shutdown();
+IMGUI_IMPL_API void             ImGui_ImplVulkan_NewFrame();
+IMGUI_IMPL_API void             ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
+IMGUI_IMPL_API bool             ImGui_ImplVulkan_CreateFontsTexture();
+IMGUI_IMPL_API void             ImGui_ImplVulkan_DestroyFontsTexture();
+IMGUI_IMPL_API void             ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
 
 // Register a texture (VkDescriptorSet == ImTextureID)
 // FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem
 // Please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
-IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout);
-IMGUI_IMPL_API void            ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set);
+IMGUI_IMPL_API VkDescriptorSet  ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout);
+IMGUI_IMPL_API void             ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set);
 
 // Optional: load Vulkan functions with a custom function loader
 // This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES
-IMGUI_IMPL_API bool         ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);
+IMGUI_IMPL_API bool             ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);
+
+// [BETA] Selected render state data shared with callbacks.
+// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplVulkan_RenderDrawData() call.
+// (Please open an issue if you feel you need access to more data)
+struct ImGui_ImplVulkan_RenderState
+{
+    VkCommandBuffer     CommandBuffer;
+    VkPipeline          Pipeline;
+    VkPipelineLayout    PipelineLayout;
+};
 
 //-------------------------------------------------------------------------
 // Internal / Miscellaneous Vulkan Helpers
diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp
index 9f75364d5a13..84a28406b887 100644
--- a/backends/imgui_impl_wgpu.cpp
+++ b/backends/imgui_impl_wgpu.cpp
@@ -5,6 +5,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -16,6 +17,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: Expose selected render state in ImGui_ImplWGPU_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2024-09-16: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU define to handle ever-changing native implementations. (#7977)
 //  2024-01-22: Added configurable PipelineMultisampleState struct. (#7240)
 //  2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes.
@@ -439,6 +441,13 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
     // Setup desired render state
     ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
 
+    // Setup render state structure (for callbacks and custom texture bindings)
+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
+    ImGui_ImplWGPU_RenderState render_state;
+    render_state.Device = bd->wgpuDevice;
+    render_state.RenderPassEncoder = pass_encoder;
+    platform_io.Renderer_RenderState = &render_state;
+
     // Render command lists
     // (Because we merged all buffers into a single one, we maintain our own offset into them)
     int global_vtx_offset = 0;
@@ -497,6 +506,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
         global_idx_offset += draw_list->IdxBuffer.Size;
         global_vtx_offset += draw_list->VtxBuffer.Size;
     }
+    platform_io.Renderer_RenderState = NULL;
 }
 
 static void ImGui_ImplWGPU_CreateFontsTexture()
diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h
index e6835dee94c8..a171fd6d0ca0 100644
--- a/backends/imgui_impl_wgpu.h
+++ b/backends/imgui_impl_wgpu.h
@@ -12,6 +12,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -54,4 +55,13 @@ IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURen
 IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
 IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateDeviceObjects();
 
+// [BETA] Selected render state data shared with callbacks.
+// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplWGPU_RenderDrawData() call.
+// (Please open an issue if you feel you need access to more data)
+struct ImGui_ImplWGPU_RenderState
+{
+    WGPUDevice                  Device;
+    WGPURenderPassEncoder       RenderPassEncoder;
+};
+
 #endif // #ifndef IMGUI_DISABLE
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index b5f526809774..4ca534c7b275 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,12 @@ Breaking changes:
 
 Other changes:
 
+- IO: added 'void* platform_io.Renderer_RenderState' which is set during the
+  ImGui_ImplXXXX_RenderDrawData() of standard backend to expose selected render
+  state to draw callbacks. (#6969, #5834, #7468, #3590)
+- Backends: DX11, DX12, Vulkan, WGPU: expose selected state in ImGui_ImplXXXX_RenderState.
+  structure during render loop. (#6969, #5834, #7468, #3590)
+
 
 -----------------------------------------------------------------------
  VERSION 1.91.3 (Released 2024-10-04)
diff --git a/imgui.h b/imgui.h
index 49ad70cee4f5..f3d5d83d49ff 100644
--- a/imgui.h
+++ b/imgui.h
@@ -3515,7 +3515,7 @@ struct ImGuiPlatformIO
     IMGUI_API ImGuiPlatformIO();
 
     //------------------------------------------------------------------
-    // Input - Interface with OS/backends
+    // Interface with OS and Platform backend
     //------------------------------------------------------------------
 
     // Optional: Access OS clipboard
@@ -3538,6 +3538,13 @@ struct ImGuiPlatformIO
     // Optional: Platform locale
     // [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point
     ImWchar     Platform_LocaleDecimalPoint;     // '.'
+
+    //------------------------------------------------------------------
+    // Interface with Renderer Backend
+    //------------------------------------------------------------------
+
+    // Written by some backends during ImGui_ImplXXXX_RenderDrawData() call to point backend_specific ImGui_ImplXXXX_RenderState* structure.
+    void*       Renderer_RenderState;
 };
 
 // (Optional) Support for IME (Input Method Editor) via the platform_io.Platform_SetImeDataFn() function.

From 74dd38d27c946087c31b21dc83265439ea7a95cd Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 7 Oct 2024 21:53:46 +0200
Subject: [PATCH 175/548] Backends: Vulkan: fixed warnings when building in
 32-bit mode.

---
 backends/imgui_impl_vulkan.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index f3f560607ec8..a608b1a639a3 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -396,7 +396,7 @@ static inline VkDeviceSize AlignBufferSize(VkDeviceSize size, VkDeviceSize align
     return (size + alignment - 1) & ~(alignment - 1);
 }
 
-static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
+static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& buffer_size, VkDeviceSize new_size, VkBufferUsageFlagBits usage)
 {
     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
@@ -504,8 +504,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
     if (draw_data->TotalVtxCount > 0)
     {
         // Create or resize the vertex/index buffers
-        size_t vertex_size = AlignBufferSize(draw_data->TotalVtxCount * sizeof(ImDrawVert), bd->BufferMemoryAlignment);
-        size_t index_size = AlignBufferSize(draw_data->TotalIdxCount * sizeof(ImDrawIdx), bd->BufferMemoryAlignment);
+        VkDeviceSize vertex_size = AlignBufferSize(draw_data->TotalVtxCount * sizeof(ImDrawVert), bd->BufferMemoryAlignment);
+        VkDeviceSize index_size = AlignBufferSize(draw_data->TotalIdxCount * sizeof(ImDrawIdx), bd->BufferMemoryAlignment);
         if (rb->VertexBuffer == VK_NULL_HANDLE || rb->VertexBufferSize < vertex_size)
             CreateOrResizeBuffer(rb->VertexBuffer, rb->VertexBufferMemory, rb->VertexBufferSize, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
         if (rb->IndexBuffer == VK_NULL_HANDLE || rb->IndexBufferSize < index_size)

From 42206b3d51347c10330b36af26ec13ae3492ba5e Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 7 Oct 2024 22:02:55 +0200
Subject: [PATCH 176/548] Backends: DX9, DX10, DX11, DX12, OpenGL, Vulkan,
 WGPU: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 (#7468, #7511, #5999, #5502)

---
 backends/imgui_impl_dx10.cpp         | 7 ++++---
 backends/imgui_impl_dx11.cpp         | 7 ++++---
 backends/imgui_impl_dx12.cpp         | 7 ++++---
 backends/imgui_impl_dx9.cpp          | 3 +++
 backends/imgui_impl_opengl2.cpp      | 3 +++
 backends/imgui_impl_opengl3.cpp      | 3 +++
 backends/imgui_impl_opengl3_loader.h | 6 ++++++
 backends/imgui_impl_vulkan.cpp       | 7 ++++---
 backends/imgui_impl_wgpu.cpp         | 7 ++++---
 docs/CHANGELOG.txt                   | 2 ++
 10 files changed, 37 insertions(+), 15 deletions(-)

diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp
index 96932c3aff23..2638caf9cadb 100644
--- a/backends/imgui_impl_dx10.cpp
+++ b/backends/imgui_impl_dx10.cpp
@@ -15,6 +15,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: DirectX10: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 //  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
 //  2021-05-19: DirectX10: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
@@ -347,9 +348,9 @@ static void ImGui_ImplDX10_CreateFontsTexture()
         D3D10_SAMPLER_DESC desc;
         ZeroMemory(&desc, sizeof(desc));
         desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
-        desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP;
-        desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP;
-        desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP;
+        desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;
+        desc.AddressV = D3D10_TEXTURE_ADDRESS_CLAMP;
+        desc.AddressW = D3D10_TEXTURE_ADDRESS_CLAMP;
         desc.MipLODBias = 0.f;
         desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
         desc.MinLOD = 0.f;
diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp
index 4ee774085bf0..088e4b67e78c 100644
--- a/backends/imgui_impl_dx11.cpp
+++ b/backends/imgui_impl_dx11.cpp
@@ -16,6 +16,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: DirectX11: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-10-07: DirectX11: Expose selected render state in ImGui_ImplDX11_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 //  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
@@ -370,9 +371,9 @@ static void ImGui_ImplDX11_CreateFontsTexture()
         D3D11_SAMPLER_DESC desc;
         ZeroMemory(&desc, sizeof(desc));
         desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
-        desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
-        desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
-        desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
+        desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+        desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+        desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
         desc.MipLODBias = 0.f;
         desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
         desc.MinLOD = 0.f;
diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index 376ab7a6831c..85a870269855 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -24,6 +24,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: DirectX12: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-10-07: DirectX12: Expose selected render state in ImGui_ImplDX12_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 //  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
@@ -489,9 +490,9 @@ bool    ImGui_ImplDX12_CreateDeviceObjects()
         // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
         D3D12_STATIC_SAMPLER_DESC staticSampler = {};
         staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
-        staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
-        staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
-        staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+        staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+        staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+        staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
         staticSampler.MipLODBias = 0.f;
         staticSampler.MaxAnisotropy = 0;
         staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp
index 24bd5d3b32d1..f1b069df11fe 100644
--- a/backends/imgui_impl_dx9.cpp
+++ b/backends/imgui_impl_dx9.cpp
@@ -15,6 +15,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: DirectX9: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-02-12: DirectX9: Using RGBA format when supported by the driver to avoid CPU side conversion. (#6575)
 //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 //  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
@@ -125,6 +126,8 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
     device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
     device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
     device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+    device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
 
     // Setup orthographic projection matrix
     // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp
index 0e69f18b28f3..789d74afb2b6 100644
--- a/backends/imgui_impl_opengl2.cpp
+++ b/backends/imgui_impl_opengl2.cpp
@@ -22,6 +22,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-06-28: OpenGL: ImGui_ImplOpenGL2_NewFrame() recreates font texture if it has been destroyed by ImGui_ImplOpenGL2_DestroyFontsTexture(). (#7748)
 //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 //  2021-12-08: OpenGL: Fixed mishandling of the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
@@ -263,6 +264,8 @@ bool ImGui_ImplOpenGL2_CreateFontsTexture()
     glBindTexture(GL_TEXTURE_2D, bd->FontTexture);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
 
diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp
index fef6ed7611c9..f5235096faff 100644
--- a/backends/imgui_impl_opengl3.cpp
+++ b/backends/imgui_impl_opengl3.cpp
@@ -22,6 +22,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-06-28: OpenGL: ImGui_ImplOpenGL3_NewFrame() recreates font texture if it has been destroyed by ImGui_ImplOpenGL3_DestroyFontsTexture(). (#7748)
 //  2024-05-07: OpenGL: Update loader for Linux to support EGL/GLVND. (#7562)
 //  2024-04-16: OpenGL: Detect ES3 contexts on desktop based on version string, to e.g. avoid calling glPolygonMode() on them. (#7447)
@@ -681,6 +682,8 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture()
     GL_CALL(glBindTexture(GL_TEXTURE_2D, bd->FontTexture));
     GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
     GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+    GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+    GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
 #ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
     GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
 #endif
diff --git a/backends/imgui_impl_opengl3_loader.h b/backends/imgui_impl_opengl3_loader.h
index 3fbc348115bd..d6ffa5a2d427 100644
--- a/backends/imgui_impl_opengl3_loader.h
+++ b/backends/imgui_impl_opengl3_loader.h
@@ -181,6 +181,9 @@ typedef khronos_uint8_t GLubyte;
 #define GL_LINEAR                         0x2601
 #define GL_TEXTURE_MAG_FILTER             0x2800
 #define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+#define GL_REPEAT                         0x2901
 typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);
 typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
 typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
@@ -231,6 +234,9 @@ GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
 GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
 #endif
 #endif /* GL_VERSION_1_1 */
+#ifndef GL_VERSION_1_2
+#define GL_CLAMP_TO_EDGE                  0x812F
+#endif /* GL_VERSION_1_2 */
 #ifndef GL_VERSION_1_3
 #define GL_TEXTURE0                       0x84C0
 #define GL_ACTIVE_TEXTURE                 0x84E0
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index a608b1a639a3..31a2516a66b6 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -34,6 +34,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-07: Vulkan: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
 //  2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering.
@@ -992,9 +993,9 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
         info.magFilter = VK_FILTER_LINEAR;
         info.minFilter = VK_FILTER_LINEAR;
         info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
-        info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
-        info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
-        info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+        info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+        info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+        info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
         info.minLod = -1000;
         info.maxLod = 1000;
         info.maxAnisotropy = 1.0f;
diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp
index 84a28406b887..a4f6c03e5d61 100644
--- a/backends/imgui_impl_wgpu.cpp
+++ b/backends/imgui_impl_wgpu.cpp
@@ -18,6 +18,7 @@
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
 //  2024-10-07: Expose selected render state in ImGui_ImplWGPU_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
+//  2024-10-07: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-09-16: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU define to handle ever-changing native implementations. (#7977)
 //  2024-01-22: Added configurable PipelineMultisampleState struct. (#7240)
 //  2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes.
@@ -565,9 +566,9 @@ static void ImGui_ImplWGPU_CreateFontsTexture()
         sampler_desc.minFilter = WGPUFilterMode_Linear;
         sampler_desc.magFilter = WGPUFilterMode_Linear;
         sampler_desc.mipmapFilter = WGPUMipmapFilterMode_Linear;
-        sampler_desc.addressModeU = WGPUAddressMode_Repeat;
-        sampler_desc.addressModeV = WGPUAddressMode_Repeat;
-        sampler_desc.addressModeW = WGPUAddressMode_Repeat;
+        sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge;
+        sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge;
+        sampler_desc.addressModeW = WGPUAddressMode_ClampToEdge;
         sampler_desc.maxAnisotropy = 1;
         bd->renderResources.Sampler = wgpuDeviceCreateSampler(bd->wgpuDevice, &sampler_desc);
     }
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 4ca534c7b275..48496340be26 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -48,6 +48,8 @@ Other changes:
   state to draw callbacks. (#6969, #5834, #7468, #3590)
 - Backends: DX11, DX12, Vulkan, WGPU: expose selected state in ImGui_ImplXXXX_RenderState.
   structure during render loop. (#6969, #5834, #7468, #3590)
+- Backends: DX9, DX10, DX11, DX12, OpenGL, Vulkan, WGPU: Changed default texture sampler
+  to Clamp instead of Repeat/Wrap. (#7468, #7511, #5999, #5502)
 
 
 -----------------------------------------------------------------------

From f890d8538161ed005680a29ab99af26d1ae5c46f Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 7 Oct 2024 22:12:09 +0200
Subject: [PATCH 177/548] Backends: Fixed typo in comments from old wip work
 'io.BackendRendererRenderState' -> 'platform_io.Renderer_RenderState'. 
 (#6969, #5834, #7468, #3590

Amend e94f95d
---
 backends/imgui_impl_dx11.cpp   | 2 +-
 backends/imgui_impl_dx11.h     | 4 ++--
 backends/imgui_impl_dx12.cpp   | 2 +-
 backends/imgui_impl_dx12.h     | 4 ++--
 backends/imgui_impl_vulkan.cpp | 2 +-
 backends/imgui_impl_vulkan.h   | 4 ++--
 backends/imgui_impl_wgpu.cpp   | 2 +-
 backends/imgui_impl_wgpu.h     | 4 ++--
 8 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp
index 088e4b67e78c..16d480e0867b 100644
--- a/backends/imgui_impl_dx11.cpp
+++ b/backends/imgui_impl_dx11.cpp
@@ -4,7 +4,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
-//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_dx11.h b/backends/imgui_impl_dx11.h
index cb79633c3386..57b19bc037ee 100644
--- a/backends/imgui_impl_dx11.h
+++ b/backends/imgui_impl_dx11.h
@@ -4,7 +4,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
-//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -33,7 +33,7 @@ IMGUI_IMPL_API void     ImGui_ImplDX11_InvalidateDeviceObjects();
 IMGUI_IMPL_API bool     ImGui_ImplDX11_CreateDeviceObjects();
 
 // [BETA] Selected render state data shared with callbacks.
-// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplDX11_RenderDrawData() call.
+// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplDX11_RenderDrawData() call.
 // (Please open an issue if you feel you need access to more data)
 struct ImGui_ImplDX11_RenderState
 {
diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index 85a870269855..8dbb1e50838a 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -4,7 +4,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
-//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
 // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h
index bee7454fab33..74001db4011f 100644
--- a/backends/imgui_impl_dx12.h
+++ b/backends/imgui_impl_dx12.h
@@ -4,7 +4,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
-//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
 // See imgui_impl_dx12.cpp file for details.
@@ -44,7 +44,7 @@ IMGUI_IMPL_API void     ImGui_ImplDX12_InvalidateDeviceObjects();
 IMGUI_IMPL_API bool     ImGui_ImplDX12_CreateDeviceObjects();
 
 // [BETA] Selected render state data shared with callbacks.
-// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplDX12_RenderDrawData() call.
+// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplDX12_RenderDrawData() call.
 // (Please open an issue if you feel you need access to more data)
 struct ImGui_ImplDX12_RenderState
 {
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index 31a2516a66b6..d670b82a0089 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -4,7 +4,7 @@
 // Implemented features:
 //  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
-//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
 // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h
index a834d7d7a572..cdbcb0caa473 100644
--- a/backends/imgui_impl_vulkan.h
+++ b/backends/imgui_impl_vulkan.h
@@ -4,7 +4,7 @@
 // Implemented features:
 //  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
-//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
 // See imgui_impl_vulkan.cpp file for details.
@@ -119,7 +119,7 @@ IMGUI_IMPL_API void             ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet d
 IMGUI_IMPL_API bool             ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr);
 
 // [BETA] Selected render state data shared with callbacks.
-// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplVulkan_RenderDrawData() call.
+// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplVulkan_RenderDrawData() call.
 // (Please open an issue if you feel you need access to more data)
 struct ImGui_ImplVulkan_RenderState
 {
diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp
index a4f6c03e5d61..95f1b0c63c0f 100644
--- a/backends/imgui_impl_wgpu.cpp
+++ b/backends/imgui_impl_wgpu.cpp
@@ -5,7 +5,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
-//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h
index a171fd6d0ca0..e4398575c11d 100644
--- a/backends/imgui_impl_wgpu.h
+++ b/backends/imgui_impl_wgpu.h
@@ -12,7 +12,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
-//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -56,7 +56,7 @@ IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
 IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateDeviceObjects();
 
 // [BETA] Selected render state data shared with callbacks.
-// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplWGPU_RenderDrawData() call.
+// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplWGPU_RenderDrawData() call.
 // (Please open an issue if you feel you need access to more data)
 struct ImGui_ImplWGPU_RenderState
 {

From 19b494df89fdba00e903fcd61734eb119ac98bb3 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 8 Oct 2024 12:37:33 +0200
Subject: [PATCH 178/548] Examples: DirectX12: update Windows SDK version.

(VS2015 doesn't support latest)
---
 .../example_win32_directx12/example_win32_directx12.vcxproj     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/example_win32_directx12/example_win32_directx12.vcxproj b/examples/example_win32_directx12/example_win32_directx12.vcxproj
index 7b64371eff84..62191839eec2 100644
--- a/examples/example_win32_directx12/example_win32_directx12.vcxproj
+++ b/examples/example_win32_directx12/example_win32_directx12.vcxproj
@@ -21,7 +21,7 @@
   
     {b4cf9797-519d-4afe-a8f4-5141a6b521d3}
     example_win32_directx12
-    10.0.18362.0
+    10.0.20348.0
   
   
   

From 92b94980c69ff3d3d7f5dc30c1c19abfb72db47e Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 7 Oct 2024 16:45:34 +0200
Subject: [PATCH 179/548] (Breaking) Default ImTextureID to use a Im64 instead
 of void* (#1641)

---
 backends/imgui_impl_dx12.cpp                  | 16 --------
 backends/imgui_impl_dx12.h                    |  3 --
 backends/imgui_impl_vulkan.cpp                |  8 ----
 backends/imgui_impl_vulkan.h                  |  3 --
 docs/CHANGELOG.txt                            | 16 +++++++-
 docs/FAQ.md                                   | 39 ++++++++++---------
 examples/example_glfw_vulkan/CMakeLists.txt   |  2 +-
 examples/example_glfw_vulkan/build_win32.bat  |  4 +-
 examples/example_glfw_vulkan/build_win64.bat  |  4 +-
 .../example_glfw_vulkan.vcxproj               |  8 ++--
 examples/example_sdl2_vulkan/build_win32.bat  |  2 +-
 .../example_sdl2_vulkan.vcxproj               | 10 ++---
 .../example_win32_directx12/build_win32.bat   |  3 +-
 .../example_win32_directx12.vcxproj           |  8 ++--
 examples/example_win32_directx12/main.cpp     |  4 --
 imgui.cpp                                     |  8 ++++
 imgui.h                                       |  4 +-
 imgui_draw.cpp                                |  4 +-
 imgui_widgets.cpp                             |  2 +-
 19 files changed, 69 insertions(+), 79 deletions(-)

diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index 8dbb1e50838a..e9345013c4cc 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -6,14 +6,6 @@
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
-// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
-// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
-// To build this on 32-bit systems:
-// - [Solution 1] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'ImTextureID=ImU64' (this is what we do in the 'example_win32_direct12/example_win32_direct12.vcxproj' project file)
-// - [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like.
-// - [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!)
-// - [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in the example_win32_direct12/build_win32.bat file)
-
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 // Learn about Dear ImGui:
@@ -446,14 +438,6 @@ static void ImGui_ImplDX12_CreateFontsTexture()
     }
 
     // Store our identifier
-    // READ THIS IF THE STATIC_ASSERT() TRIGGERS:
-    // - Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
-    // - This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
-    // [Solution 1] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'ImTextureID=ImU64' (this is what we do in the 'example_win32_direct12/example_win32_direct12.vcxproj' project file)
-    // [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like.
-    // [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!)
-    // [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in the example_win32_direct12/build_win32.bat file)
-    static_assert(sizeof(ImTextureID) >= sizeof(bd->hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID, 32-bit not supported yet.");
     io.Fonts->SetTexID((ImTextureID)bd->hFontSrvGpuDescHandle.ptr);
 }
 
diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h
index 74001db4011f..5da528573429 100644
--- a/backends/imgui_impl_dx12.h
+++ b/backends/imgui_impl_dx12.h
@@ -6,9 +6,6 @@
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
-// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
-// See imgui_impl_dx12.cpp file for details.
-
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 // Learn about Dear ImGui:
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index d670b82a0089..78d8389556ff 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -6,14 +6,6 @@
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
-// Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
-// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
-// To build this on 32-bit systems and support texture changes:
-// - [Solution 1] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'ImTextureID=ImU64' (this is what we do in our .vcxproj files)
-// - [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like.
-// - [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!)
-// - [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in our batch files)
-
 // The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
 // IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
 
diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h
index cdbcb0caa473..ca5b4db64100 100644
--- a/backends/imgui_impl_vulkan.h
+++ b/backends/imgui_impl_vulkan.h
@@ -6,9 +6,6 @@
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
-// Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
-// See imgui_impl_vulkan.cpp file for details.
-
 // The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
 // IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
 
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 48496340be26..96a52ff405c1 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -36,11 +36,25 @@ HOW TO UPDATE?
 - Please report any issue!
 
 -----------------------------------------------------------------------
- VERSION 1.91.4 WIP
+ VERSION 1.91.4 WIP (In Progress)
 -----------------------------------------------------------------------
 
 Breaking changes:
 
+- The typedef for ImTextureID now defaults to ImU64 instead of void*. (#1641)
+  - This removes the requirement to redefine it for backends which are e.g. storing
+    descriptor sets or other 64-bits structures when building on 32-bits archs.
+    It therefore simplify various building scripts/helpers.
+  - You may have compile-time issues if you were casting to 'void*' instead of 'ImTextureID'
+    when passing your types to functions taking ImTextureID values, e.g. ImGui::Image().
+    In doubt it is almost always better to do an intermediate intptr_t cast, since it
+    allows casting any pointer/integer type without warning:
+    - May warn:     ImGui::Image((void*)MyTextureData, ...);
+    - May warn:     ImGui::Image((void*)(intptr_t)MyTextureData, ...);
+    - Won't warn:   ImGui::Image((ImTextureID)(intptr_t)MyTextureData), ...);
+  - Note that you can always define ImTextureID to be your own high-level structures
+    (with dedicated constructors) if you like.
+
 Other changes:
 
 - IO: added 'void* platform_io.Renderer_RenderState' which is set during the
diff --git a/docs/FAQ.md b/docs/FAQ.md
index 4e2a42576352..38600fe47155 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -380,8 +380,9 @@ node open/closed state differently. See what makes more sense in your situation!
 Short explanation:
 - Refer to [Image Loading and Displaying Examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples) on the [Wiki](https://github.com/ocornut/imgui/wiki).
 - You may use functions such as `ImGui::Image()`, `ImGui::ImageButton()` or lower-level `ImDrawList::AddImage()` to emit draw calls that will use your own textures.
-- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value.
-- Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason).
+- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as an opaque ImTextureID value.
+- By default ImTextureID can store up to 64-bits. You may `#define` it to a custom type/structure if you need.
+- Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason), but the examples linked above may be useful references.
 
 **Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.**
 
@@ -389,27 +390,27 @@ Long explanation:
 - Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices. At the end of the frame, those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code to render them is generally fairly short (a few dozen lines). In the examples/ folder, we provide functions for popular graphics APIs (OpenGL, DirectX, etc.).
 - Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API.
  We carry the information to identify a "texture" in the ImTextureID type.
-ImTextureID is nothing more than a void*, aka 4/8 bytes worth of data: just enough to store one pointer or integer of your choice.
+ImTextureID default to ImU64 aka 8 bytes worth of data: just enough to store one pointer or integer of your choice.
 Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely passes ImTextureID values until they reach your rendering function.
 - In the [examples/](https://github.com/ocornut/imgui/tree/master/examples) backends, for each graphics API we decided on a type that is likely to be a good representation for specifying an image from the end-user perspective. This is what the _examples_ rendering functions are using:
 ```cpp
 OpenGL:
-- ImTextureID = GLuint
+- ImTextureID should contains 'GLuint' (GL texture identifier).
 - See ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_opengl3.cpp
 ```
 ```cpp
 DirectX9:
-- ImTextureID = LPDIRECT3DTEXTURE9
+- ImTextureID should contain a 'LPDIRECT3DTEXTURE9' (pointer).
 - See ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp
 ```
 ```cpp
 DirectX11:
-- ImTextureID = ID3D11ShaderResourceView*
+- ImTextureID should contain a 'ID3D11ShaderResourceView*' (poiter)
 - See ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp
 ```
 ```cpp
 DirectX12:
-- ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE
+- ImTextureID should contain a 'D3D12_GPU_DESCRIPTOR_HANDLE' (always 64-bits)
 - See ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp
 ```
 For example, in the OpenGL example backend we store raw OpenGL texture identifier (GLuint) inside ImTextureID.
@@ -421,14 +422,14 @@ If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a
 
 User code may do:
 ```cpp
-// Cast our texture type to ImTextureID / void*
+// Cast our texture type to ImTextureID
 MyTexture* texture = g_CoffeeTableTexture;
-ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
+ImGui::Image((ImTextureID)(intptr_t)texture, ImVec2(texture->Width, texture->Height));
 ```
 The renderer function called after ImGui::Render() will receive that same value that the user code passed:
 ```cpp
-// Cast ImTextureID / void* stored in the draw command as our texture type
-MyTexture* texture = (MyTexture*)pcmd->GetTexID();
+// Cast ImTextureID stored in the draw command as our texture type
+MyTexture* texture = (MyTexture*)(intptr_t)pcmd->GetTexID();
 MyEngineBindTexture2D(texture);
 ```
 Once you understand this design, you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui.
@@ -437,19 +438,19 @@ If you want to display an image file (e.g. PNG file) on the screen, please refer
 
 Refer to [Image Loading and Displaying Examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples) on the [Wiki](https://github.com/ocornut/imgui/wiki) to find simplified examples for loading textures with OpenGL, DirectX9 and DirectX11.
 
-C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTextureID / void*, and vice-versa.
-Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID / void*.
+C/C++ tip: a u64 is 8 bytes. You may safely store any pointer or integer into it by casting your value to ImTextureID, and vice-versa.
+Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID.
 Here are some examples:
 ```cpp
 GLuint my_tex = XXX;
-void* my_void_ptr;
-my_void_ptr = (void*)(intptr_t)my_tex;                  // cast a GLuint into a void* (we don't take its address! we literally store the value inside the pointer)
-my_tex = (GLuint)(intptr_t)my_void_ptr;                 // cast a void* into a GLuint
+ImTextureID my_imtexid;
+my_imtexid = (ImTextureID)(intptr_t)my_tex;                     // cast a GLuint into a ImTextureID (we don't take its address! we just copy the address)
+my_tex = (GLuint)(intptr_t)my_imtexid;                          // cast a ImTextureID into a GLuint
 
 ID3D11ShaderResourceView* my_dx11_srv = XXX;
-void* my_void_ptr;
-my_void_ptr = (void*)my_dx11_srv;                       // cast a ID3D11ShaderResourceView* into an opaque void*
-my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr;   // cast a void* into a ID3D11ShaderResourceView*
+ImTextureID my_imtexid;
+my_imtexid = (ImTextureID)(intptr_t)my_dx11_srv;                // cast a ID3D11ShaderResourceView* into an opaque ImTextureID
+my_dx11_srv = (ID3D11ShaderResourceView*)(intptr_t)_my_imtexid; // cast a ImTextureID into a ID3D11ShaderResourceView*
 ```
 Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understand how the ImDrawList are generated.
 
diff --git a/examples/example_glfw_vulkan/CMakeLists.txt b/examples/example_glfw_vulkan/CMakeLists.txt
index a6e5bf910fdf..443a144eae65 100644
--- a/examples/example_glfw_vulkan/CMakeLists.txt
+++ b/examples/example_glfw_vulkan/CMakeLists.txt
@@ -42,4 +42,4 @@ file(GLOB sources *.cpp)
 
 add_executable(example_glfw_vulkan ${sources} ${IMGUI_DIR}/backends/imgui_impl_glfw.cpp ${IMGUI_DIR}/backends/imgui_impl_vulkan.cpp ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp ${IMGUI_DIR}/imgui_tables.cpp ${IMGUI_DIR}/imgui_widgets.cpp)
 target_link_libraries(example_glfw_vulkan ${LIBRARIES})
-target_compile_definitions(example_glfw_vulkan PUBLIC -DImTextureID=ImU64)
+
diff --git a/examples/example_glfw_vulkan/build_win32.bat b/examples/example_glfw_vulkan/build_win32.bat
index be92398162e1..bb54a4210d17 100644
--- a/examples/example_glfw_vulkan/build_win32.bat
+++ b/examples/example_glfw_vulkan/build_win32.bat
@@ -7,8 +7,8 @@
 
 @set OUT_DIR=Debug
 mkdir %OUT_DIR%
-cl /nologo /Zi /MD /utf-8 %INCLUDES% /D ImTextureID=ImU64 %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
+cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
 
 @set OUT_DIR=Release
 mkdir %OUT_DIR%
-cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% /D ImTextureID=ImU64 %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
+cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/examples/example_glfw_vulkan/build_win64.bat b/examples/example_glfw_vulkan/build_win64.bat
index c60b027893b6..54e40e3e8e0a 100644
--- a/examples/example_glfw_vulkan/build_win64.bat
+++ b/examples/example_glfw_vulkan/build_win64.bat
@@ -6,8 +6,8 @@
 
 @set OUT_DIR=Debug
 mkdir %OUT_DIR%
-cl /nologo /Zi /MD /utf-8 %INCLUDES% /D ImTextureID=ImU64 %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
+cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
 
 @set OUT_DIR=Release
 mkdir %OUT_DIR%
-cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% /D ImTextureID=ImU64 %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
+cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj b/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj
index d0d1c5f88df4..a81d328df976 100644
--- a/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj
+++ b/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj
@@ -91,7 +91,7 @@
       Level4
       Disabled
       ..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)
-      ImTextureID=ImU64;_MBCS;%(PreprocessorDefinitions)
+      _MBCS;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
@@ -107,7 +107,7 @@
       Level4
       Disabled
       ..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)
-      ImTextureID=ImU64;_MBCS;%(PreprocessorDefinitions)
+      _MBCS;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
@@ -126,7 +126,7 @@
       true
       ..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)
       false
-      ImTextureID=ImU64;_MBCS;%(PreprocessorDefinitions)
+      _MBCS;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
@@ -148,7 +148,7 @@
       true
       ..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)
       false
-      ImTextureID=ImU64;_MBCS;%(PreprocessorDefinitions)
+      _MBCS;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
diff --git a/examples/example_sdl2_vulkan/build_win32.bat b/examples/example_sdl2_vulkan/build_win32.bat
index 8a4aefc223bb..977a2c7e4eb1 100644
--- a/examples/example_sdl2_vulkan/build_win32.bat
+++ b/examples/example_sdl2_vulkan/build_win32.bat
@@ -7,4 +7,4 @@
 
 @set OUT_DIR=Debug
 mkdir %OUT_DIR%
-cl /nologo /Zi /MD /utf-8 %INCLUDES% /D ImTextureID=ImU64 %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
+cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj b/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj
index ba6afaf72b70..bcf99a46c002 100644
--- a/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj
+++ b/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj
@@ -91,7 +91,7 @@
       Level4
       Disabled
       ..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)
-      ImTextureID=ImU64;_MBCS;%(PreprocessorDefinitions)
+      _MBCS;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
@@ -107,7 +107,7 @@
       Level4
       Disabled
       ..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)
-      ImTextureID=ImU64;_MBCS;%(PreprocessorDefinitions)
+      _MBCS;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
@@ -126,7 +126,7 @@
       true
       ..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)
       false
-      ImTextureID=ImU64;_MBCS;%(PreprocessorDefinitions)
+      _MBCS;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
@@ -148,7 +148,7 @@
       true
       ..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)
       false
-      ImTextureID=ImU64;_MBCS;%(PreprocessorDefinitions)
+      _MBCS;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
@@ -187,4 +187,4 @@
   
   
   
-
\ No newline at end of file
+
diff --git a/examples/example_win32_directx12/build_win32.bat b/examples/example_win32_directx12/build_win32.bat
index 68e3c921e399..cb5e8e273771 100644
--- a/examples/example_win32_directx12/build_win32.bat
+++ b/examples/example_win32_directx12/build_win32.bat
@@ -1,9 +1,8 @@
 @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
-@REM Important: to build on 32-bit systems, the DX12 backends needs '#define ImTextureID ImU64', so we pass it here.
 @set OUT_DIR=Debug
 @set OUT_EXE=example_win32_directx12
 @set INCLUDES=/I..\.. /I..\..\backends /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared"
 @set SOURCES=main.cpp ..\..\backends\imgui_impl_dx12.cpp ..\..\backends\imgui_impl_win32.cpp ..\..\imgui*.cpp
 @set LIBS=d3d12.lib d3dcompiler.lib dxgi.lib
 mkdir Debug
-cl /nologo /Zi /MD /utf-8 %INCLUDES% /D ImTextureID=ImU64 /D UNICODE /D _UNICODE %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
+cl /nologo /Zi /MD /utf-8 %INCLUDES% /D UNICODE /D _UNICODE %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/examples/example_win32_directx12/example_win32_directx12.vcxproj b/examples/example_win32_directx12/example_win32_directx12.vcxproj
index 62191839eec2..bb98c4141ca1 100644
--- a/examples/example_win32_directx12/example_win32_directx12.vcxproj
+++ b/examples/example_win32_directx12/example_win32_directx12.vcxproj
@@ -87,7 +87,7 @@
       Level4
       Disabled
       ..\..;..\..\backends;%(AdditionalIncludeDirectories)
-      ImTextureID=ImU64;_UNICODE;UNICODE;%(PreprocessorDefinitions)
+      _UNICODE;UNICODE;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
@@ -102,7 +102,7 @@
       Level4
       Disabled
       ..\..;..\..\backends;%(AdditionalIncludeDirectories)
-      ImTextureID=ImU64;_UNICODE;UNICODE;%(PreprocessorDefinitions)
+      _UNICODE;UNICODE;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
@@ -119,7 +119,7 @@
       true
       true
       ..\..;..\..\backends;%(AdditionalIncludeDirectories)
-      ImTextureID=ImU64;_UNICODE;UNICODE;%(PreprocessorDefinitions)
+      _UNICODE;UNICODE;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
@@ -138,7 +138,7 @@
       true
       true
       ..\..;..\..\backends;%(AdditionalIncludeDirectories)
-      ImTextureID=ImU64;_UNICODE;UNICODE;%(PreprocessorDefinitions)
+      _UNICODE;UNICODE;%(PreprocessorDefinitions)
       /utf-8 %(AdditionalOptions)
     
     
diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp
index 57a481c710fc..4173a8010c6b 100644
--- a/examples/example_win32_directx12/main.cpp
+++ b/examples/example_win32_directx12/main.cpp
@@ -6,10 +6,6 @@
 // - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
 // - Introduction, links and more at the top of imgui.cpp
 
-// Important: to compile on 32-bit systems, the DirectX12 backend requires code to be compiled with '#define ImTextureID ImU64'.
-// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
-// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file.
-
 #include "imgui.h"
 #include "imgui_impl_win32.h"
 #include "imgui_impl_dx12.h"
diff --git a/imgui.cpp b/imgui.cpp
index 2d7edc43e390..33170e43044b 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -430,6 +430,14 @@ 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.
 
+ - 2024/10/10 (1.91.4) - the typedef for ImTextureID now defaults to ImU64 instead of void*. (#1641)
+                         this removes the requirement to redefine it for backends which are e.g. storing descriptor sets or other 64-bits structures when building on 32-bits archs. It therefore simplify various building scripts/helpers.
+                         you may have compile-time issues if you were casting to 'void*' instead of 'ImTextureID' when passing your types to functions taking ImTextureID values, e.g. ImGui::Image().
+                         in doubt it is almost always better to do an intermediate intptr_t cast, since it allows casting any pointer/integer type without warning:
+                            - May warn:    ImGui::Image((void*)MyTextureData, ...);
+                            - May warn:    ImGui::Image((void*)(intptr_t)MyTextureData, ...);
+                            - Won't warn:  ImGui::Image((ImTextureID)(intptr_t)MyTextureData), ...);
+  -                      note that you can always define ImTextureID to be your own high-level structures (with dedicated constructors) if you like.
  - 2024/10/03 (1.91.3) - drags: treat v_min==v_max as a valid clamping range when != 0.0f. Zero is a still special value due to legacy reasons, unless using ImGuiSliderFlags_ClampZeroRange. (#7968, #3361, #76)
                        - drags: extended behavior of ImGuiSliderFlags_AlwaysClamp to include _ClampZeroRange. It considers v_min==v_max==0.0f as a valid clamping range (aka edits not allowed).
                          although unlikely, it you wish to only clamp on text input but want v_min==v_max==0.0f to mean unclamped drags, you can use _ClampOnInput instead of _AlwaysClamp. (#7968, #3361, #76)
diff --git a/imgui.h b/imgui.h
index f3d5d83d49ff..87d77c2c2e35 100644
--- a/imgui.h
+++ b/imgui.h
@@ -249,8 +249,10 @@ typedef int ImGuiWindowFlags;       // -> enum ImGuiWindowFlags_     // Flags: f
 // ImTexture: user data for renderer backend to identify a texture [Compile-time configurable type]
 // - To use something else than an opaque void* pointer: override with e.g. '#define ImTextureID MyTextureType*' in your imconfig.h file.
 // - This can be whatever to you want it to be! read the FAQ about ImTextureID for details.
+// - You can make this a structure with various constructors if you need. You will have to implement ==/!= operators.
+// - (note: before v1.91.4 (2024/10/08) the default type for ImTextureID was void*. Use intermediary intptr_t cast and read FAQ if you have casting warnings)
 #ifndef ImTextureID
-typedef void* ImTextureID;          // Default: store a pointer or an integer fitting in a pointer (most renderer backends are ok with that)
+typedef ImU64 ImTextureID;          // Default: store a pointer or an integer fitting in a pointer (most renderer backends are ok with that)
 #endif
 
 // ImDrawIdx: vertex index. [Compile-time configurable type]
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index b69bc789f88f..0c10a79b79cf 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -619,7 +619,7 @@ void ImDrawList::PushTextureID(ImTextureID texture_id)
 void ImDrawList::PopTextureID()
 {
     _TextureIdStack.pop_back();
-    _CmdHeader.TextureId = (_TextureIdStack.Size == 0) ? (ImTextureID)NULL : _TextureIdStack.Data[_TextureIdStack.Size - 1];
+    _CmdHeader.TextureId = (_TextureIdStack.Size == 0) ? ImTextureID() : _TextureIdStack.Data[_TextureIdStack.Size - 1];
     _OnChangedTextureID();
 }
 
@@ -2777,7 +2777,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
     ImFontAtlasBuildInit(atlas);
 
     // Clear atlas
-    atlas->TexID = (ImTextureID)NULL;
+    atlas->TexID = ImTextureID();
     atlas->TexWidth = atlas->TexHeight = 0;
     atlas->TexUvScale = ImVec2(0.0f, 0.0f);
     atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index baaf4f4e7e5f..156e7a813253 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1122,7 +1122,7 @@ bool ImGui::ImageButton(const char* str_id, ImTextureID user_texture_id, const I
 bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col)
 {
     // Default to using texture ID as ID. User can still push string/integer prefixes.
-    PushID((void*)(intptr_t)user_texture_id);
+    PushID((ImTextureID)(intptr_t)user_texture_id);
     if (frame_padding >= 0)
         PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2((float)frame_padding, (float)frame_padding));
     bool ret = ImageButton("", user_texture_id, size, uv0, uv1, bg_col, tint_col);

From 6b8accbfa1bca2d755e6dd14c18da5c17ef61488 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 8 Oct 2024 14:29:21 +0200
Subject: [PATCH 180/548] Fixed building when defining ImTextureID to a
 multi-token name. (#1641)

Amend 92b9498
---
 imgui_draw.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 0c10a79b79cf..b69bc789f88f 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -619,7 +619,7 @@ void ImDrawList::PushTextureID(ImTextureID texture_id)
 void ImDrawList::PopTextureID()
 {
     _TextureIdStack.pop_back();
-    _CmdHeader.TextureId = (_TextureIdStack.Size == 0) ? ImTextureID() : _TextureIdStack.Data[_TextureIdStack.Size - 1];
+    _CmdHeader.TextureId = (_TextureIdStack.Size == 0) ? (ImTextureID)NULL : _TextureIdStack.Data[_TextureIdStack.Size - 1];
     _OnChangedTextureID();
 }
 
@@ -2777,7 +2777,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
     ImFontAtlasBuildInit(atlas);
 
     // Clear atlas
-    atlas->TexID = ImTextureID();
+    atlas->TexID = (ImTextureID)NULL;
     atlas->TexWidth = atlas->TexHeight = 0;
     atlas->TexUvScale = ImVec2(0.0f, 0.0f);
     atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);

From c3629adbeb22740c7f352a0dcc17870b80630e37 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 8 Oct 2024 14:33:17 +0200
Subject: [PATCH 181/548] Backends: Metal: fixed ImTextureID cast. (#1641)

Amend 92b9498
---
 backends/imgui_impl_metal.mm | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm
index 818961048abb..b8f82a65ded5 100644
--- a/backends/imgui_impl_metal.mm
+++ b/backends/imgui_impl_metal.mm
@@ -291,7 +291,7 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData, id c
 
                 // Bind texture, Draw
                 if (ImTextureID tex_id = pcmd->GetTexID())
-                    [commandEncoder setFragmentTexture:(__bridge id)(tex_id) atIndex:0];
+                    [commandEncoder setFragmentTexture:(__bridge id)(void*)(intptr_t)(tex_id) atIndex:0];
 
                 [commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0];
                 [commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
@@ -347,7 +347,7 @@ bool ImGui_ImplMetal_CreateFontsTexture(id device)
     id  texture = [device newTextureWithDescriptor:textureDescriptor];
     [texture replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)width, (NSUInteger)height) mipmapLevel:0 withBytes:pixels bytesPerRow:(NSUInteger)width * 4];
     bd->SharedMetalContext.fontTexture = texture;
-    io.Fonts->SetTexID((__bridge void*)bd->SharedMetalContext.fontTexture); // ImTextureID == void*
+    io.Fonts->SetTexID((ImTextureID)(intptr_t)(__bridge void*)bd->SharedMetalContext.fontTexture); // ImTextureID == ImU64
 
     return (bd->SharedMetalContext.fontTexture != nil);
 }

From f3d242a90d645dec043d63d128015c87f0ac9fe8 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 8 Oct 2024 19:45:58 +0200
Subject: [PATCH 182/548] Tables: fixed initial auto-sizing issue with
 synched-instances. (#8045, #7218)

---
 docs/CHANGELOG.txt | 1 +
 imgui.h            | 2 +-
 imgui_tables.cpp   | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 96a52ff405c1..32818837fd0b 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -60,6 +60,7 @@ Other changes:
 - IO: added 'void* platform_io.Renderer_RenderState' which is set during the
   ImGui_ImplXXXX_RenderDrawData() of standard backend to expose selected render
   state to draw callbacks. (#6969, #5834, #7468, #3590)
+- Tables: fixed initial auto-sizing issue with synched-instances. (#8045, #7218)
 - Backends: DX11, DX12, Vulkan, WGPU: expose selected state in ImGui_ImplXXXX_RenderState.
   structure during render loop. (#6969, #5834, #7468, #3590)
 - Backends: DX9, DX10, DX11, DX12, OpenGL, Vulkan, WGPU: Changed default texture sampler
diff --git a/imgui.h b/imgui.h
index 87d77c2c2e35..8cda26dea3d5 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.4 WIP"
-#define IMGUI_VERSION_NUM   19131
+#define IMGUI_VERSION_NUM   19132
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index 491566d7af9e..3ba15fef5ac6 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1160,7 +1160,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
         }
 
         // Don't decrement auto-fit counters until container window got a chance to submit its items
-        if (table->HostSkipItems == false)
+        if (table->HostSkipItems == false && table->InstanceCurrent == 0)
         {
             column->AutoFitQueue >>= 1;
             column->CannotSkipItemsQueue >>= 1;

From 661bba09ce1fc815765d662fa982bc1d1d3f8c6e Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 9 Oct 2024 13:54:39 +0200
Subject: [PATCH 183/548] InputText: fixed an issue with not declaring
 ownership of Delete/Backspace/Arrow keys. (#8048)

---
 docs/CHANGELOG.txt | 4 +++-
 docs/README.md     | 2 +-
 imgui_widgets.cpp  | 8 ++++++++
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 32818837fd0b..1af37fc5f4ed 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -61,10 +61,12 @@ Other changes:
   ImGui_ImplXXXX_RenderDrawData() of standard backend to expose selected render
   state to draw callbacks. (#6969, #5834, #7468, #3590)
 - Tables: fixed initial auto-sizing issue with synched-instances. (#8045, #7218)
+- InputText: fixed an issue with not declaring ownership of Delete/Backspace/Arrow keys,
+  preventing use of external shortcuts not guarded by an ActiveId check. (#8048) [@geertbleyen]
 - Backends: DX11, DX12, Vulkan, WGPU: expose selected state in ImGui_ImplXXXX_RenderState.
   structure during render loop. (#6969, #5834, #7468, #3590)
 - Backends: DX9, DX10, DX11, DX12, OpenGL, Vulkan, WGPU: Changed default texture sampler
-  to Clamp instead of Repeat/Wrap. (#7468, #7511, #5999, #5502)
+  to Clamp instead of Repeat/Wrap. (#7468, #7511, #5999, #5502, #7230)
 
 
 -----------------------------------------------------------------------
diff --git a/docs/README.md b/docs/README.md
index 0968727f19c1..c47f03b9bc5c 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -196,7 +196,7 @@ Ongoing Dear ImGui development is and has been financially supported by users an
 **THANK YOU to all past and present supporters for helping to keep this project alive and thriving!**
 
 Dear ImGui is using software and services provided free of charge for open source projects:
-- [PVS-Studio](https://www.viva64.com/en/b/0570/) for static analysis.
+- [PVS-Studio](https://pvs-studio.com/en/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) for static analysis (supports C/C++/C#/Java).
 - [GitHub actions](https://github.com/features/actions) for continuous integration systems.
 - [OpenCppCoverage](https://github.com/OpenCppCoverage/OpenCppCoverage) for code coverage analysis.
 
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 156e7a813253..4f6315879ac8 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4569,10 +4569,18 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         if (user_clicked)
             SetKeyOwner(ImGuiKey_MouseLeft, id);
         g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
+        SetKeyOwner(ImGuiKey_LeftArrow, id);
+        SetKeyOwner(ImGuiKey_RightArrow, id);
         if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory))
+        {
             g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
+            SetKeyOwner(ImGuiKey_UpArrow, id);
+            SetKeyOwner(ImGuiKey_DownArrow, id);
+        }
         SetKeyOwner(ImGuiKey_Enter, id);
         SetKeyOwner(ImGuiKey_KeypadEnter, id);
+        SetKeyOwner(ImGuiKey_Delete, id);
+        SetKeyOwner(ImGuiKey_Backspace, id);
         SetKeyOwner(ImGuiKey_Home, id);
         SetKeyOwner(ImGuiKey_End, id);
         if (is_multiline)

From 9fbc3134591bdca66d548a97f284c3a5e2811b6f Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 9 Oct 2024 14:01:47 +0200
Subject: [PATCH 184/548] InputText: amend 661bba0. (#8048)

---
 imgui_widgets.cpp | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 4f6315879ac8..9d4ef66dabd2 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4566,23 +4566,19 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     if (g.ActiveId == id)
     {
         // Declare some inputs, the other are registered and polled via Shortcut() routing system.
+        // FIXME: The reason we don't use Shortcut() is we would need a routing flag to specify multiple mods, or to all mods combinaison into individual shortcuts.
+        const ImGuiKey always_owned_keys[] = { ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_Enter, ImGuiKey_KeypadEnter, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Home, ImGuiKey_End };
+        for (ImGuiKey key : always_owned_keys)
+            SetKeyOwner(key, id);
         if (user_clicked)
             SetKeyOwner(ImGuiKey_MouseLeft, id);
         g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
-        SetKeyOwner(ImGuiKey_LeftArrow, id);
-        SetKeyOwner(ImGuiKey_RightArrow, id);
         if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory))
         {
             g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
             SetKeyOwner(ImGuiKey_UpArrow, id);
             SetKeyOwner(ImGuiKey_DownArrow, id);
         }
-        SetKeyOwner(ImGuiKey_Enter, id);
-        SetKeyOwner(ImGuiKey_KeypadEnter, id);
-        SetKeyOwner(ImGuiKey_Delete, id);
-        SetKeyOwner(ImGuiKey_Backspace, id);
-        SetKeyOwner(ImGuiKey_Home, id);
-        SetKeyOwner(ImGuiKey_End, id);
         if (is_multiline)
         {
             SetKeyOwner(ImGuiKey_PageUp, id);

From a0b811dd37392121227dce75710580834eff2294 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 9 Oct 2024 16:39:28 +0200
Subject: [PATCH 185/548] Backends: SDLRenderer2/3: expose selected state in
 ImGui_ImplXXXX_RenderState structures during render loop. (#6969, #5834,
 #7468, #3590 + #7616)

---
 backends/imgui_impl_sdlrenderer2.cpp | 13 ++++++++++++-
 backends/imgui_impl_sdlrenderer2.h   |  9 +++++++++
 backends/imgui_impl_sdlrenderer3.cpp | 13 ++++++++++++-
 backends/imgui_impl_sdlrenderer3.h   |  9 +++++++++
 docs/CHANGELOG.txt                   |  4 ++--
 5 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp
index 8203c6cafbc6..27c9522697a6 100644
--- a/backends/imgui_impl_sdlrenderer2.cpp
+++ b/backends/imgui_impl_sdlrenderer2.cpp
@@ -10,6 +10,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -20,6 +21,7 @@
 // - Introduction, links and more at the top of imgui.cpp
 
 // CHANGELOG
+//  2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer2_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2024-05-14: *BREAKING CHANGE* ImGui_ImplSDLRenderer3_RenderDrawData() requires SDL_Renderer* passed as parameter.
 //  2023-05-30: Renamed imgui_impl_sdlrenderer.h/.cpp to imgui_impl_sdlrenderer2.h/.cpp to accommodate for upcoming SDL3.
 //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
@@ -140,12 +142,20 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
     SDL_RenderGetViewport(renderer, &old.Viewport);
     SDL_RenderGetClipRect(renderer, &old.ClipRect);
 
+    // Setup desired state
+    ImGui_ImplSDLRenderer2_SetupRenderState(renderer);
+
+    // Setup render state structure (for callbacks and custom texture bindings)
+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
+    ImGui_ImplSDLRenderer2_RenderState render_state;
+    render_state.Renderer = renderer;
+    platform_io.Renderer_RenderState = &render_state;
+
 	// Will project scissor/clipping rectangles into framebuffer space
 	ImVec2 clip_off = draw_data->DisplayPos;         // (0,0) unless using multi-viewports
 	ImVec2 clip_scale = render_scale;
 
     // Render command lists
-    ImGui_ImplSDLRenderer2_SetupRenderState(renderer);
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
         const ImDrawList* draw_list = draw_data->CmdLists[n];
@@ -198,6 +208,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
             }
         }
     }
+    platform_io.Renderer_RenderState = NULL;
 
     // Restore modified SDL_Renderer state
     SDL_RenderSetViewport(renderer, &old.Viewport);
diff --git a/backends/imgui_impl_sdlrenderer2.h b/backends/imgui_impl_sdlrenderer2.h
index c067eaeead19..804ca183d14a 100644
--- a/backends/imgui_impl_sdlrenderer2.h
+++ b/backends/imgui_impl_sdlrenderer2.h
@@ -10,6 +10,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -37,4 +38,12 @@ IMGUI_IMPL_API void     ImGui_ImplSDLRenderer2_DestroyFontsTexture();
 IMGUI_IMPL_API bool     ImGui_ImplSDLRenderer2_CreateDeviceObjects();
 IMGUI_IMPL_API void     ImGui_ImplSDLRenderer2_DestroyDeviceObjects();
 
+// [BETA] Selected render state data shared with callbacks.
+// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplSDLRenderer2_RenderDrawData() call.
+// (Please open an issue if you feel you need access to more data)
+struct ImGui_ImplSDLRenderer2_RenderState
+{
+    SDL_Renderer*       Renderer;
+};
+
 #endif // #ifndef IMGUI_DISABLE
diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp
index 9397a6467e42..5dabea199647 100644
--- a/backends/imgui_impl_sdlrenderer3.cpp
+++ b/backends/imgui_impl_sdlrenderer3.cpp
@@ -12,6 +12,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -22,6 +23,7 @@
 // - Introduction, links and more at the top of imgui.cpp
 
 // CHANGELOG
+//  2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer3_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2024-07-01: Update for SDL3 api changes: SDL_RenderGeometryRaw() uint32 version was removed (SDL#9009).
 //  2024-05-14: *BREAKING CHANGE* ImGui_ImplSDLRenderer3_RenderDrawData() requires SDL_Renderer* passed as parameter.
 //  2024-02-12: Amend to query SDL_RenderViewportSet() and restore viewport accordingly.
@@ -163,12 +165,20 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
     SDL_GetRenderViewport(renderer, &old.Viewport);
     SDL_GetRenderClipRect(renderer, &old.ClipRect);
 
+    // Setup desired state
+    ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
+
+    // Setup render state structure (for callbacks and custom texture bindings)
+    ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
+    ImGui_ImplSDLRenderer3_RenderState render_state;
+    render_state.Renderer = renderer;
+    platform_io.Renderer_RenderState = &render_state;
+
 	// Will project scissor/clipping rectangles into framebuffer space
 	ImVec2 clip_off = draw_data->DisplayPos;         // (0,0) unless using multi-viewports
 	ImVec2 clip_scale = render_scale;
 
     // Render command lists
-    ImGui_ImplSDLRenderer3_SetupRenderState(renderer);
     for (int n = 0; n < draw_data->CmdListsCount; n++)
     {
         const ImDrawList* draw_list = draw_data->CmdLists[n];
@@ -217,6 +227,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
             }
         }
     }
+    platform_io.Renderer_RenderState = NULL;
 
     // Restore modified SDL_Renderer state
     SDL_SetRenderViewport(renderer, old.ViewportEnabled ? &old.Viewport : nullptr);
diff --git a/backends/imgui_impl_sdlrenderer3.h b/backends/imgui_impl_sdlrenderer3.h
index 6c23deca9257..7d4c609e8b25 100644
--- a/backends/imgui_impl_sdlrenderer3.h
+++ b/backends/imgui_impl_sdlrenderer3.h
@@ -12,6 +12,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@@ -39,4 +40,12 @@ IMGUI_IMPL_API void     ImGui_ImplSDLRenderer3_DestroyFontsTexture();
 IMGUI_IMPL_API bool     ImGui_ImplSDLRenderer3_CreateDeviceObjects();
 IMGUI_IMPL_API void     ImGui_ImplSDLRenderer3_DestroyDeviceObjects();
 
+// [BETA] Selected render state data shared with callbacks.
+// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplSDLRenderer3_RenderDrawData() call.
+// (Please open an issue if you feel you need access to more data)
+struct ImGui_ImplSDLRenderer3_RenderState
+{
+    SDL_Renderer*       Renderer;
+};
+
 #endif // #ifndef IMGUI_DISABLE
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 1af37fc5f4ed..427086625137 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -63,8 +63,8 @@ Other changes:
 - Tables: fixed initial auto-sizing issue with synched-instances. (#8045, #7218)
 - InputText: fixed an issue with not declaring ownership of Delete/Backspace/Arrow keys,
   preventing use of external shortcuts not guarded by an ActiveId check. (#8048) [@geertbleyen]
-- Backends: DX11, DX12, Vulkan, WGPU: expose selected state in ImGui_ImplXXXX_RenderState.
-  structure during render loop. (#6969, #5834, #7468, #3590)
+- Backends: DX11, DX12, SDLRenderer2/3. Vulkan, WGPU: expose selected state in
+  ImGui_ImplXXXX_RenderState structures during render loop. (#6969, #5834, #7468, #3590)
 - Backends: DX9, DX10, DX11, DX12, OpenGL, Vulkan, WGPU: Changed default texture sampler
   to Clamp instead of Repeat/Wrap. (#7468, #7511, #5999, #5502, #7230)
 

From f29e505d94ed41e556945ec0f9f29c07cf6c412c Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 9 Oct 2024 17:14:44 +0200
Subject: [PATCH 186/548] CI: remove --disableLicenseExpirationCheck.

---
 .github/workflows/static-analysis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
index 99b058c91a2b..69df5cdf8031 100644
--- a/.github/workflows/static-analysis.yml
+++ b/.github/workflows/static-analysis.yml
@@ -42,5 +42,5 @@ jobs:
           fi
           cd examples/example_null
           pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1
-          pvs-studio-analyzer analyze --disableLicenseExpirationCheck -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
+          pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
           plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log

From 98d52b7b26cccae5d3523bbefddbcb8da627e130 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 11 Oct 2024 13:29:13 +0200
Subject: [PATCH 187/548] DrawList: AddCallback() added an optional size
 parameter allowing to copy and store any amount of user data for usage by
 callbacks: (#6969, #4770, #7665)

---
 docs/CHANGELOG.txt |  8 ++++++++
 docs/TODO.txt      |  5 ++---
 imgui.h            | 23 ++++++++++++++++++-----
 imgui_draw.cpp     | 30 ++++++++++++++++++++++++++++--
 4 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 427086625137..4fda69c0e3d8 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -60,6 +60,14 @@ Other changes:
 - IO: added 'void* platform_io.Renderer_RenderState' which is set during the
   ImGui_ImplXXXX_RenderDrawData() of standard backend to expose selected render
   state to draw callbacks. (#6969, #5834, #7468, #3590)
+- DrawList: AddCallback() added an optional size parameter allowing to copy and
+  store any amount of user data for usage by callbacks: (#6969, #4770, #7665)
+  - If userdata_size == 0: we copy/store the 'userdata' argument as-is (existing behavior).
+    It will be available unmodified in ImDrawCmd::UserCallbackData during render.
+  - If userdata_size > 0, we copy/store 'userdata_size' bytes pointed to by 'userdata' (new behavior).
+    We store them in a buffer stored inside the drawlist. ImDrawCmd::UserCallbackData 
+    will point inside that buffer so you have to retrieve data from there. Your callback
+    may need to use ImDrawCmd::UserCallbackDataSize if you expect dynamically-sized data.
 - Tables: fixed initial auto-sizing issue with synched-instances. (#8045, #7218)
 - InputText: fixed an issue with not declaring ownership of Delete/Backspace/Arrow keys,
   preventing use of external shortcuts not guarded by an ActiveId check. (#8048) [@geertbleyen]
diff --git a/docs/TODO.txt b/docs/TODO.txt
index ddceb3b3d9bb..e61501d78624 100644
--- a/docs/TODO.txt
+++ b/docs/TODO.txt
@@ -9,8 +9,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
  - doc: add a proper documentation system (maybe relying on automation? #435)
  - doc: checklist app to verify backends/integration of imgui (test inputs, rendering, callback, etc.).
  - doc/tips: tips of the day: website? applet in imgui_club?
- - doc/wiki: work on the wiki https://github.com/ocornut/imgui/wiki
-
+ 
  - window: preserve/restore relative focus ordering (persistent or not), and e.g. of multiple reappearing windows (#2304) -> also see docking reference to same #.
  - window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis). (#690)
  - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass.
@@ -44,7 +43,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
  - drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). (WIP branch)
  - drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally
  - drawlist: non-AA strokes have gaps between points (#593, #288), glitch especially on RenderCheckmark() and ColorPicker4().
- - drawlist: callback: add an extra void* in ImDrawCallback to allow passing render-local data to the callback (would break API).
+ - drawlist: callback: add an extra void* in ImDrawCallback to expose render state instead of pulling from Renderer_RenderState (would break API).
  - drawlist: AddRect vs AddLine position confusing (#2441)
  - drawlist/opt: store rounded corners in texture to use 1 quad per corner (filled and wireframe) to lower the cost of rounding. (#1962)
  - drawlist/opt: AddRect() axis aligned pixel aligned (no-aa) could use 8 triangles instead of 16 and no normal calculation.
diff --git a/imgui.h b/imgui.h
index 8cda26dea3d5..d18879ce1308 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.4 WIP"
-#define IMGUI_VERSION_NUM   19132
+#define IMGUI_VERSION_NUM   19133
 #define IMGUI_HAS_TABLE
 
 /*
@@ -2953,9 +2953,11 @@ struct ImDrawCmd
     unsigned int    IdxOffset;          // 4    // Start offset in index buffer.
     unsigned int    ElemCount;          // 4    // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[].
     ImDrawCallback  UserCallback;       // 4-8  // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally.
-    void*           UserCallbackData;   // 4-8  // The draw callback code can access this.
+    void*           UserCallbackData;   // 4-8  // Callback user data (when UserCallback != NULL). If called AddCallback() with size == 0, this is a copy of the AddCallback() argument. If called AddCallback() with size > 0, this is pointing to a buffer where data is stored.
+    int             UserCallbackDataSize;  // 4 // Size of callback user data when using storage, otherwise 0.
+    int             UserCallbackDataOffset;// 4 // [Internal] Offset of callback user data when using storage, otherwise -1.
 
-    ImDrawCmd() { memset(this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed
+    ImDrawCmd()     { memset(this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed
 
     // Since 1.83: returns ImTextureID associated with this draw call. Warning: DO NOT assume this is always same as 'TextureId' (we will change this function for an upcoming feature)
     inline ImTextureID GetTexID() const { return TextureId; }
@@ -3068,6 +3070,7 @@ struct ImDrawList
     ImDrawListSplitter      _Splitter;          // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!)
     ImVector        _ClipRectStack;     // [Internal]
     ImVector   _TextureIdStack;    // [Internal]
+    ImVector          _CallbacksDataBuf;  // [Internal]
     float                   _FringeScale;       // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content
     const char*             _OwnerName;         // Pointer to owner window's name for debugging
 
@@ -3140,8 +3143,18 @@ struct ImDrawList
     IMGUI_API void  PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments = 0);               // Quadratic Bezier (3 control points)
     IMGUI_API void  PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawFlags flags = 0);
 
-    // Advanced
-    IMGUI_API void  AddCallback(ImDrawCallback callback, void* callback_data);  // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles.
+    // Advanced: Draw Callbacks
+    // - May be used to alter render state (change sampler, blending, current shader). May be used to emit custom rendering commands (difficult to do correctly, but possible).
+    // - Use special ImDrawCallback_ResetRenderState callback to instruct backend to reset its render state to the default.
+    // - Your rendering loop must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. All standard backends are honoring this.
+    // - For some backends, the callback may access selected render-states exposed by the backend in a ImGui_ImplXXXX_RenderState structure pointed to by platform_io.Renderer_RenderState.
+    // - IMPORTANT: please be mindful of the different level of indirection between using size==0 (copying argument) and using size>0 (copying pointed data into a buffer).
+    //   - If userdata_size == 0: we copy/store the 'userdata' argument as-is. It will be available unmodified in ImDrawCmd::UserCallbackData during render.
+    //   - If userdata_size > 0,  we copy/store 'userdata_size' bytes pointed to by 'userdata'. We store them in a buffer stored inside the drawlist. ImDrawCmd::UserCallbackData will point inside that buffer so you have to retrieve data from there. Your callback may need to use ImDrawCmd::UserCallbackDataSize if you expect dynamically-sized data.
+    //   - Support for userdata_size > 0 was added in v1.91.4, October 2024. So earlier code always only allowed to copy/store a simple void*.
+    IMGUI_API void  AddCallback(ImDrawCallback callback, void* userdata, size_t userdata_size = 0);
+
+    // Advanced: Miscellaneous
     IMGUI_API void  AddDrawCmd();                                               // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible
     IMGUI_API ImDrawList* CloneOutput() const;                                  // Create a clone of the CmdBuffer/IdxBuffer/VtxBuffer.
 
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index b69bc789f88f..efee2ec9c58e 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -414,6 +414,7 @@ void ImDrawList::_ResetForNewFrame()
     _IdxWritePtr = NULL;
     _ClipRectStack.resize(0);
     _TextureIdStack.resize(0);
+    _CallbacksDataBuf.resize(0);
     _Path.resize(0);
     _Splitter.Clear();
     CmdBuffer.push_back(ImDrawCmd());
@@ -431,6 +432,7 @@ void ImDrawList::_ClearFreeMemory()
     _IdxWritePtr = NULL;
     _ClipRectStack.clear();
     _TextureIdStack.clear();
+    _CallbacksDataBuf.clear();
     _Path.clear();
     _Splitter.ClearFreeMemory();
 }
@@ -470,7 +472,7 @@ void ImDrawList::_PopUnusedDrawCmd()
     }
 }
 
-void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
+void ImDrawList::AddCallback(ImDrawCallback callback, void* userdata, size_t userdata_size)
 {
     IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
     ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
@@ -480,8 +482,26 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
         AddDrawCmd();
         curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
     }
+
     curr_cmd->UserCallback = callback;
-    curr_cmd->UserCallbackData = callback_data;
+    if (userdata_size == 0)
+    {
+        // Store user data directly in command (no indirection)
+        curr_cmd->UserCallbackData = userdata;
+        curr_cmd->UserCallbackDataSize = 0;
+        curr_cmd->UserCallbackDataOffset = -1;
+    }
+    else
+    {
+        // Copy and store user data in a buffer
+        IM_ASSERT(userdata != NULL);
+        IM_ASSERT(userdata_size < (1u << 31));
+        curr_cmd->UserCallbackData = NULL; // Will be resolved during Render()
+        curr_cmd->UserCallbackDataSize = (int)userdata_size;
+        curr_cmd->UserCallbackDataOffset = _CallbacksDataBuf.Size;
+        _CallbacksDataBuf.resize(_CallbacksDataBuf.Size + (int)userdata_size);
+        memcpy(_CallbacksDataBuf.Data + (size_t)curr_cmd->UserCallbackDataOffset, userdata, userdata_size);
+    }
 
     AddDrawCmd(); // Force a new command after us (see comment below)
 }
@@ -2222,6 +2242,12 @@ void ImGui::AddDrawListToDrawDataEx(ImDrawData* draw_data, ImVector
     if (sizeof(ImDrawIdx) == 2)
         IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
 
+    // Resolve callback data pointers
+    if (draw_list->_CallbacksDataBuf.Size > 0)
+        for (ImDrawCmd& cmd : draw_list->CmdBuffer)
+            if (cmd.UserCallback != NULL && cmd.UserCallbackDataOffset != -1 && cmd.UserCallbackDataSize > 0)
+                cmd.UserCallbackData = draw_list->_CallbacksDataBuf.Data + cmd.UserCallbackDataOffset;
+
     // Add to output list + records state in ImDrawData
     out_list->push_back(draw_list);
     draw_data->CmdListsCount++;

From c4bc6744824de148c3f825ffdcde785510e208ac Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 11 Oct 2024 15:31:01 +0200
Subject: [PATCH 188/548] IO: WantCaptureKeyboard is never set when
 ImGuiConfigFlags_NoKeyboard is enabled. (#4921)

+ Retroactively add missing changelog item in 1.90
+ Backends: Vulkan: use GetTexID() for consistency.
---
 backends/imgui_impl_vulkan.cpp |  4 ++--
 docs/CHANGELOG.txt             |  2 ++
 imgui.cpp                      | 11 ++++++++---
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index 78d8389556ff..a68f862b1b68 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -589,11 +589,11 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
                 vkCmdSetScissor(command_buffer, 0, 1, &scissor);
 
                 // Bind DescriptorSet with font or user texture
-                VkDescriptorSet desc_set[1] = { (VkDescriptorSet)pcmd->TextureId };
+                VkDescriptorSet desc_set[1] = { (VkDescriptorSet)pcmd->GetTexID() };
                 if (sizeof(ImTextureID) < sizeof(ImU64))
                 {
                     // We don't support texture switches if ImTextureID hasn't been redefined to be 64-bit. Do a flaky check that other textures haven't been used.
-                    IM_ASSERT(pcmd->TextureId == (ImTextureID)bd->FontDescriptorSet);
+                    IM_ASSERT(pcmd->GetTexID() == (ImTextureID)bd->FontDescriptorSet);
                     desc_set[0] = bd->FontDescriptorSet;
                 }
                 vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, nullptr);
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 4fda69c0e3d8..8178df1f9318 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -60,6 +60,7 @@ Other changes:
 - IO: added 'void* platform_io.Renderer_RenderState' which is set during the
   ImGui_ImplXXXX_RenderDrawData() of standard backend to expose selected render
   state to draw callbacks. (#6969, #5834, #7468, #3590)
+- IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
 - DrawList: AddCallback() added an optional size parameter allowing to copy and
   store any amount of user data for usage by callbacks: (#6969, #4770, #7665)
   - If userdata_size == 0: we copy/store the 'userdata' argument as-is (existing behavior).
@@ -480,6 +481,7 @@ Other changes:
   which was pressed over void/underlying app, which is consistent/needed to allow the
   mouse up event of a drag over void/underlying app to catch release. (#1392) [@Moka42]
 - IO: Added io.ClearInputMouse() to clear mouse state. (#4921)
+- IO: Added ImGuiConfigFlags_NoKeyboard for consistency and convenience. (#4921)
 - Windows: BeginChild(): fixed a glitch when during a resize of a child window which is
   tightly close to the boundaries of its parent (e.g. with zero WindowPadding), the child
   position could have temporarily be moved around by erroneous padding application. (#7706)
diff --git a/imgui.cpp b/imgui.cpp
index 33170e43044b..0b2d787c4aa9 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4998,9 +4998,14 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
     }
 
     // Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to Dear ImGui only, false = dispatch keyboard info to Dear ImGui + underlying app)
-    io.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL);
-    if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
-        io.WantCaptureKeyboard = true;
+    io.WantCaptureKeyboard = false;
+    if ((io.ConfigFlags & ImGuiConfigFlags_NoKeyboard) == 0)
+    {
+        if ((g.ActiveId != 0) || (modal_window != NULL))
+            io.WantCaptureKeyboard = true;
+        else if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
+            io.WantCaptureKeyboard = true;
+    }
     if (g.WantCaptureKeyboardNextFrame != -1) // Manual override
         io.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0);
 

From 20ae8bd4c32fbeb048312ad23bc71dcf8a87fa89 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 10:22:24 +0200
Subject: [PATCH 189/548] Error Handling: turned
 IsItemHovered()/IsWindowHovered() checks into IM_ASSERT_USER_ERROR. (#1651)

---
 docs/CHANGELOG.txt | 1 +
 imgui.cpp          | 8 +++-----
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 8178df1f9318..977db92e68bf 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -61,6 +61,7 @@ Other changes:
   ImGui_ImplXXXX_RenderDrawData() of standard backend to expose selected render
   state to draw callbacks. (#6969, #5834, #7468, #3590)
 - IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
+- Error Handling: turned a few more functions into recoverable errors. (#1651)
 - DrawList: AddCallback() added an optional size parameter allowing to copy and
   store any amount of user data for usage by callbacks: (#6969, #4770, #7665)
   - If userdata_size == 0: we copy/store the 'userdata' argument as-is (existing behavior).
diff --git a/imgui.cpp b/imgui.cpp
index 0b2d787c4aa9..3bd7a473a8e8 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4433,7 +4433,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
 {
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
-    IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0 && "Invalid flags for IsItemHovered()!");
+    IM_ASSERT_USER_ERROR((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0, "Invalid flags for IsItemHovered()!");
 
     if (g.NavDisableMouseHover && !g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride))
     {
@@ -4455,8 +4455,6 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
         if (flags & ImGuiHoveredFlags_ForTooltip)
             flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipMouse);
 
-        IM_ASSERT((flags & (ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy)) == 0);   // Flags not supported by this function
-
         // Done with rectangle culling so we can perform heavier checks now
         // Test if we are hovering the right window (our window could be behind another window)
         // [2021/03/02] Reworked / reverted the revert, finally. Note we want e.g. BeginGroup/ItemAdd/EndGroup to work as well. (#3851)
@@ -8143,9 +8141,9 @@ bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_b
 // Refer to FAQ entry "How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?" for details.
 bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
 {
-    IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsWindowHovered) == 0 && "Invalid flags for IsWindowHovered()!");
-
     ImGuiContext& g = *GImGui;
+    IM_ASSERT_USER_ERROR((flags & ~ImGuiHoveredFlags_AllowedMaskForIsWindowHovered) == 0, "Invalid flags for IsWindowHovered()!");
+
     ImGuiWindow* ref_window = g.HoveredWindow;
     ImGuiWindow* cur_window = g.CurrentWindow;
     if (ref_window == NULL)

From 349af8766cbb6ea7e56b242b18be8476bebbe977 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 13:52:40 +0200
Subject: [PATCH 190/548] InputText: ensure mouse cursor is set regardless of
 whether keyboard mode is enabled or not. (#6417)

+ Nav comments (#8059)
---
 docs/CHANGELOG.txt | 2 ++
 imgui.cpp          | 5 ++++-
 imgui_internal.h   | 1 +
 imgui_widgets.cpp  | 6 +++++-
 4 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 977db92e68bf..a01d5d6bc6f3 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -73,6 +73,8 @@ Other changes:
 - Tables: fixed initial auto-sizing issue with synched-instances. (#8045, #7218)
 - InputText: fixed an issue with not declaring ownership of Delete/Backspace/Arrow keys,
   preventing use of external shortcuts not guarded by an ActiveId check. (#8048) [@geertbleyen]
+- InputText: ensure mouse cursor shape is set regardless of whether keyboard mode is 
+  enabled or not. (#6417)
 - Backends: DX11, DX12, SDLRenderer2/3. Vulkan, WGPU: expose selected state in
   ImGui_ImplXXXX_RenderState structures during render loop. (#6969, #5834, #7468, #3590)
 - Backends: DX9, DX10, DX11, DX12, OpenGL, Vulkan, WGPU: Changed default texture sampler
diff --git a/imgui.cpp b/imgui.cpp
index 3bd7a473a8e8..971f48f16fc2 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4606,7 +4606,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
     }
 #endif
 
-    if (g.NavDisableMouseHover)
+    if (g.NavDisableMouseHover && (item_flags & ImGuiItemFlags_NoNavDisableMouseHover) == 0)
         return false;
 
     return true;
@@ -13340,8 +13340,11 @@ static void ImGui::NavUpdateCancelRequest()
     else
     {
         // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
+        // FIXME-NAV: This should happen on window appearing.
         if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
             g.NavWindow->NavLastIds[0] = 0;
+
+        // Clear nav focus
         g.NavId = 0;
     }
 }
diff --git a/imgui_internal.h b/imgui_internal.h
index 05378c3d9b9b..5722291afc97 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -833,6 +833,7 @@ enum ImGuiItemFlagsPrivate_
     ImGuiItemFlags_MixedValue               = 1 << 12, // false     // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
     ImGuiItemFlags_NoWindowHoverableCheck   = 1 << 13, // false     // Disable hoverable check in ItemHoverable()
     ImGuiItemFlags_AllowOverlap             = 1 << 14, // false     // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
+    ImGuiItemFlags_NoNavDisableMouseHover   = 1 << 15, // false     // Nav keyboard/gamepad mode doesn't disable hover.
 
     // Controlled by widget code
     ImGuiItemFlags_Inputable                = 1 << 20, // false     // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature.
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 9d4ef66dabd2..aac7383b1ad2 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4462,9 +4462,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
                 return false;
     }
-    const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
+
+    // Ensure mouse cursor is set even after switching to keyboard/gamepad mode. May generalize further? (#6417)
+    bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags | ImGuiItemFlags_NoNavDisableMouseHover);
     if (hovered)
         SetMouseCursor(ImGuiMouseCursor_TextInput);
+    if (hovered && g.NavDisableMouseHover)
+        hovered = false;
 
     // We are only allowed to access the state if we are already the active widget.
     ImGuiInputTextState* state = GetInputTextState(id);

From d885fe4dd0cda0166415d423e6a4a5d4ef5e997c Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 15:28:00 +0200
Subject: [PATCH 191/548] (Breaking) moved
 ImGuiConfigFlags_NavEnableSetMousePos -> io.ConfigNavMoveSetMousePos,
 ImGuiConfigFlags_NavNoCaptureKeyboard -> ConfigNavCaptureKeyboard. (#2517,
 #2009)

---
 backends/imgui_impl_glfw.cpp  |  2 +-
 backends/imgui_impl_sdl2.cpp  |  2 +-
 backends/imgui_impl_sdl3.cpp  |  2 +-
 backends/imgui_impl_win32.cpp |  2 +-
 docs/CHANGELOG.txt            |  5 +++++
 imgui.cpp                     | 27 +++++++++++++++++++------
 imgui.h                       | 37 ++++++++++++++++++++---------------
 imgui_demo.cpp                | 12 ++++++++----
 imgui_internal.h              |  2 +-
 9 files changed, 60 insertions(+), 31 deletions(-)

diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp
index 7134d3e55448..c725e9c01d96 100644
--- a/backends/imgui_impl_glfw.cpp
+++ b/backends/imgui_impl_glfw.cpp
@@ -728,7 +728,7 @@ static void ImGui_ImplGlfw_UpdateMouseData()
 #endif
         if (is_window_focused)
         {
-            // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
+            // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
             if (io.WantSetMousePos)
                 glfwSetCursorPos(window, (double)io.MousePos.x, (double)io.MousePos.y);
 
diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp
index 6d98a697eea0..1abe8b93d5e3 100644
--- a/backends/imgui_impl_sdl2.cpp
+++ b/backends/imgui_impl_sdl2.cpp
@@ -605,7 +605,7 @@ static void ImGui_ImplSDL2_UpdateMouseData()
 #endif
     if (is_app_focused)
     {
-        // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
+        // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
         if (io.WantSetMousePos)
             SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y);
 
diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp
index 599d3fc445ab..517ba1ada1a1 100644
--- a/backends/imgui_impl_sdl3.cpp
+++ b/backends/imgui_impl_sdl3.cpp
@@ -573,7 +573,7 @@ static void ImGui_ImplSDL3_UpdateMouseData()
 #endif
     if (is_app_focused)
     {
-        // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
+        // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
         if (io.WantSetMousePos)
             SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y);
 
diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp
index 0e9164efe521..bbfa1a5bedea 100644
--- a/backends/imgui_impl_win32.cpp
+++ b/backends/imgui_impl_win32.cpp
@@ -308,7 +308,7 @@ static void ImGui_ImplWin32_UpdateMouseData()
     const bool is_app_focused = (focused_window == bd->hWnd);
     if (is_app_focused)
     {
-        // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
+        // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user)
         if (io.WantSetMousePos)
         {
             POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index a01d5d6bc6f3..d67abea37f5c 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -54,6 +54,11 @@ Breaking changes:
     - Won't warn:   ImGui::Image((ImTextureID)(intptr_t)MyTextureData), ...);
   - Note that you can always define ImTextureID to be your own high-level structures
     (with dedicated constructors) if you like.
+- IO: moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
+- IO: moved ImGuiConfigFlags_NavNoCaptureKeyboard to standalone io.ConfigNavCaptureKeyboard bool 
+  (note the inverted value!). (#2517, #2009)
+  Kept legacy names (will obsolete) + code that copies settings once the first time. 
+  Dynamically changing the old value won't work. Switch to using the new value!
 
 Other changes:
 
diff --git a/imgui.cpp b/imgui.cpp
index 971f48f16fc2..fa865503cd0c 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -183,8 +183,8 @@ CODE
    - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + run examples/libs/synergy/uSynergy.c (on your console/tablet/phone app)
      in order to share your PC mouse/keyboard.
    - See https://github.com/ocornut/imgui/wiki/Useful-Extensions#remoting for other remoting solutions.
-   - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag.
-     Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs Dear ImGui to move your mouse cursor along with navigation movements.
+   - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the io.ConfigNavMoveSetMousePos flag.
+     Enabling io.ConfigNavMoveSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs Dear ImGui to move your mouse cursor along with navigation movements.
      When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantSetMousePos' to notify you that it wants the mouse cursor to be moved.
      When that happens your backend NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the backends in examples/ do that.
      (If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMousePos' properly, Dear ImGui will misbehave as it will see your mouse moving back & forth!)
@@ -430,6 +430,9 @@ 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.
 
+ - 2024/10/14 (1.91.4) - moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
+                         moved ImGuiConfigFlags_NavNoCaptureKeyboard to standalone io.ConfigNavCaptureKeyboard bool (note the inverted value!).
+                         kept legacy names (will obsolete) + code that copies settings once the first time. Dynamically changing the old value won't work. Switch to using the new value!
  - 2024/10/10 (1.91.4) - the typedef for ImTextureID now defaults to ImU64 instead of void*. (#1641)
                          this removes the requirement to redefine it for backends which are e.g. storing descriptor sets or other 64-bits structures when building on 32-bits archs. It therefore simplify various building scripts/helpers.
                          you may have compile-time issues if you were casting to 'void*' instead of 'ImTextureID' when passing your types to functions taking ImTextureID values, e.g. ImGui::Image().
@@ -5001,7 +5004,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
     {
         if ((g.ActiveId != 0) || (modal_window != NULL))
             io.WantCaptureKeyboard = true;
-        else if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
+        else if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && io.ConfigNavCaptureKeyboard)
             io.WantCaptureKeyboard = true;
     }
     if (g.WantCaptureKeyboardNextFrame != -1) // Manual override
@@ -10456,8 +10459,20 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
     if (g.IO.ConfigErrorRecovery)
         IM_ASSERT(g.IO.ConfigErrorRecoveryEnableAssert || g.IO.ConfigErrorRecoveryEnableDebugLog || g.IO.ConfigErrorRecoveryEnableTooltip || g.ErrorCallback != NULL);
 
-    // Remap legacy clipboard handlers (OBSOLETED in 1.91.1, August 2024)
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+    // Remap legacy names
+    if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)
+    {
+        g.IO.ConfigNavMoveSetMousePos = true;
+        g.IO.ConfigFlags &= ~ImGuiConfigFlags_NavEnableSetMousePos;
+    }
+    if (g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)
+    {
+        g.IO.ConfigNavCaptureKeyboard = false;
+        g.IO.ConfigFlags &= ~ImGuiConfigFlags_NavNoCaptureKeyboard;
+    }
+
+    // Remap legacy clipboard handlers (OBSOLETED in 1.91.1, August 2024)
     if (g.IO.GetClipboardTextFn != NULL && (g.PlatformIO.Platform_GetClipboardTextFn == NULL || g.PlatformIO.Platform_GetClipboardTextFn == Platform_GetClipboardTextFn_DefaultImpl))
         g.PlatformIO.Platform_GetClipboardTextFn = [](ImGuiContext* ctx) { return ctx->IO.GetClipboardTextFn(ctx->IO.ClipboardUserData); };
     if (g.IO.SetClipboardTextFn != NULL && (g.PlatformIO.Platform_SetClipboardTextFn == NULL || g.PlatformIO.Platform_SetClipboardTextFn == Platform_SetClipboardTextFn_DefaultImpl))
@@ -12168,7 +12183,7 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
 
         ImVec2 tooltip_pos = g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_MOUSE * scale;
         ImRect r_avoid;
-        if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos))
+        if (!g.NavDisableHighlight && g.NavDisableMouseHover && !g.IO.ConfigNavMoveSetMousePos)
             r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
         else
             r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
@@ -12973,7 +12988,7 @@ static void ImGui::NavUpdate()
 
     // Update mouse position if requested
     // (This will take into account the possibility that a Scroll was queued in the window to offset our absolute mouse position before scroll has been applied)
-    if (set_mouse_pos && (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
+    if (set_mouse_pos && io.ConfigNavMoveSetMousePos && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
         TeleportMousePos(NavCalcPreferredRefPos());
 
     // [DEBUG]
diff --git a/imgui.h b/imgui.h
index d18879ce1308..c2aa54420f94 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.4 WIP"
-#define IMGUI_VERSION_NUM   19133
+#define IMGUI_VERSION_NUM   19134
 #define IMGUI_HAS_TABLE
 
 /*
@@ -1597,8 +1597,6 @@ enum ImGuiConfigFlags_
     ImGuiConfigFlags_None                   = 0,
     ImGuiConfigFlags_NavEnableKeyboard      = 1 << 0,   // Master keyboard navigation enable flag. Enable full Tabbing + directional arrows + space/enter to activate.
     ImGuiConfigFlags_NavEnableGamepad       = 1 << 1,   // Master gamepad navigation enable flag. Backend also needs to set ImGuiBackendFlags_HasGamepad.
-    ImGuiConfigFlags_NavEnableSetMousePos   = 1 << 2,   // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your backend, otherwise ImGui will react as if the mouse is jumping around back and forth.
-    ImGuiConfigFlags_NavNoCaptureKeyboard   = 1 << 3,   // Instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive is set.
     ImGuiConfigFlags_NoMouse                = 1 << 4,   // Instruct dear imgui to disable mouse inputs and interactions.
     ImGuiConfigFlags_NoMouseCursorChange    = 1 << 5,   // Instruct backend to not alter mouse cursor shape and visibility. Use if the backend cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead.
     ImGuiConfigFlags_NoKeyboard             = 1 << 6,   // Instruct dear imgui to disable keyboard inputs and interactions. This is done by ignoring keyboard events and clearing existing states.
@@ -1606,6 +1604,11 @@ enum ImGuiConfigFlags_
     // User storage (to allow your backend/engine to communicate to code that may be shared between multiple projects. Those flags are NOT used by core Dear ImGui)
     ImGuiConfigFlags_IsSRGB                 = 1 << 20,  // Application is SRGB-aware.
     ImGuiConfigFlags_IsTouchScreen          = 1 << 21,  // Application is using a touch screen instead of a mouse.
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+    ImGuiConfigFlags_NavEnableSetMousePos   = 1 << 2,   // [moved/renamed in 1.91.4] -> use bool io.ConfigNavMoveSetMousePos
+    ImGuiConfigFlags_NavNoCaptureKeyboard   = 1 << 3,   // [moved/renamed in 1.91.4] -> use bool io.ConfigNavCaptureKeyboard
+#endif
 };
 
 // Backend capabilities flags stored in io.BackendFlags. Set by imgui_impl_xxx or custom backend.
@@ -1614,7 +1617,7 @@ enum ImGuiBackendFlags_
     ImGuiBackendFlags_None                  = 0,
     ImGuiBackendFlags_HasGamepad            = 1 << 0,   // Backend Platform supports gamepad and currently has one connected.
     ImGuiBackendFlags_HasMouseCursors       = 1 << 1,   // Backend Platform supports honoring GetMouseCursor() value to change the OS cursor shape.
-    ImGuiBackendFlags_HasSetMousePos        = 1 << 2,   // Backend Platform supports io.WantSetMousePos requests to reposition the OS mouse position (only used if ImGuiConfigFlags_NavEnableSetMousePos is set).
+    ImGuiBackendFlags_HasSetMousePos        = 1 << 2,   // Backend Platform supports io.WantSetMousePos requests to reposition the OS mouse position (only used if io.ConfigNavMoveSetMousePos is set).
     ImGuiBackendFlags_RendererHasVtxOffset  = 1 << 3,   // Backend Renderer supports ImDrawCmd::VtxOffset. This enables output of large meshes (64K+ vertices) while still using 16-bit indices.
 };
 
@@ -2242,17 +2245,19 @@ struct ImGuiIO
 
     // Miscellaneous options
     // (you can visualize and interact with all options in 'Demo->Configuration')
-    bool        MouseDrawCursor;                // = false          // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
-    bool        ConfigMacOSXBehaviors;          // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
-    bool        ConfigNavSwapGamepadButtons;    // = false          // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
-    bool        ConfigInputTrickleEventQueue;   // = true           // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
-    bool        ConfigInputTextCursorBlink;     // = true           // Enable blinking cursor (optional as some users consider it to be distracting).
-    bool        ConfigInputTextEnterKeepActive; // = false          // [BETA] Pressing Enter will keep item active and select contents (single-line only).
-    bool        ConfigDragClickToInputText;     // = false          // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
-    bool        ConfigWindowsResizeFromEdges;   // = true           // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
-    bool        ConfigWindowsMoveFromTitleBarOnly; // = false       // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
-    bool        ConfigScrollbarScrollByPage;    // = true           // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
-    float       ConfigMemoryCompactTimer;       // = 60.0f          // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
+    bool        MouseDrawCursor;                    // = false      // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
+    bool        ConfigMacOSXBehaviors;              // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
+    bool        ConfigNavSwapGamepadButtons;        // = false      // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
+    bool        ConfigNavMoveSetMousePos;           // = false      // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true. 
+    bool        ConfigNavCaptureKeyboard;           // = true       // Sets io.WantCaptureKeyboard when io.NavActive is set.
+    bool        ConfigInputTrickleEventQueue;       // = true       // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
+    bool        ConfigInputTextCursorBlink;         // = true       // Enable blinking cursor (optional as some users consider it to be distracting).
+    bool        ConfigInputTextEnterKeepActive;     // = false      // [BETA] Pressing Enter will keep item active and select contents (single-line only).
+    bool        ConfigDragClickToInputText;         // = false      // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
+    bool        ConfigWindowsResizeFromEdges;       // = true       // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
+    bool        ConfigWindowsMoveFromTitleBarOnly;  // = false      // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
+    bool        ConfigScrollbarScrollByPage;        // = true       // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
+    float       ConfigMemoryCompactTimer;           // = 60.0f      // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
 
     // Inputs Behaviors
     // (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle)
@@ -2358,7 +2363,7 @@ struct ImGuiIO
     bool        WantCaptureMouse;                   // Set when Dear ImGui will use mouse inputs, in this case do not dispatch them to your main game/application (either way, always pass on mouse inputs to imgui). (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.).
     bool        WantCaptureKeyboard;                // Set when Dear ImGui will use keyboard inputs, in this case do not dispatch them to your main game/application (either way, always pass keyboard inputs to imgui). (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.).
     bool        WantTextInput;                      // Mobile/console: when set, you may display an on-screen keyboard. This is set by Dear ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active).
-    bool        WantSetMousePos;                    // MousePos has been altered, backend should reposition mouse on next frame. Rarely used! Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled.
+    bool        WantSetMousePos;                    // MousePos has been altered, backend should reposition mouse on next frame. Rarely used! Set only when io.ConfigNavMoveSetMousePos is enabled.
     bool        WantSaveIniSettings;                // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving!
     bool        NavActive;                          // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag.
     bool        NavVisible;                         // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events).
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index a85e28e54ff9..1cf4b5eb61d6 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -501,8 +501,6 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::SameLine(); HelpMarker("Enable keyboard controls.");
             ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad",     &io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
             ImGui::SameLine(); HelpMarker("Enable gamepad controls. Require backend to set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
-            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", &io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
-            ImGui::SameLine(); HelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
             ImGui::CheckboxFlags("io.ConfigFlags: NoMouse",              &io.ConfigFlags, ImGuiConfigFlags_NoMouse);
             ImGui::SameLine(); HelpMarker("Instruct dear imgui to disable mouse inputs and interactions.");
 
@@ -529,6 +527,12 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
             ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
 
+            ImGui::SeparatorText("Navigation");
+            ImGui::Checkbox("io.ConfigNavSwapGamepadButtons", &io.ConfigNavSwapGamepadButtons);
+            ImGui::Checkbox("io.ConfigNavMoveSetMousePos", &io.ConfigNavMoveSetMousePos);
+            ImGui::SameLine(); HelpMarker("Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult");
+            ImGui::Checkbox("io.ConfigNavCaptureKeyboard", &io.ConfigNavCaptureKeyboard);
+
             ImGui::SeparatorText("Widgets");
             ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
             ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
@@ -7753,12 +7757,12 @@ void ImGui::ShowAboutWindow(bool* p_open)
         ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags);
         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)        ImGui::Text(" NavEnableKeyboard");
         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)         ImGui::Text(" NavEnableGamepad");
-        if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)     ImGui::Text(" NavEnableSetMousePos");
-        if (io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)     ImGui::Text(" NavNoCaptureKeyboard");
         if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)                  ImGui::Text(" NoMouse");
         if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)      ImGui::Text(" NoMouseCursorChange");
         if (io.MouseDrawCursor)                                         ImGui::Text("io.MouseDrawCursor");
         if (io.ConfigMacOSXBehaviors)                                   ImGui::Text("io.ConfigMacOSXBehaviors");
+        if (io.ConfigNavMoveSetMousePos)                                ImGui::Text("io.ConfigNavMoveSetMousePos");
+        if (io.ConfigNavCaptureKeyboard)                                ImGui::Text("io.ConfigNavCaptureKeyboard");
         if (io.ConfigInputTextCursorBlink)                              ImGui::Text("io.ConfigInputTextCursorBlink");
         if (io.ConfigWindowsResizeFromEdges)                            ImGui::Text("io.ConfigWindowsResizeFromEdges");
         if (io.ConfigWindowsMoveFromTitleBarOnly)                       ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly");
diff --git a/imgui_internal.h b/imgui_internal.h
index 5722291afc97..68593e8f4e84 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2143,7 +2143,7 @@ struct ImGuiContext
     ImGuiInputSource        NavInputSource;                     // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
     ImGuiSelectionUserData  NavLastValidSelectionUserData;      // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
     bool                    NavIdIsAlive;                       // Nav widget has been seen this frame ~~ NavRectRel is valid
-    bool                    NavMousePosDirty;                   // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
+    bool                    NavMousePosDirty;                   // When set we will update mouse position if io.ConfigNavMoveSetMousePos is set (not enabled by default)
     bool                    NavDisableHighlight;                // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
     bool                    NavDisableMouseHover;               // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again.
 

From ba5161740ea84e883cd89c775607aaf96a8159c2 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 16:52:25 +0200
Subject: [PATCH 192/548] Amend d885fe4, fixes default value of
 ConfigNavCaptureKeyboard. (#2517, #2009)

---
 imgui.cpp      |  2 ++
 imgui.h        | 24 ++++++++++++------------
 imgui_demo.cpp |  1 +
 3 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index fa865503cd0c..47ea5f471140 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1406,6 +1406,8 @@ ImGuiIO::ImGuiIO()
     ConfigMacOSXBehaviors = false;
 #endif
     ConfigNavSwapGamepadButtons = false;
+    ConfigNavMoveSetMousePos = false;
+    ConfigNavCaptureKeyboard = true;
     ConfigInputTrickleEventQueue = true;
     ConfigInputTextCursorBlink = true;
     ConfigInputTextEnterKeepActive = false;
diff --git a/imgui.h b/imgui.h
index c2aa54420f94..6a252301060c 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2245,19 +2245,19 @@ struct ImGuiIO
 
     // Miscellaneous options
     // (you can visualize and interact with all options in 'Demo->Configuration')
-    bool        MouseDrawCursor;                    // = false      // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
-    bool        ConfigMacOSXBehaviors;              // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
-    bool        ConfigNavSwapGamepadButtons;        // = false      // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
-    bool        ConfigNavMoveSetMousePos;           // = false      // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true. 
-    bool        ConfigNavCaptureKeyboard;           // = true       // Sets io.WantCaptureKeyboard when io.NavActive is set.
-    bool        ConfigInputTrickleEventQueue;       // = true       // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
-    bool        ConfigInputTextCursorBlink;         // = true       // Enable blinking cursor (optional as some users consider it to be distracting).
-    bool        ConfigInputTextEnterKeepActive;     // = false      // [BETA] Pressing Enter will keep item active and select contents (single-line only).
-    bool        ConfigDragClickToInputText;         // = false      // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
-    bool        ConfigWindowsResizeFromEdges;       // = true       // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
+    bool        MouseDrawCursor;                // = false          // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
+    bool        ConfigMacOSXBehaviors;          // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
+    bool        ConfigNavSwapGamepadButtons;    // = false          // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
+    bool        ConfigNavMoveSetMousePos;       // = false          // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true. 
+    bool        ConfigNavCaptureKeyboard;       // = true           // Sets io.WantCaptureKeyboard when io.NavActive is set.
+    bool        ConfigInputTrickleEventQueue;   // = true           // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
+    bool        ConfigInputTextCursorBlink;     // = true           // Enable blinking cursor (optional as some users consider it to be distracting).
+    bool        ConfigInputTextEnterKeepActive; // = false          // [BETA] Pressing Enter will keep item active and select contents (single-line only).
+    bool        ConfigDragClickToInputText;     // = false          // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
+    bool        ConfigWindowsResizeFromEdges;   // = true           // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
     bool        ConfigWindowsMoveFromTitleBarOnly;  // = false      // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
-    bool        ConfigScrollbarScrollByPage;        // = true       // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
-    float       ConfigMemoryCompactTimer;           // = 60.0f      // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
+    bool        ConfigScrollbarScrollByPage;    // = true           // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
+    float       ConfigMemoryCompactTimer;       // = 60.0f          // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
 
     // Inputs Behaviors
     // (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle)
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 1cf4b5eb61d6..9c9868aa5393 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -7759,6 +7759,7 @@ void ImGui::ShowAboutWindow(bool* p_open)
         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)         ImGui::Text(" NavEnableGamepad");
         if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)                  ImGui::Text(" NoMouse");
         if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)      ImGui::Text(" NoMouseCursorChange");
+        if (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard)               ImGui::Text(" NoKeyboard");
         if (io.MouseDrawCursor)                                         ImGui::Text("io.MouseDrawCursor");
         if (io.ConfigMacOSXBehaviors)                                   ImGui::Text("io.ConfigMacOSXBehaviors");
         if (io.ConfigNavMoveSetMousePos)                                ImGui::Text("io.ConfigNavMoveSetMousePos");

From b0010389011de8c5229775b71233a79e05ec1e7f Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 16:57:34 +0200
Subject: [PATCH 193/548] Nav: added io.ConfigNavEscapeClearFocusWindow to
 clear focused window on Escape. (#3200)

+ pressing escape to hide nav highlight doesn't clear location from when ctrl+tabbing back into same window later.
---
 docs/CHANGELOG.txt | 3 +++
 imgui.cpp          | 7 +++++--
 imgui.h            | 1 +
 imgui_demo.cpp     | 2 ++
 4 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index d67abea37f5c..aa64698c8005 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -67,6 +67,9 @@ Other changes:
   state to draw callbacks. (#6969, #5834, #7468, #3590)
 - IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
 - Error Handling: turned a few more functions into recoverable errors. (#1651)
+- Nav: added io.ConfigNavEscapeClearFocusWindow to clear focused window on Escape. (#3200)
+- Nav: pressing escape to hide nav highlight doesn't clear location from when ctrl+tabbing back
+  into same window later.
 - DrawList: AddCallback() added an optional size parameter allowing to copy and
   store any amount of user data for usage by callbacks: (#6969, #4770, #7665)
   - If userdata_size == 0: we copy/store the 'userdata' argument as-is (existing behavior).
diff --git a/imgui.cpp b/imgui.cpp
index 47ea5f471140..486832ec3264 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1408,6 +1408,7 @@ ImGuiIO::ImGuiIO()
     ConfigNavSwapGamepadButtons = false;
     ConfigNavMoveSetMousePos = false;
     ConfigNavCaptureKeyboard = true;
+    ConfigNavEscapeClearFocusWindow = false;
     ConfigInputTrickleEventQueue = true;
     ConfigInputTextCursorBlink = true;
     ConfigInputTextEnterKeepActive = false;
@@ -13316,7 +13317,7 @@ void ImGui::NavMoveRequestApplyResult()
         NavRestoreHighlightAfterMove();
 }
 
-// Process NavCancel input (to close a popup, get back to parent, clear focus)
+// Process Escape/NavCancel input (to close a popup, get back to parent, clear focus)
 // FIXME: In order to support e.g. Escape to clear a selection we'll need:
 // - either to store the equivalent of ActiveIdUsingKeyInputMask for a FocusScope and test for it.
 // - either to move most/all of those tests to the epilogue/end functions of the scope they are dealing with (e.g. exit child window in EndChild()) or in EndFrame(), to allow an earlier intercept
@@ -13358,11 +13359,13 @@ static void ImGui::NavUpdateCancelRequest()
     {
         // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
         // FIXME-NAV: This should happen on window appearing.
-        if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
+        if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup)))// || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
             g.NavWindow->NavLastIds[0] = 0;
 
         // Clear nav focus
         g.NavId = 0;
+        if (g.IO.ConfigNavEscapeClearFocusWindow)
+            FocusWindow(NULL);
     }
 }
 
diff --git a/imgui.h b/imgui.h
index 6a252301060c..7d17aede6208 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2250,6 +2250,7 @@ struct ImGuiIO
     bool        ConfigNavSwapGamepadButtons;    // = false          // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
     bool        ConfigNavMoveSetMousePos;       // = false          // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true. 
     bool        ConfigNavCaptureKeyboard;       // = true           // Sets io.WantCaptureKeyboard when io.NavActive is set.
+    bool        ConfigNavEscapeClearFocusWindow;// = false          // Pressing Escape (when no item is active, no popup open etc.) clears focused window + navigation id/highlight.
     bool        ConfigInputTrickleEventQueue;   // = true           // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
     bool        ConfigInputTextCursorBlink;     // = true           // Enable blinking cursor (optional as some users consider it to be distracting).
     bool        ConfigInputTextEnterKeepActive; // = false          // [BETA] Pressing Enter will keep item active and select contents (single-line only).
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 9c9868aa5393..dca67405460f 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -532,6 +532,8 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::Checkbox("io.ConfigNavMoveSetMousePos", &io.ConfigNavMoveSetMousePos);
             ImGui::SameLine(); HelpMarker("Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult");
             ImGui::Checkbox("io.ConfigNavCaptureKeyboard", &io.ConfigNavCaptureKeyboard);
+            ImGui::Checkbox("io.ConfigNavEscapeClearFocusWindow", &io.ConfigNavEscapeClearFocusWindow);
+            ImGui::SameLine(); HelpMarker("Pressing Escape clears focused window.");
 
             ImGui::SeparatorText("Widgets");
             ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);

From 626d358e55e92ceaacf6c0200d32cbf9d36fe6eb Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 17:10:36 +0200
Subject: [PATCH 194/548] Nav: fixed Ctrl+Tab so when starting with no focused
 window it starts from the top-most window. (#3200)

---
 docs/CHANGELOG.txt |  6 ++++--
 imgui.cpp          | 15 +++++++++------
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index aa64698c8005..203d4d954085 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -68,8 +68,10 @@ Other changes:
 - IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
 - Error Handling: turned a few more functions into recoverable errors. (#1651)
 - Nav: added io.ConfigNavEscapeClearFocusWindow to clear focused window on Escape. (#3200)
-- Nav: pressing escape to hide nav highlight doesn't clear location from when ctrl+tabbing back
-  into same window later.
+- Nav: pressing escape to hide nav highlight doesn't clear location from when ctrl+tabbing 
+  back into same window later.
+- Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
+  window. (#3200)
 - DrawList: AddCallback() added an optional size parameter allowing to copy and
   store any amount of user data for usage by callbacks: (#6969, #4770, #7665)
   - If userdata_size == 0: we copy/store the 'userdata' argument as-is (existing behavior).
diff --git a/imgui.cpp b/imgui.cpp
index 486832ec3264..7da199c5cb09 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -13540,7 +13540,7 @@ static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) //
     return NULL;
 }
 
-static void NavUpdateWindowingHighlightWindow(int focus_change_dir)
+static void NavUpdateWindowingTarget(int focus_change_dir)
 {
     ImGuiContext& g = *GImGui;
     IM_ASSERT(g.NavWindowingTarget);
@@ -13592,14 +13592,17 @@ static void ImGui::NavUpdateWindowing()
     const bool keyboard_prev_window = allow_windowing && g.ConfigNavWindowingKeyPrev && Shortcut(g.ConfigNavWindowingKeyPrev, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways, owner_id);
     const bool start_windowing_with_gamepad = allow_windowing && nav_gamepad_active && !g.NavWindowingTarget && IsKeyPressed(ImGuiKey_NavGamepadMenu, ImGuiInputFlags_None);
     const bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && (keyboard_next_window || keyboard_prev_window); // Note: enabled even without NavEnableKeyboard!
+    bool just_started_windowing_from_null_focus = false;
     if (start_windowing_with_gamepad || start_windowing_with_keyboard)
         if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
         {
-            g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow;
+            g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; // Current location
             g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;
             g.NavWindowingAccumDeltaPos = g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f);
             g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : false; // Gamepad starts toggling layer
             g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
+            if (g.NavWindow == NULL)
+                just_started_windowing_from_null_focus = true;
 
             // Manually register ownership of our mods. Using a global route in the Shortcut() calls instead would probably be correct but may have more side-effects.
             if (keyboard_next_window || keyboard_prev_window)
@@ -13615,9 +13618,9 @@ static void ImGui::NavUpdateWindowing()
 
         // Select window to focus
         const int focus_change_dir = (int)IsKeyPressed(ImGuiKey_GamepadL1) - (int)IsKeyPressed(ImGuiKey_GamepadR1);
-        if (focus_change_dir != 0)
+        if (focus_change_dir != 0 && !just_started_windowing_from_null_focus)
         {
-            NavUpdateWindowingHighlightWindow(focus_change_dir);
+            NavUpdateWindowingTarget(focus_change_dir);
             g.NavWindowingHighlightAlpha = 1.0f;
         }
 
@@ -13640,8 +13643,8 @@ static void ImGui::NavUpdateWindowing()
         ImGuiKeyChord shared_mods = ((g.ConfigNavWindowingKeyNext ? g.ConfigNavWindowingKeyNext : ImGuiMod_Mask_) & (g.ConfigNavWindowingKeyPrev ? g.ConfigNavWindowingKeyPrev : ImGuiMod_Mask_)) & ImGuiMod_Mask_;
         IM_ASSERT(shared_mods != 0); // Next/Prev shortcut currently needs a shared modifier to "hold", otherwise Prev actions would keep cycling between two windows.
         g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f
-        if (keyboard_next_window || keyboard_prev_window)
-            NavUpdateWindowingHighlightWindow(keyboard_next_window ? -1 : +1);
+        if ((keyboard_next_window || keyboard_prev_window) && !just_started_windowing_from_null_focus)
+            NavUpdateWindowingTarget(keyboard_next_window ? -1 : +1);
         else if ((io.KeyMods & shared_mods) != shared_mods)
             apply_focus_window = g.NavWindowingTarget;
     }

From ad37b79bca2bf548c22ca2276dd209f05583e729 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 17:30:14 +0200
Subject: [PATCH 195/548] Nav: shallow tidying up.

---
 imgui.cpp         | 8 +++-----
 imgui_internal.h  | 2 +-
 imgui_widgets.cpp | 4 ++--
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 7da199c5cb09..eafb7a84dd1e 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4443,9 +4443,9 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
 
     if (g.NavDisableMouseHover && !g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride))
     {
-        if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
+        if (g.LastItemData.ID == g.NavId && g.NavId != 0) // IsItemFocused()
             return false;
-        if (!IsItemFocused())
+        if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
             return false;
 
         if (flags & ImGuiHoveredFlags_ForTooltip)
@@ -5784,9 +5784,7 @@ bool ImGui::IsItemDeactivatedAfterEdit()
 bool ImGui::IsItemFocused()
 {
     ImGuiContext& g = *GImGui;
-    if (g.NavId != g.LastItemData.ID || g.NavId == 0)
-        return false;
-    return true;
+    return g.NavId == g.LastItemData.ID && g.NavId != 0;
 }
 
 // Important: this can be useful but it is NOT equivalent to the behavior of e.g.Button()!
diff --git a/imgui_internal.h b/imgui_internal.h
index 68593e8f4e84..99421b700601 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -906,7 +906,7 @@ enum ImGuiButtonFlagsPrivate_
     ImGuiButtonFlags_DontClosePopups        = 1 << 13,  // disable automatically closing parent popup on press // [UNUSED]
     //ImGuiButtonFlags_Disabled             = 1 << 14,  // disable interactions -> use BeginDisabled() or ImGuiItemFlags_Disabled
     ImGuiButtonFlags_AlignTextBaseLine      = 1 << 15,  // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
-    ImGuiButtonFlags_NoKeyModifiers         = 1 << 16,  // disable mouse interaction if a key modifier is held
+    ImGuiButtonFlags_NoKeyModsAllowed       = 1 << 16,  // disable mouse interaction if a key modifier is held
     ImGuiButtonFlags_NoHoldingActiveId      = 1 << 17,  // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
     ImGuiButtonFlags_NoNavFocus             = 1 << 18,  // don't override navigation focus when activated (FIXME: this is essentially used every time an item uses ImGuiItemFlags_NoNav, but because legacy specs don't requires LastItemData to be set ButtonBehavior(), we can't poll g.LastItemData.InFlags)
     ImGuiButtonFlags_NoHoveredOnFocus       = 1 << 19,  // don't report as hovered when nav focus is on this item
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index aac7383b1ad2..8cdd4aa2756c 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -561,7 +561,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
             }
 
         // Process initial action
-        if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
+        if (!(flags & ImGuiButtonFlags_NoKeyModsAllowed) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
         {
             if (mouse_button_clicked != -1 && g.ActiveId != id)
             {
@@ -6604,7 +6604,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
     else
     {
         if (window != g.HoveredWindow || !is_mouse_x_over_arrow)
-            button_flags |= ImGuiButtonFlags_NoKeyModifiers;
+            button_flags |= ImGuiButtonFlags_NoKeyModsAllowed;
     }
 
     bool hovered, held;

From 462d167456852387dcc6c3d03f1ad502992108c0 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 17:37:36 +0200
Subject: [PATCH 196/548] Nav: rectangle highlight not rendered for items with
 ImGuiItemFlags_NoNav. (#8057)

Not fully honored in ItemHoverable/IsItemHovered, seems more destructive. This is mostly designed to avoid rectangle being rendered by large InvisibleButton() when ctrl+tabbing back to a window with a big one.
---
 docs/CHANGELOG.txt | 2 ++
 imgui.cpp          | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 203d4d954085..6a062c459769 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -72,6 +72,8 @@ Other changes:
   back into same window later.
 - Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
   window. (#3200)
+- Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
+  when e.g activating the item with mouse, then ctrl+tabbing back and forth. 
 - DrawList: AddCallback() added an optional size parameter allowing to copy and
   store any amount of user data for usage by callbacks: (#6969, #4770, #7665)
   - If userdata_size == 0: we copy/store the 'userdata' argument as-is (existing behavior).
diff --git a/imgui.cpp b/imgui.cpp
index eafb7a84dd1e..0ca2f4ab19b0 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3701,6 +3701,8 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
         return;
     if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
         return;
+    if (id == g.LastItemData.ID && (g.LastItemData.InFlags & ImGuiItemFlags_NoNav))
+        return;
     ImGuiWindow* window = g.CurrentWindow;
     if (window->DC.NavHideHighlightOneFrame)
         return;

From 97da66209cffd84a6959bced872da06a91213402 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 19:03:33 +0200
Subject: [PATCH 197/548] Internals: removing ImGuiButtonFlags_Repeat (in favor
 of ImGuiItemFlags_ButtonRepeat), ImGuiButtonFlags_DontClosePopups (unused)

---
 imgui_internal.h  |  4 ++--
 imgui_widgets.cpp | 15 ++++++++-------
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/imgui_internal.h b/imgui_internal.h
index 99421b700601..5e378d669c6b 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -900,10 +900,10 @@ enum ImGuiButtonFlagsPrivate_
     ImGuiButtonFlags_PressedOnRelease       = 1 << 7,   // return true on release (default requires click+release)
     ImGuiButtonFlags_PressedOnDoubleClick   = 1 << 8,   // return true on double-click (default requires click+release)
     ImGuiButtonFlags_PressedOnDragDropHold  = 1 << 9,   // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers)
-    ImGuiButtonFlags_Repeat                 = 1 << 10,  // hold to repeat
+    //ImGuiButtonFlags_Repeat               = 1 << 10,  // hold to repeat
     ImGuiButtonFlags_FlattenChildren        = 1 << 11,  // allow interactions even if a child window is overlapping
     ImGuiButtonFlags_AllowOverlap           = 1 << 12,  // require previous frame HoveredId to either match id or be null before being usable.
-    ImGuiButtonFlags_DontClosePopups        = 1 << 13,  // disable automatically closing parent popup on press // [UNUSED]
+    //ImGuiButtonFlags_DontClosePopups      = 1 << 13,  // disable automatically closing parent popup on press
     //ImGuiButtonFlags_Disabled             = 1 << 14,  // disable interactions -> use BeginDisabled() or ImGuiItemFlags_Disabled
     ImGuiButtonFlags_AlignTextBaseLine      = 1 << 15,  // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
     ImGuiButtonFlags_NoKeyModsAllowed       = 1 << 16,  // disable mouse interaction if a key modifier is held
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 8cdd4aa2756c..2a7b1e9a89b4 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -508,8 +508,6 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
     ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.InFlags : g.CurrentItemFlags);
     if (flags & ImGuiButtonFlags_AllowOverlap)
         item_flags |= ImGuiItemFlags_AllowOverlap;
-    if (flags & ImGuiButtonFlags_Repeat)
-        item_flags |= ImGuiItemFlags_ButtonRepeat;
 
     ImGuiWindow* backup_hovered_window = g.HoveredWindow;
     const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window;
@@ -3689,21 +3687,22 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
         // Step buttons
         const ImVec2 backup_frame_padding = style.FramePadding;
         style.FramePadding.x = style.FramePadding.y;
-        ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups;
         if (flags & ImGuiInputTextFlags_ReadOnly)
             BeginDisabled();
+        PushItemFlag(ImGuiItemFlags_ButtonRepeat, true);
         SameLine(0, style.ItemInnerSpacing.x);
-        if (ButtonEx("-", ImVec2(button_size, button_size), button_flags))
+        if (ButtonEx("-", ImVec2(button_size, button_size)))
         {
             DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
             value_changed = true;
         }
         SameLine(0, style.ItemInnerSpacing.x);
-        if (ButtonEx("+", ImVec2(button_size, button_size), button_flags))
+        if (ButtonEx("+", ImVec2(button_size, button_size)))
         {
             DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
             value_changed = true;
         }
+        PopItemFlag();
         if (flags & ImGuiInputTextFlags_ReadOnly)
             EndDisabled();
 
@@ -9753,17 +9752,19 @@ static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
 
     PushStyleColor(ImGuiCol_Text, arrow_col);
     PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
+    PushItemFlag(ImGuiItemFlags_ButtonRepeat, true);
     const float backup_repeat_delay = g.IO.KeyRepeatDelay;
     const float backup_repeat_rate = g.IO.KeyRepeatRate;
     g.IO.KeyRepeatDelay = 0.250f;
     g.IO.KeyRepeatRate = 0.200f;
     float x = ImMax(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.x - scrolling_buttons_width);
     window->DC.CursorPos = ImVec2(x, tab_bar->BarRect.Min.y);
-    if (ArrowButtonEx("##<", ImGuiDir_Left, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat))
+    if (ArrowButtonEx("##<", ImGuiDir_Left, arrow_button_size, ImGuiButtonFlags_PressedOnClick))
         select_dir = -1;
     window->DC.CursorPos = ImVec2(x + arrow_button_size.x, tab_bar->BarRect.Min.y);
-    if (ArrowButtonEx("##>", ImGuiDir_Right, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat))
+    if (ArrowButtonEx("##>", ImGuiDir_Right, arrow_button_size, ImGuiButtonFlags_PressedOnClick))
         select_dir = +1;
+    PopItemFlag();
     PopStyleColor(2);
     g.IO.KeyRepeatRate = backup_repeat_rate;
     g.IO.KeyRepeatDelay = backup_repeat_delay;

From 42f47590f983f489991f6ebfb72d2b32858cc270 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 19:13:04 +0200
Subject: [PATCH 198/548] Fixed ad37b79 breaking
 IsItemHovered()->IsItemFocused() passthrough for navigation.

+ Backends: comments.
---
 backends/imgui_impl_dx12.cpp   | 1 +
 backends/imgui_impl_vulkan.cpp | 1 +
 imgui.cpp                      | 2 +-
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index e9345013c4cc..be117b6c16a2 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -18,6 +18,7 @@
 // (minor and older changes stripped away, please see git history for details)
 //  2024-10-07: DirectX12: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-10-07: DirectX12: Expose selected render state in ImGui_ImplDX12_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
+//  2024-10-07: DirectX12: Compiling with '#define ImTextureID=ImU64' is unnecessary now that dear imgui defaults ImTextureID to u64 instead of void*.
 //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 //  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
 //  2021-05-19: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index a68f862b1b68..4e4e332fc207 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -28,6 +28,7 @@
 // (minor and older changes stripped away, please see git history for details)
 //  2024-10-07: Vulkan: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
+//  2024-10-07: Vulkan: Compiling with '#define ImTextureID=ImU64' is unnecessary now that dear imgui defaults ImTextureID to u64 instead of void*.
 //  2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
 //  2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering.
 //  2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure.
diff --git a/imgui.cpp b/imgui.cpp
index 0ca2f4ab19b0..1cdf4383a2d4 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4445,7 +4445,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
 
     if (g.NavDisableMouseHover && !g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride))
     {
-        if (g.LastItemData.ID == g.NavId && g.NavId != 0) // IsItemFocused()
+        if (!IsItemFocused())
             return false;
         if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
             return false;

From 50de550ecddf8569e4aaa5f45ab803da92fc5921 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 14 Oct 2024 19:34:23 +0200
Subject: [PATCH 199/548] Tooltips: fixed incorrect tooltip positioning when
 using keyboard/gamepad navigation (1.91.3 regression). (#8036)

Regression in 1.91.3 commit 5109a77.
---
 docs/CHANGELOG.txt |  2 ++
 imgui.cpp          | 24 ++++++++++++++++++++----
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 6a062c459769..0ade98733c85 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -74,6 +74,8 @@ Other changes:
   window. (#3200)
 - Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
   when e.g activating the item with mouse, then ctrl+tabbing back and forth. 
+- Tooltips: fixed incorrect tooltip positioning when using keyboard/gamepad navigation 
+  (1.91.3 regression). (#8036)
 - DrawList: AddCallback() added an optional size parameter allowing to copy and
   store any amount of user data for usage by callbacks: (#6969, #4770, #7665)
   - If userdata_size == 0: we copy/store the 'userdata' argument as-is (existing behavior).
diff --git a/imgui.cpp b/imgui.cpp
index 1cdf4383a2d4..3ce5e90db53c 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1199,6 +1199,7 @@ static bool             NavScoreItem(ImGuiNavItemData* result);
 static void             NavApplyItemToResult(ImGuiNavItemData* result);
 static void             NavProcessItem();
 static void             NavProcessItemForTabbingRequest(ImGuiID id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags);
+static ImGuiInputSource NavCalcPreferredRefPosSource();
 static ImVec2           NavCalcPreferredRefPos();
 static void             NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
 static ImGuiWindow*     NavRestoreLastChildNavWindow(ImGuiWindow* window);
@@ -12177,14 +12178,14 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
         const float scale = g.Style.MouseCursorScale;
         const ImVec2 ref_pos = NavCalcPreferredRefPos();
 
-        if (g.IO.MouseSource == ImGuiMouseSource_TouchScreen)
+        if (g.IO.MouseSource == ImGuiMouseSource_TouchScreen && NavCalcPreferredRefPosSource() == ImGuiInputSource_Mouse)
         {
-            ImVec2 tooltip_pos = g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_TOUCH * scale - (TOOLTIP_DEFAULT_PIVOT_TOUCH * window->Size);
+            ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_TOUCH * scale - (TOOLTIP_DEFAULT_PIVOT_TOUCH * window->Size);
             if (r_outer.Contains(ImRect(tooltip_pos, tooltip_pos + window->Size)))
                 return tooltip_pos;
         }
 
-        ImVec2 tooltip_pos = g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_MOUSE * scale;
+        ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_MOUSE * scale;
         ImRect r_avoid;
         if (!g.NavDisableHighlight && g.NavDisableMouseHover && !g.IO.ConfigNavMoveSetMousePos)
             r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
@@ -12779,7 +12780,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
     }
 }
 
-static ImVec2 ImGui::NavCalcPreferredRefPos()
+static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource()
 {
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.NavWindow;
@@ -12787,6 +12788,21 @@ static ImVec2 ImGui::NavCalcPreferredRefPos()
 
     // Testing for !activated_shortcut here could in theory be removed if we decided that activating a remote shortcut altered one of the g.NavDisableXXX flag.
     if ((g.NavDisableHighlight || !g.NavDisableMouseHover || !window) && !activated_shortcut)
+        return ImGuiInputSource_Mouse;
+    else
+        return ImGuiInputSource_Keyboard; // or Nav in general
+}
+
+static ImVec2 ImGui::NavCalcPreferredRefPos()
+{
+    ImGuiContext& g = *GImGui;
+    ImGuiWindow* window = g.NavWindow;
+    ImGuiInputSource source = NavCalcPreferredRefPosSource();
+
+    const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
+
+    // Testing for !activated_shortcut here could in theory be removed if we decided that activating a remote shortcut altered one of the g.NavDisableXXX flag.
+    if (source == ImGuiInputSource_Mouse)
     {
         // Mouse (we need a fallback in case the mouse becomes invalid after being used)
         // The +1.0f offset when stored by OpenPopupEx() allows reopening this or another popup (same or another mouse button) while not moving the mouse, it is pretty standard.

From 49a9eee33f21bb4f67ffeaad7559a349d1687704 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 15 Oct 2024 10:41:34 +0200
Subject: [PATCH 200/548] Commented out obsolete internals's
 SetItemUsingMouseWheel() (#2891), TreeNodeBehaviorIsOpen() (#4814, #5423,
 #282, #2958, #924)

+ Removed obsolete header checks for IMGUI_DISABLE_METRICS_WINDOW.
---
 imgui.h          | 9 +++------
 imgui_internal.h | 5 ++---
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/imgui.h b/imgui.h
index 7d17aede6208..2f9f18c2b8a4 100644
--- a/imgui.h
+++ b/imgui.h
@@ -3616,8 +3616,8 @@ namespace ImGui
     //-- OBSOLETED in 1.89 (from August 2022)
     //IMGUI_API bool      ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // --> Use new ImageButton() signature (explicit item id, regular FramePadding). Refer to code in 1.91 if you want to grab a copy of this version.
     //-- OBSOLETED in 1.88 (from May 2022)
-    //static inline void  CaptureKeyboardFromApp(bool want_capture_keyboard = true)     { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value.
-    //static inline void  CaptureMouseFromApp(bool want_capture_mouse = true)           { SetNextFrameWantCaptureMouse(want_capture_mouse); }       // Renamed as name was misleading + removed default value.
+    //static inline void  CaptureKeyboardFromApp(bool want_capture_keyboard = true)                   { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value.
+    //static inline void  CaptureMouseFromApp(bool want_capture_mouse = true)                         { SetNextFrameWantCaptureMouse(want_capture_mouse); }       // Renamed as name was misleading + removed default value.
     //-- OBSOLETED in 1.86 (from November 2021)
     //IMGUI_API void      CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Code removed, see 1.90 for last version of the code. Calculate range of visible items for large list of evenly sized items. Prefer using ImGuiListClipper.
     //-- OBSOLETED in 1.85 (from August 2021)
@@ -3700,10 +3700,7 @@ namespace ImGui
 #endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
 
 // RENAMED IMGUI_DISABLE_METRICS_WINDOW > IMGUI_DISABLE_DEBUG_TOOLS in 1.88 (from June 2022)
-#if defined(IMGUI_DISABLE_METRICS_WINDOW) && !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && !defined(IMGUI_DISABLE_DEBUG_TOOLS)
-#define IMGUI_DISABLE_DEBUG_TOOLS
-#endif
-#if defined(IMGUI_DISABLE_METRICS_WINDOW) && defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS)
+#ifdef IMGUI_DISABLE_METRICS_WINDOW
 #error IMGUI_DISABLE_METRICS_WINDOW was renamed to IMGUI_DISABLE_DEBUG_TOOLS, please use new name.
 #endif
 
diff --git a/imgui_internal.h b/imgui_internal.h
index 5e378d669c6b..f96e7091db66 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -3478,9 +3478,8 @@ namespace ImGui
 
     // Obsolete functions
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
-    inline void     SetItemUsingMouseWheel()                                            { SetItemKeyOwner(ImGuiKey_MouseWheelY); }      // Changed in 1.89
-    inline bool     TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0)    { return TreeNodeUpdateNextOpen(id, flags); }   // Renamed in 1.89
-
+    //inline void   SetItemUsingMouseWheel()                                            { SetItemKeyOwner(ImGuiKey_MouseWheelY); }      // Changed in 1.89
+    //inline bool   TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0)    { return TreeNodeUpdateNextOpen(id, flags); }   // Renamed in 1.89
     //inline bool   IsKeyPressedMap(ImGuiKey key, bool repeat = true)                   { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity!
 
     // Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister():

From 971d243a872fbc50a654ed18d31a58f9152a294b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?DOTTEL=20Ga=C3=ABl?= 
Date: Tue, 15 Oct 2024 11:35:34 +0200
Subject: [PATCH 201/548] Fixed typo (#8063)

---
 docs/FAQ.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/FAQ.md b/docs/FAQ.md
index 38600fe47155..8dde1967b469 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -405,7 +405,7 @@ DirectX9:
 ```
 ```cpp
 DirectX11:
-- ImTextureID should contain a 'ID3D11ShaderResourceView*' (poiter)
+- ImTextureID should contain a 'ID3D11ShaderResourceView*' (pointer)
 - See ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp
 ```
 ```cpp

From 67e5f3505d481519cf038aa9d054c5d0805a768d Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 16 Oct 2024 19:55:50 +0200
Subject: [PATCH 202/548] InvisibleButton: disable navigation properly + added
 ImGuiButtonFlags_EnableNav to enable navigation. (#8057)

---
 docs/CHANGELOG.txt | 5 ++++-
 imgui.h            | 2 +-
 imgui_internal.h   | 2 +-
 imgui_widgets.cpp  | 3 ++-
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 0ade98733c85..27b7dd780349 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -73,7 +73,10 @@ Other changes:
 - Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
   window. (#3200)
 - Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
-  when e.g activating the item with mouse, then ctrl+tabbing back and forth. 
+  when e.g activating the item with mouse, then Ctrl+Tabbing back and forth. 
+- InvisibleButton, Nav: fixed an issue when InvisibleButton() would be navigable into but
+  not display navigation highlight. Properly navigation on it by default. (#8057)
+- InvisibleButton: added ImGuiButtonFlags_EnableNav to enable navigation. (#8057)
 - Tooltips: fixed incorrect tooltip positioning when using keyboard/gamepad navigation 
   (1.91.3 regression). (#8036)
 - DrawList: AddCallback() added an optional size parameter allowing to copy and
diff --git a/imgui.h b/imgui.h
index 2f9f18c2b8a4..ec5d572b94df 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1744,7 +1744,7 @@ enum ImGuiButtonFlags_
     ImGuiButtonFlags_MouseButtonRight       = 1 << 1,   // React on right mouse button
     ImGuiButtonFlags_MouseButtonMiddle      = 1 << 2,   // React on center mouse button
     ImGuiButtonFlags_MouseButtonMask_       = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, // [Internal]
-    //ImGuiButtonFlags_MouseButtonDefault_  = ImGuiButtonFlags_MouseButtonLeft,
+    ImGuiButtonFlags_EnableNav              = 1 << 3,   // InvisibleButton(): do not disable navigation/tabbing. Otherwise disabled by default.
 };
 
 // Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton()
diff --git a/imgui_internal.h b/imgui_internal.h
index f96e7091db66..6e207d60e766 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -947,7 +947,7 @@ enum ImGuiSelectableFlagsPrivate_
 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_UpsideDownArrow            = 1 << 29,// FIXME-WIP: Turn Down arrow into an Up arrow, for reversed trees (#6517)
     ImGuiTreeNodeFlags_OpenOnMask_                = ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_OpenOnArrow,
 };
 
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 2a7b1e9a89b4..1cd18c359c89 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -785,11 +785,12 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg, ImGuiBut
     ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);
     const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
     ItemSize(size);
-    if (!ItemAdd(bb, id))
+    if (!ItemAdd(bb, id, NULL, (flags & ImGuiButtonFlags_EnableNav) ? ImGuiItemFlags_None : ImGuiItemFlags_NoNav))
         return false;
 
     bool hovered, held;
     bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
+    RenderNavHighlight(bb, id);
 
     IMGUI_TEST_ENGINE_ITEM_INFO(id, str_id, g.LastItemData.StatusFlags);
     return pressed;

From 83ecc846dc40645348d808c7119d1528e76c59a9 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 16 Oct 2024 20:23:33 +0200
Subject: [PATCH 203/548] Disabled: clicking a disabled item focuses parent
 window. (#8064)

---
 docs/CHANGELOG.txt |  1 +
 imgui.h            |  2 +-
 imgui_widgets.cpp  | 19 ++++++++++++++++---
 3 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 27b7dd780349..147e9f0678be 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -74,6 +74,7 @@ Other changes:
   window. (#3200)
 - Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
   when e.g activating the item with mouse, then Ctrl+Tabbing back and forth. 
+- Disabled: clicking a disabled item focuses parent window. (#8064) 
 - InvisibleButton, Nav: fixed an issue when InvisibleButton() would be navigable into but
   not display navigation highlight. Properly navigation on it by default. (#8057)
 - InvisibleButton: added ImGuiButtonFlags_EnableNav to enable navigation. (#8057)
diff --git a/imgui.h b/imgui.h
index ec5d572b94df..ef0c59a9d50e 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.4 WIP"
-#define IMGUI_VERSION_NUM   19134
+#define IMGUI_VERSION_NUM   19135
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 1cd18c359c89..247fce39c09a 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -542,7 +542,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
 
     // Mouse handling
     const ImGuiID test_owner_id = (flags & ImGuiButtonFlags_NoTestKeyOwner) ? ImGuiKeyOwner_Any : id;
-    if (hovered)
+    const bool hovered_disabled = (g.HoveredId == id && g.HoveredIdIsDisabled);
+    if (hovered || hovered_disabled)
     {
         IM_ASSERT(id != 0); // Lazily check inside rare path.
 
@@ -559,7 +560,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
             }
 
         // Process initial action
-        if (!(flags & ImGuiButtonFlags_NoKeyModsAllowed) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
+        const bool mods_ok = !(flags & ImGuiButtonFlags_NoKeyModsAllowed) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt);
+        if (mods_ok && !hovered_disabled)
         {
             if (mouse_button_clicked != -1 && g.ActiveId != id)
             {
@@ -606,7 +608,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
                     if (!has_repeated_at_least_once)
                         pressed = true;
                     if (!(flags & ImGuiButtonFlags_NoNavFocus))
-                        SetFocusID(id, window);
+                        SetFocusID(id, window); // FIXME: Lack of FocusWindow() call here is inconsistent with other paths. Research why.
                     ClearActiveID();
                 }
             }
@@ -617,6 +619,17 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
                 if (g.IO.MouseDownDuration[g.ActiveIdMouseButton] > 0.0f && IsMouseClicked(g.ActiveIdMouseButton, ImGuiInputFlags_Repeat, test_owner_id))
                     pressed = true;
         }
+        else if (mods_ok && hovered_disabled)
+        {
+            if (mouse_button_clicked != -1 && g.ActiveId != id)
+            {
+                // Disabled path still focus
+                // FIXME-NAV: Could somehow call SetNavID() with a null ID but mouse pos as NavRectRel so nav may be resumed?
+                // Will do it once we do it for regular click on window-void.
+                if (flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick))
+                    FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild);
+            }
+        }
 
         if (pressed)
             g.NavDisableHighlight = true;

From 04d9a0455702b376eec7074885bb722ad27171c0 Mon Sep 17 00:00:00 2001
From: Pascal Thomet 
Date: Thu, 8 Aug 2024 12:21:01 +0200
Subject: [PATCH 204/548] imgui_freetype: Added support for plutosvg to render
 OpenType SVG fonts.  (#7927, #7187 + #6591, #6607)

See #7927 for details.
---
 docs/CHANGELOG.txt               |  4 ++++
 imconfig.h                       |  9 ++++++---
 misc/freetype/README.md          | 26 ++++++++++++++++++++++----
 misc/freetype/imgui_freetype.cpp | 24 +++++++++++++++++++-----
 misc/freetype/imgui_freetype.h   |  7 +++++++
 5 files changed, 58 insertions(+), 12 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 147e9f0678be..5d61daa549a1 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -93,6 +93,10 @@ Other changes:
   preventing use of external shortcuts not guarded by an ActiveId check. (#8048) [@geertbleyen]
 - InputText: ensure mouse cursor shape is set regardless of whether keyboard mode is 
   enabled or not. (#6417)
+- imgui_freetype: Added support for plutosvg (as an alternative to lunasvg) to render 
+  OpenType SVG fonts. Requires defining IMGUI_ENABLE_FREETYPE_PLUTOSVG along with IMGUI_ENABLE_FREETYPE.
+  Providing headers/librairies for plutosvg + plutovg is up to you (see #7927 for help).
+  (#7927, #7187, #6591, #6607) [@pthom]
 - Backends: DX11, DX12, SDLRenderer2/3. Vulkan, WGPU: expose selected state in
   ImGui_ImplXXXX_RenderState structures during render loop. (#6969, #5834, #7468, #3590)
 - Backends: DX9, DX10, DX11, DX12, OpenGL, Vulkan, WGPU: Changed default texture sampler
diff --git a/imconfig.h b/imconfig.h
index b8d55842b9bf..63d6ba081e99 100644
--- a/imconfig.h
+++ b/imconfig.h
@@ -83,10 +83,13 @@
 // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
 //#define IMGUI_ENABLE_FREETYPE
 
-//---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT)
-// Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided).
+//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT)
 // Only works in combination with IMGUI_ENABLE_FREETYPE.
-// (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
+// - lunasvg is currently easier to acquire/install, as e.g. it is part of vcpkg.
+// - plutosvg will support more fonts and may load them faster. It currently requires to be built manually but it is fairly easy. See misc/freetype/README for instructions.
+// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
+// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
+//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
 //#define IMGUI_ENABLE_FREETYPE_LUNASVG
 
 //---- Use stb_truetype to build and rasterize the font atlas (default)
diff --git a/misc/freetype/README.md b/misc/freetype/README.md
index 275a5386641d..3955b080e2fc 100644
--- a/misc/freetype/README.md
+++ b/misc/freetype/README.md
@@ -38,7 +38,25 @@ You can use the `ImGuiFreeTypeBuilderFlags_LoadColor` flag to load certain color
 
 ### Using OpenType SVG fonts (SVGinOT)
 - *SVG in Open Type* is a standard by Adobe and Mozilla for color OpenType and Open Font Format fonts. It allows font creators to embed complete SVG files within a font enabling full color and even animations.
-- Popular fonts such as [twemoji](https://github.com/13rac1/twemoji-color-font) and fonts made with [scfbuild](https://github.com/13rac1/scfbuild) is SVGinOT
-- Requires: [lunasvg](https://github.com/sammycage/lunasvg) v2.3.2 and above
-    1. Add `#define IMGUI_ENABLE_FREETYPE_LUNASVG` in your `imconfig.h`.
-    2. Get latest lunasvg binaries or build yourself. Under Windows you may use vcpkg with: `vcpkg install lunasvg --triplet=x64-windows`.
+- Popular fonts such as [twemoji](https://github.com/13rac1/twemoji-color-font) and fonts made with [scfbuild](https://github.com/13rac1/scfbuild) is SVGinOT 
+- Two alternatives are possible to render SVG fonts: use "lunasvg" or "plutosvg". plutosvg will support some more fonts (e.g. NotoColorEmoji-Regular) and may load them faster.
+
+#### Using lunasvg
+Requires: [lunasvg](https://github.com/sammycage/lunasvg) v2.3.2 and above
+- Add `#define IMGUI_ENABLE_FREETYPE_LUNASVG` in your `imconfig.h`.
+- Get latest lunasvg binaries or build yourself. Under Windows you may use vcpkg with: `vcpkg install lunasvg --triplet=x64-windows`.
+
+#### Using plutosvg (and plutovg)
+- Add `#define IMGUI_ENABLE_FREETYPE_PLUTOSVG` in your `imconfig.h`.
+- Compile and link with plutosvg *and* plutovg (which is required by plutosvg)
+
+_Compilation hints for plutovg_
+- Compile all source files in `plutovg/source/*.c`
+- Add include directory: `plutovg/include` + `plutovg/stb`
+
+_Compilation hints for plutosvg_
+- Compile `plutosvg/source/plutosvg.c`
+- Add include directory: `plutosvg/source`
+- Add define: `PLUTOSVG_HAS_FREETYPE`
+- Link with: plutovg, freetype
+
diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp
index d97605b25868..646a3b14e2ec 100644
--- a/misc/freetype/imgui_freetype.cpp
+++ b/misc/freetype/imgui_freetype.cpp
@@ -6,8 +6,9 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024/10/17: added plutosvg support for SVG Fonts (seems faster/better than lunasvg). Enable by using '#define IMGUI_ENABLE_FREETYPE_PLUTOSVG'. (#7927)
 //  2023/11/13: added support for ImFontConfig::RasterizationDensity field for scaling render density without scaling metrics.
-//  2023/08/01: added support for SVG fonts, enable by using '#define IMGUI_ENABLE_FREETYPE_LUNASVG' (#6591)
+//  2023/08/01: added support for SVG fonts, enable by using '#define IMGUI_ENABLE_FREETYPE_LUNASVG'. (#6591)
 //  2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly.
 //  2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL.
 //  2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
@@ -45,12 +46,21 @@
 #include FT_GLYPH_H             // 
 #include FT_SYNTHESIS_H         // 
 
-#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
+// Handle LunaSVG and PlutoSVG
+#if defined(IMGUI_ENABLE_FREETYPE_LUNASVG) && defined(IMGUI_ENABLE_FREETYPE_PLUTOSVG)
+#error "Cannot enable both IMGUI_ENABLE_FREETYPE_LUNASVG and IMGUI_ENABLE_FREETYPE_PLUTOSVG"
+#endif
+#ifdef  IMGUI_ENABLE_FREETYPE_LUNASVG
 #include FT_OTSVG_H             // 
 #include FT_BBOX_H              // 
 #include 
+#endif
+#ifdef  IMGUI_ENABLE_FREETYPE_PLUTOSVG
+#include 
+#endif
+#if defined(IMGUI_ENABLE_FREETYPE_LUNASVG) || defined (IMGUI_ENABLE_FREETYPE_PLUTOSVG)
 #if !((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
-#error IMGUI_ENABLE_FREETYPE_LUNASVG requires FreeType version >= 2.12
+#error IMGUI_ENABLE_FREETYPE_PLUTOSVG or IMGUI_ENABLE_FREETYPE_LUNASVG requires FreeType version >= 2.12
 #endif
 #endif
 
@@ -269,11 +279,11 @@ namespace
 
         // Need an outline for this to work
         FT_GlyphSlot slot = Face->glyph;
-#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
+#if defined(IMGUI_ENABLE_FREETYPE_LUNASVG) || defined(IMGUI_ENABLE_FREETYPE_PLUTOSVG)
         IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP || slot->format == FT_GLYPH_FORMAT_SVG);
 #else
 #if ((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
-        IM_ASSERT(slot->format != FT_GLYPH_FORMAT_SVG && "The font contains SVG glyphs, you'll need to enable IMGUI_ENABLE_FREETYPE_LUNASVG in imconfig.h and install required libraries in order to use this font");
+        IM_ASSERT(slot->format != FT_GLYPH_FORMAT_SVG && "The font contains SVG glyphs, you'll need to enable IMGUI_ENABLE_FREETYPE_PLUTOSVG or IMGUI_ENABLE_FREETYPE_LUNASVG in imconfig.h and install required libraries in order to use this font");
 #endif
         IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP);
 #endif // IMGUI_ENABLE_FREETYPE_LUNASVG
@@ -810,6 +820,10 @@ static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas)
     SVG_RendererHooks hooks = { ImGuiLunasvgPortInit, ImGuiLunasvgPortFree, ImGuiLunasvgPortRender, ImGuiLunasvgPortPresetSlot };
     FT_Property_Set(ft_library, "ot-svg", "svg-hooks", &hooks);
 #endif // IMGUI_ENABLE_FREETYPE_LUNASVG
+#ifdef IMGUI_ENABLE_FREETYPE_PLUTOSVG
+    // With plutosvg, use provided hooks
+    FT_Property_Set(ft_library, "ot-svg", "svg-hooks", plutosvg_ft_svg_hooks());
+#endif // IMGUI_ENABLE_FREETYPE_PLUTOSVG
 
     bool ret = ImFontAtlasBuildWithFreeTypeEx(ft_library, atlas, atlas->FontBuilderFlags);
     FT_Done_Library(ft_library);
diff --git a/misc/freetype/imgui_freetype.h b/misc/freetype/imgui_freetype.h
index b4e1d4893303..6572b1547bf8 100644
--- a/misc/freetype/imgui_freetype.h
+++ b/misc/freetype/imgui_freetype.h
@@ -5,6 +5,13 @@
 #include "imgui.h"      // IMGUI_API
 #ifndef IMGUI_DISABLE
 
+// Usage:
+// - Add '#define IMGUI_ENABLE_FREETYPE' in your imconfig to enable support for imgui_freetype in imgui.
+
+// Optional support for OpenType SVG fonts:
+// - Add '#define IMGUI_ENABLE_FREETYPE_PLUTOSVG' to use plutosvg (not provided). See #7927.
+// - Add '#define IMGUI_ENABLE_FREETYPE_LUNASVG' to use lunasvg (not provided). See #6591.
+
 // Forward declarations
 struct ImFontAtlas;
 struct ImFontBuilderIO;

From 706438a43c368c4a7d822b5ff997fa2befdbd5e6 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 17 Oct 2024 11:37:16 +0200
Subject: [PATCH 205/548] Disabled: clicking a disabled item focuses parent
 window. Fix/amend 83ecc84. (#8064)

83ecc84 was too not supporting widgets using ItemHoverable() directly + too complex.
Revert 83ecc84 in ButtonBehavior(), reimplement in UpdateMouseMovingWindowEndFrame()>
---
 imgui.cpp         | 10 ++++++----
 imgui_widgets.cpp | 16 ++--------------
 2 files changed, 8 insertions(+), 18 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 3ce5e90db53c..75e0ad40f07e 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4875,12 +4875,13 @@ void ImGui::UpdateMouseMovingWindowNewFrame()
     }
 }
 
-// Initiate moving window when clicking on empty space or title bar.
+// Initiate focusing and moving window when clicking on empty space or title bar.
+// Initiate focusing window when clicking on a disabled item.
 // Handle left-click and right-click focus.
 void ImGui::UpdateMouseMovingWindowEndFrame()
 {
     ImGuiContext& g = *GImGui;
-    if (g.ActiveId != 0 || g.HoveredId != 0)
+    if (g.ActiveId != 0 || (g.HoveredId != 0 && !g.HoveredIdIsDisabled))
         return;
 
     // Unless we just made a window/popup appear
@@ -4906,7 +4907,8 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
                     if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
                         g.MovingWindow = NULL;
 
-            // Cancel moving if clicked over an item which was disabled or inhibited by popups (note that we know HoveredId == 0 already)
+            // Cancel moving if clicked over an item which was disabled or inhibited by popups
+            // (when g.HoveredIdIsDisabled == true && g.HoveredId == 0 we are inhibited by popups, when g.HoveredIdIsDisabled == true && g.HoveredId != 0 we are over a disabled item)0 already)
             if (g.HoveredIdIsDisabled)
                 g.MovingWindow = NULL;
         }
@@ -4920,7 +4922,7 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
     // With right mouse button we close popups without changing focus based on where the mouse is aimed
     // Instead, focus will be restored to the window under the bottom-most closed popup.
     // (The left mouse button path calls FocusWindow on the hovered window, which will lead NewFrame->ClosePopupsOverWindow to trigger)
-    if (g.IO.MouseClicked[1])
+    if (g.IO.MouseClicked[1] && g.HoveredId == 0)
     {
         // Find the top-most window between HoveredWindow and the top-most Modal Window.
         // This is where we can trim the popup stack.
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 247fce39c09a..e240bdd90cc8 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -542,8 +542,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
 
     // Mouse handling
     const ImGuiID test_owner_id = (flags & ImGuiButtonFlags_NoTestKeyOwner) ? ImGuiKeyOwner_Any : id;
-    const bool hovered_disabled = (g.HoveredId == id && g.HoveredIdIsDisabled);
-    if (hovered || hovered_disabled)
+    if (hovered)
     {
         IM_ASSERT(id != 0); // Lazily check inside rare path.
 
@@ -561,7 +560,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
 
         // Process initial action
         const bool mods_ok = !(flags & ImGuiButtonFlags_NoKeyModsAllowed) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt);
-        if (mods_ok && !hovered_disabled)
+        if (mods_ok)
         {
             if (mouse_button_clicked != -1 && g.ActiveId != id)
             {
@@ -619,17 +618,6 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
                 if (g.IO.MouseDownDuration[g.ActiveIdMouseButton] > 0.0f && IsMouseClicked(g.ActiveIdMouseButton, ImGuiInputFlags_Repeat, test_owner_id))
                     pressed = true;
         }
-        else if (mods_ok && hovered_disabled)
-        {
-            if (mouse_button_clicked != -1 && g.ActiveId != id)
-            {
-                // Disabled path still focus
-                // FIXME-NAV: Could somehow call SetNavID() with a null ID but mouse pos as NavRectRel so nav may be resumed?
-                // Will do it once we do it for regular click on window-void.
-                if (flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick))
-                    FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild);
-            }
-        }
 
         if (pressed)
             g.NavDisableHighlight = true;

From e6b5cafe65fd983eb87bf2fd4d7f68e544911fcd Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 17 Oct 2024 15:11:35 +0200
Subject: [PATCH 206/548] Internals: rename ImGuiLastItemData::InFlags ->
 ItemFlags. ImGuiNextItemData::Flags -> HasFlags to avoid mistakes.

---
 imgui.cpp         | 42 +++++++++++++++++++-------------------
 imgui_internal.h  |  8 ++++----
 imgui_widgets.cpp | 52 +++++++++++++++++++++++------------------------
 3 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 75e0ad40f07e..36624f7f9ae6 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3702,7 +3702,7 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
         return;
     if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
         return;
-    if (id == g.LastItemData.ID && (g.LastItemData.InFlags & ImGuiItemFlags_NoNav))
+    if (id == g.LastItemData.ID && (g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav))
         return;
     ImGuiWindow* window = g.CurrentWindow;
     if (window->DC.NavHideHighlightOneFrame)
@@ -4448,7 +4448,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
     {
         if (!IsItemFocused())
             return false;
-        if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
+        if ((g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
             return false;
 
         if (flags & ImGuiHoveredFlags_ForTooltip)
@@ -4483,11 +4483,11 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
 
         // Test if interactions on this window are blocked by an active popup or modal.
         // The ImGuiHoveredFlags_AllowWhenBlockedByPopup flag will be tested here.
-        if (!IsWindowContentHoverable(window, flags) && !(g.LastItemData.InFlags & ImGuiItemFlags_NoWindowHoverableCheck))
+        if (!IsWindowContentHoverable(window, flags) && !(g.LastItemData.ItemFlags & ImGuiItemFlags_NoWindowHoverableCheck))
             return false;
 
         // Test if the item is disabled
-        if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
+        if ((g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
             return false;
 
         // Special handling for calling after Begin() which represent the title bar or tab.
@@ -4497,7 +4497,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
             return false;
 
         // Test if using AllowOverlap and overlapped
-        if ((g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap) && id != 0)
+        if ((g.LastItemData.ItemFlags & ImGuiItemFlags_AllowOverlap) && id != 0)
             if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByItem) == 0)
                 if (g.HoveredIdPreviousFrame != g.LastItemData.ID)
                     return false;
@@ -4640,7 +4640,7 @@ void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemS
 {
     ImGuiContext& g = *GImGui;
     g.LastItemData.ID = item_id;
-    g.LastItemData.InFlags = in_flags;
+    g.LastItemData.ItemFlags = in_flags;
     g.LastItemData.StatusFlags = item_flags;
     g.LastItemData.Rect = g.LastItemData.NavRect = item_rect;
 }
@@ -10280,7 +10280,7 @@ bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiInputFlags flags, Im
 void ImGui::SetNextItemShortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags)
 {
     ImGuiContext& g = *GImGui;
-    g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasShortcut;
+    g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasShortcut;
     g.NextItemData.Shortcut = key_chord;
     g.NextItemData.ShortcutFlags = flags;
 }
@@ -10292,7 +10292,7 @@ void ImGui::ItemHandleShortcut(ImGuiID id)
     ImGuiInputFlags flags = g.NextItemData.ShortcutFlags;
     IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetNextItemShortcut) == 0); // Passing flags not supported by SetNextItemShortcut()!
 
-    if (g.LastItemData.InFlags & ImGuiItemFlags_Disabled)
+    if (g.LastItemData.ItemFlags & ImGuiItemFlags_Disabled)
         return;
     if (flags & ImGuiInputFlags_Tooltip)
     {
@@ -10784,7 +10784,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
     g.LastItemData.ID = id;
     g.LastItemData.Rect = bb;
     g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb;
-    g.LastItemData.InFlags = g.CurrentItemFlags | g.NextItemData.ItemFlags | extra_flags;
+    g.LastItemData.ItemFlags = g.CurrentItemFlags | g.NextItemData.ItemFlags | extra_flags;
     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.
 
@@ -10802,7 +10802,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
         //      to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick).
         // We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null.
         // If we crash on a NULL g.NavWindow we need to fix the bug elsewhere.
-        if (!(g.LastItemData.InFlags & ImGuiItemFlags_NoNav))
+        if (!(g.LastItemData.ItemFlags & 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);
@@ -10812,12 +10812,12 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
                         NavProcessItem();
         }
 
-        if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasShortcut)
+        if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasShortcut)
             ItemHandleShortcut(id);
     }
 
     // Lightweight clear of SetNextItemXXX data.
-    g.NextItemData.Flags = ImGuiNextItemDataFlags_None;
+    g.NextItemData.HasFlags = ImGuiNextItemDataFlags_None;
     g.NextItemData.ItemFlags = ImGuiItemFlags_None;
 
 #ifdef IMGUI_ENABLE_TEST_ENGINE
@@ -11046,7 +11046,7 @@ void ImGui::Unindent(float indent_w)
 void ImGui::SetNextItemWidth(float item_width)
 {
     ImGuiContext& g = *GImGui;
-    g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth;
+    g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasWidth;
     g.NextItemData.Width = item_width;
 }
 
@@ -11057,7 +11057,7 @@ void ImGui::PushItemWidth(float item_width)
     ImGuiWindow* window = g.CurrentWindow;
     window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width
     window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
-    g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
+    g.NextItemData.HasFlags &= ~ImGuiNextItemDataFlags_HasWidth;
 }
 
 void ImGui::PushMultiItemsWidths(int components, float w_full)
@@ -11076,7 +11076,7 @@ void ImGui::PushMultiItemsWidths(int components, float w_full)
         prev_split = next_split;
     }
     window->DC.ItemWidth = ImMax(prev_split, 1.0f);
-    g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
+    g.NextItemData.HasFlags &= ~ImGuiNextItemDataFlags_HasWidth;
 }
 
 void ImGui::PopItemWidth()
@@ -11099,7 +11099,7 @@ float ImGui::CalcItemWidth()
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
     float w;
-    if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
+    if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasWidth)
         w = g.NextItemData.Width;
     else
         w = window->DC.ItemWidth;
@@ -12444,7 +12444,7 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
     result->Window = window;
     result->ID = g.LastItemData.ID;
     result->FocusScopeId = g.CurrentFocusScopeId;
-    result->InFlags = g.LastItemData.InFlags;
+    result->InFlags = g.LastItemData.ItemFlags;
     result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
     if (result->InFlags & ImGuiItemFlags_HasSelectionUserData)
     {
@@ -12469,7 +12469,7 @@ static void ImGui::NavProcessItem()
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
     const ImGuiID id = g.LastItemData.ID;
-    const ImGuiItemFlags item_flags = g.LastItemData.InFlags;
+    const ImGuiItemFlags item_flags = g.LastItemData.ItemFlags;
 
     // When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221)
     if (window->DC.NavIsScrollPushableX == false)
@@ -12531,7 +12531,7 @@ static void ImGui::NavProcessItem()
         SetNavFocusScope(g.CurrentFocusScopeId); // Will set g.NavFocusScopeId AND store g.NavFocusScopePath
         g.NavFocusScopeId = g.CurrentFocusScopeId;
         g.NavIdIsAlive = true;
-        if (g.LastItemData.InFlags & ImGuiItemFlags_HasSelectionUserData)
+        if (g.LastItemData.ItemFlags & ImGuiItemFlags_HasSelectionUserData)
         {
             IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
             g.NavLastValidSelectionUserData = g.NextItemData.SelectionUserData; // INTENTIONAL: At this point this field is not cleared in NextItemData. Avoid unnecessary copy to LastItemData.
@@ -12652,7 +12652,7 @@ void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGu
     ImGuiContext& g = *GImGui;
     g.NavMoveScoringItems = false;
     g.LastItemData.ID = tree_node_data->ID;
-    g.LastItemData.InFlags = tree_node_data->InFlags & ~ImGuiItemFlags_HasSelectionUserData; // Losing SelectionUserData, recovered next-frame (cheaper).
+    g.LastItemData.ItemFlags = tree_node_data->InFlags & ~ImGuiItemFlags_HasSelectionUserData; // Losing SelectionUserData, recovered next-frame (cheaper).
     g.LastItemData.NavRect = tree_node_data->NavRect;
     NavApplyItemToResult(result); // Result this instead of implementing a NavApplyPastTreeNodeToResult()
     NavClearPreferredPosForAxis(ImGuiAxis_Y);
@@ -13916,7 +13916,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
             // Rely on keeping other window->LastItemXXX fields intact.
             source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect);
             KeepAliveID(source_id);
-            bool is_hovered = ItemHoverable(g.LastItemData.Rect, source_id, g.LastItemData.InFlags);
+            bool is_hovered = ItemHoverable(g.LastItemData.Rect, source_id, g.LastItemData.ItemFlags);
             if (is_hovered && g.IO.MouseClicked[mouse_button])
             {
                 SetActiveID(source_id, window);
diff --git a/imgui_internal.h b/imgui_internal.h
index 6e207d60e766..f7e4f662e21a 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1209,7 +1209,7 @@ enum ImGuiNextItemDataFlags_
 
 struct ImGuiNextItemData
 {
-    ImGuiNextItemDataFlags      Flags;
+    ImGuiNextItemDataFlags      HasFlags;           // Called HasFlags instead of Flags to avoid mistaking this
     ImGuiItemFlags              ItemFlags;          // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData.
     // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem()
     ImGuiID                     FocusScopeId;       // Set by SetNextItemSelectionUserData()
@@ -1223,14 +1223,14 @@ struct ImGuiNextItemData
     ImGuiID                     StorageId;          // Set by SetNextItemStorageID()
 
     ImGuiNextItemData()         { memset(this, 0, sizeof(*this)); SelectionUserData = -1; }
-    inline void ClearFlags()    { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
+    inline void ClearFlags()    { HasFlags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
 };
 
 // Status storage for the last submitted item
 struct ImGuiLastItemData
 {
     ImGuiID                 ID;
-    ImGuiItemFlags          InFlags;            // See ImGuiItemFlags_
+    ImGuiItemFlags          ItemFlags;          // See ImGuiItemFlags_
     ImGuiItemStatusFlags    StatusFlags;        // See ImGuiItemStatusFlags_
     ImRect                  Rect;               // Full rectangle
     ImRect                  NavRect;            // Navigation scoring rectangle (not displayed)
@@ -3025,7 +3025,7 @@ namespace ImGui
 
     // Basic Accessors
     inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; }
-    inline ImGuiItemFlags   GetItemFlags()  { ImGuiContext& g = *GImGui; return g.LastItemData.InFlags; }
+    inline ImGuiItemFlags   GetItemFlags()  { ImGuiContext& g = *GImGui; return g.LastItemData.ItemFlags; }
     inline ImGuiID          GetActiveID()   { ImGuiContext& g = *GImGui; return g.ActiveId; }
     inline ImGuiID          GetFocusID()    { ImGuiContext& g = *GImGui; return g.NavId; }
     IMGUI_API void          SetActiveID(ImGuiID id, ImGuiWindow* window);
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index e240bdd90cc8..3aba3a4da666 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -505,7 +505,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
 
     // Default behavior inherited from item flags
     // Note that _both_ ButtonFlags and ItemFlags are valid sources, so copy one into the item_flags and only check that.
-    ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.InFlags : g.CurrentItemFlags);
+    ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.ItemFlags : g.CurrentItemFlags);
     if (flags & ImGuiButtonFlags_AllowOverlap)
         item_flags |= ImGuiItemFlags_AllowOverlap;
 
@@ -1150,7 +1150,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
     const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
     ItemSize(total_bb, style.FramePadding.y);
     const bool is_visible = ItemAdd(total_bb, id);
-    const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0;
+    const bool is_multi_select = (g.LastItemData.ItemFlags & ImGuiItemFlags_IsMultiSelect) != 0;
     if (!is_visible)
         if (!is_multi_select || !g.BoxSelectState.UnclipMode || !g.BoxSelectState.UnclipRect.Overlaps(total_bb)) // Extra layer of "no logic clip" for box-select support
         {
@@ -1180,7 +1180,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
     }
 
     const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
-    const bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0;
+    const bool mixed_value = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
     if (is_visible)
     {
         RenderNavHighlight(total_bb, id);
@@ -2562,7 +2562,7 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v
     }
     if (g.ActiveId != id)
         return false;
-    if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
+    if ((g.LastItemData.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
         return false;
 
     switch (data_type)
@@ -2609,7 +2609,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
     if (format == NULL)
         format = DataTypeGetInfo(data_type)->PrintFmt;
 
-    const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
+    const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags);
     bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
     if (!temp_input_is_active)
     {
@@ -3104,7 +3104,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
         }
 
         if (set_new_value)
-            if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
+            if ((g.LastItemData.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
                 set_new_value = false;
 
         if (set_new_value)
@@ -3209,7 +3209,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
     if (format == NULL)
         format = DataTypeGetInfo(data_type)->PrintFmt;
 
-    const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
+    const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags);
     bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
     if (!temp_input_is_active)
     {
@@ -3375,7 +3375,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
     if (format == NULL)
         format = DataTypeGetInfo(data_type)->PrintFmt;
 
-    const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
+    const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags);
     const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id);
     if (clicked || g.NavActivateId == id)
     {
@@ -3583,7 +3583,7 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
         ClearActiveID();
 
     g.CurrentWindow->DC.CursorPos = bb.Min;
-    g.LastItemData.InFlags |= ImGuiItemFlags_AllowDuplicateId;
+    g.LastItemData.ItemFlags |= ImGuiItemFlags_AllowDuplicateId;
     bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_MergedItem);
     if (init)
     {
@@ -3640,7 +3640,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
 void ImGui::SetNextItemRefVal(ImGuiDataType data_type, void* p_data)
 {
     ImGuiContext& g = *GImGui;
-    g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasRefVal;
+    g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasRefVal;
     memcpy(&g.NextItemData.RefVal, p_data, DataTypeGetInfo(data_type)->Size);
 }
 
@@ -3658,7 +3658,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
     if (format == NULL)
         format = DataTypeGetInfo(data_type)->PrintFmt;
 
-    void* p_data_default = (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasRefVal) ? &g.NextItemData.RefVal : &g.DataTypeZeroValue;
+    void* p_data_default = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasRefVal) ? &g.NextItemData.RefVal : &g.DataTypeZeroValue;
 
     char buf[64];
     if ((flags & ImGuiInputTextFlags_DisplayEmptyRefVal) && DataTypeCompare(data_type, p_data, p_data_default) == 0)
@@ -4465,7 +4465,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     }
 
     // Ensure mouse cursor is set even after switching to keyboard/gamepad mode. May generalize further? (#6417)
-    bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags | ImGuiItemFlags_NoNavDisableMouseHover);
+    bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags | ImGuiItemFlags_NoNavDisableMouseHover);
     if (hovered)
         SetMouseCursor(ImGuiMouseCursor_TextInput);
     if (hovered && g.NavDisableMouseHover)
@@ -4474,7 +4474,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     // We are only allowed to access the state if we are already the active widget.
     ImGuiInputTextState* state = GetInputTextState(id);
 
-    if (g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly)
+    if (g.LastItemData.ItemFlags & ImGuiItemFlags_ReadOnly)
         flags |= ImGuiInputTextFlags_ReadOnly;
     const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
     const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
@@ -5300,7 +5300,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         if (g.LastItemData.ID == 0 || g.LastItemData.ID != GetWindowScrollbarID(draw_window, ImGuiAxis_Y))
         {
             g.LastItemData.ID = id;
-            g.LastItemData.InFlags = item_data_backup.InFlags;
+            g.LastItemData.ItemFlags = item_data_backup.ItemFlags;
             g.LastItemData.StatusFlags = item_data_backup.StatusFlags;
         }
     }
@@ -5629,7 +5629,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
 
     // Drag and Drop Target
     // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test.
-    if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget())
+    if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(g.LastItemData.ItemFlags & ImGuiItemFlags_ReadOnly) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget())
     {
         bool accepted_drag_drop = false;
         if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
@@ -6411,7 +6411,7 @@ bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags)
     ImGuiStorage* storage = window->DC.StateStorage;
 
     bool is_open;
-    if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasOpen)
+    if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasOpen)
     {
         if (g.NextItemData.OpenCond & ImGuiCond_Always)
         {
@@ -6457,7 +6457,7 @@ static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags)
     ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.back();
     tree_node_data->ID = g.LastItemData.ID;
     tree_node_data->TreeFlags = flags;
-    tree_node_data->InFlags = g.LastItemData.InFlags;
+    tree_node_data->InFlags = g.LastItemData.ItemFlags;
     tree_node_data->NavRect = g.LastItemData.NavRect;
     window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth);
 }
@@ -6506,7 +6506,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
         interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f);
 
     // Compute open and multi-select states before ItemAdd() as it clear NextItem data.
-    ImGuiID storage_id = (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasStorageID) ? g.NextItemData.StorageId : id;
+    ImGuiID storage_id = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasStorageID) ? g.NextItemData.StorageId : id;
     bool is_open = TreeNodeUpdateNextOpen(storage_id, flags);
 
     bool is_visible;
@@ -6559,7 +6559,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
     }
 
     ImGuiButtonFlags button_flags = ImGuiTreeNodeFlags_None;
-    if ((flags & ImGuiTreeNodeFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap))
+    if ((flags & ImGuiTreeNodeFlags_AllowOverlap) || (g.LastItemData.ItemFlags & ImGuiItemFlags_AllowOverlap))
         button_flags |= ImGuiButtonFlags_AllowOverlap;
     if (!is_leaf)
         button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
@@ -6571,7 +6571,7 @@ 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;
+    const bool is_multi_select = (g.LastItemData.ItemFlags & 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;
 
@@ -6788,7 +6788,7 @@ void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond)
     ImGuiContext& g = *GImGui;
     if (g.CurrentWindow->SkipItems)
         return;
-    g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasOpen;
+    g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasOpen;
     g.NextItemData.OpenVal = is_open;
     g.NextItemData.OpenCond = (ImU8)(cond ? cond : ImGuiCond_Always);
 }
@@ -6799,7 +6799,7 @@ void ImGui::SetNextItemStorageID(ImGuiID storage_id)
     ImGuiContext& g = *GImGui;
     if (g.CurrentWindow->SkipItems)
         return;
-    g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasStorageID;
+    g.NextItemData.HasFlags |= ImGuiNextItemDataFlags_HasStorageID;
     g.NextItemData.StorageId = storage_id;
 }
 
@@ -6925,7 +6925,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
         is_visible = ItemAdd(bb, id, NULL, extra_item_flags);
     }
 
-    const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0;
+    const bool is_multi_select = (g.LastItemData.ItemFlags & ImGuiItemFlags_IsMultiSelect) != 0;
     if (!is_visible)
         if (!is_multi_select || !g.BoxSelectState.UnclipMode || !g.BoxSelectState.UnclipRect.Overlaps(bb)) // Extra layer of "no logic clip" for box-select support (would be more overhead to add to ItemAdd)
             return false;
@@ -6953,7 +6953,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
     if (flags & ImGuiSelectableFlags_SelectOnClick)     { button_flags |= ImGuiButtonFlags_PressedOnClick; }
     if (flags & ImGuiSelectableFlags_SelectOnRelease)   { button_flags |= ImGuiButtonFlags_PressedOnRelease; }
     if (flags & ImGuiSelectableFlags_AllowDoubleClick)  { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; }
-    if ((flags & ImGuiSelectableFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap)) { button_flags |= ImGuiButtonFlags_AllowOverlap; }
+    if ((flags & ImGuiSelectableFlags_AllowOverlap) || (g.LastItemData.ItemFlags & ImGuiItemFlags_AllowOverlap)) { button_flags |= ImGuiButtonFlags_AllowOverlap; }
 
     // Multi-selection support (header)
     const bool was_selected = selected;
@@ -7035,7 +7035,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
         RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb);
 
     // Automatically close popups
-    if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.InFlags & ImGuiItemFlags_AutoClosePopups))
+    if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.ItemFlags & ImGuiItemFlags_AutoClosePopups))
         CloseCurrentPopup();
 
     if (disabled_item && !disabled_global)
@@ -9960,7 +9960,7 @@ bool    ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
     // Calculate tab contents size
     ImVec2 size = TabItemCalcSize(label, (p_open != NULL) || (flags & ImGuiTabItemFlags_UnsavedDocument));
     tab->RequestedWidth = -1.0f;
-    if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
+    if (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasWidth)
         size.x = tab->RequestedWidth = g.NextItemData.Width;
     if (tab_is_new)
         tab->Width = ImMax(1.0f, size.x);

From 0f6a463fae57cbec744f89b5d1afb7bb1a7eb34f Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 17 Oct 2024 15:16:05 +0200
Subject: [PATCH 207/548] Internals: rename ImGuiTreeNodeStackData::InFlags and
 ImGuiNavItemData::InFlags to ItemFlags too.

---
 imgui.cpp         | 16 ++++++++--------
 imgui_internal.h  | 16 ++++++++--------
 imgui_widgets.cpp |  2 +-
 3 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 36624f7f9ae6..772df22a5707 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4530,7 +4530,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
 // (this does not rely on LastItemData it can be called from a ButtonBehavior() call not following an ItemAdd() call)
 // FIXME-LEGACY: the 'ImGuiItemFlags item_flags' parameter was added on 2023-06-28.
 // If you used this in your legacy/custom widgets code:
-// - Commonly: if your ItemHoverable() call comes after an ItemAdd() call: pass 'item_flags = g.LastItemData.InFlags'.
+// - Commonly: if your ItemHoverable() call comes after an ItemAdd() call: pass 'item_flags = g.LastItemData.ItemFlags'.
 // - Rare: otherwise you may pass 'item_flags = 0' (ImGuiItemFlags_None) unless you want to benefit from special behavior handled by ItemHoverable.
 bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flags)
 {
@@ -10847,7 +10847,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
         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)
+    //if ((g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav) == 0)
     //    window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG]
 #endif
 
@@ -12444,9 +12444,9 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
     result->Window = window;
     result->ID = g.LastItemData.ID;
     result->FocusScopeId = g.CurrentFocusScopeId;
-    result->InFlags = g.LastItemData.ItemFlags;
+    result->ItemFlags = g.LastItemData.ItemFlags;
     result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
-    if (result->InFlags & ImGuiItemFlags_HasSelectionUserData)
+    if (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData)
     {
         IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
         result->SelectionUserData = g.NextItemData.SelectionUserData; // INTENTIONAL: At this point this field is not cleared in NextItemData. Avoid unnecessary copy to LastItemData.
@@ -12652,7 +12652,7 @@ void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGu
     ImGuiContext& g = *GImGui;
     g.NavMoveScoringItems = false;
     g.LastItemData.ID = tree_node_data->ID;
-    g.LastItemData.ItemFlags = tree_node_data->InFlags & ~ImGuiItemFlags_HasSelectionUserData; // Losing SelectionUserData, recovered next-frame (cheaper).
+    g.LastItemData.ItemFlags = tree_node_data->ItemFlags & ~ImGuiItemFlags_HasSelectionUserData; // Losing SelectionUserData, recovered next-frame (cheaper).
     g.LastItemData.NavRect = tree_node_data->NavRect;
     NavApplyItemToResult(result); // Result this instead of implementing a NavApplyPastTreeNodeToResult()
     NavClearPreferredPosForAxis(ImGuiAxis_Y);
@@ -13039,7 +13039,7 @@ void ImGui::NavInitRequestApplyResult()
         g.NavJustMovedToFocusScopeId = result->FocusScopeId;
         g.NavJustMovedToKeyMods = 0;
         g.NavJustMovedToIsTabbing = false;
-        g.NavJustMovedToHasSelectionData = (result->InFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
+        g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
     }
 
     // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called)
@@ -13298,7 +13298,7 @@ void ImGui::NavMoveRequestApplyResult()
         g.NavJustMovedToFocusScopeId = result->FocusScopeId;
         g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
         g.NavJustMovedToIsTabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0;
-        g.NavJustMovedToHasSelectionData = (result->InFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
+        g.NavJustMovedToHasSelectionData = (result->ItemFlags & ImGuiItemFlags_HasSelectionUserData) != 0;
         //IMGUI_DEBUG_LOG_NAV("[nav] NavJustMovedFromFocusScopeId = 0x%08X, NavJustMovedToFocusScopeId = 0x%08X\n", g.NavJustMovedFromFocusScopeId, g.NavJustMovedToFocusScopeId);
     }
 
@@ -13318,7 +13318,7 @@ void ImGui::NavMoveRequestApplyResult()
     }
 
     // Tabbing: Activates Inputable, otherwise only Focus
-    if ((g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && (result->InFlags & ImGuiItemFlags_Inputable) == 0)
+    if ((g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && (result->ItemFlags & ImGuiItemFlags_Inputable) == 0)
         g.NavMoveFlags &= ~ImGuiNavMoveFlags_Activate;
 
     // Activate
diff --git a/imgui_internal.h b/imgui_internal.h
index f7e4f662e21a..75b586c3b31c 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -823,8 +823,8 @@ enum ImGuiDataTypePrivate_
 //-----------------------------------------------------------------------------
 
 // Extend ImGuiItemFlags
-// - input: PushItemFlag() manipulates g.CurrentItemFlags, ItemAdd() calls may add extra flags.
-// - output: stored in g.LastItemData.InFlags
+// - input: PushItemFlag() manipulates g.CurrentItemFlags, g.NextItemData.ItemFlags, ItemAdd() calls may add extra flags too.
+// - output: stored in g.LastItemData.ItemFlags
 enum ImGuiItemFlagsPrivate_
 {
     // Controlled by user
@@ -908,7 +908,7 @@ enum ImGuiButtonFlagsPrivate_
     ImGuiButtonFlags_AlignTextBaseLine      = 1 << 15,  // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
     ImGuiButtonFlags_NoKeyModsAllowed       = 1 << 16,  // disable mouse interaction if a key modifier is held
     ImGuiButtonFlags_NoHoldingActiveId      = 1 << 17,  // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
-    ImGuiButtonFlags_NoNavFocus             = 1 << 18,  // don't override navigation focus when activated (FIXME: this is essentially used every time an item uses ImGuiItemFlags_NoNav, but because legacy specs don't requires LastItemData to be set ButtonBehavior(), we can't poll g.LastItemData.InFlags)
+    ImGuiButtonFlags_NoNavFocus             = 1 << 18,  // don't override navigation focus when activated (FIXME: this is essentially used every time an item uses ImGuiItemFlags_NoNav, but because legacy specs don't requires LastItemData to be set ButtonBehavior(), we can't poll g.LastItemData.ItemFlags)
     ImGuiButtonFlags_NoHoveredOnFocus       = 1 << 19,  // don't report as hovered when nav focus is on this item
     ImGuiButtonFlags_NoSetKeyOwner          = 1 << 20,  // don't set key/input owner on the initial click (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
     ImGuiButtonFlags_NoTestKeyOwner         = 1 << 21,  // don't test key/input owner when polling the key (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!)
@@ -1250,7 +1250,7 @@ struct ImGuiTreeNodeStackData
 {
     ImGuiID                 ID;
     ImGuiTreeNodeFlags      TreeFlags;
-    ImGuiItemFlags          InFlags;    // Used for nav landing
+    ImGuiItemFlags          ItemFlags;  // Used for nav landing
     ImRect                  NavRect;    // Used for nav landing
 };
 
@@ -1590,14 +1590,14 @@ struct ImGuiNavItemData
     ImGuiID             ID;             // Init,Move    // Best candidate item ID
     ImGuiID             FocusScopeId;   // Init,Move    // Best candidate focus scope ID
     ImRect              RectRel;        // Init,Move    // Best candidate bounding box in window relative space
-    ImGuiItemFlags      InFlags;        // ????,Move    // Best candidate item flags
+    ImGuiItemFlags      ItemFlags;      // ????,Move    // Best candidate item flags
     float               DistBox;        //      Move    // Best candidate box distance to current NavId
     float               DistCenter;     //      Move    // Best candidate center distance to current NavId
     float               DistAxial;      //      Move    // Best candidate axial distance to current NavId
-    ImGuiSelectionUserData SelectionUserData;//I+Mov    // Best candidate SetNextItemSelectionUserData() value. Valid if (InFlags & ImGuiItemFlags_HasSelectionUserData)
+    ImGuiSelectionUserData SelectionUserData;//I+Mov    // Best candidate SetNextItemSelectionUserData() value. Valid if (ItemFlags & ImGuiItemFlags_HasSelectionUserData)
 
     ImGuiNavItemData()  { Clear(); }
-    void Clear()        { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; }
+    void Clear()        { Window = NULL; ID = FocusScopeId = 0; ItemFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; }
 };
 
 // Storage for PushFocusScope()
@@ -2177,7 +2177,7 @@ struct ImGuiContext
     ImGuiID                 NavJustMovedToFocusScopeId;         // Just navigated to this focus scope id (result of a successfully MoveRequest).
     ImGuiKeyChord           NavJustMovedToKeyMods;
     bool                    NavJustMovedToIsTabbing;            // Copy of ImGuiNavMoveFlags_IsTabbing. Maybe we should store whole flags.
-    bool                    NavJustMovedToHasSelectionData;     // Copy of move result's InFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
+    bool                    NavJustMovedToHasSelectionData;     // Copy of move result's ItemFlags & ImGuiItemFlags_HasSelectionUserData). Maybe we should just store ImGuiNavItemData.
 
     // Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
     ImGuiKeyChord           ConfigNavWindowingKeyNext;          // = ImGuiMod_Ctrl | ImGuiKey_Tab (or ImGuiMod_Super | ImGuiKey_Tab on OS X). For reconfiguration (see #4828)
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 3aba3a4da666..60bb366313ec 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -6457,7 +6457,7 @@ static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags)
     ImGuiTreeNodeStackData* tree_node_data = &g.TreeNodeStack.back();
     tree_node_data->ID = g.LastItemData.ID;
     tree_node_data->TreeFlags = flags;
-    tree_node_data->InFlags = g.LastItemData.ItemFlags;
+    tree_node_data->ItemFlags = g.LastItemData.ItemFlags;
     tree_node_data->NavRect = g.LastItemData.NavRect;
     window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth);
 }

From 38617a5ad345126d912be491d09070fbaecb2be1 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 17 Oct 2024 15:38:00 +0200
Subject: [PATCH 208/548] Internals: remove ImGuiInputTextFlags_NoMarkEdited
 and g.LockMarkEdited n favor of ImGuiItemFlags_NoMarkEdited.

---
 imgui.cpp         |  5 ++---
 imgui.h           |  2 +-
 imgui_internal.h  |  7 +++----
 imgui_widgets.cpp | 26 +++++++++++++++++---------
 4 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 772df22a5707..182bd2162198 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3986,7 +3986,6 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     DragSpeedDefaultRatio = 1.0f / 100.0f;
     DisabledAlphaBackup = 0.0f;
     DisabledStackSize = 0;
-    LockMarkEdited = 0;
     TooltipOverrideCount = 0;
     TooltipPreviousWindow = NULL;
 
@@ -4373,10 +4372,10 @@ ImGuiID ImGui::GetHoveredID()
 
 void ImGui::MarkItemEdited(ImGuiID id)
 {
-    // This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
+    // This marking is to be able to provide info for IsItemDeactivatedAfterEdit().
     // ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data.
     ImGuiContext& g = *GImGui;
-    if (g.LockMarkEdited > 0)
+    if (g.LastItemData.ItemFlags & ImGuiItemFlags_NoMarkEdited)
         return;
     if (g.ActiveId == id || g.ActiveId == 0)
     {
diff --git a/imgui.h b/imgui.h
index ef0c59a9d50e..4ea730626e57 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1154,7 +1154,7 @@ enum ImGuiInputTextFlags_
 
     // Inputs
     ImGuiInputTextFlags_AllowTabInput       = 1 << 5,   // Pressing TAB input a '\t' character into the text field
-    ImGuiInputTextFlags_EnterReturnsTrue    = 1 << 6,   // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider looking at the IsItemDeactivatedAfterEdit() function.
+    ImGuiInputTextFlags_EnterReturnsTrue    = 1 << 6,   // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider using IsItemDeactivatedAfterEdit() instead!
     ImGuiInputTextFlags_EscapeClearsAll     = 1 << 7,   // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
     ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8,   // In multi-line mode, validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter).
 
diff --git a/imgui_internal.h b/imgui_internal.h
index 75b586c3b31c..bf7759f7bcf7 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -834,6 +834,7 @@ enum ImGuiItemFlagsPrivate_
     ImGuiItemFlags_NoWindowHoverableCheck   = 1 << 13, // false     // Disable hoverable check in ItemHoverable()
     ImGuiItemFlags_AllowOverlap             = 1 << 14, // false     // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
     ImGuiItemFlags_NoNavDisableMouseHover   = 1 << 15, // false     // Nav keyboard/gamepad mode doesn't disable hover.
+    ImGuiItemFlags_NoMarkEdited             = 1 << 16, // false     // Skip calling MarkItemEdited()
 
     // Controlled by widget code
     ImGuiItemFlags_Inputable                = 1 << 20, // false     // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature.
@@ -886,9 +887,8 @@ enum ImGuiInputTextFlagsPrivate_
 {
     // [Internal]
     ImGuiInputTextFlags_Multiline           = 1 << 26,  // For internal use by InputTextMultiline()
-    ImGuiInputTextFlags_NoMarkEdited        = 1 << 27,  // For internal use by functions using InputText() before reformatting data
-    ImGuiInputTextFlags_MergedItem          = 1 << 28,  // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
-    ImGuiInputTextFlags_LocalizeDecimalPoint= 1 << 29,  // For internal use by InputScalar() and TempInputScalar()
+    ImGuiInputTextFlags_MergedItem          = 1 << 27,  // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
+    ImGuiInputTextFlags_LocalizeDecimalPoint= 1 << 28,  // For internal use by InputScalar() and TempInputScalar()
 };
 
 // Extend ImGuiButtonFlags_
@@ -2282,7 +2282,6 @@ struct ImGuiContext
     float                   DragSpeedDefaultRatio;              // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
     float                   DisabledAlphaBackup;                // Backup for style.Alpha for BeginDisabled()
     short                   DisabledStackSize;
-    short                   LockMarkEdited;
     short                   TooltipOverrideCount;
     ImGuiWindow*            TooltipPreviousWindow;              // Window of last tooltip submitted during the frame
     ImVector          ClipboardHandlerData;               // If no custom clipboard handler is defined
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 60bb366313ec..9f171c97dc94 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3601,6 +3601,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
 {
     // FIXME: May need to clarify display behavior if format doesn't contain %.
     // "%d" -> "%d" / "There are %d items" -> "%d" / "items" -> "%d" (fallback). Also see #6405
+    ImGuiContext& g = *GImGui;
     const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type);
     char fmt_buf[32];
     char data_buf[32];
@@ -3610,8 +3611,8 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
     DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
     ImStrTrimBlanks(data_buf);
 
-    ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
-
+    ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
+    g.LastItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited; // Because TempInputText() uses ImGuiInputTextFlags_MergedItem it doesn't submit a new item, so we poke LastItemData.
     bool value_changed = false;
     if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags))
     {
@@ -3630,6 +3631,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
         }
 
         // Only mark as edited if new value is different
+        g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
         value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
         if (value_changed)
             MarkItemEdited(id);
@@ -3666,8 +3668,10 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
     else
         DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
 
-    flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
-    flags |= (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
+    // Disable the MarkItemEdited() call in InputText but keep ImGuiItemStatusFlags_Edited.
+    // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
+    g.NextItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited;
+    flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
 
     bool value_changed = false;
     if (p_step == NULL)
@@ -3719,6 +3723,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
         PopID();
         EndGroup();
     }
+
+    g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
     if (value_changed)
         MarkItemEdited(g.LastItemData.ID);
 
@@ -5315,7 +5321,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     if (label_size.x > 0)
         RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
 
-    if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited))
+    if (value_changed)
         MarkItemEdited(id);
 
     IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable);
@@ -6196,8 +6202,9 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
     bool allow_opt_datatype = !(flags & ImGuiColorEditFlags_DataTypeMask_);
     if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context"))
         return;
+
     ImGuiContext& g = *GImGui;
-    g.LockMarkEdited++;
+    PushItemFlag(ImGuiItemFlags_NoMarkEdited, true);
     ImGuiColorEditFlags opts = g.ColorEditOptions;
     if (allow_opt_inputs)
     {
@@ -6239,8 +6246,8 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
     }
 
     g.ColorEditOptions = opts;
+    PopItemFlag();
     EndPopup();
-    g.LockMarkEdited--;
 }
 
 void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags)
@@ -6249,8 +6256,9 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
     bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar);
     if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context"))
         return;
+
     ImGuiContext& g = *GImGui;
-    g.LockMarkEdited++;
+    PushItemFlag(ImGuiItemFlags_NoMarkEdited, true);
     if (allow_opt_picker)
     {
         ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function
@@ -6279,8 +6287,8 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
         if (allow_opt_picker) Separator();
         CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);
     }
+    PopItemFlag();
     EndPopup();
-    g.LockMarkEdited--;
 }
 
 //-------------------------------------------------------------------------

From 604f2fa84aa2c71cab53e07235557b5b9207b76e Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 17 Oct 2024 15:42:11 +0200
Subject: [PATCH 209/548] InputScalar: added an assert to clarify that
 ImGuiInputTextFlags_EnterReturnsTrue is not supported by InputFloat, InputInt
 etc. (#8065)

It was never correctly supported. Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit().
---
 docs/CHANGELOG.txt | 2 ++
 imgui_widgets.cpp  | 1 +
 2 files changed, 3 insertions(+)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 5d61daa549a1..373c12f7037b 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -93,6 +93,8 @@ Other changes:
   preventing use of external shortcuts not guarded by an ActiveId check. (#8048) [@geertbleyen]
 - InputText: ensure mouse cursor shape is set regardless of whether keyboard mode is 
   enabled or not. (#6417)
+- InputScalar: added an assert to clarify that ImGuiInputTextFlags_EnterReturnsTrue is not
+  supported by InputFloat, InputInt, InputScalar etc. widgets. It actually never was. (#8065)
 - imgui_freetype: Added support for plutosvg (as an alternative to lunasvg) to render 
   OpenType SVG fonts. Requires defining IMGUI_ENABLE_FREETYPE_PLUTOSVG along with IMGUI_ENABLE_FREETYPE.
   Providing headers/librairies for plutosvg + plutovg is up to you (see #7927 for help).
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 9f171c97dc94..8a504ef1d52e 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3656,6 +3656,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
 
     ImGuiContext& g = *GImGui;
     ImGuiStyle& style = g.Style;
+    IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()!
 
     if (format == NULL)
         format = DataTypeGetInfo(data_type)->PrintFmt;

From db26fe7ca8de76d7802cb5c74f683e42870754ee Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 18 Oct 2024 12:35:19 +0200
Subject: [PATCH 210/548] Debug Tools: Metrics: Fixed a crash when browsing
 "InputText" section before using one. (#8071)

Caused by 21d03edcb
---
 imgui_widgets.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 8a504ef1d52e..c8e0a5b5e967 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4129,6 +4129,7 @@ ImGuiInputTextState::ImGuiInputTextState()
 {
     memset(this, 0, sizeof(*this));
     Stb = IM_NEW(ImStbTexteditState);
+    memset(Stb, 0, sizeof(*Stb));
 }
 
 ImGuiInputTextState::~ImGuiInputTextState()

From 7a56b411247a9bbe32b7642f4434561e4bc6c3eb Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 17 Oct 2024 19:57:18 +0200
Subject: [PATCH 211/548] Nav: added io.ConfigNavEscapeClearFocusItem. (#8059,
 #2048, #1074, #3200)

---
 docs/CHANGELOG.txt | 11 ++++++++---
 docs/TODO.txt      |  4 ++--
 imgui.cpp          |  9 ++++++---
 imgui.h            |  5 +++--
 imgui_demo.cpp     |  2 ++
 imgui_internal.h   |  4 +++-
 6 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 373c12f7037b..12970915222a 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,8 +43,8 @@ Breaking changes:
 
 - The typedef for ImTextureID now defaults to ImU64 instead of void*. (#1641)
   - This removes the requirement to redefine it for backends which are e.g. storing
-    descriptor sets or other 64-bits structures when building on 32-bits archs.
-    It therefore simplify various building scripts/helpers.
+    descriptor sets or other 64-bits structures when building on 32-bits archs
+    (namely our DX12 and Vulkan backends). It therefore simplify various building scripts/helpers.
   - You may have compile-time issues if you were casting to 'void*' instead of 'ImTextureID'
     when passing your types to functions taking ImTextureID values, e.g. ImGui::Image().
     In doubt it is almost always better to do an intermediate intptr_t cast, since it
@@ -67,7 +67,12 @@ Other changes:
   state to draw callbacks. (#6969, #5834, #7468, #3590)
 - IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
 - Error Handling: turned a few more functions into recoverable errors. (#1651)
-- Nav: added io.ConfigNavEscapeClearFocusWindow to clear focused window on Escape. (#3200)
+- Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change
+  how pressing Escape affects navigation. (#8059, #2048, #1074, #3200)
+  - Set io.ConfigNavEscapeClearFocusItem = true (default) to clear focused item and highlight.
+  - Set io.ConfigNavEscapeClearFocusItem = false for Escape to not have a specific effect.
+  - Set io.ConfigNavEscapeClearFocusWindow = true to completely unfocus the dear imgui window,
+    is for some reason your app relies on imgui focus to take other decisions.  
 - Nav: pressing escape to hide nav highlight doesn't clear location from when ctrl+tabbing 
   back into same window later.
 - Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
diff --git a/docs/TODO.txt b/docs/TODO.txt
index e61501d78624..dd98d18b17d3 100644
--- a/docs/TODO.txt
+++ b/docs/TODO.txt
@@ -275,13 +275,13 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
 
  - nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line? how about CTRL+Tab)
  ! nav: never clear NavId on some setup (e.g. gamepad centric)
- - nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable.
  - nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view?
  - nav: NavScrollToBringItemIntoView() with item bigger than view should focus top-right? Repro: using Nav in "About Window"
- - nav: wrap around logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping().
+ - nav: expose wrap around flags/logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping().
  - nav: patterns to make it possible for arrows key to update selection (see JustMovedTo in range_select branch)
  - nav: restore/find nearest NavId when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name)
  - nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem
+ - nav: holding space to repeat a button doesn't show button activated during hold.
  - nav: NavFlattened: init requests don't work properly on flattened siblings.
  - nav: NavFlattened: pageup/pagedown/home/end don't work properly on flattened siblings.
  - nav: NavFlattened: ESC on a flattened child should select something.
diff --git a/imgui.cpp b/imgui.cpp
index 182bd2162198..773272e2c316 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1409,6 +1409,7 @@ ImGuiIO::ImGuiIO()
     ConfigNavSwapGamepadButtons = false;
     ConfigNavMoveSetMousePos = false;
     ConfigNavCaptureKeyboard = true;
+    ConfigNavEscapeClearFocusItem = true;
     ConfigNavEscapeClearFocusWindow = false;
     ConfigInputTrickleEventQueue = true;
     ConfigInputTextCursorBlink = true;
@@ -13376,11 +13377,13 @@ static void ImGui::NavUpdateCancelRequest()
     {
         // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
         // FIXME-NAV: This should happen on window appearing.
-        if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup)))// || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
-            g.NavWindow->NavLastIds[0] = 0;
+        if (g.IO.ConfigNavEscapeClearFocusItem || g.IO.ConfigNavEscapeClearFocusWindow)
+            if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup)))// || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
+                g.NavWindow->NavLastIds[0] = 0;
 
         // Clear nav focus
-        g.NavId = 0;
+        if (g.IO.ConfigNavEscapeClearFocusItem || g.IO.ConfigNavEscapeClearFocusWindow)
+            g.NavId = 0;
         if (g.IO.ConfigNavEscapeClearFocusWindow)
             FocusWindow(NULL);
     }
diff --git a/imgui.h b/imgui.h
index 4ea730626e57..641f1d54dd44 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2250,7 +2250,8 @@ struct ImGuiIO
     bool        ConfigNavSwapGamepadButtons;    // = false          // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
     bool        ConfigNavMoveSetMousePos;       // = false          // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true. 
     bool        ConfigNavCaptureKeyboard;       // = true           // Sets io.WantCaptureKeyboard when io.NavActive is set.
-    bool        ConfigNavEscapeClearFocusWindow;// = false          // Pressing Escape (when no item is active, no popup open etc.) clears focused window + navigation id/highlight.
+    bool        ConfigNavEscapeClearFocusItem;  // = true           // Pressing Escape can clear focused item + navigation id/highlight. Set to false if you want to always keep highlight on.
+    bool        ConfigNavEscapeClearFocusWindow;// = false          // Pressing Escape can clear focused window as well (super set of io.ConfigNavEscapeClearFocusItem).
     bool        ConfigInputTrickleEventQueue;   // = true           // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
     bool        ConfigInputTextCursorBlink;     // = true           // Enable blinking cursor (optional as some users consider it to be distracting).
     bool        ConfigInputTextEnterKeepActive; // = false          // [BETA] Pressing Enter will keep item active and select contents (single-line only).
@@ -2367,7 +2368,7 @@ struct ImGuiIO
     bool        WantSetMousePos;                    // MousePos has been altered, backend should reposition mouse on next frame. Rarely used! Set only when io.ConfigNavMoveSetMousePos is enabled.
     bool        WantSaveIniSettings;                // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving!
     bool        NavActive;                          // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag.
-    bool        NavVisible;                         // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events).
+    bool        NavVisible;                         // Keyboard/Gamepad navigation highlight is visible and allowed (will handle ImGuiKey_NavXXX events).
     float       Framerate;                          // Estimate of application framerate (rolling average over 60 frames, based on io.DeltaTime), in frame per second. Solely for convenience. Slow applications may not want to use a moving average or may want to reset underlying buffers occasionally.
     int         MetricsRenderVertices;              // Vertices output during last call to Render()
     int         MetricsRenderIndices;               // Indices output during last call to Render() = number of triangles * 3
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index dca67405460f..63f6d15d1209 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -532,6 +532,8 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::Checkbox("io.ConfigNavMoveSetMousePos", &io.ConfigNavMoveSetMousePos);
             ImGui::SameLine(); HelpMarker("Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult");
             ImGui::Checkbox("io.ConfigNavCaptureKeyboard", &io.ConfigNavCaptureKeyboard);
+            ImGui::Checkbox("io.ConfigNavEscapeClearFocusItem", &io.ConfigNavEscapeClearFocusItem);
+            ImGui::SameLine(); HelpMarker("Pressing Escape clears focused item.");
             ImGui::Checkbox("io.ConfigNavEscapeClearFocusWindow", &io.ConfigNavEscapeClearFocusWindow);
             ImGui::SameLine(); HelpMarker("Pressing Escape clears focused window.");
 
diff --git a/imgui_internal.h b/imgui_internal.h
index bf7759f7bcf7..bc00d0c28fa9 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1600,7 +1600,7 @@ struct ImGuiNavItemData
     void Clear()        { Window = NULL; ID = FocusScopeId = 0; ItemFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; }
 };
 
-// Storage for PushFocusScope()
+// Storage for PushFocusScope(), g.FocusScopeStack[], g.NavFocusRoute[]
 struct ImGuiFocusScopeData
 {
     ImGuiID             ID;
@@ -3223,6 +3223,8 @@ namespace ImGui
     IMGUI_API void          RenderDragDropTargetRect(const ImRect& bb, const ImRect& item_clip_rect);
 
     // Typing-Select API
+    // (provide Windows Explorer style "select items by typing partial name" + "cycle through items by typing same letter" feature)
+    // (this is currently not documented nor used by main library, but should work. See "widgets_typingselect" in imgui_test_suite for usage code. Please let us know if you use this!)
     IMGUI_API ImGuiTypingSelectRequest* GetTypingSelectRequest(ImGuiTypingSelectFlags flags = ImGuiTypingSelectFlags_None);
     IMGUI_API int           TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx);
     IMGUI_API int           TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx);

From 23b655f8e3a37305a89174e32ceaab057dc67318 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 18 Oct 2024 16:42:22 +0200
Subject: [PATCH 212/548] Internals: (Breaking) changed g.NavDisableHighlight
 to g.NavCursorVisible : same logic but inverted value. (#1074, #2048, #7237,
 #8059, #1712, #7370, #787)

---
 imgui.cpp         | 36 ++++++++++++++++++------------------
 imgui.h           |  2 +-
 imgui_internal.h  |  3 ++-
 imgui_widgets.cpp | 10 +++++-----
 4 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 773272e2c316..4dd02ee0a02f 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3701,7 +3701,7 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
     ImGuiContext& g = *GImGui;
     if (id != g.NavId)
         return;
-    if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
+    if (!g.NavCursorVisible && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
         return;
     if (id == g.LastItemData.ID && (g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav))
         return;
@@ -3910,7 +3910,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
     NavIdIsAlive = false;
     NavMousePosDirty = false;
-    NavDisableHighlight = true;
+    NavCursorVisible = false;
     NavDisableMouseHover = false;
 
     NavAnyRequest = false;
@@ -4444,7 +4444,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
     ImGuiWindow* window = g.CurrentWindow;
     IM_ASSERT_USER_ERROR((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0, "Invalid flags for IsItemHovered()!");
 
-    if (g.NavDisableMouseHover && !g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride))
+    if (g.NavDisableMouseHover && g.NavCursorVisible && !(flags & ImGuiHoveredFlags_NoNavOverride))
     {
         if (!IsItemFocused())
             return false;
@@ -4824,7 +4824,7 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
     ImGuiContext& g = *GImGui;
     FocusWindow(window);
     SetActiveID(window->MoveId, window);
-    g.NavDisableHighlight = true;
+    g.NavCursorVisible = false;
     g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos;
     g.ActiveIdNoClearOnFocusLoss = true;
     SetActiveIdUsingAllKeyboardKeys();
@@ -5835,7 +5835,7 @@ bool ImGui::IsAnyItemActive()
 bool ImGui::IsAnyItemFocused()
 {
     ImGuiContext& g = *GImGui;
-    return g.NavId != 0 && !g.NavDisableHighlight;
+    return g.NavId != 0 && g.NavCursorVisible;
 }
 
 bool ImGui::IsItemVisible()
@@ -6689,7 +6689,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
         // Title bar only
         const float backup_border_size = style.FrameBorderSize;
         g.Style.FrameBorderSize = window->WindowBorderSize;
-        ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
+        ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && g.NavCursorVisible) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
         RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding);
         g.Style.FrameBorderSize = backup_border_size;
     }
@@ -12189,7 +12189,7 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
 
         ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_MOUSE * scale;
         ImRect r_avoid;
-        if (!g.NavDisableHighlight && g.NavDisableMouseHover && !g.IO.ConfigNavMoveSetMousePos)
+        if (g.NavCursorVisible && g.NavDisableMouseHover && !g.IO.ConfigNavMoveSetMousePos)
             r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
         else
             r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
@@ -12272,7 +12272,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
     if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
         g.NavDisableMouseHover = true;
     else
-        g.NavDisableHighlight = true;
+        g.NavCursorVisible = false;
 
     // Clear preferred scoring position (NavMoveRequestApplyResult() will tend to restore it)
     NavClearPreferredPosForAxis(ImGuiAxis_X);
@@ -12738,7 +12738,7 @@ void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
 void ImGui::NavRestoreHighlightAfterMove()
 {
     ImGuiContext& g = *GImGui;
-    g.NavDisableHighlight = false;
+    g.NavCursorVisible = true;
     g.NavDisableMouseHover = g.NavMousePosDirty = true;
 }
 
@@ -12789,7 +12789,7 @@ static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource()
     const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
 
     // Testing for !activated_shortcut here could in theory be removed if we decided that activating a remote shortcut altered one of the g.NavDisableXXX flag.
-    if ((g.NavDisableHighlight || !g.NavDisableMouseHover || !window) && !activated_shortcut)
+    if ((!g.NavCursorVisible || !g.NavDisableMouseHover || !window) && !activated_shortcut)
         return ImGuiInputSource_Mouse;
     else
         return ImGuiInputSource_Keyboard; // or Nav in general
@@ -12897,7 +12897,7 @@ static void ImGui::NavUpdate()
     // Schedule mouse position update (will be done at the bottom of this function, after 1) processing all move requests and 2) updating scrolling)
     bool set_mouse_pos = false;
     if (g.NavMousePosDirty && g.NavIdIsAlive)
-        if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
+        if (g.NavCursorVisible && g.NavDisableMouseHover && g.NavWindow)
             set_mouse_pos = true;
     g.NavMousePosDirty = false;
     IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu);
@@ -12913,7 +12913,7 @@ static void ImGui::NavUpdate()
 
     // Set output flags for user application
     io.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
-    io.NavVisible = (io.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL);
+    io.NavVisible = (io.NavActive && g.NavId != 0 && g.NavCursorVisible) || (g.NavWindowingTarget != NULL);
 
     // Process NavCancel input (to close a popup, get back to parent, clear focus)
     NavUpdateCancelRequest();
@@ -12921,7 +12921,7 @@ static void ImGui::NavUpdate()
     // Process manual activation request
     g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0;
     g.NavActivateFlags = ImGuiActivateFlags_None;
-    if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
+    if (g.NavId != 0 && g.NavCursorVisible && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
     {
         const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_NoOwner));
         const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, 0, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, 0, ImGuiKeyOwner_NoOwner)));
@@ -12946,7 +12946,7 @@ static void ImGui::NavUpdate()
         }
     }
     if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
-        g.NavDisableHighlight = true;
+        g.NavCursorVisible = false;
     if (g.NavActivateId != 0)
         IM_ASSERT(g.NavActivateDownId == g.NavActivateId);
 
@@ -13003,7 +13003,7 @@ static void ImGui::NavUpdate()
     // Always prioritize mouse highlight if navigation is disabled
     if (!nav_keyboard_active && !nav_gamepad_active)
     {
-        g.NavDisableHighlight = true;
+        g.NavCursorVisible = false;
         g.NavDisableMouseHover = set_mouse_pos = false;
     }
 
@@ -13147,7 +13147,7 @@ void ImGui::NavUpdateCreateMoveRequest()
         IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name : "", g.NavLayer);
         g.NavInitRequest = g.NavInitRequestFromMove = true;
         g.NavInitResult.ID = 0;
-        g.NavDisableHighlight = false;
+        g.NavCursorVisible = true;
     }
 
     // When using gamepad, we project the reference nav bounding box into window visible area.
@@ -13211,7 +13211,7 @@ void ImGui::NavUpdateCreateTabbingRequest()
     // See NavProcessItemForTabbingRequest() for a description of the various forward/backward tabbing cases with and without wrapping.
     const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
     if (nav_keyboard_active)
-        g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.NavDisableHighlight == true && g.ActiveId == 0) ? 0 : +1;
+        g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.NavCursorVisible == false && g.ActiveId == 0) ? 0 : +1;
     else
         g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.ActiveId == 0) ? 0 : +1;
     ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate;
@@ -15823,7 +15823,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
         Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
         Text("NavActivateId/DownId/PressedId: %08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId);
         Text("NavActivateFlags: %04X", g.NavActivateFlags);
-        Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
+        Text("NavCursorVisible: %d, NavDisableMouseHover: %d", g.NavCursorVisible, g.NavDisableMouseHover);
         Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId);
         Text("NavFocusRoute[] = ");
         for (int path_n = g.NavFocusRoute.Size - 1; path_n >= 0; path_n--)
diff --git a/imgui.h b/imgui.h
index 641f1d54dd44..d89661bf2d18 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.4 WIP"
-#define IMGUI_VERSION_NUM   19135
+#define IMGUI_VERSION_NUM   19136
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index bc00d0c28fa9..a0f1c1c094f8 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2144,7 +2144,8 @@ struct ImGuiContext
     ImGuiSelectionUserData  NavLastValidSelectionUserData;      // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
     bool                    NavIdIsAlive;                       // Nav widget has been seen this frame ~~ NavRectRel is valid
     bool                    NavMousePosDirty;                   // When set we will update mouse position if io.ConfigNavMoveSetMousePos is set (not enabled by default)
-    bool                    NavDisableHighlight;                // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
+    bool                    NavCursorVisible;                   // Nav focus rectangle is visible? We hide it after a mouse click. We show it after a nav move.
+    //bool                  NavDisableHighlight;                // Before 1.91.4 (2024/10/18) we used g.NavDisableHighlight. g.NavCursorVisible is the new variable name, with opposite value (g.NavDisableHighlight = !g.NavCursorVisible)
     bool                    NavDisableMouseHover;               // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again.
 
     // Navigation: Init & Move Requests
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index c8e0a5b5e967..7e67cea4ed66 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -620,12 +620,12 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
         }
 
         if (pressed)
-            g.NavDisableHighlight = true;
+            g.NavCursorVisible = false;
     }
 
     // Gamepad/Keyboard handling
     // We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse.
-    if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover)
+    if (g.NavId == id && g.NavCursorVisible && g.NavDisableMouseHover)
         if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
             hovered = true;
     if (g.NavActivateDownId == id)
@@ -689,7 +689,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
                 ClearActiveID();
             }
             if (!(flags & ImGuiButtonFlags_NoNavFocus))
-                g.NavDisableHighlight = true;
+                g.NavCursorVisible = false;
         }
         else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
         {
@@ -7001,7 +7001,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
         if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
         {
             SetNavID(id, window->DC.NavLayerCurrent, g.CurrentFocusScopeId, WindowRectAbsToRel(window, bb)); // (bb == NavRect)
-            g.NavDisableHighlight = true;
+            g.NavCursorVisible = false;
         }
     }
     if (pressed)
@@ -8624,7 +8624,7 @@ void ImGui::EndMenuBar()
             IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check (FIXME: Seems unnecessary)
             FocusWindow(window);
             SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
-            g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
+            g.NavCursorVisible = false; // Hide nav cursor for the current frame so we don't see the intermediary selection.
             g.NavDisableMouseHover = g.NavMousePosDirty = true;
             NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Repeat
         }

From 0536ace2b6c24bd1fb14550ac83e035e879834c1 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 18 Oct 2024 16:46:14 +0200
Subject: [PATCH 213/548] Internals: (Breaking) renamed RenderNavHighlight() to
 RenderNavCursor(), ImGuiNavHighlightFlags to ImGuiNavRenderCursorFlags.
 (#1074, #2048, #7237, #8059, #1712, #7370, #787)

+ referenced in #8057, #3882, #3411, #2155, #3351, #4722, #1658, #4050.
---
 imgui.cpp         | 14 +++++++-------
 imgui_internal.h  | 23 ++++++++++++++++-------
 imgui_tables.cpp  |  2 +-
 imgui_widgets.cpp | 46 +++++++++++++++++++++++-----------------------
 4 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 4dd02ee0a02f..6679291c2aa1 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3696,12 +3696,12 @@ void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
     }
 }
 
-void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags)
+void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags)
 {
     ImGuiContext& g = *GImGui;
     if (id != g.NavId)
         return;
-    if (!g.NavCursorVisible && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
+    if (!g.NavCursorVisible && !(flags & ImGuiNavRenderCursorFlags_AlwaysDraw))
         return;
     if (id == g.LastItemData.ID && (g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav))
         return;
@@ -3709,11 +3709,11 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl
     if (window->DC.NavHideHighlightOneFrame)
         return;
 
-    float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
+    float rounding = (flags & ImGuiNavRenderCursorFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
     ImRect display_rect = bb;
     display_rect.ClipWith(window->ClipRect);
     const float thickness = 2.0f;
-    if (flags & ImGuiNavHighlightFlags_Compact)
+    if (flags & ImGuiNavRenderCursorFlags_Compact)
     {
         window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness);
     }
@@ -6067,11 +6067,11 @@ void ImGui::EndChild()
         if ((child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY) && !nav_flattened)
         {
             ItemAdd(bb, child_window->ChildId);
-            RenderNavHighlight(bb, child_window->ChildId);
+            RenderNavCursor(bb, child_window->ChildId);
 
             // When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying)
             if (child_window->DC.NavLayersActiveMask == 0 && child_window == g.NavWindow)
-                RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_Compact);
+                RenderNavCursor(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavRenderCursorFlags_Compact);
         }
         else
         {
@@ -15950,7 +15950,7 @@ bool ImGui::DebugBreakButton(const char* label, const char* description_of_locat
     ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z, hsv.x, hsv.y, hsv.z);
     ColorConvertHSVtoRGB(hsv.x + 0.20f, hsv.y, hsv.z, col4f.x, col4f.y, col4f.z);
 
-    RenderNavHighlight(bb, id);
+    RenderNavCursor(bb, id);
     RenderFrame(bb.Min, bb.Max, GetColorU32(col4f), true, g.Style.FrameRounding);
     RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size, g.Style.ButtonTextAlign, &bb);
 
diff --git a/imgui_internal.h b/imgui_internal.h
index a0f1c1c094f8..94e0cb0e0438 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -177,7 +177,7 @@ typedef int ImGuiDebugLogFlags;         // -> enum ImGuiDebugLogFlags_      // F
 typedef int ImGuiFocusRequestFlags;     // -> enum ImGuiFocusRequestFlags_  // Flags: for FocusWindow()
 typedef int ImGuiItemStatusFlags;       // -> enum ImGuiItemStatusFlags_    // Flags: for g.LastItemData.StatusFlags
 typedef int ImGuiOldColumnFlags;        // -> enum ImGuiOldColumnFlags_     // Flags: for BeginColumns()
-typedef int ImGuiNavHighlightFlags;     // -> enum ImGuiNavHighlightFlags_  // Flags: for RenderNavHighlight()
+typedef int ImGuiNavRenderCursorFlags;  // -> enum ImGuiNavRenderCursorFlags_//Flags: for RenderNavCursor()
 typedef int ImGuiNavMoveFlags;          // -> enum ImGuiNavMoveFlags_       // Flags: for navigation requests
 typedef int ImGuiNextItemDataFlags;     // -> enum ImGuiNextItemDataFlags_  // Flags: for SetNextItemXXX() functions
 typedef int ImGuiNextWindowDataFlags;   // -> enum ImGuiNextWindowDataFlags_// Flags: for SetNextWindowXXX() functions
@@ -1546,12 +1546,18 @@ enum ImGuiScrollFlags_
     ImGuiScrollFlags_MaskY_                 = ImGuiScrollFlags_KeepVisibleEdgeY | ImGuiScrollFlags_KeepVisibleCenterY | ImGuiScrollFlags_AlwaysCenterY,
 };
 
-enum ImGuiNavHighlightFlags_
+enum ImGuiNavRenderCursorFlags_
 {
-    ImGuiNavHighlightFlags_None             = 0,
-    ImGuiNavHighlightFlags_Compact          = 1 << 1,       // Compact highlight, no padding
-    ImGuiNavHighlightFlags_AlwaysDraw       = 1 << 2,       // Draw rectangular highlight if (g.NavId == id) _even_ when using the mouse.
-    ImGuiNavHighlightFlags_NoRounding       = 1 << 3,
+    ImGuiNavRenderCursorFlags_None          = 0,
+    ImGuiNavRenderCursorFlags_Compact       = 1 << 1,       // Compact highlight, no padding/distance from focused item
+    ImGuiNavRenderCursorFlags_AlwaysDraw    = 1 << 2,       // Draw rectangular highlight if (g.NavId == id) even when g.NavCursorVisible == false, aka even when using the mouse.
+    ImGuiNavRenderCursorFlags_NoRounding    = 1 << 3,
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+    ImGuiNavHighlightFlags_None             = ImGuiNavRenderCursorFlags_None,       // Renamed in 1.91.4
+    ImGuiNavHighlightFlags_Compact          = ImGuiNavRenderCursorFlags_Compact,    // Renamed in 1.91.4
+    ImGuiNavHighlightFlags_AlwaysDraw       = ImGuiNavRenderCursorFlags_AlwaysDraw, // Renamed in 1.91.4
+    ImGuiNavHighlightFlags_NoRounding       = ImGuiNavRenderCursorFlags_NoRounding, // Renamed in 1.91.4
+#endif
 };
 
 enum ImGuiNavMoveFlags_
@@ -3343,7 +3349,10 @@ namespace ImGui
     IMGUI_API void          RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders = true, float rounding = 0.0f);
     IMGUI_API void          RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
     IMGUI_API void          RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
-    IMGUI_API void          RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_None); // Navigation highlight
+    IMGUI_API void          RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None); // Navigation highlight
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+    inline    void          RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None) { RenderNavCursor(bb, id, flags); } // Renamed in 1.91.4
+#endif
     IMGUI_API const char*   FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
     IMGUI_API void          RenderMouseCursor(ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow);
 
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index 3ba15fef5ac6..1f8035cde6f2 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -3139,7 +3139,7 @@ void ImGui::TableHeader(const char* label)
         if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0)
             TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn);
     }
-    RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding);
+    RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact | ImGuiNavRenderCursorFlags_NoRounding);
     if (held)
         table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n;
     window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f;
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 7e67cea4ed66..e5f2acc8dc40 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -739,7 +739,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
 
     // Render
     const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
-    RenderNavHighlight(bb, id);
+    RenderNavCursor(bb, id);
     RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
 
     if (g.LogEnabled)
@@ -791,7 +791,7 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg, ImGuiBut
 
     bool hovered, held;
     bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
-    RenderNavHighlight(bb, id);
+    RenderNavCursor(bb, id);
 
     IMGUI_TEST_ENGINE_ITEM_INFO(id, str_id, g.LastItemData.StatusFlags);
     return pressed;
@@ -817,7 +817,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu
     // Render
     const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
     const ImU32 text_col = GetColorU32(ImGuiCol_Text);
-    RenderNavHighlight(bb, id);
+    RenderNavCursor(bb, id);
     RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
     RenderArrow(window->DrawList, bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), text_col, dir);
 
@@ -858,7 +858,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
     ImU32 bg_col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
     if (hovered)
         window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col);
-    RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact);
+    RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact);
     ImU32 cross_col = GetColorU32(ImGuiCol_Text);
     ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
     float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
@@ -885,7 +885,7 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos)
     ImU32 text_col = GetColorU32(ImGuiCol_Text);
     if (hovered || held)
         window->DrawList->AddRectFilled(bb.Min, bb.Max, bg_col);
-    RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact);
+    RenderNavCursor(bb, id, ImGuiNavRenderCursorFlags_Compact);
     RenderArrow(window->DrawList, bb.Min, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f);
 
     // Switch to moving the window after mouse is moved beyond the initial drag threshold
@@ -1092,7 +1092,7 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& imag
 
     // Render
     const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
-    RenderNavHighlight(bb, id);
+    RenderNavCursor(bb, id);
     RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
     if (bg_col.w > 0.0f)
         window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
@@ -1183,7 +1183,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
     const bool mixed_value = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
     if (is_visible)
     {
-        RenderNavHighlight(total_bb, id);
+        RenderNavCursor(total_bb, id);
         RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
         ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
         if (mixed_value)
@@ -1285,7 +1285,7 @@ bool ImGui::RadioButton(const char* label, bool active)
     if (pressed)
         MarkItemEdited(id);
 
-    RenderNavHighlight(total_bb, id);
+    RenderNavCursor(total_bb, id);
     const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius);
     window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment);
     if (active)
@@ -1425,7 +1425,7 @@ bool ImGui::TextLink(const char* label)
 
     bool hovered, held;
     bool pressed = ButtonBehavior(bb, id, &hovered, &held);
-    RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_None);
+    RenderNavCursor(bb, id);
 
     if (hovered)
         SetMouseCursor(ImGuiMouseCursor_Hand);
@@ -1856,7 +1856,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
     // Render shape
     const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
     const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size);
-    RenderNavHighlight(bb, id);
+    RenderNavCursor(bb, id);
     if (!(flags & ImGuiComboFlags_NoPreview))
         window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft);
     if (!(flags & ImGuiComboFlags_NoArrowButton))
@@ -2658,7 +2658,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
 
     // Draw frame
     const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
-    RenderNavHighlight(frame_bb, id);
+    RenderNavCursor(frame_bb, id);
     RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
 
     // Drag behavior
@@ -3240,7 +3240,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
 
     // Draw frame
     const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
-    RenderNavHighlight(frame_bb, id);
+    RenderNavCursor(frame_bb, id);
     RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
 
     // Slider behavior
@@ -3389,7 +3389,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
 
     // Draw frame
     const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
-    RenderNavHighlight(frame_bb, id);
+    RenderNavCursor(frame_bb, id);
     RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
 
     // Slider behavior
@@ -5102,7 +5102,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     // Render frame
     if (!is_multiline)
     {
-        RenderNavHighlight(frame_bb, id);
+        RenderNavCursor(frame_bb, id);
         RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
     }
 
@@ -6113,7 +6113,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
         else
             window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding);
     }
-    RenderNavHighlight(bb, id);
+    RenderNavCursor(bb, id);
     if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
     {
         if (g.Style.FrameBorderSize > 0.0f)
@@ -6677,15 +6677,15 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
     // Render
     {
         const ImU32 text_col = GetColorU32(ImGuiCol_Text);
-        ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact;
+        ImGuiNavRenderCursorFlags nav_render_cursor_flags = ImGuiNavRenderCursorFlags_Compact;
         if (is_multi_select)
-            nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle
+            nav_render_cursor_flags |= ImGuiNavRenderCursorFlags_AlwaysDraw; // Always show the nav rectangle
         if (display_frame)
         {
             // Framed type
             const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
             RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
-            RenderNavHighlight(frame_bb, id, nav_highlight_flags);
+            RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
             if (flags & ImGuiTreeNodeFlags_Bullet)
                 RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
             else if (!is_leaf)
@@ -6705,7 +6705,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
                 const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
                 RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
             }
-            RenderNavHighlight(frame_bb, id, nav_highlight_flags);
+            RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
             if (flags & ImGuiTreeNodeFlags_Bullet)
                 RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
             else if (!is_leaf)
@@ -7026,10 +7026,10 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
         }
         if (g.NavId == id)
         {
-            ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding;
+            ImGuiNavRenderCursorFlags nav_render_cursor_flags = ImGuiNavRenderCursorFlags_Compact | ImGuiNavRenderCursorFlags_NoRounding;
             if (is_multi_select)
-                nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle
-            RenderNavHighlight(bb, id, nav_highlight_flags);
+                nav_render_cursor_flags |= ImGuiNavRenderCursorFlags_AlwaysDraw; // Always show the nav rectangle
+            RenderNavCursor(bb, id, nav_render_cursor_flags);
         }
     }
 
@@ -10109,7 +10109,7 @@ bool    ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
         float y_offset = 1.0f * g.CurrentDpiScale;
         display_draw_list->AddLine(bb.GetTL() + ImVec2(x_offset, y_offset), bb.GetTR() + ImVec2(-x_offset, y_offset), GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline), style.TabBarOverlineSize);
     }
-    RenderNavHighlight(bb, id);
+    RenderNavCursor(bb, id);
 
     // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
     const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);

From 0bae2db77fdfe16f0f3c0f76b3af60de9f624b5e Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 18 Oct 2024 18:07:58 +0200
Subject: [PATCH 214/548] Internals: (Breaking) renamed NavDisableMouseHover to
 NavHighlightItemUnderNav.

Considering adding NavHighlightItemUnderMouse as well, but would require to resolve quite a few ambiguities and for a feature we don't have yet.
---
 imgui.cpp         | 30 +++++++++++++++---------------
 imgui_internal.h  |  9 +++++----
 imgui_widgets.cpp | 14 +++++++-------
 3 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 6679291c2aa1..09acf5cd6414 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3911,7 +3911,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     NavIdIsAlive = false;
     NavMousePosDirty = false;
     NavCursorVisible = false;
-    NavDisableMouseHover = false;
+    NavHighlightItemUnderNav = false;
 
     NavAnyRequest = false;
     NavInitRequest = false;
@@ -4444,7 +4444,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
     ImGuiWindow* window = g.CurrentWindow;
     IM_ASSERT_USER_ERROR((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0, "Invalid flags for IsItemHovered()!");
 
-    if (g.NavDisableMouseHover && g.NavCursorVisible && !(flags & ImGuiHoveredFlags_NoNavOverride))
+    if (g.NavHighlightItemUnderNav && g.NavCursorVisible && !(flags & ImGuiHoveredFlags_NoNavOverride))
     {
         if (!IsItemFocused())
             return false;
@@ -4615,7 +4615,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
     }
 #endif
 
-    if (g.NavDisableMouseHover && (item_flags & ImGuiItemFlags_NoNavDisableMouseHover) == 0)
+    if (g.NavHighlightItemUnderNav && (item_flags & ImGuiItemFlags_NoNavDisableMouseHover) == 0)
         return false;
 
     return true;
@@ -6589,7 +6589,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
             g.NavWindowingAccumDeltaSize += nav_resize_dir * resize_step;
             g.NavWindowingAccumDeltaSize = ImMax(g.NavWindowingAccumDeltaSize, clamp_rect.Min - window->Pos - window->Size); // We need Pos+Size >= clmap_rect.Min, so Size >= clmap_rect.Min - Pos, so size_delta >= clmap_rect.Min - window->Pos - window->Size
             g.NavWindowingToggleLayer = false;
-            g.NavDisableMouseHover = true;
+            g.NavHighlightItemUnderNav = true;
             resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
             ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaSize);
             if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
@@ -7859,7 +7859,7 @@ void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
     if (g.NavWindow != window)
     {
         SetNavWindow(window);
-        if (window && g.NavDisableMouseHover)
+        if (window && g.NavHighlightItemUnderNav)
             g.NavMousePosDirty = true;
         g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
         g.NavLayer = ImGuiNavLayer_Main;
@@ -9778,7 +9778,7 @@ static void ImGui::UpdateMouseInputs()
 
     // If mouse moved we re-enable mouse hovering in case it was disabled by gamepad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true.
     if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
-        g.NavDisableMouseHover = false;
+        g.NavHighlightItemUnderNav = false;
 
     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
     {
@@ -9817,7 +9817,7 @@ static void ImGui::UpdateMouseInputs()
 
         // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
         if (io.MouseClicked[i])
-            g.NavDisableMouseHover = false;
+            g.NavHighlightItemUnderNav = false;
     }
 }
 
@@ -12189,7 +12189,7 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
 
         ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_MOUSE * scale;
         ImRect r_avoid;
-        if (g.NavCursorVisible && g.NavDisableMouseHover && !g.IO.ConfigNavMoveSetMousePos)
+        if (g.NavCursorVisible && g.NavHighlightItemUnderNav && !g.IO.ConfigNavMoveSetMousePos)
             r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
         else
             r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
@@ -12270,7 +12270,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
         window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
 
     if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
-        g.NavDisableMouseHover = true;
+        g.NavHighlightItemUnderNav = true;
     else
         g.NavCursorVisible = false;
 
@@ -12739,7 +12739,7 @@ void ImGui::NavRestoreHighlightAfterMove()
 {
     ImGuiContext& g = *GImGui;
     g.NavCursorVisible = true;
-    g.NavDisableMouseHover = g.NavMousePosDirty = true;
+    g.NavHighlightItemUnderNav = g.NavMousePosDirty = true;
 }
 
 static inline void ImGui::NavUpdateAnyRequestFlag()
@@ -12789,7 +12789,7 @@ static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource()
     const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID;
 
     // Testing for !activated_shortcut here could in theory be removed if we decided that activating a remote shortcut altered one of the g.NavDisableXXX flag.
-    if ((!g.NavCursorVisible || !g.NavDisableMouseHover || !window) && !activated_shortcut)
+    if ((!g.NavCursorVisible || !g.NavHighlightItemUnderNav || !window) && !activated_shortcut)
         return ImGuiInputSource_Mouse;
     else
         return ImGuiInputSource_Keyboard; // or Nav in general
@@ -12897,7 +12897,7 @@ static void ImGui::NavUpdate()
     // Schedule mouse position update (will be done at the bottom of this function, after 1) processing all move requests and 2) updating scrolling)
     bool set_mouse_pos = false;
     if (g.NavMousePosDirty && g.NavIdIsAlive)
-        if (g.NavCursorVisible && g.NavDisableMouseHover && g.NavWindow)
+        if (g.NavCursorVisible && g.NavHighlightItemUnderNav && g.NavWindow)
             set_mouse_pos = true;
     g.NavMousePosDirty = false;
     IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu);
@@ -13004,7 +13004,7 @@ static void ImGui::NavUpdate()
     if (!nav_keyboard_active && !nav_gamepad_active)
     {
         g.NavCursorVisible = false;
-        g.NavDisableMouseHover = set_mouse_pos = false;
+        g.NavHighlightItemUnderNav = set_mouse_pos = false;
     }
 
     // Update mouse position if requested
@@ -13717,7 +13717,7 @@ static void ImGui::NavUpdateWindowing()
             const float NAV_MOVE_SPEED = 800.0f;
             const float move_step = NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
             g.NavWindowingAccumDeltaPos += nav_move_dir * move_step;
-            g.NavDisableMouseHover = true;
+            g.NavHighlightItemUnderNav = true;
             ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaPos);
             if (accum_floored.x != 0.0f || accum_floored.y != 0.0f)
             {
@@ -15823,7 +15823,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
         Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
         Text("NavActivateId/DownId/PressedId: %08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId);
         Text("NavActivateFlags: %04X", g.NavActivateFlags);
-        Text("NavCursorVisible: %d, NavDisableMouseHover: %d", g.NavCursorVisible, g.NavDisableMouseHover);
+        Text("NavCursorVisible: %d, NavHighlightItemUnderNav: %d", g.NavCursorVisible, g.NavHighlightItemUnderNav);
         Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId);
         Text("NavFocusRoute[] = ");
         for (int path_n = g.NavFocusRoute.Size - 1; path_n >= 0; path_n--)
diff --git a/imgui_internal.h b/imgui_internal.h
index 94e0cb0e0438..85ca13910a60 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -833,7 +833,7 @@ enum ImGuiItemFlagsPrivate_
     ImGuiItemFlags_MixedValue               = 1 << 12, // false     // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
     ImGuiItemFlags_NoWindowHoverableCheck   = 1 << 13, // false     // Disable hoverable check in ItemHoverable()
     ImGuiItemFlags_AllowOverlap             = 1 << 14, // false     // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame.
-    ImGuiItemFlags_NoNavDisableMouseHover   = 1 << 15, // false     // Nav keyboard/gamepad mode doesn't disable hover.
+    ImGuiItemFlags_NoNavDisableMouseHover   = 1 << 15, // false     // Nav keyboard/gamepad mode doesn't disable hover highlight (behave as if NavHighlightItemUnderNav==false).
     ImGuiItemFlags_NoMarkEdited             = 1 << 16, // false     // Skip calling MarkItemEdited()
 
     // Controlled by widget code
@@ -2133,6 +2133,10 @@ struct ImGuiContext
     ImVector Viewports;                        // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData.
 
     // Gamepad/keyboard Navigation
+    bool                    NavCursorVisible;                   // Nav focus cursor/rectangle is visible? We hide it after a mouse click. We show it after a nav move.
+    bool                    NavHighlightItemUnderNav;           // Disable mouse hovering highlight. Highlight navigation focused item instead of mouse hovered item.
+    //bool                  NavDisableHighlight;                // Old name for !g.NavCursorVisible before 1.91.4 (2024/10/18). OPPOSITE VALUE (g.NavDisableHighlight == !g.NavCursorVisible)
+    //bool                  NavDisableMouseHover;               // Old name for g.NavHighlightItemUnderNav before 1.91.1 (2024/10/18) this was called When user starts using keyboard/gamepad, we hide mouse hovering highlight until mouse is touched again.
     ImGuiWindow*            NavWindow;                          // Focused window for navigation. Could be called 'FocusedWindow'
     ImGuiID                 NavId;                              // Focused item for navigation
     ImGuiID                 NavFocusScopeId;                    // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
@@ -2150,9 +2154,6 @@ struct ImGuiContext
     ImGuiSelectionUserData  NavLastValidSelectionUserData;      // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
     bool                    NavIdIsAlive;                       // Nav widget has been seen this frame ~~ NavRectRel is valid
     bool                    NavMousePosDirty;                   // When set we will update mouse position if io.ConfigNavMoveSetMousePos is set (not enabled by default)
-    bool                    NavCursorVisible;                   // Nav focus rectangle is visible? We hide it after a mouse click. We show it after a nav move.
-    //bool                  NavDisableHighlight;                // Before 1.91.4 (2024/10/18) we used g.NavDisableHighlight. g.NavCursorVisible is the new variable name, with opposite value (g.NavDisableHighlight = !g.NavCursorVisible)
-    bool                    NavDisableMouseHover;               // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again.
 
     // Navigation: Init & Move Requests
     bool                    NavAnyRequest;                      // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index e5f2acc8dc40..3b28daa4d033 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -625,7 +625,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
 
     // Gamepad/Keyboard handling
     // We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse.
-    if (g.NavId == id && g.NavCursorVisible && g.NavDisableMouseHover)
+    if (g.NavId == id && g.NavCursorVisible && g.NavHighlightItemUnderNav)
         if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
             hovered = true;
     if (g.NavActivateDownId == id)
@@ -4476,7 +4476,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags | ImGuiItemFlags_NoNavDisableMouseHover);
     if (hovered)
         SetMouseCursor(ImGuiMouseCursor_TextInput);
-    if (hovered && g.NavDisableMouseHover)
+    if (hovered && g.NavHighlightItemUnderNav)
         hovered = false;
 
     // We are only allowed to access the state if we are already the active widget.
@@ -6628,7 +6628,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
             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
+                toggled |= is_mouse_x_over_arrow && !g.NavHighlightItemUnderNav; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
             if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseClickedCount[0] == 2)
                 toggled = true; // Double click
         }
@@ -6998,7 +6998,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
     // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
     if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
     {
-        if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
+        if (!g.NavHighlightItemUnderNav && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
         {
             SetNavID(id, window->DC.NavLayerCurrent, g.CurrentFocusScopeId, WindowRectAbsToRel(window, bb)); // (bb == NavRect)
             g.NavCursorVisible = false;
@@ -8625,7 +8625,7 @@ void ImGui::EndMenuBar()
             FocusWindow(window);
             SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
             g.NavCursorVisible = false; // Hide nav cursor for the current frame so we don't see the intermediary selection.
-            g.NavDisableMouseHover = g.NavMousePosDirty = true;
+            g.NavHighlightItemUnderNav = g.NavMousePosDirty = true;
             NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Repeat
         }
     }
@@ -8833,7 +8833,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
     if (!enabled)
         EndDisabled();
 
-    const bool hovered = (g.HoveredId == id) && enabled && !g.NavDisableMouseHover;
+    const bool hovered = (g.HoveredId == id) && enabled && !g.NavHighlightItemUnderNav;
     if (menuset_is_open)
         PopItemFlag();
 
@@ -8868,7 +8868,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
         // The 'HovereWindow == window' check creates an inconsistency (e.g. moving away from menu slowly tends to hit same window, whereas moving away fast does not)
         // But we also need to not close the top-menu menu when moving over void. Perhaps we should extend the triangle check to a larger polygon.
         // (Remember to test this on BeginPopup("A")->BeginMenu("B") sequence which behaves slightly differently as B isn't a Child of A and hovering isn't shared.)
-        if (menu_is_open && !hovered && g.HoveredWindow == window && !moving_toward_child_menu && !g.NavDisableMouseHover && g.ActiveId == 0)
+        if (menu_is_open && !hovered && g.HoveredWindow == window && !moving_toward_child_menu && !g.NavHighlightItemUnderNav && g.ActiveId == 0)
             want_close = true;
 
         // Open

From 634a7ed988682e0dbb415810ded2f8d86e4996e4 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 18 Oct 2024 17:06:30 +0200
Subject: [PATCH 215/548] Nav: added SetNavCursorVisible(). (#1074, #2048,
 #7237, #8059)

+ Further internal renaming for consistency.
---
 docs/CHANGELOG.txt |  2 ++
 imgui.cpp          | 47 ++++++++++++++++++++++++++--------------------
 imgui.h            | 10 ++++++----
 imgui_internal.h   |  4 ++--
 imgui_widgets.cpp  |  4 ++--
 5 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 12970915222a..319530e0aed7 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -67,6 +67,8 @@ Other changes:
   state to draw callbacks. (#6969, #5834, #7468, #3590)
 - IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
 - Error Handling: turned a few more functions into recoverable errors. (#1651)
+- Nav: added NavSetCursorVisible(bool visible) to manipulate visibility of keyboard/gamepad
+  navigation cursor. (#1074, #2048, #7237, #8059)
 - Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change
   how pressing Escape affects navigation. (#8059, #2048, #1074, #3200)
   - Set io.ConfigNavEscapeClearFocusItem = true (default) to clear focused item and highlight.
diff --git a/imgui.cpp b/imgui.cpp
index 09acf5cd6414..ba4a34121882 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -8558,7 +8558,7 @@ void ImGui::FocusItem()
         return;
     }
 
-    ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavHighlight | ImGuiNavMoveFlags_NoSelect;
+    ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavCursorVisible | ImGuiNavMoveFlags_NoSelect;
     ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
     SetNavWindow(window);
     NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_Up, move_flags, scroll_flags);
@@ -8593,7 +8593,7 @@ void ImGui::SetKeyboardFocusHere(int offset)
 
     SetNavWindow(window);
 
-    ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavHighlight;
+    ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavCursorVisible;
     ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
     NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, move_flags, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
     if (offset == -1)
@@ -12209,6 +12209,20 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
 // In our terminology those should be interchangeable, yet right now this is super confusing.
 // Those two functions are merely a legacy artifact, so at minimum naming should be clarified.
 
+void ImGui::SetNavCursorVisible(bool visible)
+{
+    ImGuiContext& g = *GImGui;
+    g.NavCursorVisible = visible;
+}
+
+// (was called NavRestoreHighlightAfterMove() before 1.91.4)
+void ImGui::SetNavCursorVisibleAfterMove()
+{
+    ImGuiContext& g = *GImGui;
+    g.NavCursorVisible = true;
+    g.NavHighlightItemUnderNav = g.NavMousePosDirty = true;
+}
+
 void ImGui::SetNavWindow(ImGuiWindow* window)
 {
     ImGuiContext& g = *GImGui;
@@ -12735,13 +12749,6 @@ void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
     }
 }
 
-void ImGui::NavRestoreHighlightAfterMove()
-{
-    ImGuiContext& g = *GImGui;
-    g.NavCursorVisible = true;
-    g.NavHighlightItemUnderNav = g.NavMousePosDirty = true;
-}
-
 static inline void ImGui::NavUpdateAnyRequestFlag()
 {
     ImGuiContext& g = *GImGui;
@@ -13050,7 +13057,7 @@ void ImGui::NavInitRequestApplyResult()
     if (result->SelectionUserData != ImGuiSelectionUserData_Invalid)
         g.NavLastValidSelectionUserData = result->SelectionUserData;
     if (g.NavInitRequestFromMove)
-        NavRestoreHighlightAfterMove();
+        SetNavCursorVisibleAfterMove();
 }
 
 // Bias scoring rect ahead of scoring + update preferred pos (if missing) using source position
@@ -13243,9 +13250,9 @@ void ImGui::NavMoveRequestApplyResult()
     if (result == NULL)
     {
         if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
-            g.NavMoveFlags |= ImGuiNavMoveFlags_NoSetNavHighlight;
-        if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavHighlight) == 0)
-            NavRestoreHighlightAfterMove();
+            g.NavMoveFlags |= ImGuiNavMoveFlags_NoSetNavCursorVisible;
+        if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavCursorVisible) == 0)
+            SetNavCursorVisibleAfterMove();
         NavClearPreferredPosForAxis(axis); // On a failed move, clear preferred pos for this axis.
         IMGUI_DEBUG_LOG_NAV("[nav] NavMoveSubmitted but not led to a result!\n");
         return;
@@ -13330,9 +13337,9 @@ void ImGui::NavMoveRequestApplyResult()
             g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing;
     }
 
-    // Enable nav highlight
-    if ((g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavHighlight) == 0)
-        NavRestoreHighlightAfterMove();
+    // Make nav cursor visible
+    if ((g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavCursorVisible) == 0)
+        SetNavCursorVisibleAfterMove();
 }
 
 // Process Escape/NavCancel input (to close a popup, get back to parent, clear focus)
@@ -13356,7 +13363,7 @@ static void ImGui::NavUpdateCancelRequest()
     {
         // Leave the "menu" layer
         NavRestoreLayer(ImGuiNavLayer_Main);
-        NavRestoreHighlightAfterMove();
+        SetNavCursorVisibleAfterMove();
     }
     else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->RootWindowForNav->ParentWindow)
     {
@@ -13366,7 +13373,7 @@ static void ImGui::NavUpdateCancelRequest()
         IM_ASSERT(child_window->ChildId != 0);
         FocusWindow(parent_window);
         SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_window->Rect()));
-        NavRestoreHighlightAfterMove();
+        SetNavCursorVisibleAfterMove();
     }
     else if (g.OpenPopupStack.Size > 0 && g.OpenPopupStack.back().Window != NULL && !(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
     {
@@ -13732,7 +13739,7 @@ static void ImGui::NavUpdateWindowing()
     if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow))
     {
         ClearActiveID();
-        NavRestoreHighlightAfterMove();
+        SetNavCursorVisibleAfterMove();
         ClosePopupsOverWindow(apply_focus_window, false);
         FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild);
         apply_focus_window = g.NavWindow;
@@ -13779,7 +13786,7 @@ static void ImGui::NavUpdateWindowing()
             if (new_nav_layer == ImGuiNavLayer_Menu)
                 g.NavWindow->NavLastIds[new_nav_layer] = 0;
             NavRestoreLayer(new_nav_layer);
-            NavRestoreHighlightAfterMove();
+            SetNavCursorVisibleAfterMove();
         }
     }
 }
diff --git a/imgui.h b/imgui.h
index d89661bf2d18..c5ef6e935fed 100644
--- a/imgui.h
+++ b/imgui.h
@@ -900,10 +900,12 @@ namespace ImGui
     IMGUI_API void          PopClipRect();
 
     // Focus, Activation
-    // - Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHereY()" when applicable to signify "this is the default item"
-    IMGUI_API void          SetItemDefaultFocus();                                              // make last item the default focused item of a window.
+    IMGUI_API void          SetItemDefaultFocus();                                              // make last item the default focused item of of a newly appearing window.
     IMGUI_API void          SetKeyboardFocusHere(int offset = 0);                               // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget.
 
+    // Keyboard/Gamepad Navigation
+    IMGUI_API void          SetNavCursorVisible(bool visible);                                  // alter visibility of keyboard/gamepad cursor. by default: show when using an arrow key, hide when clicking with mouse.
+
     // Overlapping mode
     IMGUI_API void          SetNextItemAllowOverlap();                                          // allow next item to be overlapped by a subsequent item. Useful with invisible buttons, selectable, treenode covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this.
 
@@ -996,7 +998,7 @@ namespace ImGui
     // - Many related features are still in imgui_internal.h. For instance, most IsKeyXXX()/IsMouseXXX() functions have an owner-id-aware version.
     IMGUI_API void          SetItemKeyOwner(ImGuiKey key);                                      // Set key owner to last item ID if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
 
-    // Inputs Utilities: Mouse specific
+    // Inputs Utilities: Mouse
     // - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right.
     // - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle.
     // - Dragging operations are only reported after mouse has moved a certain distance away from the initial clicking position (see 'lock_threshold' and 'io.MouseDraggingThreshold')
@@ -1676,7 +1678,7 @@ enum ImGuiCol_
     ImGuiCol_TextLink,              // Hyperlink color
     ImGuiCol_TextSelectedBg,
     ImGuiCol_DragDropTarget,        // Rectangle highlighting a drop target
-    ImGuiCol_NavHighlight,          // Gamepad/keyboard: current highlighted item
+    ImGuiCol_NavHighlight,          // Color of gamepad/keyboard navigation cursor/rectangle, when visible
     ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
     ImGuiCol_NavWindowingDimBg,     // Darken/colorize entire screen behind the CTRL+TAB window list, when active
     ImGuiCol_ModalWindowDimBg,      // Darken/colorize entire screen behind a modal window, when one is active
diff --git a/imgui_internal.h b/imgui_internal.h
index 85ca13910a60..9212634564b4 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1578,7 +1578,7 @@ enum ImGuiNavMoveFlags_
     ImGuiNavMoveFlags_IsPageMove            = 1 << 11,  // Identify a PageDown/PageUp request.
     ImGuiNavMoveFlags_Activate              = 1 << 12,  // Activate/select target item.
     ImGuiNavMoveFlags_NoSelect              = 1 << 13,  // Don't trigger selection by not setting g.NavJustMovedTo
-    ImGuiNavMoveFlags_NoSetNavHighlight     = 1 << 14,  // Do not alter the visible state of keyboard vs mouse nav highlight
+    ImGuiNavMoveFlags_NoSetNavCursorVisible = 1 << 14,  // Do not alter the nav cursor visible state
     ImGuiNavMoveFlags_NoClearActiveId       = 1 << 15,  // (Experimental) Do not clear active id when applying move result
 };
 
@@ -3114,7 +3114,7 @@ namespace ImGui
     IMGUI_API void          NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
     IMGUI_API void          NavHighlightActivated(ImGuiID id);
     IMGUI_API void          NavClearPreferredPosForAxis(ImGuiAxis axis);
-    IMGUI_API void          NavRestoreHighlightAfterMove();
+    IMGUI_API void          SetNavCursorVisibleAfterMove();
     IMGUI_API void          NavUpdateCurrentWindowIsScrollPushableX();
     IMGUI_API void          SetNavWindow(ImGuiWindow* window);
     IMGUI_API void          SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 3b28daa4d033..c3a61070b603 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -7200,7 +7200,7 @@ int ImGui::TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count,
     else
         idx = TypingSelectFindBestLeadingMatch(req, items_count, get_item_name_func, user_data);
     if (idx != -1)
-        NavRestoreHighlightAfterMove();
+        SetNavCursorVisibleAfterMove();
     return idx;
 }
 
@@ -8883,7 +8883,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
         {
             want_open = want_open_nav_init = true;
             NavMoveRequestCancel();
-            NavRestoreHighlightAfterMove();
+            SetNavCursorVisibleAfterMove();
         }
     }
     else

From 1ff9768aa30e2e4152144a68e0edcf7aefa4d0f4 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 18 Oct 2024 17:12:00 +0200
Subject: [PATCH 216/548] Nav: (Breaking) renamed ImGuiCol_NavHighlight to
 ImGuiCol_NavCursor. (#1074, #2048, #7237, #8059, #1712, #7370, #787)

---
 docs/CHANGELOG.txt | 2 ++
 imgui.cpp          | 7 ++++---
 imgui.h            | 3 ++-
 imgui_draw.cpp     | 6 +++---
 imgui_widgets.cpp  | 2 +-
 5 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 319530e0aed7..ca0c2a3742d0 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -41,6 +41,8 @@ HOW TO UPDATE?
 
 Breaking changes:
 
+- Style: renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor, for consistency with newly
+  exposed and reworked features. Kept inline redirection enum (will obsolete).
 - The typedef for ImTextureID now defaults to ImU64 instead of void*. (#1641)
   - This removes the requirement to redefine it for backends which are e.g. storing
     descriptor sets or other 64-bits structures when building on 32-bits archs
diff --git a/imgui.cpp b/imgui.cpp
index ba4a34121882..4a965898dd44 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -430,6 +430,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.
 
+ - 2024/10/18 (1.91.4) - renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor (for consistency with newly exposed and reworked features). Kept inline redirection enum (will obsolete).
  - 2024/10/14 (1.91.4) - moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
                          moved ImGuiConfigFlags_NavNoCaptureKeyboard to standalone io.ConfigNavCaptureKeyboard bool (note the inverted value!).
                          kept legacy names (will obsolete) + code that copies settings once the first time. Dynamically changing the old value won't work. Switch to using the new value!
@@ -3491,7 +3492,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
     case ImGuiCol_TextLink: return "TextLink";
     case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
     case ImGuiCol_DragDropTarget: return "DragDropTarget";
-    case ImGuiCol_NavHighlight: return "NavHighlight";
+    case ImGuiCol_NavCursor: return "NavCursor";
     case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
     case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg";
     case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg";
@@ -3715,7 +3716,7 @@ void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFl
     const float thickness = 2.0f;
     if (flags & ImGuiNavRenderCursorFlags_Compact)
     {
-        window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness);
+        window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
     }
     else
     {
@@ -3724,7 +3725,7 @@ void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFl
         bool fully_visible = window->ClipRect.Contains(display_rect);
         if (!fully_visible)
             window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
-        window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness);
+        window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
         if (!fully_visible)
             window->DrawList->PopClipRect();
     }
diff --git a/imgui.h b/imgui.h
index c5ef6e935fed..5cc9922ff10a 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1678,7 +1678,7 @@ enum ImGuiCol_
     ImGuiCol_TextLink,              // Hyperlink color
     ImGuiCol_TextSelectedBg,
     ImGuiCol_DragDropTarget,        // Rectangle highlighting a drop target
-    ImGuiCol_NavHighlight,          // Color of gamepad/keyboard navigation cursor/rectangle, when visible
+    ImGuiCol_NavCursor,             // Color of gamepad/keyboard navigation cursor/rectangle, when visible
     ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
     ImGuiCol_NavWindowingDimBg,     // Darken/colorize entire screen behind the CTRL+TAB window list, when active
     ImGuiCol_ModalWindowDimBg,      // Darken/colorize entire screen behind a modal window, when one is active
@@ -1688,6 +1688,7 @@ enum ImGuiCol_
     ImGuiCol_TabActive = ImGuiCol_TabSelected,                  // [renamed in 1.90.9]
     ImGuiCol_TabUnfocused = ImGuiCol_TabDimmed,                 // [renamed in 1.90.9]
     ImGuiCol_TabUnfocusedActive = ImGuiCol_TabDimmedSelected,   // [renamed in 1.90.9]
+    ImGuiCol_NavHighlight = ImGuiCol_NavCursor,                 // [renamed in 1.91.4]
 #endif
 };
 
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index efee2ec9c58e..57b7d3ba2b91 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -230,7 +230,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
     colors[ImGuiCol_TextLink]               = colors[ImGuiCol_HeaderActive];
     colors[ImGuiCol_TextSelectedBg]         = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
     colors[ImGuiCol_DragDropTarget]         = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
-    colors[ImGuiCol_NavHighlight]           = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+    colors[ImGuiCol_NavCursor]              = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
     colors[ImGuiCol_NavWindowingHighlight]  = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
     colors[ImGuiCol_NavWindowingDimBg]      = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
     colors[ImGuiCol_ModalWindowDimBg]       = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
@@ -293,7 +293,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
     colors[ImGuiCol_TextLink]               = colors[ImGuiCol_HeaderActive];
     colors[ImGuiCol_TextSelectedBg]         = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
     colors[ImGuiCol_DragDropTarget]         = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
-    colors[ImGuiCol_NavHighlight]           = colors[ImGuiCol_HeaderHovered];
+    colors[ImGuiCol_NavCursor]              = colors[ImGuiCol_HeaderHovered];
     colors[ImGuiCol_NavWindowingHighlight]  = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
     colors[ImGuiCol_NavWindowingDimBg]      = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
     colors[ImGuiCol_ModalWindowDimBg]       = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
@@ -357,7 +357,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
     colors[ImGuiCol_TextLink]               = colors[ImGuiCol_HeaderActive];
     colors[ImGuiCol_TextSelectedBg]         = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
     colors[ImGuiCol_DragDropTarget]         = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
-    colors[ImGuiCol_NavHighlight]           = colors[ImGuiCol_HeaderHovered];
+    colors[ImGuiCol_NavCursor]              = colors[ImGuiCol_HeaderHovered];
     colors[ImGuiCol_NavWindowingHighlight]  = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
     colors[ImGuiCol_NavWindowingDimBg]      = ImVec4(0.20f, 0.20f, 0.20f, 0.20f);
     colors[ImGuiCol_ModalWindowDimBg]       = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index c3a61070b603..ddfc263ef2ea 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -7399,7 +7399,7 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag
     ImRect box_select_r = bs->BoxSelectRectCurr;
     box_select_r.ClipWith(scope_rect);
     window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
-    window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavHighlight)); // FIXME-MULTISELECT: Styling
+    window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT: Styling
 
     // Scroll
     const bool enable_scroll = (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms_flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0;

From 3982cb35dcf987ac278db35548d714c938bd4ab7 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 18 Oct 2024 17:26:20 +0200
Subject: [PATCH 217/548] Nav, Docs: consistently use "keyboard/gamepad"
 instead of sometimes "gamepad/keyboard".

---
 imgui.cpp         | 31 +++++++++++++++++--------------
 imgui.h           | 24 +++++++++++++-----------
 imgui_demo.cpp    |  2 +-
 imgui_internal.h  | 12 ++++++------
 imgui_widgets.cpp |  8 ++++----
 5 files changed, 41 insertions(+), 36 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 4a965898dd44..c4388cedd4c2 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1400,6 +1400,13 @@ ImGuiIO::ImGuiIO()
     FontAllowUserScaling = false;
     DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
 
+    // Keyboard/Gamepad Navigation options
+    ConfigNavSwapGamepadButtons = false;
+    ConfigNavMoveSetMousePos = false;
+    ConfigNavCaptureKeyboard = true;
+    ConfigNavEscapeClearFocusItem = true;
+    ConfigNavEscapeClearFocusWindow = false;
+
     // Miscellaneous options
     MouseDrawCursor = false;
 #ifdef __APPLE__
@@ -1407,11 +1414,6 @@ ImGuiIO::ImGuiIO()
 #else
     ConfigMacOSXBehaviors = false;
 #endif
-    ConfigNavSwapGamepadButtons = false;
-    ConfigNavMoveSetMousePos = false;
-    ConfigNavCaptureKeyboard = true;
-    ConfigNavEscapeClearFocusItem = true;
-    ConfigNavEscapeClearFocusWindow = false;
     ConfigInputTrickleEventQueue = true;
     ConfigInputTextCursorBlink = true;
     ConfigInputTextEnterKeepActive = false;
@@ -3900,8 +3902,13 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     CurrentItemFlags = ImGuiItemFlags_None;
     DebugShowGroupRects = false;
 
+    NavCursorVisible = false;
+    NavHighlightItemUnderNav = false;
+    NavMousePosDirty = false;
+    NavIdIsAlive = false;
+    NavId = 0;
     NavWindow = NULL;
-    NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
+    NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
     NavLayer = ImGuiNavLayer_Main;
     NavNextActivateId = 0;
     NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
@@ -3909,10 +3916,6 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     NavHighlightActivatedTimer = 0.0f;
     NavInputSource = ImGuiInputSource_Keyboard;
     NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
-    NavIdIsAlive = false;
-    NavMousePosDirty = false;
-    NavCursorVisible = false;
-    NavHighlightItemUnderNav = false;
 
     NavAnyRequest = false;
     NavInitRequest = false;
@@ -5197,7 +5200,7 @@ void ImGui::NewFrame()
     //IM_ASSERT(g.IO.KeyAlt == IsKeyDown(ImGuiKey_LeftAlt) || IsKeyDown(ImGuiKey_RightAlt));
     //IM_ASSERT(g.IO.KeySuper == IsKeyDown(ImGuiKey_LeftSuper) || IsKeyDown(ImGuiKey_RightSuper));
 
-    // Update gamepad/keyboard navigation
+    // Update keyboard/gamepad navigation
     NavUpdate();
 
     // Update mouse input state
@@ -9777,7 +9780,7 @@ static void ImGui::UpdateMouseInputs()
     g.MouseStationaryTimer = mouse_stationary ? (g.MouseStationaryTimer + io.DeltaTime) : 0.0f;
     //IMGUI_DEBUG_LOG("%.4f\n", g.MouseStationaryTimer);
 
-    // If mouse moved we re-enable mouse hovering in case it was disabled by gamepad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true.
+    // If mouse moved we re-enable mouse hovering in case it was disabled by keyboard/gamepad. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true.
     if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)
         g.NavHighlightItemUnderNav = false;
 
@@ -9816,7 +9819,7 @@ static void ImGui::UpdateMouseInputs()
         // We provide io.MouseDoubleClicked[] as a legacy service
         io.MouseDoubleClicked[i] = (io.MouseClickedCount[i] == 2);
 
-        // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
+        // Clicking any mouse button reactivate mouse hovering which may have been deactivated by keyboard/gamepad navigation
         if (io.MouseClicked[i])
             g.NavHighlightItemUnderNav = false;
     }
@@ -12310,7 +12313,7 @@ static float inline NavScoreItemDistInterval(float cand_min, float cand_max, flo
     return 0.0f;
 }
 
-// Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057
+// Scoring function for keyboard/gamepad directional navigation. Based on https://gist.github.com/rygorous/6981057
 static bool ImGui::NavScoreItem(ImGuiNavItemData* result)
 {
     ImGuiContext& g = *GImGui;
diff --git a/imgui.h b/imgui.h
index 5cc9922ff10a..60bcbee6c548 100644
--- a/imgui.h
+++ b/imgui.h
@@ -581,7 +581,7 @@ namespace ImGui
     //   the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x
     // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc.
     // - Format string may also be set to NULL or use the default format ("%f" or "%d").
-    // - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision).
+    // - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For keyboard/gamepad navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision).
     // - Use v_min < v_max to clamp edits to given limits. Note that CTRL+Click manual input can override those limits if ImGuiSliderFlags_AlwaysClamp is not used.
     // - Use v_max = FLT_MAX / INT_MAX etc to avoid clamping to a maximum, same with v_min = -FLT_MAX / INT_MIN to avoid clamping to a minimum.
     // - We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them.
@@ -1080,8 +1080,8 @@ enum ImGuiWindowFlags_
     ImGuiWindowFlags_NoBringToFrontOnFocus  = 1 << 13,  // Disable bringing window to front when taking focus (e.g. clicking on it or programmatically giving it focus)
     ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14,  // Always show vertical scrollbar (even if ContentSize.y < Size.y)
     ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15,  // Always show horizontal scrollbar (even if ContentSize.x < Size.x)
-    ImGuiWindowFlags_NoNavInputs            = 1 << 16,  // No gamepad/keyboard navigation within the window
-    ImGuiWindowFlags_NoNavFocus             = 1 << 17,  // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB)
+    ImGuiWindowFlags_NoNavInputs            = 1 << 16,  // No keyboard/gamepad navigation within the window
+    ImGuiWindowFlags_NoNavFocus             = 1 << 17,  // No focusing toward this window with keyboard/gamepad navigation (e.g. skipped by CTRL+TAB)
     ImGuiWindowFlags_UnsavedDocument        = 1 << 18,  // Display a dot next to the title. When used in a tab/docking context, tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
     ImGuiWindowFlags_NoNav                  = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
     ImGuiWindowFlags_NoDecoration           = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse,
@@ -1121,7 +1121,7 @@ enum ImGuiChildFlags_
     ImGuiChildFlags_AutoResizeY             = 1 << 5,   // Enable auto-resizing height. Read "IMPORTANT: Size measurement" details above.
     ImGuiChildFlags_AlwaysAutoResize        = 1 << 6,   // Combined with AutoResizeX/AutoResizeY. Always measure size even when child is hidden, always return true, always disable clipping optimization! NOT RECOMMENDED.
     ImGuiChildFlags_FrameStyle              = 1 << 7,   // Style the child window like a framed item: use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding.
-    ImGuiChildFlags_NavFlattened            = 1 << 8,   // [BETA] Share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows.
+    ImGuiChildFlags_NavFlattened            = 1 << 8,   // [BETA] Share focus scope, allow keyboard/gamepad navigation to cross over parent border to this child or between sibling child windows.
 
     // Obsolete names
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@@ -1328,7 +1328,7 @@ enum ImGuiHoveredFlags_
     ImGuiHoveredFlags_AllowWhenOverlappedByItem     = 1 << 8,   // IsItemHovered() only: Return true even if the item uses AllowOverlap mode and is overlapped by another hoverable item.
     ImGuiHoveredFlags_AllowWhenOverlappedByWindow   = 1 << 9,   // IsItemHovered() only: Return true even if the position is obstructed or overlapped by another window.
     ImGuiHoveredFlags_AllowWhenDisabled             = 1 << 10,  // IsItemHovered() only: Return true even if the item is disabled
-    ImGuiHoveredFlags_NoNavOverride                 = 1 << 11,  // IsItemHovered() only: Disable using gamepad/keyboard navigation state when active, always query mouse
+    ImGuiHoveredFlags_NoNavOverride                 = 1 << 11,  // IsItemHovered() only: Disable using keyboard/gamepad navigation state when active, always query mouse
     ImGuiHoveredFlags_AllowWhenOverlapped           = ImGuiHoveredFlags_AllowWhenOverlappedByItem | ImGuiHoveredFlags_AllowWhenOverlappedByWindow,
     ImGuiHoveredFlags_RectOnly                      = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped,
     ImGuiHoveredFlags_RootAndChildWindows           = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows,
@@ -1678,7 +1678,7 @@ enum ImGuiCol_
     ImGuiCol_TextLink,              // Hyperlink color
     ImGuiCol_TextSelectedBg,
     ImGuiCol_DragDropTarget,        // Rectangle highlighting a drop target
-    ImGuiCol_NavCursor,             // Color of gamepad/keyboard navigation cursor/rectangle, when visible
+    ImGuiCol_NavCursor,             // Color of keyboard/gamepad navigation cursor/rectangle, when visible
     ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
     ImGuiCol_NavWindowingDimBg,     // Darken/colorize entire screen behind the CTRL+TAB window list, when active
     ImGuiCol_ModalWindowDimBg,      // Darken/colorize entire screen behind a modal window, when one is active
@@ -2230,7 +2230,7 @@ struct ImGuiIO
     // Configuration                            // Default value
     //------------------------------------------------------------------
 
-    ImGuiConfigFlags   ConfigFlags;             // = 0              // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc.
+    ImGuiConfigFlags   ConfigFlags;             // = 0              // See ImGuiConfigFlags_ enum. Set by user/application. Keyboard/Gamepad navigation options, etc.
     ImGuiBackendFlags  BackendFlags;            // = 0              // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend.
     ImVec2      DisplaySize;                    //           // Main display size, in pixels (generally == GetMainViewport()->Size). May change every frame.
     float       DeltaTime;                      // = 1.0f/60.0f     // Time elapsed since last frame, in seconds. May change every frame.
@@ -2246,15 +2246,17 @@ struct ImGuiIO
     ImFont*     FontDefault;                    // = NULL           // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0].
     ImVec2      DisplayFramebufferScale;        // = (1, 1)         // For retina display or other situations where window coordinates are different from framebuffer coordinates. This generally ends up in ImDrawData::FramebufferScale.
 
-    // Miscellaneous options
-    // (you can visualize and interact with all options in 'Demo->Configuration')
-    bool        MouseDrawCursor;                // = false          // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
-    bool        ConfigMacOSXBehaviors;          // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
+    // Keyboard/Gamepad Navigation options
     bool        ConfigNavSwapGamepadButtons;    // = false          // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
     bool        ConfigNavMoveSetMousePos;       // = false          // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true. 
     bool        ConfigNavCaptureKeyboard;       // = true           // Sets io.WantCaptureKeyboard when io.NavActive is set.
     bool        ConfigNavEscapeClearFocusItem;  // = true           // Pressing Escape can clear focused item + navigation id/highlight. Set to false if you want to always keep highlight on.
     bool        ConfigNavEscapeClearFocusWindow;// = false          // Pressing Escape can clear focused window as well (super set of io.ConfigNavEscapeClearFocusItem).
+
+    // Miscellaneous options
+    // (you can visualize and interact with all options in 'Demo->Configuration')
+    bool        MouseDrawCursor;                // = false          // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
+    bool        ConfigMacOSXBehaviors;          // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
     bool        ConfigInputTrickleEventQueue;   // = true           // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
     bool        ConfigInputTextCursorBlink;     // = true           // Enable blinking cursor (optional as some users consider it to be distracting).
     bool        ConfigInputTextEnterKeepActive; // = false          // [BETA] Pressing Enter will keep item active and select contents (single-line only).
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 63f6d15d1209..c484dd48c79e 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1012,7 +1012,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
 
         // The following examples are passed for documentation purpose but may not be useful to most users.
         // Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() will pull ImGuiHoveredFlags flags values from
-        // 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or gamepad/keyboard is being used.
+        // 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or keyboard/gamepad is being used.
         // With default settings, ImGuiHoveredFlags_ForTooltip is equivalent to ImGuiHoveredFlags_DelayShort + ImGuiHoveredFlags_Stationary.
         ImGui::Button("Manual", sz);
         if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
diff --git a/imgui_internal.h b/imgui_internal.h
index 9212634564b4..bca327cdf888 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -141,7 +141,7 @@ struct ImGuiLocEntry;               // A localization entry.
 struct ImGuiMenuColumns;            // Simple column measurement, currently used for MenuItem() only
 struct ImGuiMultiSelectState;       // Multi-selection persistent state (for focused selection).
 struct ImGuiMultiSelectTempData;    // Multi-selection temporary state (while traversing).
-struct ImGuiNavItemData;            // Result of a gamepad/keyboard directional navigation move query result
+struct ImGuiNavItemData;            // Result of a keyboard/gamepad directional navigation move query result
 struct ImGuiMetricsConfig;          // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
 struct ImGuiNextWindowData;         // Storage for SetNextWindow** functions
 struct ImGuiNextItemData;           // Storage for SetNextItem** functions
@@ -2132,13 +2132,15 @@ struct ImGuiContext
     // Viewports
     ImVector Viewports;                        // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData.
 
-    // Gamepad/keyboard Navigation
+    // Keyboard/Gamepad Navigation
     bool                    NavCursorVisible;                   // Nav focus cursor/rectangle is visible? We hide it after a mouse click. We show it after a nav move.
     bool                    NavHighlightItemUnderNav;           // Disable mouse hovering highlight. Highlight navigation focused item instead of mouse hovered item.
     //bool                  NavDisableHighlight;                // Old name for !g.NavCursorVisible before 1.91.4 (2024/10/18). OPPOSITE VALUE (g.NavDisableHighlight == !g.NavCursorVisible)
     //bool                  NavDisableMouseHover;               // Old name for g.NavHighlightItemUnderNav before 1.91.1 (2024/10/18) this was called When user starts using keyboard/gamepad, we hide mouse hovering highlight until mouse is touched again.
-    ImGuiWindow*            NavWindow;                          // Focused window for navigation. Could be called 'FocusedWindow'
+    bool                    NavMousePosDirty;                   // When set we will update mouse position if io.ConfigNavMoveSetMousePos is set (not enabled by default)
+    bool                    NavIdIsAlive;                       // Nav widget has been seen this frame ~~ NavRectRel is valid
     ImGuiID                 NavId;                              // Focused item for navigation
+    ImGuiWindow*            NavWindow;                          // Focused window for navigation. Could be called 'FocusedWindow'
     ImGuiID                 NavFocusScopeId;                    // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
     ImGuiNavLayer           NavLayer;                           // Focused layer (main scrolling layer, or menu/title bar layer)
     ImGuiID                 NavActivateId;                      // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
@@ -2152,8 +2154,6 @@ struct ImGuiContext
     ImGuiActivateFlags      NavNextActivateFlags;
     ImGuiInputSource        NavInputSource;                     // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
     ImGuiSelectionUserData  NavLastValidSelectionUserData;      // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
-    bool                    NavIdIsAlive;                       // Nav widget has been seen this frame ~~ NavRectRel is valid
-    bool                    NavMousePosDirty;                   // When set we will update mouse position if io.ConfigNavMoveSetMousePos is set (not enabled by default)
 
     // Navigation: Init & Move Requests
     bool                    NavAnyRequest;                      // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
@@ -3101,7 +3101,7 @@ namespace ImGui
     IMGUI_API bool          BeginComboPreview();
     IMGUI_API void          EndComboPreview();
 
-    // Gamepad/Keyboard Navigation
+    // Keyboard/Gamepad Navigation
     IMGUI_API void          NavInitWindow(ImGuiWindow* window, bool force_reinit);
     IMGUI_API void          NavInitRequestApplyResult();
     IMGUI_API bool          NavMoveRequestButNoResultYet();
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index ddfc263ef2ea..e0bc7f7476bf 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -623,7 +623,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
             g.NavCursorVisible = false;
     }
 
-    // Gamepad/Keyboard handling
+    // Keyboard/Gamepad navigation handling
     // We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse.
     if (g.NavId == id && g.NavCursorVisible && g.NavHighlightItemUnderNav)
         if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
@@ -3049,14 +3049,14 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
                 const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
                 if (decimal_precision > 0)
                 {
-                    input_delta /= 100.0f;    // Gamepad/keyboard tweak speeds in % of slider bounds
+                    input_delta /= 100.0f; // Keyboard/Gamepad tweak speeds in % of slider bounds
                     if (tweak_slow)
                         input_delta /= 10.0f;
                 }
                 else
                 {
                     if ((v_range_f >= -100.0f && v_range_f <= 100.0f && v_range_f != 0.0f) || tweak_slow)
-                        input_delta = ((input_delta < 0.0f) ? -1.0f : +1.0f) / v_range_f; // Gamepad/keyboard tweak speeds in integer steps
+                        input_delta = ((input_delta < 0.0f) ? -1.0f : +1.0f) / v_range_f; // Keyboard/Gamepad tweak speeds in integer steps
                     else
                         input_delta /= 100.0f;
                 }
@@ -6995,7 +6995,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
                 selected = pressed = true;
     }
 
-    // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
+    // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with keyboard/gamepad
     if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
     {
         if (!g.NavHighlightItemUnderNav && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)

From ab9ce2a927ab0688c97f7fefadb49d84e41df346 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 18 Oct 2024 18:28:27 +0200
Subject: [PATCH 218/548] Nav: added io.ConfigNavCursorVisibleAuto,
 io.ConfigNavCursorVisibleAlways. (#1074, #2048, #7237, #8059, #3200, #787)

Note: the NavCursorHideFrames addition is to support 88a354585 even though ConfigNavCursorVisibleAlways is set.
---
 docs/CHANGELOG.txt | 34 ++++++++++++++++++++--------------
 docs/TODO.txt      |  1 -
 imgui.cpp          | 21 +++++++++++++++++----
 imgui.h            |  2 ++
 imgui_demo.cpp     |  6 +++++-
 imgui_internal.h   |  1 +
 imgui_widgets.cpp  | 14 ++++++++++----
 7 files changed, 55 insertions(+), 24 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index ca0c2a3742d0..3279969a2bbe 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -69,20 +69,26 @@ Other changes:
   state to draw callbacks. (#6969, #5834, #7468, #3590)
 - IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
 - Error Handling: turned a few more functions into recoverable errors. (#1651)
-- Nav: added NavSetCursorVisible(bool visible) to manipulate visibility of keyboard/gamepad
-  navigation cursor. (#1074, #2048, #7237, #8059)
-- Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change
-  how pressing Escape affects navigation. (#8059, #2048, #1074, #3200)
-  - Set io.ConfigNavEscapeClearFocusItem = true (default) to clear focused item and highlight.
-  - Set io.ConfigNavEscapeClearFocusItem = false for Escape to not have a specific effect.
-  - Set io.ConfigNavEscapeClearFocusWindow = true to completely unfocus the dear imgui window,
-    is for some reason your app relies on imgui focus to take other decisions.  
-- Nav: pressing escape to hide nav highlight doesn't clear location from when ctrl+tabbing 
-  back into same window later.
-- Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
-  window. (#3200)
-- Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
-  when e.g activating the item with mouse, then Ctrl+Tabbing back and forth. 
+- Nav (Keyboard/Gamepad navigation):
+  - Nav: added io.ConfigNavCursorVisibleAuto and io.ConfigNavCursorVisibleAlways to configure
+    visibility of navigation cursor. (#1074, #2048, #7237, #8059, #3200, #787)
+     - Set io.ConfigNavCursorVisibleAuto = true (default) to enable automatic toggling
+       of cursor visibility (mouse click hide the cursor, arrow keys makes it visible).
+     - Set io.ConfigNavCursorVisibleAlways to keep cursor always visible.
+  - Nav: added NavSetCursorVisible(bool visible) function to manipulate visibility of 
+    navigation cursor (e.g. set default state, or after some actions). (#1074, #2048, #7237, #8059)
+  - Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change
+    how pressing Escape affects navigation. (#8059, #2048, #1074, #3200)
+    - Set io.ConfigNavEscapeClearFocusItem = true (default) to clear focused item and highlight.
+    - Set io.ConfigNavEscapeClearFocusItem = false for Escape to not have a specific effect.
+    - Set io.ConfigNavEscapeClearFocusWindow = true to completely unfocus the dear imgui window,
+      is for some reason your app relies on imgui focus to take other decisions.  
+  - Nav: pressing escape to hide nav highlight doesn't clear location from when Ctrl+Tabbing 
+    back into same window later.
+  - Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
+    window. (#3200)
+  - Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
+    when e.g activating the item with mouse, then Ctrl+Tabbing back and forth. 
 - Disabled: clicking a disabled item focuses parent window. (#8064) 
 - InvisibleButton, Nav: fixed an issue when InvisibleButton() would be navigable into but
   not display navigation highlight. Properly navigation on it by default. (#8057)
diff --git a/docs/TODO.txt b/docs/TODO.txt
index dd98d18b17d3..2a42874cd3fe 100644
--- a/docs/TODO.txt
+++ b/docs/TODO.txt
@@ -274,7 +274,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
  - font/opt: Glyph currently 40 bytes (2+9*4). Consider storing UV as 16-bits integer? (->32 bytes). X0/Y0/X1/Y1 as 16 fixed-point integers? Or X0/Y0 as float and X1/Y1 as fixed8_8?
 
  - nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line? how about CTRL+Tab)
- ! nav: never clear NavId on some setup (e.g. gamepad centric)
  - nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view?
  - nav: NavScrollToBringItemIntoView() with item bigger than view should focus top-right? Repro: using Nav in "About Window"
  - nav: expose wrap around flags/logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping().
diff --git a/imgui.cpp b/imgui.cpp
index c4388cedd4c2..0ebd61dc5537 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1406,6 +1406,8 @@ ImGuiIO::ImGuiIO()
     ConfigNavCaptureKeyboard = true;
     ConfigNavEscapeClearFocusItem = true;
     ConfigNavEscapeClearFocusWindow = false;
+    ConfigNavCursorVisibleAuto = true;
+    ConfigNavCursorVisibleAlways = false;
 
     // Miscellaneous options
     MouseDrawCursor = false;
@@ -3916,6 +3918,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     NavHighlightActivatedTimer = 0.0f;
     NavInputSource = ImGuiInputSource_Keyboard;
     NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
+    NavCursorHideFrames = 0;
 
     NavAnyRequest = false;
     NavInitRequest = false;
@@ -4828,7 +4831,8 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
     ImGuiContext& g = *GImGui;
     FocusWindow(window);
     SetActiveID(window->MoveId, window);
-    g.NavCursorVisible = false;
+    if (g.IO.ConfigNavCursorVisibleAuto)
+        g.NavCursorVisible = false;
     g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos;
     g.ActiveIdNoClearOnFocusLoss = true;
     SetActiveIdUsingAllKeyboardKeys();
@@ -12216,6 +12220,8 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
 void ImGui::SetNavCursorVisible(bool visible)
 {
     ImGuiContext& g = *GImGui;
+    if (g.IO.ConfigNavCursorVisibleAlways)
+        visible = true;
     g.NavCursorVisible = visible;
 }
 
@@ -12223,7 +12229,8 @@ void ImGui::SetNavCursorVisible(bool visible)
 void ImGui::SetNavCursorVisibleAfterMove()
 {
     ImGuiContext& g = *GImGui;
-    g.NavCursorVisible = true;
+    if (g.IO.ConfigNavCursorVisibleAuto)
+        g.NavCursorVisible = true;
     g.NavHighlightItemUnderNav = g.NavMousePosDirty = true;
 }
 
@@ -12289,7 +12296,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
 
     if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
         g.NavHighlightItemUnderNav = true;
-    else
+    else if (g.IO.ConfigNavCursorVisibleAuto)
         g.NavCursorVisible = false;
 
     // Clear preferred scoring position (NavMoveRequestApplyResult() will tend to restore it)
@@ -12904,6 +12911,9 @@ static void ImGui::NavUpdate()
         NavMoveRequestApplyResult();
     g.NavTabbingCounter = 0;
     g.NavMoveSubmitted = g.NavMoveScoringItems = false;
+    if (g.NavCursorHideFrames > 0)
+        if (--g.NavCursorHideFrames == 0)
+            g.NavCursorVisible = true;
 
     // Schedule mouse position update (will be done at the bottom of this function, after 1) processing all move requests and 2) updating scrolling)
     bool set_mouse_pos = false;
@@ -12958,6 +12968,8 @@ static void ImGui::NavUpdate()
     }
     if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
         g.NavCursorVisible = false;
+    else if (g.IO.ConfigNavCursorVisibleAlways && g.NavCursorHideFrames == 0)
+        g.NavCursorVisible = true;
     if (g.NavActivateId != 0)
         IM_ASSERT(g.NavActivateDownId == g.NavActivateId);
 
@@ -13158,7 +13170,8 @@ void ImGui::NavUpdateCreateMoveRequest()
         IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name : "", g.NavLayer);
         g.NavInitRequest = g.NavInitRequestFromMove = true;
         g.NavInitResult.ID = 0;
-        g.NavCursorVisible = true;
+        if (g.IO.ConfigNavCursorVisibleAuto)
+            g.NavCursorVisible = true;
     }
 
     // When using gamepad, we project the reference nav bounding box into window visible area.
diff --git a/imgui.h b/imgui.h
index 60bcbee6c548..73705cd367d7 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2252,6 +2252,8 @@ struct ImGuiIO
     bool        ConfigNavCaptureKeyboard;       // = true           // Sets io.WantCaptureKeyboard when io.NavActive is set.
     bool        ConfigNavEscapeClearFocusItem;  // = true           // Pressing Escape can clear focused item + navigation id/highlight. Set to false if you want to always keep highlight on.
     bool        ConfigNavEscapeClearFocusWindow;// = false          // Pressing Escape can clear focused window as well (super set of io.ConfigNavEscapeClearFocusItem).
+    bool        ConfigNavCursorVisibleAuto;     // = true           // Using directional navigation key makes the cursor visible. Mouse click hides the cursor.
+    bool        ConfigNavCursorVisibleAlways;   // = false          // Navigation cursor is always visible.
 
     // Miscellaneous options
     // (you can visualize and interact with all options in 'Demo->Configuration')
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index c484dd48c79e..668c5c0eedad 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -527,7 +527,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
             ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
 
-            ImGui::SeparatorText("Navigation");
+            ImGui::SeparatorText("Keyboard/Gamepad Navigation");
             ImGui::Checkbox("io.ConfigNavSwapGamepadButtons", &io.ConfigNavSwapGamepadButtons);
             ImGui::Checkbox("io.ConfigNavMoveSetMousePos", &io.ConfigNavMoveSetMousePos);
             ImGui::SameLine(); HelpMarker("Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult");
@@ -536,6 +536,10 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::SameLine(); HelpMarker("Pressing Escape clears focused item.");
             ImGui::Checkbox("io.ConfigNavEscapeClearFocusWindow", &io.ConfigNavEscapeClearFocusWindow);
             ImGui::SameLine(); HelpMarker("Pressing Escape clears focused window.");
+            ImGui::Checkbox("io.ConfigNavCursorVisibleAuto", &io.ConfigNavCursorVisibleAuto);
+            ImGui::SameLine(); HelpMarker("Using directional navigation key makes the cursor visible. Mouse click hides the cursor.");
+            ImGui::Checkbox("io.ConfigNavCursorVisibleAlways", &io.ConfigNavCursorVisibleAlways);
+            ImGui::SameLine(); HelpMarker("Navigation cursor is always visible.");
 
             ImGui::SeparatorText("Widgets");
             ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
diff --git a/imgui_internal.h b/imgui_internal.h
index bca327cdf888..97a51a3559d4 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2154,6 +2154,7 @@ struct ImGuiContext
     ImGuiActivateFlags      NavNextActivateFlags;
     ImGuiInputSource        NavInputSource;                     // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
     ImGuiSelectionUserData  NavLastValidSelectionUserData;      // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
+    ImS8                    NavCursorHideFrames;
 
     // Navigation: Init & Move Requests
     bool                    NavAnyRequest;                      // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index e0bc7f7476bf..307e11d5b780 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -619,7 +619,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
                     pressed = true;
         }
 
-        if (pressed)
+        if (pressed && g.IO.ConfigNavCursorVisibleAuto)
             g.NavCursorVisible = false;
     }
 
@@ -688,7 +688,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
                 }
                 ClearActiveID();
             }
-            if (!(flags & ImGuiButtonFlags_NoNavFocus))
+            if (!(flags & ImGuiButtonFlags_NoNavFocus) && g.IO.ConfigNavCursorVisibleAuto)
                 g.NavCursorVisible = false;
         }
         else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
@@ -7001,7 +7001,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
         if (!g.NavHighlightItemUnderNav && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
         {
             SetNavID(id, window->DC.NavLayerCurrent, g.CurrentFocusScopeId, WindowRectAbsToRel(window, bb)); // (bb == NavRect)
-            g.NavCursorVisible = false;
+            if (g.IO.ConfigNavCursorVisibleAuto)
+                g.NavCursorVisible = false;
         }
     }
     if (pressed)
@@ -8624,7 +8625,12 @@ void ImGui::EndMenuBar()
             IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check (FIXME: Seems unnecessary)
             FocusWindow(window);
             SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
-            g.NavCursorVisible = false; // Hide nav cursor for the current frame so we don't see the intermediary selection.
+            // FIXME-NAV: How to deal with this when not using g.IO.ConfigNavCursorVisibleAuto?
+            if (g.NavCursorVisible)
+            {
+                g.NavCursorVisible = false; // Hide nav cursor for the current frame so we don't see the intermediary selection. Will be set again
+                g.NavCursorHideFrames = 2;
+            }
             g.NavHighlightItemUnderNav = g.NavMousePosDirty = true;
             NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Repeat
         }

From 83b64b8be222248d9d15a4f9325ddf5f1e97ddbc Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 18 Oct 2024 21:33:35 +0200
Subject: [PATCH 219/548] Version 1.91.4

---
 docs/CHANGELOG.txt | 10 +++++-----
 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, 14 insertions(+), 14 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 3279969a2bbe..b7b8df333fb1 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -36,18 +36,18 @@ HOW TO UPDATE?
 - Please report any issue!
 
 -----------------------------------------------------------------------
- VERSION 1.91.4 WIP (In Progress)
+ VERSION 1.91.4 (Released 2024-10-18)
 -----------------------------------------------------------------------
 
 Breaking changes:
 
-- Style: renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor, for consistency with newly
-  exposed and reworked features. Kept inline redirection enum (will obsolete).
+- Style: renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor, for consistency with 
+  newly exposed and reworked features. Kept inline redirection enum (will obsolete).
 - The typedef for ImTextureID now defaults to ImU64 instead of void*. (#1641)
   - This removes the requirement to redefine it for backends which are e.g. storing
     descriptor sets or other 64-bits structures when building on 32-bits archs
     (namely our DX12 and Vulkan backends). It therefore simplify various building scripts/helpers.
-  - You may have compile-time issues if you were casting to 'void*' instead of 'ImTextureID'
+  - You may have compile-time warnings if you were casting to 'void*' instead of 'ImTextureID'
     when passing your types to functions taking ImTextureID values, e.g. ImGui::Image().
     In doubt it is almost always better to do an intermediate intptr_t cast, since it
     allows casting any pointer/integer type without warning:
@@ -109,7 +109,7 @@ Other changes:
 - InputText: ensure mouse cursor shape is set regardless of whether keyboard mode is 
   enabled or not. (#6417)
 - InputScalar: added an assert to clarify that ImGuiInputTextFlags_EnterReturnsTrue is not
-  supported by InputFloat, InputInt, InputScalar etc. widgets. It actually never was. (#8065)
+  supported by InputFloat, InputInt, InputScalar etc. widgets. It actually never was. (#8065, #3946)
 - imgui_freetype: Added support for plutosvg (as an alternative to lunasvg) to render 
   OpenType SVG fonts. Requires defining IMGUI_ENABLE_FREETYPE_PLUTOSVG along with IMGUI_ENABLE_FREETYPE.
   Providing headers/librairies for plutosvg + plutovg is up to you (see #7927 for help).
diff --git a/imgui.cpp b/imgui.cpp
index 0ebd61dc5537..f85d4f139cf5 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4 WIP
+// dear imgui, v1.91.4
 // (main code and documentation)
 
 // Help:
diff --git a/imgui.h b/imgui.h
index 73705cd367d7..22f992fa92e4 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4 WIP
+// dear imgui, v1.91.4
 // (headers)
 
 // Help:
@@ -28,8 +28,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.4 WIP"
-#define IMGUI_VERSION_NUM   19136
+#define IMGUI_VERSION       "1.91.4"
+#define IMGUI_VERSION_NUM   19140
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 668c5c0eedad..5849e11ef9e2 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4 WIP
+// dear imgui, v1.91.4
 // (demo code)
 
 // Help:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 57b7d3ba2b91..2fba4993fc45 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4 WIP
+// dear imgui, v1.91.4
 // (drawing and font code)
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index 97a51a3559d4..c9ddceb34206 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4 WIP
+// dear imgui, v1.91.4
 // (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 1f8035cde6f2..598496be4222 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4 WIP
+// dear imgui, v1.91.4
 // (tables and columns code)
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 307e11d5b780..dea089c265f6 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4 WIP
+// dear imgui, v1.91.4
 // (widgets code)
 
 /*

From 99109c0b3b052cffa154a9295440f68868a39f74 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 18 Oct 2024 22:04:03 +0200
Subject: [PATCH 220/548] Amend Changelog, oops didn't get it in the previous
 commit.

---
 docs/CHANGELOG.txt | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index b7b8df333fb1..81aec81ea587 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -55,7 +55,7 @@ Breaking changes:
     - May warn:     ImGui::Image((void*)(intptr_t)MyTextureData, ...);
     - Won't warn:   ImGui::Image((ImTextureID)(intptr_t)MyTextureData), ...);
   - Note that you can always define ImTextureID to be your own high-level structures
-    (with dedicated constructors) if you like.
+    (with dedicated constructors and extra render parameters) if you like.
 - IO: moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
 - IO: moved ImGuiConfigFlags_NavNoCaptureKeyboard to standalone io.ConfigNavCaptureKeyboard bool 
   (note the inverted value!). (#2517, #2009)
@@ -65,9 +65,9 @@ Breaking changes:
 Other changes:
 
 - IO: added 'void* platform_io.Renderer_RenderState' which is set during the
-  ImGui_ImplXXXX_RenderDrawData() of standard backend to expose selected render
-  state to draw callbacks. (#6969, #5834, #7468, #3590)
-- IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
+  ImGui_ImplXXXX_RenderDrawData() of standard backends to expose selected render
+  states to your draw callbacks. (#6969, #5834, #7468, #3590)
+- IO: io.WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921)
 - Error Handling: turned a few more functions into recoverable errors. (#1651)
 - Nav (Keyboard/Gamepad navigation):
   - Nav: added io.ConfigNavCursorVisibleAuto and io.ConfigNavCursorVisibleAlways to configure
@@ -80,15 +80,14 @@ Other changes:
   - Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change
     how pressing Escape affects navigation. (#8059, #2048, #1074, #3200)
     - Set io.ConfigNavEscapeClearFocusItem = true (default) to clear focused item and highlight.
-    - Set io.ConfigNavEscapeClearFocusItem = false for Escape to not have a specific effect.
+    - Set io.ConfigNavEscapeClearFocusItem = false for Escape to not have an effect.
     - Set io.ConfigNavEscapeClearFocusWindow = true to completely unfocus the dear imgui window,
       is for some reason your app relies on imgui focus to take other decisions.  
-  - Nav: pressing escape to hide nav highlight doesn't clear location from when Ctrl+Tabbing 
-    back into same window later.
-  - Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most
-    window. (#3200)
-  - Nav: rectangle highlight not rendered for items with ImGuiItemFlags_NoNav. Can be relevant
-    when e.g activating the item with mouse, then Ctrl+Tabbing back and forth. 
+  - Nav: pressing escape to hide the navigation cursor doesn't clear location, so it may be
+    restored when Ctrl+Tabbing back into the same window later.
+  - Nav: fixed Ctrl+Tab initiated with no focused window from skipping the top-most window. (#3200)
+  - Nav: navigation cursor is not rendered for items with `ImGuiItemFlags_NoNav`. Can be relevant 
+    when e.g activating a _NoNav item with mouse, then Ctrl+Tabbing back and forth.
 - Disabled: clicking a disabled item focuses parent window. (#8064) 
 - InvisibleButton, Nav: fixed an issue when InvisibleButton() would be navigable into but
   not display navigation highlight. Properly navigation on it by default. (#8057)
@@ -103,9 +102,11 @@ Other changes:
     We store them in a buffer stored inside the drawlist. ImDrawCmd::UserCallbackData 
     will point inside that buffer so you have to retrieve data from there. Your callback
     may need to use ImDrawCmd::UserCallbackDataSize if you expect dynamically-sized data.
-- Tables: fixed initial auto-sizing issue with synched-instances. (#8045, #7218)
+  - Note that we use a raw type-less copy.
+- Tables: fixed initial auto-sizing issue with synced-instances. (#8045, #7218)
 - InputText: fixed an issue with not declaring ownership of Delete/Backspace/Arrow keys,
-  preventing use of external shortcuts not guarded by an ActiveId check. (#8048) [@geertbleyen]
+  preventing use of external shortcuts that are not guarded by an ActiveId check. (#8048) 
+  [@geertbleyen]
 - InputText: ensure mouse cursor shape is set regardless of whether keyboard mode is 
   enabled or not. (#6417)
 - InputScalar: added an assert to clarify that ImGuiInputTextFlags_EnterReturnsTrue is not
@@ -115,7 +116,8 @@ Other changes:
   Providing headers/librairies for plutosvg + plutovg is up to you (see #7927 for help).
   (#7927, #7187, #6591, #6607) [@pthom]
 - Backends: DX11, DX12, SDLRenderer2/3. Vulkan, WGPU: expose selected state in
-  ImGui_ImplXXXX_RenderState structures during render loop. (#6969, #5834, #7468, #3590)
+  ImGui_ImplXXXX_RenderState structures during render loop user draw callbacks. 
+  (#6969, #5834, #7468, #3590)
 - Backends: DX9, DX10, DX11, DX12, OpenGL, Vulkan, WGPU: Changed default texture sampler
   to Clamp instead of Repeat/Wrap. (#7468, #7511, #5999, #5502, #7230)
 

From 41f02825fc5ca54596fab73b57157d85af3130b2 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 23 Oct 2024 12:16:00 +0200
Subject: [PATCH 221/548] Version 1.91.5 WIP

---
 docs/CHANGELOG.txt | 8 ++++++++
 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, 17 insertions(+), 9 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 81aec81ea587..2342c4726e74 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -35,6 +35,14 @@ 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.5 WIP (In Progress)
+-----------------------------------------------------------------------
+
+Breaking changes:
+
+Other changes:
+
 -----------------------------------------------------------------------
  VERSION 1.91.4 (Released 2024-10-18)
 -----------------------------------------------------------------------
diff --git a/imgui.cpp b/imgui.cpp
index f85d4f139cf5..0d704e16639b 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4
+// dear imgui, v1.91.5 WIP
 // (main code and documentation)
 
 // Help:
diff --git a/imgui.h b/imgui.h
index 22f992fa92e4..04f958eec69b 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4
+// dear imgui, v1.91.5 WIP
 // (headers)
 
 // Help:
@@ -28,8 +28,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.4"
-#define IMGUI_VERSION_NUM   19140
+#define IMGUI_VERSION       "1.91.5 WIP"
+#define IMGUI_VERSION_NUM   19141
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 5849e11ef9e2..f24254e2ea40 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4
+// dear imgui, v1.91.5 WIP
 // (demo code)
 
 // Help:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 2fba4993fc45..01723b35c97d 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4
+// dear imgui, v1.91.5 WIP
 // (drawing and font code)
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index c9ddceb34206..0c441a260b9c 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4
+// dear imgui, v1.91.5 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 598496be4222..03007bb79913 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4
+// dear imgui, v1.91.5 WIP
 // (tables and columns code)
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index dea089c265f6..757eb8ab68d7 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.4
+// dear imgui, v1.91.5 WIP
 // (widgets code)
 
 /*

From 4994e75852a8140072cc5dd74fac4638150a4a9e Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 23 Oct 2024 12:40:20 +0200
Subject: [PATCH 222/548] Backends: DX12: Unmap() call specify written range.

The range is informational and may be used by debug tools.
---
 backends/imgui_impl_dx12.cpp | 11 +++++++++--
 docs/CHANGELOG.txt           |  3 +++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index be117b6c16a2..7a428a1a5ad1 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -16,6 +16,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-23: DirectX12: Unmap() call specify written range. The range is informational and may be used by debug tools.
 //  2024-10-07: DirectX12: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-10-07: DirectX12: Expose selected render state in ImGui_ImplDX12_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2024-10-07: DirectX12: Compiling with '#define ImTextureID=ImU64' is unnecessary now that dear imgui defaults ImTextureID to u64 instead of void*.
@@ -218,9 +219,9 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
     }
 
     // Upload vertex/index data into a single contiguous GPU buffer
+    // During Map() we specify a null read range (as per DX12 API, this is informational and for tooling only)
     void* vtx_resource, *idx_resource;
-    D3D12_RANGE range;
-    memset(&range, 0, sizeof(D3D12_RANGE));
+    D3D12_RANGE range = { 0, 0 };
     if (fr->VertexBuffer->Map(0, &range, &vtx_resource) != S_OK)
         return;
     if (fr->IndexBuffer->Map(0, &range, &idx_resource) != S_OK)
@@ -235,7 +236,13 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
         vtx_dst += draw_list->VtxBuffer.Size;
         idx_dst += draw_list->IdxBuffer.Size;
     }
+
+    // During Unmap() we specify the written range (as per DX12 API, this is informational and for tooling only)
+    range.End = (SIZE_T)((intptr_t)vtx_dst - (intptr_t)vtx_resource);
+    IM_ASSERT(range.End == draw_data->TotalVtxCount * sizeof(ImDrawVert));
     fr->VertexBuffer->Unmap(0, &range);
+    range.End = (SIZE_T)((intptr_t)idx_dst - (intptr_t)idx_resource);
+    IM_ASSERT(range.End == draw_data->TotalIdxCount * sizeof(ImDrawIdx));
     fr->IndexBuffer->Unmap(0, &range);
 
     // Setup desired DX state
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 2342c4726e74..f66866e9e2c8 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,9 @@ Breaking changes:
 
 Other changes:
 
+- Backends: DX12: Unmap() call specify written range. The range is informational and may be used by debug tools.
+
+
 -----------------------------------------------------------------------
  VERSION 1.91.4 (Released 2024-10-18)
 -----------------------------------------------------------------------

From 062e580436e60e2e991268ef911773969a1b5774 Mon Sep 17 00:00:00 2001
From: Eugene Sandulenko 
Date: Thu, 24 Oct 2024 09:26:57 +0200
Subject: [PATCH 223/548] Fixed copy/paste error in DebugModeWindow() (#8094)

---
 imgui.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/imgui.cpp b/imgui.cpp
index 0d704e16639b..81f872f7ba61 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -16351,7 +16351,7 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label)
     for (int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
     {
         ImRect r = window->NavRectRel[layer];
-        if (r.Min.x >= r.Max.y && r.Min.y >= r.Max.y)
+        if (r.Min.x >= r.Max.x && r.Min.y >= r.Max.y)
             BulletText("NavLastIds[%d]: 0x%08X", layer, window->NavLastIds[layer]);
         else
             BulletText("NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window->NavLastIds[layer], r.Min.x, r.Min.y, r.Max.x, r.Max.y);

From 06092a9756b5476ad0b36d6f980fe904a87418da Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 24 Oct 2024 14:47:07 +0200
Subject: [PATCH 224/548] Backends: SDL2, SDL3: SDL_EVENT_MOUSE_WHEEL event
 doesn't require dividing by 100.0f on Emscripten. (#4019, #6096, #1463)

Ref https://github.com/libsdl-org/SDL/issues/10454#issuecomment-2434187317
---
 backends/imgui_impl_sdl2.cpp | 3 ++-
 backends/imgui_impl_sdl3.cpp | 4 +---
 docs/CHANGELOG.txt           | 3 ++-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp
index 1abe8b93d5e3..d87f5081ee48 100644
--- a/backends/imgui_impl_sdl2.cpp
+++ b/backends/imgui_impl_sdl2.cpp
@@ -21,6 +21,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-24: Emscripten: from SDL 2.30.9, SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f.
 //  2024-09-09: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190)
 //  2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
 //               - io.GetClipboardTextFn    -> platform_io.Platform_GetClipboardTextFn
@@ -359,7 +360,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
             float wheel_x = -(float)event->wheel.x;
             float wheel_y = (float)event->wheel.y;
 #endif
-#ifdef __EMSCRIPTEN__
+#if defined(__EMSCRIPTEN__) && !SDL_VERSION_ATLEAST(2,31,0)
             wheel_x /= 100.0f;
 #endif
             io.AddMouseSourceEvent(event->wheel.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp
index 517ba1ada1a1..ca960cad5315 100644
--- a/backends/imgui_impl_sdl3.cpp
+++ b/backends/imgui_impl_sdl3.cpp
@@ -21,6 +21,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-24: Emscripten: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f on Emscripten.
 //  2024-09-03: Update for SDL3 api changes: SDL_GetGamepads() memory ownership revert. (#7918, #7898, #7807)
 //  2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
 //               - io.GetClipboardTextFn    -> platform_io.Platform_GetClipboardTextFn
@@ -338,9 +339,6 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
             //IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY);
             float wheel_x = -event->wheel.x;
             float wheel_y = event->wheel.y;
-    #ifdef __EMSCRIPTEN__
-            wheel_x /= 100.0f;
-    #endif
             io.AddMouseSourceEvent(event->wheel.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
             io.AddMouseWheelEvent(wheel_x, wheel_y);
             return true;
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index f66866e9e2c8..997acce28dfa 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -44,7 +44,8 @@ Breaking changes:
 Other changes:
 
 - Backends: DX12: Unmap() call specify written range. The range is informational and may be used by debug tools.
-
+- Backends: SDL3: Update for SDL3 api change: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f 
+  on Emscripten target. (#4019, #6096, #1463)
 
 -----------------------------------------------------------------------
  VERSION 1.91.4 (Released 2024-10-18)

From a855bd8df3ca172e17fc7bb5ac88e0a76bd9b965 Mon Sep 17 00:00:00 2001
From: Eugene Sandulenko 
Date: Thu, 24 Oct 2024 00:20:13 +0200
Subject: [PATCH 225/548] Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize()
 forward declaration with the actual include. (#8095, #7967, #3190)

---
 backends/imgui_impl_sdl2.cpp | 2 +-
 docs/CHANGELOG.txt           | 5 +++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp
index d87f5081ee48..7a8af3b82240 100644
--- a/backends/imgui_impl_sdl2.cpp
+++ b/backends/imgui_impl_sdl2.cpp
@@ -115,7 +115,7 @@
 #endif
 #define SDL_HAS_VULKAN                      SDL_VERSION_ATLEAST(2,0,6)
 #if SDL_HAS_VULKAN
-extern "C" { extern DECLSPEC void SDLCALL SDL_Vulkan_GetDrawableSize(SDL_Window* window, int* w, int* h); }
+#include 
 #endif
 
 // SDL Data
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 997acce28dfa..2e8d2823fc4a 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -44,8 +44,9 @@ Breaking changes:
 Other changes:
 
 - Backends: DX12: Unmap() call specify written range. The range is informational and may be used by debug tools.
-- Backends: SDL3: Update for SDL3 api change: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f 
-  on Emscripten target. (#4019, #6096, #1463)
+- Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the actual include. (#8095, #7967, #3190) [@sev-] 
+- Backends: SDL2, SDL3: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing 
+  by 100.0f on Emscripten target. (#4019, #6096, #1463)
 
 -----------------------------------------------------------------------
  VERSION 1.91.4 (Released 2024-10-18)

From b4033b37ad7980e34a7335aac8375ffc109ef818 Mon Sep 17 00:00:00 2001
From: Nicolas Chavez 
Date: Mon, 21 Oct 2024 14:19:31 +0200
Subject: [PATCH 226/548] Backends: WGPU: update for Dawn WGPU String usage.
 (#8082, #8083)

---
 backends/imgui_impl_wgpu.cpp | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp
index 95f1b0c63c0f..075f74734a1f 100644
--- a/backends/imgui_impl_wgpu.cpp
+++ b/backends/imgui_impl_wgpu.cpp
@@ -17,6 +17,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-10-14: Update Dawn support for change of string usages. (#8082, #8083)
 //  2024-10-07: Expose selected render state in ImGui_ImplWGPU_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2024-10-07: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-09-16: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU define to handle ever-changing native implementations. (#7977)
@@ -275,7 +276,11 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c
 
     WGPUProgrammableStageDescriptor stage_desc = {};
     stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc);
+#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
+    stage_desc.entryPoint = { "main", WGPU_STRLEN };
+#else
     stage_desc.entryPoint = "main";
+#endif
     return stage_desc;
 }
 
@@ -388,6 +393,9 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
         {
             nullptr,
             "Dear ImGui Vertex buffer",
+#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
+            WGPU_STRLEN,
+#endif
             WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
             MEMALIGN(fr->VertexBufferSize * sizeof(ImDrawVert), 4),
             false
@@ -412,6 +420,9 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
         {
             nullptr,
             "Dear ImGui Index buffer",
+#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
+            WGPU_STRLEN,
+#endif
             WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
             MEMALIGN(fr->IndexBufferSize * sizeof(ImDrawIdx), 4),
             false
@@ -522,7 +533,11 @@ static void ImGui_ImplWGPU_CreateFontsTexture()
     // Upload texture to graphics system
     {
         WGPUTextureDescriptor tex_desc = {};
+#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
+        tex_desc.label = { "Dear ImGui Font Texture", WGPU_STRLEN };
+#else
         tex_desc.label = "Dear ImGui Font Texture";
+#endif
         tex_desc.dimension = WGPUTextureDimension_2D;
         tex_desc.size.width = width;
         tex_desc.size.height = height;
@@ -585,6 +600,9 @@ static void ImGui_ImplWGPU_CreateUniformBuffer()
     {
         nullptr,
         "Dear ImGui Uniform buffer",
+#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN
+        WGPU_STRLEN,
+#endif
         WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform,
         MEMALIGN(sizeof(Uniforms), 16),
         false

From a908d73c16a4c539b320b9f5cb001c70908ae065 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 24 Oct 2024 17:24:47 +0200
Subject: [PATCH 227/548] Backends: avoid missing -Wmissing-declaration
 warning.  (#8087, #7997)

---
 backends/imgui_impl_allegro5.cpp | 1 +
 backends/imgui_impl_glfw.cpp     | 1 +
 backends/imgui_impl_osx.mm       | 1 +
 backends/imgui_impl_sdl2.cpp     | 1 +
 backends/imgui_impl_sdl3.cpp     | 1 +
 backends/imgui_impl_win32.cpp    | 1 +
 6 files changed, 6 insertions(+)

diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp
index 9c25716231c6..d5d65703e496 100644
--- a/backends/imgui_impl_allegro5.cpp
+++ b/backends/imgui_impl_allegro5.cpp
@@ -311,6 +311,7 @@ static void ImGui_ImplAllegro5_SetClipboardText(ImGuiContext*, const char* text)
 #endif
 
 // Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code);
 ImGuiKey ImGui_ImplAllegro5_KeyCodeToImGuiKey(int key_code)
 {
     switch (key_code)
diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp
index c725e9c01d96..774fb0d5d78a 100644
--- a/backends/imgui_impl_glfw.cpp
+++ b/backends/imgui_impl_glfw.cpp
@@ -187,6 +187,7 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
 // Functions
 
 // Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode);
 ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode)
 {
     IM_UNUSED(scancode);
diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm
index 3115bf1c2144..de9b57408a06 100644
--- a/backends/imgui_impl_osx.mm
+++ b/backends/imgui_impl_osx.mm
@@ -261,6 +261,7 @@ - (void)onApplicationBecomeInactive:(NSNotification*)aNotification
 // Functions
 
 // Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code);
 ImGuiKey ImGui_ImplOSX_KeyCodeToImGuiKey(int key_code)
 {
     switch (key_code)
diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp
index 7a8af3b82240..529ca79e0a2f 100644
--- a/backends/imgui_impl_sdl2.cpp
+++ b/backends/imgui_impl_sdl2.cpp
@@ -182,6 +182,7 @@ static void ImGui_ImplSDL2_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImG
 }
 
 // Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode);
 ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode)
 {
     IM_UNUSED(scancode);
diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp
index ca960cad5315..de8b531582d8 100644
--- a/backends/imgui_impl_sdl3.cpp
+++ b/backends/imgui_impl_sdl3.cpp
@@ -161,6 +161,7 @@ static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* view
 }
 
 // Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode);
 ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode)
 {
     // Keypad doesn't have individual key values in SDL3
diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp
index bbfa1a5bedea..477d54abe97e 100644
--- a/backends/imgui_impl_win32.cpp
+++ b/backends/imgui_impl_win32.cpp
@@ -421,6 +421,7 @@ void    ImGui_ImplWin32_NewFrame()
 
 // Map VK_xxx to ImGuiKey_xxx.
 // Not static to allow third-party code to use that if they want to (but undocumented)
+ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam);
 ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam)
 {
     // There is no distinct VK_xxx for keypad enter, instead it is VK_RETURN + KF_EXTENDED.

From 1039b7f543cf18a3349b7411399ce3ed4900ce38 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 24 Oct 2024 17:49:01 +0200
Subject: [PATCH 228/548] Examples: added more build_win64.bat helpers.

---
 examples/example_glfw_vulkan/build_win64.bat  |  3 ++-
 examples/example_sdl2_vulkan/build_win32.bat  |  4 ++++
 examples/example_sdl2_vulkan/build_win64.bat  | 14 ++++++++++++++
 examples/example_sdl3_opengl3/build_win32.bat |  8 +++++++-
 examples/example_sdl3_opengl3/build_win64.bat | 14 ++++++++++++++
 5 files changed, 41 insertions(+), 2 deletions(-)
 create mode 100644 examples/example_sdl2_vulkan/build_win64.bat
 create mode 100644 examples/example_sdl3_opengl3/build_win64.bat

diff --git a/examples/example_glfw_vulkan/build_win64.bat b/examples/example_glfw_vulkan/build_win64.bat
index 54e40e3e8e0a..ca9b788d8eef 100644
--- a/examples/example_glfw_vulkan/build_win64.bat
+++ b/examples/example_glfw_vulkan/build_win64.bat
@@ -1,5 +1,6 @@
-@REM Build for Visual Studio compiler. Run your copy of amd64/vcvars32.bat to setup 64-bit command-line compiler.
+@REM Build for Visual Studio compiler. Run your copy of vcvars64.bat or vcvarsall.bat to setup 64-bit command-line compiler.
 
+@set OUT_EXE=example_glfw_vulkan
 @set INCLUDES=/I..\.. /I..\..\backends /I..\libs\glfw\include /I %VULKAN_SDK%\include
 @set SOURCES=main.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp
 @set LIBS=/LIBPATH:..\libs\glfw\lib-vc2010-64 /libpath:%VULKAN_SDK%\lib glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
diff --git a/examples/example_sdl2_vulkan/build_win32.bat b/examples/example_sdl2_vulkan/build_win32.bat
index 977a2c7e4eb1..f634aba00679 100644
--- a/examples/example_sdl2_vulkan/build_win32.bat
+++ b/examples/example_sdl2_vulkan/build_win32.bat
@@ -8,3 +8,7 @@
 @set OUT_DIR=Debug
 mkdir %OUT_DIR%
 cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
+
+@set OUT_DIR=Release
+@REM mkdir %OUT_DIR%
+@REM cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/examples/example_sdl2_vulkan/build_win64.bat b/examples/example_sdl2_vulkan/build_win64.bat
new file mode 100644
index 000000000000..5d315cca21df
--- /dev/null
+++ b/examples/example_sdl2_vulkan/build_win64.bat
@@ -0,0 +1,14 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars64.bat or vcvarsall.bat to setup command-line compiler.
+
+@set OUT_EXE=example_sdl2_vulkan
+@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include /I %VULKAN_SDK%\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x64 /libpath:%VULKAN_SDK%\lib SDL2.lib SDL2main.lib shell32.lib vulkan-1.lib
+
+@set OUT_DIR=Debug
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
+
+@set OUT_DIR=Release
+@REM mkdir %OUT_DIR%
+@REM cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/examples/example_sdl3_opengl3/build_win32.bat b/examples/example_sdl3_opengl3/build_win32.bat
index 5b8d5f87136b..5bed40ac1791 100644
--- a/examples/example_sdl3_opengl3/build_win32.bat
+++ b/examples/example_sdl3_opengl3/build_win32.bat
@@ -1,8 +1,14 @@
 @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
-@set OUT_DIR=Debug
+
 @set OUT_EXE=example_sdl3_opengl3
 @set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include
 @set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp
 @set LIBS=/LIBPATH:%SDL3_DIR%\lib\x86 SDL3.lib opengl32.lib shell32.lib
+
+@set OUT_DIR=Debug
 mkdir %OUT_DIR%
 cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
+
+@set OUT_DIR=Release
+@REM mkdir %OUT_DIR%
+@REM cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/examples/example_sdl3_opengl3/build_win64.bat b/examples/example_sdl3_opengl3/build_win64.bat
new file mode 100644
index 000000000000..87c6bb8b520f
--- /dev/null
+++ b/examples/example_sdl3_opengl3/build_win64.bat
@@ -0,0 +1,14 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars64.bat or vcvarsall.bat to setup command-line compiler.
+
+@set OUT_EXE=example_sdl3_opengl3
+@set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:%SDL3_DIR%\lib\x64 SDL3.lib opengl32.lib shell32.lib
+
+@set OUT_DIR=Debug
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
+
+@set OUT_DIR=Release
+@REM mkdir %OUT_DIR%
+@REM cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console

From ccb6646baeac88d276078ebade5616f4c6d7c03a Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 24 Oct 2024 18:07:22 +0200
Subject: [PATCH 229/548] Examples: added SDL3+Vulkan example. (#8084, #8085)

---
 docs/CHANGELOG.txt                            |   7 +-
 examples/example_sdl3_vulkan/build_win32.bat  |  14 +
 examples/example_sdl3_vulkan/build_win64.bat  |  14 +
 .../example_sdl3_vulkan.vcxproj               | 190 ++++++
 .../example_sdl3_vulkan.vcxproj.filters       |  64 ++
 examples/example_sdl3_vulkan/main.cpp         | 587 ++++++++++++++++++
 examples/imgui_examples.sln                   |  10 +
 7 files changed, 884 insertions(+), 2 deletions(-)
 create mode 100644 examples/example_sdl3_vulkan/build_win32.bat
 create mode 100644 examples/example_sdl3_vulkan/build_win64.bat
 create mode 100644 examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj
 create mode 100644 examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj.filters
 create mode 100644 examples/example_sdl3_vulkan/main.cpp

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 2e8d2823fc4a..194803ac6de1 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,10 +43,13 @@ Breaking changes:
 
 Other changes:
 
-- Backends: DX12: Unmap() call specify written range. The range is informational and may be used by debug tools.
-- Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the actual include. (#8095, #7967, #3190) [@sev-] 
+- Backends: DX12: Unmap() call specify written range. The range is informational and
+  may be used by debug tools.
+- Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the 
+  actual include. (#8095, #7967, #3190) [@sev-] 
 - Backends: SDL2, SDL3: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing 
   by 100.0f on Emscripten target. (#4019, #6096, #1463)
+- Examples: Added SDL3+Vulkan example. (#8084, #8085)
 
 -----------------------------------------------------------------------
  VERSION 1.91.4 (Released 2024-10-18)
diff --git a/examples/example_sdl3_vulkan/build_win32.bat b/examples/example_sdl3_vulkan/build_win32.bat
new file mode 100644
index 000000000000..3e26d3088211
--- /dev/null
+++ b/examples/example_sdl3_vulkan/build_win32.bat
@@ -0,0 +1,14 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+
+@set OUT_EXE=example_sdl3_vulkan
+@set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include /I %VULKAN_SDK%\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:%SDL3_DIR%\lib\x86 /libpath:%VULKAN_SDK%\lib32 SDL3.lib shell32.lib vulkan-1.lib
+
+@set OUT_DIR=Debug
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
+
+@set OUT_DIR=Release
+@REM mkdir %OUT_DIR%
+@REM cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/examples/example_sdl3_vulkan/build_win64.bat b/examples/example_sdl3_vulkan/build_win64.bat
new file mode 100644
index 000000000000..5d038d1ee69f
--- /dev/null
+++ b/examples/example_sdl3_vulkan/build_win64.bat
@@ -0,0 +1,14 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars64.bat or vcvarsall.bat to setup command-line compiler.
+
+@set OUT_EXE=example_sdl3_vulkan
+@set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include /I %VULKAN_SDK%\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:%SDL3_DIR%\lib\x64 /libpath:%VULKAN_SDK%\lib SDL3.lib shell32.lib vulkan-1.lib
+
+@set OUT_DIR=Debug
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
+
+@set OUT_DIR=Release
+@REM mkdir %OUT_DIR%
+@REM cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj b/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj
new file mode 100644
index 000000000000..d48e4aff3051
--- /dev/null
+++ b/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj
@@ -0,0 +1,190 @@
+
+
+  
+    
+      Debug
+      Win32
+    
+    
+      Debug
+      x64
+    
+    
+      Release
+      Win32
+    
+    
+      Release
+      x64
+    
+  
+  
+    {663A7E89-1E42-4222-921C-177F5B5910DF}
+    example_sdl3_vulkan
+    8.1
+  
+  
+  
+    Application
+    true
+    MultiByte
+    v140
+  
+  
+    Application
+    true
+    MultiByte
+    v140
+  
+  
+    Application
+    false
+    true
+    MultiByte
+    v140
+  
+  
+    Application
+    false
+    true
+    MultiByte
+    v140
+  
+  
+  
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+    
+  
+  
+  
+    $(ProjectDir)$(Configuration)\
+    $(ProjectDir)$(Configuration)\
+    $(IncludePath)
+  
+  
+    $(ProjectDir)$(Configuration)\
+    $(ProjectDir)$(Configuration)\
+    $(IncludePath)
+  
+  
+    $(ProjectDir)$(Configuration)\
+    $(ProjectDir)$(Configuration)\
+    $(IncludePath)
+  
+  
+    $(ProjectDir)$(Configuration)\
+    $(ProjectDir)$(Configuration)\
+    $(IncludePath)
+  
+  
+    
+      Level4
+      Disabled
+      ..\..;..\..\backends;%VULKAN_SDK%\include;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)
+      _MBCS;%(PreprocessorDefinitions)
+      /utf-8 %(AdditionalOptions)
+    
+    
+      true
+      %VULKAN_SDK%\lib32;%SDL3_DIR%\lib\x86;%(AdditionalLibraryDirectories)
+      vulkan-1.lib;SDL3.lib;%(AdditionalDependencies)
+      Console
+      msvcrt.lib
+    
+  
+  
+    
+      Level4
+      Disabled
+      ..\..;..\..\backends;%VULKAN_SDK%\include;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)
+      _MBCS;%(PreprocessorDefinitions)
+      /utf-8 %(AdditionalOptions)
+    
+    
+      true
+      %VULKAN_SDK%\lib;%SDL3_DIR%\lib\x64;%(AdditionalLibraryDirectories)
+      vulkan-1.lib;SDL3.lib;%(AdditionalDependencies)
+      Console
+      msvcrt.lib
+    
+  
+  
+    
+      Level4
+      MaxSpeed
+      true
+      true
+      ..\..;..\..\backends;%VULKAN_SDK%\include;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)
+      false
+      _MBCS;%(PreprocessorDefinitions)
+      /utf-8 %(AdditionalOptions)
+    
+    
+      true
+      true
+      true
+      %VULKAN_SDK%\lib32;%SDL3_DIR%\lib\x86;%(AdditionalLibraryDirectories)
+      vulkan-1.lib;SDL3.lib;%(AdditionalDependencies)
+      Console
+      
+      
+    
+  
+  
+    
+      Level4
+      MaxSpeed
+      true
+      true
+      ..\..;..\..\backends;%VULKAN_SDK%\include;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)
+      false
+      _MBCS;%(PreprocessorDefinitions)
+      /utf-8 %(AdditionalOptions)
+    
+    
+      true
+      true
+      true
+      %VULKAN_SDK%\lib;%SDL3_DIR%\lib\x64;%(AdditionalLibraryDirectories)
+      vulkan-1.lib;SDL3.lib;%(AdditionalDependencies)
+      Console
+      
+      
+    
+  
+  
+    
+    
+    
+    
+    
+    
+    
+    
+  
+  
+    
+    
+    
+    
+    
+  
+  
+    
+    
+    
+  
+  
+  
+  
+
\ No newline at end of file
diff --git a/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj.filters b/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj.filters
new file mode 100644
index 000000000000..46ebb58290a7
--- /dev/null
+++ b/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj.filters
@@ -0,0 +1,64 @@
+
+
+  
+    
+      {20b90ce4-7fcb-4731-b9a0-075f875de82d}
+    
+    
+      {f18ab499-84e1-499f-8eff-9754361e0e52}
+      cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+    
+  
+  
+    
+      imgui
+    
+    
+      imgui
+    
+    
+      imgui
+    
+    
+      sources
+    
+    
+      sources
+    
+    
+      sources
+    
+    
+      imgui
+    
+    
+      imgui
+    
+  
+  
+    
+      imgui
+    
+    
+      imgui
+    
+    
+      imgui
+    
+    
+      sources
+    
+    
+      sources
+    
+  
+  
+    
+    
+      imgui
+    
+    
+      imgui
+    
+  
+
\ No newline at end of file
diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp
new file mode 100644
index 000000000000..dde3c0d4c1f1
--- /dev/null
+++ b/examples/example_sdl3_vulkan/main.cpp
@@ -0,0 +1,587 @@
+// Dear ImGui: standalone example application for SDL3 + Vulkan
+
+// Learn about Dear ImGui:
+// - FAQ                  https://dearimgui.com/faq
+// - Getting Started      https://dearimgui.com/getting-started
+// - Documentation        https://dearimgui.com/docs (same as your local docs/ folder).
+// - Introduction, links and more at the top of imgui.cpp
+
+// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
+// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
+//   You will use those if you want to use this rendering backend in your engine/app.
+// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
+//   the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
+// Read comments in imgui_impl_vulkan.h.
+
+#include "imgui.h"
+#include "imgui_impl_sdl3.h"
+#include "imgui_impl_vulkan.h"
+#include           // printf, fprintf
+#include          // abort
+#include 
+#include 
+
+// This example doesn't compile with Emscripten yet! Awaiting SDL3 support.
+#ifdef __EMSCRIPTEN__
+#include "../libs/emscripten/emscripten_mainloop_stub.h"
+#endif
+
+// Volk headers
+#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
+#define VOLK_IMPLEMENTATION
+#include 
+#endif
+
+//#define APP_USE_UNLIMITED_FRAME_RATE
+#ifdef _DEBUG
+#define APP_USE_VULKAN_DEBUG_REPORT
+#endif
+
+// Data
+static VkAllocationCallbacks*   g_Allocator = nullptr;
+static VkInstance               g_Instance = VK_NULL_HANDLE;
+static VkPhysicalDevice         g_PhysicalDevice = VK_NULL_HANDLE;
+static VkDevice                 g_Device = VK_NULL_HANDLE;
+static uint32_t                 g_QueueFamily = (uint32_t)-1;
+static VkQueue                  g_Queue = VK_NULL_HANDLE;
+static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
+static VkPipelineCache          g_PipelineCache = VK_NULL_HANDLE;
+static VkDescriptorPool         g_DescriptorPool = VK_NULL_HANDLE;
+
+static ImGui_ImplVulkanH_Window g_MainWindowData;
+static uint32_t                 g_MinImageCount = 2;
+static bool                     g_SwapChainRebuild = false;
+
+static void check_vk_result(VkResult err)
+{
+    if (err == 0)
+        return;
+    fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
+    if (err < 0)
+        abort();
+}
+
+#ifdef APP_USE_VULKAN_DEBUG_REPORT
+static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
+{
+    (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
+    fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
+    return VK_FALSE;
+}
+#endif // APP_USE_VULKAN_DEBUG_REPORT
+
+static bool IsExtensionAvailable(const ImVector& properties, const char* extension)
+{
+    for (const VkExtensionProperties& p : properties)
+        if (strcmp(p.extensionName, extension) == 0)
+            return true;
+    return false;
+}
+
+static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice()
+{
+    uint32_t gpu_count;
+    VkResult err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr);
+    check_vk_result(err);
+    IM_ASSERT(gpu_count > 0);
+
+    ImVector gpus;
+    gpus.resize(gpu_count);
+    err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus.Data);
+    check_vk_result(err);
+
+    // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
+    // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
+    // dedicated GPUs) is out of scope of this sample.
+    for (VkPhysicalDevice& device : gpus)
+    {
+        VkPhysicalDeviceProperties properties;
+        vkGetPhysicalDeviceProperties(device, &properties);
+        if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
+            return device;
+    }
+
+    // Use first GPU (Integrated) is a Discrete one is not available.
+    if (gpu_count > 0)
+        return gpus[0];
+    return VK_NULL_HANDLE;
+}
+
+static void SetupVulkan(ImVector instance_extensions)
+{
+    VkResult err;
+#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
+    volkInitialize();
+#endif
+
+    // Create Vulkan Instance
+    {
+        VkInstanceCreateInfo create_info = {};
+        create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+
+        // Enumerate available extensions
+        uint32_t properties_count;
+        ImVector properties;
+        vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, nullptr);
+        properties.resize(properties_count);
+        err = vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, properties.Data);
+        check_vk_result(err);
+
+        // Enable required extensions
+        if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
+            instance_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+#ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
+        if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME))
+        {
+            instance_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
+            create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
+        }
+#endif
+
+        // Enabling validation layers
+#ifdef APP_USE_VULKAN_DEBUG_REPORT
+        const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
+        create_info.enabledLayerCount = 1;
+        create_info.ppEnabledLayerNames = layers;
+        instance_extensions.push_back("VK_EXT_debug_report");
+#endif
+
+        // Create Vulkan Instance
+        create_info.enabledExtensionCount = (uint32_t)instance_extensions.Size;
+        create_info.ppEnabledExtensionNames = instance_extensions.Data;
+        err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
+        check_vk_result(err);
+#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
+        volkLoadInstance(g_Instance);
+#endif
+
+        // Setup the debug report callback
+#ifdef APP_USE_VULKAN_DEBUG_REPORT
+        auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
+        IM_ASSERT(f_vkCreateDebugReportCallbackEXT != nullptr);
+        VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
+        debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
+        debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+        debug_report_ci.pfnCallback = debug_report;
+        debug_report_ci.pUserData = nullptr;
+        err = f_vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
+        check_vk_result(err);
+#endif
+    }
+
+    // Select Physical Device (GPU)
+    g_PhysicalDevice = SetupVulkan_SelectPhysicalDevice();
+
+    // Select graphics queue family
+    {
+        uint32_t count;
+        vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, nullptr);
+        VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
+        vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues);
+        for (uint32_t i = 0; i < count; i++)
+            if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
+            {
+                g_QueueFamily = i;
+                break;
+            }
+        free(queues);
+        IM_ASSERT(g_QueueFamily != (uint32_t)-1);
+    }
+
+    // Create Logical Device (with 1 queue)
+    {
+        ImVector device_extensions;
+        device_extensions.push_back("VK_KHR_swapchain");
+
+        // Enumerate physical device extension
+        uint32_t properties_count;
+        ImVector properties;
+        vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, nullptr);
+        properties.resize(properties_count);
+        vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, properties.Data);
+#ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME
+        if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME))
+            device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
+#endif
+
+        const float queue_priority[] = { 1.0f };
+        VkDeviceQueueCreateInfo queue_info[1] = {};
+        queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+        queue_info[0].queueFamilyIndex = g_QueueFamily;
+        queue_info[0].queueCount = 1;
+        queue_info[0].pQueuePriorities = queue_priority;
+        VkDeviceCreateInfo create_info = {};
+        create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+        create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
+        create_info.pQueueCreateInfos = queue_info;
+        create_info.enabledExtensionCount = (uint32_t)device_extensions.Size;
+        create_info.ppEnabledExtensionNames = device_extensions.Data;
+        err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
+        check_vk_result(err);
+        vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
+    }
+
+    // Create Descriptor Pool
+    // The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that)
+    // If you wish to load e.g. additional textures you may need to alter pools sizes.
+    {
+        VkDescriptorPoolSize pool_sizes[] =
+        {
+            { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 },
+        };
+        VkDescriptorPoolCreateInfo pool_info = {};
+        pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+        pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
+        pool_info.maxSets = 1;
+        pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
+        pool_info.pPoolSizes = pool_sizes;
+        err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
+        check_vk_result(err);
+    }
+}
+
+// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo.
+// Your real engine/app may not use them.
+static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
+{
+    wd->Surface = surface;
+
+    // Check for WSI support
+    VkBool32 res;
+    vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
+    if (res != VK_TRUE)
+    {
+        fprintf(stderr, "Error no WSI support on physical device 0\n");
+        exit(-1);
+    }
+
+    // Select Surface Format
+    const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
+    const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+    wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
+
+    // Select Present Mode
+#ifdef APP_UNLIMITED_FRAME_RATE
+    VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
+#else
+    VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
+#endif
+    wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
+    //printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
+
+    // Create SwapChain, RenderPass, Framebuffer, etc.
+    IM_ASSERT(g_MinImageCount >= 2);
+    ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
+}
+
+static void CleanupVulkan()
+{
+    vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
+
+#ifdef APP_USE_VULKAN_DEBUG_REPORT
+    // Remove the debug report callback
+    auto f_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
+    f_vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
+#endif // APP_USE_VULKAN_DEBUG_REPORT
+
+    vkDestroyDevice(g_Device, g_Allocator);
+    vkDestroyInstance(g_Instance, g_Allocator);
+}
+
+static void CleanupVulkanWindow()
+{
+    ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
+}
+
+static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
+{
+    VkResult err;
+
+    VkSemaphore image_acquired_semaphore  = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
+    VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
+    err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
+    if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
+    {
+        g_SwapChainRebuild = true;
+        return;
+    }
+    check_vk_result(err);
+
+    ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
+    {
+        err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX);    // wait indefinitely instead of periodically checking
+        check_vk_result(err);
+
+        err = vkResetFences(g_Device, 1, &fd->Fence);
+        check_vk_result(err);
+    }
+    {
+        err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
+        check_vk_result(err);
+        VkCommandBufferBeginInfo info = {};
+        info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+        info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+        err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
+        check_vk_result(err);
+    }
+    {
+        VkRenderPassBeginInfo info = {};
+        info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+        info.renderPass = wd->RenderPass;
+        info.framebuffer = fd->Framebuffer;
+        info.renderArea.extent.width = wd->Width;
+        info.renderArea.extent.height = wd->Height;
+        info.clearValueCount = 1;
+        info.pClearValues = &wd->ClearValue;
+        vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
+    }
+
+    // Record dear imgui primitives into command buffer
+    ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);
+
+    // Submit command buffer
+    vkCmdEndRenderPass(fd->CommandBuffer);
+    {
+        VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+        VkSubmitInfo info = {};
+        info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+        info.waitSemaphoreCount = 1;
+        info.pWaitSemaphores = &image_acquired_semaphore;
+        info.pWaitDstStageMask = &wait_stage;
+        info.commandBufferCount = 1;
+        info.pCommandBuffers = &fd->CommandBuffer;
+        info.signalSemaphoreCount = 1;
+        info.pSignalSemaphores = &render_complete_semaphore;
+
+        err = vkEndCommandBuffer(fd->CommandBuffer);
+        check_vk_result(err);
+        err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
+        check_vk_result(err);
+    }
+}
+
+static void FramePresent(ImGui_ImplVulkanH_Window* wd)
+{
+    if (g_SwapChainRebuild)
+        return;
+    VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
+    VkPresentInfoKHR info = {};
+    info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+    info.waitSemaphoreCount = 1;
+    info.pWaitSemaphores = &render_complete_semaphore;
+    info.swapchainCount = 1;
+    info.pSwapchains = &wd->Swapchain;
+    info.pImageIndices = &wd->FrameIndex;
+    VkResult err = vkQueuePresentKHR(g_Queue, &info);
+    if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
+    {
+        g_SwapChainRebuild = true;
+        return;
+    }
+    check_vk_result(err);
+    wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
+}
+
+// Main code
+int main(int, char**)
+{
+    // Setup SDL
+    if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD) != 0)
+    {
+        printf("Error: SDL_Init(): %s\n", SDL_GetError());
+        return -1;
+    }
+
+    // Create window with Vulkan graphics context
+    SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_HIDDEN);
+    SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+Vulkan example", 1280, 720, window_flags);
+    if (window == nullptr)
+    {
+        printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
+        return -1;
+    }
+
+    ImVector extensions;
+    {
+        uint32_t sdl_extensions_count = 0;
+        const char* const* sdl_extensions = SDL_Vulkan_GetInstanceExtensions(&sdl_extensions_count);
+        for (uint32_t n = 0; n < sdl_extensions_count; n++)
+            extensions.push_back(sdl_extensions[n]);
+    }
+    SetupVulkan(extensions);
+
+    // Create Window Surface
+    VkSurfaceKHR surface;
+    VkResult err;
+    if (SDL_Vulkan_CreateSurface(window, g_Instance, g_Allocator, &surface) == 0)
+    {
+        printf("Failed to create Vulkan surface.\n");
+        return 1;
+    }
+
+    // Create Framebuffers
+    int w, h;
+    SDL_GetWindowSize(window, &w, &h);
+    ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
+    SetupVulkanWindow(wd, surface, w, h);
+    SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+    SDL_ShowWindow(window);
+
+    // Setup Dear ImGui context
+    IMGUI_CHECKVERSION();
+    ImGui::CreateContext();
+    ImGuiIO& io = ImGui::GetIO(); (void)io;
+    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
+    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
+
+    // Setup Dear ImGui style
+    ImGui::StyleColorsDark();
+    //ImGui::StyleColorsLight();
+
+    // Setup Platform/Renderer backends
+    ImGui_ImplSDL3_InitForVulkan(window);
+    ImGui_ImplVulkan_InitInfo init_info = {};
+    init_info.Instance = g_Instance;
+    init_info.PhysicalDevice = g_PhysicalDevice;
+    init_info.Device = g_Device;
+    init_info.QueueFamily = g_QueueFamily;
+    init_info.Queue = g_Queue;
+    init_info.PipelineCache = g_PipelineCache;
+    init_info.DescriptorPool = g_DescriptorPool;
+    init_info.RenderPass = wd->RenderPass;
+    init_info.Subpass = 0;
+    init_info.MinImageCount = g_MinImageCount;
+    init_info.ImageCount = wd->ImageCount;
+    init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
+    init_info.Allocator = g_Allocator;
+    init_info.CheckVkResultFn = check_vk_result;
+    ImGui_ImplVulkan_Init(&init_info);
+
+    // Load Fonts
+    // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+    // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+    // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+    // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+    // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
+    // - Read 'docs/FONTS.md' for more instructions and details.
+    // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+    //io.Fonts->AddFontDefault();
+    //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
+    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+    //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+    //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
+    //IM_ASSERT(font != nullptr);
+
+    // Our state
+    bool show_demo_window = true;
+    bool show_another_window = false;
+    ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+    // Main loop
+    bool done = false;
+    while (!done)
+    {
+        // Poll and handle events (inputs, window resize, etc.)
+        // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+        // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
+        // - 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.
+        SDL_Event event;
+        while (SDL_PollEvent(&event))
+        {
+            ImGui_ImplSDL3_ProcessEvent(&event);
+            if (event.type == SDL_EVENT_QUIT)
+                done = true;
+            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;
+        }
+
+        // Resize swap chain?
+        int fb_width, fb_height;
+        SDL_GetWindowSize(window, &fb_width, &fb_height);
+        if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
+        {
+            ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
+            ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount);
+            g_MainWindowData.FrameIndex = 0;
+            g_SwapChainRebuild = false;
+        }
+
+        // Start the Dear ImGui frame
+        ImGui_ImplVulkan_NewFrame();
+        ImGui_ImplSDL3_NewFrame();
+        ImGui::NewFrame();
+
+        // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+        if (show_demo_window)
+            ImGui::ShowDemoWindow(&show_demo_window);
+
+        // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
+        {
+            static float f = 0.0f;
+            static int counter = 0;
+
+            ImGui::Begin("Hello, world!");                          // Create a window called "Hello, world!" and append into it.
+
+            ImGui::Text("This is some useful text.");               // Display some text (you can use a format strings too)
+            ImGui::Checkbox("Demo Window", &show_demo_window);      // Edit bools storing our window open/close state
+            ImGui::Checkbox("Another Window", &show_another_window);
+
+            ImGui::SliderFloat("float", &f, 0.0f, 1.0f);            // Edit 1 float using a slider from 0.0f to 1.0f
+            ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+            if (ImGui::Button("Button"))                            // Buttons return true when clicked (most widgets return true when edited/activated)
+                counter++;
+            ImGui::SameLine();
+            ImGui::Text("counter = %d", counter);
+
+            ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
+            ImGui::End();
+        }
+
+        // 3. Show another simple window.
+        if (show_another_window)
+        {
+            ImGui::Begin("Another Window", &show_another_window);   // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+            ImGui::Text("Hello from another window!");
+            if (ImGui::Button("Close Me"))
+                show_another_window = false;
+            ImGui::End();
+        }
+
+        // Rendering
+        ImGui::Render();
+        ImDrawData* draw_data = ImGui::GetDrawData();
+        const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f);
+        if (!is_minimized)
+        {
+            wd->ClearValue.color.float32[0] = clear_color.x * clear_color.w;
+            wd->ClearValue.color.float32[1] = clear_color.y * clear_color.w;
+            wd->ClearValue.color.float32[2] = clear_color.z * clear_color.w;
+            wd->ClearValue.color.float32[3] = clear_color.w;
+            FrameRender(wd, draw_data);
+            FramePresent(wd);
+        }
+    }
+
+    // Cleanup
+    err = vkDeviceWaitIdle(g_Device);
+    check_vk_result(err);
+    ImGui_ImplVulkan_Shutdown();
+    ImGui_ImplSDL3_Shutdown();
+    ImGui::DestroyContext();
+
+    CleanupVulkanWindow();
+    CleanupVulkan();
+
+    SDL_DestroyWindow(window);
+    SDL_Quit();
+
+    return 0;
+}
diff --git a/examples/imgui_examples.sln b/examples/imgui_examples.sln
index 9aee4a99e093..ea9f65cbd3e9 100644
--- a/examples/imgui_examples.sln
+++ b/examples/imgui_examples.sln
@@ -33,6 +33,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_opengl3", "exa
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_sdlrenderer3", "example_sdl3_sdlrenderer3\example_sdl3_sdlrenderer3.vcxproj", "{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_vulkan", "example_sdl3_vulkan\example_sdl3_vulkan.vcxproj", "{663A7E89-1E42-4222-921C-177F5B5910DF}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -161,6 +163,14 @@ Global
 		{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}.Release|Win32.Build.0 = Release|Win32
 		{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}.Release|x64.ActiveCfg = Release|x64
 		{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}.Release|x64.Build.0 = Release|x64
+		{663A7E89-1E42-4222-921C-177F5B5910DF}.Debug|Win32.ActiveCfg = Debug|Win32
+		{663A7E89-1E42-4222-921C-177F5B5910DF}.Debug|Win32.Build.0 = Debug|Win32
+		{663A7E89-1E42-4222-921C-177F5B5910DF}.Debug|x64.ActiveCfg = Debug|x64
+		{663A7E89-1E42-4222-921C-177F5B5910DF}.Debug|x64.Build.0 = Debug|x64
+		{663A7E89-1E42-4222-921C-177F5B5910DF}.Release|Win32.ActiveCfg = Release|Win32
+		{663A7E89-1E42-4222-921C-177F5B5910DF}.Release|Win32.Build.0 = Release|Win32
+		{663A7E89-1E42-4222-921C-177F5B5910DF}.Release|x64.ActiveCfg = Release|x64
+		{663A7E89-1E42-4222-921C-177F5B5910DF}.Release|x64.Build.0 = Release|x64
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

From 81cfe09657891236fe45839842f67119e6d2eef1 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 28 Oct 2024 15:44:44 +0100
Subject: [PATCH 230/548] Selectable, Style: selected Selectable() use _Header
 color instead of an arbitrary lerp between _Header and _HeaderHovered.
 (#8106, #1861)

---
 docs/CHANGELOG.txt | 2 ++
 imgui_demo.cpp     | 2 +-
 imgui_widgets.cpp  | 8 ++------
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 194803ac6de1..4e987c00379e 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,8 @@ Breaking changes:
 
 Other changes:
 
+- Selectable: selected Selectables use ImGuiCol_Header instead of an arbitrary lerp
+  between _Header and _HeaderHovered which was introduced v1.91 (#8106, #1861)
 - Backends: DX12: Unmap() call specify written range. The range is informational and
   may be used by debug tools.
 - Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the 
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index f24254e2ea40..c6c06a58cd16 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -10220,7 +10220,7 @@ struct ExampleAssetsBrowser
 
             // Rendering parameters
             const ImU32 icon_type_overlay_colors[3] = { 0, IM_COL32(200, 70, 70, 255), IM_COL32(70, 170, 70, 255) };
-            const ImU32 icon_bg_color = ImGui::GetColorU32(ImGuiCol_MenuBarBg);
+            const ImU32 icon_bg_color = ImGui::GetColorU32(IM_COL32(35, 35, 35, 220));
             const ImVec2 icon_type_overlay_size = ImVec2(4.0f, 4.0f);
             const bool display_label = (LayoutItemSize.x >= ImGui::CalcTextSize("999").x);
 
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 757eb8ab68d7..ee15e990ac66 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -7017,12 +7017,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
         const bool highlighted = hovered || (flags & ImGuiSelectableFlags_Highlight);
         if (highlighted || selected)
         {
-            // FIXME-MULTISELECT: Styling: Color for 'selected' elements? ImGuiCol_HeaderSelected
-            ImU32 col;
-            if (selected && !highlighted)
-                col = GetColorU32(ImLerp(GetStyleColorVec4(ImGuiCol_Header), GetStyleColorVec4(ImGuiCol_HeaderHovered), 0.5f));
-            else
-                col = GetColorU32((held && highlighted) ? ImGuiCol_HeaderActive : highlighted ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
+            // Between 1.91.0 and 1.91.4 we made selected Selectable use an arbitrary lerp between _Header and _HeaderHovered. Removed that now. (#8106)
+            ImU32 col = GetColorU32((held && highlighted) ? ImGuiCol_HeaderActive : highlighted ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
             RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
         }
         if (g.NavId == id)

From 81b689b9693df736386026916b598eeedf43a9bb Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 28 Oct 2024 15:52:37 +0100
Subject: [PATCH 231/548] Backends: OpenGL3: added additional debug GL_CALL
 enclosure for glCreateShader() calls. (#8104)

---
 backends/imgui_impl_opengl3.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp
index f5235096faff..c03156a7e174 100644
--- a/backends/imgui_impl_opengl3.cpp
+++ b/backends/imgui_impl_opengl3.cpp
@@ -895,13 +895,15 @@ bool    ImGui_ImplOpenGL3_CreateDeviceObjects()
 
     // Create shaders
     const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader };
-    GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER);
+    GLuint vert_handle;
+    GL_CALL(vert_handle = glCreateShader(GL_VERTEX_SHADER));
     glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr);
     glCompileShader(vert_handle);
     CheckShader(vert_handle, "vertex shader");
 
     const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader };
-    GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
+    GLuint frag_handle;
+    GL_CALL(frag_handle = glCreateShader(GL_FRAGMENT_SHADER));
     glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr);
     glCompileShader(frag_handle);
     CheckShader(frag_handle, "fragment shader");

From d67e2eea1a0775066bb966ac8bbb9ecd6b5c48ba Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 28 Oct 2024 16:43:41 +0100
Subject: [PATCH 232/548] Backends: Win32: internal rename.

---
 backends/imgui_impl_win32.cpp | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp
index 477d54abe97e..97735ae33fe9 100644
--- a/backends/imgui_impl_win32.cpp
+++ b/backends/imgui_impl_win32.cpp
@@ -559,22 +559,10 @@ ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam)
 #define DBT_DEVNODES_CHANGED 0x0007
 #endif
 
-// Win32 message handler (process Win32 mouse/keyboard inputs, etc.)
-// Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
-// When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs.
-// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
-// - 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.
-// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds.
-// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
-#if 0
-// Copy this line into your .cpp file to forward declare the function.
-extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-#endif
-
+// Helper to obtain the source of mouse messages.
 // See https://learn.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages
 // Prefer to call this at the top of the message handler to avoid the possibility of other Win32 calls interfering with this.
-static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
+static ImGuiMouseSource ImGui_ImplWin32_GetMouseSourceFromMessageExtraInfo()
 {
     LPARAM extra_info = ::GetMessageExtraInfo();
     if ((extra_info & 0xFFFFFF80) == 0xFF515700)
@@ -584,6 +572,18 @@ static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo()
     return ImGuiMouseSource_Mouse;
 }
 
+// Win32 message handler (process Win32 mouse/keyboard inputs, etc.)
+// Call from your application's message handler. Keep calling your message handler unless this function returns TRUE.
+// When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs.
+// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
+// - 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.
+// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds.
+// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
+
+// Copy this line into your .cpp file to forward declare the function:
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
 IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
     // Most backends don't have silent checks like this one, but we need it because WndProc are called early in CreateWindow().
@@ -599,7 +599,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
     case WM_NCMOUSEMOVE:
     {
         // We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events
-        ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
+        ImGuiMouseSource mouse_source = ImGui_ImplWin32_GetMouseSourceFromMessageExtraInfo();
         const int area = (msg == WM_MOUSEMOVE) ? 1 : 2;
         bd->MouseHwnd = hwnd;
         if (bd->MouseTrackedArea != area)
@@ -646,7 +646,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
     case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
     case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
     {
-        ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
+        ImGuiMouseSource mouse_source = ImGui_ImplWin32_GetMouseSourceFromMessageExtraInfo();
         int button = 0;
         if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
         if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; }
@@ -664,7 +664,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
     case WM_MBUTTONUP:
     case WM_XBUTTONUP:
     {
-        ImGuiMouseSource mouse_source = GetMouseSourceFromMessageExtraInfo();
+        ImGuiMouseSource mouse_source = ImGui_ImplWin32_GetMouseSourceFromMessageExtraInfo();
         int button = 0;
         if (msg == WM_LBUTTONUP) { button = 0; }
         if (msg == WM_RBUTTONUP) { button = 1; }

From 3b8c7d0326d307598edce07e53f03614f972b757 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 28 Oct 2024 16:58:07 +0100
Subject: [PATCH 233/548] Backends: Win32: rework to add
 ImGui_ImplWin32_WndProcHandlerEx() not using current context (experimental).
 (#8069, #6293, #5856, #586)

+ GetIOEx(). Amend fedf45c + cba656a. Amend 416cfdb9.
---
 backends/imgui_impl_win32.cpp | 94 +++++++++++++++++++----------------
 imgui.cpp                     |  7 +++
 imgui.h                       |  2 +-
 imgui_internal.h              |  1 +
 4 files changed, 59 insertions(+), 45 deletions(-)

diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp
index 97735ae33fe9..c213f8158011 100644
--- a/backends/imgui_impl_win32.cpp
+++ b/backends/imgui_impl_win32.cpp
@@ -133,12 +133,16 @@ static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData()
 {
     return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
 }
+static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData(ImGuiIO& io)
+{
+    return (ImGui_ImplWin32_Data*)io.BackendPlatformUserData;
+}
 
 // Functions
-static void ImGui_ImplWin32_UpdateKeyboardCodePage()
+static void ImGui_ImplWin32_UpdateKeyboardCodePage(ImGuiIO& io)
 {
     // Retrieve keyboard code page, required for handling of non-Unicode Windows.
-    ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
+    ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
     HKL keyboard_layout = ::GetKeyboardLayout(0);
     LCID keyboard_lcid = MAKELCID(HIWORD(keyboard_layout), SORT_DEFAULT);
     if (::GetLocaleInfoA(keyboard_lcid, (LOCALE_RETURN_NUMBER | LOCALE_IDEFAULTANSICODEPAGE), (LPSTR)&bd->KeyboardCodePage, sizeof(bd->KeyboardCodePage)) == 0)
@@ -168,7 +172,7 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
     bd->TicksPerSecond = perf_frequency;
     bd->Time = perf_counter;
     bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
-    ImGui_ImplWin32_UpdateKeyboardCodePage();
+    ImGui_ImplWin32_UpdateKeyboardCodePage(io);
 
     // Set platform dependent data in viewport
     ImGuiViewport* main_viewport = ImGui::GetMainViewport();
@@ -228,13 +232,11 @@ void    ImGui_ImplWin32_Shutdown()
     IM_DELETE(bd);
 }
 
-static bool ImGui_ImplWin32_UpdateMouseCursor()
+static bool ImGui_ImplWin32_UpdateMouseCursor(ImGuiIO& io, ImGuiMouseCursor imgui_cursor)
 {
-    ImGuiIO& io = ImGui::GetIO();
     if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
         return false;
 
-    ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
     if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
     {
         // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
@@ -266,42 +268,39 @@ static bool IsVkDown(int vk)
     return (::GetKeyState(vk) & 0x8000) != 0;
 }
 
-static void ImGui_ImplWin32_AddKeyEvent(ImGuiKey key, bool down, int native_keycode, int native_scancode = -1)
+static void ImGui_ImplWin32_AddKeyEvent(ImGuiIO& io, ImGuiKey key, bool down, int native_keycode, int native_scancode = -1)
 {
-    ImGuiIO& io = ImGui::GetIO();
     io.AddKeyEvent(key, down);
     io.SetKeyEventNativeData(key, native_keycode, native_scancode); // To support legacy indexing (<1.87 user code)
     IM_UNUSED(native_scancode);
 }
 
-static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds()
+static void ImGui_ImplWin32_ProcessKeyEventsWorkarounds(ImGuiIO& io)
 {
     // Left & right Shift keys: when both are pressed together, Windows tend to not generate the WM_KEYUP event for the first released one.
     if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && !IsVkDown(VK_LSHIFT))
-        ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, false, VK_LSHIFT);
+        ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_LeftShift, false, VK_LSHIFT);
     if (ImGui::IsKeyDown(ImGuiKey_RightShift) && !IsVkDown(VK_RSHIFT))
-        ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, false, VK_RSHIFT);
+        ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_RightShift, false, VK_RSHIFT);
 
     // Sometimes WM_KEYUP for Win key is not passed down to the app (e.g. for Win+V on some setups, according to GLFW).
     if (ImGui::IsKeyDown(ImGuiKey_LeftSuper) && !IsVkDown(VK_LWIN))
-        ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftSuper, false, VK_LWIN);
+        ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_LeftSuper, false, VK_LWIN);
     if (ImGui::IsKeyDown(ImGuiKey_RightSuper) && !IsVkDown(VK_RWIN))
-        ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightSuper, false, VK_RWIN);
+        ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_RightSuper, false, VK_RWIN);
 }
 
-static void ImGui_ImplWin32_UpdateKeyModifiers()
+static void ImGui_ImplWin32_UpdateKeyModifiers(ImGuiIO& io)
 {
-    ImGuiIO& io = ImGui::GetIO();
     io.AddKeyEvent(ImGuiMod_Ctrl, IsVkDown(VK_CONTROL));
     io.AddKeyEvent(ImGuiMod_Shift, IsVkDown(VK_SHIFT));
     io.AddKeyEvent(ImGuiMod_Alt, IsVkDown(VK_MENU));
     io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_LWIN) || IsVkDown(VK_RWIN));
 }
 
-static void ImGui_ImplWin32_UpdateMouseData()
+static void ImGui_ImplWin32_UpdateMouseData(ImGuiIO& io)
 {
-    ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
-    ImGuiIO& io = ImGui::GetIO();
+    ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
     IM_ASSERT(bd->hWnd != 0);
 
     HWND focused_window = ::GetForegroundWindow();
@@ -328,11 +327,10 @@ static void ImGui_ImplWin32_UpdateMouseData()
 }
 
 // Gamepad navigation mapping
-static void ImGui_ImplWin32_UpdateGamepads()
+static void ImGui_ImplWin32_UpdateGamepads(ImGuiIO& io)
 {
 #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
-    ImGuiIO& io = ImGui::GetIO();
-    ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
+    ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
     //if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs.
     //    return;
 
@@ -381,7 +379,9 @@ static void ImGui_ImplWin32_UpdateGamepads()
     MAP_ANALOG(ImGuiKey_GamepadRStickDown,      gamepad.sThumbRY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
     #undef MAP_BUTTON
     #undef MAP_ANALOG
-#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
+#else // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
+    IM_UNUSED(io);
+#endif
 }
 
 void    ImGui_ImplWin32_NewFrame()
@@ -402,21 +402,21 @@ void    ImGui_ImplWin32_NewFrame()
     bd->Time = current_time;
 
     // Update OS mouse position
-    ImGui_ImplWin32_UpdateMouseData();
+    ImGui_ImplWin32_UpdateMouseData(io);
 
     // Process workarounds for known Windows key handling issues
-    ImGui_ImplWin32_ProcessKeyEventsWorkarounds();
+    ImGui_ImplWin32_ProcessKeyEventsWorkarounds(io);
 
     // Update OS mouse cursor with the cursor requested by imgui
     ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
     if (bd->LastMouseCursor != mouse_cursor)
     {
         bd->LastMouseCursor = mouse_cursor;
-        ImGui_ImplWin32_UpdateMouseCursor();
+        ImGui_ImplWin32_UpdateMouseCursor(io, mouse_cursor);
     }
 
     // Update game controllers (if enabled and available)
-    ImGui_ImplWin32_UpdateGamepads();
+    ImGui_ImplWin32_UpdateGamepads(io);
 }
 
 // Map VK_xxx to ImGuiKey_xxx.
@@ -578,21 +578,27 @@ static ImGuiMouseSource ImGui_ImplWin32_GetMouseSourceFromMessageExtraInfo()
 // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
 // - 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.
-// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds.
 // PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
 
-// Copy this line into your .cpp file to forward declare the function:
-extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+// Copy either line into your .cpp file to forward declare the function:
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);                // Use ImGui::GetCurrentContext()
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, ImGuiIO& io); // Doesn't use ImGui::GetCurrentContext()
 
 IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
     // Most backends don't have silent checks like this one, but we need it because WndProc are called early in CreateWindow().
     // We silently allow both context or just only backend data to be nullptr.
-    ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
-    if (bd == nullptr)
+    if (ImGui::GetCurrentContext() == NULL)
         return 0;
-    ImGuiIO& io = ImGui::GetIO();
+    return ImGui_ImplWin32_WndProcHandlerEx(hwnd, msg, wParam, lParam, ImGui::GetIO());
+}
 
+// This version is in theory thread-safe in the sense that no path should access ImGui::GetCurrentContext().
+IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, ImGuiIO& io)
+{
+    ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
+    if (bd == NULL)
+        return 0;
     switch (msg)
     {
     case WM_MOUSEMOVE:
@@ -653,7 +659,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
         if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; }
         if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
         if (bd->MouseButtonsDown == 0 && ::GetCapture() == nullptr)
-            ::SetCapture(hwnd);
+            ::SetCapture(hwnd); // Allow us to read mouse coordinates when dragging mouse outside of our window bounds.
         bd->MouseButtonsDown |= 1 << button;
         io.AddMouseSourceEvent(mouse_source);
         io.AddMouseButtonEvent(button, true);
@@ -692,7 +698,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
         if (wParam < 256)
         {
             // Submit modifiers
-            ImGui_ImplWin32_UpdateKeyModifiers();
+            ImGui_ImplWin32_UpdateKeyModifiers(io);
 
             // Obtain virtual key code and convert to ImGuiKey
             const ImGuiKey key = ImGui_ImplWin32_KeyEventToImGuiKey(wParam, lParam);
@@ -701,28 +707,28 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
 
             // Special behavior for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit the key down event.
             if (key == ImGuiKey_PrintScreen && !is_key_down)
-                ImGui_ImplWin32_AddKeyEvent(key, true, vk, scancode);
+                ImGui_ImplWin32_AddKeyEvent(io, key, true, vk, scancode);
 
             // Submit key event
             if (key != ImGuiKey_None)
-                ImGui_ImplWin32_AddKeyEvent(key, is_key_down, vk, scancode);
+                ImGui_ImplWin32_AddKeyEvent(io, key, is_key_down, vk, scancode);
 
             // Submit individual left/right modifier events
             if (vk == VK_SHIFT)
             {
                 // Important: Shift keys tend to get stuck when pressed together, missing key-up events are corrected in ImGui_ImplWin32_ProcessKeyEventsWorkarounds()
-                if (IsVkDown(VK_LSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftShift, is_key_down, VK_LSHIFT, scancode); }
-                if (IsVkDown(VK_RSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightShift, is_key_down, VK_RSHIFT, scancode); }
+                if (IsVkDown(VK_LSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_LeftShift, is_key_down, VK_LSHIFT, scancode); }
+                if (IsVkDown(VK_RSHIFT) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_RightShift, is_key_down, VK_RSHIFT, scancode); }
             }
             else if (vk == VK_CONTROL)
             {
-                if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); }
-                if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); }
+                if (IsVkDown(VK_LCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_LeftCtrl, is_key_down, VK_LCONTROL, scancode); }
+                if (IsVkDown(VK_RCONTROL) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_RightCtrl, is_key_down, VK_RCONTROL, scancode); }
             }
             else if (vk == VK_MENU)
             {
-                if (IsVkDown(VK_LMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_LeftAlt, is_key_down, VK_LMENU, scancode); }
-                if (IsVkDown(VK_RMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(ImGuiKey_RightAlt, is_key_down, VK_RMENU, scancode); }
+                if (IsVkDown(VK_LMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_LeftAlt, is_key_down, VK_LMENU, scancode); }
+                if (IsVkDown(VK_RMENU) == is_key_down) { ImGui_ImplWin32_AddKeyEvent(io, ImGuiKey_RightAlt, is_key_down, VK_RMENU, scancode); }
             }
         }
         return 0;
@@ -732,7 +738,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
         io.AddFocusEvent(msg == WM_SETFOCUS);
         return 0;
     case WM_INPUTLANGCHANGE:
-        ImGui_ImplWin32_UpdateKeyboardCodePage();
+        ImGui_ImplWin32_UpdateKeyboardCodePage(io);
         return 0;
     case WM_CHAR:
         if (::IsWindowUnicode(hwnd))
@@ -750,7 +756,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
         return 0;
     case WM_SETCURSOR:
         // This is required to restore cursor when transitioning from e.g resize borders to client area.
-        if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
+        if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor(io, bd->LastMouseCursor))
             return 1;
         return 0;
     case WM_DEVICECHANGE:
diff --git a/imgui.cpp b/imgui.cpp
index 81f872f7ba61..25089e0fd962 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4748,6 +4748,13 @@ ImGuiIO& ImGui::GetIO()
     return GImGui->IO;
 }
 
+// This variant exists to facilitate backends experimenting with multi-threaded parallel context. (#8069, #6293, #5856)
+ImGuiIO& ImGui::GetIOEx(ImGuiContext* ctx)
+{
+    IM_ASSERT(ctx != NULL);
+    return ctx->IO;
+}
+
 ImGuiPlatformIO& ImGui::GetPlatformIO()
 {
     IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext()?");
diff --git a/imgui.h b/imgui.h
index 04f958eec69b..eb3991d972d1 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2248,7 +2248,7 @@ struct ImGuiIO
 
     // Keyboard/Gamepad Navigation options
     bool        ConfigNavSwapGamepadButtons;    // = false          // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout.
-    bool        ConfigNavMoveSetMousePos;       // = false          // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true. 
+    bool        ConfigNavMoveSetMousePos;       // = false          // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true.
     bool        ConfigNavCaptureKeyboard;       // = true           // Sets io.WantCaptureKeyboard when io.NavActive is set.
     bool        ConfigNavEscapeClearFocusItem;  // = true           // Pressing Escape can clear focused item + navigation id/highlight. Set to false if you want to always keep highlight on.
     bool        ConfigNavEscapeClearFocusWindow;// = false          // Pressing Escape can clear focused window as well (super set of io.ConfigNavEscapeClearFocusItem).
diff --git a/imgui_internal.h b/imgui_internal.h
index 0c441a260b9c..fab1573031d2 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2936,6 +2936,7 @@ namespace ImGui
     // If this ever crashes because g.CurrentWindow is NULL, it means that either:
     // - ImGui::NewFrame() has never been called, which is illegal.
     // - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
+    IMGUI_API ImGuiIO&      GetIOEx(ImGuiContext* ctx);
     inline    ImGuiWindow*  GetCurrentWindowRead()      { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
     inline    ImGuiWindow*  GetCurrentWindow()          { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; }
     IMGUI_API ImGuiWindow*  FindWindowByID(ImGuiID id);

From 0bde57c25a90ee1b99e511385611db6185d318f8 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 29 Oct 2024 11:47:03 +0100
Subject: [PATCH 234/548] Font, Misc: remove qualifier from most font
 functions.

Fixed ClearOutputData() not clearing Used4kPagesMap (mostly harmless).
---
 backends/imgui_impl_dx10.h   |  2 +-
 backends/imgui_impl_dx11.cpp |  2 +-
 backends/imgui_impl_dx11.h   |  2 +-
 backends/imgui_impl_dx12.h   |  2 +-
 backends/imgui_impl_wgpu.h   |  2 +-
 docs/CHANGELOG.txt           |  1 +
 imgui.cpp                    |  2 +-
 imgui.h                      | 16 ++++++++--------
 imgui_draw.cpp               | 15 ++++++++-------
 9 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/backends/imgui_impl_dx10.h b/backends/imgui_impl_dx10.h
index 95759737b590..667f296f17bd 100644
--- a/backends/imgui_impl_dx10.h
+++ b/backends/imgui_impl_dx10.h
@@ -26,7 +26,7 @@ IMGUI_IMPL_API void     ImGui_ImplDX10_NewFrame();
 IMGUI_IMPL_API void     ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
 
 // Use if you want to reset your rendering device without losing Dear ImGui state.
-IMGUI_IMPL_API void     ImGui_ImplDX10_InvalidateDeviceObjects();
 IMGUI_IMPL_API bool     ImGui_ImplDX10_CreateDeviceObjects();
+IMGUI_IMPL_API void     ImGui_ImplDX10_InvalidateDeviceObjects();
 
 #endif // #ifndef IMGUI_DISABLE
diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp
index 16d480e0867b..b928bb86fbc0 100644
--- a/backends/imgui_impl_dx11.cpp
+++ b/backends/imgui_impl_dx11.cpp
@@ -23,7 +23,7 @@
 //  2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
 //  2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
 //  2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
-//  2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
+//  2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX11_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
 //  2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
 //  2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
 //  2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
diff --git a/backends/imgui_impl_dx11.h b/backends/imgui_impl_dx11.h
index 57b19bc037ee..c3b8379b14b7 100644
--- a/backends/imgui_impl_dx11.h
+++ b/backends/imgui_impl_dx11.h
@@ -29,8 +29,8 @@ IMGUI_IMPL_API void     ImGui_ImplDX11_NewFrame();
 IMGUI_IMPL_API void     ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
 
 // Use if you want to reset your rendering device without losing Dear ImGui state.
-IMGUI_IMPL_API void     ImGui_ImplDX11_InvalidateDeviceObjects();
 IMGUI_IMPL_API bool     ImGui_ImplDX11_CreateDeviceObjects();
+IMGUI_IMPL_API void     ImGui_ImplDX11_InvalidateDeviceObjects();
 
 // [BETA] Selected render state data shared with callbacks.
 // This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplDX11_RenderDrawData() call.
diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h
index 5da528573429..1e36d730f77b 100644
--- a/backends/imgui_impl_dx12.h
+++ b/backends/imgui_impl_dx12.h
@@ -37,8 +37,8 @@ IMGUI_IMPL_API void     ImGui_ImplDX12_NewFrame();
 IMGUI_IMPL_API void     ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list);
 
 // Use if you want to reset your rendering device without losing Dear ImGui state.
-IMGUI_IMPL_API void     ImGui_ImplDX12_InvalidateDeviceObjects();
 IMGUI_IMPL_API bool     ImGui_ImplDX12_CreateDeviceObjects();
+IMGUI_IMPL_API void     ImGui_ImplDX12_InvalidateDeviceObjects();
 
 // [BETA] Selected render state data shared with callbacks.
 // This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplDX12_RenderDrawData() call.
diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h
index e4398575c11d..f9fb037764f6 100644
--- a/backends/imgui_impl_wgpu.h
+++ b/backends/imgui_impl_wgpu.h
@@ -52,8 +52,8 @@ IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame();
 IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder);
 
 // Use if you want to reset your rendering device without losing Dear ImGui state.
-IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
 IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateDeviceObjects();
+IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
 
 // [BETA] Selected render state data shared with callbacks.
 // This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplWGPU_RenderDrawData() call.
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 4e987c00379e..7443976155d5 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -45,6 +45,7 @@ Other changes:
 
 - Selectable: selected Selectables use ImGuiCol_Header instead of an arbitrary lerp
   between _Header and _HeaderHovered which was introduced v1.91 (#8106, #1861)
+- Fonts: removed const qualifiers from most font functions.
 - Backends: DX12: Unmap() call specify written range. The range is informational and
   may be used by debug tools.
 - Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the 
diff --git a/imgui.cpp b/imgui.cpp
index 25089e0fd962..94358e41714b 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3637,7 +3637,7 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
         // min   max   ellipsis_max
         //          <-> this is generally some padding value
 
-        const ImFont* font = draw_list->_Data->Font;
+        ImFont* font = draw_list->_Data->Font;
         const float font_size = draw_list->_Data->FontSize;
         const float font_scale = draw_list->_Data->FontScale;
         const char* text_end_ellipsis = NULL;
diff --git a/imgui.h b/imgui.h
index eb3991d972d1..7aec7b0e254e 100644
--- a/imgui.h
+++ b/imgui.h
@@ -3122,7 +3122,7 @@ struct ImDrawList
     IMGUI_API void  AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f);
     IMGUI_API void  AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot = 0.0f, int num_segments = 0);
     IMGUI_API void  AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
-    IMGUI_API void  AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
+    IMGUI_API void  AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
     IMGUI_API void  AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points)
     IMGUI_API void  AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0);               // Quadratic Bezier (3 control points)
 
@@ -3471,18 +3471,18 @@ struct ImFont
     // Methods
     IMGUI_API ImFont();
     IMGUI_API ~ImFont();
-    IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c) const;
-    IMGUI_API const ImFontGlyph*FindGlyphNoFallback(ImWchar c) const;
-    float                       GetCharAdvance(ImWchar c) const     { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; }
+    IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c);
+    IMGUI_API const ImFontGlyph*FindGlyphNoFallback(ImWchar c);
+    float                       GetCharAdvance(ImWchar c)           { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; }
     bool                        IsLoaded() const                    { return ContainerAtlas != NULL; }
     const char*                 GetDebugName() const                { return ConfigData ? ConfigData->Name : ""; }
 
     // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable.
     // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable.
-    IMGUI_API ImVec2            CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8
-    IMGUI_API const char*       CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const;
-    IMGUI_API void              RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c) const;
-    IMGUI_API void              RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const;
+    IMGUI_API ImVec2            CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL); // utf8
+    IMGUI_API const char*       CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width);
+    IMGUI_API void              RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c);
+    IMGUI_API void              RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false);
 
     // [Internal] Don't use!
     IMGUI_API void              BuildLookupTable();
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 01723b35c97d..d54c96babcbb 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1646,7 +1646,7 @@ void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const Im
     PathStroke(col, 0, thickness);
 }
 
-void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
+void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
 {
     if ((col & IM_COL32_A_MASK) == 0)
         return;
@@ -3638,6 +3638,7 @@ void    ImFont::ClearOutputData()
     DirtyLookupTables = true;
     Ascent = Descent = 0.0f;
     MetricsTotalSurface = 0;
+    memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap));
 }
 
 static ImWchar FindFirstExistingGlyph(ImFont* font, const ImWchar* candidate_chars, int candidate_chars_count)
@@ -3822,7 +3823,7 @@ void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst)
     IndexAdvanceX[dst] = (src < index_size) ? IndexAdvanceX.Data[src] : 1.0f;
 }
 
-const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const
+const ImFontGlyph* ImFont::FindGlyph(ImWchar c)
 {
     if (c >= (size_t)IndexLookup.Size)
         return FallbackGlyph;
@@ -3832,7 +3833,7 @@ const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const
     return &Glyphs.Data[i];
 }
 
-const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const
+const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c)
 {
     if (c >= (size_t)IndexLookup.Size)
         return NULL;
@@ -3855,7 +3856,7 @@ static inline const char* CalcWordWrapNextLineStartA(const char* text, const cha
 // Simple word-wrapping for English, not full-featured. Please submit failing cases!
 // This will return the next location to wrap from. If no wrapping if necessary, this will fast-forward to e.g. text_end.
 // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.)
-const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const
+const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width)
 {
     // For references, possible wrap point marked with ^
     //  "aaa bbb, ccc,ddd. eee   fff. ggg!"
@@ -3953,7 +3954,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
     return s;
 }
 
-ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const
+ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining)
 {
     if (!text_end)
         text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this.
@@ -4032,7 +4033,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
 }
 
 // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound.
-void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c) const
+void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c)
 {
     const ImFontGlyph* glyph = FindGlyph(c);
     if (!glyph || !glyph->Visible)
@@ -4047,7 +4048,7 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im
 }
 
 // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound.
-void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
+void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip)
 {
     if (!text_end)
         text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls.

From 9a0dff1bc56bff17269ec922f78b03ca838e3ea2 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 29 Oct 2024 14:26:02 +0100
Subject: [PATCH 235/548] Buttons: using ImGuiItemFlags_ButtonRepeat makes
 default button behavior use PressedOnClick instead of PressedOnClickRelease
 when unspecified.

---
 docs/CHANGELOG.txt |  2 ++
 imgui.h            |  2 +-
 imgui_widgets.cpp  | 14 +++++++-------
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 7443976155d5..82c6b226638a 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -45,6 +45,8 @@ Other changes:
 
 - Selectable: selected Selectables use ImGuiCol_Header instead of an arbitrary lerp
   between _Header and _HeaderHovered which was introduced v1.91 (#8106, #1861)
+- Buttons: using ImGuiItemFlags_ButtonRepeat makes default button behavior use
+  PressedOnClick instead of PressedOnClickRelease when unspecified.
 - Fonts: removed const qualifiers from most font functions.
 - Backends: DX12: Unmap() call specify written range. The range is informational and
   may be used by debug tools.
diff --git a/imgui.h b/imgui.h
index 7aec7b0e254e..6f6779abf054 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.5 WIP"
-#define IMGUI_VERSION_NUM   19141
+#define IMGUI_VERSION_NUM   19142
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index ee15e990ac66..1ee9a962437c 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -495,19 +495,19 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindow();
 
+    // Default behavior inherited from item flags
+    // Note that _both_ ButtonFlags and ItemFlags are valid sources, so copy one into the item_flags and only check that.
+    ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.ItemFlags : g.CurrentItemFlags);
+    if (flags & ImGuiButtonFlags_AllowOverlap)
+        item_flags |= ImGuiItemFlags_AllowOverlap;
+
     // Default only reacts to left mouse button
     if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0)
         flags |= ImGuiButtonFlags_MouseButtonLeft;
 
     // Default behavior requires click + release inside bounding box
     if ((flags & ImGuiButtonFlags_PressedOnMask_) == 0)
-        flags |= ImGuiButtonFlags_PressedOnDefault_;
-
-    // Default behavior inherited from item flags
-    // Note that _both_ ButtonFlags and ItemFlags are valid sources, so copy one into the item_flags and only check that.
-    ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.ItemFlags : g.CurrentItemFlags);
-    if (flags & ImGuiButtonFlags_AllowOverlap)
-        item_flags |= ImGuiItemFlags_AllowOverlap;
+        flags |= (item_flags & ImGuiItemFlags_ButtonRepeat) ? ImGuiButtonFlags_PressedOnClick : ImGuiButtonFlags_PressedOnDefault_;
 
     ImGuiWindow* backup_hovered_window = g.HoveredWindow;
     const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window;

From a4fcc93f4af38e567de0a09e40b67134158be5de Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 30 Oct 2024 15:07:26 +0100
Subject: [PATCH 236/548] Log/Capture: renaming ImGuiLogType to ImGuiLogFlags

---
 imgui.cpp        | 33 +++++++++++++++++----------------
 imgui_internal.h | 20 ++++++++++++--------
 2 files changed, 29 insertions(+), 24 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 94358e41714b..44a17508ff52 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4007,7 +4007,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     memset(LocalizationTable, 0, sizeof(LocalizationTable));
 
     LogEnabled = false;
-    LogType = ImGuiLogType_None;
+    LogFlags = ImGuiLogFlags_None;
     LogNextPrefix = LogNextSuffix = NULL;
     LogFile = NULL;
     LogLinePosY = FLT_MAX;
@@ -14324,15 +14324,16 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char*
 }
 
 // Start logging/capturing text output
-void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth)
+void ImGui::LogBegin(ImGuiLogFlags flags, int auto_open_depth)
 {
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
     IM_ASSERT(g.LogEnabled == false);
-    IM_ASSERT(g.LogFile == NULL);
-    IM_ASSERT(g.LogBuffer.empty());
+    IM_ASSERT(g.LogFile == NULL && g.LogBuffer.empty());
+    IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiLogFlags_OutputMask_)); // Check that only 1 type flag is used
+
     g.LogEnabled = g.ItemUnclipByLog = true;
-    g.LogType = type;
+    g.LogFlags = flags;
     g.LogNextPrefix = g.LogNextSuffix = NULL;
     g.LogDepthRef = window->DC.TreeDepth;
     g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth : g.LogDepthToExpandDefault);
@@ -14355,7 +14356,7 @@ void ImGui::LogToTTY(int auto_open_depth)
         return;
     IM_UNUSED(auto_open_depth);
 #ifndef IMGUI_DISABLE_TTY_FUNCTIONS
-    LogBegin(ImGuiLogType_TTY, auto_open_depth);
+    LogBegin(ImGuiLogFlags_OutputTTY, auto_open_depth);
     g.LogFile = stdout;
 #endif
 }
@@ -14381,7 +14382,7 @@ void ImGui::LogToFile(int auto_open_depth, const char* filename)
         return;
     }
 
-    LogBegin(ImGuiLogType_File, auto_open_depth);
+    LogBegin(ImGuiLogFlags_OutputFile, auto_open_depth);
     g.LogFile = f;
 }
 
@@ -14391,7 +14392,7 @@ void ImGui::LogToClipboard(int auto_open_depth)
     ImGuiContext& g = *GImGui;
     if (g.LogEnabled)
         return;
-    LogBegin(ImGuiLogType_Clipboard, auto_open_depth);
+    LogBegin(ImGuiLogFlags_OutputClipboard, auto_open_depth);
 }
 
 void ImGui::LogToBuffer(int auto_open_depth)
@@ -14399,7 +14400,7 @@ void ImGui::LogToBuffer(int auto_open_depth)
     ImGuiContext& g = *GImGui;
     if (g.LogEnabled)
         return;
-    LogBegin(ImGuiLogType_Buffer, auto_open_depth);
+    LogBegin(ImGuiLogFlags_OutputBuffer, auto_open_depth);
 }
 
 void ImGui::LogFinish()
@@ -14409,29 +14410,29 @@ void ImGui::LogFinish()
         return;
 
     LogText(IM_NEWLINE);
-    switch (g.LogType)
+    switch (g.LogFlags & ImGuiLogFlags_OutputMask_)
     {
-    case ImGuiLogType_TTY:
+    case ImGuiLogFlags_OutputTTY:
 #ifndef IMGUI_DISABLE_TTY_FUNCTIONS
         fflush(g.LogFile);
 #endif
         break;
-    case ImGuiLogType_File:
+    case ImGuiLogFlags_OutputFile:
         ImFileClose(g.LogFile);
         break;
-    case ImGuiLogType_Buffer:
+    case ImGuiLogFlags_OutputBuffer:
         break;
-    case ImGuiLogType_Clipboard:
+    case ImGuiLogFlags_OutputClipboard:
         if (!g.LogBuffer.empty())
             SetClipboardText(g.LogBuffer.begin());
         break;
-    case ImGuiLogType_None:
+    default:
         IM_ASSERT(0);
         break;
     }
 
     g.LogEnabled = g.ItemUnclipByLog = false;
-    g.LogType = ImGuiLogType_None;
+    g.LogFlags = ImGuiLogFlags_None;
     g.LogFile = NULL;
     g.LogBuffer.clear();
 }
diff --git a/imgui_internal.h b/imgui_internal.h
index fab1573031d2..af7270be8c7a 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -177,6 +177,7 @@ typedef int ImGuiDebugLogFlags;         // -> enum ImGuiDebugLogFlags_      // F
 typedef int ImGuiFocusRequestFlags;     // -> enum ImGuiFocusRequestFlags_  // Flags: for FocusWindow()
 typedef int ImGuiItemStatusFlags;       // -> enum ImGuiItemStatusFlags_    // Flags: for g.LastItemData.StatusFlags
 typedef int ImGuiOldColumnFlags;        // -> enum ImGuiOldColumnFlags_     // Flags: for BeginColumns()
+typedef int ImGuiLogFlags;              // -> enum ImGuiLogFlags_           // Flags: for LogBegin() text capturing function
 typedef int ImGuiNavRenderCursorFlags;  // -> enum ImGuiNavRenderCursorFlags_//Flags: for RenderNavCursor()
 typedef int ImGuiNavMoveFlags;          // -> enum ImGuiNavMoveFlags_       // Flags: for navigation requests
 typedef int ImGuiNextItemDataFlags;     // -> enum ImGuiNextItemDataFlags_  // Flags: for SetNextItemXXX() functions
@@ -989,13 +990,16 @@ enum ImGuiLayoutType_
     ImGuiLayoutType_Vertical = 1
 };
 
-enum ImGuiLogType
+// Flags for LogBegin() text capturing function
+enum ImGuiLogFlags_
 {
-    ImGuiLogType_None = 0,
-    ImGuiLogType_TTY,
-    ImGuiLogType_File,
-    ImGuiLogType_Buffer,
-    ImGuiLogType_Clipboard,
+    ImGuiLogFlags_None = 0,
+
+    ImGuiLogFlags_OutputTTY         = 1 << 0,
+    ImGuiLogFlags_OutputFile        = 1 << 1,
+    ImGuiLogFlags_OutputBuffer      = 1 << 2,
+    ImGuiLogFlags_OutputClipboard   = 1 << 3,
+    ImGuiLogFlags_OutputMask_       = ImGuiLogFlags_OutputTTY | ImGuiLogFlags_OutputFile | ImGuiLogFlags_OutputBuffer | ImGuiLogFlags_OutputClipboard,
 };
 
 // X/Y enums are fixed to 0/1 so they may be used to index ImVec2
@@ -2316,7 +2320,7 @@ struct ImGuiContext
 
     // Capture/Logging
     bool                    LogEnabled;                         // Currently capturing
-    ImGuiLogType            LogType;                            // Capture target
+    ImGuiLogFlags           LogFlags;                           // Capture flags/type
     ImFileHandle            LogFile;                            // If != NULL log to stdout/ file
     ImGuiTextBuffer         LogBuffer;                          // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.
     const char*             LogNextPrefix;
@@ -3067,7 +3071,7 @@ namespace ImGui
     IMGUI_API void          EndDisabledOverrideReenable();
 
     // Logging/Capture
-    IMGUI_API void          LogBegin(ImGuiLogType type, int auto_open_depth);           // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.
+    IMGUI_API void          LogBegin(ImGuiLogFlags flags, int auto_open_depth);         // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.
     IMGUI_API void          LogToBuffer(int auto_open_depth = -1);                      // Start logging/capturing to internal buffer
     IMGUI_API void          LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL);
     IMGUI_API void          LogSetNextTextDecoration(const char* prefix, const char* suffix);

From f37a9a27e582ad5316186f017e66b662efd9ca6b Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 30 Oct 2024 15:10:35 +0100
Subject: [PATCH 237/548] Log/Capture: reworked scope + decorating menus, tabs.

---
 docs/CHANGELOG.txt | 2 ++
 imgui.cpp          | 4 +++-
 imgui_internal.h   | 1 +
 imgui_widgets.cpp  | 4 ++++
 4 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 82c6b226638a..c20f0f04794d 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -48,6 +48,8 @@ Other changes:
 - Buttons: using ImGuiItemFlags_ButtonRepeat makes default button behavior use
   PressedOnClick instead of PressedOnClickRelease when unspecified.
 - Fonts: removed const qualifiers from most font functions.
+- Log/Capture: better decorating of BeginMenu() and TabItem() output.
+- Log/Capture: a non terminated log ends automatically in the window which called it.
 - Backends: DX12: Unmap() call specify written range. The range is informational and
   may be used by debug tools.
 - Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the 
diff --git a/imgui.cpp b/imgui.cpp
index 44a17508ff52..5d079f4aea54 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4008,6 +4008,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
 
     LogEnabled = false;
     LogFlags = ImGuiLogFlags_None;
+    LogWindow = NULL;
     LogNextPrefix = LogNextSuffix = NULL;
     LogFile = NULL;
     LogLinePosY = FLT_MAX;
@@ -7748,7 +7749,7 @@ void ImGui::End()
     }
 
     // Stop logging
-    if (!(window->Flags & ImGuiWindowFlags_ChildWindow))    // FIXME: add more options for scope of logging
+    if (g.LogWindow == window) // FIXME: add more options for scope of logging
         LogFinish();
 
     if (window->DC.IsSetPos)
@@ -14334,6 +14335,7 @@ void ImGui::LogBegin(ImGuiLogFlags flags, int auto_open_depth)
 
     g.LogEnabled = g.ItemUnclipByLog = true;
     g.LogFlags = flags;
+    g.LogWindow = window;
     g.LogNextPrefix = g.LogNextSuffix = NULL;
     g.LogDepthRef = window->DC.TreeDepth;
     g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth : g.LogDepthToExpandDefault);
diff --git a/imgui_internal.h b/imgui_internal.h
index af7270be8c7a..932a0484ca86 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2321,6 +2321,7 @@ struct ImGuiContext
     // Capture/Logging
     bool                    LogEnabled;                         // Currently capturing
     ImGuiLogFlags           LogFlags;                           // Capture flags/type
+    ImGuiWindow*            LogWindow;
     ImFileHandle            LogFile;                            // If != NULL log to stdout/ file
     ImGuiTextBuffer         LogBuffer;                          // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.
     const char*             LogNextPrefix;
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 1ee9a962437c..def3f5870a4c 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -8811,6 +8811,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
         float w = label_size.x;
         ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
         pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, label_size.y));
+        LogSetNextTextDecoration("[", "]");
         RenderText(text_pos, label);
         PopStyleVar();
         window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
@@ -8827,6 +8828,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
         float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
         ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
         pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
+        LogSetNextTextDecoration("", ">");
         RenderText(text_pos, label);
         if (icon_w > 0.0f)
             RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
@@ -9040,6 +9042,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
             if (shortcut_w > 0.0f)
             {
                 PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
+                LogSetNextTextDecoration("(", ")");
                 RenderText(pos + ImVec2(offsets->OffsetShortcut + stretch_w, 0.0f), shortcut, NULL, false);
                 PopStyleColor();
             }
@@ -10288,6 +10291,7 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
         text_ellipsis_clip_bb.Max.x -= unsaved_marker_visible ? (button_sz * 0.80f) : 0.0f;
         ellipsis_max_x = text_pixel_clip_bb.Max.x;
     }
+    LogSetNextTextDecoration("/", "\\");
     RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, text_pixel_clip_bb.Max.x, ellipsis_max_x, label, NULL, &label_size);
 
 #if 0

From 772ca9e9a9d9c8f7c90730b751279490fa427f7d Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 30 Oct 2024 15:14:02 +0100
Subject: [PATCH 238/548] Log/Capture: added experimental
 io.ConfigWindowsCopyContentsWithCtrlC config option.

---
 docs/CHANGELOG.txt |  4 ++++
 imgui.cpp          | 18 ++++++++----------
 imgui.h            |  5 +++--
 imgui_demo.cpp     |  4 +++-
 4 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index c20f0f04794d..026448b767bd 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -50,6 +50,10 @@ Other changes:
 - Fonts: removed const qualifiers from most font functions.
 - Log/Capture: better decorating of BeginMenu() and TabItem() output.
 - Log/Capture: a non terminated log ends automatically in the window which called it.
+- Log/Capture: added experimental io.ConfigWindowsCopyContentsWithCtrlC option to
+  automatically copy window contents into clipboard using CTRL+C. This is experimental
+  because (1) it currently breaks on nested Begin/End, (2) text output quality varies,
+  and (3) text output comes in submission order rather than spatial order.
 - Backends: DX12: Unmap() call specify written range. The range is informational and
   may be used by debug tools.
 - Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the 
diff --git a/imgui.cpp b/imgui.cpp
index 5d079f4aea54..b24f75068666 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1422,6 +1422,7 @@ ImGuiIO::ImGuiIO()
     ConfigDragClickToInputText = false;
     ConfigWindowsResizeFromEdges = true;
     ConfigWindowsMoveFromTitleBarOnly = false;
+    ConfigWindowsCopyContentsWithCtrlC = false;
     ConfigScrollbarScrollByPage = true;
     ConfigMemoryCompactTimer = 60.0f;
     ConfigDebugIsDebuggerPresent = false;
@@ -7587,6 +7588,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
         if (want_focus && window == g.NavWindow)
             NavInitWindow(window, false); // <-- this is in the way for us to be able to defer and sort reappearing FocusWindow() calls
 
+        // Pressing CTRL+C copy window content into the clipboard
+        // [EXPERIMENTAL] Breaks on nested Begin/End pairs. We need to work that out and add better logging scope.
+        // [EXPERIMENTAL] Text outputs has many issues.
+        if (g.IO.ConfigWindowsCopyContentsWithCtrlC)
+            if (g.NavWindow && g.NavWindow->RootWindow == window && g.ActiveId == 0 && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C))
+                LogToClipboard(0);
+
         // Title bar
         if (!(flags & ImGuiWindowFlags_NoTitleBar))
             RenderWindowTitleBarContents(window, ImRect(title_bar_rect.Min.x + window->WindowBorderSize, title_bar_rect.Min.y, title_bar_rect.Max.x - window->WindowBorderSize, title_bar_rect.Max.y), name, p_open);
@@ -7597,16 +7605,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
         if (flags & ImGuiWindowFlags_Tooltip)
             g.TooltipPreviousWindow = window;
 
-        // Pressing CTRL+C while holding on a window copy its content to the clipboard
-        // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope.
-        // Maybe we can support CTRL+C on every element?
-        /*
-        //if (g.NavWindow == window && g.ActiveId == 0)
-        if (g.ActiveId == window->MoveId)
-            if (g.IO.KeyCtrl && IsKeyPressed(ImGuiKey_C))
-                LogToClipboard();
-        */
-
         // We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin().
         // This is useful to allow creating context menus on title bar only, etc.
         SetLastItemDataForWindow(window, title_bar_rect);
diff --git a/imgui.h b/imgui.h
index 6f6779abf054..726c97f7366b 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2242,7 +2242,7 @@ struct ImGuiIO
     // Font system
     ImFontAtlas*Fonts;                          //            // Font atlas: load, rasterize and pack one or more fonts into a single texture.
     float       FontGlobalScale;                // = 1.0f           // Global scale all fonts
-    bool        FontAllowUserScaling;           // = false          // Allow user scaling text of individual window with CTRL+Wheel.
+    bool        FontAllowUserScaling;           // = false          // [OBSOLETE] Allow user scaling text of individual window with CTRL+Wheel.
     ImFont*     FontDefault;                    // = NULL           // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0].
     ImVec2      DisplayFramebufferScale;        // = (1, 1)         // For retina display or other situations where window coordinates are different from framebuffer coordinates. This generally ends up in ImDrawData::FramebufferScale.
 
@@ -2263,8 +2263,9 @@ struct ImGuiIO
     bool        ConfigInputTextCursorBlink;     // = true           // Enable blinking cursor (optional as some users consider it to be distracting).
     bool        ConfigInputTextEnterKeepActive; // = false          // [BETA] Pressing Enter will keep item active and select contents (single-line only).
     bool        ConfigDragClickToInputText;     // = false          // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
-    bool        ConfigWindowsResizeFromEdges;   // = true           // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
+    bool        ConfigWindowsResizeFromEdges;   // = true           // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
     bool        ConfigWindowsMoveFromTitleBarOnly;  // = false      // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
+    bool        ConfigWindowsCopyContentsWithCtrlC; // = false      // [EXPERIMENTAL] CTRL+C copy the contents of focused window into the clipboard. Experimental because: (1) has known issues with nested Begin/End pairs (2) text output quality varies (3) text output is in submission order rather than spatial order.
     bool        ConfigScrollbarScrollByPage;    // = true           // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
     float       ConfigMemoryCompactTimer;       // = 60.0f          // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
 
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index c6c06a58cd16..1a52b0ed2a7c 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -549,8 +549,10 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText);
             ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
             ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
-            ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
+            ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback.");
             ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
+            ImGui::Checkbox("io.ConfigWindowsCopyContentsWithCtrlC", &io.ConfigWindowsCopyContentsWithCtrlC); // [EXPERIMENTAL]
+            ImGui::SameLine(); HelpMarker("*EXPERIMENTAL* CTRL+C copy the contents of focused window into the clipboard.\n\nExperimental because:\n- (1) has known issues with nested Begin/End pairs.\n- (2) text output quality varies.\n- (3) text output is in submission order rather than spatial order.");
             ImGui::Checkbox("io.ConfigScrollbarScrollByPage", &io.ConfigScrollbarScrollByPage);
             ImGui::SameLine(); HelpMarker("Enable scrolling page by page when clicking outside the scrollbar grab.\nWhen disabled, always scroll to clicked location.\nWhen enabled, Shift+Click scrolls to clicked location.");
             ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);

From 71c77c081ac36841e682498229088e7678207112 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 30 Oct 2024 15:41:45 +0100
Subject: [PATCH 239/548] Demo: added a "Windows" section.

---
 imgui_demo.cpp | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 1a52b0ed2a7c..f44aedc6e4c7 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -541,13 +541,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::Checkbox("io.ConfigNavCursorVisibleAlways", &io.ConfigNavCursorVisibleAlways);
             ImGui::SameLine(); HelpMarker("Navigation cursor is always visible.");
 
-            ImGui::SeparatorText("Widgets");
-            ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
-            ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
-            ImGui::Checkbox("io.ConfigInputTextEnterKeepActive", &io.ConfigInputTextEnterKeepActive);
-            ImGui::SameLine(); HelpMarker("Pressing Enter will keep item active and select contents (single-line only).");
-            ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText);
-            ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
+            ImGui::SeparatorText("Windows");
             ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
             ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback.");
             ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
@@ -555,6 +549,14 @@ void ImGui::ShowDemoWindow(bool* p_open)
             ImGui::SameLine(); HelpMarker("*EXPERIMENTAL* CTRL+C copy the contents of focused window into the clipboard.\n\nExperimental because:\n- (1) has known issues with nested Begin/End pairs.\n- (2) text output quality varies.\n- (3) text output is in submission order rather than spatial order.");
             ImGui::Checkbox("io.ConfigScrollbarScrollByPage", &io.ConfigScrollbarScrollByPage);
             ImGui::SameLine(); HelpMarker("Enable scrolling page by page when clicking outside the scrollbar grab.\nWhen disabled, always scroll to clicked location.\nWhen enabled, Shift+Click scrolls to clicked location.");
+
+            ImGui::SeparatorText("Widgets");
+            ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
+            ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
+            ImGui::Checkbox("io.ConfigInputTextEnterKeepActive", &io.ConfigInputTextEnterKeepActive);
+            ImGui::SameLine(); HelpMarker("Pressing Enter will keep item active and select contents (single-line only).");
+            ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText);
+            ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
             ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);
             ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
             ImGui::Text("Also see Style->Rendering for rendering options.");

From f77d22837c0d2e8d0582cd1e8f077a88fa6ebd9b Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 4 Nov 2024 14:24:54 +0100
Subject: [PATCH 240/548] Examples: Android+OpenGL: Using ALooper_pollOnce()
 instead of ALooper_pollAll(). (#8013)

---
 docs/CHANGELOG.txt                        | 4 +++-
 examples/example_android_opengl3/main.cpp | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 026448b767bd..02297a64bdf9 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -60,7 +60,9 @@ Other changes:
   actual include. (#8095, #7967, #3190) [@sev-] 
 - Backends: SDL2, SDL3: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing 
   by 100.0f on Emscripten target. (#4019, #6096, #1463)
-- Examples: Added SDL3+Vulkan example. (#8084, #8085)
+- Examples: SDL3+Vulkan: Added example. (#8084, #8085)
+- Examples: Android+OpenGL: Using ALooper_pollOnce() instead of ALooper_pollAll()
+  which has been deprecated. (#8013) [@feather179]
 
 -----------------------------------------------------------------------
  VERSION 1.91.4 (Released 2024-10-18)
diff --git a/examples/example_android_opengl3/main.cpp b/examples/example_android_opengl3/main.cpp
index e0ad5f9360c8..42aa622f762f 100644
--- a/examples/example_android_opengl3/main.cpp
+++ b/examples/example_android_opengl3/main.cpp
@@ -68,7 +68,7 @@ void android_main(struct android_app* app)
         struct android_poll_source* out_data;
 
         // Poll all events. If the app is not visible, this loop blocks until g_Initialized == true.
-        while (ALooper_pollAll(g_Initialized ? 0 : -1, nullptr, &out_events, (void**)&out_data) >= 0)
+        while (ALooper_pollOnce(g_Initialized ? 0 : -1, nullptr, &out_events, (void**)&out_data) >= 0)
         {
             // Process one event
             if (out_data != nullptr)

From 75f83de52abe2b419eacbcbbee5d62c99f65b85b Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 4 Nov 2024 19:48:40 +0100
Subject: [PATCH 241/548] InputText: fixed a bug (regression in 1.91.2) where
 modifying text buffer within a callback would sometimes prevents further
 appending to the buffer. (#7925)

There's a confusion between TextA.Size and CurLenA we should be merging them.
Amend 19accb14a
---
 docs/CHANGELOG.txt | 2 ++
 imgui.h            | 2 +-
 imgui_internal.h   | 2 +-
 imgui_widgets.cpp  | 6 ++++--
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 02297a64bdf9..7bb626478e4b 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -48,6 +48,8 @@ Other changes:
 - Buttons: using ImGuiItemFlags_ButtonRepeat makes default button behavior use
   PressedOnClick instead of PressedOnClickRelease when unspecified.
 - Fonts: removed const qualifiers from most font functions.
+- InputText: fixed a bug (regression in 1.91.2) where modifying text buffer within
+  a callback would sometimes prevents further appending to the buffer.
 - Log/Capture: better decorating of BeginMenu() and TabItem() output.
 - Log/Capture: a non terminated log ends automatically in the window which called it.
 - Log/Capture: added experimental io.ConfigWindowsCopyContentsWithCtrlC option to
diff --git a/imgui.h b/imgui.h
index 726c97f7366b..9fd077379422 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.5 WIP"
-#define IMGUI_VERSION_NUM   19142
+#define IMGUI_VERSION_NUM   19143
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index 932a0484ca86..18b1467778be 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1111,7 +1111,7 @@ struct IMGUI_API ImGuiInputTextState
     ImStbTexteditState*     Stb;                    // State for stb_textedit.h
     ImGuiID                 ID;                     // widget id owning the text state
     int                     CurLenA;                // UTF-8 length of the string in TextA (in bytes)
-    ImVector          TextA;                  // main UTF8 buffer.
+    ImVector          TextA;                  // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1).
     ImVector          InitialTextA;           // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
     ImVector          CallbackTextBackup;     // temporary storage for callback to support automatic reconcile of undo-stack
     int                     BufCapacityA;           // end-user buffer capacity
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index def3f5870a4c..40e482d45205 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4200,6 +4200,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
     if (new_text == new_text_end)
         return;
 
+    // Grow internal buffer if needed
     const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
     const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);
     if (new_text_len + BufTextLen >= BufSize)
@@ -4213,7 +4214,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
         IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
         IM_ASSERT(Buf == edit_state->TextA.Data);
         int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
-        edit_state->TextA.reserve(new_buf_size + 1);
+        edit_state->TextA.resize(new_buf_size + 1);
         Buf = edit_state->TextA.Data;
         BufSize = edit_state->BufCapacityA = new_buf_size;
     }
@@ -5034,7 +5035,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                         IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
                         InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ?
                         state->CurLenA = callback_data.BufTextLen;  // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
-                        state->TextA.Size = state->CurLenA + 1;
                         state->CursorAnimReset();
                     }
                 }
@@ -5342,6 +5342,8 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
     Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId);
     DebugLocateItemOnHover(state->ID);
     Text("CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end);
+    Text("TextA.Size: %d, Capacity: %d", state->TextA.Size, state->TextA.Capacity);
+    Text("BufCapacityA: %d", state->BufCapacityA);
     Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x);
     Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point);
     if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 10), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY)) // Visualize undo state

From 82d0584e7bbefdd5de1d181f8bcf6eb6d656d525 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 4 Nov 2024 20:24:36 +0100
Subject: [PATCH 242/548] InputText: using CurLenA instead of TextA.Size for
 correctness. (#7925)

Was harmless because TextA is always zero-terminated, and TextA.Size >= CurLenA + 1.
---
 imgui_widgets.cpp | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 40e482d45205..01828c5e8310 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3930,7 +3930,7 @@ namespace ImStb
 {
 static int     STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj)                             { return obj->CurLenA; }
 static char    STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx <= obj->CurLenA); return obj->TextA[idx]; }
-static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->TextA.Size); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
+static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->CurLenA); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
 static char    STB_TEXTEDIT_NEWLINE = '\n';
 static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
 {
@@ -3953,7 +3953,7 @@ static int IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL(ImGuiInputTextState* obj, int id
     if (idx >= obj->CurLenA)
         return obj->CurLenA + 1;
     unsigned int c;
-    return idx + ImTextCharFromUtf8(&c, obj->TextA.Data + idx, obj->TextA.Data + obj->TextA.Size);
+    return idx + ImTextCharFromUtf8(&c, obj->TextA.Data + idx, obj->TextA.Data + obj->CurLenA);
 }
 
 static int IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
@@ -3986,8 +3986,8 @@ static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
 
     const char* curr_p = obj->TextA.Data + idx;
     const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, curr_p);
-    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, curr_p, obj->TextA.Data + obj->TextA.Size);
-    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, prev_p, obj->TextA.Data + obj->TextA.Size);
+    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, curr_p, obj->TextA.Data + obj->CurLenA);
+    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, prev_p, obj->TextA.Data + obj->CurLenA);
 
     bool prev_white = ImCharIsBlankW(prev_c);
     bool prev_separ = ImCharIsSeparatorW(prev_c);
@@ -4002,8 +4002,8 @@ static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
 
     const char* curr_p = obj->TextA.Data + idx;
     const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, curr_p);
-    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, curr_p, obj->TextA.Data + obj->TextA.Size);
-    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, prev_p, obj->TextA.Data + obj->TextA.Size);
+    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, curr_p, obj->TextA.Data + obj->CurLenA);
+    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, prev_p, obj->TextA.Data + obj->CurLenA);
 
     bool prev_white = ImCharIsBlankW(prev_c);
     bool prev_separ = ImCharIsSeparatorW(prev_c);
@@ -5342,8 +5342,8 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
     Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId);
     DebugLocateItemOnHover(state->ID);
     Text("CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end);
-    Text("TextA.Size: %d, Capacity: %d", state->TextA.Size, state->TextA.Capacity);
     Text("BufCapacityA: %d", state->BufCapacityA);
+    Text("(Internal Buffer: TextA Size: %d, Capacity: %d)", state->TextA.Size, state->TextA.Capacity);
     Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x);
     Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point);
     if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 10), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY)) // Visualize undo state

From d4791f1bbef15fa407c853bf845ee1adefb0b940 Mon Sep 17 00:00:00 2001
From: Brotcrunsher 
Date: Tue, 5 Nov 2024 10:12:52 +0100
Subject: [PATCH 243/548] Fixed a comment typo. (#8128)

---
 imgui.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/imgui.h b/imgui.h
index 9fd077379422..27e3bda5e706 100644
--- a/imgui.h
+++ b/imgui.h
@@ -3065,7 +3065,7 @@ enum ImDrawListFlags_
 // access the current window draw list and draw custom primitives.
 // You can interleave normal ImGui:: calls and adding primitives to the current draw list.
 // In single viewport mode, top-left is == GetMainViewport()->Pos (generally 0,0), bottom-right is == GetMainViewport()->Pos+Size (generally io.DisplaySize).
-// You are totally free to apply whatever transformation matrix to want to the data (depending on the use of the transformation you may want to apply it to ClipRect as well!)
+// You are totally free to apply whatever transformation matrix you want to the data (depending on the use of the transformation you may want to apply it to ClipRect as well!)
 // Important: Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions), if you use this API a lot consider coarse culling your drawn objects.
 struct ImDrawList
 {

From 88e232739bc9da4c4070a9c912b7ebee0acc84f6 Mon Sep 17 00:00:00 2001
From: Maya Warrier <34803055+mayawarrier@users.noreply.github.com>
Date: Tue, 5 Nov 2024 04:44:39 -0500
Subject: [PATCH 244/548] Ignore clang warning Wnontrivial-memaccess (#8129)

Produced when memset(this, ..) is used on a non-trivially copyable type
---
 backends/imgui_impl_metal.mm | 7 +++++++
 backends/imgui_impl_osx.mm   | 7 +++++++
 imgui_draw.cpp               | 1 +
 imgui_internal.h             | 1 +
 4 files changed, 16 insertions(+)

diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm
index b8f82a65ded5..102f6982afd8 100644
--- a/backends/imgui_impl_metal.mm
+++ b/backends/imgui_impl_metal.mm
@@ -38,6 +38,13 @@
 #import 
 #import 
 
+#if defined(__clang__)
+#if __has_warning("-Wunknown-warning-option")
+#pragma clang diagnostic ignored "-Wunknown-warning-option"         // warning: unknown warning group 'xxx'
+#endif
+#pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
+#endif
+
 #pragma mark - Support classes
 
 // A wrapper around a MTLBuffer object that knows the last time it was reused
diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm
index de9b57408a06..6ff4f19a42c5 100644
--- a/backends/imgui_impl_osx.mm
+++ b/backends/imgui_impl_osx.mm
@@ -27,6 +27,13 @@
 #import 
 #import 
 
+#if defined(__clang__)
+#if __has_warning("-Wunknown-warning-option")
+#pragma clang diagnostic ignored "-Wunknown-warning-option"         // warning: unknown warning group 'xxx'
+#endif
+#pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
+#endif
+
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
 //  2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index d54c96babcbb..2385d2ed8c1b 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -66,6 +66,7 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
 #pragma clang diagnostic ignored "-Wreserved-identifier"            // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
+#pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
 #elif defined(__GNUC__)
 #pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
 #pragma GCC diagnostic ignored "-Wunused-function"          // warning: 'xxxx' defined but not used
diff --git a/imgui_internal.h b/imgui_internal.h
index 18b1467778be..ad90e0309c2f 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -91,6 +91,7 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wmissing-noreturn"               // warning: function 'xxx' could be declared with attribute 'noreturn'
 #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
+#pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
 #elif defined(__GNUC__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wpragmas"              // warning: unknown option after '#pragma GCC diagnostic' kind

From be2d006e2e7e9f029e893ff358d9acc87c250411 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 5 Nov 2024 10:50:49 +0100
Subject: [PATCH 245/548] Align warning blocks. Removed -Wunused-function,
 -Wmissing-prototypes from imgui_internal.h

As supposedly they were for stb_textedit.h which is now moved to imgui_draw.cpp
---
 imgui.cpp        | 18 +++++++++---------
 imgui.h          |  8 ++++----
 imgui_demo.cpp   | 12 ++++++------
 imgui_draw.cpp   | 14 +++++++-------
 imgui_internal.h | 12 +++++-------
 5 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index b24f75068666..01a72c6b7b3c 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1126,15 +1126,15 @@ CODE
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
 #elif defined(__GNUC__)
 // We disable -Wpragmas because GCC doesn't provide a has_warning equivalent and some forks/patches may not follow the warning/version association.
-#pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
-#pragma GCC diagnostic ignored "-Wunused-function"          // warning: 'xxxx' defined but not used
-#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"      // warning: cast to pointer from integer of different size
-#pragma GCC diagnostic ignored "-Wformat"                   // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'
-#pragma GCC diagnostic ignored "-Wdouble-promotion"         // warning: implicit conversion from 'float' to 'double' when passing argument to function
-#pragma GCC diagnostic ignored "-Wconversion"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"        // warning: format not a string literal, format string not checked
-#pragma GCC diagnostic ignored "-Wstrict-overflow"          // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
-#pragma GCC diagnostic ignored "-Wclass-memaccess"          // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wunused-function"                  // warning: 'xxxx' defined but not used
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"              // warning: cast to pointer from integer of different size
+#pragma GCC diagnostic ignored "-Wformat"                           // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'
+#pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wconversion"                       // warning: conversion to 'xxxx' from 'xxxx' may alter its value
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"                // warning: format not a string literal, format string not checked
+#pragma GCC diagnostic ignored "-Wstrict-overflow"                  // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
+#pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #endif
 
 // Debug options
diff --git a/imgui.h b/imgui.h
index 27e3bda5e706..973a52f53468 100644
--- a/imgui.h
+++ b/imgui.h
@@ -130,15 +130,15 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wunknown-warning-option"         // warning: unknown warning group 'xxx'
 #endif
 #pragma clang diagnostic ignored "-Wunknown-pragmas"                // warning: unknown warning group 'xxx'
-#pragma clang diagnostic ignored "-Wold-style-cast"
+#pragma clang diagnostic ignored "-Wold-style-cast"                 // warning: use of old-style cast
 #pragma clang diagnostic ignored "-Wfloat-equal"                    // warning: comparing floating point with == or != is unsafe
-#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"  // warning: zero as null pointer constant
 #pragma clang diagnostic ignored "-Wreserved-identifier"            // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
 #elif defined(__GNUC__)
 #pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpragmas"          // warning: unknown option after '#pragma GCC diagnostic' kind
-#pragma GCC diagnostic ignored "-Wclass-memaccess"  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #endif
 
 //-----------------------------------------------------------------------------
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index f44aedc6e4c7..f5e16f06c161 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -145,12 +145,12 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
 #elif defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
-#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"      // warning: cast to pointer from integer of different size
-#pragma GCC diagnostic ignored "-Wformat-security"          // warning: format string is not a string literal (potentially insecure)
-#pragma GCC diagnostic ignored "-Wdouble-promotion"         // warning: implicit conversion from 'float' to 'double' when passing argument to function
-#pragma GCC diagnostic ignored "-Wconversion"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value
-#pragma GCC diagnostic ignored "-Wmisleading-indentation"   // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on GitHub.
+#pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"              // warning: cast to pointer from integer of different size
+#pragma GCC diagnostic ignored "-Wformat-security"                  // warning: format string is not a string literal (potentially insecure)
+#pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wconversion"                       // warning: conversion to 'xxxx' from 'xxxx' may alter its value
+#pragma GCC diagnostic ignored "-Wmisleading-indentation"           // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on GitHub.
 #endif
 
 // Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 2385d2ed8c1b..ac6d0228196e 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -68,12 +68,12 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
 #pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
 #elif defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
-#pragma GCC diagnostic ignored "-Wunused-function"          // warning: 'xxxx' defined but not used
-#pragma GCC diagnostic ignored "-Wdouble-promotion"         // warning: implicit conversion from 'float' to 'double' when passing argument to function
-#pragma GCC diagnostic ignored "-Wconversion"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value
-#pragma GCC diagnostic ignored "-Wstack-protector"          // warning: stack protector not protecting local variables: variable length buffer
-#pragma GCC diagnostic ignored "-Wclass-memaccess"          // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wunused-function"                  // warning: 'xxxx' defined but not used
+#pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wconversion"                       // warning: conversion to 'xxxx' from 'xxxx' may alter its value
+#pragma GCC diagnostic ignored "-Wstack-protector"                  // warning: stack protector not protecting local variables: variable length buffer
+#pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #endif
 
 //-------------------------------------------------------------------------
@@ -102,7 +102,7 @@ namespace IMGUI_STB_NAMESPACE
 
 #if defined(__clang__)
 #pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-function"
+#pragma clang diagnostic ignored "-Wunused-function"        // warning: 'xxxx' defined but not used
 #pragma clang diagnostic ignored "-Wmissing-prototypes"
 #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
 #pragma clang diagnostic ignored "-Wcast-qual"              // warning: cast from 'const xxxx *' to 'xxx *' drops const qualifier
diff --git a/imgui_internal.h b/imgui_internal.h
index ad90e0309c2f..a35ab64e2e12 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -82,11 +82,9 @@ Index of this file:
 #endif
 #pragma clang diagnostic ignored "-Wunknown-pragmas"                // warning: unknown warning group 'xxx'
 #pragma clang diagnostic ignored "-Wfloat-equal"                    // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants ok, for ImFloor()
-#pragma clang diagnostic ignored "-Wunused-function"                // for stb_textedit.h
-#pragma clang diagnostic ignored "-Wmissing-prototypes"             // for stb_textedit.h
-#pragma clang diagnostic ignored "-Wold-style-cast"
-#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
-#pragma clang diagnostic ignored "-Wdouble-promotion"
+#pragma clang diagnostic ignored "-Wold-style-cast"                 // warning: use of old-style cast
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"  // warning: zero as null pointer constant
+#pragma clang diagnostic ignored "-Wdouble-promotion"               // warning: implicit conversion from 'float' to 'double' when passing argument to function
 #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
 #pragma clang diagnostic ignored "-Wmissing-noreturn"               // warning: function 'xxx' could be declared with attribute 'noreturn'
 #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
@@ -94,8 +92,8 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
 #elif defined(__GNUC__)
 #pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpragmas"              // warning: unknown option after '#pragma GCC diagnostic' kind
-#pragma GCC diagnostic ignored "-Wclass-memaccess"      // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion"  // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
 #endif
 

From 63234f8dd0a2acf5fa48184798382ea1e045ab3a Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 5 Nov 2024 11:32:02 +0100
Subject: [PATCH 246/548] InputText: Internals: rename CurLenA->TextLen,
 InitialTextA->TextToRevertTo.

Follow the refactors in #7925.
---
 imgui_internal.h  | 10 ++---
 imgui_widgets.cpp | 96 +++++++++++++++++++++++------------------------
 2 files changed, 53 insertions(+), 53 deletions(-)

diff --git a/imgui_internal.h b/imgui_internal.h
index a35ab64e2e12..6d84f1027aca 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1109,11 +1109,11 @@ struct IMGUI_API ImGuiInputTextState
     ImGuiContext*           Ctx;                    // parent UI context (needs to be set explicitly by parent).
     ImStbTexteditState*     Stb;                    // State for stb_textedit.h
     ImGuiID                 ID;                     // widget id owning the text state
-    int                     CurLenA;                // UTF-8 length of the string in TextA (in bytes)
+    int                     TextLen;                // UTF-8 length of the string in TextA (in bytes)
     ImVector          TextA;                  // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1).
-    ImVector          InitialTextA;           // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
+    ImVector          TextToRevertTo;         // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
     ImVector          CallbackTextBackup;     // temporary storage for callback to support automatic reconcile of undo-stack
-    int                     BufCapacityA;           // end-user buffer capacity
+    int                     BufCapacity;            // end-user buffer capacity (include zero terminator)
     ImVec2                  Scroll;                 // horizontal offset (managed manually) + vertical scrolling (pulled from child window's own Scroll.y)
     float                   CursorAnim;             // timer for cursor blink, reset on every user action so the cursor reappears immediately
     bool                    CursorFollow;           // set when we want scrolling to follow the current cursor position (not always!)
@@ -1126,8 +1126,8 @@ struct IMGUI_API ImGuiInputTextState
 
     ImGuiInputTextState();
     ~ImGuiInputTextState();
-    void        ClearText()                 { CurLenA = 0; TextA[0] = 0; CursorClamp(); }
-    void        ClearFreeMemory()           { TextA.clear(); InitialTextA.clear(); }
+    void        ClearText()                 { TextLen = 0; TextA[0] = 0; CursorClamp(); }
+    void        ClearFreeMemory()           { TextA.clear(); TextToRevertTo.clear(); }
     void        OnKeyPressed(int key);      // Cannot be inline because we call in code in stb_textedit.h implementation
     void        OnCharPressed(unsigned int c);
 
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 01828c5e8310..9d572422283f 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3928,15 +3928,15 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
 // - ...but we don't use that feature.
 namespace ImStb
 {
-static int     STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj)                             { return obj->CurLenA; }
-static char    STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx <= obj->CurLenA); return obj->TextA[idx]; }
-static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->CurLenA); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
+static int     STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj)                             { return obj->TextLen; }
+static char    STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx <= obj->TextLen); return obj->TextA[idx]; }
+static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
 static char    STB_TEXTEDIT_NEWLINE = '\n';
 static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
 {
     const char* text = obj->TextA.Data;
     const char* text_remaining = NULL;
-    const ImVec2 size = InputTextCalcTextSize(obj->Ctx, text + line_start_idx, text + obj->CurLenA, &text_remaining, NULL, true);
+    const ImVec2 size = InputTextCalcTextSize(obj->Ctx, text + line_start_idx, text + obj->TextLen, &text_remaining, NULL, true);
     r->x0 = 0.0f;
     r->x1 = size.x;
     r->baseline_y_delta = size.y;
@@ -3950,10 +3950,10 @@ static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob
 
 static int IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
 {
-    if (idx >= obj->CurLenA)
-        return obj->CurLenA + 1;
+    if (idx >= obj->TextLen)
+        return obj->TextLen + 1;
     unsigned int c;
-    return idx + ImTextCharFromUtf8(&c, obj->TextA.Data + idx, obj->TextA.Data + obj->CurLenA);
+    return idx + ImTextCharFromUtf8(&c, obj->TextA.Data + idx, obj->TextA.Data + obj->TextLen);
 }
 
 static int IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
@@ -3986,8 +3986,8 @@ static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
 
     const char* curr_p = obj->TextA.Data + idx;
     const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, curr_p);
-    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, curr_p, obj->TextA.Data + obj->CurLenA);
-    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, prev_p, obj->TextA.Data + obj->CurLenA);
+    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, curr_p, obj->TextA.Data + obj->TextLen);
+    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, prev_p, obj->TextA.Data + obj->TextLen);
 
     bool prev_white = ImCharIsBlankW(prev_c);
     bool prev_separ = ImCharIsSeparatorW(prev_c);
@@ -4002,8 +4002,8 @@ static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
 
     const char* curr_p = obj->TextA.Data + idx;
     const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, curr_p);
-    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, curr_p, obj->TextA.Data + obj->CurLenA);
-    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, prev_p, obj->TextA.Data + obj->CurLenA);
+    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, curr_p, obj->TextA.Data + obj->TextLen);
+    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, prev_p, obj->TextA.Data + obj->TextLen);
 
     bool prev_white = ImCharIsBlankW(prev_c);
     bool prev_separ = ImCharIsSeparatorW(prev_c);
@@ -4020,7 +4020,7 @@ static int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx)
 }
 static int  STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx)
 {
-    int len = obj->CurLenA;
+    int len = obj->TextLen;
     idx = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx);
     while (idx < len && !is_word_boundary_from_left(obj, idx))
         idx = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx);
@@ -4029,7 +4029,7 @@ static int  STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx)
 static int  STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx)
 {
     idx = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx);
-    int len = obj->CurLenA;
+    int len = obj->TextLen;
     while (idx < len && !is_word_boundary_from_right(obj, idx))
         idx = IMSTB_TEXTEDIT_GETNEXTCHARINDEX(obj, idx);
     return idx > len ? len : idx;
@@ -4043,7 +4043,7 @@ static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
     char* dst = obj->TextA.Data + pos;
 
     obj->Edited = true;
-    obj->CurLenA -= n;
+    obj->TextLen -= n;
 
     // Offset remaining text (FIXME-OPT: Use memmove)
     const char* src = obj->TextA.Data + pos + n;
@@ -4055,10 +4055,10 @@ static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
 static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len)
 {
     const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
-    const int text_len = obj->CurLenA;
+    const int text_len = obj->TextLen;
     IM_ASSERT(pos <= text_len);
 
-    if (!is_resizable && (new_text_len + obj->CurLenA + 1 > obj->BufCapacityA))
+    if (!is_resizable && (new_text_len + obj->TextLen + 1 > obj->BufCapacity))
         return false;
 
     // Grow internal buffer if needed
@@ -4075,8 +4075,8 @@ static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ch
     memcpy(text + pos, new_text, (size_t)new_text_len);
 
     obj->Edited = true;
-    obj->CurLenA += new_text_len;
-    obj->TextA[obj->CurLenA] = '\0';
+    obj->TextLen += new_text_len;
+    obj->TextA[obj->TextLen] = '\0';
 
     return true;
 }
@@ -4108,8 +4108,8 @@ static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ch
 // the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?)
 static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
 {
-    stb_text_makeundo_replace(str, state, 0, str->CurLenA, text_len);
-    ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenA);
+    stb_text_makeundo_replace(str, state, 0, str->TextLen, text_len);
+    ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->TextLen);
     state->cursor = state->select_start = state->select_end = 0;
     if (text_len <= 0)
         return;
@@ -4157,13 +4157,13 @@ void ImGuiInputTextState::OnCharPressed(unsigned int c)
 
 // Those functions are not inlined in imgui_internal.h, allowing us to hide ImStbTexteditState from that header.
 void ImGuiInputTextState::CursorAnimReset()                 { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
-void ImGuiInputTextState::CursorClamp()                     { Stb->cursor = ImMin(Stb->cursor, CurLenA); Stb->select_start = ImMin(Stb->select_start, CurLenA); Stb->select_end = ImMin(Stb->select_end, CurLenA); }
+void ImGuiInputTextState::CursorClamp()                     { Stb->cursor = ImMin(Stb->cursor, TextLen); Stb->select_start = ImMin(Stb->select_start, TextLen); Stb->select_end = ImMin(Stb->select_end, TextLen); }
 bool ImGuiInputTextState::HasSelection() const              { return Stb->select_start != Stb->select_end; }
 void ImGuiInputTextState::ClearSelection()                  { Stb->select_start = Stb->select_end = Stb->cursor; }
 int  ImGuiInputTextState::GetCursorPos() const              { return Stb->cursor; }
 int  ImGuiInputTextState::GetSelectionStart() const         { return Stb->select_start; }
 int  ImGuiInputTextState::GetSelectionEnd() const           { return Stb->select_end; }
-void ImGuiInputTextState::SelectAll()                       { Stb->select_start = 0; Stb->cursor = Stb->select_end = CurLenA; Stb->has_preferred_x = 0; }
+void ImGuiInputTextState::SelectAll()                       { Stb->select_start = 0; Stb->cursor = Stb->select_end = TextLen; Stb->has_preferred_x = 0; }
 void ImGuiInputTextState::ReloadUserBufAndSelectAll()       { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; }
 void ImGuiInputTextState::ReloadUserBufAndKeepSelection()   { ReloadUserBuf = true; ReloadSelectionStart = Stb->select_start; ReloadSelectionEnd = Stb->select_end; }
 void ImGuiInputTextState::ReloadUserBufAndMoveToEnd()       { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; }
@@ -4216,7 +4216,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
         int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
         edit_state->TextA.resize(new_buf_size + 1);
         Buf = edit_state->TextA.Data;
-        BufSize = edit_state->BufCapacityA = new_buf_size;
+        BufSize = edit_state->BufCapacity = new_buf_size;
     }
 
     if (BufTextLen != pos)
@@ -4380,8 +4380,8 @@ void ImGui::InputTextDeactivateHook(ImGuiID id)
     else
     {
         IM_ASSERT(state->TextA.Data != 0);
-        g.InputTextDeactivatedState.TextA.resize(state->CurLenA + 1);
-        memcpy(g.InputTextDeactivatedState.TextA.Data, state->TextA.Data, state->CurLenA + 1);
+        g.InputTextDeactivatedState.TextA.resize(state->TextLen + 1);
+        memcpy(g.InputTextDeactivatedState.TextA.Data, state->TextA.Data, state->TextLen + 1);
     }
 }
 
@@ -4521,21 +4521,21 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         if (!init_reload_from_user_buf)
         {
             // Take a copy of the initial buffer value.
-            state->InitialTextA.resize(buf_len + 1);    // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
-            memcpy(state->InitialTextA.Data, buf, buf_len + 1);
+            state->TextToRevertTo.resize(buf_len + 1);    // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
+            memcpy(state->TextToRevertTo.Data, buf, buf_len + 1);
         }
 
         // Preserve cursor position and undo/redo stack if we come back to same widget
         // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
         bool recycle_state = (state->ID == id && !init_changed_specs && !init_reload_from_user_buf);
-        if (recycle_state && (state->CurLenA != buf_len || (strncmp(state->TextA.Data, buf, buf_len) != 0)))
+        if (recycle_state && (state->TextLen != buf_len || (strncmp(state->TextA.Data, buf, buf_len) != 0)))
             recycle_state = false;
 
         // Start edition
         state->ID = id;
         state->TextA.resize(buf_size + 1);          // we use +1 to make sure that .Data is always pointing to at least an empty string.
-        state->CurLenA = (int)strlen(buf);
-        memcpy(state->TextA.Data, buf, state->CurLenA + 1);
+        state->TextLen = (int)strlen(buf);
+        memcpy(state->TextA.Data, buf, state->TextLen + 1);
 
         if (recycle_state)
         {
@@ -4646,7 +4646,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     {
         IM_ASSERT(state != NULL);
         state->Edited = false;
-        state->BufCapacityA = buf_size;
+        state->BufCapacity = buf_size;
         state->Flags = flags;
 
         // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
@@ -4871,7 +4871,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             if (g.PlatformIO.Platform_SetClipboardTextFn != NULL)
             {
                 const int ib = state->HasSelection() ? ImMin(state->Stb->select_start, state->Stb->select_end) : 0;
-                const int ie = state->HasSelection() ? ImMax(state->Stb->select_start, state->Stb->select_end) : state->CurLenA;
+                const int ie = state->HasSelection() ? ImMax(state->Stb->select_start, state->Stb->select_end) : state->TextLen;
 
                 char backup = state->TextA.Data[ie];
                 state->TextA.Data[ie] = 0; // A bit of a hack since SetClipboardText only takes null terminated strings
@@ -4936,15 +4936,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                 IMSTB_TEXTEDIT_CHARTYPE empty_string;
                 stb_textedit_replace(state, state->Stb, &empty_string, 0);
             }
-            else if (strcmp(buf, state->InitialTextA.Data) != 0)
+            else if (strcmp(buf, state->TextToRevertTo.Data) != 0)
             {
-                apply_new_text = state->InitialTextA.Data;
-                apply_new_text_length = state->InitialTextA.Size - 1;
+                apply_new_text = state->TextToRevertTo.Data;
+                apply_new_text_length = state->TextToRevertTo.Size - 1;
 
                 // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents.
                 // Push records into the undo stack so we can CTRL+Z the revert operation itself
                 value_changed = true;
-                stb_textedit_replace(state, state->Stb, state->InitialTextA.Data, state->InitialTextA.Size - 1);
+                stb_textedit_replace(state, state->Stb, state->TextToRevertTo.Data, state->TextToRevertTo.Size - 1);
             }
         }
 
@@ -5003,14 +5003,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                     callback_data.UserData = callback_user_data;
 
                     // FIXME-OPT: Undo stack reconcile needs a backup of the data until we rework API, see #7925
-                    state->CallbackTextBackup.resize(state->CurLenA + 1);
-                    memcpy(state->CallbackTextBackup.Data, state->TextA.Data, state->CurLenA + 1);
+                    state->CallbackTextBackup.resize(state->TextLen + 1);
+                    memcpy(state->CallbackTextBackup.Data, state->TextA.Data, state->TextLen + 1);
 
                     char* callback_buf = is_readonly ? buf : state->TextA.Data;
                     callback_data.EventKey = event_key;
                     callback_data.Buf = callback_buf;
-                    callback_data.BufTextLen = state->CurLenA;
-                    callback_data.BufSize = state->BufCapacityA;
+                    callback_data.BufTextLen = state->TextLen;
+                    callback_data.BufSize = state->BufCapacity;
                     callback_data.BufDirty = false;
 
                     const int utf8_cursor_pos = callback_data.CursorPos = state->Stb->cursor;
@@ -5023,7 +5023,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                     // Read back what user may have modified
                     callback_buf = is_readonly ? buf : state->TextA.Data; // Pointer may have been invalidated by a resize callback
                     IM_ASSERT(callback_data.Buf == callback_buf);         // Invalid to modify those fields
-                    IM_ASSERT(callback_data.BufSize == state->BufCapacityA);
+                    IM_ASSERT(callback_data.BufSize == state->BufCapacity);
                     IM_ASSERT(callback_data.Flags == flags);
                     const bool buf_dirty = callback_data.BufDirty;
                     if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty)            { state->Stb->cursor = callback_data.CursorPos; state->CursorFollow = true; }
@@ -5034,7 +5034,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                         // Callback may update buffer and thus set buf_dirty even in read-only mode.
                         IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
                         InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ?
-                        state->CurLenA = callback_data.BufTextLen;  // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
+                        state->TextLen = callback_data.BufTextLen;  // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
                         state->CursorAnimReset();
                     }
                 }
@@ -5044,7 +5044,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             if (!is_readonly && strcmp(state->TextA.Data, buf) != 0)
             {
                 apply_new_text = state->TextA.Data;
-                apply_new_text_length = state->CurLenA;
+                apply_new_text_length = state->TextLen;
                 value_changed = true;
             }
         }
@@ -5128,7 +5128,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     {
         IM_ASSERT(state != NULL);
         if (!is_displaying_hint)
-            buf_display_end = buf_display + state->CurLenA;
+            buf_display_end = buf_display + state->TextLen;
 
         // Render text (with cursor and selection)
         // This is going to be messy. We need to:
@@ -5138,7 +5138,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
         // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
         const char* text_begin = state->TextA.Data;
-        const char* text_end = text_begin + state->CurLenA;
+        const char* text_end = text_begin + state->TextLen;
         ImVec2 cursor_offset, select_start_offset;
 
         {
@@ -5280,7 +5280,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         if (is_multiline)
             text_size = ImVec2(inner_size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width
         else if (!is_displaying_hint && g.ActiveId == id)
-            buf_display_end = buf_display + state->CurLenA;
+            buf_display_end = buf_display + state->TextLen;
         else if (!is_displaying_hint)
             buf_display_end = buf_display + strlen(buf_display);
 
@@ -5341,8 +5341,8 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
     ImStb::StbUndoState* undo_state = &stb_state->undostate;
     Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId);
     DebugLocateItemOnHover(state->ID);
-    Text("CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end);
-    Text("BufCapacityA: %d", state->BufCapacityA);
+    Text("CurLenA: %d, Cursor: %d, Selection: %d..%d", state->TextLen, stb_state->cursor, stb_state->select_start, stb_state->select_end);
+    Text("BufCapacityA: %d", state->BufCapacity);
     Text("(Internal Buffer: TextA Size: %d, Capacity: %d)", state->TextA.Size, state->TextA.Capacity);
     Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x);
     Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point);

From ec2f1d69c8d8d6373d64ee0ffb29b51b78925d65 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 5 Nov 2024 13:18:16 +0100
Subject: [PATCH 247/548] Docs: word-wrap some the older changelogs.

---
 docs/CHANGELOG.txt | 765 +++++++++++++++++++++++++++++++--------------
 1 file changed, 523 insertions(+), 242 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 7bb626478e4b..9e43a56a1faa 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -4597,20 +4597,27 @@ Other Changes:
   - See https://github.com/ocornut/imgui/issues/1599 for recommended gamepad mapping or download PNG/PSD at http://goo.gl/9LgVZW
   - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. Read imgui.cpp for more details.
 - To use Keyboard Navigation:
-  - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
-  - Basic controls: arrows to navigate, Alt to enter menus, Space to activate item, Enter to edit text, Escape to cancel/close, Ctrl-Tab to focus windows, etc.
-  - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag will be set.
-    For more advanced uses, you may want to read from io.NavActive or io.NavVisible. Read imgui.cpp for more details.
+  - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically
+    fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
+  - Basic controls: arrows to navigate, Alt to enter menus, Space to activate item, Enter to edit text,
+    Escape to cancel/close, Ctrl-Tab to focus windows, etc.
+  - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard),
+    the io.WantCaptureKeyboard flag will be set.
+  - For more advanced uses, you may want to read from io.NavActive or io.NavVisible. Read imgui.cpp for more details.
 - Navigation: SetItemDefaultFocus() sets the navigation position in addition to scrolling. (#787)
 - Navigation: Added IsItemFocused(), added IsAnyItemFocused(). (#787)
 - Navigation: Added window flags: ImGuiWindowFlags_NoNav (== ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus).
 - Navigation: Style: Added ImGuiCol_NavHighlight, ImGuiCol_NavWindowingHighlight colors. (#787)
 - Navigation: TreeNode: Added ImGuiTreeNodeFlags_NavLeftJumpsBackHere flag to allow Nav Left direction to jump back to parent tree node from any of its child. (#1079)
 - Navigation: IO: Added io.ConfigFlags (input), io.NavActive (output), io.NavVisible (output). (#787)
-- Context: Removed the default global context and font atlas instances, which caused various problems to users of multiple contexts and DLL users. (#1565, #1599)
-  YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. Existing apps will assert/crash without it.
-- Context: Added SetAllocatorFunctions() to rewire memory allocators (as a replacement to previous parameters to CreateContext()). Allocators are shared by all contexts and imgui helpers. (#1565, #586, #992, #1007, #1558)
-- Context: You may pass a ImFontAtlas to CreateContext() to specify a font atlas to share. Shared font atlas are not owned by the context and not destroyed along with it. (#1599)
+- Context: Removed the default global context and font atlas instances, which caused various
+  problems to users of multiple contexts and DLL users. (#1565, #1599) YOU NOW NEED TO CALL
+  ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END.
+  Existing apps will assert/crash without it.
+- Context: Added SetAllocatorFunctions() to rewire memory allocators (as a replacement to previous
+  parameters to CreateContext()). Allocators are shared by all contexts and imgui helpers. (#1565, #586, #992, #1007, #1558)
+- Context: You may pass a ImFontAtlas to CreateContext() to specify a font atlas to share.
+  Shared font atlas are not owned by the context and not destroyed along with it. (#1599)
 - Context: Added IMGUI_DISABLE_DEFAULT_ALLOCATORS to disable linking with malloc/free. (#1565, #586, #992, #1007, #1558)
 - IO: Added io.ConfigFlags for user application to store settings for imgui and for the backend:
   - ImGuiConfigFlags_NavEnableKeyboard: Enable keyboard navigation.
@@ -4619,61 +4626,85 @@ Other Changes:
   - ImGuiConfigFlags_NoMouseCursorChange: Instruct backend to not alter mouse cursor shape and visibility (by default the example backend use mouse cursor API of the platform when available)
   - ImGuiConfigFlags_NoMouse: Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information passed by the backend.
   - ImGuiConfigFlags_IsSRGB, ImGuiConfigFlags_IsTouchScreen: Flags for general application use.
-- IO: Added io.BackendFlags for backend to store its capabilities (currently: _HasGamepad, _HasMouseCursors, _HasSetMousePos). This will be used more in the next version.
+- IO: Added io.BackendFlags for backend to store its capabilities (currently: _HasGamepad,
+  _HasMouseCursors, _HasSetMousePos). This will be used more in the next version.
 - IO: Added ImGuiKey_Insert, ImGuiKey_Space keys. Setup in all example backends. (#1541)
 - IO: Added Horizontal Mouse Wheel support for horizontal scrolling. (#1463) [@tseeker]
 - IO: Added IsAnyMouseDown() helper which is helpful for backends to handle mouse capturing.
-- Window: Clicking on a window with the ImGuiWIndowFlags_NoMove flags takes an ActiveId so we can't hover something else when dragging afterwards. (#1381, #1337)
-- Window: IsWindowHovered(): Added ImGuiHoveredFlags_AnyWindow, ImGuiFocusedFlags_AnyWindow flags (See Breaking Changes). Added to demo. (#1382)
-- Window: Added SetNextWindowBgAlpha() helper. Particularly helpful since the legacy 5-parameters version of Begin() has been marked as obsolete in 1.53. (#1567)
-- Window: Fixed SetNextWindowContentSize() with 0.0f on Y axis (or SetNextWindowContentWidth()) overwriting the contents size. Got broken on Dec 10 (1.53). (#1363)
+- Window: Clicking on a window with the ImGuiWIndowFlags_NoMove flags takes an ActiveId so
+  we can't hover something else when dragging afterwards. (#1381, #1337)
+- Window: IsWindowHovered(): Added ImGuiHoveredFlags_AnyWindow, ImGuiFocusedFlags_AnyWindow flags
+  (See Breaking Changes). Added to demo. (#1382)
+- Window: Added SetNextWindowBgAlpha() helper. Particularly helpful since the legacy 5-parameters
+  version of Begin() has been marked as obsolete in 1.53. (#1567)
+- Window: Fixed SetNextWindowContentSize() with 0.0f on Y axis (or SetNextWindowContentWidth())
+  overwriting the contents size. Got broken on Dec 10 (1.53). (#1363)
 - ArrowButton: Added ArrowButton() given a cardinal direction (e.g. ImGuiDir_Left).
 - InputText: Added alternative clipboard shortcuts: Shift+Delete (cut), CTRL+Insert (copy), Shift+Insert (paste). (#1541)
-- InputText: Fixed losing Cursor X position when clicking outside on an item that's submitted after the InputText(). It was only noticeable when restoring focus programmatically. (#1418, #1554)
-- InputText: Added ImGuiInputTextFlags_CharsScientific flag to also allow 'e'/'E' for input of values using scientific notation. Automatically used by InputFloat.
+- InputText: Fixed losing Cursor X position when clicking outside on an item that's submitted
+  after the InputText(). It was only noticeable when restoring focus programmatically. (#1418, #1554)
+- InputText: Added ImGuiInputTextFlags_CharsScientific flag to also allow 'e'/'E' for input of values
+  using scientific notation. Automatically used by InputFloat.
 - Style: Default style is now StyleColorsDark(), instead of the old StyleColorsClassic(). (#707)
 - Style: Enable window border by default. (#707)
-- Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding, ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181)
+- Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding,
+  ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181)
 - Style: Added style.MouseCursorScale help when using the software mouse cursor facility. (#939).
 - Style: Close button nows display a cross before hovering. Fixed cross positioning being a little off. Uses button colors for highlight when hovering. (#707)
 - Popup: OpenPopup() Always reopen existing pop-ups. (Removed imgui_internal.h's OpenPopupEx() which was used for this.) (#1497, #1533).
 - Popup: BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick() all react on mouse release instead of mouse press. (~#439)
-- Popup: Better handling of user mistakenly calling OpenPopup() every frame (with reopen_existing option). The error will now be more visible and easier to understand. (#1497)
+- Popup: Better handling of user mistakenly calling OpenPopup() every frame (with the 'reopen_existing' option).
+  The error will now be more visible and easier to understand. (#1497)
 - Popup: BeginPopup(): Exposed extra_flags parameter that are passed through to Begin(). (#1533)
-- Popup: BeginPopupModal: fixed the conditional test for SetNextWindowPos() which was polling the wrong window, which in practice made the test succeed all the time.
+- Popup: BeginPopupModal: fixed the conditional test for SetNextWindowPos() which was polling
+  the wrong window, which in practice made the test succeed all the time.
 - Tooltip: BeginTooltip() sets ImGuiWindowFlags_NoInputs flag.
-- Scrollbar: Fixed ScrollbarY enable test after ScrollbarX has been enabled being a little off (small regression from Nov 2017). (#1574)
-- Scrollbar: Fixed ScrollbarX enable test subtracting WindowPadding.x (this has been there since the addition of horizontal scroll bar!).
+- Scrollbar: Fixed ScrollbarY enable test after ScrollbarX has been enabled being a little
+  off (small regression from Nov 2017). (#1574)
+- Scrollbar: Fixed ScrollbarX enable test subtracting WindowPadding.x (this has been there
+  since the addition of horizontal scroll bar!).
 - Columns: Clear offsets data when columns count changed. (#1525)
 - Columns: Fixed a memory leak of ImGuiColumnsSet's Columns vector. (#1529) [@unprompted]
 - Columns: Fixed resizing a window very small breaking some columns positioning (broken in 1.53).
-- Columns: The available column extent takes consideration of the right-most clipped pixel, so the right-most column may look a little wider but will contain the same amount of visible contents.
+- Columns: The available column extent takes consideration of the right-most clipped pixel,
+  so the right-most column may look a little wider but will contain the same amount of visible contents.
 - MenuBar: Fixed menu bar pushing a clipping rect outside of its allocated bound (usually unnoticeable).
 - TreeNode: nodes with the ImGuiTreeNodeFlags_Leaf flag correctly disable highlight when DragDrop is active. (#143, #581)
 - Drag and Drop: Increased payload type string to 32 characters instead of 8. (#143)
 - Drag and Drop: TreeNode as drop target displays rectangle over full frame. (#1597, #143)
 - DragFloat: Fix/workaround for backends which do not preserve a valid mouse position when dragged out of bounds. (#1559)
 - InputFloat: Allow inputing value using scientific notation e.g. "1e+10".
-- InputDouble: Added InputDouble() function. We use a format string instead of a decimal_precision parameter to also for "%e" and variants. (#1011)
+- InputDouble: Added InputDouble() function. We use a format string instead of a 'decimal_precision'
+  parameter to also for "%e" and variants. (#1011)
 - Slider, Combo: Use ImGuiCol_FrameBgHovered color when hovered. (#1456) [@stfx]
-- Combo: BeginCombo(): Added ImGuiComboFlags_NoArrowButton to disable the arrow button and only display the wide value preview box.
-- Combo: BeginCombo(): Added ImGuiComboFlags_NoPreview to disable the preview and only display a square arrow button.
+- Combo: BeginCombo(): Added ImGuiComboFlags_NoArrowButton to disable the arrow button and
+  only display the wide value preview box.
+- Combo: BeginCombo(): Added ImGuiComboFlags_NoPreview to disable the preview and only
+  display a square arrow button.
 - Combo: Arrow button isn't displayed over frame background so its blended color matches other buttons. Left side of the button isn't rounded.
 - PlotLines: plot a flat line if scale_min==scale_max. (#1621)
-- Fonts: Changed DisplayOffset.y to defaults to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer.
-  If you were adding or subtracting (not assigning) to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. (#1619)
+- Fonts: Changed DisplayOffset.y to defaults to 0 instead of +1. Fixed rounding of Ascent/Descent
+  to match TrueType renderer. If you were adding or subtracting (not assigning) to ImFont::DisplayOffset
+  check if your fonts are correctly aligned vertically. (#1619)
 - Fonts: Updated stb_truetype from 1.14 to stb_truetype 1.19. (w/ include fix from some platforms #1622)
 - Fonts: Added optional FreeType rasterizer in misc/freetype. Moved from imgui_club repo. (#618) [@Vuhdo, @mikesart, @ocornut]
 - Fonts: Moved extra_fonts/ to misc/fonts/.
 - ImFontAtlas: Fixed cfg.MergeMode not reusing existing glyphs if available (always overwrote).
-- ImFontAtlas: Handle stb_truetype stbtt_InitFont() and stbtt_PackBegin() possible failures more gracefully, GetTexDataAsRGBA32() won't crash during conversion. (#1527)
-- ImFontAtlas: Moved mouse cursor data out of ImGuiContext, fix drawing them with multiple contexts. Also remove the last remaining undesirable dependency on ImGui in imgui_draw.cpp. (#939)
-- ImFontAtlas: Added ImFontAtlasFlags_NoPowerOfTwoHeight flag to disable padding font height to nearest power of two. (#1613)
-- ImFontAtlas: Added ImFontAtlasFlags_NoMouseCursors flag to disable baking software mouse cursors, mostly to save texture memory on very low end hardware. (#1613)
-- ImDrawList: Fixed AddRect() with anti-aliasing disabled (lower-right corner pixel was often missing, rounding looks a little better.) (#1646)
+- ImFontAtlas: Handle stb_truetype stbtt_InitFont() and stbtt_PackBegin() possible failures
+  more gracefully, GetTexDataAsRGBA32() won't crash during conversion. (#1527)
+- ImFontAtlas: Moved mouse cursor data out of ImGuiContext, fix drawing them with multiple contexts.
+  Also remove the last remaining undesirable dependency on ImGui in imgui_draw.cpp. (#939)
+- ImFontAtlas: Added ImFontAtlasFlags_NoPowerOfTwoHeight flag to disable padding font height
+  to nearest power of two. (#1613)
+- ImFontAtlas: Added ImFontAtlasFlags_NoMouseCursors flag to disable baking software mouse cursors,
+  mostly to save texture memory on very low end hardware. (#1613)
+- ImDrawList: Fixed AddRect() with anti-aliasing disabled (lower-right corner pixel was often
+  missing, rounding looks a little better.) (#1646)
 - ImDrawList: Added CloneOutput() helper to facilitate the cloning of ImDrawData or ImDrawList for multi-threaded rendering.
-- Misc: Functions passed to libc qsort are explicitly marked cdecl to support compiling with vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul]
-- Misc: ImVec2: added [] operator. This is becoming desirable for some code working of either axes independently. Better adding it sooner than later.
+- Misc: Functions passed to libc qsort are explicitly marked cdecl to support compiling with
+  vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul]
+- Misc: ImVec2: added [] operator. This is becoming desirable for some code working of either
+  axes independently. Better adding it sooner than later.
 - Misc: NewFrame(): Added an assert to detect incorrect filling of the io.KeyMap[] array earlier. (#1555)
 - Misc: Added IM_OFFSETOF() helper in imgui.h (previously was in imgui_internal.h)
 - Misc: Added IM_NEW(), IM_DELETE() helpers in imgui.h (previously were in imgui_internal.h)
@@ -4692,7 +4723,8 @@ Other Changes:
 - Examples: Using Dark theme by default. (#707). Tweaked demo code.
 - Examples: Added support for horizontal mouse wheel for API that allows it. (#1463) [@tseeker]
 - Examples: All examples now setup the io.BackendFlags to signify they can honor mouse cursors, gamepad, etc.
-- Examples: DirectX10: Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that was left in DX10 example but removed in 1.47 (Nov 2015) in every other backends. (#1733)
+- Examples: DirectX10: Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that
+  was left in DX10 example but removed in 1.47 (Nov 2015) in every other backends. (#1733)
 - Examples: DirectX12: Added DirectX 12 example. (#301) [@jdm3]
 - Examples: OpenGL3+GLFW,SDL: Changed GLSL shader version from 330 to 150. (#1466, #1504)
 - Examples: OpenGL3+GLFW,SDL: Added a way to override the GLSL version string in the Init function. (#1466, #1504).
@@ -4706,11 +4738,13 @@ Other Changes:
 - Examples: GLFW: Added support for mouse cursor shapes (the diagonal resize cursors are unfortunately not supported by GLFW at the moment. (#1495)
 - Examples: GLFW: Don't attempt to change the mouse cursor input mode if it is set to GLFW_CURSOR_DISABLED by the application. (#1202) [@PhilCK]
 - Examples: SDL: Added support for mouse cursor shapes. (#1626) [@olls]
-- Examples: SDL: Using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging (SDL 2.0.4+ only, otherwise using SDL_WINDOW_INPUT_FOCUS instead of previously SDL_WINDOW_MOUSE_FOCUS). (#1559)
+- Examples: SDL: Using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging
+  (SDL 2.0.4+ only, otherwise using SDL_WINDOW_INPUT_FOCUS instead of previously SDL_WINDOW_MOUSE_FOCUS). (#1559)
 - Examples: SDL: Enabled vsync by default so people don't come at us when the examples are running at 2000 FPS and burning a CPU core.
 - Examples: SDL: Using SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency() to handle frame-rate over 1000 FPS properly. (#996)
 - Examples: SDL: Using scan-code exclusively instead of a confusing mixture of scan-codes and key-codes.
-- Examples: SDL: Visual Studio: Added .vcxproj file. Using %SDL2_DIR% in the default .vcxproj and build files instead of %SDL_DIR%, the earlier being more standard.
+- Examples: SDL: Visual Studio: Added .vcxproj file. Using %SDL2_DIR% in the default .vcxproj
+  and build files instead of %SDL_DIR%, the earlier being more standard.
 - Examples: Vulkan: Visual Studio: Added .vcxproj file.
 - Examples: Apple: Fixed filenames in OSX xcode project. Various other Mac friendly fixes. [@gerryhernandez etc.]
 - Examples: Visual Studio: Disabled extraneous function-level check in Release build.
@@ -4756,41 +4790,63 @@ Other Changes:
   - See ImGuiDragDropFlags for various options.
   - The ColorEdit4() and ColorButton() widgets now support Drag and Drop.
   - The API is tagged as Beta as it still may be subject to small changes.
-- Drag and Drop: When drag and drop is active, tree nodes and collapsing header can be opened by hovering on them for 0.7 seconds.
-- Renamed io.OSXBehaviors to io.OptMacOSXBehaviors. Should not affect users as the compile-time default is usually enough. (#473, #650)
+- Drag and Drop: When drag and drop is active, tree nodes and collapsing header can be opened
+  by hovering on them for 0.7 seconds.
+- Renamed io.OSXBehaviors to io.OptMacOSXBehaviors. Should not affect users as the compile-time
+  default is usually enough. (#473, #650)
 - Style: Added StyleColorsDark() style. (#707) [@dougbinks]
 - Style: Added StyleColorsLight() style. Best used with frame borders + thicker font than the default font. (#707)
 - Style: Added style.PopupRounding setting. (#1112)
-- Style: Added style.FrameBorderSize, style.WindowBorderSize, style.PopupBorderSize. Removed ImGuiWindowFlags_ShowBorders window flag!
+- Style: Added style.FrameBorderSize, style.WindowBorderSize, style.PopupBorderSize.
+  Removed ImGuiWindowFlags_ShowBorders window flag!
   Borders are now fully set up in the ImGuiStyle structure. Use ImGui::ShowStyleEditor() to look them up. (#707, fix #819, #1031)
 - Style: Various small changes to the classic style (most noticeably, buttons are now using blue shades). (#707)
 - Style: Renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg.
 - Style: Renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding.
 - Style: Removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency. (#707)
 - Style: Made the ScaleAllSizes() helper rounds down every values so they are aligned on integers.
-- Focus: Added SetItemDefaultFocus(), which in the current (master) branch behave the same as doing `if (IsWindowAppearing()) SetScrollHere()`.
-  In the navigation branch this will also set the default focus. Prefer using this when creating combo boxes with `BeginCombo()` so your code will be forward-compatible with gamepad/keyboard navigation features. (#787)
-- Combo: Pop-up grows horizontally to accommodate for contents that is larger then the parent combo button.
-- Combo: Added BeginCombo()/EndCombo() API which allows use to submit content of any form and manage your selection state without relying on indices.
-- Combo: Added ImGuiComboFlags_PopupAlignLeft flag to BeginCombo() to prioritize keeping the pop-up on the left side (for small-button-looking combos).
-- Combo: Added ImGuiComboFlags_HeightSmall, ImGuiComboFlags_HeightLarge, ImGuiComboFlags_HeightLargest to easily provide desired pop-up height.
-- Combo: You can use SetNextWindowSizeConstraints() before BeginCombo() to specify specific pop-up width/height constraints.
+- Focus: Added SetItemDefaultFocus(), which in the current (master) branch behave the same
+  as doing `if (IsWindowAppearing()) SetScrollHere()`. In the navigation branch this will also
+  set the default focus. Prefer using this when creating combo boxes with `BeginCombo()` so your
+  code will be forward-compatible with gamepad/keyboard navigation features. (#787)
+- Combo: Pop-up grows horizontally to accommodate for contents that is larger then the parent
+  combo button.
+- Combo: Added BeginCombo()/EndCombo() API which allows use to submit content of any form and
+  manage your selection state without relying on indices.
+- Combo: Added ImGuiComboFlags_PopupAlignLeft flag to BeginCombo() to prioritize keeping the
+  pop-up on the left side (for small-button-looking combos).
+- Combo: Added ImGuiComboFlags_HeightSmall, ImGuiComboFlags_HeightLarge, ImGuiComboFlags_HeightLargest
+  to easily provide desired pop-up height.
+- Combo: You can use SetNextWindowSizeConstraints() before BeginCombo() to specify specific
+  pop-up width/height constraints.
 - Combo: Offset popup position by border size so that a double border isn't so visible. (#707)
 - Combo: Recycling windows by using a stack number instead of a unique id, wasting less memory (like menus do).
 - InputText: Added ImGuiInputTextFlags_NoUndoRedo flag. (#1506, #1508) [@ibachar]
-- Window: Fixed auto-resize allocating too much space for scrollbar when SizeContents is bigger than maximum window size (fixes c0547d3). (#1417)
-- Window: Child windows with MenuBar use regular WindowPadding.y so layout look consistent as child or as a regular window.
-- Window: Begin(): Fixed appending into a child window with a second Begin() from a different window stack querying the wrong window for the window->Collapsed test.
-- Window: Calling IsItemActive(), IsItemHovered() etc. after a call to Begin() provides item data for the title bar, so you can easily test if the title bar is being hovered, etc. (#823)
+- Window: Fixed auto-resize allocating too much space for scrollbar when SizeContents is
+  bigger than maximum window size (fixes c0547d3). (#1417)
+- Window: Child windows with MenuBar use regular WindowPadding.y so layout look consistent as
+  child or as a regular window.
+- Window: Begin(): Fixed appending into a child window with a second Begin() from a different
+  window stack querying the wrong window for the window->Collapsed test.
+- Window: Calling IsItemActive(), IsItemHovered() etc. after a call to Begin() provides item
+  data for the title bar, so you can easily test if the title bar is being hovered, etc. (#823)
 - Window: Made it possible to use SetNextWindowPos() on a child window.
-- Window: Fixed a one frame glitch. When an appearing window claimed the focus themselves, the title bar wouldn't use the focused color for one frame.
-- Window: Added ImGuiWindowFlags_ResizeFromAnySide flag to resize from any borders or from the lower-left corner of a window. This requires your backend to honor GetMouseCursor() requests for full usability. (#822)
+- Window: Fixed a one frame glitch. When an appearing window claimed the focus themselves, the
+  title bar wouldn't use the focused color for one frame.
+- Window: Added ImGuiWindowFlags_ResizeFromAnySide flag to resize from any borders or from the
+  lower-left corner of a window. This requires your backend to honor GetMouseCursor() requests
+  for full usability. (#822)
 - Window: Sizing fixes when using SetNextWindowSize() on individual axises.
-- Window: Hide new window for one frame until they calculate their size. Also fixes SetNextWindowPos() given a non-zero pivot. (#1694)
+- Window: Hide new window for one frame until they calculate their size.
+  Also fixes SetNextWindowPos() given a non-zero pivot. (#1694)
 - Window: Made mouse wheel scrolling accommodate better to windows that are smaller than the scroll step.
-- Window: SetNextWindowContentSize() adjust for the size of decorations (title bar/menu bar), but _not_ for borders are we consistently make borders not affect layout.
-  If you need a non-child window of an exact size with border enabled but zero window padding, you'll need to accommodate for the border size yourself.
-- Window: Using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. (#1380, #1502)
+- Window: SetNextWindowContentSize() adjust for the size of decorations (title bar/menu bar),
+  but _not_ for borders are we consistently make borders not affect layout.
+  If you need a non-child window of an exact size with border enabled but zero window padding,
+  you'll need to accommodate for the border size yourself.
+- Window: Using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel
+  event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar
+  are also set. (#1380, #1502)
 - Window: Active Modal window always set the WantCaptureKeyboard flag. (#744)
 - Window: Moving window doesn't use accumulating MouseDelta so straying out of imgui boundaries keeps moved imgui window at the same cursor-relative position.
 - IsWindowFocused(): Added ImGuiFocusedFlags_ChildWindows flag to include child windows in the focused test. (#1382).
@@ -4799,39 +4855,52 @@ Other Changes:
 - IsWindowHovered(): Added ImGuiHoveredFlags_RootWindow flag to start hovered test from the root (top-most) window. The combination of both flags obsoletes IsRootWindowOrAnyChildHovered(). (#1382)
 - IsWindowHovered(): Fixed return value when an item is active to use the same logic as IsItemHovered(). (#1382, #1404)
 - IsWindowHovered(): Always return true when current window is being moved. (#1382)
-- Scrollbar: Fixed issues with vertical scrollbar flickering/appearing, typically when manually resizing and using a pattern of filling available height (e.g. full sized BeginChild).
+- Scrollbar: Fixed issues with vertical scrollbar flickering/appearing, typically when manually
+  resizing and using a pattern of filling available height (e.g. full sized BeginChild).
 - Scrollbar: Minor graphical fix for when scrollbar don't have enough visible space to display the full grab.
-- Scrolling: Fixed padding and scrolling asymmetry where lower/right sides of a window wouldn't use WindowPadding properly + causing minor scrolling glitches.
+- Scrolling: Fixed padding and scrolling asymmetry where lower/right sides of a window wouldn't
+  use WindowPadding properly + causing minor scrolling glitches.
 - Tree: TreePush with zero arguments was ambiguous. Resolved by making it call TreePush(const void*). [@JasonWilkins]
 - Tree: Renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. (#600, #1330)
 - MenuBar: Fixed minor rendering issues on the right size when resizing a window very small and using rounded window corners.
-- MenuBar: better software clipping to handle small windows, in particular child window don't have minimum constraints so we need to render clipped menus better.
+- MenuBar: better software clipping to handle small windows, in particular child window don't have
+  minimum constraints so we need to render clipped menus better.
 - BeginMenu(): Tweaked the Arrow/Triangle displayed on child menu items.
-- Columns: Clipping columns borders on Y axis on CPU because some Linux GPU drivers appears to be unhappy with triangle spanning large regions. (#125)
-- Columns: Added ImGuiColumnsFlags_GrowParentContentsSize to internal API to restore old content sizes behavior (may be obsolete). (#1444, #125)
-- Columns: Columns width is no longer lost when dragging a column to the right side of the window, until releasing the mouse button you have a chance to save them. (#1499, #125). [@ggtucker]
+- Columns: Clipping columns borders on Y axis on CPU because some Linux GPU drivers appears to
+  be unhappy with triangle spanning large regions. (#125)
+- Columns: Added ImGuiColumnsFlags_GrowParentContentsSize to internal API to restore old content
+  sizes behavior (may be obsolete). (#1444, #125)
+- Columns: Columns width is no longer lost when dragging a column to the right side of the window,
+  until releasing the mouse button you have a chance to save them. (#1499, #125). [@ggtucker]
 - Columns: Fixed dragging when using a same of columns multiple times in the frame. (#125)
 - Indent(), Unindent(): Allow passing negative values.
 - ColorEdit4(): Made IsItemActive() return true when picker pop-up is active. (#1489)
 - ColorEdit4(): Tweaked tooltip so that the color button aligns more correctly with text.
-- ColorEdit4(): Support drag and drop. Color buttons can be used as drag sources, and ColorEdit widgets as drag targets. (#143)
-- ColorPicker4(): Fixed continuously returning true when holding mouse button on the sat/value/alpha locations. We only return true on value change. (#1489)
-- NewFrame(): using literal strings in the most-frequently firing IM_ASSERT expressions to increase the odd of programmers seeing them (especially those who don't use a debugger).
-- NewFrame() now asserts if neither Render or EndFrame have been called. Exposed EndFrame(). Made it legal to call EndFrame() more than one. (#1423)
+- ColorEdit4(): Support drag and drop. Color buttons can be used as drag sources, and ColorEdit
+  widgets as drag targets. (#143)
+- ColorPicker4(): Fixed continuously returning true when holding mouse button on the sat/value/alpha
+  locations. We only return true on value change. (#1489)
+- NewFrame(): using literal strings in the most-frequently firing IM_ASSERT expressions to
+  increase the odd of programmers seeing them (especially those who don't use a debugger).
+- NewFrame() now asserts if neither Render or EndFrame have been called. Exposed EndFrame().
+  Made it legal to call EndFrame() more than one. (#1423)
 - ImGuiStorage: Added BuildSortByKey() helper to rebuild storage from scratch.
 - ImFont: Added GetDebugName() helper.
 - ImFontAtlas: Added missing Thai punctuation in the GetGlyphRangesThai() ranges. (#1396) [@nProtect]
 - ImDrawList: Removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Anti-aliasing is controlled via the regular style.AntiAliased flags.
 - ImDrawList: Added ImDrawList::AddImageRounded() helper. (#845) [@thedmd]
 - ImDrawList: Refactored to make ImDrawList independent of ImGui. Removed static variable in PathArcToFast() which caused linking issues to some.
-- ImDrawList: Exposed ImDrawCornerFlags, replaced occurrences of ~0 with an explicit ImDrawCornerFlags_All. NB: Inversed BotLeft (prev 1<<3, now 1<<2) and BotRight (prev 1<<2, now 1<<3).
+- ImDrawList: Exposed ImDrawCornerFlags, replaced occurrences of ~0 with an explicit ImDrawCornerFlags_All.
+  NB: Inversed BotLeft (prev 1<<3, now 1<<2) and BotRight (prev 1<<2, now 1<<3).
 - ImVector: Added ImVector::push_front() helper.
 - ImVector: Added ImVector::contains() helper.
 - ImVector: insert() uses grow_capacity() instead of using grow policy inconsistent with push_back().
 - Internals: Remove requirement to define IMGUI_DEFINE_PLACEMENT_NEW to use the IM_PLACEMENT_NEW macro. (#1103)
-- Internals: ButtonBehavior: Fixed ImGuiButtonFlags_NoHoldingActiveID flag from incorrectly setting the ActiveIdClickOffset field.
-  This had no known effect within imgui code but could have affected custom drag and drop patterns. And it is more correct this way! (#1418)
-- Internals: ButtonBehavior: Fixed ImGuiButtonFlags_AllowOverlapMode to avoid temporarily activating widgets on click before they have been correctly double-hovered. (#319, #600)
+- Internals: ButtonBehavior: Fixed ImGuiButtonFlags_NoHoldingActiveID flag from incorrectly
+  setting the ActiveIdClickOffset field. This had no known effect within imgui code but could have
+  affected custom drag and drop patterns. And it is more correct this way! (#1418)
+- Internals: ButtonBehavior: Fixed ImGuiButtonFlags_AllowOverlapMode to avoid temporarily activating
+widgets on click before they have been correctly double-hovered. (#319, #600)
 - Internals: Added SplitterBehavior() helper. (#319)
 - Internals: Added IM_NEW(), IM_DELETE() helpers. (#484, #504, #1517)
 - Internals: Basic refactor of the settings API which now allows external elements to be loaded/saved.
@@ -4840,9 +4909,11 @@ Other Changes:
 - Demo: Renamed the emblematic ShowTestWindow() function to ShowDemoWindow().
 - Demo: Style Editor: Added a "Simplified settings" sections with check-boxes for border size and frame rounding. (#707, #1019)
 - Demo: Style Editor: Added combo box to select stock styles and select current font when multiple are loaded. (#707)
-- Demo: Style Editor: Using local storage so Save/Revert button makes more sense without code passing its storage. Added horizontal scroll bar. Fixed Save/Revert button to be always accessible. (#1211)
+- Demo: Style Editor: Using local storage so Save/Revert button makes more sense without code passing
+  its storage. Added horizontal scroll bar. Fixed Save/Revert button to be always accessible. (#1211)
 - Demo: Console: Fixed context menu issue. (#1404)
-- Demo: Console: Fixed incorrect positioning which was hidden by a minor scroll issue (this would affect people who copied the Console code as is).
+- Demo: Console: Fixed incorrect positioning which was hidden by a minor scroll issue (this would
+  affect people who copied the Console code as is).
 - Demo: Constrained Resize: Added more test cases. (#1417)
 - Demo: Custom Rendering: Fixed clipping rectangle extruding out of parent window.
 - Demo: Layout: Removed unnecessary and misleading BeginChild/EndChild calls.
@@ -4864,24 +4935,41 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 
 Breaking Changes:
 
-- IO: `io.MousePos` needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing, instead of ImVec2(-1,-1) as previously) This is needed so we can clear `io.MouseDelta` field when the mouse is made available again.
-- Renamed `AlignFirstTextHeightToWidgets()` to `AlignTextToFramePadding()`. Kept inline redirection function (will obsolete).
-- Obsoleted the legacy 5 parameters version of Begin(). Please avoid using it. If you need a transparent window background, uses `PushStyleColor()`. The old size parameter there was also misleading and equivalent to calling `SetNextWindowSize(size, ImGuiCond_FirstTimeEver)`. Kept inline redirection function (will obsolete).
-- Obsoleted `IsItemHoveredRect()`, `IsMouseHoveringWindow()` in favor of using the newly introduced flags of `IsItemHovered()` and `IsWindowHovered()`. Kept inline redirection function (will obsolete). (#1382)
-- Obsoleted 'SetNextWindowPosCenter()' in favor of using 1SetNextWindowPos()` with a pivot value which allows to do the same and more. Keep inline redirection function.
-- Removed `IsItemRectHovered()`, `IsWindowRectHovered()` recently introduced in 1.51 which were merely the more consistent/correct names for the above functions which are now obsolete anyway. (#1382)
-- Changed `IsWindowHovered()` default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. (#1382)
-- Renamed imconfig.h's `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS` to `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS` for consistency.
+- IO: `io.MousePos` needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing,
+  instead of ImVec2(-1,-1) as previously) This is needed so we can clear `io.MouseDelta` field when
+  the mouse is made available again.
+- Renamed `AlignFirstTextHeightToWidgets()` to `AlignTextToFramePadding()`.
+  Kept inline redirection function (will obsolete).
+- Obsoleted the legacy 5 parameters version of Begin(). Please avoid using it. If you need a
+  transparent window background, uses `PushStyleColor()`. The old size parameter there was also
+  misleading and equivalent to calling `SetNextWindowSize(size, ImGuiCond_FirstTimeEver)`.
+  Kept inline redirection function (will obsolete).
+- Obsoleted `IsItemHoveredRect()`, `IsMouseHoveringWindow()` in favor of using the newly introduced
+  flags of `IsItemHovered()` and `IsWindowHovered()`. Kept inline redirection function (will obsolete). (#1382)
+- Obsoleted 'SetNextWindowPosCenter()' in favor of using 1SetNextWindowPos()` with a pivot value which
+  allows to do the same and more. Keep inline redirection function.
+- Removed `IsItemRectHovered()`, `IsWindowRectHovered()` recently introduced in 1.51 which were merely
+  the more consistent/correct names for the above functions which are now obsolete anyway. (#1382)
+- Changed `IsWindowHovered()` default parameters behavior to return false if an item is active in
+  another window (e.g. click-dragging item from another window to this window). You can use the newly
+  introduced IsWindowHovered() flags to requests this specific behavior if you need it. (#1382)
+- Renamed imconfig.h's `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS`
+  to `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS` for consistency.
 - Renamed ImFont::Glyph to ImFontGlyph. Kept redirection typedef (will obsolete).
 
 Other Changes:
 
 - ProgressBar: fixed rendering when straddling rounded area. (#1296)
-- SliderFloat, DragFloat: Using scientific notation e.g. "%.1e" in the displayed format string doesn't mistakenly trigger rounding of the value. [@MomentsInGraphics]
-- Combo, InputFloat, InputInt: Made the small button on the right side align properly with the equivalent colored button of ColorEdit4().
-- IO: Tweaked logic for `io.WantCaptureMouse` so it now outputs false when e.g. hovering over void while an InputText() is active. (#621) [@pdoane]
-- IO: Fixed `io.WantTextInput` from mistakenly outputting true when an activated Drag or Slider was previously turned into an InputText(). (#1317)
-- Misc: Added flags to `IsItemHovered()`, `IsWindowHovered()` to access advanced hovering-test behavior. Generally useful for pop-ups and drag and drop behaviors: (relates to ~#439, #1013, #143, #925)
+- SliderFloat, DragFloat: Using scientific notation e.g. "%.1e" in the displayed format string doesn't
+  mistakenly trigger rounding of the value. [@MomentsInGraphics]
+- Combo, InputFloat, InputInt: Made the small button on the right side align properly with the
+  equivalent colored button of ColorEdit4().
+- IO: Tweaked logic for `io.WantCaptureMouse` so it now outputs false when e.g. hovering over void
+  while an InputText() is active. (#621) [@pdoane]
+- IO: Fixed `io.WantTextInput` from mistakenly outputting true when an activated Drag or Slider was
+  previously turned into an InputText(). (#1317)
+- Misc: Added flags to `IsItemHovered()`, `IsWindowHovered()` to access advanced hovering-test behavior.
+  Generally useful for pop-ups and drag and drop behaviors: (relates to ~#439, #1013, #143, #925)
   - `ImGuiHoveredFlags_AllowWhenBlockedByPopup`
   - `ImGuiHoveredFlags_AllowWhenBlockedByActiveItem`
   - `ImGuiHoveredFlags_AllowWhenOverlapped`
@@ -4892,54 +4980,80 @@ Other Changes:
 - CheckBox: Now rendering a tick mark instead of a full square.
 - ColorEdit4: Added "Copy as..." option in context menu. (#346)
 - ColorPicker: Improved ColorPicker hue wheel color interpolation. (#1313) [@thevaber]
-- ColorButton: Reduced bordering artifact that would be particularly visible with an opaque Col_FrameBg and FrameRounding enabled.
-- ColorButton: Fixed rendering color button with a checkerboard if the transparency comes from the global style.Alpha and not from the actual source color.
-- TreeNode: Added `ImGuiTreeNodeFlags_FramePadding` flag to conveniently create a tree node with full padding at the beginning of a line, without having to call `AlignTextToFramePadding()`.
+- ColorButton: Reduced bordering artifact that would be particularly visible with an opaque
+  Col_FrameBg and FrameRounding enabled.
+- ColorButton: Fixed rendering color button with a checkerboard if the transparency comes from the global
+  style.Alpha and not from the actual source color.
+- TreeNode: Added `ImGuiTreeNodeFlags_FramePadding` flag to conveniently create a tree node with full
+  padding at the beginning of a line, without having to call `AlignTextToFramePadding()`.
 - Trees: Fixed calling `SetNextTreeNodeOpen()` on a collapsed window leaking to the first tree node item of the next frame.
-- Layout: Horizontal layout is automatically enforced in a menu bar, so you can use non-MenuItem elements without calling SameLine().
-- Separator: Output a vertical separator when used inside a menu bar (or in general when horizontal layout is active, but that isn't exposed yet!).
+- Layout: Horizontal layout is automatically enforced in a menu bar, so you can use non-MenuItem elements
+  without calling SameLine().
+- Separator: Output a vertical separator when used inside a menu bar (or in general when horizontal layout
+  is active, but that isn't exposed yet!).
 - Window: Added `IsWindowAppearing()` helper (helpful e.g. as a condition before initializing some of your own things.).
 - Window: Added pivot parameter to `SetNextWindowPos()`, making it possible to center or right align a window. Obsoleted `SetNextWindowPosCenter()`.
 - Window: Fixed title bar color of top-most window under a modal window.
 - Window: Fixed not being able to move a window by clicking on one of its child window. (#1337, #635)
-- Window: Fixed `Begin()` auto-fit calculation code that predict the presence of a scrollbar so it works better when window size constraints are used.
-- Window: Fixed calling `Begin()` more than once per frame setting `window_just_activated_by_user` which in turn would set enable the Appearing condition for that frame.
-- Window: The implicit "Debug" window now uses a "Debug##Default" identifier instead of "Debug" to allow user creating a window called "Debug" without losing their custom flags.
-- Window: Made the `ImGuiWindowFlags_NoMove` flag properly inherited from parent to child. In a setup with ParentWindow (no flag) -> Child (NoMove) -> SubChild (no flag), the user won't be able to move the parent window by clicking on SubChild. (#1381)
+- Window: Fixed `Begin()` auto-fit calculation code that predict the presence of a scrollbar so it works
+  better when window size constraints are used.
+- Window: Fixed calling `Begin()` more than once per frame setting `window_just_activated_by_user` which
+  in turn would set enable the Appearing condition for that frame.
+- Window: The implicit "Debug" window now uses a "Debug##Default" identifier instead of "Debug" to allow
+  user creating a window called "Debug" without losing their custom flags.
+- Window: Made the `ImGuiWindowFlags_NoMove` flag properly inherited from parent to child. In a setup
+  with ParentWindow (no flag) -> Child (NoMove) -> SubChild (no flag), the user won't be able to move
+  the parent window by clicking on SubChild. (#1381)
 - Popups: Pop-ups can be closed with a right-click anywhere, without altering focus under the pop-up. (~#439)
-- Popups: `BeginPopupContextItem()`, `BeginPopupContextWindow()` are now setup to allow reopening a context menu by right-clicking again. (~#439)
+- Popups: `BeginPopupContextItem()`, `BeginPopupContextWindow()` are now setup to allow reopening
+  a context menu by right-clicking again. (~#439)
 - Popups: `BeginPopupContextItem()` now supports a NULL string identifier and uses the last item ID if available.
 - Popups: Added `OpenPopupOnItemClick()` helper which mimic `BeginPopupContextItem()` but doesn't do the BeginPopup().
 - MenuItem: Only activating on mouse release. [@Urmeli0815] (was already fixed in nav branch).
 - MenuItem: Made tick mark thicker (thick mark?).
-- MenuItem: Tweaks to be usable inside a menu bar (nb: it looks like a regular menu and thus is misleading, prefer using Button() and regular widgets in menu bar if you need to). (#1387)
+- MenuItem: Tweaks to be usable inside a menu bar (nb: it looks like a regular menu and thus is misleading,
+  prefer using Button() and regular widgets in menu bar if you need to). (#1387)
 - ImDrawList: Fixed a rare draw call merging bug which could lead to undisplayed triangles. (#1172, #1368)
-- ImDrawList: Fixed a rare bug in `ChannelsMerge()` when all contents has been clipped, leading to an extraneous draw call being created. (#1172, #1368)
+- ImDrawList: Fixed a rare bug in `ChannelsMerge()` when all contents has been clipped, leading to
+  an extraneous draw call being created. (#1172, #1368)
 - ImFont: Added `AddGlyph()` building helper for use by custom atlas builders.
-- ImFontAtlas: Added support for CustomRect API to submit custom rectangles to be packed into the atlas. You can map them as font glyphs, or use them for custom purposes.
-  After the atlas is built you can query the position of your rectangles in the texture and then copy your data there. You can use this features to create e.g. full color font-mapped icons.
-- ImFontAtlas: Fixed fall-back handling when merging fonts, if a glyph was missing from the second font input it could have used a glyph from the first one. (#1349) [@inolen]
-- ImFontAtlas: Fixed memory leak on build failure case when stbtt_InitFont failed (generally due to incorrect or supported font type). (#1391) (@Moka42)
-- ImFontConfig: Added `RasterizerMultiply` option to alter the brightness of individual fonts at rasterization time, which may help increasing readability for some.
-- ImFontConfig: Added `RasterizerFlags` to pass options to custom rasterizer (e.g. the [imgui_freetype](https://github.com/ocornut/imgui_club/tree/master/imgui_freetype) rasterizer in imgui_club has such options).
+- ImFontAtlas: Added support for CustomRect API to submit custom rectangles to be packed into the atlas.
+  You can map them as font glyphs, or use them for custom purposes.
+  After the atlas is built you can query the position of your rectangles in the texture and then copy
+  your data there. You can use this features to create e.g. full color font-mapped icons.
+- ImFontAtlas: Fixed fall-back handling when merging fonts, if a glyph was missing from the second font
+  input it could have used a glyph from the first one. (#1349) [@inolen]
+- ImFontAtlas: Fixed memory leak on build failure case when stbtt_InitFont failed (generally due to
+  incorrect or supported font type). (#1391) (@Moka42)
+- ImFontConfig: Added `RasterizerMultiply` option to alter the brightness of individual fonts at
+  rasterization time, which may help increasing readability for some.
+- ImFontConfig: Added `RasterizerFlags` to pass options to custom rasterizer (e.g. the
+  [imgui_freetype](https://github.com/ocornut/imgui_club/tree/master/imgui_freetype) rasterizer in imgui_club has such options).
 - ImVector: added resize() variant with initialization value.
-- Misc: Changed the internal name formatting of child windows identifier to use slashes (instead of dots) as separator, more readable.
+- Misc: Changed the internal name formatting of child windows identifier to use slashes
+  (instead of dots) as separator, more readable.
 - Misc: Fixed compilation with `IMGUI_DISABLE_OBSOLETE_FUNCTIONS` defined.
 - Misc: Marked all format+va_list functions with format attribute so GCC/Clang can warn about misuses.
 - Misc: Fixed compilation on NetBSD due to missing alloca.h (#1319) [@RyuKojiro]
 - Misc: Improved warnings compilation for newer versions of Clang. (#1324) (@waywardmonkeys)
-- Misc: Added `io.WantMoveMouse flags` (from Nav branch) and honored in Examples applications. Currently unused but trying to spread Examples applications code that supports it.
-- Misc: Added `IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS` support in imconfig.h to allow user reimplementing the `ImFormatString()` functions e.g. to use stb_printf(). (#1038)
-- Misc: [Windows] Fixed default Win32 `SetClipboardText()` handler leaving the Win32 clipboard handler unclosed on failure. [@pdoane]
-- Style: Added `ImGuiStyle::ScaleAllSizes(float)` helper to make it easier to have application transition e.g. from low to high DPI with a matching style.
+- Misc: Added `io.WantMoveMouse flags` (from Nav branch) and honored in Examples applications.
+  Currently unused but trying to spread Examples applications code that supports it.
+- Misc: Added `IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS` support in imconfig.h to allow user
+  reimplementing the `ImFormatString()` functions e.g. to use stb_printf(). (#1038)
+- Misc: [Windows] Fixed default Win32 `SetClipboardText()` handler leaving the Win32 clipboard
+  handler unclosed on failure. [@pdoane]
+- Style: Added `ImGuiStyle::ScaleAllSizes(float)` helper to make it easier to have application
+  transition e.g. from low to high DPI with a matching style.
 - Metrics: Draw window bounding boxes when hovering Pos/Size; List all draw layers; Trimming empty commands like Render() does.
 - Examples: OpenGL3: Save and restore sampler state. (#1145) [@nlguillemot]
 - Examples: OpenGL2, OpenGL3: Save and restore polygon mode. (#1307) [@JJscott]
 - Examples: DirectX11: Allow creating device with feature level 10 since we don't really need much for that example. (#1333)
-- Examples: DirectX9/10/12: Using the Win32 SetCapture/ReleaseCapture API to read mouse coordinates when they are out of bounds. (#1375) [@Gargaj, @ocornut]
+- Examples: DirectX9/10/12: Using the Win32 SetCapture/ReleaseCapture API to read mouse coordinates
+  when they are out of bounds. (#1375) [@Gargaj, @ocornut]
 - Tools: Fixed binary_to_compressed_c tool to return 0 when successful. (#1350) [@benvanik]
 - Internals: Exposed more helpers and unfinished features in imgui_internal.h. (use at your own risk!).
-- Internals: A bunch of internal refactoring, hopefully haven't broken anything! Merged a bunch of internal changes from the upcoming Navigation branch.
+- Internals: A bunch of internal refactoring, hopefully haven't broken anything!
+  Merged a bunch of internal changes from the upcoming Navigation branch.
 - Various tweaks, fixes and documentation changes.
 
 Beta Navigation Branch:
@@ -4948,12 +5062,16 @@ Beta Navigation Branch:
 - Nav: Added `#define IMGUI_HAS_NAV` in imgui.h to ease sharing code between both branches. (#787)
 - Nav: MainMenuBar now releases focus when user gets out of the menu layer. (#787)
 - Nav: When applying focus to a window with only menus, the menu layer is automatically activated. (#787)
-- Nav: Added `ImGuiNavInput_KeyMenu` (~Alt key) aside from ImGuiNavInput_PadMenu input as it is one differentiator of pad vs keyboard that was detrimental to the keyboard experience. Although isn't officially supported, it makes the current experience better. (#787)
+- Nav: Added `ImGuiNavInput_KeyMenu` (~Alt key) aside from ImGuiNavInput_PadMenu input as it is
+  one differentiator of pad vs keyboard that was detrimental to the keyboard experience.
+  Although isn't officially supported, it makes the current experience better. (#787)
 - Nav: Move requests now wrap vertically inside Menus and Pop-ups. (#787)
 - Nav: Allow to collapse tree nodes with NavLeft and open them with NavRight. (#787, #1079).
-- Nav: It's now possible to navigate sibling of a menu-bar while navigating inside one of their child. If a Left<>Right navigation request fails to find a match we forward the request to the root menu. (#787, #126)
+- Nav: It's now possible to navigate sibling of a menu-bar while navigating inside one of their child.
+  If a Left<>Right navigation request fails to find a match we forward the request to the root menu. (#787, #126)
 - Nav: Fixed `SetItemDefaultFocus` from stealing default focus when we are initializing default focus for a menu bar layer. (#787)
-- Nav: Support for fall-back horizontal scrolling with PadLeft/PadRight (nb: fall-back scrolling is only used to navigate windows that have no interactive items). (#787)
+- Nav: Support for fall-back horizontal scrolling with PadLeft/PadRight (nb: fall-back scrolling
+  is only used to navigate windows that have no interactive items). (#787)
 - Nav: Fixed tool-tip from being selectable in the window selection list. (#787)
 - Nav: `CollapsingHeader(bool*)` variant: fixed for `IsItemHovered()` not working properly in the nav branch. (#600, #787)
 - Nav: InputText: Fixed using Up/Down history callback feature when Nav is enabled. (#787)
@@ -4970,7 +5088,14 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 
 Breaking Changes:
 
-Work on dear imgui has been gradually resuming. It means that fixes and new features should be tackled at a faster rate than last year. However, in order to move forward with the library and get rid of some cruft, I have taken the liberty to be a little bit more aggressive than usual with API breaking changes. Read the details below and search for those names in your code! In the grand scheme of things, those changes are small and should not affect everyone, but this is technically our most aggressive release so far in term of API breakage. If you want to be extra forward-facing, you can enable `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h to disable the obsolete names/redirection.
+Work on dear imgui has been gradually resuming. It means that fixes and new features should be tackled at
+a faster rate than last year. However, in order to move forward with the library and get rid of some cruft,
+I have taken the liberty to be a little bit more aggressive than usual with API breaking changes.
+Read the details below and search for those names in your code! In the grand scheme of things,
+those changes are small and should not affect everyone, but this is technically our most aggressive
+release so far in term of API breakage.
+If you want to be extra forward-facing, you can enable `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in
+your imconfig.h to disable the obsolete names/redirection.
 
 - Renamed `IsItemHoveredRect()` to `IsItemRectHovered()`. Kept inline redirection function (will obsolete).
 - Renamed `IsMouseHoveringWindow()` to `IsWindowRectHovered()` for consistency. Kept inline redirection function (will obsolete).
@@ -4978,43 +5103,79 @@ Work on dear imgui has been gradually resuming. It means that fixes and new feat
 - Renamed `ImGuiCol_Columns***` enums to `ImGuiCol_Separator***`. Kept redirection enums (will obsolete).
 - Renamed `ImGuiSetCond***` types and enums to `ImGuiCond***`. Kept redirection enums (will obsolete).
 - Renamed `GetStyleColName()` to `GetStyleColorName()` for consistency. Unlikely to be used by end-user!
-- Added `PushStyleColor(ImGuiCol idx, ImU32 col)` overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicitly to fix.
+- Added `PushStyleColor(ImGuiCol idx, ImU32 col)` overload, which _might_ cause an "ambiguous call"
+  compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicitly to fix.
 - Marked the weird `IMGUI_ONCE_UPON_A_FRAME` helper macro as obsolete. Prefer using the more explicit `ImGuiOnceUponAFrame`.
-- Changed `ColorEdit4(const char* label, float col[4], bool show_alpha = true)` signature to `ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)`, where flags 0x01 is a safe no-op (hello dodgy backward compatibility!). The new `ColorEdit4`/`ColorPicker4` functions have lots of available flags! Check and run the demo window, under "Color/Picker Widgets", to understand the various new options.
-- Changed signature of `ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)` to `ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))`. This function was rarely used and was very dodgy (no explicit ID!).
-- Changed `BeginPopupContextWindow(bool also_over_items=true, const char* str_id=NULL, int mouse_button=1)` signature to `(const char* str_id=NULL, int mouse_button=1, bool also_over_items=true)`. This is perhaps the most aggressive change in this update, but note that the majority of users relied on default parameters completely, so this will affect only a fraction of users of this already rarely used function.
-- Removed `IsPosHoveringAnyWindow()`, which was partly broken and misleading. In the vast majority of cases, people using that function wanted to use `io.WantCaptureMouse` flag. Replaced with IM_ASSERT + comment redirecting user to `io.WantCaptureMouse`. (#1237)
+- Changed `ColorEdit4(const char* label, float col[4], bool show_alpha = true)` signature to
+  `ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)`, where flags 0x01 is a safe no-op
+  (hello dodgy backward compatibility!). The new `ColorEdit4`/`ColorPicker4` functions have lots of available flags!
+  Check and run the demo window, under "Color/Picker Widgets", to understand the various new options.
+- Changed signature of `ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)`
+  to `ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))`.
+  This function was rarely used and was very dodgy (no explicit ID!).
+- Changed `BeginPopupContextWindow(bool also_over_items=true, const char* str_id=NULL, int mouse_button=1)`
+  signature to `(const char* str_id=NULL, int mouse_button=1, bool also_over_items=true)`.
+  This is perhaps the most aggressive change in this update, but note that the majority of users relied
+  on default parameters completely, so this will affect only a fraction of users of this already rarely
+  used function.
+- Removed `IsPosHoveringAnyWindow()`, which was partly broken and misleading. In the vast majority of cases,
+  people using that function wanted to use `io.WantCaptureMouse` flag. Replaced with IM_ASSERT + a comment
+  redirecting user to `io.WantCaptureMouse`. (#1237)
 - Removed the old `ValueColor()` helpers, they are equivalent to calling `Text(label)` + `SameLine()` + `ColorButton()`.
-- Removed `ColorEditMode()` and `ImGuiColorEditMode` type in favor of `ImGuiColorEditFlags` and parameters to the various Color*() functions. The `SetColorEditOptions()` function allows to initialize default but the user can still change them with right-click context menu. Commenting out your old call to `ColorEditMode()` may just be fine!
+- Removed `ColorEditMode()` and `ImGuiColorEditMode` type in favor of `ImGuiColorEditFlags` and
+  parameters to the various Color*() functions. The `SetColorEditOptions()` function allows to
+  initialize default but the user can still change them with right-click context menu.
+  Commenting out your old call to `ColorEditMode()` may just be fine!
 
 Other Changes:
 
-- Added flags to `ColorEdit3()`, `ColorEdit4()`. The color edit widget now has a context-menu and access to the color picker. (#346)
+- Added flags to `ColorEdit3()`, `ColorEdit4()`. The color edit widget now has a context-menu
+  and access to the color picker. (#346)
 - Added flags to `ColorButton()`. (#346)
-- Added `ColorPicker3()`, `ColorPicker4()`. The API along with those of the updated `ColorEdit4()` was designed so you may use them in various situation and hopefully compose your own picker if required. There are a bunch of available flags, check the Demo window and comment for `ImGuiColorEditFlags_`. Some of the options it supports are: two color picker types (hue bar + sat/val rectangle, hue wheel + rotating sat/val triangle), display as u8 or float, lifting 0.0..1.0 constraints (currently rgba only), context menus, alpha bar, background checkerboard options, preview tooltip, basic revert. For simple use, calling the existing `ColorEdit4()` function as you did before will be enough, as you can now open the color picker from there. (#346) [@r-lyeh, @nem0, @thennequin, @dariomanesku and @ocornut]
-- Added `SetColorEditOptions()` to set default color options (e.g. if you want HSV over RGBA, float over u8, select a default picker mode etc. at startup time without a user intervention. Note that the user can still change options with the context menu unless disabled with `ImGuiColorFlags_NoOptions` or explicitly enforcing a display type/picker mode etc.).
+- Added `ColorPicker3()`, `ColorPicker4()`. (#346) [@r-lyeh, @nem0, @thennequin, @dariomanesku and @ocornut]
+  The API along with those of the updated `ColorEdit4()` was designed so you may use them in various
+  situation and hopefully compose your own picker if required. There are a bunch of available flags,
+  check the Demo window and comment for `ImGuiColorEditFlags_`.
+  Some of the options it supports are: two color picker types (hue bar + sat/val rectangle,
+  hue wheel + rotating sat/val triangle), display as u8 or float, lifting 0.0..1.0 constraints
+  (currently rgba only),  context menus, alpha bar, background checkerboard options, preview tooltip,
+  basic revert. For simple use, calling the existing `ColorEdit4()` function as you did before
+  will be enough, as you can now open the color picker from there.
+- Added `SetColorEditOptions()` to set default color options (e.g. if you want HSV over RGBA,
+  float over u8, select a default picker mode etc. at startup time without a user intervention.
+  Note that the user can still change options with the context menu unless disabled with
+  `ImGuiColorFlags_NoOptions` or explicitly enforcing a display type/picker mode etc.).
 - Added user-facing `IsPopupOpen()` function. (#891) [@mkeeter]
-- Added `GetColorU32(u32)` variant that perform the style alpha multiply without a floating-point round trip, and helps makes code more consistent when using ImDrawList APIs.
+- Added `GetColorU32(u32)` variant that perform the style alpha multiply without a floating-point
+  round trip, and helps makes code more consistent when using ImDrawList APIs.
 - Added `PushStyleColor(ImGuiCol idx, ImU32 col)` overload.
-- Added `GetStyleColorVec4(ImGuiCol idx)` which is equivalent to accessing `ImGui::GetStyle().Colors[idx]` (aka return the raw style color without alpha alteration).
-- ImFontAtlas: Added `GlyphRangesBuilder` helper class, which makes it easier to build custom glyph ranges from your app/game localization data, or add into existing glyph ranges.
+- Added `GetStyleColorVec4(ImGuiCol idx)` which is equivalent to accessing `ImGui::GetStyle().Colors[idx]`
+  (aka return the raw style color without alpha alteration).
+- ImFontAtlas: Added `GlyphRangesBuilder` helper class, which makes it easier to build custom glyph ranges
+  from your app/game localization data, or add into existing glyph ranges.
 - ImFontAtlas: Added `TexGlyphPadding` option. (#1282) [@jadwallis]
 - ImFontAtlas: Made it possible to override size of AddFontDefault() (even if it isn't really recommended!).
 - ImDrawList: Added `GetClipRectMin()`, `GetClipRectMax()` helpers.
 - Fixed Ini saving crash if the ImGuiWindowFlags_NoSavedSettings gets removed from a window after its creation (unlikely!). (#1000)
-- Fixed `PushID()`/`PopID()` from marking parent window as Accessed (which needlessly woke up the root "Debug" window when used outside of a regular window). (#747)
+- Fixed `PushID()`/`PopID()` from marking parent window as Accessed (which needlessly woke up the
+  root "Debug" window when used outside of a regular window). (#747)
 - Fixed an assert when calling `CloseCurrentPopup()` twice in a row. [@nem0]
 - Window size can be loaded from .ini data even if ImGuiWindowFlags_NoResize flag is set. (#1048, #1056)
 - Columns: Added `SetColumnWidth()`. (#913) [@ggtucker]
 - Columns: Dragging a column preserve its width by default. (#913) [@ggtucker]
 - Columns: Fixed first column appearing wider than others. (#1266)
-- Columns: Fixed allocating space on the right-most side with the assumption of a vertical scrollbar. The space is only allocated when needed. (#125, #913, #893, #1138)
-- Columns: Fixed the right-most column from registering its content width to the parent window, which led to various issues when using auto-resizing window or e.g. horizontal scrolling. (#519, #125, #913)
+- Columns: Fixed allocating space on the right-most side with the assumption of a vertical scrollbar.
+  The space is only allocated when needed. (#125, #913, #893, #1138)
+- Columns: Fixed the right-most column from registering its content width to the parent window,
+  which led to various issues when using auto-resizing window or e.g. horizontal scrolling. (#519, #125, #913)
 - Columns: Refactored some of the columns code internally toward a better API (not yet exposed) + minor optimizations. (#913) [@ggtucker, @ocornut]
-- Popups: Most pop-ups windows can be moved by the user after appearing (if they don't have explicit positions provided by caller, or e.g. sub-menu pop-up). The previous restriction was totally arbitrary. (#1252)
-- Tooltip: `SetTooltip()` is expanded immediately into a window, honoring current font / styling setting. Add internal mechanism to override tooltips. (#862)
+- Popups: Most pop-ups windows can be moved by the user after appearing (if they don't have explicit
+  positions provided by caller, or e.g. sub-menu pop-up). The previous restriction was totally arbitrary. (#1252)
+- Tooltip: `SetTooltip()` is expanded immediately into a window, honoring current font / styling setting.
+  Add internal mechanism to override tooltips. (#862)
 - PlotHistogram: bars are drawn based on zero-line, so negative values are going under. (#828)
-- Scrolling: Fixed return values of `GetScrollMaxX()`, `GetScrollMaxY()` when both scrollbars were enabled. Tweak demo to display more data. (#1271) [@degracode]
+- Scrolling: Fixed return values of `GetScrollMaxX()`, `GetScrollMaxY()` when both scrollbars were enabled.
+  Tweak demo to display more data. (#1271) [@degracode]
 - Scrolling: Fixes for Vertical Scrollbar not automatically getting enabled if enabled Horizontal Scrollbar straddle the vertical limit. (#1271, #246)
 - Scrolling: `SetScrollHere()`, `SetScrollFromPosY()`: Fixed Y scroll aiming when Horizontal Scrollbar is enabled. (#665).
 - [Windows] Clipboard: Fixed not closing Win32 clipboard on early open failure path. (#1264)
@@ -5022,7 +5183,8 @@ Other Changes:
 - Demo: Rearranged everything under Widgets in a more consistent way.
 - Demo: Columns: Added Horizontal Scrolling demo. Tweaked another Columns demo. (#519, #125, #913)
 - Examples: OpenGL: Various makefiles for MINGW, Linux. (#1209, #1229, #1209) [@fr500, @acda]
-- Examples: Enabled vsync by default in example applications, so it doesn't confuse people that the sample run at 2000+ fps and waste an entire CPU. (#1213, #1151).
+- Examples: Enabled vsync by default in example applications, so it doesn't confuse people that
+  the sample run at 2000+ fps and waste an entire CPU. (#1213, #1151).
 - Various other small fixes, tweaks, comments, optimizations.
 
 
@@ -5035,11 +5197,16 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 Breaking Changes:
 
 - Added a void* user_data parameter to Clipboard function handlers. (#875)
-- SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal.
+- SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window.
+  This was sort of always the intent and hopefully breakage should be minimal.
 - Renamed ImDrawList::PathFill() - rarely used directly - to ImDrawList::PathFillConvex() for clarity and consistency.
 - Removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
-- Style: style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc.
-- BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild().
+- Style: style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f)
+  for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc.
+- BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions
+  as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple
+  times to a same child from different locations of the stack id. If that's the case, generate an id with GetId()
+  and use it instead of passing string to BeginChild().
 
 Other Changes:
 
@@ -5049,7 +5216,8 @@ Other Changes:
 - InputText(): Fixed pressing home key on last character when it isn't a trailing \n (#588, #815)
 - InputText(): Fixed state corruption/crash bug in stb_textedit.h redo logic when exhausting undo/redo char buffer. (#715. #681)
 - InputTextMultiline(): Fixed CTRL+DownArrow moving scrolling out of bounds.
-- InputTextMultiline(): Scrollbar fix for when input and latched internal buffers differs in a way that affects vertical scrollbar existence. (#725)
+- InputTextMultiline(): Scrollbar fix for when input and latched internal buffers differs in
+  a way that affects vertical scrollbar existence. (#725)
 - ImFormatString(): Fixed an overflow handling bug with implementation of vsnprintf() that do not return -1. (#793)
 - BeginChild(const char*) now applies stack id to provided label, consistent with other widgets. (#894, #713)
 - SameLine() with explicit X position is relative to left of group/columns. (ref #746, #125, #630)
@@ -5068,7 +5236,8 @@ Other Changes:
 - Fixed PlotLines() PlotHistogram() calling with values_count == 0.
 - Fixed clicking on a window's void while staying still overzealously marking .ini settings as dirty. (#923)
 - Fixed assert triggering when a window has zero rendering but has a callback. (#810)
-- Scrollbar: Fixed rendering when sizes are negative to reduce glitches (which can happen with certain style settings and zero WindowMinSize).
+- Scrollbar: Fixed rendering when sizes are negative to reduce glitches (which can happen with
+  certain style settings and zero WindowMinSize).
 - EndGroup(): Made IsItemHovered() work when an item was activated within the group. (#849)
 - BulletText(): Fixed stopping to display formatted string after the '##' mark.
 - Closing the focused window restore focus to the first active root window in descending z-order .(part of #727)
@@ -5078,7 +5247,8 @@ Other Changes:
 - ImGuiListClipper: Fixed automatic-height calc path dumbly having user display element 0 twice. (#661, #716)
 - ImGuiListClipper: Fix to behave within column. (#661, #662, #716)
 - ImDrawList: Renamed ImDrawList::PathFill() to ImDrawList::PathFillConvex() for clarity. (BREAKING API)
-- Columns: End() avoid calling Columns(1) if no columns set is open, not sure why it wasn't the case already (pros: faster, cons: exercise less code).
+- Columns: End() avoid calling Columns(1) if no columns set is open, not sure why it wasn't the
+  case already (pros: faster, cons: exercise less code).
 - ColorButton(): Fix ColorButton showing wrong hex value for alpha. (#1068) [@codecat]
 - ColorEdit4(): better preserve inputting value out of 0..255 range, display then clamped in Hexadecimal form.
 - Shutdown() clear out some remaining pointers for sanity. (#836)
@@ -5089,7 +5259,8 @@ Other Changes:
 - ImFont: Added GetGlyphRangesThai() helper. [@nProtect]
 - ImFont: CalcWordWrapPositionA() fixed font scaling with fallback character.
 - ImFont: Calculate and store the approximate texture surface to get an idea of how costly each source font is.
-- ImFontConfig: Added GlyphOffset to explicitly offset glyphs at font build time, useful for merged fonts. Removed MergeGlyphCenterV. (BREAKING API)
+- ImFontConfig: Added GlyphOffset to explicitly offset glyphs at font build time, useful for merged fonts.
+  Removed MergeGlyphCenterV. (BREAKING API)
 - Clarified asserts in CheckStacksSize() when there is a stack mismatch.
 - Context: Support for #define-ing GImGui and IMGUI_SET_CURRENT_CONTEXT_FUNC to enable custom thread-based hackery (#586)
 - Updated stb_truetype.h to 1.14 (added OTF support, removed warnings). (#883, #976)
@@ -5111,7 +5282,8 @@ Other Changes:
 - Examples: OpenGL*: Saving/restoring active texture number (the value modified by glActiveTexture). (#1087, #1088, #1116)
 - Examples: OpenGL*: Saving/restoring separate color/alpha blend functions correctly. (#1120) [@greggman]
 - Examples: OpenGL2: Uploading font texture as RGBA32 to increase compatibility with users shaders for beginners. (#824)
-- Examples: Vulkan: Countless fixes and improvements. (#785, #804, #910, #1017, #1039, #1041, #1042, #1043, #1080) [@martty, @Loftilus, @ParticlePeter, @SaschaWillems]
+- Examples: Vulkan: Countless fixes and improvements. (#785, #804, #910, #1017, #1039, #1041,
+  #1042, #1043, #1080) [@martty, @Loftilus, @ParticlePeter, @SaschaWillems]
 - Examples: DirectX9/10/10: Only call SetCursor(NULL) is io.MouseDrawCursor is set. (#585, #909)
 - Examples: DirectX9: Explicitly setting viewport to match that other examples are doing. (#937)
 - Examples: GLFW+OpenGL3: Fixed Shutdown() calling GL functions with NULL parameters if NewFrame was never called. (#800)
@@ -5131,11 +5303,22 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 Breaking Changes:
 
 - Renamed `SetNextTreeNodeOpened()` to `SetNextTreeNodeOpen()` for consistency, no redirection.
-- Removed confusing set of `GetInternalState()`, `GetInternalStateSize()`, `SetInternalState()` functions. Now using `CreateContext()`, `DestroyContext()`, `GetCurrentContext()`, `SetCurrentContext()`. If you were using multiple contexts the change should be obvious and trivial.
-- Obsoleted old signature of `CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false)`, as extra parameters were badly designed and rarely used. Most uses were using 1 parameter and shouldn't affect you. You can replace the "default_open = true" flag in new API with `CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen)`.
-- Changed `ImDrawList::PushClipRect(ImVec4 rect)` to `ImDraw::PushClipRect(ImVec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false)`. Note that higher-level `ImGui::PushClipRect()` is preferable because it will clip at logic/widget level, whereas `ImDrawList::PushClipRect()` only affect your renderer.
-- Title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore (see #655). If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar.
-  This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color. (Or If this is confusing, just pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color.)
+- Removed confusing set of `GetInternalState()`, `GetInternalStateSize()`, `SetInternalState()` functions.
+  Now using `CreateContext()`, `DestroyContext()`, `GetCurrentContext()`, `SetCurrentContext()`.
+  If you were using multiple contexts the change should be obvious and trivial.
+- Obsoleted old signature of `CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false)`,
+  as extra parameters were badly designed and rarely used. Most uses were using 1 parameter and shouldn't affect you.
+  You can replace the "default_open = true" flag in new API with `CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen)`.
+- Changed `ImDrawList::PushClipRect(ImVec4 rect)` to `ImDraw::PushClipRect(ImVec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false)`.
+  Note that higher-level `ImGui::PushClipRect()` is preferable because it will clip at logic/widget level, whereas `ImDrawList::PushClipRect()` only affect your renderer.
+- Title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background
+  (ImGuiCol_WindowBg color) anymore (see #655). If your TitleBg/TitleBgActive alpha was 1.0f or you are using
+  the default theme it will not affect you. However if your TitleBg/TitleBgActive alpha was <1.0f you need to
+  tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar.
+  This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output,
+  given the OLD color and the OLD WindowBg color. (Or If this is confusing, just pick the RGB value from
+  title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create
+  TitleBgActive from a tweaked TitleBg color.)
 
     ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col)
     {
@@ -5146,9 +5329,11 @@ Breaking Changes:
 
 Other changes:
 
-- New version of ImGuiListClipper helper calculates item height automatically. See comments and demo code. (#662, #661, #660)
+- New version of ImGuiListClipper helper calculates item height automatically.
+  See comments and demo code. (#662, #661, #660)
 - Added SetNextWindowSizeConstraints() to enable basic min/max and programmatic size constraints on window. Added demo. (#668)
-- Added PushClipRect()/PopClipRect() (previously part of imgui_internal.h). Changed ImDrawList::PushClipRect() prototype. (#610)
+- Added PushClipRect()/PopClipRect() (previously part of imgui_internal.h).
+  Changed ImDrawList::PushClipRect() prototype. (#610)
 - Added IsRootWindowOrAnyChildHovered() helper. (#615)
 - Added TreeNodeEx() functions. (#581, #600, #190)
 - Added ImGuiTreeNodeFlags_Selected flag to display TreeNode as "selected". (#581, #190)
@@ -5158,31 +5343,38 @@ Other changes:
 - Added ImGuiTreeNodeFlags_DefaultOpen flag (previously private).
 - Added ImGuiTreeNodeFlags_OpenOnDoubleClick flag.
 - Added ImGuiTreeNodeFlags_OpenOnArrow flag.
-- Added ImGuiTreeNodeFlags_Leaf flag, always opened, no arrow, for convenience. For simple use case prefer using TreeAdvanceToLabelPos()+Text().
+- Added ImGuiTreeNodeFlags_Leaf flag, always opened, no arrow, for convenience.
+  For simple use case prefer using TreeAdvanceToLabelPos()+Text().
 - Added ImGuiTreeNodeFlags_Bullet flag, to add a bullet to Leaf node or replace Arrow with a bullet.
 - Added TreeAdvanceToLabelPos(), GetTreeNodeToLabelSpacing() helpers. (#581, #324)
-- Added CreateContext()/DestroyContext()/GetCurrentContext()/SetCurrentContext(). Obsoleted nearly identical GetInternalState()/SetInternalState() functions. (#586, #269)
+- Added CreateContext()/DestroyContext()/GetCurrentContext()/SetCurrentContext().
+  Obsoleted nearly identical GetInternalState()/SetInternalState() functions. (#586, #269)
 - Added NewLine() to undo a SameLine() and as a shy reminder that horizontal layout support hasn't been implemented yet.
 - Added IsItemClicked() helper. (#581)
 - Added CollapsingHeader() variant with close button. (#600)
 - Fixed MenuBar missing lower border when borders are enabled.
 - InputText(): Fixed clipping of cursor rendering in case it gets out of the box (which can be forced w/ ImGuiInputTextFlags_NoHorizontalScroll. (#601)
 - Style: Changed default IndentSpacing from 22 to 21. (#581, #324)
-- Style: Fixed TitleBg/TitleBgActive color being rendered above WindowBg color, which was inconsistent and causing visual artifact. (#655)
-  This broke the meaning of TitleBg and TitleBgActive. Only affect values where Alpha<1.0f. Fixed default theme. Read comments in "API BREAKING CHANGES" section to convert.
+- Style: Fixed TitleBg/TitleBgActive color being rendered above WindowBg color, which was
+  inconsistent and causing visual artifact. (#655)
+  This broke the meaning of TitleBg and TitleBgActive. Only affect values where Alpha<1.0f.
+  Fixed default theme. Read comments in "API BREAKING CHANGES" section to convert.
 - Relative rendering of order of Child windows creation is preserved, to allow more control with overlapping children. (#595)
 - Fixed GetWindowContentRegionMax() being off by ScrollbarSize amount when explicit SizeContents is set.
 - Indent(), Unindent(): optional non-default indenting width. (#324, #581)
 - Bullet(), BulletText(): Slightly bigger. Less polygons.
-- ButtonBehavior(): fixed subtle old bug when a repeating button would also return true on mouse release (barely noticeable unless RepeatRate is set to be very slow). (#656)
+- ButtonBehavior(): fixed subtle old bug when a repeating button would also return true on mouse
+  release (barely noticeable unless RepeatRate is set to be very slow). (#656)
 - BeginMenu(): a menu that becomes disabled while open gets closed down, facilitate user's code. (#126)
 - BeginGroup(): fixed using within Columns set. (#630)
 - Fixed a lag in reading the currently hovered window when dragging a window. (#635)
 - Obsoleted 4 parameters version of CollapsingHeader(). Refactored code into TreeNodeBehavior. (#600, #579)
 - Scrollbar: minor fix for top-right rounding of scrollbar background when window has menu bar but no title bar.
 - MenuItem(): the check mark renders in disabled color when menu item is disabled.
-- Fixed clipping rectangle floating point representation to ensure renderer-side float point operations yield correct results in typical DirectX/GL settings. (#582, 597)
-- Fixed GetFrontMostModalRootWindow(), fixing missing fade-out when a combo pop was used stacked over a modal window. (#604)
+- Fixed clipping rectangle floating point representation to ensure renderer-side floating-point
+  operations yield correct results in typical DirectX/GL settings. (#582, 597)
+- Fixed GetFrontMostModalRootWindow(), fixing missing fade-out when a combo pop was used stacked
+  over a modal window. (#604)
 - ImDrawList: Added AddQuad(), AddQuadFilled() helpers.
 - ImDrawList: AddText() refactor, moving some code to ImFont, reserving less unused vertices when large vertical clipping occurs.
 - ImFont: Added RenderChar() helper.
@@ -5193,7 +5385,8 @@ Other changes:
 - Renamed majority of use of the word "opened" to "open" for clarity. Renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(). (#625, #579)
 - Examples: OpenGL3: Saving/restoring glActiveTexture() state. (#602)
 - Examples: DirectX9: save/restore all device state.
-- Examples: DirectX9: Removed dependency on d3dx9.h, d3dx9.lib, dxguid.lib so it can be used in a DirectXMath.h only environment. (#611)
+- Examples: DirectX9: Removed dependency on d3dx9.h, d3dx9.lib, dxguid.lib so it can be used in
+  a DirectXMath.h only environment. (#611)
 - Examples: DirectX10/X11: Apply depth-stencil state (no use of depth buffer). (#640, #636)
 - Examples: DirectX11/X11: Added comments on removing dependency on D3DCompiler. (#638)
 - Examples: SDL: Initialize video+timer subsystem only.
@@ -5208,33 +5401,53 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 
 Breaking Changes:
 
-- Consistently honoring exact width passed to PushItemWidth() (when positive), previously it would add extra FramePadding.x*2 over that width. Some hand-tuned layout may be affected slightly. (#346)
-- Style: removed `style.WindowFillAlphaDefault` which was confusing and redundant, baked alpha into `ImGuiCol_WindowBg` color. If you had a custom WindowBg color but didn't change WindowFillAlphaDefault, multiply WindowBg alpha component by 0.7. Renamed `ImGuiCol_TooltipBg` to `ImGuiCol_PopupBG`, applies to other types of pop-ups. `bg_alpha` parameter of 5-parameters version of Begin() is an override. (#337)
-- InputText(): Added BufTextLen field in ImGuiTextEditCallbackData. Requesting user to update it if the buffer is modified in the callback. Added a temporary length-check assert to minimize panic for the 3 people using the callback. (#541)
-- Renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). (#340)
+- Consistently honoring exact width passed to PushItemWidth() (when positive), previously it would
+  add extra FramePadding.x*2 over that width. Some hand-tuned layout may be affected slightly. (#346)
+- Style: removed `style.WindowFillAlphaDefault` which was confusing and redundant, baked alpha into
+  `ImGuiCol_WindowBg` color. If you had a custom WindowBg color but didn't change WindowFillAlphaDefault,
+  multiply WindowBg alpha component by 0.7. Renamed `ImGuiCol_TooltipBg` to `ImGuiCol_PopupBG`,
+  applies to other types of pop-ups. `bg_alpha` parameter of 5-parameters version of Begin() is an override. (#337)
+- InputText(): Added BufTextLen field in ImGuiTextEditCallbackData. Requesting user to update it
+  if the buffer is modified in the callback. Added a temporary length-check assert to minimize panic
+  for the 3 people using the callback. (#541)
+- Renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize().
+  Kept inline redirection function (will obsolete). (#340)
 
 Other Changes:
 
-- Consistently honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. Some hand-tuned layout may be affected slightly. (#346)
-- Fixed clipping of child windows within parent not taking account of child outer clipping boundaries (including scrollbar, etc.). (#506)
-- TextUnformatted(): Fixed rare crash bug with large blurb of text (2k+) not finished with a '\n' and fully above the clipping Y line. (#535)
+- Consistently honoring exact width passed to PushItemWidth(), previously it would add extra
+  FramePadding.x*2 over that width. Some hand-tuned layout may be affected slightly. (#346)
+- Fixed clipping of child windows within parent not taking account of child outer clipping
+  boundaries (including scrollbar, etc.). (#506)
+- TextUnformatted(): Fixed rare crash bug with large blurb of text (2k+) not finished with
+  a '\n' and fully above the clipping Y line. (#535)
 - IO: Added 'KeySuper' field to hold CMD keyboard modifiers for OS X. Updated all examples accordingly. (#473)
 - Added ImGuiWindowFlags_ForceVerticalScrollbar, ImGuiWindowFlags_ForceHorizontalScrollbar flags. (#476)
 - Added IM_COL32 macros to generate a U32 packed color, convenient for direct use of ImDrawList api. (#346)
 - Added GetFontTexUvWhitePixel() helper, convenient for direct use of ImDrawList api.
-- Selectable(): Added ImGuiSelectableFlags_AllowDoubleClick flag to allow user reacting on double-click. (@zapolnov) (#516)
+- Selectable(): Added ImGuiSelectableFlags_AllowDoubleClick flag to allow user reacting
+  on double-click. (@zapolnov) (#516)
 - Begin(): made the close button explicitly set the boolean to false instead of toggling it. (#499)
 - BeginChild()/EndChild(): fixed incorrect layout to allow widgets submitted after an auto-fitted child window. (#540)
-- BeginChild(): Added ImGuiWindowFlags_AlwaysUseWindowPadding flag to ensure non-bordered child window uses window padding. (#462)
-- Fixed InputTextMultiLine(), ListBox(), BeginChildFrame(), ProgressBar(): outer frame not honoring bordering. (#462, #503)
+- BeginChild(): Added ImGuiWindowFlags_AlwaysUseWindowPadding flag to ensure non-bordered child window
+  uses window padding. (#462)
+- Fixed InputTextMultiLine(), ListBox(), BeginChildFrame(), ProgressBar(): outer frame not
+  honoring bordering. (#462, #503)
 - Fixed Image(), ImageButtion() rendering a rectangle 1 px too large on each axis. (#457)
 - SetItemAllowOverlap(): Promoted from imgui_internal.h to public imgui.h api. (#517)
 - Combo(): Right-most button stays highlighted when pop-up is open.
 - Combo(): Display pop-up above if there's isn't enough space below / or select largest side. (#505)
-- DragFloat(), SliderFloat(), InputFloat(): fixed cases of erroneously returning true repeatedly after a text input modification (e.g. "0.0" --> "0.000" would keep returning true). (#564)
-- DragFloat(): Always apply value when mouse is held/widget active, so that an always-resetting variable (e.g. non saved local) can be passed.
-- InputText(): OS X friendly behaviors: Word movement uses ALT key; Shortcuts uses CMD key; Double-clicking text select a single word; Jumping to next word sets cursor to end of current word instead of beginning of current word. (@zhiayang), (#473)
-- InputText(): Added BufTextLen in ImGuiTextEditCallbackData. Requesting user to maintain it if buffer is modified. Zero-ing structure properly before use. (#541)
+- DragFloat(), SliderFloat(), InputFloat(): fixed cases of erroneously returning true repeatedly
+  after a text input modification (e.g. "0.0" --> "0.000" would keep returning true). (#564)
+- DragFloat(): Always apply value when mouse is held/widget active, so that an always-resetting
+  variable (e.g. non saved local) can be passed.
+- InputText(): OS X friendly behaviors:  (@zhiayang), (#473)
+  - Word movement uses ALT key;
+  - Shortcuts uses CMD key;
+  - Double-clicking text select a single word;
+  - Jumping to next word sets cursor to end of current word instead of beginning of current word.
+- InputText(): Added BufTextLen in ImGuiTextEditCallbackData. Requesting user to maintain it
+  if buffer is modified. Zero-ing structure properly before use. (#541)
 - CheckboxFlags(): Added support for testing/setting multiple flags at the same time. (@DMartinek) (#555)
 - TreeNode(), CollapsingHeader() fixed not being able to use "##" sequence in a formatted label.
 - ColorEdit4(): Empty label doesn't add InnerSpacing.x, matching behavior of other widgets. (#346)
@@ -5260,11 +5473,13 @@ Other Changes:
 - Demo: plot code doesn't use ImVector to avoid heap allocation and be more friendly to custom allocator users. (#538)
 - Fixed compilation on DragonFly BSD (@mneumann) (#563)
 - Examples: Vulkan: Added a Vulkan example (@Loftilus) (#549)
-- Examples: DX10, DX11: Saving/restoring most device state so dropping render function in your codebase shouldn't have DX device side-effects. (#570)
+- Examples: DX10, DX11: Saving/restoring most device state so dropping render function in your
+  codebase shouldn't have DX device side-effects. (#570)
 - Examples: DX10, DX11: Fixed ImGui_ImplDX??_NewFrame() from recreating device objects if render isn't called (g_pVB not set).
 - Examples: OpenGL3: Fix BindVertexArray/BindBuffer order. (@nlguillemot) (#527)
 - Examples: OpenGL: skip rendering and calling glViewport() if we have zero-fixed buffer. (#486)
-- Examples: SDL2+OpenGL3: Fix context creation options. Made ImGui_ImplSdlGL3_NewFrame() signature match GL2 one. (#468, #463)
+- Examples: SDL2+OpenGL3: Fix context creation options. Made ImGui_ImplSdlGL3_NewFrame() signature
+  match GL2 one. (#468, #463)
 - Examples: SDL2+OpenGL2/3: Fix for high-dpi displays. (@nickgravelyn)
 - Various extra comments and clarification in the code.
 - Various other fixes and optimizations.
@@ -5388,7 +5603,11 @@ Breaking Changes:
   are now incorporating the scrolling amount. They were incorrectly not incorporating this amount previously.
   It PROBABLY shouldn't break anything, but that depends on how you used them. Namely:
   - If you always used SetCursorPos() with values relative to GetCursorPos() there shouldn't be a problem.
-    However if you used absolute coordinates, note that SetCursorPosY(100.0f) will put you at +100 from the initial Y position (which may be scrolled out of the view), NOT at +100 from the window top border. Since there wasn't any official scrolling value on X axis (past just manually moving the cursor) this can only affect you if you used to set absolute coordinates on the Y axis which is hopefully rare/unlikely, and trivial to fix.
+    However if you used absolute coordinates, note that SetCursorPosY(100.0f) will put you at +100 from the
+    initial Y position (which may be scrolled out of the view), NOT at +100 from the window top border.
+    Since there wasn't any official scrolling value on X axis (past just manually moving the cursor) this can
+    only affect you if you used to set absolute coordinates on the Y axis which is hopefully rare/unlikely,
+    and trivial to fix.
   - The value of GetWindowContentRegionMax() isn't necessarily close to GetWindowWidth() if horizontally scrolling.
     Previously they were roughly interchangeable (roughly because the content region exclude window padding).
 
@@ -5416,9 +5635,11 @@ Other Changes:
 - TreeNode(): Fixed mouse interaction padding past the node label being accounted for in layout (#282).
 - BeginChild(): Passing a ImGuiWindowFlags_NoMove inhibits moving parent window from this child.
 - BeginChild() fixed missing rounding for child sizes which leaked into layout and have items misaligned.
-- Begin(): Removed default name = "Debug" parameter. We already have a "Debug" window pushed to the stack in the first place so it's not really a useful default.
+- Begin(): Removed default name = "Debug" parameter. We already have a "Debug" window pushed to the stack in
+  the first place so it's not really a useful default.
 - Begin(): Minor fixes with windows main clipping rectangle (e.g. child window with border).
-- Begin(): Window flags are only read on the first call of the frame. Subsequent calls ignore flags, which allows appending to a window without worryin about flags.
+- Begin(): Window flags are only read on the first call of the frame. Subsequent calls ignore flags, which allows
+  appending to a window without worryin about flags.
 - InputText(): ignore character input when ctrl/alt are held. (Normally those text input are ignored by most wrappers.) (#279).
 - Demo: Fixed incorrectly formed string passed to Combo (#298).
 - Demo: Added simple Log demo.
@@ -5573,10 +5794,13 @@ Other Changes:
 - Added TitleBgActive color in style so focused window is made visible. (#253)
 - Added CaptureKeyboardFromApp() / CaptureMouseFromApp() to manually enforce inputs capturing.
 - Added DragFloatRange2() DragIntRange2() helpers. (#76)
-- Added a Y centering ratio to SetScrollFromCursorPos() which can be used to aim the top or bottom of the window. (#150)
+- Added a Y centering ratio to SetScrollFromCursorPos() which can be used to aim the top
+  or bottom of the window. (#150)
 - Added SetScrollY(), SetScrollFromPos(), GetCursorStartPos() for manual scrolling manipulations. (#150).
-- Added GetKeyIndex() helper for converting from ImGuiKey_\* enum to user's keycodes. Basically pulls from io.KeysMap[].
-- Added missing ImGuiKey_PageUp, ImGuiKey_PageDown so more UI code can be written without referring to implementation-side keycodes.
+- Added GetKeyIndex() helper for converting from ImGuiKey_\* enum to user's keycodes.
+  Basically pulls from io.KeysMap[].
+- Added missing ImGuiKey_PageUp, ImGuiKey_PageDown so more UI code can be written without
+  referring to implementation-side keycodes.
 - MenuItem() can be activated on release. (#245)
 - Allowing NewFrame() with DeltaTime==0.0f to not assert.
 - Fixed IsMouseDragging(). (#260)
@@ -5587,8 +5811,8 @@ Other Changes:
 - Fixed text baseline alignment of small button (no padding) after regular buttons.
 - Fixed ListBoxHeader() not honoring negative sizes the same way as BeginChild() or BeginChildFrame(). (#263)
 - Fixed warnings for more pedantic compiler settings (#258).
-- ImVector<> cannot be re-defined anymore, cannot be replaced with std::vector<>. Allowed us to clean up and optimize
-  lots of code. Yeah! (#262)
+- ImVector<> cannot be re-defined anymore, cannot be replaced with std::vector<>.
+  Allowed us to clean up and optimize lots of code. Yeah! (#262)
 - ImDrawList: store pointer to their owner name for easier auditing/debugging.
 - Examples: added scroll tracking example with SetScrollFromCursorPos().
 - Examples: metrics windows render clip rectangle when hovering over a draw call.
@@ -5611,11 +5835,12 @@ Breaking Changes:
 
 Other Changes:
 
-- Added InputTextMultiline() multi-line text editor, vertical scrolling, selection, optimized enough to handle rather
-  big chunks of text in stateless context (thousands of lines are ok), option for allowing Tab to be input, option
-  for validating with Return or Ctrl+Return (#200).
-- Added modal window API, BeginPopupModal(), follows the popup api scheme. Modal windows can be closed by clicking
-  outside. By default the rest of the screen is dimmed (using ImGuiCol_ModalWindowDarkening). Modal windows can be stacked.
+- Added InputTextMultiline() multi-line text editor, vertical scrolling, selection, optimized
+  enough to handle rather big chunks of text in stateless context (thousands of lines are ok),
+  option for allowing Tab to be input, option for validating with Return or Ctrl+Return (#200).
+- Added modal window API, BeginPopupModal(), follows the popup api scheme. Modal windows can be closed
+  by clicking outside. By default the rest of the screen is dimmed (using ImGuiCol_ModalWindowDarkening).
+  Modal windows can be stacked.
 - Added GetGlyphRangesCyrillic() helper (#237).
 - Added SetNextWindowPosCenter() to center a window prior to knowing its size. (#249)
 - Added IsWindowHovered() helper.
@@ -5631,7 +5856,8 @@ Other Changes:
 - Selectable(): Added flag ImGuiSelectableFlags_DontClosePopups.
 - Selectable(): Added flag ImGuiSelectableFlags_SpanAllColumns (#125).
 - Combo(): Fixed issue with activating a Combo() not taking active id (#241).
-- ColorButton(), ColorEdit4(): fix to ensure that the colored square stays square when non-default padding settings are used.
+- ColorButton(), ColorEdit4(): fix to ensure that the colored square stays square when
+  non-default padding settings are used.
 - BeginChildFrame(): returns bool like BeginChild() for clipping.
 - SetScrollPosHere(): takes account of item height + more accurate centering + fixed precision issue.
 - ImFont: ignoring '\r'.
@@ -5653,26 +5879,30 @@ Breaking Changes:
 - The third parameter of Button(), 'repeat_if_held' has been removed. While it's been very rarely used,
   some code will possibly break if you didn't rely on the default parameter.
   Use PushButtonRepeat()/PopButtonRepeat() to configure repeat.
-- Renamed IsRectClipped() to !IsRectVisible() for consistency (opposite return value!). Kept inline redirection function (will obsolete)
-- Renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline indirection function (will obsolete).
+- Renamed IsRectClipped() to !IsRectVisible() for consistency (opposite return value!).
+  Kept inline redirection function (will obsolete)
+- Renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency.
+  Kept inline indirection function (will obsolete).
 
 Other Changes:
 
-- Menus: Added a menu system! Menus are typically populated with menu items and sub-menus, but you can add any sort of
-  widgets in them (buttons, text inputs, sliders, etc.). (#126)
-- Menus: Added MenuItem() to append a menu item. Optional shortcut display, acts a button & toggle with checked/unchecked state,
-  disabled mode. Menu items can be used in any window.
+- Menus: Added a menu system! Menus are typically populated with menu items and sub-menus,
+  but you can add any sort of widgets in them (buttons, text inputs, sliders, etc.). (#126)
+- Menus: Added MenuItem() to append a menu item. Optional shortcut display, acts a button & toggle
+  with checked/unchecked state, disabled mode. Menu items can be used in any window.
 - Menus: Added BeginMenu() to append a sub-menu. Note that you generally want to add sub-menu inside a popup or a menu-bar.
   They will work inside a normal window but it will be a bit unusual.
 - Menus: Added BeginMenuBar() to append to window menu-bar (set ImGuiWindowFlags_MenuBar to enable).
 - Menus: Added BeginMainMenuBar() helper to append to a fullscreen main menu-bar.
 - Popups: Support for stacked popups. Each popup level inhibit inputs to lower levels. The menus system is based on this. (#126).
-- Popups: Added BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid() to create a popup window on mouse-click.
+- Popups: Added BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid() to
+  create a popup window on mouse-click.
 - Popups: Popups have borders by default (#197), attenuated border alpha in default theme.
-- Popups & Tooltip: Fit within display. Handling various positioning/sizing/scrolling edge cases. Better hysteresis when moving
-  in corners. Tooltip always tries to stay away from mouse-cursor.
+- Popups & Tooltip: Fit within display. Handling various positioning/sizing/scrolling edge
+  cases. Better hysteresis when moving in corners. Tooltip always tries to stay away from mouse-cursor.
 - Added ImGuiStorage::GetVoidPtrRef() for manipulating stored void*.
-- Added IsKeyDown() IsMouseDown() as convenience and for consistency with existing functions (instead of reading them from IO structures).
+- Added IsKeyDown() IsMouseDown() as convenience and for consistency with existing functions
+  (instead of reading them from IO structures).
 - Added Dummy() helper to advance layout by a given size. Unlike InvisibleButton() this doesn't catch any click.
 - Added configurable io.KeyRepeatDelay, io.KeyRepeatRate keyboard and mouse repeat rate.
 - Added PushButtonRepeat() / PopButtonRepeat() to enable hold-button-to-repeat press on any button.
@@ -5698,7 +5928,8 @@ Other Changes:
 - Window: Added ImGuiSetCond_Appearing to test the hidden->visible transition in SetWindow***/SetNextWindow*** functions.
 - Window: Auto-fitting cancel out one worth of vertical spacing for vertical symmetry (like what group and tooltip do).
 - Window: Default item width for auto-resizing windows expressed as a factor of font height, scales better with different font.
-- Window: Fixed auto-fit calculation mismatch of whether a scrollbar will be added by maximum height clamping. Also honor NoScrollBar in the case of height clamping, not adding extra horizontal space.
+- Window: Fixed auto-fit calculation mismatch of whether a scrollbar will be added by maximum height
+  clamping. Also honor NoScrollBar in the case of height clamping, not adding extra horizontal space.
 - Window: Hovering require to hover same child window. Reverted 860cf57 (December 3). Might break something if you have
   child overlapping items in parent window.
 - Window: Fixed appending multiple times to an existing child via multiple BeginChild/EndChild calls to same child name.
@@ -5707,7 +5938,8 @@ Other Changes:
 - Metrics: Added io.MetricsActiveWindows counter. (#213.
 - Metrics: Added io.MetricsAllocs counter (number of active memory allocations).
 - Metrics: ShowMetricsWindow() shows popups stack, allocations.
-- Style: Added style.DisplayWindowPadding to prevent windows from reaching edges of display (similar to style.DisplaySafeAreaPadding which is still in effect and also affect popups/tooltips).
+- Style: Added style.DisplayWindowPadding to prevent windows from reaching edges of display
+  (similar to style.DisplaySafeAreaPadding which is still in effect and also affect popups/tooltips).
 - Style: Removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
 - Style: Added style.ScrollbarRounding. (#212)
 - Style: Added ImGuiCol_TextDisabled for disabled text. Added TextDisabled() helper.
@@ -5749,9 +5981,11 @@ Other Changes:
   Hold SHIFT/ALT to speed-up/slow-down. Double-click or CTRL+click to input text.
   Passing min >= max makes the widget unbounded.
 - Added DragFloat2(), DragFloat3(), DragFloat4(), DragInt2(), DragInt3(), DragInt4() helper variants.
-- Added ShowMetricsWindow() which is mainly useful to debug ImGui internals. Added IO.MetricsRenderVertices counter.
+- Added ShowMetricsWindow() which is mainly useful to debug ImGui internals.
+- Added IO.MetricsRenderVertices counter.
 - Added ResetMouseDragDelta() for iterative dragging operations.
-- Added ImFontAtlas::AddFontFromCompressedTTF() helper + binary_to_compressed_c.cpp tool to compress a file and create a .c array from it.
+- Added ImFontAtlas::AddFontFromCompressedTTF() helper + binary_to_compressed_c.cpp tool to
+  compress a file and create a .c array from it.
 - Added PushId() GetId() variants that takes string range to avoid user making unnecessary copies.
 - Added IsItemVisible().
 - Fixed IsRectClipped() incorrectly returning false when log is enabled.
@@ -5773,7 +6007,8 @@ Other Changes:
 - ShowTestWindow(): added examples for DragFloat, DragInt and only custom label embedded in format strings.
 - ShowTestWindow(): fixed "manipulating titles" example not doing the right thing, broken in ff35d24
 - Examples: OpenGL/GLFW: Fixed modifier key state setting in GLFW callbacks.
-- Examples: OpenGL/GLFW: Added glBindTexture(0) in OpenGL fixed pipeline examples. Save restore current program and texture in the OpenGL3 example.
+- Examples: OpenGL/GLFW: Added glBindTexture(0) in OpenGL fixed pipeline examples.
+  Save restore current program and texture in the OpenGL3 example.
 - Examples: DirectX11: Removed unnecessary vertices conversion and CUSTOMVERTEX types.
 - Comments, fixes, tweaks.
 
@@ -5787,16 +6022,22 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 Other Changes:
 
 - Added a more convenient three parameters version of Begin() which covers the common uses better.
-- Added mouse cursor types handling (resize, move, text input cursors, etc.) that user can query with GetMouseCursor(). Added demo and instructions in ShowTestWindow().
+- Added mouse cursor types handling (resize, move, text input cursors, etc.) that user
+  can query with GetMouseCursor(). Added demo and instructions in ShowTestWindow().
 - Added embedded mouse cursor data for MouseDrawCursor software cursor rendering, for consoles/tablets/etc. (#155).
-- Added first version of BeginPopup/EndPopup() helper API to create popup menus. Popups automatically lock their position to the mouse cursor when first appearing. They close  automatically when clicking outside, and inhibit hovering items from other windows when active (to allow for clicking outside). (#126)
+- Added first version of BeginPopup/EndPopup() helper API to create popup menus. Popups automatically
+  lock their position to the mouse cursor when first appearing. They close automatically when clicking
+  outside, and inhibit hovering items from other windows when active (to allow for clicking outside). (#126)
 - Added thickness parameter to ImDrawList::AddLine().
 - Added ImDrawList::PushClipRectFullScreen() helper.
-- Added style.DisplaySafeAreaPadding which was previously hard-coded (useful if you can't see the edges of your display, e.g. TV screens).
+- Added style.DisplaySafeAreaPadding which was previously hard-coded.
+   (useful if you can't see the edges of your display, e.g. TV screens).
 - Added CalcItemRectClosestPoint() helper.
-- Added GetMouseDragDelta(), IsMouseDragging() helpers, given a mouse button and an optional "unlock" threshold. Added io.MouseDragThreshold setting. (#167)
+- Added GetMouseDragDelta(), IsMouseDragging() helpers, given a mouse button and an optional
+  "unlock" threshold. Added io.MouseDragThreshold setting. (#167)
 - IsItemHovered() return false if another widget is active, aka we can't use what we are hovering now.
-- Added IsItemHoveredRect() if old behavior of IsItemHovered() is needed (e.g. for implementing the drop side of a drag'n drop operation).
+- Added IsItemHoveredRect() if old behavior of IsItemHovered() is needed (e.g. for implementing
+  the drop side of a drag'n drop operation).
 - IsItemhovered() include space taken by label and behave consistently for all widgets (#145)
 - Auto-filling child window feed their content size to parent (#170)
 - InputText() removed the odd ~ characters when clipping.
@@ -5806,15 +6047,20 @@ Other Changes:
 - Selectable(const char*, bool) version has bool defaulting to false.
 - Selectable(): fixed misusage of GetContentRegionMax().x leaking into auto-fitting.
 - Windows starting Collapsed runs initial auto-fit to retrieve a width for their title bar (#175)
-- Fixed new window from having an incorrect content size on their first frame, if queried by user. Fixed SetWindowPos/SetNextWindowPos having a side-effect size computation (#175)
+- Fixed new window from having an incorrect content size on their first frame, if queried by user.
+  Fixed SetWindowPos/SetNextWindowPos having a side-effect size computation (#175)
 - InputFloat(): fixed label alignment if total widget width forcefully bigger than space available.
 - Auto contents size aware of enforced vertical scrollbar if window is larger than display size.
-- Fixed new windows auto-fitting bigger than their .ini saved size. This was a bug but it may be a desirable effect sometimes, may reconsider it.
-- Fixed negative clipping rectangle when collapsing windows that could affect manual submission to ImDrawList and end-user rendering function if unhandled (#177)
+- Fixed new windows auto-fitting bigger than their .ini saved size.
+  This was a bug but it may be a desirable effect sometimes, may reconsider it.
+- Fixed negative clipping rectangle when collapsing windows that could affect manual
+  submission to ImDrawList and end-user rendering function if unhandled (#177)
 - Fixed bounding measurement of empty groups (fix #162)
-- Fixed assignment order in Begin() making auto-fit size effectively lag by one frame. Also disabling "clamp into view" while windows are auto-fitting so that auto-fitting window in corners don't get pushed away.
+- Fixed assignment order in Begin() making auto-fit size effectively lag by one frame. Also disabling
+  "clamp into view" while windows are auto-fitting so that auto-fitting window in corners don't get pushed away.
 - Fixed MouseClickedPos not updated on double-click update (#167)
-- Fixed MouseDrawCursor feature submitting an empty trailing command in the draw list. Fixed unmerged draw calls for software mouse cursor.
+- Fixed MouseDrawCursor feature submitting an empty trailing command in the draw list.
+ Fixed unmerged draw calls for software mouse cursor.
 - Fixed double-clicking on resize grip keeping the grip active if mouse button is kept held.
 - Bounding box tests exclude higher bound, so touching items (zero spacing) don't report double hover when cursor is on edge.
 - Setting io.LogFilename to NULL disable default LogToFile() (part of #175)
@@ -5845,7 +6091,8 @@ Other Changes:
 - Added IsRootWindowFocused(), IsRootWindowOrAnyChildFocused().
 - Added io.KeyAlt + support in examples apps, in prevision for future usage of Alt modifier (was missing).
 - Added ImGuiStyleVar_GrabMinSize enum value for PushStyleVar().
-- Various fixes related to vertical alignment of text after widget of varied sizes. Allow for multiple blocks of multiple lines text on the same "line". Added demos.
+- Various fixes related to vertical alignment of text after widget of varied sizes.
+  Allow for multiple blocks of multiple lines text on the same "line". Added demos.
 - Explicit size passed to Plot*(), Button() includes the frame padding.
 - Style: Changed default Border and Column border colors to be most subtle.
 - Renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing.
@@ -5874,8 +6121,10 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 
 Other Changes:
 
-- Examples: refactored all examples application to make it easier to isolate and grab the code you need for OpenGL 2/3, DirectX 9/11, and toward a more sensible format for samples.
-- Scrollbar grab have a minimum size (style.GrabSizeMin), always visible even with huge scroll amount. (#150).
+- Examples: refactored all examples application to make it easier to isolate and grab the
+  code you need for OpenGL 2/3, DirectX 9/11, and toward a more sensible format for samples.
+- Scrollbar grab have a minimum size (style.GrabSizeMin), always visible even with huge
+  scroll amount. (#150).
 - Scrollbar: Clicking inside the grab box doesn't modify scroll value. Subsequent movement always relative.
 - Added "###" labelling syntax to pass a label that isn't part of the hashed ID (#107), e.g. ("%d###static_id",rand()).
 - Added GetColumnIndex(), GetColumnsCount() (#154)
@@ -5885,12 +6134,15 @@ Other Changes:
 - Fixed ListBoxHeader() incorrect handling of SkipItems early out when window is collapsed.
 - Fixed using IsItemHovered() after EndChild() (#151)
 - Fixed malformed UTF-8 decoding errors leading to infinite loops (#158)
-- InputText() handles buffer limit correctly for multi-byte UTF-8 characters, won't insert an incomplete UTF-8 character when reaching buffer limit (fix #158)
-- Handle double-width space (0x3000) in various places the same as single-width spaces, for Chinese/Japanese users.
+- InputText() handles buffer limit correctly for multi-byte UTF-8 characters, won't insert
+  an incomplete UTF-8 character when reaching buffer limit (fix #158)
+- Handle double-width space (0x3000) in various places the same as single-width spaces,
+  for Chinese/Japanese users.
 - Collapse triangle uses text color (not border color).
 - Fixed font fallback glyph width.
 - Renamed style.ScrollBarWidth to style.ScrollbarWidth to be consistent with other casing.
-- Windows: setup a default handler for ImeSetInputScreenPosFn so the IME dialog (for Japanese/Chinese, etc.) is positioned correctly as you input text.
+- Windows: setup a default handler for ImeSetInputScreenPosFn so the IME dialog
+  (for Japanese/Chinese, etc.) is positioned correctly as you input text.
 - Windows: default clipboard handlers for Windows handle UTF-8.
 - Examples: Fixed DirectX 9/11 examples applications handling of Microsoft IME.
 - Examples: Allow DirectX 9/11 examples applications to resize the window.
@@ -5909,7 +6161,8 @@ Other Changes:
 - Added Bullet() helper - equivalent to BulletText(""), SameLine().
 - Added SetWindowFocus(), SetWindowFocus(const char*), SetNextWindowFocus() (#146)
 - Added SetWindowPos(), SetWindowSize(), SetWindowCollaposed() given a window name.
-- Added SetNextTreeNodeOpened() with optional condition flag in replacement of OpenNextNode() and consistent with other API.
+- Added SetNextTreeNodeOpened() with optional condition flag in replacement of OpenNextNode()
+  and consistent with other API.
 - Renamed ImGuiSetCondition_* to ImGuiSetCond_* and ImGuiCondition_FirstUseThisSession to ImGuiCond_Once.
 - Added missing definition for ImGui::GetWindowCollapsed().
 - Fixed GetGlyphRangesJapanese() actually missing katakana ranges and a few useful extensions.
@@ -5940,18 +6193,23 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 
 Other Changes:
 
-- InputText: having a InputText widget active doesn't steal mouse inputs from clicking on a button before losing focus (relate to #134)
+- InputText: having a InputText widget active doesn't steal mouse inputs from clicking on
+  a button before losing focus (relate to #134)
 - InputText: cursor/selection/undo stack persist when using other widgets and getting back to same (#134).
-- InputText: fix effective buffer size being smaller than necessary by 1 byte (so if you give 3 bytes you can input 2 ascii chars + zero terminator, which is correct).
+- InputText: fix effective buffer size being smaller than necessary by 1 byte (so if you give
+  3 bytes you can input 2 ascii chars + zero terminator, which is correct).
 - Added IsAnyItemActive().
-- Child window explicitly inherit collapse state from parent (so if user keeps submitting items even thought Begin has returned 'false' the child items will be clipped faster).
+- Child window explicitly inherit collapse state from parent (so if user keeps submitting items
+  even thought Begin has returned 'false' the child items will be clipped faster).
 - BeginChild() return a bool the same way Begin() does. if true you can skip submitting content.
 - Removed extraneous (1,1) padding on child window (pointed out in #125)
 - Columns: doesn't bail out when SkipItems is set (fix #136)
 - Columns: Separator() within column correctly vertical offset all cells (pointed out in #125)
-- GetColumnOffset() / SetColumnOffset() handles padding values more correctly so matching columns can be lined up between a parent and a child window (cf. #125)
+- GetColumnOffset() / SetColumnOffset() handles padding values more correctly so matching columns
+  can be lined up between a parent and a child window (cf. #125)
 - Fix ImFont::BuildLookupTable() potential dangling pointer dereference (fix #131)
-- Fix hovering of child window extending past their parent not taking account of parent clipping rectangle (fix #137)
+- Fix hovering of child window extending past their parent not taking account of parent clipping
+  rectangle (fix #137)
 - Sliders: value text is clipped inside the frame when resizing sliders to be small.
 - ImGuITextFilter::Draw() use regular width call rather than computing its own arbitrary width.
 - ImGuiTextFilter: can take a default filter string during construction.
@@ -5969,11 +6227,13 @@ Other Changes:
 - Added ListBox() (#129).
 - Added ListBoxHeader(), ListBoxFooter() for customized list traversal and creating multi-selection boxes.
 - Fixed title bar text clipping issue (fix #128).
-- InputText: added ImGuiInputTextFlags_CallbackCharFilter system for filtering/replacement (#130). Callback now passed an "EventFlag" parameter.
+- InputText: added ImGuiInputTextFlags_CallbackCharFilter system for filtering/replacement (#130).
+  Callback now passed an "EventFlag" parameter.
 - InputText: Added ImGuiInputTextFlags_CharsUppercase and ImGuiInputTextFlags_CharsNoBlank stock filters.
 - PushItemWidth() can take negative value to right-align items.
 - Optimisation: Columns offsets cached to avoid unnecessary binary search.
-- Optimisation: Optimized CalcTextSize() function by about 25% (they are often the bottleneck when submitting thousands of clipped items).
+- Optimisation: Optimized CalcTextSize() function by about 25% (they are often the bottleneck when
+  submitting thousands of clipped items).
 - Added ImGuiCol_ChildWindowBg, ImGuiStyleVar_ChildWindowRounding for completeness and flexibility.
 - Added BeginChild() variant that takes an ImGuiID.
 - Tweak default ImGuiCol_HeaderActive color to be less bright.
@@ -5989,9 +6249,11 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 Other Changes:
 
 - Added ImGuiWindowFlags_NoCollapse flag.
-- Added a way to replace the internal state pointer so that we can optionally share it between modules (e.g. multiple DLLs).
+- Added a way to replace the internal state pointer so that we can optionally share it between
+  modules (e.g. multiple DLLs).
 - Added tint_col parameter to ImageButton().
-- Added CalcListClipping() helper to perform faster/coarse clipping on user side (when manipulating lists with thousands of items).
+- Added CalcListClipping() helper to perform faster/coarse clipping on user side
+  (when manipulating lists with thousands of items).
 - Added GetCursorPosX() / GetCursorPosY() shortcuts.
 - Renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing().
 - Combo box always appears above other child windows of a same parent.
@@ -6013,7 +6275,8 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 
 Breaking Changes:
 
-- Big update! Initialisation had to be changed. You don't need to load PNG data anymore. The new system gives you uncompressed texture data.
+- Big update! Initialisation had to be changed. You don't need to load PNG data anymore. Th
+  new system gives you uncompressed texture data.
   - This sequence:
       const void* png_data;
       unsigned int png_size;
@@ -6026,19 +6289,23 @@ Breaking Changes:
       io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
       // 
       io.Fonts->TexID = (your_texture_identifier);
-  - PixelCenterOffset has been removed and isn't a necessary setting anymore. Offset your projection matrix by 0.5 if you have rendering problems.
+  - PixelCenterOffset has been removed and isn't a necessary setting anymore. Offset your
+    projection matrix by 0.5 if you have rendering problems.
 
 Other Changes:
 
 - Loading TTF files with stb_truetype.h.
 - We still embed a compressed pixel-perfect TTF version of ProggyClean for convenience.
 - Runtime font rendering is a little faster than previously.
-- You can load multiple fonts with multiple size inside the font atlas. Rendering with multiple fonts are still merged into a single draw call whenever possible.
+- You can load multiple fonts with multiple size inside the font atlas. Rendering with multiple
+  fonts are still merged into a single draw call whenever possible.
 - The system handles UTF-8 and provide ranges to easily load e.g. characters for Japanese display.
 - Added PushFont() / PopFont().
 - Added Image() and ImageButton() to display your own texture data.
-- Added callback system in command-list. This can be used if you want to do your own rendering (e.g. render a 3D scene) inside ImGui widgets.
-- Added IsItemActive() to tell if last widget is being held / modified (as opposed to just being hovered). Useful for custom dragging behaviors.
+- Added callback system in command-list. This can be used if you want to do your own rendering
+  (e.g. render a 3D scene) inside ImGui widgets.
+- Added IsItemActive() to tell if last widget is being held / modified (as opposed to just
+  being hovered). Useful for custom dragging behaviors.
 - Style: Added FrameRounding setting for a more rounded look (default to 0 for now).
 - Window: Fixed using multiple Begin/End pair on the same wnidow.
 - Window: Fixed style.WindowMinSize not being honored properly.
@@ -6071,7 +6338,8 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 - Dragging outside area of a widget while it is active doesn't trigger hover on other widgets.
 - Activating widget bring parent window to front if not already.
 - Checkbox and Radio buttons activate on click-release to be consistent with other widgets and most UI.
-- InputText() nows consume input characters immediately so they cannot be reused if ImGui::Update is called again with a call to ImGui::Render(). (fixes #105)
+- InputText() nows consume input characters immediately so they cannot be reused if
+  ImGui::Update is called again with a call to ImGui::Render(). (fixes #105)
 - Examples: Console: added support for History callbacks + some cleanup.
 - Various small optimisations.
 - Cleanup and other fixes.
@@ -6089,7 +6357,8 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 - Widgets more consistently handle empty labels (starting with ## mark) for their size calculation.
 - Fixed crashing with zero sized frame-buffer.
 - Fixed ImGui::Combo() not registering its size properly when clipped out of screen.
-- Renamed second parameter to Begin() to 'bool* p_opened' to be a little more self-explanatory. Added more comments on the use of Begin().
+- Renamed second parameter to Begin() to 'bool* p_opened' to be a little more self-explanatory.
+  Added more comments on the use of Begin().
 - Logging: Added LogText() to pass text straight to the log output (tty/clipboard/file) without rendering it.
 - Logging: Added LogFinish() to stop logging at an arbitrary point.
 - Logging: Log depth padding relative to start depth.
@@ -6108,7 +6377,10 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 
 - Added ImGuiWindowFlags_NoScrollWithMouse, disable mouse wheel scrolling on a window.
 - Added ImGuiWindowFlags_NoSavedSettings, disable loading/saving window state to .ini file.
-- Added SetNextWindowPos(), SetNextWindowSize(), SetNextWindowCollapsed() API along with SetWindowPos(), SetWindowSize(), SetWindowCollapsed(). All functions include an optional second parameter to easily set current value vs session default value vs persistent default value.
+- Added SetNextWindowPos(), SetNextWindowSize(), SetNextWindowCollapsed() API along
+  with SetWindowPos(), SetWindowSize(), SetWindowCollapsed(). All functions include an
+  optional second parameter to easily set current value vs session default value vs.
+  persistent default value.
 - Removed rarely useful SetNewWindowDefaultPos() in favor of new API.
 - Fixed hovering of lower-right resize grip when it is above a child window.
 - Fixed InputInt() writing to output when it doesn't need to.
@@ -6134,7 +6406,8 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 - Increased visibility of check box and radio button with smaller size.
 - Smooth mouse scrolling on OSX (uses floating point scroll/wheel input).
 - New version of IMGUI_ONCE_UPON_A_FRAME helper macro that works with all compilers.
-- Moved IO.Font*** options to inside the IO.Font-> structure.. Added IO.FontGlobalScale setting (in addition to Font->Scale per individual font).
+- Moved IO.Font*** options to inside the IO.Font-> structure.
+- Added IO.FontGlobalScale setting (in addition to Font->Scale per individual font).
 - Fixed more Clang -Weverything warnings.
 - Examples: Added DirectX11 example application.
 - Examples: Created single .sln solution for all example projects.
@@ -6162,7 +6435,8 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 - Fixed unaligned memory access for Emscripten compatibility.
 - Various pedantic warning fixes (now testing with Clang).
 - Added extra asserts to catch incorrect usage.
-- PushStyleColor() / PushStyleVar() can be used outside the scope of a window (namely to change variables that are used within the Begin() call).
+- PushStyleColor() / PushStyleVar() can be used outside the scope of a window (namely to change
+  variables that are used within the Begin() call).
 - PushTextWrapPos() defaults to 0.0 (right-end of current drawing region).
 - Fixed compatibility with std::vector if user decide to #define ImVector.
 - MouseWheel input is now normalized.
@@ -6200,7 +6474,8 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 - Comments and fixes.
 - Added SetKeyboardFocusHere() to set input focus from code.
 - Added GetWindowFont(), GetWindowFontSize() for users of the low-level ImDrawList API.
-- Added a UserData void *pointer so that the callback functions can access user state "Just in case a project has adverse reactions to adding globals or statics in their own code."
+- Added a UserData void *pointer so that the callback functions can access user state
+  "Just in case a project has adverse reactions to adding globals or statics in their own code."
 - Renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL
 
 
@@ -6228,7 +6503,8 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 - Added IsMouseHoveringWindow(), IsMouseHoveringAnyWindow(), IsPosHoveringAnyWindow() helpers.
 - Added va_list variations of all functions taking ellipsis (...) parameters.
 - Added section in documentation to explicitly document cases of API breaking changes (e.g. renamed IM_MALLOC below).
-- Moved IM_MALLOC / IM_FREE defines. to IO structure members that can be set at runtime (also allowing precompiled ImGui to cover more use cases).
+- Moved IM_MALLOC / IM_FREE defines. to IO structure members that can be set at runtime
+  (also allowing precompiled ImGui to cover more use cases).
 - Fixed OpenGL samples for Retina display.
 - Comments and minor fixes.
 
@@ -6268,7 +6544,10 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 
 Breaking Changes:
 
-- The behaviour of PixelCenterOffset changed! You may need to change your value if you had set it to non-default in your code and/or offset your projection matrix by 0.5 pixels. It is likely that the default PixelCenterOffset value of 0.0 is now suitable unless your rendering uses some form of multisampling.
+- The behaviour of PixelCenterOffset changed! You may need to change your value if you had set
+  it to non-default in your code and/or offset your projection matrix by 0.5 pixels. It is
+  likely that the default PixelCenterOffset value of 0.0 is now suitable unless your rendering
+  uses some form of multisampling.
 
 Other Changes:
 
@@ -6299,10 +6578,12 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v
 Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.07
 
 - Added InputFloat4(), SliderFloat4() helpers.
-- Added global Alpha in ImGuiStyle structure. When Alpha=0.0, ImGui skips most of logic and all rendering processing.
+- Added global Alpha in ImGuiStyle structure. When Alpha=0.0, ImGui skips most of logic
+  and all rendering processing.
 - Fix clipping of title bar text.
 - Fix to allow the user to call NewFrame() multiple times without calling Render().
-- Reduce inner window clipping to take account for the extend of CollapsingHeader() - share same clipping rectangle.
+- Reduce inner window clipping to take account for the extend of CollapsingHeader() - share
+  same clipping rectangle.
 - Fix for child windows with inverted clip rectangles (when scrolled and out of screen, Etc.).
 - Minor fixes, tweaks, comments.
 

From 57ab2b4226010f3291c79a9ba1e72e72041fbe9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20B=C3=B6hme?= 
Date: Tue, 5 Nov 2024 23:26:41 +0100
Subject: [PATCH 248/548] Fixed unused function warning (#8130)

---
 imgui.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/imgui.cpp b/imgui.cpp
index 01a72c6b7b3c..9de1a81577d8 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1210,9 +1210,11 @@ static int              FindWindowFocusIndex(ImGuiWindow* window);
 // Error Checking and Debug Tools
 static void             ErrorCheckNewFrameSanityChecks();
 static void             ErrorCheckEndFrameSanityChecks();
+#ifndef IMGUI_DISABLE_DEBUG_TOOLS
 static void             UpdateDebugToolItemPicker();
 static void             UpdateDebugToolStackQueries();
 static void             UpdateDebugToolFlashStyleColor();
+#endif
 
 // Inputs
 static void             UpdateKeyboardInputs();

From 6f287dd16d5d7f393d5b6089585dd87ea5ea0d92 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 6 Nov 2024 16:56:51 +0100
Subject: [PATCH 249/548] (Breaking) Removed pre-1.87 obsolete io.KeyMap[],
 io.KeysDown[], io.NavInputs[]. Remove IMGUI_DISABLE_OBSOLETE_KEYIO. (#4921)

---
 backends/imgui_impl_allegro5.cpp |   2 +-
 backends/imgui_impl_allegro5.h   |   2 +-
 backends/imgui_impl_android.cpp  |   2 +-
 backends/imgui_impl_android.h    |   2 +-
 backends/imgui_impl_glfw.cpp     |   2 +-
 backends/imgui_impl_glfw.h       |   2 +-
 backends/imgui_impl_glut.cpp     |   2 +-
 backends/imgui_impl_glut.h       |   2 +-
 backends/imgui_impl_osx.h        |   2 +-
 backends/imgui_impl_osx.mm       |   2 +-
 backends/imgui_impl_sdl2.cpp     |   2 +-
 backends/imgui_impl_sdl2.h       |   2 +-
 backends/imgui_impl_sdl3.cpp     |   2 +-
 backends/imgui_impl_sdl3.h       |   2 +-
 backends/imgui_impl_win32.cpp    |   2 +-
 backends/imgui_impl_win32.h      |   2 +-
 docs/CHANGELOG.txt               |  12 +++
 imconfig.h                       |   1 -
 imgui.cpp                        | 173 +++----------------------------
 imgui.h                          |  57 +++-------
 imgui_demo.cpp                   |   8 --
 21 files changed, 60 insertions(+), 223 deletions(-)

diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp
index d5d65703e496..3e6d766470e0 100644
--- a/backends/imgui_impl_allegro5.cpp
+++ b/backends/imgui_impl_allegro5.cpp
@@ -3,7 +3,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy ALLEGRO_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy ALLEGRO_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Clipboard support (from Allegro 5.1.12)
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 // Issues:
diff --git a/backends/imgui_impl_allegro5.h b/backends/imgui_impl_allegro5.h
index f1501eca8ff6..aba5c47701ea 100644
--- a/backends/imgui_impl_allegro5.h
+++ b/backends/imgui_impl_allegro5.h
@@ -3,7 +3,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy ALLEGRO_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy ALLEGRO_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Clipboard support (from Allegro 5.1.12)
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 // Issues:
diff --git a/backends/imgui_impl_android.cpp b/backends/imgui_impl_android.cpp
index b0c46393111f..05939293cb84 100644
--- a/backends/imgui_impl_android.cpp
+++ b/backends/imgui_impl_android.cpp
@@ -2,7 +2,7 @@
 // This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
 
 // Implemented features:
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
 // Missing features:
 //  [ ] Platform: Clipboard support.
diff --git a/backends/imgui_impl_android.h b/backends/imgui_impl_android.h
index 92a044db028a..efe27dcb9568 100644
--- a/backends/imgui_impl_android.h
+++ b/backends/imgui_impl_android.h
@@ -2,7 +2,7 @@
 // This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
 
 // Implemented features:
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
 // Missing features:
 //  [ ] Platform: Clipboard support.
diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp
index 774fb0d5d78a..afa2185a3b67 100644
--- a/backends/imgui_impl_glfw.cpp
+++ b/backends/imgui_impl_glfw.cpp
@@ -6,7 +6,7 @@
 // Implemented features:
 //  [X] Platform: Clipboard support.
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
 
diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h
index 60b95bd99d46..5d8940a0c98e 100644
--- a/backends/imgui_impl_glfw.h
+++ b/backends/imgui_impl_glfw.h
@@ -5,7 +5,7 @@
 // Implemented features:
 //  [X] Platform: Clipboard support.
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
 
diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp
index d8ffc9073688..6bb9eae7eeea 100644
--- a/backends/imgui_impl_glut.cpp
+++ b/backends/imgui_impl_glut.cpp
@@ -6,7 +6,7 @@
 // !!! Nowadays, prefer using GLFW or SDL instead!
 
 // Implemented features:
-//  [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values are obsolete since 1.87 and not supported since 1.91.5]
 // Issues:
 //  [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
 //  [ ] Platform: Missing horizontal mouse wheel support.
diff --git a/backends/imgui_impl_glut.h b/backends/imgui_impl_glut.h
index a7479e1d7480..feeca8b3fcd0 100644
--- a/backends/imgui_impl_glut.h
+++ b/backends/imgui_impl_glut.h
@@ -6,7 +6,7 @@
 // !!! Nowadays, prefer using GLFW or SDL instead!
 
 // Implemented features:
-//  [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values are obsolete since 1.87 and not supported since 1.91.5]
 // Issues:
 //  [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
 //  [ ] Platform: Missing horizontal mouse wheel support.
diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h
index 28e1331285df..4caab8ff5f73 100644
--- a/backends/imgui_impl_osx.h
+++ b/backends/imgui_impl_osx.h
@@ -6,7 +6,7 @@
 // Implemented features:
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 //  [X] Platform: Mouse support. Can discriminate Mouse/Pen.
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 //  [X] Platform: IME support.
diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm
index 6ff4f19a42c5..69108ca4a5dc 100644
--- a/backends/imgui_impl_osx.mm
+++ b/backends/imgui_impl_osx.mm
@@ -6,7 +6,7 @@
 // Implemented features:
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 //  [X] Platform: Mouse support. Can discriminate Mouse/Pen.
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 //  [X] Platform: IME support.
diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp
index 529ca79e0a2f..14022159f8c4 100644
--- a/backends/imgui_impl_sdl2.cpp
+++ b/backends/imgui_impl_sdl2.cpp
@@ -6,7 +6,7 @@
 // Implemented features:
 //  [X] Platform: Clipboard support.
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 //  [X] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h
index e551e52a2853..8ccc6fdc7c62 100644
--- a/backends/imgui_impl_sdl2.h
+++ b/backends/imgui_impl_sdl2.h
@@ -5,7 +5,7 @@
 // Implemented features:
 //  [X] Platform: Clipboard support.
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 //  [X] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp
index de8b531582d8..3cd56a756a6a 100644
--- a/backends/imgui_impl_sdl3.cpp
+++ b/backends/imgui_impl_sdl3.cpp
@@ -7,7 +7,7 @@
 // Implemented features:
 //  [X] Platform: Clipboard support.
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 
diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h
index 880ba9615b18..c4a5a1230e3c 100644
--- a/backends/imgui_impl_sdl3.h
+++ b/backends/imgui_impl_sdl3.h
@@ -7,7 +7,7 @@
 // Implemented features:
 //  [X] Platform: Clipboard support.
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 
diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp
index c213f8158011..687bc5a18d61 100644
--- a/backends/imgui_impl_win32.cpp
+++ b/backends/imgui_impl_win32.cpp
@@ -4,7 +4,7 @@
 // Implemented features:
 //  [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 
diff --git a/backends/imgui_impl_win32.h b/backends/imgui_impl_win32.h
index 3ad1a7eaf181..0dfd56a801be 100644
--- a/backends/imgui_impl_win32.h
+++ b/backends/imgui_impl_win32.h
@@ -4,7 +4,7 @@
 // Implemented features:
 //  [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
-//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
+//  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
 //  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 9e43a56a1faa..603828c39947 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -41,6 +41,18 @@ HOW TO UPDATE?
 
 Breaking changes:
 
+- Commented out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before).
+  - io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022).
+  - io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022).
+  - Pre-1.87 backends are not supported:
+    - backends need to call io.AddKeyEvent(), io.AddMouseEvent() instead of writing to io.KeysDown[], io.MouseDown[] fields.
+    - backends need to call io.AddKeyAnalogEvent() for gamepad values instead of writing to io.NavInputs[] fields.
+  - For more reference:
+    - read 1.87 and 1.88 part of this section or read Changelog for 1.87 and 1.88.
+    - read https://github.com/ocornut/imgui/issues/4921
+  - If you have trouble updating a very old codebase using legacy backend-specific key codes:
+    consider updating to 1.91.4 first, then #define IMGUI_DISABLE_OBSOLETE_KEYIO, then update to latest.
+
 Other changes:
 
 - Selectable: selected Selectables use ImGuiCol_Header instead of an arbitrary lerp
diff --git a/imconfig.h b/imconfig.h
index 63d6ba081e99..fea89dea0913 100644
--- a/imconfig.h
+++ b/imconfig.h
@@ -29,7 +29,6 @@
 
 //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
 //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
-//#define IMGUI_DISABLE_OBSOLETE_KEYIO                      // 1.87+ disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This is automatically done by IMGUI_DISABLE_OBSOLETE_FUNCTIONS.
 
 //---- Disable all of Dear ImGui or don't implement standard windows/tools.
 // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp.
diff --git a/imgui.cpp b/imgui.cpp
index 9de1a81577d8..74da7355e0df 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -174,7 +174,6 @@ CODE
       - Set 'io.BackendFlags |= ImGuiBackendFlags_HasGamepad' + call io.AddKeyEvent/AddKeyAnalogEvent() with ImGuiKey_Gamepad_XXX keys.
       - For analog values (0.0f to 1.0f), backend is responsible to handling a dead-zone and rescaling inputs accordingly.
         Backend code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.).
-      - BEFORE 1.87, BACKENDS USED TO WRITE TO io.NavInputs[]. This is now obsolete. Please call io functions instead!
    - If you need to share inputs between your game and the Dear ImGui interface, the easiest approach is to go all-or-nothing,
      with a buttons combo to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved.
 
@@ -430,6 +429,16 @@ 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.
 
+ - 2024/11/06 (1.91.5) - commented/obsoleted out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before)
+                            - io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022).
+                            - io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022).
+                            - pre-1.87 backends are not supported:
+                               - backends need to call io.AddKeyEvent(), io.AddMouseEvent() instead of writing to io.KeysDown[], io.MouseDown[] fields.
+                               - backends need to call io.AddKeyAnalogEvent() for gamepad values instead of writing to io.NavInputs[] fields.
+                            - for more reference:
+                              - read 1.87 and 1.88 part of this section or read Changelog for 1.87 and 1.88.
+                              - read https://github.com/ocornut/imgui/issues/4921
+                            - if you have trouble updating a very old codebase using legacy backend-specific key codes: consider updating to 1.91.4 first, then #define IMGUI_DISABLE_OBSOLETE_KEYIO, then update to latest.
  - 2024/10/18 (1.91.4) - renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor (for consistency with newly exposed and reworked features). Kept inline redirection enum (will obsolete).
  - 2024/10/14 (1.91.4) - moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
                          moved ImGuiConfigFlags_NavNoCaptureKeyboard to standalone io.ConfigNavCaptureKeyboard bool (note the inverted value!).
@@ -1390,10 +1399,6 @@ ImGuiIO::ImGuiIO()
     IniSavingRate = 5.0f;
     IniFilename = "imgui.ini"; // Important: "imgui.ini" is relative to current working dir, most apps will want to lock this to an absolute path (e.g. same path as executables).
     LogFilename = "imgui_log.txt";
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-    for (int i = 0; i < ImGuiKey_COUNT; i++)
-        KeyMap[i] = -1;
-#endif
     UserData = NULL;
 
     Fonts = NULL;
@@ -1456,8 +1461,6 @@ ImGuiIO::ImGuiIO()
     for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
     for (int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; }
     AppAcceptingEvents = true;
-    BackendUsingLegacyKeyArrays = (ImS8)-1;
-    BackendUsingLegacyNavInputArray = true; // assume using legacy array until proven wrong
 }
 
 // Pass in translated ASCII characters for text input.
@@ -1538,9 +1541,6 @@ void ImGuiIO::ClearEventsQueue()
 // Clear current keyboard/gamepad state + current frame text input buffer. Equivalent to releasing all keys/buttons.
 void ImGuiIO::ClearInputKeys()
 {
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-    memset(KeysDown, 0, sizeof(KeysDown));
-#endif
     for (int n = 0; n < IM_ARRAYSIZE(KeysData); n++)
     {
         if (ImGui::IsMouseKey((ImGuiKey)(n + ImGuiKey_KeysData_OFFSET)))
@@ -1625,17 +1625,6 @@ void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
         else if (key == ImGuiKey_RightCtrl) { key = ImGuiKey_RightSuper; }
     }
 
-    // Verify that backend isn't mixing up using new io.AddKeyEvent() api and old io.KeysDown[] + io.KeyMap[] data.
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-    IM_ASSERT((BackendUsingLegacyKeyArrays == -1 || BackendUsingLegacyKeyArrays == 0) && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
-    if (BackendUsingLegacyKeyArrays == -1)
-        for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
-            IM_ASSERT(KeyMap[n] == -1 && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
-    BackendUsingLegacyKeyArrays = 0;
-#endif
-    if (ImGui::IsGamepadKey(key))
-        BackendUsingLegacyNavInputArray = false;
-
     // Filter duplicate (in particular: key mods and gamepad analog values are commonly spammed)
     const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_Key, (int)key);
     const ImGuiKeyData* key_data = ImGui::GetKeyData(&g, key);
@@ -1671,20 +1660,10 @@ void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native
         return;
     IM_ASSERT(ImGui::IsNamedKey(key)); // >= 512
     IM_ASSERT(native_legacy_index == -1 || ImGui::IsLegacyKey((ImGuiKey)native_legacy_index)); // >= 0 && <= 511
-    IM_UNUSED(native_keycode);  // Yet unused
-    IM_UNUSED(native_scancode); // Yet unused
-
-    // Build native->imgui map so old user code can still call key functions with native 0..511 values.
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-    const int legacy_key = (native_legacy_index != -1) ? native_legacy_index : native_keycode;
-    if (!ImGui::IsLegacyKey((ImGuiKey)legacy_key))
-        return;
-    KeyMap[legacy_key] = key;
-    KeyMap[key] = legacy_key;
-#else
-    IM_UNUSED(key);
-    IM_UNUSED(native_legacy_index);
-#endif
+    IM_UNUSED(key);                 // Yet unused
+    IM_UNUSED(native_keycode);      // Yet unused
+    IM_UNUSED(native_scancode);     // Yet unused
+    IM_UNUSED(native_legacy_index); // Yet unused
 }
 
 // Set master flag for accepting key/mouse/text events (default to true). Useful if you have native dialog boxes that are interrupting your application loop/refresh, and you want to disable events being queued while your app is frozen.
@@ -8928,27 +8907,10 @@ ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key)
     if (key & ImGuiMod_Mask_)
         key = ConvertSingleModFlagToKey(key);
 
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-    IM_ASSERT(key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_NamedKey_END);
-    if (IsLegacyKey(key) && g.IO.KeyMap[key] != -1)
-        key = (ImGuiKey)g.IO.KeyMap[key];  // Remap native->imgui or imgui->native
-#else
     IM_ASSERT(IsNamedKey(key) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend & user code.");
-#endif
     return &g.IO.KeysData[key - ImGuiKey_KeysData_OFFSET];
 }
 
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-// Formally moved to obsolete section in 1.90.5 in spite of documented as obsolete since 1.87
-ImGuiKey ImGui::GetKeyIndex(ImGuiKey key)
-{
-    ImGuiContext& g = *GImGui;
-    IM_ASSERT(IsNamedKey(key));
-    const ImGuiKeyData* key_data = GetKeyData(key);
-    return (ImGuiKey)(key_data - g.IO.KeysData);
-}
-#endif
-
 // Those names a provided for debugging purpose and are not meant to be saved persistently not compared.
 static const char* const GKeyNames[] =
 {
@@ -8980,18 +8942,7 @@ const char* ImGui::GetKeyName(ImGuiKey key)
 {
     if (key == ImGuiKey_None)
         return "None";
-#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
     IM_ASSERT(IsNamedKeyOrMod(key) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
-#else
-    ImGuiContext& g = *GImGui;
-    if (IsLegacyKey(key))
-    {
-        if (g.IO.KeyMap[key] == -1)
-            return "N/A";
-        IM_ASSERT(IsNamedKey((ImGuiKey)g.IO.KeyMap[key]));
-        key = (ImGuiKey)g.IO.KeyMap[key];
-    }
-#endif
     if (key & ImGuiMod_Mask_)
         key = ConvertSingleModFlagToKey(key);
     if (!IsNamedKey(key))
@@ -9635,74 +9586,6 @@ static void ImGui::UpdateKeyboardInputs()
     if (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard)
         io.ClearInputKeys();
 
-    // Import legacy keys or verify they are not used
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-    if (io.BackendUsingLegacyKeyArrays == 0)
-    {
-        // Backend used new io.AddKeyEvent() API: Good! Verify that old arrays are never written to externally.
-        for (int n = 0; n < ImGuiKey_LegacyNativeKey_END; n++)
-            IM_ASSERT((io.KeysDown[n] == false || IsKeyDown((ImGuiKey)n)) && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!");
-    }
-    else
-    {
-        if (g.FrameCount == 0)
-            for (int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++)
-                IM_ASSERT(g.IO.KeyMap[n] == -1 && "Backend is not allowed to write to io.KeyMap[0..511]!");
-
-        // Build reverse KeyMap (Named -> Legacy)
-        for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++)
-            if (io.KeyMap[n] != -1)
-            {
-                IM_ASSERT(IsLegacyKey((ImGuiKey)io.KeyMap[n]));
-                io.KeyMap[io.KeyMap[n]] = n;
-            }
-
-        // Import legacy keys into new ones
-        for (int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++)
-            if (io.KeysDown[n] || io.BackendUsingLegacyKeyArrays == 1)
-            {
-                const ImGuiKey key = (ImGuiKey)(io.KeyMap[n] != -1 ? io.KeyMap[n] : n);
-                IM_ASSERT(io.KeyMap[n] == -1 || IsNamedKey(key));
-                io.KeysData[key].Down = io.KeysDown[n];
-                if (key != n)
-                    io.KeysDown[key] = io.KeysDown[n]; // Allow legacy code using io.KeysDown[GetKeyIndex()] with old backends
-                io.BackendUsingLegacyKeyArrays = 1;
-            }
-        if (io.BackendUsingLegacyKeyArrays == 1)
-        {
-            GetKeyData(ImGuiMod_Ctrl)->Down = io.KeyCtrl;
-            GetKeyData(ImGuiMod_Shift)->Down = io.KeyShift;
-            GetKeyData(ImGuiMod_Alt)->Down = io.KeyAlt;
-            GetKeyData(ImGuiMod_Super)->Down = io.KeySuper;
-        }
-    }
-#endif
-
-    // Import legacy ImGuiNavInput_ io inputs and convert to gamepad keys
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-    const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
-    if (io.BackendUsingLegacyNavInputArray && nav_gamepad_active)
-    {
-        #define MAP_LEGACY_NAV_INPUT_TO_KEY1(_KEY, _NAV1)           do { io.KeysData[_KEY].Down = (io.NavInputs[_NAV1] > 0.0f); io.KeysData[_KEY].AnalogValue = io.NavInputs[_NAV1]; } while (0)
-        #define MAP_LEGACY_NAV_INPUT_TO_KEY2(_KEY, _NAV1, _NAV2)    do { io.KeysData[_KEY].Down = (io.NavInputs[_NAV1] > 0.0f) || (io.NavInputs[_NAV2] > 0.0f); io.KeysData[_KEY].AnalogValue = ImMax(io.NavInputs[_NAV1], io.NavInputs[_NAV2]); } while (0)
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceDown, ImGuiNavInput_Activate);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceRight, ImGuiNavInput_Cancel);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceLeft, ImGuiNavInput_Menu);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceUp, ImGuiNavInput_Input);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadLeft, ImGuiNavInput_DpadLeft);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadRight, ImGuiNavInput_DpadRight);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadUp, ImGuiNavInput_DpadUp);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadDown, ImGuiNavInput_DpadDown);
-        MAP_LEGACY_NAV_INPUT_TO_KEY2(ImGuiKey_GamepadL1, ImGuiNavInput_FocusPrev, ImGuiNavInput_TweakSlow);
-        MAP_LEGACY_NAV_INPUT_TO_KEY2(ImGuiKey_GamepadR1, ImGuiNavInput_FocusNext, ImGuiNavInput_TweakFast);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickLeft, ImGuiNavInput_LStickLeft);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickRight, ImGuiNavInput_LStickRight);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickUp, ImGuiNavInput_LStickUp);
-        MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickDown, ImGuiNavInput_LStickDown);
-        #undef NAV_MAP_KEY
-    }
-#endif
-
     // Update aliases
     for (int n = 0; n < ImGuiMouseButton_COUNT; n++)
         UpdateAliasKey(MouseButtonToKey(n), io.MouseDown[n], io.MouseDown[n] ? 1.0f : 0.0f);
@@ -10100,13 +9983,6 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
             key_changed_mask.SetBit(key_data_index);
             if (trickle_interleaved_nonchar_keys_and_text && !key_is_potentially_for_char_input)
                 key_changed_nonchar = true;
-
-            // Allow legacy code using io.KeysDown[GetKeyIndex()] with new backends
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-            io.KeysDown[key_data_index] = key_data->Down;
-            if (io.KeyMap[key_data_index] != -1)
-                io.KeysDown[io.KeyMap[key_data_index]] = key_data->Down;
-#endif
         }
         else if (e->Type == ImGuiInputEventType_Text)
         {
@@ -10468,14 +10344,6 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
     IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting.");
     IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
     IM_ASSERT(g.Style.ColorButtonPosition == ImGuiDir_Left || g.Style.ColorButtonPosition == ImGuiDir_Right);
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-    for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_COUNT; n++)
-        IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < ImGuiKey_LegacyNativeKey_END && "io.KeyMap[] contains an out of bound value (need to be 0..511, or -1 for unmapped key)");
-
-    // Check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only added in 1.60 WIP)
-    if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && g.IO.BackendUsingLegacyKeyArrays == 1)
-        IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
-#endif
 
     // Error handling: we do not accept 100% silent recovery! Please contact me if you feel this is getting in your way.
     if (g.IO.ConfigErrorRecovery)
@@ -15732,18 +15600,11 @@ void ImGui::ShowMetricsWindow(bool* p_open)
     {
         Text("KEYBOARD/GAMEPAD/MOUSE KEYS");
         {
-            // We iterate both legacy native range and named ImGuiKey ranges, which is a little odd but this allows displaying the data for old/new backends.
             // User code should never have to go through such hoops! You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END.
             Indent();
-#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
-            struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } };
-#else
-            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); }
-            Text("Keys pressed:");      for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !IsKeyPressed(key)) continue;  SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); }
-            Text("Keys released:");     for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !IsKeyReleased(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); }
+            Text("Keys down:");         for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (!IsKeyDown(key)) continue;     SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); SameLine(); Text("(%.02f)", GetKeyData(key)->DownDuration); }
+            Text("Keys pressed:");      for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (!IsKeyPressed(key)) continue;  SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); }
+            Text("Keys released:");     for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (!IsKeyReleased(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); }
             Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
             Text("Chars queue:");       for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; SameLine(); Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
             DebugRenderKeyboardPreview(GetWindowDrawList());
diff --git a/imgui.h b/imgui.h
index 973a52f53468..824cea059ad3 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.5 WIP"
-#define IMGUI_VERSION_NUM   19143
+#define IMGUI_VERSION_NUM   19144
 #define IMGUI_HAS_TABLE
 
 /*
@@ -961,9 +961,8 @@ namespace ImGui
 
     // Inputs Utilities: Keyboard/Mouse/Gamepad
     // - the ImGuiKey enum contains all possible keyboard, mouse and gamepad inputs (e.g. ImGuiKey_A, ImGuiKey_MouseLeft, ImGuiKey_GamepadDpadUp...).
-    // - before v1.87, we used ImGuiKey to carry native/user indices as defined by each backends. About use of those legacy ImGuiKey values:
-    //  - without IMGUI_DISABLE_OBSOLETE_KEYIO (legacy support): you can still use your legacy native/user indices (< 512) according to how your backend/engine stored them in io.KeysDown[], but need to cast them to ImGuiKey.
-    //  - with    IMGUI_DISABLE_OBSOLETE_KEYIO (this is the way forward): any use of ImGuiKey will assert with key < 512. GetKeyIndex() is pass-through and therefore deprecated (gone if IMGUI_DISABLE_OBSOLETE_KEYIO is defined).
+    // - (legacy: before v1.87, we used ImGuiKey to carry native/user indices as defined by each backends. This was obsoleted in 1.87 (2022-02) and completely removed in 1.91.5 (2024-11). See https://github.com/ocornut/imgui/issues/4921)
+    // - (legacy: any use of ImGuiKey will assert when key < 512 to detect passing legacy native/user indices)
     IMGUI_API bool          IsKeyDown(ImGuiKey key);                                            // is key being held.
     IMGUI_API bool          IsKeyPressed(ImGuiKey key, bool repeat = true);                     // was key pressed (went from !Down to Down)? if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate
     IMGUI_API bool          IsKeyReleased(ImGuiKey key);                                        // was key released (went from Down to !Down)?
@@ -1415,15 +1414,10 @@ enum ImGuiSortDirection : ImU8
     ImGuiSortDirection_Descending   = 2     // Descending = 9->0, Z->A etc.
 };
 
-// Since 1.90, defining IMGUI_DISABLE_OBSOLETE_FUNCTIONS automatically defines IMGUI_DISABLE_OBSOLETE_KEYIO as well.
-#if defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && !defined(IMGUI_DISABLE_OBSOLETE_KEYIO)
-#define IMGUI_DISABLE_OBSOLETE_KEYIO
-#endif
-
 // A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value): can represent Keyboard, Mouse and Gamepad values.
-// All our named keys are >= 512. Keys value 0 to 511 are left unused as legacy native/opaque key values (< 1.87).
-// Since >= 1.89 we increased typing (went from int to enum), some legacy code may need a cast to ImGuiKey.
-// Read details about the 1.87 and 1.89 transition : https://github.com/ocornut/imgui/issues/4921
+// All our named keys are >= 512. Keys value 0 to 511 are left unused and were legacy native/opaque key values (< 1.87).
+// Support for legacy keys was completely removed in 1.91.5.
+// Read details about the 1.87+ transition : https://github.com/ocornut/imgui/issues/4921
 // Note that "Keys" related to physical keys and are not the same concept as input "Characters", the later are submitted via io.AddInputCharacter().
 // The keyboard key enum values are named after the keys on a standard US keyboard, and on other keyboard types the keys reported may not match the keycaps.
 enum ImGuiKey : int
@@ -1535,19 +1529,12 @@ enum ImGuiKey : int
     ImGuiMod_Super                  = 1 << 15, // Windows/Super (non-macOS), Ctrl (macOS)
     ImGuiMod_Mask_                  = 0xF000,  // 4-bits
 
-    // [Internal] Prior to 1.87 we required user to fill io.KeysDown[512] using their own native index + the io.KeyMap[] array.
-    // We are ditching this method but keeping a legacy path for user code doing e.g. IsKeyPressed(MY_NATIVE_KEY_CODE)
-    // If you need to iterate all keys (for e.g. an input mapper) you may use ImGuiKey_NamedKey_BEGIN..ImGuiKey_NamedKey_END.
+    // [Internal] If you need to iterate all keys (for e.g. an input mapper) you may use ImGuiKey_NamedKey_BEGIN..ImGuiKey_NamedKey_END.
     ImGuiKey_NamedKey_BEGIN         = 512,
     ImGuiKey_NamedKey_END           = ImGuiKey_COUNT,
     ImGuiKey_NamedKey_COUNT         = ImGuiKey_NamedKey_END - ImGuiKey_NamedKey_BEGIN,
-#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
     ImGuiKey_KeysData_SIZE          = ImGuiKey_NamedKey_COUNT,  // Size of KeysData[]: only hold named keys
     ImGuiKey_KeysData_OFFSET        = ImGuiKey_NamedKey_BEGIN,  // Accesses to io.KeysData[] must use (key - ImGuiKey_KeysData_OFFSET) index.
-#else
-    ImGuiKey_KeysData_SIZE          = ImGuiKey_COUNT,           // Size of KeysData[]: hold legacy 0..512 keycodes + named keys
-    ImGuiKey_KeysData_OFFSET        = 0,                        // Accesses to io.KeysData[] must use (key - ImGuiKey_KeysData_OFFSET) index.
-#endif
 
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
     ImGuiMod_Shortcut               = ImGuiMod_Ctrl,            // Removed in 1.90.7, you can now simply use ImGuiMod_Ctrl
@@ -1581,18 +1568,6 @@ enum ImGuiInputFlags_
     ImGuiInputFlags_Tooltip                 = 1 << 18,  // Automatically display a tooltip when hovering item [BETA] Unsure of right api (opt-in/opt-out)
 };
 
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-// OBSOLETED in 1.88 (from July 2022): ImGuiNavInput and io.NavInputs[].
-// Official backends between 1.60 and 1.86: will keep working and feed gamepad inputs as long as IMGUI_DISABLE_OBSOLETE_KEYIO is not set.
-// Custom backends: feed gamepad inputs via io.AddKeyEvent() and ImGuiKey_GamepadXXX enums.
-enum ImGuiNavInput
-{
-    ImGuiNavInput_Activate, ImGuiNavInput_Cancel, ImGuiNavInput_Input, ImGuiNavInput_Menu, ImGuiNavInput_DpadLeft, ImGuiNavInput_DpadRight, ImGuiNavInput_DpadUp, ImGuiNavInput_DpadDown,
-    ImGuiNavInput_LStickLeft, ImGuiNavInput_LStickRight, ImGuiNavInput_LStickUp, ImGuiNavInput_LStickDown, ImGuiNavInput_FocusPrev, ImGuiNavInput_FocusNext, ImGuiNavInput_TweakSlow, ImGuiNavInput_TweakFast,
-    ImGuiNavInput_COUNT,
-};
-#endif
-
 // Configuration flags stored in io.ConfigFlags. Set by user/application.
 enum ImGuiConfigFlags_
 {
@@ -2425,20 +2400,18 @@ struct ImGuiIO
     float       PenPressure;                        // Touch/Pen pressure (0.0f to 1.0f, should be >0.0f only when MouseDown[0] == true). Helper storage currently unused by Dear ImGui.
     bool        AppFocusLost;                       // Only modify via AddFocusEvent()
     bool        AppAcceptingEvents;                 // Only modify via SetAppAcceptingEvents()
-    ImS8        BackendUsingLegacyKeyArrays;        // -1: unknown, 0: using AddKeyEvent(), 1: using legacy io.KeysDown[]
-    bool        BackendUsingLegacyNavInputArray;    // 0: using AddKeyAnalogEvent(), 1: writing to legacy io.NavInputs[] directly
     ImWchar16   InputQueueSurrogate;                // For AddInputCharacterUTF16()
     ImVector InputQueueCharacters;         // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper.
 
     // Legacy: before 1.87, we required backend to fill io.KeyMap[] (imgui->native map) during initialization and io.KeysDown[] (native indices) every frame.
     // This is still temporarily supported as a legacy feature. However the new preferred scheme is for backend to call io.AddKeyEvent().
     //   Old (<1.87):  ImGui::IsKeyPressed(ImGui::GetIO().KeyMap[ImGuiKey_Space]) --> New (1.87+) ImGui::IsKeyPressed(ImGuiKey_Space)
-#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
-    int         KeyMap[ImGuiKey_COUNT];             // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512.
-    bool        KeysDown[ImGuiKey_COUNT];           // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow.
-    float       NavInputs[ImGuiNavInput_COUNT];     // [LEGACY] Since 1.88, NavInputs[] was removed. Backends from 1.60 to 1.86 won't build. Feed gamepad inputs via io.AddKeyEvent() and ImGuiKey_GamepadXXX enums.
+    //   Old (<1.87):  ImGui::IsKeyPressed(MYPLATFORM_KEY_SPACE)                  --> New (1.87+) ImGui::IsKeyPressed(ImGuiKey_Space)
+    // Read https://github.com/ocornut/imgui/issues/4921 for details.
+    //int       KeyMap[ImGuiKey_COUNT];             // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512.
+    //bool      KeysDown[ImGuiKey_COUNT];           // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow.
+    //float     NavInputs[ImGuiNavInput_COUNT];     // [LEGACY] Since 1.88, NavInputs[] was removed. Backends from 1.60 to 1.86 won't build. Feed gamepad inputs via io.AddKeyEvent() and ImGuiKey_GamepadXXX enums.
     //void*     ImeWindowHandle;                    // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
-#endif
 
     // Legacy: before 1.91.1, clipboard functions were stored in ImGuiIO instead of ImGuiPlatformIO.
     // As this is will affect all users of custom engines/backends, we are providing proper legacy redirection (will obsolete).
@@ -3617,9 +3590,6 @@ namespace ImGui
     // OBSOLETED in 1.89.4 (from March 2023)
     static inline void  PushAllowKeyboardFocus(bool tab_stop)                   { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); }
     static inline void  PopAllowKeyboardFocus()                                 { PopItemFlag(); }
-    // OBSOLETED in 1.87 (from February 2022 but more formally obsoleted April 2024)
-    IMGUI_API ImGuiKey  GetKeyIndex(ImGuiKey key);                              // Map ImGuiKey_* values into legacy native key index. == io.KeyMap[key]. When using a 1.87+ backend using io.AddKeyEvent(), calling GetKeyIndex() with ANY ImGuiKey_XXXX values will return the same value!
-    //static inline ImGuiKey GetKeyIndex(ImGuiKey key)                          { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END); return key; }
 
     // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
     //-- OBSOLETED in 1.89 (from August 2022)
@@ -3627,6 +3597,9 @@ namespace ImGui
     //-- OBSOLETED in 1.88 (from May 2022)
     //static inline void  CaptureKeyboardFromApp(bool want_capture_keyboard = true)                   { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value.
     //static inline void  CaptureMouseFromApp(bool want_capture_mouse = true)                         { SetNextFrameWantCaptureMouse(want_capture_mouse); }       // Renamed as name was misleading + removed default value.
+    //-- OBSOLETED in 1.87 (from February 2022, more formally obsoleted April 2024)
+    //IMGUI_API ImGuiKey  GetKeyIndex(ImGuiKey key);                                                  { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END); const ImGuiKeyData* key_data = GetKeyData(key); return (ImGuiKey)(key_data - g.IO.KeysData); } // Map ImGuiKey_* values into legacy native key index. == io.KeyMap[key]. When using a 1.87+ backend using io.AddKeyEvent(), calling GetKeyIndex() with ANY ImGuiKey_XXXX values will return the same value!
+    //static inline ImGuiKey GetKeyIndex(ImGuiKey key)                                                { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END); return key; }
     //-- OBSOLETED in 1.86 (from November 2021)
     //IMGUI_API void      CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Code removed, see 1.90 for last version of the code. Calculate range of visible items for large list of evenly sized items. Prefer using ImGuiListClipper.
     //-- OBSOLETED in 1.85 (from August 2021)
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index f5e16f06c161..e28ca3b7aac4 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -7370,13 +7370,8 @@ static void ShowDemoWindowInputs()
             // displaying the data for old/new backends.
             // User code should never have to go through such hoops!
             // You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END.
-#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
             struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } };
             ImGuiKey start_key = ImGuiKey_NamedKey_BEGIN;
-#else
-            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); }
             ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
             ImGui::Text("Chars queue:");       for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine();  ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
@@ -7699,9 +7694,6 @@ void ImGui::ShowAboutWindow(bool* p_open)
 #ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
         ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
 #endif
-#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
-        ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_KEYIO");
-#endif
 #ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
         ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
 #endif

From 738d6db3e6b9b28284aa1026dbf082238d9c9aab Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 6 Nov 2024 17:42:02 +0100
Subject: [PATCH 250/548] (Breaking) Removed used of ImGuiKey_KeysData_SIZE,
 ImGuiKey_KeysData_OFFSET. (#4921)

---
 imgui.cpp | 39 ++++++++++++++++++++-------------------
 imgui.h   |  6 +++---
 2 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 74da7355e0df..028f08c3c7ae 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1541,13 +1541,15 @@ void ImGuiIO::ClearEventsQueue()
 // Clear current keyboard/gamepad state + current frame text input buffer. Equivalent to releasing all keys/buttons.
 void ImGuiIO::ClearInputKeys()
 {
-    for (int n = 0; n < IM_ARRAYSIZE(KeysData); n++)
+    ImGuiContext& g = *Ctx;
+    for (int key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key++)
     {
-        if (ImGui::IsMouseKey((ImGuiKey)(n + ImGuiKey_KeysData_OFFSET)))
+        if (ImGui::IsMouseKey((ImGuiKey)key))
             continue;
-        KeysData[n].Down             = false;
-        KeysData[n].DownDuration     = -1.0f;
-        KeysData[n].DownDurationPrev = -1.0f;
+        ImGuiKeyData* key_data = &g.IO.KeysData[key - ImGuiKey_NamedKey_BEGIN];
+        key_data->Down = false;
+        key_data->DownDuration = -1.0f;
+        key_data->DownDurationPrev = -1.0f;
     }
     KeyCtrl = KeyShift = KeyAlt = KeySuper = false;
     KeyMods = ImGuiMod_None;
@@ -1558,7 +1560,7 @@ void ImGuiIO::ClearInputMouse()
 {
     for (ImGuiKey key = ImGuiKey_Mouse_BEGIN; key < ImGuiKey_Mouse_END; key = (ImGuiKey)(key + 1))
     {
-        ImGuiKeyData* key_data = &KeysData[key - ImGuiKey_KeysData_OFFSET];
+        ImGuiKeyData* key_data = &KeysData[key - ImGuiKey_NamedKey_BEGIN];
         key_data->Down = false;
         key_data->DownDuration = -1.0f;
         key_data->DownDurationPrev = -1.0f;
@@ -8908,7 +8910,7 @@ ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key)
         key = ConvertSingleModFlagToKey(key);
 
     IM_ASSERT(IsNamedKey(key) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend & user code.");
-    return &g.IO.KeysData[key - ImGuiKey_KeysData_OFFSET];
+    return &g.IO.KeysData[key - ImGuiKey_NamedKey_BEGIN];
 }
 
 // Those names a provided for debugging purpose and are not meant to be saved persistently not compared.
@@ -9609,22 +9611,21 @@ static void ImGui::UpdateKeyboardInputs()
 
     // Clear gamepad data if disabled
     if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0)
-        for (int i = ImGuiKey_Gamepad_BEGIN; i < ImGuiKey_Gamepad_END; i++)
+        for (int key = ImGuiKey_Gamepad_BEGIN; key < ImGuiKey_Gamepad_END; key++)
         {
-            io.KeysData[i - ImGuiKey_KeysData_OFFSET].Down = false;
-            io.KeysData[i - ImGuiKey_KeysData_OFFSET].AnalogValue = 0.0f;
+            io.KeysData[key - ImGuiKey_NamedKey_BEGIN].Down = false;
+            io.KeysData[key - ImGuiKey_NamedKey_BEGIN].AnalogValue = 0.0f;
         }
 
     // Update keys
-    for (int i = 0; i < ImGuiKey_KeysData_SIZE; i++)
+    for (int key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key++)
     {
-        ImGuiKeyData* key_data = &io.KeysData[i];
+        ImGuiKeyData* key_data = &io.KeysData[key - ImGuiKey_NamedKey_BEGIN];
         key_data->DownDurationPrev = key_data->DownDuration;
         key_data->DownDuration = key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f;
         if (key_data->DownDuration == 0.0f)
         {
-            ImGuiKey key = (ImGuiKey)(ImGuiKey_KeysData_OFFSET + i);
-            if (IsKeyboardKey(key))
+            if (IsKeyboardKey((ImGuiKey)key))
                 g.LastKeyboardKeyPressTime = g.Time;
             else if (key == ImGuiKey_ReservedForModCtrl || key == ImGuiKey_ReservedForModShift || key == ImGuiKey_ReservedForModAlt || key == ImGuiKey_ReservedForModSuper)
                 g.LastKeyboardKeyPressTime = g.Time;
@@ -9634,7 +9635,7 @@ static void ImGui::UpdateKeyboardInputs()
     // Update keys/input owner (named keys only): one entry per key
     for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
     {
-        ImGuiKeyData* key_data = &io.KeysData[key - ImGuiKey_KeysData_OFFSET];
+        ImGuiKeyData* key_data = &io.KeysData[key - ImGuiKey_NamedKey_BEGIN];
         ImGuiKeyOwnerData* owner_data = &g.KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN];
         owner_data->OwnerCurr = owner_data->OwnerNext;
         if (!key_data->Down) // Important: ownership is released on the frame after a release. Ensure a 'MouseDown -> CloseWindow -> MouseUp' chain doesn't lead to someone else seeing the MouseUp.
@@ -9920,7 +9921,7 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
 
     bool mouse_moved = false, mouse_wheeled = false, key_changed = false, key_changed_nonchar = false, text_inputted = false;
     int  mouse_button_changed = 0x00;
-    ImBitArray key_changed_mask;
+    ImBitArray key_changed_mask;
 
     int event_n = 0;
     for (; event_n < g.InputEventsQueue.Size; event_n++)
@@ -15602,9 +15603,9 @@ void ImGui::ShowMetricsWindow(bool* p_open)
         {
             // User code should never have to go through such hoops! You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END.
             Indent();
-            Text("Keys down:");         for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (!IsKeyDown(key)) continue;     SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); SameLine(); Text("(%.02f)", GetKeyData(key)->DownDuration); }
-            Text("Keys pressed:");      for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (!IsKeyPressed(key)) continue;  SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); }
-            Text("Keys released:");     for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (!IsKeyReleased(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); }
+            Text("Keys down:");         for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (!IsKeyDown(key)) continue;     SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); SameLine(); Text("(%.02f)", GetKeyData(key)->DownDuration); }
+            Text("Keys pressed:");      for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (!IsKeyPressed(key)) continue;  SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); }
+            Text("Keys released:");     for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (!IsKeyReleased(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); }
             Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
             Text("Chars queue:");       for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; SameLine(); Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
             DebugRenderKeyboardPreview(GetWindowDrawList());
diff --git a/imgui.h b/imgui.h
index 824cea059ad3..6965c5e6bbec 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1533,8 +1533,8 @@ enum ImGuiKey : int
     ImGuiKey_NamedKey_BEGIN         = 512,
     ImGuiKey_NamedKey_END           = ImGuiKey_COUNT,
     ImGuiKey_NamedKey_COUNT         = ImGuiKey_NamedKey_END - ImGuiKey_NamedKey_BEGIN,
-    ImGuiKey_KeysData_SIZE          = ImGuiKey_NamedKey_COUNT,  // Size of KeysData[]: only hold named keys
-    ImGuiKey_KeysData_OFFSET        = ImGuiKey_NamedKey_BEGIN,  // Accesses to io.KeysData[] must use (key - ImGuiKey_KeysData_OFFSET) index.
+    //ImGuiKey_KeysData_SIZE        = ImGuiKey_NamedKey_COUNT,  // Size of KeysData[]: only hold named keys
+    //ImGuiKey_KeysData_OFFSET      = ImGuiKey_NamedKey_BEGIN,  // Accesses to io.KeysData[] must use (key - ImGuiKey_NamedKey_BEGIN) index.
 
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
     ImGuiMod_Shortcut               = ImGuiMod_Ctrl,            // Removed in 1.90.7, you can now simply use ImGuiMod_Ctrl
@@ -2380,7 +2380,7 @@ struct ImGuiIO
 
     // Other state maintained from data above + IO function calls
     ImGuiKeyChord KeyMods;                          // Key mods flags (any of ImGuiMod_Ctrl/ImGuiMod_Shift/ImGuiMod_Alt/ImGuiMod_Super flags, same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags. Read-only, updated by NewFrame()
-    ImGuiKeyData  KeysData[ImGuiKey_KeysData_SIZE]; // Key state for all known keys. Use IsKeyXXX() functions to access this.
+    ImGuiKeyData  KeysData[ImGuiKey_NamedKey_COUNT];// Key state for all known keys. Use IsKeyXXX() functions to access this.
     bool        WantCaptureMouseUnlessPopupClose;   // Alternative to WantCaptureMouse: (WantCaptureMouse == true && WantCaptureMouseUnlessPopupClose == false) when a click over void is expected to close a popup.
     ImVec2      MousePosPrev;                       // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid)
     ImVec2      MouseClickedPos[5];                 // Position at time of clicking

From df0776e931d2be6efe5d8a6e465b97851b23c9d5 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 6 Nov 2024 17:49:52 +0100
Subject: [PATCH 251/548] (Breaking) Removed ImGuiKey_COUNT. (#4921)

---
 docs/CHANGELOG.txt | 2 ++
 imgui.cpp          | 1 +
 imgui.h            | 7 ++++---
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 603828c39947..1e8016a133e9 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -52,6 +52,8 @@ Breaking changes:
     - read https://github.com/ocornut/imgui/issues/4921
   - If you have trouble updating a very old codebase using legacy backend-specific key codes:
     consider updating to 1.91.4 first, then #define IMGUI_DISABLE_OBSOLETE_KEYIO, then update to latest.
+  - Obsoleted ImGuiKey_COUNT (it is unusually error-prone/misleading since valid keys don't start at 0).
+    Probably use ImGuiKey_NamedKey_BEGIN/ImGuiKey_NamedKey_END?
 
 Other changes:
 
diff --git a/imgui.cpp b/imgui.cpp
index 028f08c3c7ae..7f853fa0f433 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -439,6 +439,7 @@ CODE
                               - read 1.87 and 1.88 part of this section or read Changelog for 1.87 and 1.88.
                               - read https://github.com/ocornut/imgui/issues/4921
                             - if you have trouble updating a very old codebase using legacy backend-specific key codes: consider updating to 1.91.4 first, then #define IMGUI_DISABLE_OBSOLETE_KEYIO, then update to latest.
+                       - obsoleted ImGuiKey_COUNT (it is unusually error-prone/misleading since valid keys don't start at 0). probably use ImGuiKey_NamedKey_BEGIN/ImGuiKey_NamedKey_END?
  - 2024/10/18 (1.91.4) - renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor (for consistency with newly exposed and reworked features). Kept inline redirection enum (will obsolete).
  - 2024/10/14 (1.91.4) - moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
                          moved ImGuiConfigFlags_NavNoCaptureKeyboard to standalone io.ConfigNavCaptureKeyboard bool (note the inverted value!).
diff --git a/imgui.h b/imgui.h
index 6965c5e6bbec..ec3d6c0a7109 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1424,6 +1424,8 @@ enum ImGuiKey : int
 {
     // Keyboard
     ImGuiKey_None = 0,
+    ImGuiKey_NamedKey_BEGIN = 512,  // First valid key value (other than 0)
+
     ImGuiKey_Tab = 512,             // == ImGuiKey_NamedKey_BEGIN
     ImGuiKey_LeftArrow,
     ImGuiKey_RightArrow,
@@ -1511,7 +1513,7 @@ enum ImGuiKey : int
 
     // [Internal] Reserved for mod storage
     ImGuiKey_ReservedForModCtrl, ImGuiKey_ReservedForModShift, ImGuiKey_ReservedForModAlt, ImGuiKey_ReservedForModSuper,
-    ImGuiKey_COUNT,
+    ImGuiKey_NamedKey_END,
 
     // Keyboard Modifiers (explicitly submitted by backend via AddKeyEvent() calls)
     // - This is mirroring the data also written to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeySuper, in a format allowing
@@ -1530,13 +1532,12 @@ enum ImGuiKey : int
     ImGuiMod_Mask_                  = 0xF000,  // 4-bits
 
     // [Internal] If you need to iterate all keys (for e.g. an input mapper) you may use ImGuiKey_NamedKey_BEGIN..ImGuiKey_NamedKey_END.
-    ImGuiKey_NamedKey_BEGIN         = 512,
-    ImGuiKey_NamedKey_END           = ImGuiKey_COUNT,
     ImGuiKey_NamedKey_COUNT         = ImGuiKey_NamedKey_END - ImGuiKey_NamedKey_BEGIN,
     //ImGuiKey_KeysData_SIZE        = ImGuiKey_NamedKey_COUNT,  // Size of KeysData[]: only hold named keys
     //ImGuiKey_KeysData_OFFSET      = ImGuiKey_NamedKey_BEGIN,  // Accesses to io.KeysData[] must use (key - ImGuiKey_NamedKey_BEGIN) index.
 
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+    ImGuiKey_COUNT                  = ImGuiKey_NamedKey_END,    // Obsoleted in 1.91.5 because it was extremely misleading (since named keys don't start at 0 anymore)
     ImGuiMod_Shortcut               = ImGuiMod_Ctrl,            // Removed in 1.90.7, you can now simply use ImGuiMod_Ctrl
     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

From d97bbf19042c8addf7098978609de20fef9978e6 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 6 Nov 2024 18:08:15 +0100
Subject: [PATCH 252/548] Tabs, Style: made ImGuiCol_TabDimmedSelectedOverline
 alpha 0 (not visible) in default styles.

---
 docs/CHANGELOG.txt | 2 ++
 imgui_draw.cpp     | 6 +++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 1e8016a133e9..abf339421f9a 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -64,6 +64,8 @@ Other changes:
 - Fonts: removed const qualifiers from most font functions.
 - InputText: fixed a bug (regression in 1.91.2) where modifying text buffer within
   a callback would sometimes prevents further appending to the buffer.
+- Tabs, Style: made ImGuiCol_TabDimmedSelectedOverline alpha 0 (not visible) in default
+  styles as the current look is not right (but ImGuiCol_TabSelectedOverline stays the same).
 - Log/Capture: better decorating of BeginMenu() and TabItem() output.
 - Log/Capture: a non terminated log ends automatically in the window which called it.
 - Log/Capture: added experimental io.ConfigWindowsCopyContentsWithCtrlC option to
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index ac6d0228196e..43a49eb299c6 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -218,7 +218,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
     colors[ImGuiCol_TabSelectedOverline]    = colors[ImGuiCol_HeaderActive];
     colors[ImGuiCol_TabDimmed]              = ImLerp(colors[ImGuiCol_Tab],          colors[ImGuiCol_TitleBg], 0.80f);
     colors[ImGuiCol_TabDimmedSelected]      = ImLerp(colors[ImGuiCol_TabSelected],  colors[ImGuiCol_TitleBg], 0.40f);
-    colors[ImGuiCol_TabDimmedSelectedOverline] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
+    colors[ImGuiCol_TabDimmedSelectedOverline] = ImVec4(0.50f, 0.50f, 0.50f, 0.00f);
     colors[ImGuiCol_PlotLines]              = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
     colors[ImGuiCol_PlotLinesHovered]       = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
     colors[ImGuiCol_PlotHistogram]          = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
@@ -281,7 +281,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
     colors[ImGuiCol_TabSelectedOverline]    = colors[ImGuiCol_HeaderActive];
     colors[ImGuiCol_TabDimmed]              = ImLerp(colors[ImGuiCol_Tab],          colors[ImGuiCol_TitleBg], 0.80f);
     colors[ImGuiCol_TabDimmedSelected]      = ImLerp(colors[ImGuiCol_TabSelected],  colors[ImGuiCol_TitleBg], 0.40f);
-    colors[ImGuiCol_TabDimmedSelectedOverline] = colors[ImGuiCol_HeaderActive];
+    colors[ImGuiCol_TabDimmedSelectedOverline] = ImVec4(0.53f, 0.53f, 0.87f, 0.00f);
     colors[ImGuiCol_PlotLines]              = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
     colors[ImGuiCol_PlotLinesHovered]       = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
     colors[ImGuiCol_PlotHistogram]          = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
@@ -345,7 +345,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
     colors[ImGuiCol_TabSelectedOverline]    = colors[ImGuiCol_HeaderActive];
     colors[ImGuiCol_TabDimmed]              = ImLerp(colors[ImGuiCol_Tab],          colors[ImGuiCol_TitleBg], 0.80f);
     colors[ImGuiCol_TabDimmedSelected]      = ImLerp(colors[ImGuiCol_TabSelected],  colors[ImGuiCol_TitleBg], 0.40f);
-    colors[ImGuiCol_TabDimmedSelectedOverline] = ImVec4(0.26f, 0.59f, 1.00f, 1.00f);
+    colors[ImGuiCol_TabDimmedSelectedOverline] = ImVec4(0.26f, 0.59f, 1.00f, 0.00f);
     colors[ImGuiCol_PlotLines]              = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
     colors[ImGuiCol_PlotLinesHovered]       = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
     colors[ImGuiCol_PlotHistogram]          = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);

From 3543dfda953beefd9add1316328e2c7cfb4aa637 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 6 Nov 2024 18:14:44 +0100
Subject: [PATCH 253/548] Docs: document removal of ImFont const qualifier as
 potentially breaking.

---
 docs/CHANGELOG.txt | 34 +++++++++++++++++-----------------
 imgui.cpp          |  1 +
 2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index abf339421f9a..ebc128a04ac7 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -54,6 +54,7 @@ Breaking changes:
     consider updating to 1.91.4 first, then #define IMGUI_DISABLE_OBSOLETE_KEYIO, then update to latest.
   - Obsoleted ImGuiKey_COUNT (it is unusually error-prone/misleading since valid keys don't start at 0).
     Probably use ImGuiKey_NamedKey_BEGIN/ImGuiKey_NamedKey_END?
+- Fonts: removed const qualifiers from most font functions in prevision for upcoming fonts improvements.
 
 Other changes:
 
@@ -61,7 +62,6 @@ Other changes:
   between _Header and _HeaderHovered which was introduced v1.91 (#8106, #1861)
 - Buttons: using ImGuiItemFlags_ButtonRepeat makes default button behavior use
   PressedOnClick instead of PressedOnClickRelease when unspecified.
-- Fonts: removed const qualifiers from most font functions.
 - InputText: fixed a bug (regression in 1.91.2) where modifying text buffer within
   a callback would sometimes prevents further appending to the buffer.
 - Tabs, Style: made ImGuiCol_TabDimmedSelectedOverline alpha 0 (not visible) in default
@@ -74,9 +74,9 @@ Other changes:
   and (3) text output comes in submission order rather than spatial order.
 - Backends: DX12: Unmap() call specify written range. The range is informational and
   may be used by debug tools.
-- Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the 
-  actual include. (#8095, #7967, #3190) [@sev-] 
-- Backends: SDL2, SDL3: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing 
+- Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the
+  actual include. (#8095, #7967, #3190) [@sev-]
+- Backends: SDL2, SDL3: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing
   by 100.0f on Emscripten target. (#4019, #6096, #1463)
 - Examples: SDL3+Vulkan: Added example. (#8084, #8085)
 - Examples: Android+OpenGL: Using ALooper_pollOnce() instead of ALooper_pollAll()
@@ -88,7 +88,7 @@ Other changes:
 
 Breaking changes:
 
-- Style: renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor, for consistency with 
+- Style: renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor, for consistency with
   newly exposed and reworked features. Kept inline redirection enum (will obsolete).
 - The typedef for ImTextureID now defaults to ImU64 instead of void*. (#1641)
   - This removes the requirement to redefine it for backends which are e.g. storing
@@ -104,9 +104,9 @@ Breaking changes:
   - Note that you can always define ImTextureID to be your own high-level structures
     (with dedicated constructors and extra render parameters) if you like.
 - IO: moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
-- IO: moved ImGuiConfigFlags_NavNoCaptureKeyboard to standalone io.ConfigNavCaptureKeyboard bool 
+- IO: moved ImGuiConfigFlags_NavNoCaptureKeyboard to standalone io.ConfigNavCaptureKeyboard bool
   (note the inverted value!). (#2517, #2009)
-  Kept legacy names (will obsolete) + code that copies settings once the first time. 
+  Kept legacy names (will obsolete) + code that copies settings once the first time.
   Dynamically changing the old value won't work. Switch to using the new value!
 
 Other changes:
@@ -122,48 +122,48 @@ Other changes:
      - Set io.ConfigNavCursorVisibleAuto = true (default) to enable automatic toggling
        of cursor visibility (mouse click hide the cursor, arrow keys makes it visible).
      - Set io.ConfigNavCursorVisibleAlways to keep cursor always visible.
-  - Nav: added NavSetCursorVisible(bool visible) function to manipulate visibility of 
+  - Nav: added NavSetCursorVisible(bool visible) function to manipulate visibility of
     navigation cursor (e.g. set default state, or after some actions). (#1074, #2048, #7237, #8059)
   - Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change
     how pressing Escape affects navigation. (#8059, #2048, #1074, #3200)
     - Set io.ConfigNavEscapeClearFocusItem = true (default) to clear focused item and highlight.
     - Set io.ConfigNavEscapeClearFocusItem = false for Escape to not have an effect.
     - Set io.ConfigNavEscapeClearFocusWindow = true to completely unfocus the dear imgui window,
-      is for some reason your app relies on imgui focus to take other decisions.  
+      is for some reason your app relies on imgui focus to take other decisions.
   - Nav: pressing escape to hide the navigation cursor doesn't clear location, so it may be
     restored when Ctrl+Tabbing back into the same window later.
   - Nav: fixed Ctrl+Tab initiated with no focused window from skipping the top-most window. (#3200)
-  - Nav: navigation cursor is not rendered for items with `ImGuiItemFlags_NoNav`. Can be relevant 
+  - Nav: navigation cursor is not rendered for items with `ImGuiItemFlags_NoNav`. Can be relevant
     when e.g activating a _NoNav item with mouse, then Ctrl+Tabbing back and forth.
-- Disabled: clicking a disabled item focuses parent window. (#8064) 
+- Disabled: clicking a disabled item focuses parent window. (#8064)
 - InvisibleButton, Nav: fixed an issue when InvisibleButton() would be navigable into but
   not display navigation highlight. Properly navigation on it by default. (#8057)
 - InvisibleButton: added ImGuiButtonFlags_EnableNav to enable navigation. (#8057)
-- Tooltips: fixed incorrect tooltip positioning when using keyboard/gamepad navigation 
+- Tooltips: fixed incorrect tooltip positioning when using keyboard/gamepad navigation
   (1.91.3 regression). (#8036)
 - DrawList: AddCallback() added an optional size parameter allowing to copy and
   store any amount of user data for usage by callbacks: (#6969, #4770, #7665)
   - If userdata_size == 0: we copy/store the 'userdata' argument as-is (existing behavior).
     It will be available unmodified in ImDrawCmd::UserCallbackData during render.
   - If userdata_size > 0, we copy/store 'userdata_size' bytes pointed to by 'userdata' (new behavior).
-    We store them in a buffer stored inside the drawlist. ImDrawCmd::UserCallbackData 
+    We store them in a buffer stored inside the drawlist. ImDrawCmd::UserCallbackData
     will point inside that buffer so you have to retrieve data from there. Your callback
     may need to use ImDrawCmd::UserCallbackDataSize if you expect dynamically-sized data.
   - Note that we use a raw type-less copy.
 - Tables: fixed initial auto-sizing issue with synced-instances. (#8045, #7218)
 - InputText: fixed an issue with not declaring ownership of Delete/Backspace/Arrow keys,
-  preventing use of external shortcuts that are not guarded by an ActiveId check. (#8048) 
+  preventing use of external shortcuts that are not guarded by an ActiveId check. (#8048)
   [@geertbleyen]
-- InputText: ensure mouse cursor shape is set regardless of whether keyboard mode is 
+- InputText: ensure mouse cursor shape is set regardless of whether keyboard mode is
   enabled or not. (#6417)
 - InputScalar: added an assert to clarify that ImGuiInputTextFlags_EnterReturnsTrue is not
   supported by InputFloat, InputInt, InputScalar etc. widgets. It actually never was. (#8065, #3946)
-- imgui_freetype: Added support for plutosvg (as an alternative to lunasvg) to render 
+- imgui_freetype: Added support for plutosvg (as an alternative to lunasvg) to render
   OpenType SVG fonts. Requires defining IMGUI_ENABLE_FREETYPE_PLUTOSVG along with IMGUI_ENABLE_FREETYPE.
   Providing headers/librairies for plutosvg + plutovg is up to you (see #7927 for help).
   (#7927, #7187, #6591, #6607) [@pthom]
 - Backends: DX11, DX12, SDLRenderer2/3. Vulkan, WGPU: expose selected state in
-  ImGui_ImplXXXX_RenderState structures during render loop user draw callbacks. 
+  ImGui_ImplXXXX_RenderState structures during render loop user draw callbacks.
   (#6969, #5834, #7468, #3590)
 - Backends: DX9, DX10, DX11, DX12, OpenGL, Vulkan, WGPU: Changed default texture sampler
   to Clamp instead of Repeat/Wrap. (#7468, #7511, #5999, #5502, #7230)
diff --git a/imgui.cpp b/imgui.cpp
index 7f853fa0f433..1f2dbc09a84b 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -440,6 +440,7 @@ CODE
                               - read https://github.com/ocornut/imgui/issues/4921
                             - if you have trouble updating a very old codebase using legacy backend-specific key codes: consider updating to 1.91.4 first, then #define IMGUI_DISABLE_OBSOLETE_KEYIO, then update to latest.
                        - obsoleted ImGuiKey_COUNT (it is unusually error-prone/misleading since valid keys don't start at 0). probably use ImGuiKey_NamedKey_BEGIN/ImGuiKey_NamedKey_END?
+                       - fonts: removed const qualifiers from most font functions in prevision for upcoming font improvements.
  - 2024/10/18 (1.91.4) - renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor (for consistency with newly exposed and reworked features). Kept inline redirection enum (will obsolete).
  - 2024/10/14 (1.91.4) - moved ImGuiConfigFlags_NavEnableSetMousePos to standalone io.ConfigNavMoveSetMousePos bool.
                          moved ImGuiConfigFlags_NavNoCaptureKeyboard to standalone io.ConfigNavCaptureKeyboard bool (note the inverted value!).

From 3b683927ee623d010725c7664cd4e2c4ac20085c Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 7 Nov 2024 14:39:54 +0100
Subject: [PATCH 254/548] imgui_freetype: Fixed a crash in build font atlas
 when using merged fonts and the first font in a merged set has no loaded
 glyph. (#8081)

---
 docs/CHANGELOG.txt               | 2 ++
 misc/freetype/imgui_freetype.cpp | 5 +++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index ebc128a04ac7..a1655fdabd90 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -72,6 +72,8 @@ Other changes:
   automatically copy window contents into clipboard using CTRL+C. This is experimental
   because (1) it currently breaks on nested Begin/End, (2) text output quality varies,
   and (3) text output comes in submission order rather than spatial order.
+- imgui_freetype: Fixed a crash in build font atlas when using merged fonts and the
+  first font in a merged set has no loaded glyph. (#8081)
 - Backends: DX12: Unmap() call specify written range. The range is informational and
   may be used by debug tools.
 - Backends: SDL2: Replace SDL_Vulkan_GetDrawableSize() forward declaration with the
diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp
index 646a3b14e2ec..c2d5f074c0fa 100644
--- a/misc/freetype/imgui_freetype.cpp
+++ b/misc/freetype/imgui_freetype.cpp
@@ -681,8 +681,6 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
     for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
     {
         ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
-        if (src_tmp.GlyphsCount == 0)
-            continue;
 
         // When merging fonts with MergeMode=true:
         // - We can have multiple input fonts writing into a same destination font.
@@ -693,6 +691,9 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
         const float ascent = src_tmp.Font.Info.Ascender;
         const float descent = src_tmp.Font.Info.Descender;
         ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
+
+        if (src_tmp.GlyphsCount == 0)
+            continue;
         const float font_off_x = cfg.GlyphOffset.x;
         const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent);
 

From 17bd417a3d18610dbdaba4b56296bdcf87c7cbbf Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 7 Nov 2024 14:57:16 +0100
Subject: [PATCH 255/548] AddCustomRectFontGlyph: added storage for Colored
 bool in ImFontAtlasCustomRect. (#8133)

---
 imgui.h        | 5 +++--
 imgui_draw.cpp | 3 +++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/imgui.h b/imgui.h
index ec3d6c0a7109..de6ec7b1c2cf 100644
--- a/imgui.h
+++ b/imgui.h
@@ -3278,11 +3278,12 @@ struct ImFontAtlasCustomRect
 {
     unsigned short  Width, Height;  // Input    // Desired rectangle dimension
     unsigned short  X, Y;           // Output   // Packed position in Atlas
-    unsigned int    GlyphID;        // Input    // For custom font glyphs only (ID < 0x110000)
+    unsigned int    GlyphID : 31;   // Input    // For custom font glyphs only (ID < 0x110000)
+    unsigned int    GlyphColored : 1; // Input  // For custom font glyphs only: glyph is colored, removed tinting.
     float           GlyphAdvanceX;  // Input    // For custom font glyphs only: glyph xadvance
     ImVec2          GlyphOffset;    // Input    // For custom font glyphs only: glyph display offset
     ImFont*         Font;           // Input    // For custom font glyphs only: target font
-    ImFontAtlasCustomRect()         { Width = Height = 0; X = Y = 0xFFFF; GlyphID = 0; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0, 0); Font = NULL; }
+    ImFontAtlasCustomRect()         { Width = Height = 0; X = Y = 0xFFFF; GlyphID = 0; GlyphColored = 0; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0, 0); Font = NULL; }
     bool IsPacked() const           { return X != 0xFFFF; }
 };
 
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 43a49eb299c6..c0a5b5b7585b 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -2676,6 +2676,7 @@ int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int
     r.Width = (unsigned short)width;
     r.Height = (unsigned short)height;
     r.GlyphID = id;
+    r.GlyphColored = 0; // Set to 1 manually to mark glyph as colored // FIXME: No official API for that (#8133)
     r.GlyphAdvanceX = advance_x;
     r.GlyphOffset = offset;
     r.Font = font;
@@ -3286,6 +3287,8 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
         ImVec2 uv0, uv1;
         atlas->CalcCustomRectUV(r, &uv0, &uv1);
         r->Font->AddGlyph(NULL, (ImWchar)r->GlyphID, r->GlyphOffset.x, r->GlyphOffset.y, r->GlyphOffset.x + r->Width, r->GlyphOffset.y + r->Height, uv0.x, uv0.y, uv1.x, uv1.y, r->GlyphAdvanceX);
+        if (r->GlyphColored)
+            r->Font->Glyphs.back().Colored = 1;
     }
 
     // Build all fonts lookup tables

From 419a9ada16eb9b6d84ead4911b9c2a32820cfffb Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 7 Nov 2024 19:08:37 +0100
Subject: [PATCH 256/548] Ignore clang warning Wnontrivial-memaccess (#8129,
 #8135)

Amend 88e2327
Use void* cast in backend where the memset are infrequent.
---
 backends/imgui_impl_metal.mm   | 9 +--------
 backends/imgui_impl_osx.mm     | 9 +--------
 backends/imgui_impl_vulkan.cpp | 6 +++---
 imgui.cpp                      | 1 +
 imgui.h                        | 1 +
 imgui_tables.cpp               | 1 +
 imgui_widgets.cpp              | 1 +
 7 files changed, 9 insertions(+), 19 deletions(-)

diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm
index 102f6982afd8..12dc3d50f52c 100644
--- a/backends/imgui_impl_metal.mm
+++ b/backends/imgui_impl_metal.mm
@@ -38,13 +38,6 @@
 #import 
 #import 
 
-#if defined(__clang__)
-#if __has_warning("-Wunknown-warning-option")
-#pragma clang diagnostic ignored "-Wunknown-warning-option"         // warning: unknown warning group 'xxx'
-#endif
-#pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
-#endif
-
 #pragma mark - Support classes
 
 // A wrapper around a MTLBuffer object that knows the last time it was reused
@@ -83,7 +76,7 @@ - (MetalBuffer*)dequeueReusableBufferOfLength:(NSUInteger)length device:(id
 #import 
 
-#if defined(__clang__)
-#if __has_warning("-Wunknown-warning-option")
-#pragma clang diagnostic ignored "-Wunknown-warning-option"         // warning: unknown warning group 'xxx'
-#endif
-#pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
-#endif
-
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
 //  2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO:
@@ -94,7 +87,7 @@
     id                          Monitor;
     NSWindow*                   Window;
 
-    ImGui_ImplOSX_Data()        { memset(this, 0, sizeof(*this)); }
+    ImGui_ImplOSX_Data()        { memset((void*)this, 0, sizeof(*this)); }
 };
 
 static ImGui_ImplOSX_Data*      ImGui_ImplOSX_GetBackendData()      { return (ImGui_ImplOSX_Data*)ImGui::GetIO().BackendPlatformUserData; }
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index 4e4e332fc207..d499ecb92350 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -489,7 +489,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
         wrb->Index = 0;
         wrb->Count = v->ImageCount;
         wrb->FrameRenderBuffers = (ImGui_ImplVulkan_FrameRenderBuffers*)IM_ALLOC(sizeof(ImGui_ImplVulkan_FrameRenderBuffers) * wrb->Count);
-        memset(wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkan_FrameRenderBuffers) * wrb->Count);
+        memset((void*)wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkan_FrameRenderBuffers) * wrb->Count);
     }
     IM_ASSERT(wrb->Count == v->ImageCount);
     wrb->Index = (wrb->Index + 1) % wrb->Count;
@@ -1445,8 +1445,8 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
         wd->SemaphoreCount = wd->ImageCount + 1;
         wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount);
         wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->SemaphoreCount);
-        memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount);
-        memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->SemaphoreCount);
+        memset((void*)wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount);
+        memset((void*)wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->SemaphoreCount);
         for (uint32_t i = 0; i < wd->ImageCount; i++)
             wd->Frames[i].Backbuffer = backbuffers[i];
     }
diff --git a/imgui.cpp b/imgui.cpp
index 1f2dbc09a84b..2ea9417b44ac 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1135,6 +1135,7 @@ CODE
 #pragma clang diagnostic ignored "-Wdouble-promotion"               // warning: implicit conversion from 'float' to 'double' when passing argument to function  // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
 #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
+#pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
 #elif defined(__GNUC__)
 // We disable -Wpragmas because GCC doesn't provide a has_warning equivalent and some forks/patches may not follow the warning/version association.
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
diff --git a/imgui.h b/imgui.h
index de6ec7b1c2cf..32425db89a12 100644
--- a/imgui.h
+++ b/imgui.h
@@ -135,6 +135,7 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"  // warning: zero as null pointer constant
 #pragma clang diagnostic ignored "-Wreserved-identifier"            // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
+#pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
 #elif defined(__GNUC__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index 03007bb79913..122cd87b1a72 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -229,6 +229,7 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
 #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
+#pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
 #elif defined(__GNUC__)
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"                // warning: format not a string literal, format string not checked
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 9d572422283f..bb445d977311 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -79,6 +79,7 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
 #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
+#pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
 #elif defined(__GNUC__)
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"                // warning: format not a string literal, format string not checked

From 01d27a4acde14c13e86adfcd0569e752f181e205 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 7 Nov 2024 16:58:50 +0100
Subject: [PATCH 257/548] Internals: added IM_LIKELY(), IM_UNLIKELY() helper
 macros (yet unused). Added ImFontGetCharAdvanceX() macro.

---
 imgui_draw.cpp   | 16 +++++++++-------
 imgui_internal.h |  9 +++++++++
 2 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index c0a5b5b7585b..7934949ec95c 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -3847,7 +3847,7 @@ const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c)
     return &Glyphs.Data[i];
 }
 
-// Wrapping skips upcoming blanks
+// Trim trailing space and find beginning of next line
 static inline const char* CalcWordWrapNextLineStartA(const char* text, const char* text_end)
 {
     while (text < text_end && ImCharIsBlankA(*text))
@@ -3857,6 +3857,8 @@ static inline const char* CalcWordWrapNextLineStartA(const char* text, const cha
     return text;
 }
 
+#define ImFontGetCharAdvanceX(_FONT, _CH)  ((int)(_CH) < (_FONT)->IndexAdvanceX.Size ? (_FONT)->IndexAdvanceX.Data[_CH] : (_FONT)->FallbackAdvanceX)
+
 // Simple word-wrapping for English, not full-featured. Please submit failing cases!
 // This will return the next location to wrap from. If no wrapping if necessary, this will fast-forward to e.g. text_end.
 // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.)
@@ -3909,7 +3911,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
             }
         }
 
-        const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX);
+        const float char_width = ImFontGetCharAdvanceX(this, c);
         if (ImCharIsBlankW(c))
         {
             if (inside_word)
@@ -4014,7 +4016,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
                 continue;
         }
 
-        const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX) * scale;
+        const float char_width = ImFontGetCharAdvanceX(this, c);
         if (line_width + char_width >= max_width)
         {
             s = prev_s;
@@ -4063,9 +4065,9 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
     if (y > clip_rect.w)
         return;
 
-    const float start_x = x;
     const float scale = size / FontSize;
     const float line_height = FontSize * scale;
+    const float origin_x = x;
     const bool word_wrap_enabled = (wrap_width > 0.0f);
 
     // Fast-forward to first visible line
@@ -4124,11 +4126,11 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
         {
             // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
             if (!word_wrap_eol)
-                word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - start_x));
+                word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - origin_x));
 
             if (s >= word_wrap_eol)
             {
-                x = start_x;
+                x = origin_x;
                 y += line_height;
                 if (y > clip_rect.w)
                     break; // break out of main loop
@@ -4149,7 +4151,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
         {
             if (c == '\n')
             {
-                x = start_x;
+                x = origin_x;
                 y += line_height;
                 if (y > clip_rect.w)
                     break; // break out of main loop
diff --git a/imgui_internal.h b/imgui_internal.h
index 6d84f1027aca..9e6452bcb37e 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -260,6 +260,15 @@ extern IMGUI_API ImGuiContext* GImGui;  // Current implicit context pointer
 #define IM_FLOOR IM_TRUNC
 #endif
 
+// Hint for branch prediction
+#if (defined(__cplusplus) && (__cplusplus >= 202002L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 202002L))
+#define IM_LIKELY   [[likely]]
+#define IM_UNLIKELY [[unlikely]]
+#else
+#define IM_LIKELY
+#define IM_UNLIKELY
+#endif
+
 // Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall
 #ifdef _MSC_VER
 #define IMGUI_CDECL __cdecl

From 31b967f098dc53a6bb36f9be36f4a9e5d592f775 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 7 Nov 2024 19:35:00 +0100
Subject: [PATCH 258/548] Fix 01d27a4 (sorry I cherry-picked from wrong branch)

---
 imgui_draw.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 7934949ec95c..48d42f392822 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -4016,7 +4016,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
                 continue;
         }
 
-        const float char_width = ImFontGetCharAdvanceX(this, c);
+        const float char_width = ImFontGetCharAdvanceX(this, c) * scale;
         if (line_width + char_width >= max_width)
         {
             s = prev_s;

From f401021d5a5d56fe2304056c391e78f81c8d4b8f Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 7 Nov 2024 19:38:30 +0100
Subject: [PATCH 259/548] Version 1.91.5

---
 docs/CHANGELOG.txt | 14 +++++++++-----
 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(+), 14 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index a1655fdabd90..ce752ca290d0 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -36,9 +36,11 @@ HOW TO UPDATE?
 - Please report any issue!
 
 -----------------------------------------------------------------------
- VERSION 1.91.5 WIP (In Progress)
+ VERSION 1.91.5 (Released 2024-11-07)
 -----------------------------------------------------------------------
 
+Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.5
+
 Breaking changes:
 
 - Commented out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before).
@@ -47,8 +49,8 @@ Breaking changes:
   - Pre-1.87 backends are not supported:
     - backends need to call io.AddKeyEvent(), io.AddMouseEvent() instead of writing to io.KeysDown[], io.MouseDown[] fields.
     - backends need to call io.AddKeyAnalogEvent() for gamepad values instead of writing to io.NavInputs[] fields.
-  - For more reference:
-    - read 1.87 and 1.88 part of this section or read Changelog for 1.87 and 1.88.
+  - For more references:
+    - read 1.87 and 1.88 part of API BREAKING CHANGES in imgui.cpp or read Changelog for 1.87 and 1.88.
     - read https://github.com/ocornut/imgui/issues/4921
   - If you have trouble updating a very old codebase using legacy backend-specific key codes:
     consider updating to 1.91.4 first, then #define IMGUI_DISABLE_OBSOLETE_KEYIO, then update to latest.
@@ -66,12 +68,12 @@ Other changes:
   a callback would sometimes prevents further appending to the buffer.
 - Tabs, Style: made ImGuiCol_TabDimmedSelectedOverline alpha 0 (not visible) in default
   styles as the current look is not right (but ImGuiCol_TabSelectedOverline stays the same).
-- Log/Capture: better decorating of BeginMenu() and TabItem() output.
-- Log/Capture: a non terminated log ends automatically in the window which called it.
 - Log/Capture: added experimental io.ConfigWindowsCopyContentsWithCtrlC option to
   automatically copy window contents into clipboard using CTRL+C. This is experimental
   because (1) it currently breaks on nested Begin/End, (2) text output quality varies,
   and (3) text output comes in submission order rather than spatial order.
+- Log/Capture: better decorating of BeginMenu() and TabItem() output.
+- Log/Capture: a non terminated log ends automatically in the window which called it.
 - imgui_freetype: Fixed a crash in build font atlas when using merged fonts and the
   first font in a merged set has no loaded glyph. (#8081)
 - Backends: DX12: Unmap() call specify written range. The range is informational and
@@ -88,6 +90,8 @@ Other changes:
  VERSION 1.91.4 (Released 2024-10-18)
 -----------------------------------------------------------------------
 
+Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.4
+
 Breaking changes:
 
 - Style: renamed ImGuiCol_NavHighlight to ImGuiCol_NavCursor, for consistency with
diff --git a/imgui.cpp b/imgui.cpp
index 2ea9417b44ac..4624c45d9ee0 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5 WIP
+// dear imgui, v1.91.5
 // (main code and documentation)
 
 // Help:
diff --git a/imgui.h b/imgui.h
index 32425db89a12..d6286592bb91 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5 WIP
+// dear imgui, v1.91.5
 // (headers)
 
 // Help:
@@ -28,8 +28,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.5 WIP"
-#define IMGUI_VERSION_NUM   19144
+#define IMGUI_VERSION       "1.91.5"
+#define IMGUI_VERSION_NUM   19150
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index e28ca3b7aac4..76a06cc7d334 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5 WIP
+// dear imgui, v1.91.5
 // (demo code)
 
 // Help:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 48d42f392822..fa82a9419376 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5 WIP
+// dear imgui, v1.91.5
 // (drawing and font code)
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index 9e6452bcb37e..49452ab0ad22 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5 WIP
+// dear imgui, v1.91.5
 // (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 122cd87b1a72..e36e6f17289e 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5 WIP
+// dear imgui, v1.91.5
 // (tables and columns code)
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index bb445d977311..b5d66baa02af 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5 WIP
+// dear imgui, v1.91.5
 // (widgets code)
 
 /*

From 3381ab423b359bda18ef47e9919643bbaf5cc131 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 12 Nov 2024 11:44:29 +0100
Subject: [PATCH 260/548] Version 1.91.6 WIP + fixed typo in tooltip.

---
 docs/CHANGELOG.txt | 9 +++++++++
 imgui.cpp          | 4 ++--
 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, 19 insertions(+), 10 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index ce752ca290d0..67d5bef53308 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -35,6 +35,14 @@ 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.6 WIP (In Progress)
+-----------------------------------------------------------------------
+
+Breaking changes:
+
+Other changes:
+
 -----------------------------------------------------------------------
  VERSION 1.91.5 (Released 2024-11-07)
 -----------------------------------------------------------------------
@@ -86,6 +94,7 @@ Other changes:
 - Examples: Android+OpenGL: Using ALooper_pollOnce() instead of ALooper_pollAll()
   which has been deprecated. (#8013) [@feather179]
 
+
 -----------------------------------------------------------------------
  VERSION 1.91.4 (Released 2024-10-18)
 -----------------------------------------------------------------------
diff --git a/imgui.cpp b/imgui.cpp
index 4624c45d9ee0..431cac9c168e 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5
+// dear imgui, v1.91.6 WIP
 // (main code and documentation)
 
 // Help:
@@ -10579,7 +10579,7 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
         BulletText("Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
         BulletText("Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
         //BulletText("Code intending to use duplicate ID may use e.g. PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()"); // Not making this too visible for fear of it being abused.
-        BulletText("Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
+        BulletText("Set io.ConfigDebugHighlightIdConflicts=false to disable this warning in non-programmers builds.");
         Separator();
         Text("(Hold CTRL to: use");
         SameLine();
diff --git a/imgui.h b/imgui.h
index d6286592bb91..815b079242bf 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5
+// dear imgui, v1.91.6 WIP
 // (headers)
 
 // Help:
@@ -28,8 +28,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.5"
-#define IMGUI_VERSION_NUM   19150
+#define IMGUI_VERSION       "1.91.6 WIP"
+#define IMGUI_VERSION_NUM   19151
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 76a06cc7d334..ac34e6b1d5da 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5
+// dear imgui, v1.91.6 WIP
 // (demo code)
 
 // Help:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index fa82a9419376..0003fe1e2963 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5
+// dear imgui, v1.91.6 WIP
 // (drawing and font code)
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index 49452ab0ad22..2af196cb789e 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5
+// dear imgui, v1.91.6 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 e36e6f17289e..5254f7858743 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5
+// dear imgui, v1.91.6 WIP
 // (tables and columns code)
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index b5d66baa02af..c60378f82140 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.5
+// dear imgui, v1.91.6 WIP
 // (widgets code)
 
 /*

From e97b97467e434d2c53b76a19563d641e55130e16 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Tue, 12 Nov 2024 19:09:00 +0100
Subject: [PATCH 261/548] Error Handling: fixed cases where recoverable error
 handling would crash. (#1651)

---
 docs/CHANGELOG.txt | 4 ++++
 imgui.cpp          | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 67d5bef53308..6586cba20486 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,10 @@ Breaking changes:
 
 Other changes:
 
+- Error Handling: fixed cases where recoverable error handling would crash when 
+  processing errors outside of the NewFrame()..EndFrame() scope. (#1651)
+
+
 -----------------------------------------------------------------------
  VERSION 1.91.5 (Released 2024-11-07)
 -----------------------------------------------------------------------
diff --git a/imgui.cpp b/imgui.cpp
index 431cac9c168e..45af644aed36 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -10542,7 +10542,7 @@ bool    ImGui::ErrorLog(const char* msg)
     // Output to tooltip
     if (g.IO.ConfigErrorRecoveryEnableTooltip)
     {
-        if (BeginErrorTooltip())
+        if (g.WithinFrameScope && BeginErrorTooltip())
         {
             if (g.ErrorCountCurrentFrame < 20)
             {

From 8be0723fb7a626f0fad6e70a2ad9139e442c4008 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 13 Nov 2024 16:55:06 +0100
Subject: [PATCH 262/548] Amend Changelog to better document how changing
 button behavior of InputInt/InputFloat step buttons affected some mis-uses
 (#8149)

---
 docs/CHANGELOG.txt | 5 +++++
 imgui.cpp          | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 6586cba20486..0dc526e24dbb 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -76,6 +76,11 @@ Other changes:
   between _Header and _HeaderHovered which was introduced v1.91 (#8106, #1861)
 - Buttons: using ImGuiItemFlags_ButtonRepeat makes default button behavior use
   PressedOnClick instead of PressedOnClickRelease when unspecified.
+  - This is intended to make the +/- buttons of InputInt/InputFloat react on the
+    initial mouse down event.
+  - Note that it may reveal incorrect usage if you were using InputInt/InputFloat
+    without persistent storage by relying solely on e.g. IsItemDeactivatedAfterEdit():
+    this was never supported and didn't work consistantly (see #8149).
 - InputText: fixed a bug (regression in 1.91.2) where modifying text buffer within
   a callback would sometimes prevents further appending to the buffer.
 - Tabs, Style: made ImGuiCol_TabDimmedSelectedOverline alpha 0 (not visible) in default
diff --git a/imgui.cpp b/imgui.cpp
index 45af644aed36..3512ec87dda9 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -5788,7 +5788,7 @@ bool ImGui::IsItemDeactivatedAfterEdit()
     return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEditedBefore || (g.ActiveId == 0 && g.ActiveIdHasBeenEditedBefore));
 }
 
-// == GetItemID() == GetFocusID()
+// == (GetItemID() == GetFocusID() && GetFocusID() != 0)
 bool ImGui::IsItemFocused()
 {
     ImGuiContext& g = *GImGui;

From 3260ea6954554f5cfac7461e94bc18d14cce3617 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 15 Nov 2024 16:03:58 +0100
Subject: [PATCH 263/548] Examples: Win32+DX12: Tweaks.

---
 backends/imgui_impl_dx12.cpp              |  3 ++
 backends/imgui_impl_dx12.h                |  3 ++
 examples/example_win32_directx12/main.cpp | 36 +++++++++++------------
 3 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index 7a428a1a5ad1..24b195bda900 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -6,6 +6,9 @@
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
+// The aim of imgui_impl_dx12.h/.cpp is to be usable in your engine without any modification.
+// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
+
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 // Learn about Dear ImGui:
diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h
index 1e36d730f77b..b5a8dde2e7f2 100644
--- a/backends/imgui_impl_dx12.h
+++ b/backends/imgui_impl_dx12.h
@@ -6,6 +6,9 @@
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
+// The aim of imgui_impl_dx12.h/.cpp is to be usable in your engine without any modification.
+// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
+
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 // Learn about Dear ImGui:
diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp
index 4173a8010c6b..168b6966038e 100644
--- a/examples/example_win32_directx12/main.cpp
+++ b/examples/example_win32_directx12/main.cpp
@@ -22,20 +22,20 @@
 #pragma comment(lib, "dxguid.lib")
 #endif
 
-#include "imgui_internal.h"
+// Config for example app
+static const int APP_NUM_FRAMES_IN_FLIGHT = 3;
+static const int APP_NUM_BACK_BUFFERS = 3;
 
 struct FrameContext
 {
-    ID3D12CommandAllocator* CommandAllocator;
-    UINT64                  FenceValue;
+    ID3D12CommandAllocator*     CommandAllocator;
+    UINT64                      FenceValue;
 };
 
 // Data
-static int const                    NUM_FRAMES_IN_FLIGHT = 3;
-static FrameContext                 g_frameContext[NUM_FRAMES_IN_FLIGHT] = {};
+static FrameContext                 g_frameContext[APP_NUM_FRAMES_IN_FLIGHT] = {};
 static UINT                         g_frameIndex = 0;
 
-static int const                    NUM_BACK_BUFFERS = 3;
 static ID3D12Device*                g_pd3dDevice = nullptr;
 static ID3D12DescriptorHeap*        g_pd3dRtvDescHeap = nullptr;
 static ID3D12DescriptorHeap*        g_pd3dSrvDescHeap = nullptr;
@@ -47,8 +47,8 @@ static UINT64                       g_fenceLastSignaledValue = 0;
 static IDXGISwapChain3*             g_pSwapChain = nullptr;
 static bool                         g_SwapChainOccluded = false;
 static HANDLE                       g_hSwapChainWaitableObject = nullptr;
-static ID3D12Resource*              g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {};
-static D3D12_CPU_DESCRIPTOR_HANDLE  g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {};
+static ID3D12Resource*              g_mainRenderTargetResource[APP_NUM_BACK_BUFFERS] = {};
+static D3D12_CPU_DESCRIPTOR_HANDLE  g_mainRenderTargetDescriptor[APP_NUM_BACK_BUFFERS] = {};
 
 // Forward declarations of helper functions
 bool CreateDeviceD3D(HWND hWnd);
@@ -249,7 +249,7 @@ bool CreateDeviceD3D(HWND hWnd)
     DXGI_SWAP_CHAIN_DESC1 sd;
     {
         ZeroMemory(&sd, sizeof(sd));
-        sd.BufferCount = NUM_BACK_BUFFERS;
+        sd.BufferCount = APP_NUM_BACK_BUFFERS;
         sd.Width = 0;
         sd.Height = 0;
         sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
@@ -292,7 +292,7 @@ bool CreateDeviceD3D(HWND hWnd)
     {
         D3D12_DESCRIPTOR_HEAP_DESC desc = {};
         desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
-        desc.NumDescriptors = NUM_BACK_BUFFERS;
+        desc.NumDescriptors = APP_NUM_BACK_BUFFERS;
         desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
         desc.NodeMask = 1;
         if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dRtvDescHeap)) != S_OK)
@@ -300,7 +300,7 @@ bool CreateDeviceD3D(HWND hWnd)
 
         SIZE_T rtvDescriptorSize = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
         D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = g_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart();
-        for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
+        for (UINT i = 0; i < APP_NUM_BACK_BUFFERS; i++)
         {
             g_mainRenderTargetDescriptor[i] = rtvHandle;
             rtvHandle.ptr += rtvDescriptorSize;
@@ -325,7 +325,7 @@ bool CreateDeviceD3D(HWND hWnd)
             return false;
     }
 
-    for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++)
+    for (UINT i = 0; i < APP_NUM_FRAMES_IN_FLIGHT; i++)
         if (g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&g_frameContext[i].CommandAllocator)) != S_OK)
             return false;
 
@@ -351,7 +351,7 @@ bool CreateDeviceD3D(HWND hWnd)
             return false;
         swapChain1->Release();
         dxgiFactory->Release();
-        g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
+        g_pSwapChain->SetMaximumFrameLatency(APP_NUM_BACK_BUFFERS);
         g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
     }
 
@@ -364,7 +364,7 @@ void CleanupDeviceD3D()
     CleanupRenderTarget();
     if (g_pSwapChain) { g_pSwapChain->SetFullscreenState(false, nullptr); g_pSwapChain->Release(); g_pSwapChain = nullptr; }
     if (g_hSwapChainWaitableObject != nullptr) { CloseHandle(g_hSwapChainWaitableObject); }
-    for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++)
+    for (UINT i = 0; i < APP_NUM_FRAMES_IN_FLIGHT; i++)
         if (g_frameContext[i].CommandAllocator) { g_frameContext[i].CommandAllocator->Release(); g_frameContext[i].CommandAllocator = nullptr; }
     if (g_pd3dCommandQueue) { g_pd3dCommandQueue->Release(); g_pd3dCommandQueue = nullptr; }
     if (g_pd3dCommandList) { g_pd3dCommandList->Release(); g_pd3dCommandList = nullptr; }
@@ -386,7 +386,7 @@ void CleanupDeviceD3D()
 
 void CreateRenderTarget()
 {
-    for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
+    for (UINT i = 0; i < APP_NUM_BACK_BUFFERS; i++)
     {
         ID3D12Resource* pBackBuffer = nullptr;
         g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer));
@@ -399,13 +399,13 @@ void CleanupRenderTarget()
 {
     WaitForLastSubmittedFrame();
 
-    for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
+    for (UINT i = 0; i < APP_NUM_BACK_BUFFERS; i++)
         if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = nullptr; }
 }
 
 void WaitForLastSubmittedFrame()
 {
-    FrameContext* frameCtx = &g_frameContext[g_frameIndex % NUM_FRAMES_IN_FLIGHT];
+    FrameContext* frameCtx = &g_frameContext[g_frameIndex % APP_NUM_FRAMES_IN_FLIGHT];
 
     UINT64 fenceValue = frameCtx->FenceValue;
     if (fenceValue == 0)
@@ -427,7 +427,7 @@ FrameContext* WaitForNextFrameResources()
     HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, nullptr };
     DWORD numWaitableObjects = 1;
 
-    FrameContext* frameCtx = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT];
+    FrameContext* frameCtx = &g_frameContext[nextFrameIndex % APP_NUM_FRAMES_IN_FLIGHT];
     UINT64 fenceValue = frameCtx->FenceValue;
     if (fenceValue != 0) // means no fence was signaled
     {

From 40b2286d16e92ea017347a62cb91e63f378ff455 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 15 Nov 2024 19:02:26 +0100
Subject: [PATCH 264/548] (Breaking) Backends: DX12: changed
 ImGui_ImplDX12_Init() signature. Added ImGui_ImplDX12_InitInfo. Added support
 for Srv allocators.

Ref 7708
---
 backends/imgui_impl_dx12.cpp              | 67 +++++++++++++++++++----
 backends/imgui_impl_dx12.h                | 40 ++++++++++----
 docs/CHANGELOG.txt                        | 10 ++++
 examples/example_win32_directx12/main.cpp | 66 ++++++++++++++++++++--
 4 files changed, 155 insertions(+), 28 deletions(-)

diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index 24b195bda900..105bcb213289 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -19,6 +19,8 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-11-15: DirectX12: *BREAKING CHANGE* Changed ImGui_ImplDX12_Init() signature to take a ImGui_ImplDX12_InitInfo struct. Legacy ImGui_ImplDX12_Init() signature is still supported (will obsolete).
+//  2024-11-15: DirectX12: *BREAKING CHANGE* User is now required to pass function pointers to allocate/free SRV Descriptors. We provide convenience legacy fields to pass a single descriptor, matching the old API, but upcoming features will want multiple.
 //  2024-10-23: DirectX12: Unmap() call specify written range. The range is informational and may be used by debug tools.
 //  2024-10-07: DirectX12: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-10-07: DirectX12: Expose selected render state in ImGui_ImplDX12_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
@@ -57,6 +59,7 @@
 struct ImGui_ImplDX12_RenderBuffers;
 struct ImGui_ImplDX12_Data
 {
+    ImGui_ImplDX12_InitInfo     InitInfo;
     ID3D12Device*               pd3dDevice;
     ID3D12RootSignature*        pRootSignature;
     ID3D12PipelineState*        pPipelineState;
@@ -695,8 +698,14 @@ void    ImGui_ImplDX12_InvalidateDeviceObjects()
     ImGuiIO& io = ImGui::GetIO();
     SafeRelease(bd->pRootSignature);
     SafeRelease(bd->pPipelineState);
+
+    // Free SRV descriptor used by texture
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+    if (bd->InitInfo.SrvDescriptorFreeFn != NULL)
+#endif
+        bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, bd->hFontSrvCpuDescHandle, bd->hFontSrvGpuDescHandle);
     SafeRelease(bd->pFontTextureResource);
-    io.Fonts->SetTexID(0); // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
+    io.Fonts->SetTexID(0); // We copied bd->hFontSrvGpuDescHandle to io.Fonts->TexID so let's clear that as well.
 
     for (UINT i = 0; i < bd->numFramesInFlight; i++)
     {
@@ -706,8 +715,7 @@ void    ImGui_ImplDX12_InvalidateDeviceObjects()
     }
 }
 
-bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
-                         D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle)
+bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
 {
     ImGuiIO& io = ImGui::GetIO();
     IMGUI_CHECKVERSION();
@@ -715,21 +723,39 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
 
     // Setup backend capabilities flags
     ImGui_ImplDX12_Data* bd = IM_NEW(ImGui_ImplDX12_Data)();
+
+    bd->InitInfo = *init_info; // Deep copy
+    bd->pd3dDevice = init_info->Device;
+    bd->RTVFormat = init_info->RTVFormat;
+    bd->numFramesInFlight = init_info->NumFramesInFlight;
+    bd->pd3dSrvDescHeap = init_info->SrvDescriptorHeap;
+
     io.BackendRendererUserData = (void*)bd;
     io.BackendRendererName = "imgui_impl_dx12";
     io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;  // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
 
-    bd->pd3dDevice = device;
-    bd->RTVFormat = rtv_format;
-    bd->hFontSrvCpuDescHandle = font_srv_cpu_desc_handle;
-    bd->hFontSrvGpuDescHandle = font_srv_gpu_desc_handle;
-    bd->pFrameResources = new ImGui_ImplDX12_RenderBuffers[num_frames_in_flight];
-    bd->numFramesInFlight = num_frames_in_flight;
-    bd->pd3dSrvDescHeap = cbv_srv_heap;
-    bd->frameIndex = UINT_MAX;
+    // Allocate 1 SRV descriptor for the font texture
+    if (init_info->SrvDescriptorAllocFn != NULL)
+    {
+        IM_ASSERT(init_info->SrvDescriptorFreeFn != NULL);
+        init_info->SrvDescriptorAllocFn(&bd->InitInfo, &bd->hFontSrvCpuDescHandle, &bd->hFontSrvGpuDescHandle);
+    }
+    else
+    {
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+        IM_ASSERT(init_info->LegacySingleSrvCpuDescriptor.ptr != 0 && init_info->LegacySingleSrvGpuDescriptor.ptr != 0);
+        bd->hFontSrvCpuDescHandle = init_info->LegacySingleSrvCpuDescriptor;
+        bd->hFontSrvGpuDescHandle = init_info->LegacySingleSrvGpuDescriptor;
+#else
+        IM_ASSERT(init_info->SrvDescriptorAllocFn != NULL);
+        IM_ASSERT(init_info->SrvDescriptorFreeFn != NULL);
+#endif
+    }
 
     // Create buffers with a default size (they will later be grown as needed)
-    for (int i = 0; i < num_frames_in_flight; i++)
+    bd->frameIndex = UINT_MAX;
+    bd->pFrameResources = new ImGui_ImplDX12_RenderBuffers[bd->numFramesInFlight];
+    for (int i = 0; i < (int)bd->numFramesInFlight; i++)
     {
         ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[i];
         fr->IndexBuffer = nullptr;
@@ -741,6 +767,22 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO
     return true;
 }
 
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+// Legacy initialization API Obsoleted in 1.91.5
+// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap'
+bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* srv_descriptor_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle)
+{
+    ImGui_ImplDX12_InitInfo init_info;
+    init_info.Device = device;
+    init_info.NumFramesInFlight = num_frames_in_flight;
+    init_info.RTVFormat = rtv_format;
+    init_info.SrvDescriptorHeap = srv_descriptor_heap;
+    init_info.LegacySingleSrvCpuDescriptor = font_srv_cpu_desc_handle;
+    init_info.LegacySingleSrvGpuDescriptor = font_srv_gpu_desc_handle;;
+    return ImGui_ImplDX12_Init(&init_info);
+}
+#endif
+
 void ImGui_ImplDX12_Shutdown()
 {
     ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
@@ -750,6 +792,7 @@ void ImGui_ImplDX12_Shutdown()
     // Clean up windows and device objects
     ImGui_ImplDX12_InvalidateDeviceObjects();
     delete[] bd->pFrameResources;
+
     io.BackendRendererName = nullptr;
     io.BackendRendererUserData = nullptr;
     io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset;
diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h
index b5a8dde2e7f2..34938fb56347 100644
--- a/backends/imgui_impl_dx12.h
+++ b/backends/imgui_impl_dx12.h
@@ -21,24 +21,42 @@
 #include "imgui.h"      // IMGUI_IMPL_API
 #ifndef IMGUI_DISABLE
 #include  // DXGI_FORMAT
+#include       // D3D12_CPU_DESCRIPTOR_HANDLE
 
-struct ID3D12Device;
-struct ID3D12DescriptorHeap;
-struct ID3D12GraphicsCommandList;
-struct D3D12_CPU_DESCRIPTOR_HANDLE;
-struct D3D12_GPU_DESCRIPTOR_HANDLE;
+// Initialization data, for ImGui_ImplDX12_Init()
+struct ImGui_ImplDX12_InitInfo
+{
+    ID3D12Device*               Device;
+    ID3D12CommandQueue*         CommandQueue;
+    int                         NumFramesInFlight;
+    DXGI_FORMAT                 RTVFormat;
+    void*                       UserData;
 
-// Follow "Getting Started" link and check examples/ folder to learn about using backends!
+    // Allocating SRV descriptors for textures is up to the application, so we provide callbacks.
+    // (current version of the backend will only allocate one descriptor, future versions will need to allocate more)
+    ID3D12DescriptorHeap*       SrvDescriptorHeap;
+    void                        (*SrvDescriptorAllocFn)(ImGui_ImplDX12_InitInfo* info, D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_desc_handle);
+    void                        (*SrvDescriptorFreeFn)(ImGui_ImplDX12_InitInfo* info, D3D12_CPU_DESCRIPTOR_HANDLE cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE gpu_desc_handle);
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+    D3D12_CPU_DESCRIPTOR_HANDLE LegacySingleSrvCpuDescriptor; // To facilitate transition from single descriptor to allocator callback, you may use those.
+    D3D12_GPU_DESCRIPTOR_HANDLE LegacySingleSrvGpuDescriptor;
+#endif
 
-// Before calling the render function, caller must prepare the command list by resetting it and setting the appropriate
-// render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle.
-// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture.
-IMGUI_IMPL_API bool     ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
-                                            D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle);
+    ImGui_ImplDX12_InitInfo()   { memset(this, 0, sizeof(*this)); }
+};
+
+// Follow "Getting Started" link and check examples/ folder to learn about using backends!
+IMGUI_IMPL_API bool     ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* info);
 IMGUI_IMPL_API void     ImGui_ImplDX12_Shutdown();
 IMGUI_IMPL_API void     ImGui_ImplDX12_NewFrame();
 IMGUI_IMPL_API void     ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list);
 
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+// Legacy initialization API Obsoleted in 1.91.5
+// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap'
+IMGUI_IMPL_API bool     ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* srv_descriptor_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle);
+#endif
+
 // Use if you want to reset your rendering device without losing Dear ImGui state.
 IMGUI_IMPL_API bool     ImGui_ImplDX12_CreateDeviceObjects();
 IMGUI_IMPL_API void     ImGui_ImplDX12_InvalidateDeviceObjects();
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 0dc526e24dbb..ef42ebc4d11e 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -41,10 +41,20 @@ HOW TO UPDATE?
 
 Breaking changes:
 
+- Backends: DX12: Changed ImGui_ImplDX12_Init() signature to take a
+  ImGui_ImplDX12_InitInfo struct.
+  - Using the new API, application is now required to pass function pointers
+    to allocate/free SRV Descriptors.
+  - We provide convenience legacy fields to pass a single descriptor,
+    matching the old API, but upcoming features will want multiple.
+  - Legacy ImGui_ImplDX12_Init() signature is still supported (will obsolete).
+
 Other changes:
 
 - Error Handling: fixed cases where recoverable error handling would crash when 
   processing errors outside of the NewFrame()..EndFrame() scope. (#1651)
+- Examples: Win32+DX12: Using a basic free-list allocator to manage multiple
+  SRV descriptors.
 
 
 -----------------------------------------------------------------------
diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp
index 168b6966038e..257410e2cb2e 100644
--- a/examples/example_win32_directx12/main.cpp
+++ b/examples/example_win32_directx12/main.cpp
@@ -25,6 +25,7 @@
 // Config for example app
 static const int APP_NUM_FRAMES_IN_FLIGHT = 3;
 static const int APP_NUM_BACK_BUFFERS = 3;
+static const int APP_SRV_HEAP_SIZE = 64;
 
 struct FrameContext
 {
@@ -32,6 +33,51 @@ struct FrameContext
     UINT64                      FenceValue;
 };
 
+// Simple free list based allocator
+struct ExampleDescriptorHeapAllocator
+{
+    ID3D12DescriptorHeap*       Heap = nullptr;
+    D3D12_DESCRIPTOR_HEAP_TYPE  HeapType = D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
+    D3D12_CPU_DESCRIPTOR_HANDLE HeapStartCpu;
+    D3D12_GPU_DESCRIPTOR_HANDLE HeapStartGpu;
+    UINT                        HeapHandleIncrement;
+    ImVector               FreeIndices;
+
+    void Create(ID3D12Device* device, ID3D12DescriptorHeap* heap)
+    {
+        IM_ASSERT(Heap == nullptr && FreeIndices.empty());
+        Heap = heap;
+        D3D12_DESCRIPTOR_HEAP_DESC desc = heap->GetDesc();
+        HeapType = desc.Type;
+        HeapStartCpu = Heap->GetCPUDescriptorHandleForHeapStart();
+        HeapStartGpu = Heap->GetGPUDescriptorHandleForHeapStart();
+        HeapHandleIncrement = device->GetDescriptorHandleIncrementSize(HeapType);
+        FreeIndices.reserve((int)desc.NumDescriptors);
+        for (int n = desc.NumDescriptors; n > 0; n--)
+            FreeIndices.push_back(n);
+    }
+    void Destroy()
+    {
+        Heap = NULL;
+        FreeIndices.clear();
+    }
+    void Alloc(D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_desc_handle)
+    {
+        IM_ASSERT(FreeIndices.Size > 0);
+        int idx = FreeIndices.back();
+        FreeIndices.pop_back();
+        out_cpu_desc_handle->ptr = HeapStartCpu.ptr + (idx * HeapHandleIncrement);
+        out_gpu_desc_handle->ptr = HeapStartGpu.ptr + (idx * HeapHandleIncrement);
+    }
+    void Free(D3D12_CPU_DESCRIPTOR_HANDLE out_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE out_gpu_desc_handle)
+    {
+        int cpu_idx = (int)((out_cpu_desc_handle.ptr - HeapStartCpu.ptr) / HeapHandleIncrement);
+        int gpu_idx = (int)((out_gpu_desc_handle.ptr - HeapStartGpu.ptr) / HeapHandleIncrement);
+        IM_ASSERT(cpu_idx == gpu_idx);
+        FreeIndices.push_back(cpu_idx);
+    }
+};
+
 // Data
 static FrameContext                 g_frameContext[APP_NUM_FRAMES_IN_FLIGHT] = {};
 static UINT                         g_frameIndex = 0;
@@ -39,6 +85,7 @@ static UINT                         g_frameIndex = 0;
 static ID3D12Device*                g_pd3dDevice = nullptr;
 static ID3D12DescriptorHeap*        g_pd3dRtvDescHeap = nullptr;
 static ID3D12DescriptorHeap*        g_pd3dSrvDescHeap = nullptr;
+static ExampleDescriptorHeapAllocator g_pd3dSrvDescHeapAlloc;
 static ID3D12CommandQueue*          g_pd3dCommandQueue = nullptr;
 static ID3D12GraphicsCommandList*   g_pd3dCommandList = nullptr;
 static ID3D12Fence*                 g_fence = nullptr;
@@ -93,10 +140,18 @@ int main(int, char**)
 
     // Setup Platform/Renderer backends
     ImGui_ImplWin32_Init(hwnd);
-    ImGui_ImplDX12_Init(g_pd3dDevice, NUM_FRAMES_IN_FLIGHT,
-        DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap,
-        g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(),
-        g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart());
+
+    ImGui_ImplDX12_InitInfo init_info = {};
+    init_info.Device = g_pd3dDevice;
+    init_info.CommandQueue = g_pd3dCommandQueue;
+    init_info.NumFramesInFlight = APP_NUM_FRAMES_IN_FLIGHT;
+    init_info.RTVFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+    // Allocating SRV descriptors (for textures) is up to the application, so we provide callbacks.
+    // (current version of the backend will only allocate one descriptor, future versions will need to allocate more)
+    init_info.SrvDescriptorHeap = g_pd3dSrvDescHeap;
+    init_info.SrvDescriptorAllocFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_handle) { return g_pd3dSrvDescHeapAlloc.Alloc(out_cpu_handle, out_gpu_handle); };
+    init_info.SrvDescriptorFreeFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle)            { return g_pd3dSrvDescHeapAlloc.Free(cpu_handle, gpu_handle); };
+    ImGui_ImplDX12_Init(&init_info);
 
     // Load Fonts
     // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
@@ -310,10 +365,11 @@ bool CreateDeviceD3D(HWND hWnd)
     {
         D3D12_DESCRIPTOR_HEAP_DESC desc = {};
         desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
-        desc.NumDescriptors = 1;
+        desc.NumDescriptors = APP_SRV_HEAP_SIZE;
         desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
         if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dSrvDescHeap)) != S_OK)
             return false;
+        g_pd3dSrvDescHeapAlloc.Create(g_pd3dDevice, g_pd3dSrvDescHeap);
     }
 
     {

From 08400f5be7fa8a83682b99d611ab7cdc66258425 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 15 Nov 2024 19:14:04 +0100
Subject: [PATCH 265/548] Backends: DX12: tidying up, added a
 ImGui_ImplDX12_Texture helper struct.

---
 backends/imgui_impl_dx12.cpp | 34 +++++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index 105bcb213289..8f9eb090c274 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -55,8 +55,16 @@
 #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
 #endif
 
-// DirectX data
+// DirectX12 data
 struct ImGui_ImplDX12_RenderBuffers;
+
+struct ImGui_ImplDX12_Texture
+{
+    ID3D12Resource*             pTextureResource;
+    D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle;
+    D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle;
+};
+
 struct ImGui_ImplDX12_Data
 {
     ImGui_ImplDX12_InitInfo     InitInfo;
@@ -64,9 +72,7 @@ struct ImGui_ImplDX12_Data
     ID3D12RootSignature*        pRootSignature;
     ID3D12PipelineState*        pPipelineState;
     DXGI_FORMAT                 RTVFormat;
-    ID3D12Resource*             pFontTextureResource;
-    D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle;
-    D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle;
+    ImGui_ImplDX12_Texture      FontTexture;
     ID3D12DescriptorHeap*       pd3dSrvDescHeap;
     UINT                        numFramesInFlight;
 
@@ -316,6 +322,7 @@ static void ImGui_ImplDX12_CreateFontsTexture()
     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
 
     // Upload texture to graphics system
+    ImGui_ImplDX12_Texture* font_tex = &bd->FontTexture;
     {
         D3D12_HEAP_PROPERTIES props;
         memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
@@ -446,13 +453,13 @@ static void ImGui_ImplDX12_CreateFontsTexture()
         srvDesc.Texture2D.MipLevels = desc.MipLevels;
         srvDesc.Texture2D.MostDetailedMip = 0;
         srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
-        bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, bd->hFontSrvCpuDescHandle);
-        SafeRelease(bd->pFontTextureResource);
-        bd->pFontTextureResource = pTexture;
+        bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, font_tex->hFontSrvCpuDescHandle);
+        SafeRelease(font_tex->pTextureResource);
+        font_tex->pTextureResource = pTexture;
     }
 
     // Store our identifier
-    io.Fonts->SetTexID((ImTextureID)bd->hFontSrvGpuDescHandle.ptr);
+    io.Fonts->SetTexID((ImTextureID)font_tex->hFontSrvGpuDescHandle.ptr);
 }
 
 bool    ImGui_ImplDX12_CreateDeviceObjects()
@@ -700,11 +707,12 @@ void    ImGui_ImplDX12_InvalidateDeviceObjects()
     SafeRelease(bd->pPipelineState);
 
     // Free SRV descriptor used by texture
+    ImGui_ImplDX12_Texture* font_tex = &bd->FontTexture;
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
     if (bd->InitInfo.SrvDescriptorFreeFn != NULL)
 #endif
-        bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, bd->hFontSrvCpuDescHandle, bd->hFontSrvGpuDescHandle);
-    SafeRelease(bd->pFontTextureResource);
+        bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, font_tex->hFontSrvCpuDescHandle, font_tex->hFontSrvGpuDescHandle);
+    SafeRelease(font_tex->pTextureResource);
     io.Fonts->SetTexID(0); // We copied bd->hFontSrvGpuDescHandle to io.Fonts->TexID so let's clear that as well.
 
     for (UINT i = 0; i < bd->numFramesInFlight; i++)
@@ -738,14 +746,14 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
     if (init_info->SrvDescriptorAllocFn != NULL)
     {
         IM_ASSERT(init_info->SrvDescriptorFreeFn != NULL);
-        init_info->SrvDescriptorAllocFn(&bd->InitInfo, &bd->hFontSrvCpuDescHandle, &bd->hFontSrvGpuDescHandle);
+        init_info->SrvDescriptorAllocFn(&bd->InitInfo, &bd->FontTexture.hFontSrvCpuDescHandle, &bd->FontTexture.hFontSrvGpuDescHandle);
     }
     else
     {
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
         IM_ASSERT(init_info->LegacySingleSrvCpuDescriptor.ptr != 0 && init_info->LegacySingleSrvGpuDescriptor.ptr != 0);
-        bd->hFontSrvCpuDescHandle = init_info->LegacySingleSrvCpuDescriptor;
-        bd->hFontSrvGpuDescHandle = init_info->LegacySingleSrvGpuDescriptor;
+        bd->FontTexture.hFontSrvCpuDescHandle = init_info->LegacySingleSrvCpuDescriptor;
+        bd->FontTexture.hFontSrvGpuDescHandle = init_info->LegacySingleSrvGpuDescriptor;
 #else
         IM_ASSERT(init_info->SrvDescriptorAllocFn != NULL);
         IM_ASSERT(init_info->SrvDescriptorFreeFn != NULL);

From 142827f7d8618d107f18d995da3530dab8aefd8f Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 18 Nov 2024 15:16:41 +0100
Subject: [PATCH 266/548] Backends: DX12: rework legacy path for handling
 ImGui_ImplDX12_Init() being called with space for a single descriptor.

---
 backends/imgui_impl_dx12.cpp | 48 +++++++++++++++++++++---------------
 1 file changed, 28 insertions(+), 20 deletions(-)

diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index 8f9eb090c274..acf98858b55f 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -72,13 +72,15 @@ struct ImGui_ImplDX12_Data
     ID3D12RootSignature*        pRootSignature;
     ID3D12PipelineState*        pPipelineState;
     DXGI_FORMAT                 RTVFormat;
-    ImGui_ImplDX12_Texture      FontTexture;
     ID3D12DescriptorHeap*       pd3dSrvDescHeap;
     UINT                        numFramesInFlight;
 
     ImGui_ImplDX12_RenderBuffers* pFrameResources;
     UINT                        frameIndex;
 
+    ImGui_ImplDX12_Texture      FontTexture;
+    bool                        LegacySingleDescriptorUsed;
+
     ImGui_ImplDX12_Data()       { memset((void*)this, 0, sizeof(*this)); frameIndex = UINT_MAX; }
 };
 
@@ -708,10 +710,7 @@ void    ImGui_ImplDX12_InvalidateDeviceObjects()
 
     // Free SRV descriptor used by texture
     ImGui_ImplDX12_Texture* font_tex = &bd->FontTexture;
-#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
-    if (bd->InitInfo.SrvDescriptorFreeFn != NULL)
-#endif
-        bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, font_tex->hFontSrvCpuDescHandle, font_tex->hFontSrvGpuDescHandle);
+    bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, font_tex->hFontSrvCpuDescHandle, font_tex->hFontSrvGpuDescHandle);
     SafeRelease(font_tex->pTextureResource);
     io.Fonts->SetTexID(0); // We copied bd->hFontSrvGpuDescHandle to io.Fonts->TexID so let's clear that as well.
 
@@ -731,8 +730,9 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
 
     // Setup backend capabilities flags
     ImGui_ImplDX12_Data* bd = IM_NEW(ImGui_ImplDX12_Data)();
-
     bd->InitInfo = *init_info; // Deep copy
+    init_info = &bd->InitInfo;
+
     bd->pd3dDevice = init_info->Device;
     bd->RTVFormat = init_info->RTVFormat;
     bd->numFramesInFlight = init_info->NumFramesInFlight;
@@ -742,23 +742,31 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
     io.BackendRendererName = "imgui_impl_dx12";
     io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;  // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
 
-    // Allocate 1 SRV descriptor for the font texture
-    if (init_info->SrvDescriptorAllocFn != NULL)
-    {
-        IM_ASSERT(init_info->SrvDescriptorFreeFn != NULL);
-        init_info->SrvDescriptorAllocFn(&bd->InitInfo, &bd->FontTexture.hFontSrvCpuDescHandle, &bd->FontTexture.hFontSrvGpuDescHandle);
-    }
-    else
-    {
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+    if (init_info->SrvDescriptorAllocFn == NULL)
+    {
+        // Wrap legacy behavior of passing space for a single descriptor
         IM_ASSERT(init_info->LegacySingleSrvCpuDescriptor.ptr != 0 && init_info->LegacySingleSrvGpuDescriptor.ptr != 0);
-        bd->FontTexture.hFontSrvCpuDescHandle = init_info->LegacySingleSrvCpuDescriptor;
-        bd->FontTexture.hFontSrvGpuDescHandle = init_info->LegacySingleSrvGpuDescriptor;
-#else
-        IM_ASSERT(init_info->SrvDescriptorAllocFn != NULL);
-        IM_ASSERT(init_info->SrvDescriptorFreeFn != NULL);
-#endif
+        init_info->SrvDescriptorAllocFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_handle)
+        {
+            ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
+            IM_ASSERT(bd->LegacySingleDescriptorUsed == false);
+            *out_cpu_handle = bd->InitInfo.LegacySingleSrvCpuDescriptor;
+            *out_gpu_handle = bd->InitInfo.LegacySingleSrvGpuDescriptor;
+            bd->LegacySingleDescriptorUsed = true;
+        };
+        init_info->SrvDescriptorFreeFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE, D3D12_GPU_DESCRIPTOR_HANDLE)
+        {
+            ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
+            IM_ASSERT(bd->LegacySingleDescriptorUsed == true);
+            bd->LegacySingleDescriptorUsed = false;
+        };
     }
+#endif
+
+    // Allocate 1 SRV descriptor for the font texture
+    IM_ASSERT(init_info->SrvDescriptorAllocFn != NULL && init_info->SrvDescriptorFreeFn != NULL);
+    init_info->SrvDescriptorAllocFn(&bd->InitInfo, &bd->FontTexture.hFontSrvCpuDescHandle, &bd->FontTexture.hFontSrvGpuDescHandle);
 
     // Create buffers with a default size (they will later be grown as needed)
     bd->frameIndex = UINT_MAX;

From eb0ad66d88d96be3ccad31e22ef9d3126ec79ef2 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 18 Nov 2024 18:46:27 +0100
Subject: [PATCH 267/548] Demo: example tree used by Property Editor &
 Selection demos properly freed on app closure. (#8158)

---
 docs/CHANGELOG.txt |  2 ++
 imgui_demo.cpp     | 11 ++++++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index ef42ebc4d11e..29d1cf98ab99 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -53,6 +53,8 @@ Other changes:
 
 - Error Handling: fixed cases where recoverable error handling would crash when 
   processing errors outside of the NewFrame()..EndFrame() scope. (#1651)
+- Demo: example tree used by Property Editor & Selection demos properly freed
+  on application closure. (#8158) [@Legulysse]
 - Examples: Win32+DX12: Using a basic free-list allocator to manage multiple
   SRV descriptors.
 
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index ac34e6b1d5da..c822c162e567 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -308,6 +308,13 @@ static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, Exampl
     return node;
 }
 
+static void ExampleTree_DestroyNode(ExampleTreeNode* node)
+{
+    for (ExampleTreeNode* child_node : node->Childs)
+        ExampleTree_DestroyNode(child_node);
+    IM_DELETE(node);
+}
+
 // Create example tree data
 // (this allocates _many_ more times than most other code in either Dear ImGui or others demo)
 static ExampleTreeNode* ExampleTree_CreateDemoTree()
@@ -343,7 +350,7 @@ static ExampleTreeNode* ExampleTree_CreateDemoTree()
 // [SECTION] Demo Window / ShowDemoWindow()
 //-----------------------------------------------------------------------------
 
-// Data to be shared accross different functions of the demo.
+// Data to be shared across different functions of the demo.
 struct ImGuiDemoWindowData
 {
     // Examples Apps (accessible from the "Examples" menu)
@@ -371,6 +378,8 @@ struct ImGuiDemoWindowData
 
     // Other data
     ExampleTreeNode* DemoTree = NULL;
+
+    ~ImGuiDemoWindowData() { if (DemoTree) ExampleTree_DestroyNode(DemoTree); }
 };
 
 // Demonstrate most Dear ImGui features (this is big function!)

From 5ae3dd52a07e4996c777dfb0a85682260f968674 Mon Sep 17 00:00:00 2001
From: chuikingshek 
Date: Tue, 19 Nov 2024 02:36:26 +0800
Subject: [PATCH 268/548] Fonts: added IMGUI_DISABLE_DEFAULT_FONT macro.
 (#8161)

---
 docs/CHANGELOG.txt |  2 ++
 imconfig.h         |  1 +
 imgui_draw.cpp     | 11 +++++++++++
 3 files changed, 14 insertions(+)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 29d1cf98ab99..f04eccd6f15a 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -53,6 +53,8 @@ Other changes:
 
 - Error Handling: fixed cases where recoverable error handling would crash when 
   processing errors outside of the NewFrame()..EndFrame() scope. (#1651)
+- Misc: added IMGUI_DISABLE_DEFAULT_FONT to strip embedded font from binary. (#8161)
+  [@demonese]
 - Demo: example tree used by Property Editor & Selection demos properly freed
   on application closure. (#8158) [@Legulysse]
 - Examples: Win32+DX12: Using a basic free-list allocator to manage multiple
diff --git a/imconfig.h b/imconfig.h
index fea89dea0913..adc69d1a3e52 100644
--- a/imconfig.h
+++ b/imconfig.h
@@ -48,6 +48,7 @@
 //#define IMGUI_DISABLE_FILE_FUNCTIONS                      // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
 //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS              // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
 //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS                  // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
+//#define IMGUI_DISABLE_DEFAULT_FONT                        // Disable default embedded font (ProggyClean.ttf), remove ~14 KB from output binary. AddFontDefault() will assert.
 //#define IMGUI_DISABLE_SSE                                 // Disable use of SSE intrinsics even if available
 
 //---- Enable Test Engine / Automation features.
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 0003fe1e2963..731dd05988bb 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -2560,7 +2560,9 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
 // Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder)
 static unsigned int stb_decompress_length(const unsigned char* input);
 static unsigned int stb_decompress(unsigned char* output, const unsigned char* input, unsigned int length);
+#ifndef IMGUI_DISABLE_DEFAULT_FONT
 static const char*  GetDefaultCompressedFontDataTTFBase85();
+#endif
 static unsigned int Decode85Byte(char c)                                    { return c >= '\\' ? c-36 : c-35; }
 static void         Decode85(const unsigned char* src, unsigned char* dst)
 {
@@ -2576,6 +2578,7 @@ static void         Decode85(const unsigned char* src, unsigned char* dst)
 // Load embedded ProggyClean.ttf at size 13, disable oversampling
 ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
 {
+#ifndef IMGUI_DISABLE_DEFAULT_FONT
     ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
     if (!font_cfg_template)
     {
@@ -2593,6 +2596,11 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
     const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault();
     ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, glyph_ranges);
     return font;
+#else
+    IM_ASSERT(0 && "AddFontDefault() disabled in this build.");
+    IM_UNUSED(font_cfg_template);
+    return NULL;
+#endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
 }
 
 ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
@@ -4578,6 +4586,8 @@ static unsigned int stb_decompress(unsigned char *output, const unsigned char *i
 // Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding).
 // The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size.
 //-----------------------------------------------------------------------------
+
+#ifndef IMGUI_DISABLE_DEFAULT_FONT
 static const char proggy_clean_ttf_compressed_data_base85[11980 + 1] =
     "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
     "2*>]b(MC;$jPfY.;h^`IWM9
Date: Wed, 20 Nov 2024 14:02:44 +0100
Subject: [PATCH 269/548] Misc: changed embedded ProggyClean encoding to save a
 bit of binary space (~12kb to 9.5kb). (#8161)

Encoding as char to ensure compatibility with big endian (#81)
---
 docs/CHANGELOG.txt                    |   1 +
 imconfig.h                            |   2 +-
 imgui_draw.cpp                        | 280 +++++++++++++++++---------
 misc/fonts/binary_to_compressed_c.cpp |  23 ++-
 4 files changed, 206 insertions(+), 100 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index f04eccd6f15a..5305b889e51a 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -53,6 +53,7 @@ Other changes:
 
 - Error Handling: fixed cases where recoverable error handling would crash when 
   processing errors outside of the NewFrame()..EndFrame() scope. (#1651)
+- Misc: changed embedded ProggyClean encoding to save a bit of binary space (~12kb to 9.5kb).
 - Misc: added IMGUI_DISABLE_DEFAULT_FONT to strip embedded font from binary. (#8161)
   [@demonese]
 - Demo: example tree used by Property Editor & Selection demos properly freed
diff --git a/imconfig.h b/imconfig.h
index adc69d1a3e52..3504a4e4d369 100644
--- a/imconfig.h
+++ b/imconfig.h
@@ -48,7 +48,7 @@
 //#define IMGUI_DISABLE_FILE_FUNCTIONS                      // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
 //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS              // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
 //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS                  // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
-//#define IMGUI_DISABLE_DEFAULT_FONT                        // Disable default embedded font (ProggyClean.ttf), remove ~14 KB from output binary. AddFontDefault() will assert.
+//#define IMGUI_DISABLE_DEFAULT_FONT                        // Disable default embedded font (ProggyClean.ttf), remove ~9.5 KB from output binary. AddFontDefault() will assert.
 //#define IMGUI_DISABLE_SSE                                 // Disable use of SSE intrinsics even if available
 
 //---- Enable Test Engine / Automation features.
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 731dd05988bb..0f74a98b3d07 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -2560,9 +2560,6 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
 // Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder)
 static unsigned int stb_decompress_length(const unsigned char* input);
 static unsigned int stb_decompress(unsigned char* output, const unsigned char* input, unsigned int length);
-#ifndef IMGUI_DISABLE_DEFAULT_FONT
-static const char*  GetDefaultCompressedFontDataTTFBase85();
-#endif
 static unsigned int Decode85Byte(char c)                                    { return c >= '\\' ? c-36 : c-35; }
 static void         Decode85(const unsigned char* src, unsigned char* dst)
 {
@@ -2574,6 +2571,9 @@ static void         Decode85(const unsigned char* src, unsigned char* dst)
         dst += 4;
     }
 }
+#ifndef IMGUI_DISABLE_DEFAULT_FONT
+static const char* GetDefaultCompressedFontDataTTF(int* out_size);
+#endif
 
 // Load embedded ProggyClean.ttf at size 13, disable oversampling
 ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
@@ -2592,9 +2592,10 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
     font_cfg.EllipsisChar = (ImWchar)0x0085;
     font_cfg.GlyphOffset.y = 1.0f * IM_TRUNC(font_cfg.SizePixels / 13.0f);  // Add +1 offset per 13 units
 
-    const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85();
+    int ttf_compressed_size = 0;
+    const char* ttf_compressed = GetDefaultCompressedFontDataTTF(&ttf_compressed_size);
     const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault();
-    ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, glyph_ranges);
+    ImFont* font = AddFontFromMemoryCompressedTTF(ttf_compressed, ttf_compressed_size, font_cfg.SizePixels, &font_cfg, glyph_ranges);
     return font;
 #else
     IM_ASSERT(0 && "AddFontDefault() disabled in this build.");
@@ -4583,102 +4584,185 @@ static unsigned int stb_decompress(unsigned char *output, const unsigned char *i
 // Download and more information at http://www.proggyfonts.net or http://upperboundsinteractive.com/fonts.php
 //-----------------------------------------------------------------------------
 // File: 'ProggyClean.ttf' (41208 bytes)
-// Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding).
-// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size.
+// Exported using "misc/fonts/binary_to_compressed_c.exe ../ProggyClean.ttf proggy_clean_ttf_compressed (with compression, no base85 encoding).
 //-----------------------------------------------------------------------------
 
 #ifndef IMGUI_DISABLE_DEFAULT_FONT
-static const char proggy_clean_ttf_compressed_data_base85[11980 + 1] =
-    "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
-    "2*>]b(MC;$jPfY.;h^`IWM9Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1=Ke$$'5F%)]0^#0X@U.a$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;--VsM.M0rJfLH2eTM`*oJMHRC`N"
-    "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`�j@'DbG&#^$PG.Ll+DNa&VZ>1i%h1S9u5o@YaaW$e+bROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc."
-    "x]Ip.PH^'/aqUO/$1WxLoW0[iLAw=4h(9.`G"
-    "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?Ggv:[7MI2k).'2($5FNP&EQ(,)"
-    "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#"
-    "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM"
-    "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu"
-    "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/"
-    "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[Ket`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO"
-    "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%"
-    "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$MhLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]"
-    "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
-    "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
-    "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VBpqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<-+k?'(^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
-    "D?@f&1'BW-)Ju#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX("
-    "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs"
-    "bIu)'Z,*[>br5fX^:FPAWr-m2KgLQ_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
-    "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aege0jT6'N#(q%.O=?2S]u*(m<-"
-    "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i"
-    "sZ88+dKQ)W6>J%CL`.d*(B`-n8D9oK-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P	r+$%CE=68>K8r0=dSC%%(@p7"
-    ".m7jilQ02'0-VWAgTlGW'b)Tq7VT9q^*^$$.:&N@@"
-    "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*"
-    "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u"
-    "@-W$U%VEQ/,,>>#)D#%8cY#YZ?=,`Wdxu/ae&#"
-    "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$so8lKN%5/$(vdfq7+ebA#"
-    "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoFDoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8"
-    "6e%B/:=>)N4xeW.*wft-;$'58-ESqr#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#"
-    "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjLV#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#SfD07&6D@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5"
-    "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%"
-    "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;"
-    "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmLq9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:"
-    "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3$U4O]GKx'm9)b@p7YsvK3w^YR-"
-    "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*"
-    "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdFTi1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IXSsDiWP,##P`%/L-"
-    "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdFl*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj"
-    "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#$(>.Z-I&J(Q0Hd5Q%7Co-b`-cP)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8WlA2);Sa"
-    ">gXm8YB`1d@K#n]76-a$U,mF%Ul:#/'xoFM9QX-$.QN'>"
-    "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I"
-    "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-uW%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)"
-    "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo"
-    "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P"
-    "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*'IAO"
-    "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#"
-    ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T"
-    "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4"
-    "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#"
-    "/QHC#3^ZC#7jmC#;v)D#?,)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
-    "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
-    "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
-
-static const char* GetDefaultCompressedFontDataTTFBase85()
-{
-    return proggy_clean_ttf_compressed_data_base85;
+static const unsigned int proggy_clean_ttf_compressed_size = 9583;
+static const unsigned char proggy_clean_ttf_compressed_data[9583] =
+{
+    87,188,0,0,0,0,0,0,0,0,160,248,0,4,0,0,55,0,1,0,0,0,12,0,128,0,3,0,64,79,83,47,50,136,235,116,144,0,0,1,72,130,21,44,78,99,109,97,112,2,18,35,117,0,0,3,160,130,19,36,82,99,118,116,
+    32,130,23,130,2,33,4,252,130,4,56,2,103,108,121,102,18,175,137,86,0,0,7,4,0,0,146,128,104,101,97,100,215,145,102,211,130,27,32,204,130,3,33,54,104,130,16,39,8,66,1,195,0,0,1,4,130,
+    15,59,36,104,109,116,120,138,0,126,128,0,0,1,152,0,0,2,6,108,111,99,97,140,115,176,216,0,0,5,130,30,41,2,4,109,97,120,112,1,174,0,218,130,31,32,40,130,16,44,32,110,97,109,101,37,89,
+    187,150,0,0,153,132,130,19,44,158,112,111,115,116,166,172,131,239,0,0,155,36,130,51,44,210,112,114,101,112,105,2,1,18,0,0,4,244,130,47,32,8,132,203,46,1,0,0,60,85,233,213,95,15,60,
+    245,0,3,8,0,131,0,34,183,103,119,130,63,43,0,0,189,146,166,215,0,0,254,128,3,128,131,111,130,241,33,2,0,133,0,32,1,130,65,38,192,254,64,0,0,3,128,131,16,130,5,32,1,131,7,138,3,33,2,
+    0,130,17,36,1,1,0,144,0,130,121,130,23,38,2,0,8,0,64,0,10,130,9,32,118,130,9,130,6,32,0,130,59,33,1,144,131,200,35,2,188,2,138,130,16,32,143,133,7,37,1,197,0,50,2,0,131,0,33,4,9,131,
+    5,145,3,43,65,108,116,115,0,64,0,0,32,172,8,0,131,0,35,5,0,1,128,131,77,131,3,33,3,128,191,1,33,1,128,130,184,35,0,0,128,0,130,3,131,11,32,1,130,7,33,0,128,131,1,32,1,136,9,32,0,132,
+    15,135,5,32,1,131,13,135,27,144,35,32,1,149,25,131,21,32,0,130,0,32,128,132,103,130,35,132,39,32,0,136,45,136,97,133,17,130,5,33,0,0,136,19,34,0,128,1,133,13,133,5,32,128,130,15,132,
+    131,32,3,130,5,32,3,132,27,144,71,32,0,133,27,130,29,130,31,136,29,131,63,131,3,65,63,5,132,5,132,205,130,9,33,0,0,131,9,137,119,32,3,132,19,138,243,130,55,32,1,132,35,135,19,131,201,
+    136,11,132,143,137,13,130,41,32,0,131,3,144,35,33,128,0,135,1,131,223,131,3,141,17,134,13,136,63,134,15,136,53,143,15,130,96,33,0,3,131,4,130,3,34,28,0,1,130,5,34,0,0,76,130,17,131,
+    9,36,28,0,4,0,48,130,17,46,8,0,8,0,2,0,0,0,127,0,255,32,172,255,255,130,9,34,0,0,129,132,9,130,102,33,223,213,134,53,132,22,33,1,6,132,6,64,4,215,32,129,165,216,39,177,0,1,141,184,
+    1,255,133,134,45,33,198,0,193,1,8,190,244,1,28,1,158,2,20,2,136,2,252,3,20,3,88,3,156,3,222,4,20,4,50,4,80,4,98,4,162,5,22,5,102,5,188,6,18,6,116,6,214,7,56,7,126,7,236,8,78,8,108,
+    8,150,8,208,9,16,9,74,9,136,10,22,10,128,11,4,11,86,11,200,12,46,12,130,12,234,13,94,13,164,13,234,14,80,14,150,15,40,15,176,16,18,16,116,16,224,17,82,17,182,18,4,18,110,18,196,19,
+    76,19,172,19,246,20,88,20,174,20,234,21,64,21,128,21,166,21,184,22,18,22,126,22,198,23,52,23,142,23,224,24,86,24,186,24,238,25,54,25,150,25,212,26,72,26,156,26,240,27,92,27,200,28,
+    4,28,76,28,150,28,234,29,42,29,146,29,210,30,64,30,142,30,224,31,36,31,118,31,166,31,166,32,16,130,1,52,46,32,138,32,178,32,200,33,20,33,116,33,152,33,238,34,98,34,134,35,12,130,1,
+    33,128,35,131,1,60,152,35,176,35,216,36,0,36,74,36,104,36,144,36,174,37,6,37,96,37,130,37,248,37,248,38,88,38,170,130,1,8,190,216,39,64,39,154,40,10,40,104,40,168,41,14,41,32,41,184,
+    41,248,42,54,42,96,42,96,43,2,43,42,43,94,43,172,43,230,44,32,44,52,44,154,45,40,45,92,45,120,45,170,45,232,46,38,46,166,47,38,47,182,47,244,48,94,48,200,49,62,49,180,50,30,50,158,
+    51,30,51,130,51,238,52,92,52,206,53,58,53,134,53,212,54,38,54,114,54,230,55,118,55,216,56,58,56,166,57,18,57,116,57,174,58,46,58,154,59,6,59,124,59,232,60,58,60,150,61,34,61,134,61,
+    236,62,86,62,198,63,42,63,154,64,18,64,106,64,208,65,54,65,162,66,8,66,64,66,122,66,184,66,240,67,98,67,204,68,42,68,138,68,238,69,88,69,182,69,226,70,84,70,180,71,20,71,122,71,218,
+    72,84,72,198,73,64,0,36,70,21,8,8,77,3,0,7,0,11,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,55,0,59,0,63,0,67,0,71,0,75,0,79,0,83,0,87,0,91,0,95,0,99,0,103,0,107,0,111,0,115,
+    0,119,0,123,0,127,0,131,0,135,0,139,0,143,0,0,17,53,51,21,49,150,3,32,5,130,23,32,33,130,3,211,7,151,115,32,128,133,0,37,252,128,128,2,128,128,190,5,133,74,32,4,133,6,206,5,42,0,7,
+    1,128,0,0,2,0,4,0,0,65,139,13,37,0,1,53,51,21,7,146,3,32,3,130,19,32,1,141,133,32,3,141,14,131,13,38,255,0,128,128,0,6,1,130,84,35,2,128,4,128,140,91,132,89,32,51,65,143,6,139,7,33,
+    1,0,130,57,32,254,130,3,32,128,132,4,32,4,131,14,138,89,35,0,0,24,0,130,0,33,3,128,144,171,66,55,33,148,115,65,187,19,32,5,130,151,143,155,163,39,32,1,136,182,32,253,134,178,132,7,
+    132,200,145,17,32,3,65,48,17,165,17,39,0,0,21,0,128,255,128,3,65,175,17,65,3,27,132,253,131,217,139,201,155,233,155,27,131,67,131,31,130,241,33,255,0,131,181,137,232,132,15,132,4,138,
+    247,34,255,0,128,179,238,32,0,130,0,32,20,65,239,48,33,0,19,67,235,10,32,51,65,203,14,65,215,11,32,7,154,27,135,39,32,33,130,35,33,128,128,130,231,32,253,132,231,32,128,132,232,34,
+    128,128,254,133,13,136,8,32,253,65,186,5,130,36,130,42,176,234,133,231,34,128,0,0,66,215,44,33,0,1,68,235,6,68,211,19,32,49,68,239,14,139,207,139,47,66,13,7,32,51,130,47,33,1,0,130,
+    207,35,128,128,1,0,131,222,131,5,130,212,130,6,131,212,32,0,130,10,133,220,130,233,130,226,32,254,133,255,178,233,39,3,1,128,3,0,2,0,4,68,15,7,68,99,12,130,89,130,104,33,128,4,133,
+    93,130,10,38,0,0,11,1,0,255,0,68,63,16,70,39,9,66,215,8,32,7,68,77,6,68,175,14,32,29,68,195,6,132,7,35,2,0,128,255,131,91,132,4,65,178,5,141,111,67,129,23,165,135,140,107,142,135,33,
+    21,5,69,71,6,131,7,33,1,0,140,104,132,142,130,4,137,247,140,30,68,255,12,39,11,0,128,0,128,3,0,3,69,171,15,67,251,7,65,15,8,66,249,11,65,229,7,67,211,7,66,13,7,35,1,128,128,254,133,
+    93,32,254,131,145,132,4,132,18,32,2,151,128,130,23,34,0,0,9,154,131,65,207,8,68,107,15,68,51,7,32,7,70,59,7,135,121,130,82,32,128,151,111,41,0,0,4,0,128,255,0,1,128,1,137,239,33,0,
+    37,70,145,10,65,77,10,65,212,14,37,0,0,0,5,0,128,66,109,5,70,123,10,33,0,19,72,33,18,133,237,70,209,11,33,0,2,130,113,137,119,136,115,33,1,0,133,43,130,5,34,0,0,10,69,135,6,70,219,
+    13,66,155,7,65,9,12,66,157,11,66,9,11,32,7,130,141,132,252,66,151,9,137,9,66,15,30,36,0,20,0,128,0,130,218,71,11,42,68,51,8,65,141,7,73,19,15,69,47,23,143,39,66,81,7,32,1,66,55,6,34,
+    1,128,128,68,25,5,69,32,6,137,6,136,25,32,254,131,42,32,3,66,88,26,148,26,32,0,130,0,32,14,164,231,70,225,12,66,233,7,67,133,19,71,203,15,130,161,32,255,130,155,32,254,139,127,134,
+    12,164,174,33,0,15,164,159,33,59,0,65,125,20,66,25,7,32,5,68,191,6,66,29,7,144,165,65,105,9,35,128,128,255,0,137,2,133,182,164,169,33,128,128,197,171,130,155,68,235,7,32,21,70,77,19,
+    66,21,10,68,97,8,66,30,5,66,4,43,34,0,17,0,71,19,41,65,253,20,71,25,23,65,91,15,65,115,7,34,2,128,128,66,9,8,130,169,33,1,0,66,212,13,132,28,72,201,43,35,0,0,0,18,66,27,38,76,231,5,
+    68,157,20,135,157,32,7,68,185,13,65,129,28,66,20,5,32,253,66,210,11,65,128,49,133,61,32,0,65,135,6,74,111,37,72,149,12,66,203,19,65,147,19,68,93,7,68,85,8,76,4,5,33,255,0,133,129,34,
+    254,0,128,68,69,8,181,197,34,0,0,12,65,135,32,65,123,20,69,183,27,133,156,66,50,5,72,87,10,67,137,32,33,0,19,160,139,78,251,13,68,55,20,67,119,19,65,91,36,69,177,15,32,254,143,16,65,
+    98,53,32,128,130,0,32,0,66,43,54,70,141,23,66,23,15,131,39,69,47,11,131,15,70,129,19,74,161,9,36,128,255,0,128,254,130,153,65,148,32,67,41,9,34,0,0,4,79,15,5,73,99,10,71,203,8,32,3,
+    72,123,6,72,43,8,32,2,133,56,131,99,130,9,34,0,0,6,72,175,5,73,159,14,144,63,135,197,132,189,133,66,33,255,0,73,6,7,70,137,12,35,0,0,0,10,130,3,73,243,25,67,113,12,65,73,7,69,161,7,
+    138,7,37,21,2,0,128,128,254,134,3,73,116,27,33,128,128,130,111,39,12,0,128,1,0,3,128,2,72,219,21,35,43,0,47,0,67,47,20,130,111,33,21,1,68,167,13,81,147,8,133,230,32,128,77,73,6,32,
+    128,131,142,134,18,130,6,32,255,75,18,12,131,243,37,128,0,128,3,128,3,74,231,21,135,123,32,29,134,107,135,7,32,21,74,117,7,135,7,134,96,135,246,74,103,23,132,242,33,0,10,67,151,28,
+    67,133,20,66,141,11,131,11,32,3,77,71,6,32,128,130,113,32,1,81,4,6,134,218,66,130,24,131,31,34,0,26,0,130,0,77,255,44,83,15,11,148,155,68,13,7,32,49,78,231,18,79,7,11,73,243,11,32,
+    33,65,187,10,130,63,65,87,8,73,239,19,35,0,128,1,0,131,226,32,252,65,100,6,32,128,139,8,33,1,0,130,21,32,253,72,155,44,73,255,20,32,128,71,67,8,81,243,39,67,15,20,74,191,23,68,121,
+    27,32,1,66,150,6,32,254,79,19,11,131,214,32,128,130,215,37,2,0,128,253,0,128,136,5,65,220,24,147,212,130,210,33,0,24,72,219,42,84,255,13,67,119,16,69,245,19,72,225,19,65,3,15,69,93,
+    19,131,55,132,178,71,115,14,81,228,6,142,245,33,253,0,132,43,172,252,65,16,11,75,219,8,65,219,31,66,223,24,75,223,10,33,29,1,80,243,10,66,175,8,131,110,134,203,133,172,130,16,70,30,
+    7,164,183,130,163,32,20,65,171,48,65,163,36,65,143,23,65,151,19,65,147,13,65,134,17,133,17,130,216,67,114,5,164,217,65,137,12,72,147,48,79,71,19,74,169,22,80,251,8,65,173,7,66,157,
+    15,74,173,15,32,254,65,170,8,71,186,45,72,131,6,77,143,40,187,195,152,179,65,123,38,68,215,57,68,179,15,65,85,7,69,187,14,32,21,66,95,15,67,19,25,32,1,83,223,6,32,2,76,240,7,77,166,
+    43,65,8,5,130,206,32,0,67,39,54,143,167,66,255,19,82,193,11,151,47,85,171,5,67,27,17,132,160,69,172,11,69,184,56,66,95,6,33,12,1,130,237,32,2,68,179,27,68,175,16,80,135,15,72,55,7,
+    71,87,12,73,3,12,132,12,66,75,32,76,215,5,169,139,147,135,148,139,81,12,12,81,185,36,75,251,7,65,23,27,76,215,9,87,165,12,65,209,15,72,157,7,65,245,31,32,128,71,128,6,32,1,82,125,5,
+    34,0,128,254,131,169,32,254,131,187,71,180,9,132,27,32,2,88,129,44,32,0,78,47,40,65,79,23,79,171,14,32,21,71,87,8,72,15,14,65,224,33,130,139,74,27,62,93,23,7,68,31,7,75,27,7,139,15,
+    74,3,7,74,23,27,65,165,11,65,177,15,67,123,5,32,1,130,221,32,252,71,96,5,74,12,12,133,244,130,25,34,1,0,128,130,2,139,8,93,26,8,65,9,32,65,57,14,140,14,32,0,73,79,67,68,119,11,135,
+    11,32,51,90,75,14,139,247,65,43,7,131,19,139,11,69,159,11,65,247,6,36,1,128,128,253,0,90,71,9,33,1,0,132,14,32,128,89,93,14,69,133,6,130,44,131,30,131,6,65,20,56,33,0,16,72,179,40,
+    75,47,12,65,215,19,74,95,19,65,43,11,131,168,67,110,5,75,23,17,69,106,6,75,65,5,71,204,43,32,0,80,75,47,71,203,15,159,181,68,91,11,67,197,7,73,101,13,68,85,6,33,128,128,130,214,130,
+    25,32,254,74,236,48,130,194,37,0,18,0,128,255,128,77,215,40,65,139,64,32,51,80,159,10,65,147,39,130,219,84,212,43,130,46,75,19,97,74,33,11,65,201,23,65,173,31,33,1,0,79,133,6,66,150,
+    5,67,75,48,85,187,6,70,207,37,32,71,87,221,13,73,163,14,80,167,15,132,15,83,193,19,82,209,8,78,99,9,72,190,11,77,110,49,89,63,5,80,91,35,99,63,32,70,235,23,81,99,10,69,148,10,65,110,
+    36,32,0,65,99,47,95,219,11,68,171,51,66,87,7,72,57,7,74,45,17,143,17,65,114,50,33,14,0,65,111,40,159,195,98,135,15,35,7,53,51,21,100,78,9,95,146,16,32,254,82,114,6,32,128,67,208,37,
+    130,166,99,79,58,32,17,96,99,14,72,31,19,72,87,31,82,155,7,67,47,14,32,21,131,75,134,231,72,51,17,72,78,8,133,8,80,133,6,33,253,128,88,37,9,66,124,36,72,65,12,134,12,71,55,43,66,139,
+    27,85,135,10,91,33,12,65,35,11,66,131,11,71,32,8,90,127,6,130,244,71,76,11,168,207,33,0,12,66,123,32,32,0,65,183,15,68,135,11,66,111,7,67,235,11,66,111,15,32,254,97,66,12,160,154,67,
+    227,52,80,33,15,87,249,15,93,45,31,75,111,12,93,45,11,77,99,9,160,184,81,31,12,32,15,98,135,30,104,175,7,77,249,36,69,73,15,78,5,12,32,254,66,151,19,34,128,128,4,87,32,12,149,35,133,
+    21,96,151,31,32,19,72,35,5,98,173,15,143,15,32,21,143,99,158,129,33,0,0,65,35,52,65,11,15,147,15,98,75,11,33,1,0,143,151,132,15,32,254,99,200,37,132,43,130,4,39,0,10,0,128,1,128,3,
+    0,104,151,14,97,187,20,69,131,15,67,195,11,87,227,7,33,128,128,132,128,33,254,0,68,131,9,65,46,26,42,0,0,0,7,0,0,255,128,3,128,0,88,223,15,33,0,21,89,61,22,66,209,12,65,2,12,37,0,2,
+    1,0,3,128,101,83,8,36,0,1,53,51,29,130,3,34,21,1,0,66,53,8,32,0,68,215,6,100,55,25,107,111,9,66,193,11,72,167,8,73,143,31,139,31,33,1,0,131,158,32,254,132,5,33,253,128,65,16,9,133,
+    17,89,130,25,141,212,33,0,0,93,39,8,90,131,25,93,39,14,66,217,6,106,179,8,159,181,71,125,15,139,47,138,141,87,11,14,76,23,14,65,231,26,140,209,66,122,8,81,179,5,101,195,26,32,47,74,
+    75,13,69,159,11,83,235,11,67,21,16,136,167,131,106,130,165,130,15,32,128,101,90,24,134,142,32,0,65,103,51,108,23,11,101,231,15,75,173,23,74,237,23,66,15,6,66,46,17,66,58,17,65,105,
+    49,66,247,55,71,179,12,70,139,15,86,229,7,84,167,15,32,1,95,72,12,89,49,6,33,128,128,65,136,38,66,30,9,32,0,100,239,7,66,247,29,70,105,20,65,141,19,69,81,15,130,144,32,128,83,41,5,
+    32,255,131,177,68,185,5,133,126,65,97,37,32,0,130,0,33,21,0,130,55,66,195,28,67,155,13,34,79,0,83,66,213,13,73,241,19,66,59,19,65,125,11,135,201,66,249,16,32,128,66,44,11,66,56,17,
+    68,143,8,68,124,38,67,183,12,96,211,9,65,143,29,112,171,5,32,0,68,131,63,34,33,53,51,71,121,11,32,254,98,251,16,32,253,74,231,10,65,175,37,133,206,37,0,0,8,1,0,0,107,123,11,113,115,
+    9,33,0,1,130,117,131,3,73,103,7,66,51,18,66,44,5,133,75,70,88,5,32,254,65,39,12,68,80,9,34,12,0,128,107,179,28,68,223,6,155,111,86,147,15,32,2,131,82,141,110,33,254,0,130,15,32,4,103,
+    184,15,141,35,87,176,5,83,11,5,71,235,23,114,107,11,65,189,16,70,33,15,86,153,31,135,126,86,145,30,65,183,41,32,0,130,0,32,10,65,183,24,34,35,0,39,67,85,9,65,179,15,143,15,33,1,0,65,
+    28,17,157,136,130,123,32,20,130,3,32,0,97,135,24,115,167,19,80,71,12,32,51,110,163,14,78,35,19,131,19,155,23,77,229,8,78,9,17,151,17,67,231,46,94,135,8,73,31,31,93,215,56,82,171,25,
+    72,77,8,162,179,169,167,99,131,11,69,85,19,66,215,15,76,129,13,68,115,22,72,79,35,67,113,5,34,0,0,19,70,31,46,65,89,52,73,223,15,85,199,33,95,33,8,132,203,73,29,32,67,48,16,177,215,
+    101,13,15,65,141,43,69,141,15,75,89,5,70,0,11,70,235,21,178,215,36,10,0,128,0,0,71,207,24,33,0,19,100,67,6,80,215,11,66,67,7,80,43,12,71,106,7,80,192,5,65,63,5,66,217,26,33,0,13,156,
+    119,68,95,5,72,233,12,134,129,85,81,11,76,165,20,65,43,8,73,136,8,75,10,31,38,128,128,0,0,0,13,1,130,4,32,3,106,235,29,114,179,12,66,131,23,32,7,77,133,6,67,89,12,131,139,116,60,9,
+    89,15,37,32,0,74,15,7,103,11,22,65,35,5,33,55,0,93,81,28,67,239,23,78,85,5,107,93,14,66,84,17,65,193,26,74,183,10,66,67,34,143,135,79,91,15,32,7,117,111,8,75,56,9,84,212,9,154,134,
+    32,0,130,0,32,18,130,3,70,171,41,83,7,16,70,131,19,84,191,15,84,175,19,84,167,30,84,158,12,154,193,68,107,15,33,0,0,65,79,42,65,71,7,73,55,7,118,191,16,83,180,9,32,255,76,166,9,154,
+    141,32,0,130,0,69,195,52,65,225,15,151,15,75,215,31,80,56,10,68,240,17,100,32,9,70,147,39,65,93,12,71,71,41,92,85,15,84,135,23,78,35,15,110,27,10,84,125,8,107,115,29,136,160,38,0,0,
+    14,0,128,255,0,82,155,24,67,239,8,119,255,11,69,131,11,77,29,6,112,31,8,134,27,105,203,8,32,2,75,51,11,75,195,12,74,13,29,136,161,37,128,0,0,0,11,1,130,163,82,115,8,125,191,17,69,35,
+    12,74,137,15,143,15,32,1,65,157,12,136,12,161,142,65,43,40,65,199,6,65,19,24,102,185,11,76,123,11,99,6,12,135,12,32,254,130,8,161,155,101,23,9,39,8,0,0,1,128,3,128,2,78,63,17,72,245,
+    12,67,41,11,90,167,9,32,128,97,49,9,32,128,109,51,14,132,97,81,191,8,130,97,125,99,12,121,35,9,127,75,15,71,79,12,81,151,23,87,97,7,70,223,15,80,245,16,105,97,15,32,254,113,17,6,32,
+    128,130,8,105,105,8,76,122,18,65,243,21,74,63,7,38,4,1,0,255,0,2,0,119,247,28,133,65,32,255,141,91,35,0,0,0,16,67,63,36,34,59,0,63,77,59,9,119,147,11,143,241,66,173,15,66,31,11,67,
+    75,8,81,74,16,32,128,131,255,87,181,42,127,43,5,34,255,128,2,120,235,11,37,19,0,23,0,0,37,109,191,14,118,219,7,127,43,14,65,79,14,35,0,0,0,3,73,91,5,130,5,38,3,0,7,0,11,0,0,70,205,
+    11,88,221,12,32,0,73,135,7,87,15,22,73,135,10,79,153,15,97,71,19,65,49,11,32,1,131,104,121,235,11,80,65,11,142,179,144,14,81,123,46,32,1,88,217,5,112,5,8,65,201,15,83,29,15,122,147,
+    11,135,179,142,175,143,185,67,247,39,66,199,7,35,5,0,128,3,69,203,15,123,163,12,67,127,7,130,119,71,153,10,141,102,70,175,8,32,128,121,235,30,136,89,100,191,11,116,195,11,111,235,15,
+    72,39,7,32,2,97,43,5,132,5,94,67,8,131,8,125,253,10,32,3,65,158,16,146,16,130,170,40,0,21,0,128,0,0,3,128,5,88,219,15,24,64,159,32,135,141,65,167,15,68,163,10,97,73,49,32,255,82,58,
+    7,93,80,8,97,81,16,24,67,87,52,34,0,0,5,130,231,33,128,2,80,51,13,65,129,8,113,61,6,132,175,65,219,5,130,136,77,152,17,32,0,95,131,61,70,215,6,33,21,51,90,53,10,78,97,23,105,77,31,
+    65,117,7,139,75,24,68,195,9,24,64,22,9,33,0,128,130,11,33,128,128,66,25,5,121,38,5,134,5,134,45,66,40,36,66,59,18,34,128,0,0,66,59,81,135,245,123,103,19,120,159,19,77,175,12,33,255,
+    0,87,29,10,94,70,21,66,59,54,39,3,1,128,3,0,2,128,4,24,65,7,15,66,47,7,72,98,12,37,0,0,0,3,1,0,24,65,55,21,131,195,32,1,67,178,6,33,4,0,77,141,8,32,6,131,47,74,67,16,24,69,3,20,24,
+    65,251,7,133,234,130,229,94,108,17,35,0,0,6,0,141,175,86,59,5,162,79,85,166,8,70,112,13,32,13,24,64,67,26,24,71,255,7,123,211,12,80,121,11,69,215,15,66,217,11,69,71,10,131,113,132,
+    126,119,90,9,66,117,19,132,19,32,0,130,0,24,64,47,59,33,7,0,73,227,5,68,243,15,85,13,12,76,37,22,74,254,15,130,138,33,0,4,65,111,6,137,79,65,107,16,32,1,77,200,6,34,128,128,3,75,154,
+    12,37,0,16,0,0,2,0,104,115,36,140,157,68,67,19,68,51,15,106,243,15,134,120,70,37,10,68,27,10,140,152,65,121,24,32,128,94,155,7,67,11,8,24,74,11,25,65,3,12,83,89,18,82,21,37,67,200,
+    5,130,144,24,64,172,12,33,4,0,134,162,74,80,14,145,184,32,0,130,0,69,251,20,32,19,81,243,5,82,143,8,33,5,53,89,203,5,133,112,79,109,15,33,0,21,130,71,80,175,41,36,75,0,79,0,83,121,
+    117,9,87,89,27,66,103,11,70,13,15,75,191,11,135,67,87,97,20,109,203,5,69,246,8,108,171,5,78,195,38,65,51,13,107,203,11,77,3,17,24,75,239,17,65,229,28,79,129,39,130,175,32,128,123,253,
+    7,132,142,24,65,51,15,65,239,41,36,128,128,0,0,13,65,171,5,66,163,28,136,183,118,137,11,80,255,15,67,65,7,74,111,8,32,0,130,157,32,253,24,76,35,10,103,212,5,81,175,9,69,141,7,66,150,
+    29,131,158,24,75,199,28,124,185,7,76,205,15,68,124,14,32,3,123,139,16,130,16,33,128,128,108,199,6,33,0,3,65,191,35,107,11,6,73,197,11,24,70,121,15,83,247,15,24,70,173,23,69,205,14,
+    32,253,131,140,32,254,136,4,94,198,9,32,3,78,4,13,66,127,13,143,13,32,0,130,0,33,16,0,24,69,59,39,109,147,12,76,253,19,24,69,207,15,69,229,15,130,195,71,90,10,139,10,130,152,73,43,
+    40,91,139,10,65,131,37,35,75,0,79,0,84,227,12,143,151,68,25,15,80,9,23,95,169,11,34,128,2,128,112,186,5,130,6,83,161,19,76,50,6,130,37,65,145,44,110,83,5,32,16,67,99,6,71,67,15,76,
+    55,17,140,215,67,97,23,76,69,15,77,237,11,104,211,23,77,238,11,65,154,43,33,0,10,83,15,28,83,13,20,67,145,19,67,141,14,97,149,21,68,9,15,86,251,5,66,207,5,66,27,37,82,1,23,127,71,12,
+    94,235,10,110,175,24,98,243,15,132,154,132,4,24,66,69,10,32,4,67,156,43,130,198,35,2,1,0,4,75,27,9,69,85,9,95,240,7,32,128,130,35,32,28,66,43,40,24,82,63,23,83,123,12,72,231,15,127,
+    59,23,116,23,19,117,71,7,24,77,99,15,67,111,15,71,101,8,36,2,128,128,252,128,127,60,11,32,1,132,16,130,18,141,24,67,107,9,32,3,68,194,15,175,15,38,0,11,0,128,1,128,2,80,63,25,32,0,
+    24,65,73,11,69,185,15,83,243,16,32,0,24,81,165,8,130,86,77,35,6,155,163,88,203,5,24,66,195,30,70,19,19,24,80,133,15,32,1,75,211,8,32,254,108,133,8,79,87,20,65,32,9,41,0,0,7,0,128,0,
+    0,2,128,2,68,87,15,66,1,16,92,201,16,24,76,24,17,133,17,34,128,0,30,66,127,64,34,115,0,119,73,205,9,66,43,11,109,143,15,24,79,203,11,90,143,15,131,15,155,31,65,185,15,86,87,11,35,128,
+    128,253,0,69,7,6,130,213,33,1,0,119,178,15,142,17,66,141,74,83,28,6,36,7,0,0,4,128,82,39,18,76,149,12,67,69,21,32,128,79,118,15,32,0,130,0,32,8,131,206,32,2,79,83,9,100,223,14,102,
+    113,23,115,115,7,24,65,231,12,130,162,32,4,68,182,19,130,102,93,143,8,69,107,29,24,77,255,12,143,197,72,51,7,76,195,15,132,139,85,49,15,130,152,131,18,71,81,23,70,14,11,36,0,10,0,128,
+    2,69,59,9,89,151,15,66,241,11,76,165,12,71,43,15,75,49,13,65,12,23,132,37,32,0,179,115,130,231,95,181,16,132,77,32,254,67,224,8,65,126,20,79,171,8,32,2,89,81,5,75,143,6,80,41,8,34,
+    2,0,128,24,81,72,9,32,0,130,0,35,17,0,0,255,77,99,39,95,65,36,67,109,15,24,69,93,11,77,239,5,95,77,23,35,128,1,0,128,24,86,7,8,132,167,32,2,69,198,41,130,202,33,0,26,120,75,44,24,89,
+    51,15,71,243,12,70,239,11,24,84,3,11,66,7,11,71,255,10,32,21,69,155,35,88,151,12,32,128,74,38,10,65,210,8,74,251,5,65,226,5,75,201,13,32,3,65,9,41,146,41,40,0,0,0,9,1,0,1,0,2,91,99,
+    19,32,35,106,119,13,70,219,15,83,239,12,137,154,32,2,67,252,19,36,128,0,0,4,1,130,196,32,2,130,8,91,107,8,32,0,135,81,24,73,211,8,132,161,73,164,13,36,0,8,0,128,2,105,123,26,139,67,
+    76,99,15,34,1,0,128,135,76,83,156,20,92,104,8,67,251,30,24,86,47,27,123,207,12,24,86,7,15,71,227,8,32,4,65,20,20,131,127,32,0,130,123,32,0,71,223,26,32,19,90,195,22,71,223,15,84,200,
+    6,32,128,133,241,24,84,149,9,67,41,25,36,0,0,0,22,0,88,111,49,32,87,66,21,5,77,3,27,123,75,7,71,143,19,135,183,71,183,19,130,171,74,252,5,131,5,89,87,17,32,1,132,18,130,232,68,11,10,
+    33,1,128,70,208,16,66,230,18,147,18,130,254,223,255,75,27,23,65,59,15,135,39,155,255,34,128,128,254,104,92,8,33,0,128,65,32,11,65,1,58,33,26,0,130,0,72,71,18,78,55,17,76,11,19,86,101,
+    12,75,223,11,89,15,11,24,76,87,15,75,235,15,131,15,72,95,7,85,71,11,72,115,11,73,64,6,34,1,128,128,66,215,9,34,128,254,128,134,14,33,128,255,67,102,5,32,0,130,16,70,38,11,66,26,57,
+    88,11,8,24,76,215,34,78,139,7,95,245,7,32,7,24,73,75,23,32,128,131,167,130,170,101,158,9,82,49,22,118,139,6,32,18,67,155,44,116,187,9,108,55,14,80,155,23,66,131,15,93,77,10,131,168,
+    32,128,73,211,12,24,75,187,22,32,4,96,71,20,67,108,19,132,19,120,207,8,32,5,76,79,15,66,111,21,66,95,8,32,3,190,211,111,3,8,211,212,32,20,65,167,44,34,75,0,79,97,59,13,32,33,112,63,
+    10,65,147,19,69,39,19,143,39,24,66,71,9,130,224,65,185,43,94,176,12,65,183,24,71,38,8,24,72,167,7,65,191,38,136,235,24,96,167,12,65,203,62,115,131,13,65,208,42,175,235,67,127,6,32,
+    4,76,171,29,114,187,5,32,71,65,211,5,65,203,68,72,51,8,164,219,32,0,172,214,71,239,58,78,3,27,66,143,15,77,19,15,147,31,35,33,53,51,21,66,183,10,173,245,66,170,30,150,30,34,0,0,23,
+    80,123,54,76,1,16,73,125,15,82,245,11,167,253,24,76,85,12,70,184,5,32,254,131,185,37,254,0,128,1,0,128,133,16,117,158,18,92,27,38,65,3,17,130,251,35,17,0,128,254,24,69,83,39,140,243,
+    121,73,19,109,167,7,81,41,15,24,95,175,12,102,227,15,121,96,11,24,95,189,7,32,3,145,171,154,17,24,77,47,9,33,0,5,70,71,37,68,135,7,32,29,117,171,11,69,87,15,24,79,97,19,24,79,149,23,
+    131,59,32,1,75,235,5,72,115,11,72,143,7,132,188,71,27,46,131,51,32,0,69,95,6,175,215,32,21,131,167,81,15,19,151,191,151,23,131,215,71,43,5,32,254,24,79,164,24,74,109,8,77,166,13,65,
+    176,26,88,162,5,98,159,6,171,219,120,247,6,79,29,8,99,169,10,103,59,19,65,209,35,131,35,91,25,19,112,94,15,83,36,8,173,229,33,20,0,88,75,43,71,31,12,65,191,71,33,1,0,130,203,32,254,
+    131,4,68,66,7,67,130,6,104,61,13,173,215,38,13,1,0,0,0,2,128,67,111,28,74,129,16,104,35,19,79,161,16,87,14,7,138,143,132,10,67,62,36,114,115,5,162,151,67,33,16,108,181,15,143,151,67,
+    5,5,24,100,242,15,170,153,34,0,0,14,65,51,34,32,55,79,75,9,32,51,74,7,10,65,57,38,132,142,32,254,72,0,14,139,163,32,128,80,254,8,67,158,21,65,63,7,32,4,72,227,27,95,155,12,67,119,19,
+    124,91,24,149,154,72,177,34,97,223,8,155,151,24,108,227,15,88,147,16,72,117,19,68,35,11,92,253,15,70,199,15,24,87,209,17,32,2,87,233,7,32,1,24,88,195,10,119,24,8,32,3,81,227,24,65,
+    125,21,35,128,128,0,25,76,59,48,24,90,187,9,97,235,12,66,61,11,91,105,19,24,79,141,11,24,79,117,15,24,79,129,27,90,53,13,130,13,32,253,131,228,24,79,133,40,69,70,8,66,137,31,65,33,
+    19,96,107,8,68,119,29,66,7,5,68,125,16,65,253,19,65,241,27,24,90,179,13,24,79,143,18,33,128,128,130,246,32,254,130,168,68,154,36,77,51,9,97,47,5,167,195,32,21,131,183,78,239,27,155,
+    195,78,231,14,201,196,77,11,6,32,5,73,111,37,97,247,12,77,19,31,155,207,78,215,19,162,212,69,17,14,66,91,19,80,143,57,78,203,39,159,215,32,128,93,134,8,24,80,109,24,66,113,15,169,215,
+    66,115,6,32,4,69,63,33,32,0,101,113,7,86,227,35,143,211,36,49,53,51,21,1,77,185,14,65,159,28,69,251,34,67,56,8,33,9,0,24,107,175,25,90,111,12,110,251,11,119,189,24,119,187,34,87,15,
+    9,32,4,66,231,37,90,39,7,66,239,8,84,219,15,69,105,23,24,85,27,27,87,31,11,33,1,128,76,94,6,32,1,85,241,7,33,128,128,106,48,10,33,128,128,69,136,11,133,13,24,79,116,49,84,236,8,24,
+    91,87,9,32,5,165,255,69,115,12,66,27,15,159,15,24,72,247,12,74,178,5,24,80,64,15,33,0,128,143,17,77,89,51,130,214,24,81,43,7,170,215,74,49,8,159,199,143,31,139,215,69,143,5,32,254,
+    24,81,50,35,181,217,84,123,70,143,195,159,15,65,187,16,66,123,7,65,175,15,65,193,29,68,207,39,79,27,5,70,131,6,32,4,68,211,33,33,67,0,83,143,14,159,207,143,31,140,223,33,0,128,24,80,
+    82,14,24,93,16,23,32,253,65,195,5,68,227,40,133,214,107,31,7,32,5,67,115,27,87,9,8,107,31,43,66,125,6,32,0,103,177,23,131,127,72,203,36,32,0,110,103,8,155,163,73,135,6,32,19,24,112,
+    99,10,65,71,11,73,143,19,143,31,126,195,5,24,85,21,9,24,76,47,14,32,254,24,93,77,36,68,207,11,39,25,0,0,255,128,3,128,4,66,51,37,95,247,13,82,255,24,76,39,19,147,221,66,85,27,24,118,
+    7,8,24,74,249,12,76,74,8,91,234,8,67,80,17,131,222,33,253,0,121,30,44,73,0,16,69,15,6,32,0,65,23,38,69,231,12,65,179,6,98,131,16,86,31,27,24,108,157,14,80,160,8,24,65,46,17,33,4,0,
+    96,2,18,144,191,65,226,8,68,19,5,171,199,80,9,15,180,199,67,89,5,32,255,24,79,173,28,174,201,24,79,179,50,32,1,24,122,5,10,82,61,10,180,209,83,19,8,32,128,24,80,129,27,111,248,43,131,
+    71,24,115,103,8,67,127,41,78,213,24,100,247,19,66,115,39,75,107,5,32,254,165,219,78,170,40,24,112,163,49,32,1,97,203,6,65,173,64,32,0,83,54,7,133,217,88,37,12,32,254,131,28,33,128,
+    3,67,71,44,84,183,6,32,5,69,223,33,96,7,7,123,137,16,192,211,24,112,14,9,32,255,67,88,29,68,14,10,84,197,38,33,0,22,116,47,50,32,87,106,99,9,116,49,15,89,225,15,97,231,23,70,41,19,
+    82,85,8,93,167,6,32,253,132,236,108,190,7,89,251,5,116,49,58,33,128,128,131,234,32,15,24,74,67,38,70,227,24,24,83,45,23,89,219,12,70,187,12,89,216,19,32,2,69,185,24,141,24,70,143,66,
+    24,82,119,56,78,24,10,32,253,133,149,132,6,24,106,233,7,69,198,48,178,203,81,243,12,68,211,15,106,255,23,66,91,15,69,193,7,100,39,10,24,83,72,16,176,204,33,19,0,88,207,45,68,21,12,
+    68,17,10,65,157,53,68,17,6,32,254,92,67,10,65,161,25,69,182,43,24,118,91,47,69,183,18,181,209,111,253,12,89,159,8,66,112,12,69,184,45,35,0,0,0,9,24,80,227,26,73,185,16,118,195,15,131,
+    15,33,1,0,65,59,15,66,39,27,160,111,66,205,12,148,111,143,110,33,128,128,156,112,24,81,199,8,75,199,23,66,117,20,155,121,32,254,68,126,12,72,213,29,134,239,149,123,89,27,16,148,117,
+    65,245,8,24,71,159,14,141,134,134,28,73,51,55,109,77,15,105,131,11,68,67,11,76,169,27,107,209,12,102,174,8,32,128,72,100,18,116,163,56,79,203,11,75,183,44,85,119,19,71,119,23,151,227,
+    32,1,93,27,8,65,122,5,77,102,8,110,120,20,66,23,8,66,175,17,66,63,12,133,12,79,35,8,74,235,33,67,149,16,69,243,15,78,57,15,69,235,16,67,177,7,151,192,130,23,67,84,29,141,192,174,187,
+    77,67,15,69,11,12,159,187,77,59,10,199,189,24,70,235,50,96,83,19,66,53,23,105,65,19,77,47,12,163,199,66,67,37,78,207,50,67,23,23,174,205,67,228,6,71,107,13,67,22,14,66,85,11,83,187,
+    38,124,47,49,95,7,19,66,83,23,67,23,19,24,96,78,17,80,101,16,71,98,40,33,0,7,88,131,22,24,89,245,12,84,45,12,102,213,5,123,12,9,32,2,126,21,14,43,255,0,128,128,0,0,20,0,128,255,128,
+    3,126,19,39,32,75,106,51,7,113,129,15,24,110,135,19,126,47,15,115,117,11,69,47,11,32,2,109,76,9,102,109,9,32,128,75,2,10,130,21,32,254,69,47,6,32,3,94,217,47,32,0,65,247,10,69,15,46,
+    65,235,31,65,243,15,101,139,10,66,174,14,65,247,16,72,102,28,69,17,14,84,243,9,165,191,88,47,48,66,53,12,32,128,71,108,6,203,193,32,17,75,187,42,73,65,16,65,133,52,114,123,9,167,199,
+    69,21,37,86,127,44,75,171,11,180,197,78,213,12,148,200,81,97,46,24,95,243,9,32,4,66,75,33,113,103,9,87,243,36,143,225,24,84,27,31,90,145,8,148,216,67,49,5,24,84,34,14,75,155,27,67,
+    52,13,140,13,36,0,20,0,128,255,24,135,99,46,88,59,43,155,249,80,165,7,136,144,71,161,23,32,253,132,33,32,254,88,87,44,136,84,35,128,0,0,21,81,103,5,94,47,44,76,51,12,143,197,151,15,
+    65,215,31,24,64,77,13,65,220,20,65,214,14,71,4,40,65,213,13,32,0,130,0,35,21,1,2,0,135,0,34,36,0,72,134,10,36,1,0,26,0,130,134,11,36,2,0,14,0,108,134,11,32,3,138,23,32,4,138,11,34,
+    5,0,20,134,33,34,0,0,6,132,23,32,1,134,15,32,18,130,25,133,11,37,1,0,13,0,49,0,133,11,36,2,0,7,0,38,134,11,36,3,0,17,0,45,134,11,32,4,138,35,36,5,0,10,0,62,134,23,32,6,132,23,36,3,
+    0,1,4,9,130,87,131,167,133,11,133,167,133,11,133,167,133,11,37,3,0,34,0,122,0,133,11,133,167,133,11,133,167,133,11,133,167,34,50,0,48,130,1,34,52,0,47,134,5,8,49,49,0,53,98,121,32,
+    84,114,105,115,116,97,110,32,71,114,105,109,109,101,114,82,101,103,117,108,97,114,84,84,88,32,80,114,111,103,103,121,67,108,101,97,110,84,84,50,48,48,52,47,130,2,53,49,53,0,98,0,121,
+    0,32,0,84,0,114,0,105,0,115,0,116,0,97,0,110,130,15,32,71,132,15,36,109,0,109,0,101,130,9,32,82,130,5,36,103,0,117,0,108,130,29,32,114,130,43,34,84,0,88,130,35,32,80,130,25,34,111,
+    0,103,130,1,34,121,0,67,130,27,32,101,132,59,32,84,130,31,33,0,0,65,155,9,34,20,0,0,65,11,6,130,8,135,2,33,1,1,130,9,8,120,1,1,2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,1,10,1,11,1,12,1,13,1,14,
+    1,15,1,16,1,17,1,18,1,19,1,20,1,21,1,22,1,23,1,24,1,25,1,26,1,27,1,28,1,29,1,30,1,31,1,32,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,16,0,17,0,18,0,19,0,20,0,21,0,
+    22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0,31,130,187,8,66,33,0,34,0,35,0,36,0,37,0,38,0,39,0,40,0,41,0,42,0,43,0,44,0,45,0,46,0,47,0,48,0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,
+    57,0,58,0,59,0,60,0,61,0,62,0,63,0,64,0,65,0,66,130,243,9,75,68,0,69,0,70,0,71,0,72,0,73,0,74,0,75,0,76,0,77,0,78,0,79,0,80,0,81,0,82,0,83,0,84,0,85,0,86,0,87,0,88,0,89,0,90,0,91,0,
+    92,0,93,0,94,0,95,0,96,0,97,1,33,1,34,1,35,1,36,1,37,1,38,1,39,1,40,1,41,1,42,1,43,1,44,1,45,1,46,1,47,1,48,1,49,1,50,1,51,1,52,1,53,1,54,1,55,1,56,1,57,1,58,1,59,1,60,1,61,1,62,1,
+    63,1,64,1,65,0,172,0,163,0,132,0,133,0,189,0,150,0,232,0,134,0,142,0,139,0,157,0,169,0,164,0,239,0,138,0,218,0,131,0,147,0,242,0,243,0,141,0,151,0,136,0,195,0,222,0,241,0,158,0,170,
+    0,245,0,244,0,246,0,162,0,173,0,201,0,199,0,174,0,98,0,99,0,144,0,100,0,203,0,101,0,200,0,202,0,207,0,204,0,205,0,206,0,233,0,102,0,211,0,208,0,209,0,175,0,103,0,240,0,145,0,214,0,
+    212,0,213,0,104,0,235,0,237,0,137,0,106,0,105,0,107,0,109,0,108,0,110,0,160,0,111,0,113,0,112,0,114,0,115,0,117,0,116,0,118,0,119,0,234,0,120,0,122,0,121,0,123,0,125,0,124,0,184,0,
+    161,0,127,0,126,0,128,0,129,0,236,0,238,0,186,14,117,110,105,99,111,100,101,35,48,120,48,48,48,49,141,14,32,50,141,14,32,51,141,14,32,52,141,14,32,53,141,14,32,54,141,14,32,55,141,
+    14,32,56,141,14,32,57,141,14,32,97,141,14,32,98,141,14,32,99,141,14,32,100,141,14,32,101,141,14,32,102,140,14,33,49,48,141,14,141,239,32,49,141,239,32,49,141,239,32,49,141,239,32,49,
+    141,239,32,49,141,239,32,49,141,239,32,49,141,239,32,49,141,239,32,49,141,239,32,49,141,239,32,49,141,239,32,49,141,239,32,49,141,239,45,49,102,6,100,101,108,101,116,101,4,69,117,114,
+    111,140,236,32,56,141,236,32,56,141,236,32,56,141,236,32,56,141,236,32,56,141,236,32,56,141,236,32,56,141,236,32,56,141,236,32,56,141,236,32,56,141,236,32,56,141,236,32,56,141,236,
+    32,56,141,236,32,56,141,236,32,56,65,220,13,32,57,65,220,13,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,
+    239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,35,57,102,0,0,5,250,72,249,98,247,
+};
+
+static const char* GetDefaultCompressedFontDataTTF(int* out_size)
+{
+    *out_size = proggy_clean_ttf_compressed_size;
+    return (const char*)proggy_clean_ttf_compressed_data;
 }
 #endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
 
diff --git a/misc/fonts/binary_to_compressed_c.cpp b/misc/fonts/binary_to_compressed_c.cpp
index f41d20f75733..f16c3b2c3af1 100644
--- a/misc/fonts/binary_to_compressed_c.cpp
+++ b/misc/fonts/binary_to_compressed_c.cpp
@@ -113,21 +113,42 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
         }
         fprintf(out, "\";\n\n");
     }
+#if 0
     else
     {
+        // As individual bytes, not subject to endianness issues.
+        fprintf(out, "%sconst unsigned int %s_%ssize = %d;\n", static_str, symbol, compressed_str, (int)compressed_sz);
+        fprintf(out, "%sconst unsigned char %s_%sdata[%d] =\n{", static_str, symbol, compressed_str, (int)compressed_sz);
+        int column = 0;
+        for (int i = 0; i < compressed_sz; i++)
+        {
+            unsigned char d = *(unsigned char*)(compressed + i);
+            if (column == 0)
+                fprintf(out, "\n    ");
+            column += fprintf(out, "%d,", d);
+            if (column >= 180)
+                column = 0;
+        }
+        fprintf(out, "\n};\n\n");
+    }
+#else
+    else
+    {
+        // As integers
         fprintf(out, "%sconst unsigned int %s_%ssize = %d;\n", static_str, symbol, compressed_str, (int)compressed_sz);
         fprintf(out, "%sconst unsigned int %s_%sdata[%d/4] =\n{", static_str, symbol, compressed_str, (int)((compressed_sz + 3) / 4)*4);
         int column = 0;
         for (int i = 0; i < compressed_sz; i += 4)
         {
             unsigned int d = *(unsigned int*)(compressed + i);
-            if ((column++ % 12) == 0)
+            if ((column++ % 14) == 0)
                 fprintf(out, "\n    0x%08x, ", d);
             else
                 fprintf(out, "0x%08x, ", d);
         }
         fprintf(out, "\n};\n\n");
     }
+#endif
 
     // Cleanup
     delete[] data;

From 551b6c4d662a3938f0cd197e79cc29922feec1ff Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 20 Nov 2024 14:32:44 +0100
Subject: [PATCH 270/548] Tools: binary_to_compressed_c: added -u8/-u32/-base85
 export options.

---
 docs/CHANGELOG.txt                    |  1 +
 imgui_draw.cpp                        |  6 ++--
 misc/fonts/binary_to_compressed_c.cpp | 51 +++++++++++++++++----------
 3 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 5305b889e51a..5a49416e20c9 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -56,6 +56,7 @@ Other changes:
 - Misc: changed embedded ProggyClean encoding to save a bit of binary space (~12kb to 9.5kb).
 - Misc: added IMGUI_DISABLE_DEFAULT_FONT to strip embedded font from binary. (#8161)
   [@demonese]
+- Tools: binary_to_compressed_c: added -u8/-u32/-base85 export options.
 - Demo: example tree used by Property Editor & Selection demos properly freed
   on application closure. (#8158) [@Legulysse]
 - Examples: Win32+DX12: Using a basic free-list allocator to manage multiple
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 0f74a98b3d07..5647f53fde72 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -4583,11 +4583,11 @@ static unsigned int stb_decompress(unsigned char *output, const unsigned char *i
 // MIT license (see License.txt in http://www.proggyfonts.net/index.php?menu=download)
 // Download and more information at http://www.proggyfonts.net or http://upperboundsinteractive.com/fonts.php
 //-----------------------------------------------------------------------------
-// File: 'ProggyClean.ttf' (41208 bytes)
-// Exported using "misc/fonts/binary_to_compressed_c.exe ../ProggyClean.ttf proggy_clean_ttf_compressed (with compression, no base85 encoding).
-//-----------------------------------------------------------------------------
 
 #ifndef IMGUI_DISABLE_DEFAULT_FONT
+
+// File: 'ProggyClean.ttf' (41208 bytes)
+// Exported using binary_to_compressed_c.exe -u8 "ProggyClean.ttf" proggy_clean_ttf
 static const unsigned int proggy_clean_ttf_compressed_size = 9583;
 static const unsigned char proggy_clean_ttf_compressed_data[9583] =
 {
diff --git a/misc/fonts/binary_to_compressed_c.cpp b/misc/fonts/binary_to_compressed_c.cpp
index f16c3b2c3af1..b0a243a710df 100644
--- a/misc/fonts/binary_to_compressed_c.cpp
+++ b/misc/fonts/binary_to_compressed_c.cpp
@@ -2,10 +2,11 @@
 // (binary_to_compressed_c.cpp)
 // Helper tool to turn a file into a C array, if you want to embed font data in your source code.
 
-// The data is first compressed with stb_compress() to reduce source code size,
-// then encoded in Base85 to fit in a string so we can fit roughly 4 bytes of compressed data into 5 bytes of source code (suggested by @mmalex)
-// (If we used 32-bit constants it would require take 11 bytes of source code to encode 4 bytes, and be endianness dependent)
-// Note that even with compression, the output array is likely to be bigger than the binary file..
+// The data is first compressed with stb_compress() to reduce source code size.
+// Then stored in a C array:
+// - Base85:   ~5 bytes of source code for 4 bytes of input data. 5 bytes stored in binary (suggested by @mmalex).
+// - As int:  ~11 bytes of source code for 4 bytes of input data. 4 bytes stored in binary. Endianness dependant, need swapping on big-endian CPU.
+// - As char: ~12 bytes of source code for 4 bytes of input data. 4 bytes stored in binary. Not endianness dependant.
 // Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF()
 
 // Build with, e.g:
@@ -15,10 +16,12 @@
 // You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui
 
 // Usage:
-//   binary_to_compressed_c.exe [-base85] [-nocompress] [-nostatic]  
+//   binary_to_compressed_c.exe [-nocompress] [-nostatic] [-base85]  
 // Usage example:
 //   # binary_to_compressed_c.exe myfont.ttf MyFont > myfont.cpp
 //   # binary_to_compressed_c.exe -base85 myfont.ttf MyFont > myfont.cpp
+// Note:
+//   Base85 encoding will be obsoleted by future version of Dear ImGui!
 
 #define _CRT_SECURE_NO_WARNINGS
 #include 
@@ -31,23 +34,36 @@ typedef unsigned int stb_uint;
 typedef unsigned char stb_uchar;
 stb_uint stb_compress(stb_uchar* out, stb_uchar* in, stb_uint len);
 
-static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression, bool use_static);
+enum SourceEncoding
+{
+    SourceEncoding_U8,      // New default since 2024/11
+    SourceEncoding_U32,
+    SourceEncoding_Base85,
+};
+
+static bool binary_to_compressed_c(const char* filename, const char* symbol, SourceEncoding source_encoding, bool use_compression, bool use_static);
 
 int main(int argc, char** argv)
 {
     if (argc < 3)
     {
-        printf("Syntax: %s [-base85] [-nocompress] [-nostatic]  \n", argv[0]);
+        printf("Syntax: %s [-u8|-u32|-base85] [-nocompress] [-nostatic]  \n", argv[0]);
+        printf("Source encoding types:\n");
+        printf(" -u8     = ~12 bytes of source per 4 bytes of data. 4 bytes in binary.\n");
+        printf(" -u32    = ~11 bytes of source per 4 bytes of data. 4 bytes in binary. Need endianness swapping on big-endian.\n");
+        printf(" -base85 =  ~5 bytes of source per 4 bytes of data. 5 bytes in binary. Need decoder.\n");
         return 0;
     }
 
     int argn = 1;
-    bool use_base85_encoding = false;
     bool use_compression = true;
     bool use_static = true;
+    SourceEncoding source_encoding = SourceEncoding_U8; // New default
     while (argn < (argc - 2) && argv[argn][0] == '-')
     {
-        if (strcmp(argv[argn], "-base85") == 0) { use_base85_encoding = true; argn++; }
+        if (strcmp(argv[argn], "-u8") == 0) { source_encoding = SourceEncoding_U8; argn++; }
+        else if (strcmp(argv[argn], "-u32") == 0) { source_encoding = SourceEncoding_U32; argn++; }
+        else if (strcmp(argv[argn], "-base85") == 0) { source_encoding = SourceEncoding_Base85; argn++; }
         else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; }
         else if (strcmp(argv[argn], "-nostatic") == 0) { use_static = false; argn++; }
         else
@@ -57,7 +73,7 @@ int main(int argc, char** argv)
         }
     }
 
-    bool ret = binary_to_compressed_c(argv[argn], argv[argn + 1], use_base85_encoding, use_compression, use_static);
+    bool ret = binary_to_compressed_c(argv[argn], argv[argn + 1], source_encoding, use_compression, use_static);
     if (!ret)
         fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]);
     return ret ? 0 : 1;
@@ -69,7 +85,7 @@ char Encode85Byte(unsigned int x)
     return (char)((x >= '\\') ? x + 1 : x);
 }
 
-bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression, bool use_static)
+bool binary_to_compressed_c(const char* filename, const char* symbol, SourceEncoding source_encoding, bool use_compression, bool use_static)
 {
     // Read file
     FILE* f = fopen(filename, "rb");
@@ -91,11 +107,11 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
     // Output as Base85 encoded
     FILE* out = stdout;
     fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz);
-    fprintf(out, "// Exported using binary_to_compressed_c.cpp\n");
     const char* static_str = use_static ? "static " : "";
     const char* compressed_str = use_compression ? "compressed_" : "";
-    if (use_base85_encoding)
+    if (source_encoding == SourceEncoding_Base85)
     {
+        fprintf(out, "// Exported using binary_to_compressed_c.exe -base85 \"%s\" %s\n", filename, symbol);
         fprintf(out, "%sconst char %s_%sdata_base85[%d+1] =\n    \"", static_str, symbol, compressed_str, (int)((compressed_sz + 3) / 4)*5);
         char prev_c = 0;
         for (int src_i = 0; src_i < compressed_sz; src_i += 4)
@@ -113,10 +129,10 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
         }
         fprintf(out, "\";\n\n");
     }
-#if 0
-    else
+    else if (source_encoding == SourceEncoding_U8)
     {
         // As individual bytes, not subject to endianness issues.
+        fprintf(out, "// Exported using binary_to_compressed_c.exe -u8 \"%s\" %s\n", filename, symbol);
         fprintf(out, "%sconst unsigned int %s_%ssize = %d;\n", static_str, symbol, compressed_str, (int)compressed_sz);
         fprintf(out, "%sconst unsigned char %s_%sdata[%d] =\n{", static_str, symbol, compressed_str, (int)compressed_sz);
         int column = 0;
@@ -131,10 +147,10 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
         }
         fprintf(out, "\n};\n\n");
     }
-#else
-    else
+    else if (source_encoding == SourceEncoding_U32)
     {
         // As integers
+        fprintf(out, "// Exported using binary_to_compressed_c.exe -u32 \"%s\" %s\n", filename, symbol);
         fprintf(out, "%sconst unsigned int %s_%ssize = %d;\n", static_str, symbol, compressed_str, (int)compressed_sz);
         fprintf(out, "%sconst unsigned int %s_%sdata[%d/4] =\n{", static_str, symbol, compressed_str, (int)((compressed_sz + 3) / 4)*4);
         int column = 0;
@@ -148,7 +164,6 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
         }
         fprintf(out, "\n};\n\n");
     }
-#endif
 
     // Cleanup
     delete[] data;

From 20360e00ceb26b67a4569521b762fbd89d9db61c Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 20 Nov 2024 21:46:47 +0100
Subject: [PATCH 271/548] Merge miscellaneous small changes to reduce drift
 with texture update branch.

- ImGuiDebugLogFlags_EventFont is yet unused.
---
 backends/imgui_impl_opengl3.cpp  |  3 +-
 imgui.cpp                        | 28 +++++-----
 imgui.h                          | 19 ++++---
 imgui_draw.cpp                   | 90 ++++++++++++++++++--------------
 imgui_internal.h                 | 25 ++++-----
 misc/freetype/imgui_freetype.cpp |  1 +
 6 files changed, 95 insertions(+), 71 deletions(-)

diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp
index c03156a7e174..57c699421d19 100644
--- a/backends/imgui_impl_opengl3.cpp
+++ b/backends/imgui_impl_opengl3.cpp
@@ -164,6 +164,7 @@
 // In the rest of your app/engine, you can use another loader of your choice (gl3w, glew, glad, glbinding, glext, glLoadGen, etc.).
 // If you happen to be developing a new feature for this backend (imgui_impl_opengl3.cpp):
 // - You may need to regenerate imgui_impl_opengl3_loader.h to add new symbols. See https://github.com/dearimgui/gl3w_stripped
+//   Typically you would run: python3 ./gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt
 // - You can temporarily use an unstripped version. See https://github.com/dearimgui/gl3w_stripped/releases
 // Changes to this backend using new APIs should be accompanied by a regenerated stripped loader version.
 #define IMGL3W_IMPL
@@ -689,7 +690,7 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture()
 #endif
     GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
 
-    // Store our identifier
+    // Store identifier
     io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
 
     // Restore state
diff --git a/imgui.cpp b/imgui.cpp
index 3512ec87dda9..a8c86cc57bcb 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4010,7 +4010,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     StackSizesInBeginForCurrentWindow = NULL;
 
     DebugDrawIdConflictsCount = 0;
-    DebugLogFlags = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_OutputToTTY;
+    DebugLogFlags = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_OutputToTTY | ImGuiDebugLogFlags_EventFont;
     DebugLocateId = 0;
     DebugLogSkippedErrors = 0;
     DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
@@ -4226,8 +4226,8 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NUL
     FontWindowScale = 1.0f;
     SettingsOffset = -1;
     DrawList = &DrawListInst;
-    DrawList->_Data = &Ctx->DrawListSharedData;
     DrawList->_OwnerName = Name;
+    DrawList->_Data = &Ctx->DrawListSharedData;
     NavPreferredScoringPosRel[0] = NavPreferredScoringPosRel[1] = ImVec2(FLT_MAX, FLT_MAX);
 }
 
@@ -5025,7 +5025,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
     io.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false;
 }
 
-// Calling SetupDrawListSharedData() is followed by SetCurrentFont() which sets up the remaining data.
+// Called once a frame. Followed by SetCurrentFont() which sets up the remaining data.
 static void SetupDrawListSharedData()
 {
     ImGuiContext& g = *GImGui;
@@ -15180,6 +15180,17 @@ void ImGui::UpdateDebugToolFlashStyleColor()
         DebugFlashStyleColorStop();
 }
 
+static const char* FormatTextureIDForDebugDisplay(char* buf, int buf_size, ImTextureID tex_id)
+{
+    union { void* ptr; int integer; } tex_id_opaque;
+    memcpy(&tex_id_opaque, &tex_id, ImMin(sizeof(void*), sizeof(tex_id)));
+    if (sizeof(tex_id) >= sizeof(void*))
+        ImFormatString(buf, buf_size, "0x%p", tex_id_opaque.ptr);
+    else
+        ImFormatString(buf, buf_size, "0x%04X", tex_id_opaque.integer);
+    return buf;
+}
+
 // Avoid naming collision with imgui_demo.cpp's HelpMarker() for unity builds.
 static void MetricsHelpMarker(const char* desc)
 {
@@ -15868,16 +15879,6 @@ void ImGui::DebugNodeColumns(ImGuiOldColumns* columns)
     TreePop();
 }
 
-static void FormatTextureIDForDebugDisplay(char* buf, int buf_size, ImTextureID tex_id)
-{
-    union { void* ptr; int integer; } tex_id_opaque;
-    memcpy(&tex_id_opaque, &tex_id, ImMin(sizeof(void*), sizeof(tex_id)));
-    if (sizeof(tex_id) >= sizeof(void*))
-        ImFormatString(buf, buf_size, "0x%p", tex_id_opaque.ptr);
-    else
-        ImFormatString(buf, buf_size, "0x%04X", tex_id_opaque.integer);
-}
-
 // [DEBUG] Display contents of ImDrawList
 void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label)
 {
@@ -16379,6 +16380,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
     ShowDebugLogFlag("Clipper", ImGuiDebugLogFlags_EventClipper);
     ShowDebugLogFlag("Focus", ImGuiDebugLogFlags_EventFocus);
     ShowDebugLogFlag("IO", ImGuiDebugLogFlags_EventIO);
+    //ShowDebugLogFlag("Font", ImGuiDebugLogFlags_EventFont);
     ShowDebugLogFlag("Nav", ImGuiDebugLogFlags_EventNav);
     ShowDebugLogFlag("Popup", ImGuiDebugLogFlags_EventPopup);
     ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection);
diff --git a/imgui.h b/imgui.h
index 815b079242bf..12dc7d0082e7 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2309,6 +2309,7 @@ struct ImGuiIO
     // (the imgui_impl_xxxx backend files are setting those up for you)
     //------------------------------------------------------------------
 
+    // Nowadays those would be stored in ImGuiPlatformIO but we are leaving them here for legacy reasons.
     // Optional: Platform/Renderer backend name (informational only! will be displayed in About Window) + User data for backend/wrappers to store their own stuff.
     const char* BackendPlatformName;            // = NULL
     const char* BackendRendererName;            // = NULL
@@ -3064,10 +3065,11 @@ struct ImDrawList
     float                   _FringeScale;       // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content
     const char*             _OwnerName;         // Pointer to owner window's name for debugging
 
-    // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui)
-    ImDrawList(ImDrawListSharedData* shared_data) { memset(this, 0, sizeof(*this)); _Data = shared_data; }
-
-    ~ImDrawList() { _ClearFreeMemory(); }
+    // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData().
+    // (advanced: you may create and use your own ImDrawListSharedData so you can use ImDrawList without ImGui, but that's more involved)
+    IMGUI_API ImDrawList(ImDrawListSharedData* shared_data);
+    IMGUI_API ~ImDrawList();
+    
     IMGUI_API void  PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect = false);  // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
     IMGUI_API void  PushClipRectFullScreen();
     IMGUI_API void  PopClipRect();
@@ -3277,14 +3279,16 @@ struct ImFontGlyphRangesBuilder
 // See ImFontAtlas::AddCustomRectXXX functions.
 struct ImFontAtlasCustomRect
 {
-    unsigned short  Width, Height;  // Input    // Desired rectangle dimension
     unsigned short  X, Y;           // Output   // Packed position in Atlas
+
+    // [Internal]
+    unsigned short  Width, Height;  // Input    // Desired rectangle dimension
     unsigned int    GlyphID : 31;   // Input    // For custom font glyphs only (ID < 0x110000)
     unsigned int    GlyphColored : 1; // Input  // For custom font glyphs only: glyph is colored, removed tinting.
     float           GlyphAdvanceX;  // Input    // For custom font glyphs only: glyph xadvance
     ImVec2          GlyphOffset;    // Input    // For custom font glyphs only: glyph display offset
     ImFont*         Font;           // Input    // For custom font glyphs only: target font
-    ImFontAtlasCustomRect()         { Width = Height = 0; X = Y = 0xFFFF; GlyphID = 0; GlyphColored = 0; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0, 0); Font = NULL; }
+    ImFontAtlasCustomRect()         { X = Y = 0xFFFF; Width = Height = 0; GlyphID = 0; GlyphColored = 0; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0, 0); Font = NULL; }
     bool IsPacked() const           { return X != 0xFFFF; }
 };
 
@@ -3431,8 +3435,9 @@ struct ImFont
     const ImFontGlyph*          FallbackGlyph;      // 4-8   // out // = FindGlyph(FontFallbackChar)
 
     // Members: Cold ~32/40 bytes
+    // Conceptually ConfigData[] is the list of font sources merged to create this font.
     ImFontAtlas*                ContainerAtlas;     // 4-8   // out //            // What we has been loaded into
-    const ImFontConfig*         ConfigData;         // 4-8   // in  //            // Pointer within ContainerAtlas->ConfigData
+    const ImFontConfig*         ConfigData;         // 4-8   // in  //            // Pointer within ContainerAtlas->ConfigData to ConfigDataCount instances
     short                       ConfigDataCount;    // 2     // in  // ~ 1        // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont.
     ImWchar                     FallbackChar;       // 2     // out // = FFFD/'?' // Character used if a glyph isn't found.
     ImWchar                     EllipsisChar;       // 2     // out // = '...'/'.'// Character used for ellipsis rendering.
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 5647f53fde72..fd1feb0a84a5 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -14,7 +14,7 @@ Index of this file:
 // [SECTION] Helpers ShadeVertsXXX functions
 // [SECTION] ImFontConfig
 // [SECTION] ImFontAtlas
-// [SECTION] ImFontAtlas glyph ranges helpers
+// [SECTION] ImFontAtlas: glyph ranges helpers
 // [SECTION] ImFontGlyphRangesBuilder
 // [SECTION] ImFont
 // [SECTION] ImGui Internal Render Helpers
@@ -394,6 +394,17 @@ void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
     ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
 }
 
+ImDrawList::ImDrawList(ImDrawListSharedData* shared_data)
+{
+    memset(this, 0, sizeof(*this)); 
+    _Data = shared_data;
+}
+
+ImDrawList::~ImDrawList()
+{
+    _ClearFreeMemory();
+}
+
 // Initialize before use in a new frame. We always have a command ready in the buffer.
 // In the majority of cases, you would want to call PushClipRect() and PushTextureID() after this.
 void ImDrawList::_ResetForNewFrame()
@@ -2528,6 +2539,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
     IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0);
     IM_ASSERT(font_cfg->SizePixels > 0.0f && "Is ImFontConfig struct correctly initialized?");
     IM_ASSERT(font_cfg->OversampleH > 0 && font_cfg->OversampleV > 0 && "Is ImFontConfig struct correctly initialized?");
+    IM_ASSERT(font_cfg->RasterizerDensity > 0.0f);
 
     // Create new font
     if (!font_cfg->MergeMode)
@@ -2546,9 +2558,16 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
         memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize);
     }
 
+    // Round font size
+    // - We started rounding in 1.90 WIP (18991) as our layout system currently doesn't support non-rounded font size well yet.
+    // - Note that using io.FontGlobalScale or SetWindowFontScale(), with are legacy-ish, partially supported features, can still lead to unrounded sizes.
+    // - We may support it better later and remove this rounding.
+    new_font_cfg.SizePixels = ImTrunc(new_font_cfg.SizePixels);
+
     if (new_font_cfg.DstFont->EllipsisChar == (ImWchar)-1)
         new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar;
 
+    // Pointers to ConfigData and BuilderData are otherwise dangling
     ImFontAtlasUpdateConfigDataPointers(this);
 
     // Invalidate texture
@@ -3163,35 +3182,35 @@ static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)
     IM_ASSERT(r->IsPacked());
 
     const int w = atlas->TexWidth;
-    if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
+    if (atlas->Flags & ImFontAtlasFlags_NoMouseCursors)
     {
-        // Render/copy pixels
-        IM_ASSERT(r->Width == FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1 && r->Height == FONT_ATLAS_DEFAULT_TEX_DATA_H);
-        const int x_for_white = r->X;
-        const int x_for_black = r->X + FONT_ATLAS_DEFAULT_TEX_DATA_W + 1;
+        // White pixels only
+        IM_ASSERT(r->Width == 2 && r->Height == 2);
+        const int offset = (int)r->X + (int)r->Y * w;
         if (atlas->TexPixelsAlpha8 != NULL)
         {
-            ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', 0xFF);
-            ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', 0xFF);
+            atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF;
         }
         else
         {
-            ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', IM_COL32_WHITE);
-            ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', IM_COL32_WHITE);
+            atlas->TexPixelsRGBA32[offset] = atlas->TexPixelsRGBA32[offset + 1] = atlas->TexPixelsRGBA32[offset + w] = atlas->TexPixelsRGBA32[offset + w + 1] = IM_COL32_WHITE;
         }
     }
     else
     {
-        // Render 4 white pixels
-        IM_ASSERT(r->Width == 2 && r->Height == 2);
-        const int offset = (int)r->X + (int)r->Y * w;
+        // White pixels and mouse cursor
+        IM_ASSERT(r->Width == FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1 && r->Height == FONT_ATLAS_DEFAULT_TEX_DATA_H);
+        const int x_for_white = r->X;
+        const int x_for_black = r->X + FONT_ATLAS_DEFAULT_TEX_DATA_W + 1;
         if (atlas->TexPixelsAlpha8 != NULL)
         {
-            atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF;
+            ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', 0xFF);
+            ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', 0xFF);
         }
         else
         {
-            atlas->TexPixelsRGBA32[offset] = atlas->TexPixelsRGBA32[offset + 1] = atlas->TexPixelsRGBA32[offset + w] = atlas->TexPixelsRGBA32[offset + w + 1] = IM_COL32_WHITE;
+            ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', IM_COL32_WHITE);
+            ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', IM_COL32_WHITE);
         }
     }
     atlas->TexUvWhitePixel = ImVec2((r->X + 0.5f) * atlas->TexUvScale.x, (r->Y + 0.5f) * atlas->TexUvScale.y);
@@ -3205,38 +3224,38 @@ static void ImFontAtlasBuildRenderLinesTexData(ImFontAtlas* atlas)
     // This generates a triangular shape in the texture, with the various line widths stacked on top of each other to allow interpolation between them
     ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdLines);
     IM_ASSERT(r->IsPacked());
-    for (unsigned int n = 0; n < IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1; n++) // +1 because of the zero-width row
+    for (int n = 0; n < IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1; n++) // +1 because of the zero-width row
     {
         // Each line consists of at least two empty pixels at the ends, with a line of solid pixels in the middle
-        unsigned int y = n;
-        unsigned int line_width = n;
-        unsigned int pad_left = (r->Width - line_width) / 2;
-        unsigned int pad_right = r->Width - (pad_left + line_width);
+        int y = n;
+        int line_width = n;
+        int pad_left = (r->Width - line_width) / 2;
+        int pad_right = r->Width - (pad_left + line_width);
 
         // Write each slice
         IM_ASSERT(pad_left + line_width + pad_right == r->Width && y < r->Height); // Make sure we're inside the texture bounds before we start writing pixels
         if (atlas->TexPixelsAlpha8 != NULL)
         {
             unsigned char* write_ptr = &atlas->TexPixelsAlpha8[r->X + ((r->Y + y) * atlas->TexWidth)];
-            for (unsigned int i = 0; i < pad_left; i++)
+            for (int i = 0; i < pad_left; i++)
                 *(write_ptr + i) = 0x00;
 
-            for (unsigned int i = 0; i < line_width; i++)
+            for (int i = 0; i < line_width; i++)
                 *(write_ptr + pad_left + i) = 0xFF;
 
-            for (unsigned int i = 0; i < pad_right; i++)
+            for (int i = 0; i < pad_right; i++)
                 *(write_ptr + pad_left + line_width + i) = 0x00;
         }
         else
         {
             unsigned int* write_ptr = &atlas->TexPixelsRGBA32[r->X + ((r->Y + y) * atlas->TexWidth)];
-            for (unsigned int i = 0; i < pad_left; i++)
+            for (int i = 0; i < pad_left; i++)
                 *(write_ptr + i) = IM_COL32(255, 255, 255, 0);
 
-            for (unsigned int i = 0; i < line_width; i++)
+            for (int i = 0; i < line_width; i++)
                 *(write_ptr + pad_left + i) = IM_COL32_WHITE;
 
-            for (unsigned int i = 0; i < pad_right; i++)
+            for (int i = 0; i < pad_right; i++)
                 *(write_ptr + pad_left + line_width + i) = IM_COL32(255, 255, 255, 0);
         }
 
@@ -3251,13 +3270,6 @@ static void ImFontAtlasBuildRenderLinesTexData(ImFontAtlas* atlas)
 // Note: this is called / shared by both the stb_truetype and the FreeType builder
 void ImFontAtlasBuildInit(ImFontAtlas* atlas)
 {
-    // Round font size
-    // - We started rounding in 1.90 WIP (18991) as our layout system currently doesn't support non-rounded font size well yet.
-    // - Note that using io.FontGlobalScale or SetWindowFontScale(), with are legacy-ish, partially supported features, can still lead to unrounded sizes.
-    // - We may support it better later and remove this rounding.
-    for (ImFontConfig& cfg : atlas->ConfigData)
-       cfg.SizePixels = ImTrunc(cfg.SizePixels);
-
     // Register texture region for mouse cursors or standard white pixels
     if (atlas->PackIdMouseCursors < 0)
     {
@@ -3308,6 +3320,10 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
     atlas->TexReady = true;
 }
 
+//-------------------------------------------------------------------------
+// [SECTION] ImFontAtlas: glyph ranges helpers
+//-------------------------------------------------------------------------
+
 // Retrieve list of range (2 int per range, values are inclusive)
 const ImWchar*   ImFontAtlas::GetGlyphRangesDefault()
 {
@@ -3369,10 +3385,6 @@ static void UnpackAccumulativeOffsetsIntoRanges(int base_codepoint, const short*
     out_ranges[0] = 0;
 }
 
-//-------------------------------------------------------------------------
-// [SECTION] ImFontAtlas glyph ranges helpers
-//-------------------------------------------------------------------------
-
 const ImWchar*  ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon()
 {
     // Store 2500 regularly used characters for Simplified Chinese.
@@ -3799,8 +3811,9 @@ void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, floa
         advance_x += cfg->GlyphExtraSpacing.x;
     }
 
+    int glyph_idx = Glyphs.Size;
     Glyphs.resize(Glyphs.Size + 1);
-    ImFontGlyph& glyph = Glyphs.back();
+    ImFontGlyph& glyph = Glyphs[glyph_idx];
     glyph.Codepoint = (unsigned int)codepoint;
     glyph.Visible = (x0 != x1) && (y0 != y1);
     glyph.Colored = false;
@@ -3836,6 +3849,7 @@ void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst)
     IndexAdvanceX[dst] = (src < index_size) ? IndexAdvanceX.Data[src] : 1.0f;
 }
 
+// Find glyph, return fallback if missing
 const ImFontGlyph* ImFont::FindGlyph(ImWchar c)
 {
     if (c >= (size_t)IndexLookup.Size)
diff --git a/imgui_internal.h b/imgui_internal.h
index 2af196cb789e..40cf3c0c37ae 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -212,11 +212,6 @@ extern IMGUI_API ImGuiContext* GImGui;  // Current implicit context pointer
 #endif
 
 // Debug Logging for ShowDebugLogWindow(). This is designed for relatively rare events so please don't spam.
-#ifndef IMGUI_DISABLE_DEBUG_TOOLS
-#define IMGUI_DEBUG_LOG(...)            ImGui::DebugLog(__VA_ARGS__)
-#else
-#define IMGUI_DEBUG_LOG(...)            ((void)0)
-#endif
 #define IMGUI_DEBUG_LOG_ERROR(...)      do { ImGuiContext& g2 = *GImGui; if (g2.DebugLogFlags & ImGuiDebugLogFlags_EventError) IMGUI_DEBUG_LOG(__VA_ARGS__); else g2.DebugLogSkippedErrors++; } while (0)
 #define IMGUI_DEBUG_LOG_ACTIVEID(...)   do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId)    IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
 #define IMGUI_DEBUG_LOG_FOCUS(...)      do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus)       IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
@@ -225,6 +220,7 @@ extern IMGUI_API ImGuiContext* GImGui;  // Current implicit context pointer
 #define IMGUI_DEBUG_LOG_SELECTION(...)  do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)   IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
 #define IMGUI_DEBUG_LOG_CLIPPER(...)    do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper)     IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
 #define IMGUI_DEBUG_LOG_IO(...)         do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO)          IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
+#define IMGUI_DEBUG_LOG_FONT(...)       do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFont)        IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
 #define IMGUI_DEBUG_LOG_INPUTROUTING(...) do{if (g.DebugLogFlags & ImGuiDebugLogFlags_EventInputRouting)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
 
 // Static Asserts
@@ -760,10 +756,13 @@ IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStorag
 #define IM_DRAWLIST_ARCFAST_SAMPLE_MAX                          IM_DRAWLIST_ARCFAST_TABLE_SIZE // Sample index _PathArcToFastEx() for 360 angle.
 
 // Data shared between all ImDrawList instances
-// You may want to create your own instance of this if you want to use ImDrawList completely without ImGui. In that case, watch out for future changes to this structure.
+// Conceptually this could have been called e.g. ImDrawListSharedContext
+// Typically one ImGui context would create and maintain one of this.
+// You may want to create your own instance of you try to ImDrawList completely without ImGui. In that case, watch out for future changes to this structure.
 struct IMGUI_API ImDrawListSharedData
 {
     ImVec2          TexUvWhitePixel;            // UV of white pixel in the atlas
+    const ImVec4*   TexUvLines;                 // UV of anti-aliased lines in the atlas
     ImFont*         Font;                       // Current/default font (optional, for simplified AddText overload)
     float           FontSize;                   // Current/default font size (optional, for simplified AddText overload)
     float           FontScale;                  // Current/default font scale (== FontSize / Font->FontSize)
@@ -779,7 +778,6 @@ struct IMGUI_API ImDrawListSharedData
     ImVec2          ArcFastVtx[IM_DRAWLIST_ARCFAST_TABLE_SIZE]; // Sample points on the quarter of the circle.
     float           ArcFastRadiusCutoff;                        // Cutoff radius after which arc drawing will fallback to slower PathArcTo()
     ImU8            CircleSegmentCounts[64];    // Precomputed segment count for given radius before we calculate it dynamically (to avoid calculation overhead)
-    const ImVec4*   TexUvLines;                 // UV of anti-aliased lines in the atlas
 
     ImDrawListSharedData();
     void SetCircleTessellationMaxError(float max_error);
@@ -1919,6 +1917,7 @@ typedef void (*ImGuiErrorCallback)(ImGuiContext* ctx, void* user_data, const cha
 // [SECTION] Metrics, Debug Tools
 //-----------------------------------------------------------------------------
 
+// See IMGUI_DEBUG_LOG() and IMGUI_DEBUG_LOG_XXX() macros.
 enum ImGuiDebugLogFlags_
 {
     // Event types
@@ -1931,11 +1930,12 @@ enum ImGuiDebugLogFlags_
     ImGuiDebugLogFlags_EventClipper         = 1 << 5,
     ImGuiDebugLogFlags_EventSelection       = 1 << 6,
     ImGuiDebugLogFlags_EventIO              = 1 << 7,
-    ImGuiDebugLogFlags_EventInputRouting    = 1 << 8,
-    ImGuiDebugLogFlags_EventDocking         = 1 << 9,   // Unused in this branch
-    ImGuiDebugLogFlags_EventViewport        = 1 << 10,  // Unused in this branch
+    ImGuiDebugLogFlags_EventFont            = 1 << 8,
+    ImGuiDebugLogFlags_EventInputRouting    = 1 << 9,
+    ImGuiDebugLogFlags_EventDocking         = 1 << 10,  // Unused in this branch
+    ImGuiDebugLogFlags_EventViewport        = 1 << 11,  // Unused in this branch
 
-    ImGuiDebugLogFlags_EventMask_           = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventInputRouting | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport,
+    ImGuiDebugLogFlags_EventMask_           = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventFont | ImGuiDebugLogFlags_EventInputRouting | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport,
     ImGuiDebugLogFlags_OutputToTTY          = 1 << 20,  // Also send output to TTY
     ImGuiDebugLogFlags_OutputToTestEngine   = 1 << 21,  // Also send output to Test Engine
 };
@@ -3524,7 +3524,8 @@ namespace ImGui
 // [SECTION] ImFontAtlas internal API
 //-----------------------------------------------------------------------------
 
-// This structure is likely to evolve as we add support for incremental atlas updates
+// This structure is likely to evolve as we add support for incremental atlas updates.
+// Conceptually this could be in ImGuiPlatformIO, but we are far from ready to make this public.
 struct ImFontBuilderIO
 {
     bool    (*FontBuilder_Build)(ImFontAtlas* atlas);
diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp
index c2d5f074c0fa..e68a2af40bbd 100644
--- a/misc/freetype/imgui_freetype.cpp
+++ b/misc/freetype/imgui_freetype.cpp
@@ -169,6 +169,7 @@ namespace
         const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint);
         const FT_Bitmap*        RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info);
         void                    BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = nullptr);
+        FreeTypeFont()          { memset(this, 0, sizeof(*this)); }
         ~FreeTypeFont()         { CloseFont(); }
 
         // [Internals]

From dfbf1b4f6b1a12b3854c58ef7cc160c998a66537 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 20 Nov 2024 22:19:34 +0100
Subject: [PATCH 272/548] Backends: DX9: cache result of
 ImGui_ImplDX9_CheckFormatSupport() as we are going to need it more often.

---
 backends/imgui_impl_dx9.cpp | 47 ++++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp
index f1b069df11fe..4d1527b5a137 100644
--- a/backends/imgui_impl_dx9.cpp
+++ b/backends/imgui_impl_dx9.cpp
@@ -52,6 +52,7 @@ struct ImGui_ImplDX9_Data
     LPDIRECT3DTEXTURE9          FontTexture;
     int                         VertexBufferSize;
     int                         IndexBufferSize;
+    bool                        HasRgbaSupport;
 
     ImGui_ImplDX9_Data()        { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
 };
@@ -291,6 +292,24 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
     state_block->Release();
 }
 
+static bool ImGui_ImplDX9_CheckFormatSupport(LPDIRECT3DDEVICE9 pDevice, D3DFORMAT format)
+{
+    LPDIRECT3D9 pd3d = nullptr;
+    if (pDevice->GetDirect3D(&pd3d) != D3D_OK)
+        return false;
+    D3DDEVICE_CREATION_PARAMETERS param = {};
+    D3DDISPLAYMODE mode = {};
+    if (pDevice->GetCreationParameters(¶m) != D3D_OK || pDevice->GetDisplayMode(0, &mode) != D3D_OK)
+    {
+        pd3d->Release();
+        return false;
+    }
+    // Font texture should support linear filter, color blend and write to render-target
+    bool support = (pd3d->CheckDeviceFormat(param.AdapterOrdinal, param.DeviceType, mode.Format, D3DUSAGE_DYNAMIC | D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, format)) == D3D_OK;
+    pd3d->Release();
+    return support;
+}
+
 bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
 {
     ImGuiIO& io = ImGui::GetIO();
@@ -305,6 +324,7 @@ bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
 
     bd->pd3dDevice = device;
     bd->pd3dDevice->AddRef();
+    bd->HasRgbaSupport = ImGui_ImplDX9_CheckFormatSupport(bd->pd3dDevice, D3DFMT_A8B8G8R8);
 
     return true;
 }
@@ -323,24 +343,6 @@ void ImGui_ImplDX9_Shutdown()
     IM_DELETE(bd);
 }
 
-static bool ImGui_ImplDX9_CheckFormatSupport(IDirect3DDevice9* pDevice, D3DFORMAT format)
-{
-    IDirect3D9* pd3d = nullptr;
-    if (pDevice->GetDirect3D(&pd3d) != D3D_OK)
-        return false;
-    D3DDEVICE_CREATION_PARAMETERS param = {};
-    D3DDISPLAYMODE mode = {};
-    if (pDevice->GetCreationParameters(¶m) != D3D_OK || pDevice->GetDisplayMode(0, &mode) != D3D_OK)
-    {
-        pd3d->Release();
-        return false;
-    }
-    // Font texture should support linear filter, color blend and write to render-target
-    bool support = (pd3d->CheckDeviceFormat(param.AdapterOrdinal, param.DeviceType, mode.Format, D3DUSAGE_DYNAMIC | D3DUSAGE_QUERY_FILTER | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, format)) == D3D_OK;
-    pd3d->Release();
-    return support;
-}
-
 static bool ImGui_ImplDX9_CreateFontsTexture()
 {
     // Build texture atlas
@@ -352,21 +354,18 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
 
     // Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
 #ifndef IMGUI_USE_BGRA_PACKED_COLOR
-    const bool rgba_support = ImGui_ImplDX9_CheckFormatSupport(bd->pd3dDevice, D3DFMT_A8B8G8R8);
-    if (!rgba_support && io.Fonts->TexPixelsUseColors)
+    if (!bd->HasRgbaSupport && io.Fonts->TexPixelsUseColors)
     {
         ImU32* dst_start = (ImU32*)ImGui::MemAlloc((size_t)width * height * bytes_per_pixel);
         for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + (size_t)width * height; dst < dst_end; src++, dst++)
             *dst = IMGUI_COL_TO_DX9_ARGB(*src);
         pixels = (unsigned char*)dst_start;
     }
-#else
-    const bool rgba_support = false;
 #endif
 
     // Upload texture to graphics system
     bd->FontTexture = nullptr;
-    if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, rgba_support ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0)
+    if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, bd->HasRgbaSupport ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0)
         return false;
     D3DLOCKED_RECT tex_locked_rect;
     if (bd->FontTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK)
@@ -379,7 +378,7 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
     io.Fonts->SetTexID((ImTextureID)bd->FontTexture);
 
 #ifndef IMGUI_USE_BGRA_PACKED_COLOR
-    if (!rgba_support && io.Fonts->TexPixelsUseColors)
+    if (!bd->HasRgbaSupport && io.Fonts->TexPixelsUseColors)
         ImGui::MemFree(pixels);
 #endif
 

From 5b7feebfd8f3e58392d955b4c8ae01f77eae25ed Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 21 Nov 2024 16:57:51 +0100
Subject: [PATCH 273/548] Backends: DX9: extract RGBA convert loop as we are
 going to need it more often.

---
 backends/imgui_impl_dx9.cpp | 42 ++++++++++++++++++++-----------------
 1 file changed, 23 insertions(+), 19 deletions(-)

diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp
index 4d1527b5a137..c97d3c740ef9 100644
--- a/backends/imgui_impl_dx9.cpp
+++ b/backends/imgui_impl_dx9.cpp
@@ -343,6 +343,28 @@ void ImGui_ImplDX9_Shutdown()
     IM_DELETE(bd);
 }
 
+// Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
+static void ImGui_ImplDX9_CopyTextureRegion(bool tex_use_colors, ImU32* src, int src_pitch, ImU32* dst, int dst_pitch, int w, int h)
+{
+#ifndef IMGUI_USE_BGRA_PACKED_COLOR
+    ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
+    const bool convert_rgba_to_bgra = (!bd->HasRgbaSupport && tex_use_colors);
+#else
+    const bool convert_rgba_to_bgra = false;
+    IM_UNUSED(tex_use_colors);
+#endif
+    for (int y = 0; y < h; y++)
+    {
+        ImU32* src_p = (ImU32*)((unsigned char*)src + src_pitch * y);
+        ImU32* dst_p = (ImU32*)((unsigned char*)dst + dst_pitch * y);
+        if (convert_rgba_to_bgra)
+            for (int x = w; x > 0; x--, src_p++, dst_p++) // Convert copy
+                *dst_p = IMGUI_COL_TO_DX9_ARGB(*src_p);
+        else
+            memcpy(dst_p, src_p, w * 4); // Raw copy
+    }
+}
+
 static bool ImGui_ImplDX9_CreateFontsTexture()
 {
     // Build texture atlas
@@ -352,17 +374,6 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
     int width, height, bytes_per_pixel;
     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
 
-    // Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
-#ifndef IMGUI_USE_BGRA_PACKED_COLOR
-    if (!bd->HasRgbaSupport && io.Fonts->TexPixelsUseColors)
-    {
-        ImU32* dst_start = (ImU32*)ImGui::MemAlloc((size_t)width * height * bytes_per_pixel);
-        for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + (size_t)width * height; dst < dst_end; src++, dst++)
-            *dst = IMGUI_COL_TO_DX9_ARGB(*src);
-        pixels = (unsigned char*)dst_start;
-    }
-#endif
-
     // Upload texture to graphics system
     bd->FontTexture = nullptr;
     if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, bd->HasRgbaSupport ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0)
@@ -370,18 +381,11 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
     D3DLOCKED_RECT tex_locked_rect;
     if (bd->FontTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK)
         return false;
-    for (int y = 0; y < height; y++)
-        memcpy((unsigned char*)tex_locked_rect.pBits + (size_t)tex_locked_rect.Pitch * y, pixels + (size_t)width * bytes_per_pixel * y, (size_t)width * bytes_per_pixel);
+    ImGui_ImplDX9_CopyTextureRegion(io.Fonts->TexPixelsUseColors, (ImU32*)pixels, width * bytes_per_pixel, (ImU32*)tex_locked_rect.pBits, (int)tex_locked_rect.Pitch, width, height);
     bd->FontTexture->UnlockRect(0);
 
     // Store our identifier
     io.Fonts->SetTexID((ImTextureID)bd->FontTexture);
-
-#ifndef IMGUI_USE_BGRA_PACKED_COLOR
-    if (!bd->HasRgbaSupport && io.Fonts->TexPixelsUseColors)
-        ImGui::MemFree(pixels);
-#endif
-
     return true;
 }
 

From 9b273294377dfe0e054614489f90632bfb7af0e3 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 25 Nov 2024 18:59:56 +0100
Subject: [PATCH 274/548] Comments on ImageButton(). (#8165) + comments on
 Emscripten -sSINGLE_FILE option. (#8153)

---
 examples/example_glfw_opengl3/Makefile.emscripten | 3 +++
 examples/example_glfw_wgpu/Makefile.emscripten    | 3 +++
 examples/example_sdl2_opengl3/Makefile.emscripten | 3 +++
 examples/example_sdl3_opengl3/Makefile.emscripten | 3 +++
 imgui.h                                           | 3 ++-
 imgui_widgets.cpp                                 | 5 ++---
 6 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/examples/example_glfw_opengl3/Makefile.emscripten b/examples/example_glfw_opengl3/Makefile.emscripten
index bd972abffc85..bba4ac9dc579 100644
--- a/examples/example_glfw_opengl3/Makefile.emscripten
+++ b/examples/example_glfw_opengl3/Makefile.emscripten
@@ -35,6 +35,9 @@ EMS =
 EMS += -s DISABLE_EXCEPTION_CATCHING=1
 LDFLAGS += -s USE_GLFW=3 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
 
+# Build as single file (binary text encoded in .html file)
+#LDFLAGS += -sSINGLE_FILE
+
 # Uncomment next line to fix possible rendering bugs with Emscripten version older then 1.39.0 (https://github.com/ocornut/imgui/issues/2877)
 #EMS += -s BINARYEN_TRAP_MODE=clamp
 #EMS += -s SAFE_HEAP=1    ## Adds overhead
diff --git a/examples/example_glfw_wgpu/Makefile.emscripten b/examples/example_glfw_wgpu/Makefile.emscripten
index 5c79f0c77dbb..78d64b4d3179 100644
--- a/examples/example_glfw_wgpu/Makefile.emscripten
+++ b/examples/example_glfw_wgpu/Makefile.emscripten
@@ -36,6 +36,9 @@ EMS += -s DISABLE_EXCEPTION_CATCHING=1
 LDFLAGS += -s USE_GLFW=3 -s USE_WEBGPU=1
 LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
 
+# Build as single file (binary text encoded in .html file)
+#LDFLAGS += -sSINGLE_FILE
+
 # Emscripten allows preloading a file or folder to be accessible at runtime.
 # The Makefile for this example project suggests embedding the misc/fonts/ folder into our application, it will then be accessible as "/fonts"
 # See documentation for more details: https://emscripten.org/docs/porting/files/packaging_files.html
diff --git a/examples/example_sdl2_opengl3/Makefile.emscripten b/examples/example_sdl2_opengl3/Makefile.emscripten
index da0348435d03..bc06adeb74b6 100644
--- a/examples/example_sdl2_opengl3/Makefile.emscripten
+++ b/examples/example_sdl2_opengl3/Makefile.emscripten
@@ -36,6 +36,9 @@ EMS += -s USE_SDL=2
 EMS += -s DISABLE_EXCEPTION_CATCHING=1
 LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
 
+# Build as single file (binary text encoded in .html file)
+#LDFLAGS += -sSINGLE_FILE
+
 # Uncomment next line to fix possible rendering bugs with Emscripten version older then 1.39.0 (https://github.com/ocornut/imgui/issues/2877)
 #EMS += -s BINARYEN_TRAP_MODE=clamp
 #EMS += -s SAFE_HEAP=1    ## Adds overhead
diff --git a/examples/example_sdl3_opengl3/Makefile.emscripten b/examples/example_sdl3_opengl3/Makefile.emscripten
index 9e9ffd6034f7..57247ff21265 100644
--- a/examples/example_sdl3_opengl3/Makefile.emscripten
+++ b/examples/example_sdl3_opengl3/Makefile.emscripten
@@ -40,6 +40,9 @@ EMS += -s USE_SDL=2
 EMS += -s DISABLE_EXCEPTION_CATCHING=1
 LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
 
+# Build as single file (binary text encoded in .html file)
+#LDFLAGS += -sSINGLE_FILE
+
 # Uncomment next line to fix possible rendering bugs with Emscripten version older then 1.39.0 (https://github.com/ocornut/imgui/issues/2877)
 #EMS += -s BINARYEN_TRAP_MODE=clamp
 #EMS += -s SAFE_HEAP=1    ## Adds overhead
diff --git a/imgui.h b/imgui.h
index 12dc7d0082e7..35a903889246 100644
--- a/imgui.h
+++ b/imgui.h
@@ -564,6 +564,7 @@ namespace ImGui
     // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
     // - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
     // - Note that Image() may add +2.0f to provided size if a border is visible, ImageButton() adds style.FramePadding*2.0f to provided size.
+    // - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified.
     IMGUI_API void          Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0));
     IMGUI_API bool          ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1));
 
@@ -3069,7 +3070,7 @@ struct ImDrawList
     // (advanced: you may create and use your own ImDrawListSharedData so you can use ImDrawList without ImGui, but that's more involved)
     IMGUI_API ImDrawList(ImDrawListSharedData* shared_data);
     IMGUI_API ~ImDrawList();
-    
+
     IMGUI_API void  PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect = false);  // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
     IMGUI_API void  PushClipRectFullScreen();
     IMGUI_API void  PopClipRect();
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index c60378f82140..81b480cb174b 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1073,8 +1073,6 @@ void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const I
     window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
 }
 
-// ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390)
-// We provide this internal helper to write your own variant while we figure out how to redesign the public ImageButton() API.
 bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
 {
     ImGuiContext& g = *GImGui;
@@ -1102,7 +1100,8 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& imag
     return pressed;
 }
 
-// Note that ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button.
+// - ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button.
+// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. (#8165) // FIXME: Maybe that's not the best design?
 bool ImGui::ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
 {
     ImGuiContext& g = *GImGui;

From 61ab94d5534b0809079c136fd1301227e91f6003 Mon Sep 17 00:00:00 2001
From: Arseny Kapoulkine 
Date: Fri, 22 Nov 2024 07:40:30 +0900
Subject: [PATCH 275/548] Backends: Vulkan: Make descriptor pool optional
 (#8172, #4867)

Comments/amends by ocornut
---
 backends/imgui_impl_vulkan.cpp | 31 +++++++++++++++++++++++++++----
 backends/imgui_impl_vulkan.h   | 16 ++++++++++++----
 docs/CHANGELOG.txt             |  3 +++
 3 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index d499ecb92350..1d2d8a19d66a 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -26,6 +26,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-11-27: Vulkan: Make user-provided descriptor pool optional. As a convenience, when setting init_info->DescriptorPoolSize the backend will create one itself. (#8172, #4867)
 //  2024-10-07: Vulkan: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
 //  2024-10-07: Vulkan: Compiling with '#define ImTextureID=ImU64' is unnecessary now that dear imgui defaults ImTextureID to u64 instead of void*.
@@ -131,6 +132,7 @@ static bool g_FunctionsLoaded = true;
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdSetViewport) \
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateBuffer) \
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateCommandPool) \
+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateDescriptorPool) \
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateDescriptorSetLayout) \
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateFence) \
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateFramebuffer) \
@@ -221,6 +223,7 @@ struct ImGui_ImplVulkan_Data
     VkPipeline                  Pipeline;
     VkShaderModule              ShaderModuleVert;
     VkShaderModule              ShaderModuleFrag;
+    VkDescriptorPool            DescriptorPool;
 
     // Font data
     VkSampler                   FontSampler;
@@ -1010,6 +1013,20 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
         check_vk_result(err);
     }
 
+    if (v->DescriptorPoolSize)
+    {
+        VkDescriptorPoolSize pool_size = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, v->DescriptorPoolSize };
+        VkDescriptorPoolCreateInfo pool_info = {};
+        pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+        pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
+        pool_info.maxSets = v->DescriptorPoolSize;
+        pool_info.poolSizeCount = 1;
+        pool_info.pPoolSizes = &pool_size;
+
+        err = vkCreateDescriptorPool(v->Device, &pool_info, v->Allocator, &bd->DescriptorPool);
+        check_vk_result(err);
+    }
+
     if (!bd->PipelineLayout)
     {
         // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
@@ -1048,6 +1065,7 @@ void    ImGui_ImplVulkan_DestroyDeviceObjects()
     if (bd->DescriptorSetLayout)  { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
     if (bd->PipelineLayout)       { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }
     if (bd->Pipeline)             { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; }
+    if (bd->DescriptorPool)       { vkDestroyDescriptorPool(v->Device, bd->DescriptorPool, v->Allocator); bd->DescriptorPool = VK_NULL_HANDLE; }
 }
 
 bool    ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
@@ -1110,7 +1128,10 @@ bool    ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
     IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE);
     IM_ASSERT(info->Device != VK_NULL_HANDLE);
     IM_ASSERT(info->Queue != VK_NULL_HANDLE);
-    IM_ASSERT(info->DescriptorPool != VK_NULL_HANDLE);
+    if (info->DescriptorPool != VK_NULL_HANDLE) // Either DescriptorPool or DescriptorPoolSize must be set, not both!
+        IM_ASSERT(info->DescriptorPoolSize == 0);
+    else
+        IM_ASSERT(info->DescriptorPoolSize > 0);
     IM_ASSERT(info->MinImageCount >= 2);
     IM_ASSERT(info->ImageCount >= info->MinImageCount);
     if (info->UseDynamicRendering == false)
@@ -1159,19 +1180,20 @@ void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
     bd->VulkanInitInfo.MinImageCount = min_image_count;
 }
 
-// Register a texture
+// Register a texture by creating a descriptor
 // FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem, please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
 VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout)
 {
     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+    VkDescriptorPool pool = bd->DescriptorPool ? bd->DescriptorPool : v->DescriptorPool;
 
     // Create Descriptor Set:
     VkDescriptorSet descriptor_set;
     {
         VkDescriptorSetAllocateInfo alloc_info = {};
         alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
-        alloc_info.descriptorPool = v->DescriptorPool;
+        alloc_info.descriptorPool = pool;
         alloc_info.descriptorSetCount = 1;
         alloc_info.pSetLayouts = &bd->DescriptorSetLayout;
         VkResult err = vkAllocateDescriptorSets(v->Device, &alloc_info, &descriptor_set);
@@ -1199,7 +1221,8 @@ void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set)
 {
     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
-    vkFreeDescriptorSets(v->Device, v->DescriptorPool, 1, &descriptor_set);
+    VkDescriptorPool pool = bd->DescriptorPool ? bd->DescriptorPool : v->DescriptorPool;
+    vkFreeDescriptorSets(v->Device, pool, 1, &descriptor_set);
 }
 
 void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkan_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h
index ca5b4db64100..8d9e19f9a7ee 100644
--- a/backends/imgui_impl_vulkan.h
+++ b/backends/imgui_impl_vulkan.h
@@ -62,10 +62,15 @@
 #endif
 
 // Initialization data, for ImGui_ImplVulkan_Init()
-// - VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
-//   and must contain a pool size large enough to hold an ImGui VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor.
-// - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure.
 // [Please zero-clear before use!]
+// - About descriptor pool:
+//   - A VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
+//     and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors.
+//   - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you.
+//   - Current version of the backend use 1 descriptor for the font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture().
+//   - It is expected that as early as Q1 2025 the backend will use a few more descriptors, so aim at 10 + number of desierd calls to ImGui_ImplVulkan_AddTexture().
+// - About dynamic rendering:
+//   - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure.
 struct ImGui_ImplVulkan_InitInfo
 {
     VkInstance                      Instance;
@@ -73,7 +78,7 @@ struct ImGui_ImplVulkan_InitInfo
     VkDevice                        Device;
     uint32_t                        QueueFamily;
     VkQueue                         Queue;
-    VkDescriptorPool                DescriptorPool;               // See requirements in note above
+    VkDescriptorPool                DescriptorPool;               // See requirements in note above; ignored if using DescriptorPoolSize > 0
     VkRenderPass                    RenderPass;                   // Ignored if using dynamic rendering
     uint32_t                        MinImageCount;                // >= 2
     uint32_t                        ImageCount;                   // >= MinImageCount
@@ -83,6 +88,9 @@ struct ImGui_ImplVulkan_InitInfo
     VkPipelineCache                 PipelineCache;
     uint32_t                        Subpass;
 
+    // (Optional) Set to create internal descriptor pool instead of using DescriptorPool
+    uint32_t                        DescriptorPoolSize;
+
     // (Optional) Dynamic Rendering
     // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3.
     bool                            UseDynamicRendering;
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 5a49416e20c9..642adfc31ef3 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -59,6 +59,9 @@ Other changes:
 - Tools: binary_to_compressed_c: added -u8/-u32/-base85 export options.
 - Demo: example tree used by Property Editor & Selection demos properly freed
   on application closure. (#8158) [@Legulysse]
+- Backends: Vulkan: Make user-provided descriptor pool optional. As a convenience,
+  when setting init_info->DescriptorPoolSize then the backend will create and manage
+  one itself. (#8172, #4867) [@zeux]
 - Examples: Win32+DX12: Using a basic free-list allocator to manage multiple
   SRV descriptors.
 

From e6dd8f626a189d984a078d9e2f6d4d36a7af91cb Mon Sep 17 00:00:00 2001
From: Teselka <53512153+Teselka@users.noreply.github.com>
Date: Fri, 22 Nov 2024 13:33:25 +0200
Subject: [PATCH 276/548] Misc: changed CRC32 table to use crc32c polynomial in
 order to be compatible with SSE 4.2 instructions. (#8169, #4933)

---
 docs/CHANGELOG.txt |  3 +++
 imgui.cpp          | 34 ++++++++++++++++++----------------
 imgui.h            |  2 +-
 3 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 642adfc31ef3..e901e437eb69 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -48,6 +48,9 @@ Breaking changes:
   - We provide convenience legacy fields to pass a single descriptor,
     matching the old API, but upcoming features will want multiple.
   - Legacy ImGui_ImplDX12_Init() signature is still supported (will obsolete).
+- Misc: changed CRC32 table to use CRC32c polynomial in order to be compatible
+  with the result of SSE 4.2 instructions. As a result, old .ini data may be
+  partially lost. (#8169, #4933) [@Teselka]
 
 Other changes:
 
diff --git a/imgui.cpp b/imgui.cpp
index a8c86cc57bcb..072c09799635 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -429,6 +429,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.
 
+ - 2024/11/27 (1.91.6) - changed CRC32 table to use CRC32c polynomial in order to be compatible with the result of SSE 4.2 instructions. As a result, old .ini data may be partially lost.
  - 2024/11/06 (1.91.5) - commented/obsoleted out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before)
                             - io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022).
                             - io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022).
@@ -2152,24 +2153,25 @@ void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end,
 // CRC32 needs a 1KB lookup table (not cache friendly)
 // Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily:
 // - avoid an unnecessary branch/memory tap, - keep the ImHashXXX functions usable by static constructors, - make it thread-safe.
+// On 2024/11/27 this was changed from crc32-adler to crc32c (polynomial 0x1EDC6F41), which invalidated some hashes stored in .ini files.
 static const ImU32 GCrc32LookupTable[256] =
 {
-    0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
-    0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
-    0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
-    0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
-    0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
-    0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
-    0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
-    0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
-    0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
-    0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
-    0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
-    0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
-    0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
-    0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
-    0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
-    0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
+    0x00000000,0xF26B8303,0xE13B70F7,0x1350F3F4,0xC79A971F,0x35F1141C,0x26A1E7E8,0xD4CA64EB,0x8AD958CF,0x78B2DBCC,0x6BE22838,0x9989AB3B,0x4D43CFD0,0xBF284CD3,0xAC78BF27,0x5E133C24,
+    0x105EC76F,0xE235446C,0xF165B798,0x030E349B,0xD7C45070,0x25AFD373,0x36FF2087,0xC494A384,0x9A879FA0,0x68EC1CA3,0x7BBCEF57,0x89D76C54,0x5D1D08BF,0xAF768BBC,0xBC267848,0x4E4DFB4B,
+    0x20BD8EDE,0xD2D60DDD,0xC186FE29,0x33ED7D2A,0xE72719C1,0x154C9AC2,0x061C6936,0xF477EA35,0xAA64D611,0x580F5512,0x4B5FA6E6,0xB93425E5,0x6DFE410E,0x9F95C20D,0x8CC531F9,0x7EAEB2FA,
+    0x30E349B1,0xC288CAB2,0xD1D83946,0x23B3BA45,0xF779DEAE,0x05125DAD,0x1642AE59,0xE4292D5A,0xBA3A117E,0x4851927D,0x5B016189,0xA96AE28A,0x7DA08661,0x8FCB0562,0x9C9BF696,0x6EF07595,
+    0x417B1DBC,0xB3109EBF,0xA0406D4B,0x522BEE48,0x86E18AA3,0x748A09A0,0x67DAFA54,0x95B17957,0xCBA24573,0x39C9C670,0x2A993584,0xD8F2B687,0x0C38D26C,0xFE53516F,0xED03A29B,0x1F682198,
+    0x5125DAD3,0xA34E59D0,0xB01EAA24,0x42752927,0x96BF4DCC,0x64D4CECF,0x77843D3B,0x85EFBE38,0xDBFC821C,0x2997011F,0x3AC7F2EB,0xC8AC71E8,0x1C661503,0xEE0D9600,0xFD5D65F4,0x0F36E6F7,
+    0x61C69362,0x93AD1061,0x80FDE395,0x72966096,0xA65C047D,0x5437877E,0x4767748A,0xB50CF789,0xEB1FCBAD,0x197448AE,0x0A24BB5A,0xF84F3859,0x2C855CB2,0xDEEEDFB1,0xCDBE2C45,0x3FD5AF46,
+    0x7198540D,0x83F3D70E,0x90A324FA,0x62C8A7F9,0xB602C312,0x44694011,0x5739B3E5,0xA55230E6,0xFB410CC2,0x092A8FC1,0x1A7A7C35,0xE811FF36,0x3CDB9BDD,0xCEB018DE,0xDDE0EB2A,0x2F8B6829,
+    0x82F63B78,0x709DB87B,0x63CD4B8F,0x91A6C88C,0x456CAC67,0xB7072F64,0xA457DC90,0x563C5F93,0x082F63B7,0xFA44E0B4,0xE9141340,0x1B7F9043,0xCFB5F4A8,0x3DDE77AB,0x2E8E845F,0xDCE5075C,
+    0x92A8FC17,0x60C37F14,0x73938CE0,0x81F80FE3,0x55326B08,0xA759E80B,0xB4091BFF,0x466298FC,0x1871A4D8,0xEA1A27DB,0xF94AD42F,0x0B21572C,0xDFEB33C7,0x2D80B0C4,0x3ED04330,0xCCBBC033,
+    0xA24BB5A6,0x502036A5,0x4370C551,0xB11B4652,0x65D122B9,0x97BAA1BA,0x84EA524E,0x7681D14D,0x2892ED69,0xDAF96E6A,0xC9A99D9E,0x3BC21E9D,0xEF087A76,0x1D63F975,0x0E330A81,0xFC588982,
+    0xB21572C9,0x407EF1CA,0x532E023E,0xA145813D,0x758FE5D6,0x87E466D5,0x94B49521,0x66DF1622,0x38CC2A06,0xCAA7A905,0xD9F75AF1,0x2B9CD9F2,0xFF56BD19,0x0D3D3E1A,0x1E6DCDEE,0xEC064EED,
+    0xC38D26C4,0x31E6A5C7,0x22B65633,0xD0DDD530,0x0417B1DB,0xF67C32D8,0xE52CC12C,0x1747422F,0x49547E0B,0xBB3FFD08,0xA86F0EFC,0x5A048DFF,0x8ECEE914,0x7CA56A17,0x6FF599E3,0x9D9E1AE0,
+    0xD3D3E1AB,0x21B862A8,0x32E8915C,0xC083125F,0x144976B4,0xE622F5B7,0xF5720643,0x07198540,0x590AB964,0xAB613A67,0xB831C993,0x4A5A4A90,0x9E902E7B,0x6CFBAD78,0x7FAB5E8C,0x8DC0DD8F,
+    0xE330A81A,0x115B2B19,0x020BD8ED,0xF0605BEE,0x24AA3F05,0xD6C1BC06,0xC5914FF2,0x37FACCF1,0x69E9F0D5,0x9B8273D6,0x88D28022,0x7AB90321,0xAE7367CA,0x5C18E4C9,0x4F48173D,0xBD23943E,
+    0xF36E6F75,0x0105EC76,0x12551F82,0xE03E9C81,0x34F4F86A,0xC69F7B69,0xD5CF889D,0x27A40B9E,0x79B737BA,0x8BDCB4B9,0x988C474D,0x6AE7C44E,0xBE2DA0A5,0x4C4623A6,0x5F16D052,0xAD7D5351
 };
 
 // Known size hash
diff --git a/imgui.h b/imgui.h
index 35a903889246..30115e810b30 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.6 WIP"
-#define IMGUI_VERSION_NUM   19151
+#define IMGUI_VERSION_NUM   19152
 #define IMGUI_HAS_TABLE
 
 /*

From 326dc95f9c7ab7adf6ee63f4221b64b4002b6bed Mon Sep 17 00:00:00 2001
From: Teselka <53512153+Teselka@users.noreply.github.com>
Date: Wed, 20 Nov 2024 13:10:36 +0200
Subject: [PATCH 277/548] Misc: use native crc32 instructions on SEE 4.2
 targets. (#8169, #4933)

---
 docs/CHANGELOG.txt |  1 +
 imgui.cpp          | 18 ++++++++++++++++++
 imgui_internal.h   |  4 ++++
 3 files changed, 23 insertions(+)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index e901e437eb69..b93888c85f63 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -62,6 +62,7 @@ Other changes:
 - Tools: binary_to_compressed_c: added -u8/-u32/-base85 export options.
 - Demo: example tree used by Property Editor & Selection demos properly freed
   on application closure. (#8158) [@Legulysse]
+- Misc: use SSE 4.2 crc32 instructions when available. (#8169, #4933) [@Teselka]
 - Backends: Vulkan: Make user-provided descriptor pool optional. As a convenience,
   when setting init_info->DescriptorPoolSize then the backend will create and manage
   one itself. (#8172, #4867) [@zeux]
diff --git a/imgui.cpp b/imgui.cpp
index 072c09799635..ff5d25408cc7 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -2150,6 +2150,7 @@ void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end,
     }
 }
 
+#ifndef IMGUI_ENABLE_SSE4_2
 // CRC32 needs a 1KB lookup table (not cache friendly)
 // Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily:
 // - avoid an unnecessary branch/memory tap, - keep the ImHashXXX functions usable by static constructors, - make it thread-safe.
@@ -2173,6 +2174,7 @@ static const ImU32 GCrc32LookupTable[256] =
     0xE330A81A,0x115B2B19,0x020BD8ED,0xF0605BEE,0x24AA3F05,0xD6C1BC06,0xC5914FF2,0x37FACCF1,0x69E9F0D5,0x9B8273D6,0x88D28022,0x7AB90321,0xAE7367CA,0x5C18E4C9,0x4F48173D,0xBD23943E,
     0xF36E6F75,0x0105EC76,0x12551F82,0xE03E9C81,0x34F4F86A,0xC69F7B69,0xD5CF889D,0x27A40B9E,0x79B737BA,0x8BDCB4B9,0x988C474D,0x6AE7C44E,0xBE2DA0A5,0x4C4623A6,0x5F16D052,0xAD7D5351
 };
+#endif
 
 // Known size hash
 // It is ok to call ImHashData on a string with known length but the ### operator won't be supported.
@@ -2181,10 +2183,16 @@ ImGuiID ImHashData(const void* data_p, size_t data_size, ImGuiID seed)
 {
     ImU32 crc = ~seed;
     const unsigned char* data = (const unsigned char*)data_p;
+#ifndef IMGUI_ENABLE_SSE4_2
     const ImU32* crc32_lut = GCrc32LookupTable;
     while (data_size-- != 0)
         crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
     return ~crc;
+#else
+    while (data_size-- != 0)
+        crc = _mm_crc32_u8(crc, *data++);
+    return ~crc;
+#endif
 }
 
 // Zero-terminated string hash, with support for ### to reset back to seed value
@@ -2198,7 +2206,9 @@ ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed)
     seed = ~seed;
     ImU32 crc = seed;
     const unsigned char* data = (const unsigned char*)data_p;
+#ifndef IMGUI_ENABLE_SSE4_2
     const ImU32* crc32_lut = GCrc32LookupTable;
+#endif
     if (data_size != 0)
     {
         while (data_size-- != 0)
@@ -2206,7 +2216,11 @@ ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed)
             unsigned char c = *data++;
             if (c == '#' && data_size >= 2 && data[0] == '#' && data[1] == '#')
                 crc = seed;
+#ifndef IMGUI_ENABLE_SSE4_2
             crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
+#else
+            crc = _mm_crc32_u8(crc, c);
+#endif
         }
     }
     else
@@ -2215,7 +2229,11 @@ ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed)
         {
             if (c == '#' && data[0] == '#' && data[1] == '#')
                 crc = seed;
+#ifndef IMGUI_ENABLE_SSE4_2
             crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
+#else
+            crc = _mm_crc32_u8(crc, c);
+#endif
         }
     }
     return ~crc;
diff --git a/imgui_internal.h b/imgui_internal.h
index 40cf3c0c37ae..fd8a185a597d 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -61,6 +61,10 @@ Index of this file:
 #if (defined __SSE__ || defined __x86_64__ || defined _M_X64 || (defined(_M_IX86_FP) && (_M_IX86_FP >= 1))) && !defined(IMGUI_DISABLE_SSE)
 #define IMGUI_ENABLE_SSE
 #include 
+#if (defined __AVX__ || defined __SSE4_2__)
+#define IMGUI_ENABLE_SSE4_2
+#include 
+#endif
 #endif
 
 // Visual Studio warnings

From 2d660108b27a5c03ea8bd8bbd70a0aa3054b995a Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 27 Nov 2024 12:34:16 +0100
Subject: [PATCH 278/548] Misc: amend crc32 to use _mm_crc32_u32. (#8169,
 #4933)

---
 imgui.cpp | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index ff5d25408cc7..5f6c859007c5 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -2183,13 +2183,19 @@ ImGuiID ImHashData(const void* data_p, size_t data_size, ImGuiID seed)
 {
     ImU32 crc = ~seed;
     const unsigned char* data = (const unsigned char*)data_p;
+    const unsigned char *data_end = (const unsigned char*)data_p + data_size;
 #ifndef IMGUI_ENABLE_SSE4_2
     const ImU32* crc32_lut = GCrc32LookupTable;
-    while (data_size-- != 0)
+    while (data < data_end)
         crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
     return ~crc;
 #else
-    while (data_size-- != 0)
+    while (data + 4 <= data_end)
+    {
+        crc = _mm_crc32_u32(crc, *(ImU32*)data);
+        data += 4;
+    }
+    while (data < data_end)
         crc = _mm_crc32_u8(crc, *data++);
     return ~crc;
 #endif

From 96877eb9c30192d8d99b632a66418c037b92913e Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 27 Nov 2024 12:38:12 +0100
Subject: [PATCH 279/548] Backends: Vulkan: fixed build with VK_NO_PROTOTYPES.
 (#8172, #4867)

Amend 61ab94d
---
 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 1d2d8a19d66a..8a61a81ba9d2 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -147,6 +147,7 @@ static bool g_FunctionsLoaded = true;
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSwapchainKHR) \
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyBuffer) \
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyCommandPool) \
+    IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyDescriptorPool) \
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyDescriptorSetLayout) \
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyFence) \
     IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyFramebuffer) \

From 90dd510df1e2fa85c490ddc97e2ea059c46e9fd3 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 11 Oct 2024 17:45:28 +0200
Subject: [PATCH 280/548] Backends: DX11: create sampler outside of
 ImGui_ImplDX11_CreateFontsTexture().

---
 backends/imgui_impl_dx11.cpp | 40 +++++++++++++++++++++++-------------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp
index b928bb86fbc0..4316a9f1069b 100644
--- a/backends/imgui_impl_dx11.cpp
+++ b/backends/imgui_impl_dx11.cpp
@@ -364,21 +364,16 @@ static void ImGui_ImplDX11_CreateFontsTexture()
 
     // Store our identifier
     io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
+}
 
-    // Create texture sampler
-    // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
+static void ImGui_ImplDX11_DestroyFontsTexture()
+{
+    ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+    if (bd->pFontTextureView)
     {
-        D3D11_SAMPLER_DESC desc;
-        ZeroMemory(&desc, sizeof(desc));
-        desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
-        desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
-        desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
-        desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
-        desc.MipLODBias = 0.f;
-        desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
-        desc.MinLOD = 0.f;
-        desc.MaxLOD = 0.f;
-        bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
+        bd->pFontTextureView->Release();
+        bd->pFontTextureView = nullptr;
+        ImGui::GetIO().Fonts->SetTexID(0); // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
     }
 }
 
@@ -531,6 +526,22 @@ bool    ImGui_ImplDX11_CreateDeviceObjects()
         bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
     }
 
+    // Create texture sampler
+    // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
+    {
+        D3D11_SAMPLER_DESC desc;
+        ZeroMemory(&desc, sizeof(desc));
+        desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+        desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+        desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+        desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+        desc.MipLODBias = 0.f;
+        desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
+        desc.MinLOD = 0.f;
+        desc.MaxLOD = 0.f;
+        bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
+    }
+
     ImGui_ImplDX11_CreateFontsTexture();
 
     return true;
@@ -542,8 +553,9 @@ void    ImGui_ImplDX11_InvalidateDeviceObjects()
     if (!bd->pd3dDevice)
         return;
 
+    ImGui_ImplDX11_DestroyFontsTexture();
+
     if (bd->pFontSampler)           { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
-    if (bd->pFontTextureView)       { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
     if (bd->pIB)                    { bd->pIB->Release(); bd->pIB = nullptr; }
     if (bd->pVB)                    { bd->pVB->Release(); bd->pVB = nullptr; }
     if (bd->pBlendState)            { bd->pBlendState->Release(); bd->pBlendState = nullptr; }

From c1123fd8d0519942c4347708af999d876e7b7728 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 27 Nov 2024 14:17:32 +0100
Subject: [PATCH 281/548] Backends: Vulkan: small refactor to use a texture
 struct.

---
 backends/imgui_impl_vulkan.cpp | 101 ++++++++++++++++++---------------
 1 file changed, 55 insertions(+), 46 deletions(-)

diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index 8a61a81ba9d2..2d966408986e 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -213,6 +213,16 @@ struct ImGui_ImplVulkan_WindowRenderBuffers
     ImGui_ImplVulkan_FrameRenderBuffers* FrameRenderBuffers;
 };
 
+struct ImGui_ImplVulkan_Texture
+{
+    VkDeviceMemory              Memory;
+    VkImage                     Image;
+    VkImageView                 ImageView;
+    VkDescriptorSet             DescriptorSet;
+
+    ImGui_ImplVulkan_Texture() { memset(this, 0, sizeof(*this)); }
+};
+
 // Vulkan data
 struct ImGui_ImplVulkan_Data
 {
@@ -226,14 +236,11 @@ struct ImGui_ImplVulkan_Data
     VkShaderModule              ShaderModuleFrag;
     VkDescriptorPool            DescriptorPool;
 
-    // Font data
-    VkSampler                   FontSampler;
-    VkDeviceMemory              FontMemory;
-    VkImage                     FontImage;
-    VkImageView                 FontView;
-    VkDescriptorSet             FontDescriptorSet;
-    VkCommandPool               FontCommandPool;
-    VkCommandBuffer             FontCommandBuffer;
+    // Texture management
+    ImGui_ImplVulkan_Texture    FontTexture;
+    VkSampler                   TexSampler;
+    VkCommandPool               TexCommandPool;
+    VkCommandBuffer             TexCommandBuffer;
 
     // Render buffers for main window
     ImGui_ImplVulkan_WindowRenderBuffers MainWindowRenderBuffers;
@@ -598,8 +605,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
                 if (sizeof(ImTextureID) < sizeof(ImU64))
                 {
                     // We don't support texture switches if ImTextureID hasn't been redefined to be 64-bit. Do a flaky check that other textures haven't been used.
-                    IM_ASSERT(pcmd->GetTexID() == (ImTextureID)bd->FontDescriptorSet);
-                    desc_set[0] = bd->FontDescriptorSet;
+                    IM_ASSERT(pcmd->GetTexID() == (ImTextureID)bd->FontTexture.DescriptorSet);
+                    desc_set[0] = bd->FontTexture.DescriptorSet;
                 }
                 vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, nullptr);
 
@@ -631,39 +638,39 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
     VkResult err;
 
     // Destroy existing texture (if any)
-    if (bd->FontView || bd->FontImage || bd->FontMemory || bd->FontDescriptorSet)
+    if (bd->FontTexture.DescriptorSet)
     {
         vkQueueWaitIdle(v->Queue);
         ImGui_ImplVulkan_DestroyFontsTexture();
     }
 
     // Create command pool/buffer
-    if (bd->FontCommandPool == VK_NULL_HANDLE)
+    if (bd->TexCommandPool == VK_NULL_HANDLE)
     {
         VkCommandPoolCreateInfo info = {};
         info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
         info.flags = 0;
         info.queueFamilyIndex = v->QueueFamily;
-        vkCreateCommandPool(v->Device, &info, v->Allocator, &bd->FontCommandPool);
+        vkCreateCommandPool(v->Device, &info, v->Allocator, &bd->TexCommandPool);
     }
-    if (bd->FontCommandBuffer == VK_NULL_HANDLE)
+    if (bd->TexCommandBuffer == VK_NULL_HANDLE)
     {
         VkCommandBufferAllocateInfo info = {};
         info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
-        info.commandPool = bd->FontCommandPool;
+        info.commandPool = bd->TexCommandPool;
         info.commandBufferCount = 1;
-        err = vkAllocateCommandBuffers(v->Device, &info, &bd->FontCommandBuffer);
+        err = vkAllocateCommandBuffers(v->Device, &info, &bd->TexCommandBuffer);
         check_vk_result(err);
     }
 
     // Start command buffer
     {
-        err = vkResetCommandPool(v->Device, bd->FontCommandPool, 0);
+        err = vkResetCommandPool(v->Device, bd->TexCommandPool, 0);
         check_vk_result(err);
         VkCommandBufferBeginInfo begin_info = {};
         begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
         begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
-        err = vkBeginCommandBuffer(bd->FontCommandBuffer, &begin_info);
+        err = vkBeginCommandBuffer(bd->TexCommandBuffer, &begin_info);
         check_vk_result(err);
     }
 
@@ -673,6 +680,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
     size_t upload_size = width * height * 4 * sizeof(char);
 
     // Create the Image:
+    ImGui_ImplVulkan_Texture* backend_tex = &bd->FontTexture;
     {
         VkImageCreateInfo info = {};
         info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@@ -688,17 +696,17 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
         info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
         info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
         info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-        err = vkCreateImage(v->Device, &info, v->Allocator, &bd->FontImage);
+        err = vkCreateImage(v->Device, &info, v->Allocator, &backend_tex->Image);
         check_vk_result(err);
         VkMemoryRequirements req;
-        vkGetImageMemoryRequirements(v->Device, bd->FontImage, &req);
+        vkGetImageMemoryRequirements(v->Device, backend_tex->Image, &req);
         VkMemoryAllocateInfo alloc_info = {};
         alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
         alloc_info.allocationSize = IM_MAX(v->MinAllocationSize, req.size);
         alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);
-        err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->FontMemory);
+        err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &backend_tex->Memory);
         check_vk_result(err);
-        err = vkBindImageMemory(v->Device, bd->FontImage, bd->FontMemory, 0);
+        err = vkBindImageMemory(v->Device, backend_tex->Image, backend_tex->Memory, 0);
         check_vk_result(err);
     }
 
@@ -706,18 +714,18 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
     {
         VkImageViewCreateInfo info = {};
         info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
-        info.image = bd->FontImage;
+        info.image = backend_tex->Image;
         info.viewType = VK_IMAGE_VIEW_TYPE_2D;
         info.format = VK_FORMAT_R8G8B8A8_UNORM;
         info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
         info.subresourceRange.levelCount = 1;
         info.subresourceRange.layerCount = 1;
-        err = vkCreateImageView(v->Device, &info, v->Allocator, &bd->FontView);
+        err = vkCreateImageView(v->Device, &info, v->Allocator, &backend_tex->ImageView);
         check_vk_result(err);
     }
 
     // Create the Descriptor Set:
-    bd->FontDescriptorSet = (VkDescriptorSet)ImGui_ImplVulkan_AddTexture(bd->FontSampler, bd->FontView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+    backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSampler, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
 
     // Create the Upload Buffer:
     VkDeviceMemory upload_buffer_memory;
@@ -767,11 +775,11 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
         copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
         copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
         copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-        copy_barrier[0].image = bd->FontImage;
+        copy_barrier[0].image = backend_tex->Image;
         copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
         copy_barrier[0].subresourceRange.levelCount = 1;
         copy_barrier[0].subresourceRange.layerCount = 1;
-        vkCmdPipelineBarrier(bd->FontCommandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, copy_barrier);
+        vkCmdPipelineBarrier(bd->TexCommandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, copy_barrier);
 
         VkBufferImageCopy region = {};
         region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@@ -779,7 +787,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
         region.imageExtent.width = width;
         region.imageExtent.height = height;
         region.imageExtent.depth = 1;
-        vkCmdCopyBufferToImage(bd->FontCommandBuffer, upload_buffer, bd->FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
+        vkCmdCopyBufferToImage(bd->TexCommandBuffer, upload_buffer, backend_tex->Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
 
         VkImageMemoryBarrier use_barrier[1] = {};
         use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -789,22 +797,22 @@ bool ImGui_ImplVulkan_CreateFontsTexture()
         use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
         use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
         use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-        use_barrier[0].image = bd->FontImage;
+        use_barrier[0].image = backend_tex->Image;
         use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
         use_barrier[0].subresourceRange.levelCount = 1;
         use_barrier[0].subresourceRange.layerCount = 1;
-        vkCmdPipelineBarrier(bd->FontCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, use_barrier);
+        vkCmdPipelineBarrier(bd->TexCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, use_barrier);
     }
 
     // Store our identifier
-    io.Fonts->SetTexID((ImTextureID)bd->FontDescriptorSet);
+    io.Fonts->SetTexID((ImTextureID)backend_tex->DescriptorSet);
 
     // End command buffer
     VkSubmitInfo end_info = {};
     end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
     end_info.commandBufferCount = 1;
-    end_info.pCommandBuffers = &bd->FontCommandBuffer;
-    err = vkEndCommandBuffer(bd->FontCommandBuffer);
+    end_info.pCommandBuffers = &bd->TexCommandBuffer;
+    err = vkEndCommandBuffer(bd->TexCommandBuffer);
     check_vk_result(err);
     err = vkQueueSubmit(v->Queue, 1, &end_info, VK_NULL_HANDLE);
     check_vk_result(err);
@@ -825,16 +833,17 @@ void ImGui_ImplVulkan_DestroyFontsTexture()
     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
 
-    if (bd->FontDescriptorSet)
+    ImGui_ImplVulkan_Texture* backend_tex = &bd->FontTexture;
+
+    if (backend_tex->DescriptorSet)
     {
-        ImGui_ImplVulkan_RemoveTexture(bd->FontDescriptorSet);
-        bd->FontDescriptorSet = VK_NULL_HANDLE;
+        ImGui_ImplVulkan_RemoveTexture(backend_tex->DescriptorSet);
+        backend_tex->DescriptorSet = VK_NULL_HANDLE;
         io.Fonts->SetTexID(0);
     }
-
-    if (bd->FontView)   { vkDestroyImageView(v->Device, bd->FontView, v->Allocator); bd->FontView = VK_NULL_HANDLE; }
-    if (bd->FontImage)  { vkDestroyImage(v->Device, bd->FontImage, v->Allocator); bd->FontImage = VK_NULL_HANDLE; }
-    if (bd->FontMemory) { vkFreeMemory(v->Device, bd->FontMemory, v->Allocator); bd->FontMemory = VK_NULL_HANDLE; }
+    if (backend_tex->ImageView) { vkDestroyImageView(v->Device, backend_tex->ImageView, v->Allocator); backend_tex->ImageView = VK_NULL_HANDLE; }
+    if (backend_tex->Image)     { vkDestroyImage(v->Device, backend_tex->Image, v->Allocator); backend_tex->Image = VK_NULL_HANDLE; }
+    if (backend_tex->Memory)    { vkFreeMemory(v->Device, backend_tex->Memory, v->Allocator); backend_tex->Memory = VK_NULL_HANDLE; }
 }
 
 static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator)
@@ -982,7 +991,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
     VkResult err;
 
-    if (!bd->FontSampler)
+    if (!bd->TexSampler)
     {
         // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
         VkSamplerCreateInfo info = {};
@@ -996,7 +1005,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
         info.minLod = -1000;
         info.maxLod = 1000;
         info.maxAnisotropy = 1.0f;
-        err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->FontSampler);
+        err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->TexSampler);
         check_vk_result(err);
     }
 
@@ -1058,11 +1067,11 @@ void    ImGui_ImplVulkan_DestroyDeviceObjects()
     ImGui_ImplVulkan_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->TexCommandBuffer)     { vkFreeCommandBuffers(v->Device, bd->TexCommandPool, 1, &bd->TexCommandBuffer); bd->TexCommandBuffer = VK_NULL_HANDLE; }
+    if (bd->TexCommandPool)       { vkDestroyCommandPool(v->Device, bd->TexCommandPool, v->Allocator); bd->TexCommandPool = VK_NULL_HANDLE; }
+    if (bd->TexSampler)           { vkDestroySampler(v->Device, bd->TexSampler, v->Allocator); bd->TexSampler = 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; }
-    if (bd->FontSampler)          { vkDestroySampler(v->Device, bd->FontSampler, v->Allocator); bd->FontSampler = VK_NULL_HANDLE; }
     if (bd->DescriptorSetLayout)  { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
     if (bd->PipelineLayout)       { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }
     if (bd->Pipeline)             { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; }
@@ -1163,7 +1172,7 @@ void ImGui_ImplVulkan_NewFrame()
     ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
     IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplVulkan_Init()?");
 
-    if (!bd->FontDescriptorSet)
+    if (!bd->FontTexture.DescriptorSet)
         ImGui_ImplVulkan_CreateFontsTexture();
 }
 

From dda7672008e4f447a4a179d30cf5745fd5a18fb0 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 28 Nov 2024 19:23:01 +0100
Subject: [PATCH 282/548] Backends: Vulkan: removed sizeof(ImTextureID) check.

(not necessary anymore and it happens to when with a later coming change of ImTextureID, so best removed earlier).
---
 backends/imgui_impl_vulkan.cpp | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index 2d966408986e..69f4937629cb 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -601,14 +601,8 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
                 vkCmdSetScissor(command_buffer, 0, 1, &scissor);
 
                 // Bind DescriptorSet with font or user texture
-                VkDescriptorSet desc_set[1] = { (VkDescriptorSet)pcmd->GetTexID() };
-                if (sizeof(ImTextureID) < sizeof(ImU64))
-                {
-                    // We don't support texture switches if ImTextureID hasn't been redefined to be 64-bit. Do a flaky check that other textures haven't been used.
-                    IM_ASSERT(pcmd->GetTexID() == (ImTextureID)bd->FontTexture.DescriptorSet);
-                    desc_set[0] = bd->FontTexture.DescriptorSet;
-                }
-                vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, nullptr);
+                VkDescriptorSet desc_set = (VkDescriptorSet)pcmd->GetTexID();
+                vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, &desc_set, 0, nullptr);
 
                 // Draw
                 vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);

From 9b26743c6b30d647662c3ef315d9968fde4c1033 Mon Sep 17 00:00:00 2001
From: Diego Mateos 
Date: Fri, 29 Nov 2024 13:31:11 +0100
Subject: [PATCH 283/548] SliderAngle: only write back to value v_rad on
 value_changed. (#8193)

---
 imgui_widgets.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 81b480cb174b..f9939cec430f 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3329,7 +3329,8 @@ bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, fl
         format = "%.0f deg";
     float v_deg = (*v_rad) * 360.0f / (2 * IM_PI);
     bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, format, flags);
-    *v_rad = v_deg * (2 * IM_PI) / 360.0f;
+    if (value_changed)
+        *v_rad = v_deg * (2 * IM_PI) / 360.0f;
     return value_changed;
 }
 

From 19a1f2a5d2cb1366d7c702e905e6aa5ed4b1ab12 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 29 Nov 2024 18:46:17 +0100
Subject: [PATCH 284/548] Fonts: fixed AddCustomRect() not being packed with
 TexGlyphPadding + not accounted in surface area. (#8107)

---
 docs/CHANGELOG.txt               |  2 ++
 imgui.h                          |  6 +++---
 imgui_draw.cpp                   | 18 +++++++++++-------
 misc/freetype/imgui_freetype.cpp |  4 +++-
 4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index b93888c85f63..6650debf0238 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -62,6 +62,8 @@ Other changes:
 - Tools: binary_to_compressed_c: added -u8/-u32/-base85 export options.
 - Demo: example tree used by Property Editor & Selection demos properly freed
   on application closure. (#8158) [@Legulysse]
+- Fonts: fixed AddCustomRect() not being packed with TexGlyphPadding + not accounted
+  for surface area used to determine best-guess texture size. (#8107) [@YarikTH, @ocornut]
 - Misc: use SSE 4.2 crc32 instructions when available. (#8169, #4933) [@Teselka]
 - Backends: Vulkan: Make user-provided descriptor pool optional. As a convenience,
   when setting init_info->DescriptorPoolSize then the backend will create and manage
diff --git a/imgui.h b/imgui.h
index 30115e810b30..423e2a8bae82 100644
--- a/imgui.h
+++ b/imgui.h
@@ -3230,8 +3230,8 @@ struct ImFontConfig
     float           SizePixels;             //          // Size in pixels for rasterizer (more or less maps to the resulting font height).
     int             OversampleH;            // 2        // Rasterize at higher quality for sub-pixel positioning. Note the difference between 2 and 3 is minimal. You can reduce this to 1 for large glyphs save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details.
     int             OversampleV;            // 1        // Rasterize at higher quality for sub-pixel positioning. This is not really useful as we don't use sub-pixel positions on the Y axis.
-    bool            PixelSnapH;             // false    // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
-    ImVec2          GlyphExtraSpacing;      // 0, 0     // Extra spacing (in pixels) between glyphs. Only X axis is supported for now.
+    bool            PixelSnapH;             // false    // Align every glyph AdvanceX to pixel boundaries. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
+    ImVec2          GlyphExtraSpacing;      // 0, 0     // Extra spacing (in pixels) between glyphs when rendered: essentially add to glyph->AdvanceX. Only X axis is supported for now.
     ImVec2          GlyphOffset;            // 0, 0     // Offset all glyphs from this font input.
     const ImWchar*  GlyphRanges;            // NULL     // THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list).
     float           GlyphMinAdvanceX;       // 0        // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
@@ -3389,7 +3389,7 @@ struct ImFontAtlas
     ImFontAtlasFlags            Flags;              // Build flags (see ImFontAtlasFlags_)
     ImTextureID                 TexID;              // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.
     int                         TexDesiredWidth;    // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.
-    int                         TexGlyphPadding;    // Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0 (will also need to set AntiAliasedLinesUseTex = false).
+    int                         TexGlyphPadding;    // FIXME: Should be called "TexPackPadding". Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0 (will also need to set AntiAliasedLinesUseTex = false).
     bool                        Locked;             // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert.
     void*                       UserData;           // Store your own atlas related user-data (if e.g. you have multiple font atlas).
 
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index fd1feb0a84a5..631472a71dd6 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -2941,6 +2941,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
     int total_surface = 0;
     int buf_rects_out_n = 0;
     int buf_packedchars_out_n = 0;
+    const int pack_padding = atlas->TexGlyphPadding;
     for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
     {
         ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
@@ -2964,18 +2965,19 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
 
         // Gather the sizes of all rectangles we will need to pack (this loop is based on stbtt_PackFontRangesGatherRects)
         const float scale = (cfg.SizePixels > 0.0f) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels * cfg.RasterizerDensity) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -cfg.SizePixels * cfg.RasterizerDensity);
-        const int padding = atlas->TexGlyphPadding;
         for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++)
         {
             int x0, y0, x1, y1;
             const int glyph_index_in_font = stbtt_FindGlyphIndex(&src_tmp.FontInfo, src_tmp.GlyphsList[glyph_i]);
             IM_ASSERT(glyph_index_in_font != 0);
             stbtt_GetGlyphBitmapBoxSubpixel(&src_tmp.FontInfo, glyph_index_in_font, scale * cfg.OversampleH, scale * cfg.OversampleV, 0, 0, &x0, &y0, &x1, &y1);
-            src_tmp.Rects[glyph_i].w = (stbrp_coord)(x1 - x0 + padding + cfg.OversampleH - 1);
-            src_tmp.Rects[glyph_i].h = (stbrp_coord)(y1 - y0 + padding + cfg.OversampleV - 1);
+            src_tmp.Rects[glyph_i].w = (stbrp_coord)(x1 - x0 + pack_padding + cfg.OversampleH - 1);
+            src_tmp.Rects[glyph_i].h = (stbrp_coord)(y1 - y0 + pack_padding + cfg.OversampleV - 1);
             total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h;
         }
     }
+    for (int i = 0; i < atlas->CustomRects.Size; i++)
+        total_surface += (atlas->CustomRects[i].Width + pack_padding) * (atlas->CustomRects[i].Height + pack_padding);
 
     // We need a width for the skyline algorithm, any width!
     // The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.
@@ -2991,7 +2993,8 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
     // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values).
     const int TEX_HEIGHT_MAX = 1024 * 32;
     stbtt_pack_context spc = {};
-    stbtt_PackBegin(&spc, NULL, atlas->TexWidth, TEX_HEIGHT_MAX, 0, atlas->TexGlyphPadding, NULL);
+    stbtt_PackBegin(&spc, NULL, atlas->TexWidth, TEX_HEIGHT_MAX, 0, 0, NULL);
+    spc.padding = atlas->TexGlyphPadding; // Because we mixup stbtt_PackXXX and stbrp_PackXXX there's a bit of a hack here, not passing the value to stbtt_PackBegin() allows us to still pack a TexWidth-1 wide item. (#8107)
     ImFontAtlasBuildPackCustomRects(atlas, spc.pack_info);
 
     // 6. Pack each source font. No rendering yet, we are working with rectangles in an infinitely tall texture at this point.
@@ -3137,13 +3140,14 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa
     if (user_rects.Size < 1) { __builtin_unreachable(); } // Workaround for GCC bug if IM_ASSERT() is defined to conditionally throw (see #5343)
 #endif
 
+    const int pack_padding = atlas->TexGlyphPadding;
     ImVector pack_rects;
     pack_rects.resize(user_rects.Size);
     memset(pack_rects.Data, 0, (size_t)pack_rects.size_in_bytes());
     for (int i = 0; i < user_rects.Size; i++)
     {
-        pack_rects[i].w = user_rects[i].Width;
-        pack_rects[i].h = user_rects[i].Height;
+        pack_rects[i].w = user_rects[i].Width + pack_padding;
+        pack_rects[i].h = user_rects[i].Height + pack_padding;
     }
     stbrp_pack_rects(pack_context, &pack_rects[0], pack_rects.Size);
     for (int i = 0; i < pack_rects.Size; i++)
@@ -3151,7 +3155,7 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa
         {
             user_rects[i].X = (unsigned short)pack_rects[i].x;
             user_rects[i].Y = (unsigned short)pack_rects[i].y;
-            IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height);
+            IM_ASSERT(pack_rects[i].w == user_rects[i].Width + pack_padding && pack_rects[i].h == user_rects[i].Height + pack_padding);
             atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h);
         }
 }
diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp
index e68a2af40bbd..bee15ba08399 100644
--- a/misc/freetype/imgui_freetype.cpp
+++ b/misc/freetype/imgui_freetype.cpp
@@ -573,6 +573,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
     // 8. Render/rasterize font characters into the texture
     int total_surface = 0;
     int buf_rects_out_n = 0;
+    const int pack_padding = atlas->TexGlyphPadding;
     for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
     {
         ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
@@ -590,7 +591,6 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
             ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply);
 
         // Gather the sizes of all rectangles we will need to pack
-        const int padding = atlas->TexGlyphPadding;
         for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++)
         {
             ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i];
@@ -623,6 +623,8 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
             total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h;
         }
     }
+    for (int i = 0; i < atlas->CustomRects.Size; i++)
+        total_surface += (atlas->CustomRects[i].Width + pack_padding) * (atlas->CustomRects[i].Height + pack_padding);
 
     // We need a width for the skyline algorithm, any width!
     // The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.

From ee2119d7cbe1361689f9a7a6ef6853c1deae08f6 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Fri, 29 Nov 2024 19:10:39 +0100
Subject: [PATCH 285/548] imgui_freetype: Fix build broken by 19a1f2a (#8107)

---
 misc/freetype/imgui_freetype.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp
index bee15ba08399..1bd3be65ad7a 100644
--- a/misc/freetype/imgui_freetype.cpp
+++ b/misc/freetype/imgui_freetype.cpp
@@ -618,8 +618,8 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
             buf_bitmap_current_used_bytes += bitmap_size_in_bytes;
             src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width, multiply_enabled ? multiply_table : nullptr);
 
-            src_tmp.Rects[glyph_i].w = (stbrp_coord)(src_glyph.Info.Width + padding);
-            src_tmp.Rects[glyph_i].h = (stbrp_coord)(src_glyph.Info.Height + padding);
+            src_tmp.Rects[glyph_i].w = (stbrp_coord)(src_glyph.Info.Width + pack_padding);
+            src_tmp.Rects[glyph_i].h = (stbrp_coord)(src_glyph.Info.Height + pack_padding);
             total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h;
         }
     }

From 43c51eb12d187d9113af0f646d24da9e8cc04c83 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 2 Dec 2024 13:23:09 +0100
Subject: [PATCH 286/548] Tables: fixed SetNextWindowScroll() value being
 ignored by BeginTable() during the first frame or when scrolling flags have
 changed. (#8196)

---
 docs/CHANGELOG.txt | 2 ++
 imgui_tables.cpp   | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 6650debf0238..874c7502f5bb 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -56,6 +56,8 @@ Other changes:
 
 - Error Handling: fixed cases where recoverable error handling would crash when 
   processing errors outside of the NewFrame()..EndFrame() scope. (#1651)
+- Tables: fixed SetNextWindowScroll() value being ignored by BeginTable() during
+  the first frame or when scrolling flags have changed. (#8196)
 - Misc: changed embedded ProggyClean encoding to save a bit of binary space (~12kb to 9.5kb).
 - Misc: added IMGUI_DISABLE_DEFAULT_FONT to strip embedded font from binary. (#8161)
   [@demonese]
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index 5254f7858743..db34aa347d00 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -410,7 +410,8 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
 
         // Reset scroll if we are reactivating it
         if ((previous_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0)
-            SetNextWindowScroll(ImVec2(0.0f, 0.0f));
+            if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll) == 0)
+                SetNextWindowScroll(ImVec2(0.0f, 0.0f));
 
         // Create scrolling region (without border and zero window padding)
         ImGuiWindowFlags child_window_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None;

From 923ca4765a8a6b4cc10b7f438c8e63a25d1f5c61 Mon Sep 17 00:00:00 2001
From: Thomas Hope 
Date: Sat, 30 Nov 2024 16:58:48 +0100
Subject: [PATCH 287/548] Backends: OpenGL3: Fix compile error with
 IMGUI_IMPL_OPENGL_ES2 and IMGUI_IMPL_OPENGL_DEBUG (#8197)

---
 backends/imgui_impl_opengl3.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp
index 57c699421d19..8f3177837423 100644
--- a/backends/imgui_impl_opengl3.cpp
+++ b/backends/imgui_impl_opengl3.cpp
@@ -299,6 +299,8 @@ bool    ImGui_ImplOpenGL3_Init(const char* glsl_version)
     // Query for GL version (e.g. 320 for GL 3.2)
 #if defined(IMGUI_IMPL_OPENGL_ES2)
     // GLES 2
+    const char* gl_version_str = "";
+    IM_UNUSED(gl_version_str); // For IMGUI_IMPL_OPENGL_DEBUG block below.
     bd->GlVersion = 200;
     bd->GlProfileIsES2 = true;
 #else
@@ -336,7 +338,7 @@ bool    ImGui_ImplOpenGL3_Init(const char* glsl_version)
 #endif
 
 #ifdef IMGUI_IMPL_OPENGL_DEBUG
-    printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
+    printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2/IsEs3 = %d/%d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
 #endif
 
 #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET

From 70b6ba42402f27b40760c15c7d7e926cc06c96fa Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 4 Dec 2024 10:38:19 +0100
Subject: [PATCH 288/548] Clarify that IMGUI_USE_BGRA_PACKED_COLOR requires
 backend support. (#8201)

---
 backends/imgui_impl_dx9.cpp | 1 +
 backends/imgui_impl_dx9.h   | 1 +
 imconfig.h                  | 2 +-
 imgui.h                     | 3 ++-
 4 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp
index c97d3c740ef9..ee0e239409b6 100644
--- a/backends/imgui_impl_dx9.cpp
+++ b/backends/imgui_impl_dx9.cpp
@@ -4,6 +4,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR is supported, as this is the optimal color encoding for DirectX9.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_dx9.h b/backends/imgui_impl_dx9.h
index df6a0a012479..c096b3398e3c 100644
--- a/backends/imgui_impl_dx9.h
+++ b/backends/imgui_impl_dx9.h
@@ -4,6 +4,7 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR is supported, as this is the optimal color encoding for DirectX9.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/imconfig.h b/imconfig.h
index 3504a4e4d369..6790f147ac85 100644
--- a/imconfig.h
+++ b/imconfig.h
@@ -59,7 +59,7 @@
 //#define IMGUI_INCLUDE_IMGUI_USER_H
 //#define IMGUI_USER_H_FILENAME         "my_folder/my_imgui_user.h"
 
-//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
+//---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support.
 //#define IMGUI_USE_BGRA_PACKED_COLOR
 
 //---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
diff --git a/imgui.h b/imgui.h
index 423e2a8bae82..b86c7d4e5d89 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2715,7 +2715,8 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
 #endif
 
 // Helpers macros to generate 32-bit encoded colors
-// User can declare their own format by #defining the 5 _SHIFT/_MASK macros in their imconfig file.
+// - User can declare their own format by #defining the 5 _SHIFT/_MASK macros in their imconfig file.
+// - Any setting other than the default will need custom backend support. The only standard backend that supports anything else than the default is DirectX9.
 #ifndef IM_COL32_R_SHIFT
 #ifdef IMGUI_USE_BGRA_PACKED_COLOR
 #define IM_COL32_R_SHIFT    16

From 6f6ac84228a6502b6f21c7dc3641195783a06fb2 Mon Sep 17 00:00:00 2001
From: Jack Holmes 
Date: Wed, 4 Dec 2024 17:59:51 +0000
Subject: [PATCH 289/548] Demo: Assets Browser: use correct axis for layout
 computation, to allow making items non-square. (#8207)

---
 imgui_demo.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index c822c162e567..5efbe6304538 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -10175,7 +10175,7 @@ struct ExampleAssetsBrowser
         }
 
         ImGuiIO& io = ImGui::GetIO();
-        ImGui::SetNextWindowContentSize(ImVec2(0.0f, LayoutOuterPadding + LayoutLineCount * (LayoutItemSize.x + LayoutItemSpacing)));
+        ImGui::SetNextWindowContentSize(ImVec2(0.0f, LayoutOuterPadding + LayoutLineCount * (LayoutItemSize.y + LayoutItemSpacing)));
         if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove))
         {
             ImDrawList* draw_list = ImGui::GetWindowDrawList();

From 566558b17c528b82d88236d9e38d270eb766c261 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 5 Dec 2024 12:25:02 +0100
Subject: [PATCH 290/548] Replacing NULL with nullptr in examples/backends when
 they creeped back. (#6313, #7071, #4537)

---
 backends/imgui_impl_dx11.cpp              |  2 +-
 backends/imgui_impl_dx12.cpp              |  6 +++---
 backends/imgui_impl_glfw.cpp              |  4 ++--
 backends/imgui_impl_sdl2.cpp              | 14 +++++++-------
 backends/imgui_impl_sdl2.h                |  2 +-
 backends/imgui_impl_sdl3.cpp              | 22 +++++++++++-----------
 backends/imgui_impl_sdl3.h                |  2 +-
 backends/imgui_impl_sdlrenderer2.cpp      |  2 +-
 backends/imgui_impl_sdlrenderer3.cpp      |  2 +-
 backends/imgui_impl_vulkan.cpp            |  4 ++--
 backends/imgui_impl_wgpu.cpp              |  2 +-
 backends/imgui_impl_win32.cpp             |  4 ++--
 examples/example_win32_directx12/main.cpp |  2 +-
 misc/freetype/imgui_freetype.cpp          |  2 +-
 14 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp
index 4316a9f1069b..4a87c23a17cc 100644
--- a/backends/imgui_impl_dx11.cpp
+++ b/backends/imgui_impl_dx11.cpp
@@ -298,7 +298,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
         global_idx_offset += draw_list->IdxBuffer.Size;
         global_vtx_offset += draw_list->VtxBuffer.Size;
     }
-    platform_io.Renderer_RenderState = NULL;
+    platform_io.Renderer_RenderState = nullptr;
 
     // Restore modified DX state
     device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index acf98858b55f..a020941286b6 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -311,7 +311,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
         global_idx_offset += draw_list->IdxBuffer.Size;
         global_vtx_offset += draw_list->VtxBuffer.Size;
     }
-    platform_io.Renderer_RenderState = NULL;
+    platform_io.Renderer_RenderState = nullptr;
 }
 
 static void ImGui_ImplDX12_CreateFontsTexture()
@@ -743,7 +743,7 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
     io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;  // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
 
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
-    if (init_info->SrvDescriptorAllocFn == NULL)
+    if (init_info->SrvDescriptorAllocFn == nullptr)
     {
         // Wrap legacy behavior of passing space for a single descriptor
         IM_ASSERT(init_info->LegacySingleSrvCpuDescriptor.ptr != 0 && init_info->LegacySingleSrvGpuDescriptor.ptr != 0);
@@ -765,7 +765,7 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
 #endif
 
     // Allocate 1 SRV descriptor for the font texture
-    IM_ASSERT(init_info->SrvDescriptorAllocFn != NULL && init_info->SrvDescriptorFreeFn != NULL);
+    IM_ASSERT(init_info->SrvDescriptorAllocFn != nullptr && init_info->SrvDescriptorFreeFn != nullptr);
     init_info->SrvDescriptorAllocFn(&bd->InitInfo, &bd->FontTexture.hFontSrvCpuDescHandle, &bd->FontTexture.hFontSrvGpuDescHandle);
 
     // Create buffers with a default size (they will later be grown as needed)
diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp
index afa2185a3b67..1cdb2534fe5c 100644
--- a/backends/imgui_impl_glfw.cpp
+++ b/backends/imgui_impl_glfw.cpp
@@ -595,8 +595,8 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
     bd->Time = 0.0;
 
     ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
-    platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(NULL, text); };
-    platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) { return glfwGetClipboardString(NULL); };
+    platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(nullptr, text); };
+    platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) { return glfwGetClipboardString(nullptr); };
 #ifdef __EMSCRIPTEN__
     platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplGlfw_EmscriptenOpenURL(url); return true; };
 #endif
diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp
index 14022159f8c4..af5f6b0132cb 100644
--- a/backends/imgui_impl_sdl2.cpp
+++ b/backends/imgui_impl_sdl2.cpp
@@ -324,7 +324,7 @@ static void ImGui_ImplSDL2_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
 static ImGuiViewport* ImGui_ImplSDL2_GetViewportForWindowID(Uint32 window_id)
 {
     ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
-    return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : NULL;
+    return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr;
 }
 
 // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
@@ -342,7 +342,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
     {
         case SDL_MOUSEMOTION:
         {
-            if (ImGui_ImplSDL2_GetViewportForWindowID(event->motion.windowID) == NULL)
+            if (ImGui_ImplSDL2_GetViewportForWindowID(event->motion.windowID) == nullptr)
                 return false;
             ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y);
             io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
@@ -351,7 +351,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
         }
         case SDL_MOUSEWHEEL:
         {
-            if (ImGui_ImplSDL2_GetViewportForWindowID(event->wheel.windowID) == NULL)
+            if (ImGui_ImplSDL2_GetViewportForWindowID(event->wheel.windowID) == nullptr)
                 return false;
             //IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY);
 #if SDL_VERSION_ATLEAST(2,0,18) // If this fails to compile on Emscripten: update to latest Emscripten!
@@ -371,7 +371,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
         case SDL_MOUSEBUTTONDOWN:
         case SDL_MOUSEBUTTONUP:
         {
-            if (ImGui_ImplSDL2_GetViewportForWindowID(event->button.windowID) == NULL)
+            if (ImGui_ImplSDL2_GetViewportForWindowID(event->button.windowID) == nullptr)
                 return false;
             int mouse_button = -1;
             if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
@@ -388,7 +388,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
         }
         case SDL_TEXTINPUT:
         {
-            if (ImGui_ImplSDL2_GetViewportForWindowID(event->text.windowID) == NULL)
+            if (ImGui_ImplSDL2_GetViewportForWindowID(event->text.windowID) == nullptr)
                 return false;
             io.AddInputCharactersUTF8(event->text.text);
             return true;
@@ -396,7 +396,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
         case SDL_KEYDOWN:
         case SDL_KEYUP:
         {
-            if (ImGui_ImplSDL2_GetViewportForWindowID(event->key.windowID) == NULL)
+            if (ImGui_ImplSDL2_GetViewportForWindowID(event->key.windowID) == nullptr)
                 return false;
             ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod);
             ImGuiKey key = ImGui_ImplSDL2_KeyEventToImGuiKey(event->key.keysym.sym, event->key.keysym.scancode);
@@ -406,7 +406,7 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
         }
         case SDL_WINDOWEVENT:
         {
-            if (ImGui_ImplSDL2_GetViewportForWindowID(event->window.windowID) == NULL)
+            if (ImGui_ImplSDL2_GetViewportForWindowID(event->window.windowID) == nullptr)
                 return false;
             // - When capturing mouse, SDL will send a bunch of conflicting LEAVE/ENTER event on every mouse move, but the final ENTER tends to be right.
             // - However we won't get a correct LEAVE event for a captured window.
diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h
index 8ccc6fdc7c62..e071e97155e2 100644
--- a/backends/imgui_impl_sdl2.h
+++ b/backends/imgui_impl_sdl2.h
@@ -41,6 +41,6 @@ IMGUI_IMPL_API bool     ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
 // Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. You may override this.
 // When using manual mode, caller is responsible for opening/closing gamepad.
 enum ImGui_ImplSDL2_GamepadMode { ImGui_ImplSDL2_GamepadMode_AutoFirst, ImGui_ImplSDL2_GamepadMode_AutoAll, ImGui_ImplSDL2_GamepadMode_Manual };
-IMGUI_IMPL_API void     ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array = NULL, int manual_gamepads_count = -1);
+IMGUI_IMPL_API void     ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array = nullptr, int manual_gamepads_count = -1);
 
 #endif // #ifndef IMGUI_DISABLE
diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp
index 3cd56a756a6a..0955859a5534 100644
--- a/backends/imgui_impl_sdl3.cpp
+++ b/backends/imgui_impl_sdl3.cpp
@@ -128,7 +128,7 @@ static const char* ImGui_ImplSDL3_GetClipboardText(ImGuiContext*)
     if (bd->ClipboardTextData)
         SDL_free(bd->ClipboardTextData);
     const char* sdl_clipboard_text = SDL_GetClipboardText();
-    bd->ClipboardTextData = sdl_clipboard_text ? SDL_strdup(sdl_clipboard_text) : NULL;
+    bd->ClipboardTextData = sdl_clipboard_text ? SDL_strdup(sdl_clipboard_text) : nullptr;
     return bd->ClipboardTextData;
 }
 
@@ -142,7 +142,7 @@ static void ImGui_ImplSDL3_PlatformSetImeData(ImGuiContext*, ImGuiViewport* view
     ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
     SDL_WindowID window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle;
     SDL_Window* window = SDL_GetWindowFromID(window_id);
-    if ((data->WantVisible == false || bd->ImeWindow != window) && bd->ImeWindow != NULL)
+    if ((data->WantVisible == false || bd->ImeWindow != window) && bd->ImeWindow != nullptr)
     {
         SDL_StopTextInput(bd->ImeWindow);
         bd->ImeWindow = nullptr;
@@ -308,7 +308,7 @@ static void ImGui_ImplSDL3_UpdateKeyModifiers(SDL_Keymod sdl_key_mods)
 static ImGuiViewport* ImGui_ImplSDL3_GetViewportForWindowID(SDL_WindowID window_id)
 {
     ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData();
-    return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : NULL;
+    return (window_id == bd->WindowID) ? ImGui::GetMainViewport() : nullptr;
 }
 
 // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
@@ -326,7 +326,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
     {
         case SDL_EVENT_MOUSE_MOTION:
         {
-            if (ImGui_ImplSDL3_GetViewportForWindowID(event->motion.windowID) == NULL)
+            if (ImGui_ImplSDL3_GetViewportForWindowID(event->motion.windowID) == nullptr)
                 return false;
             ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y);
             io.AddMouseSourceEvent(event->motion.which == SDL_TOUCH_MOUSEID ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse);
@@ -335,7 +335,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
         }
         case SDL_EVENT_MOUSE_WHEEL:
         {
-            if (ImGui_ImplSDL3_GetViewportForWindowID(event->wheel.windowID) == NULL)
+            if (ImGui_ImplSDL3_GetViewportForWindowID(event->wheel.windowID) == nullptr)
                 return false;
             //IMGUI_DEBUG_LOG("wheel %.2f %.2f, precise %.2f %.2f\n", (float)event->wheel.x, (float)event->wheel.y, event->wheel.preciseX, event->wheel.preciseY);
             float wheel_x = -event->wheel.x;
@@ -347,7 +347,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
         case SDL_EVENT_MOUSE_BUTTON_DOWN:
         case SDL_EVENT_MOUSE_BUTTON_UP:
         {
-            if (ImGui_ImplSDL3_GetViewportForWindowID(event->button.windowID) == NULL)
+            if (ImGui_ImplSDL3_GetViewportForWindowID(event->button.windowID) == nullptr)
                 return false;
             int mouse_button = -1;
             if (event->button.button == SDL_BUTTON_LEFT) { mouse_button = 0; }
@@ -364,7 +364,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
         }
         case SDL_EVENT_TEXT_INPUT:
         {
-            if (ImGui_ImplSDL3_GetViewportForWindowID(event->text.windowID) == NULL)
+            if (ImGui_ImplSDL3_GetViewportForWindowID(event->text.windowID) == nullptr)
                 return false;
             io.AddInputCharactersUTF8(event->text.text);
             return true;
@@ -372,7 +372,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
         case SDL_EVENT_KEY_DOWN:
         case SDL_EVENT_KEY_UP:
         {
-            if (ImGui_ImplSDL3_GetViewportForWindowID(event->key.windowID) == NULL)
+            if (ImGui_ImplSDL3_GetViewportForWindowID(event->key.windowID) == nullptr)
                 return false;
             //IMGUI_DEBUG_LOG("SDL_EVENT_KEY_%d: key=%d, scancode=%d, mod=%X\n", (event->type == SDL_EVENT_KEY_DOWN) ? "DOWN" : "UP", event->key.key, event->key.scancode, event->key.mod);
             ImGui_ImplSDL3_UpdateKeyModifiers((SDL_Keymod)event->key.mod);
@@ -383,7 +383,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
         }
         case SDL_EVENT_WINDOW_MOUSE_ENTER:
         {
-            if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == NULL)
+            if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == nullptr)
                 return false;
             bd->MouseWindowID = event->window.windowID;
             bd->MousePendingLeaveFrame = 0;
@@ -395,7 +395,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
         // FIXME: Unconfirmed whether this is still needed with SDL3.
         case SDL_EVENT_WINDOW_MOUSE_LEAVE:
         {
-            if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == NULL)
+            if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == nullptr)
                 return false;
             bd->MousePendingLeaveFrame = ImGui::GetFrameCount() + 1;
             return true;
@@ -403,7 +403,7 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
         case SDL_EVENT_WINDOW_FOCUS_GAINED:
         case SDL_EVENT_WINDOW_FOCUS_LOST:
         {
-            if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == NULL)
+            if (ImGui_ImplSDL3_GetViewportForWindowID(event->window.windowID) == nullptr)
                 return false;
             io.AddFocusEvent(event->type == SDL_EVENT_WINDOW_FOCUS_GAINED);
             return true;
diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h
index c4a5a1230e3c..b86aa1901839 100644
--- a/backends/imgui_impl_sdl3.h
+++ b/backends/imgui_impl_sdl3.h
@@ -42,6 +42,6 @@ IMGUI_IMPL_API bool     ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event);
 // Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. You may override this.
 // When using manual mode, caller is responsible for opening/closing gamepad.
 enum ImGui_ImplSDL3_GamepadMode { ImGui_ImplSDL3_GamepadMode_AutoFirst, ImGui_ImplSDL3_GamepadMode_AutoAll, ImGui_ImplSDL3_GamepadMode_Manual };
-IMGUI_IMPL_API void     ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad** manual_gamepads_array = NULL, int manual_gamepads_count = -1);
+IMGUI_IMPL_API void     ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad** manual_gamepads_array = nullptr, int manual_gamepads_count = -1);
 
 #endif // #ifndef IMGUI_DISABLE
diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp
index 27c9522697a6..485adabb3438 100644
--- a/backends/imgui_impl_sdlrenderer2.cpp
+++ b/backends/imgui_impl_sdlrenderer2.cpp
@@ -208,7 +208,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
             }
         }
     }
-    platform_io.Renderer_RenderState = NULL;
+    platform_io.Renderer_RenderState = nullptr;
 
     // Restore modified SDL_Renderer state
     SDL_RenderSetViewport(renderer, &old.Viewport);
diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp
index 5dabea199647..1238246c2fb4 100644
--- a/backends/imgui_impl_sdlrenderer3.cpp
+++ b/backends/imgui_impl_sdlrenderer3.cpp
@@ -227,7 +227,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer*
             }
         }
     }
-    platform_io.Renderer_RenderState = NULL;
+    platform_io.Renderer_RenderState = nullptr;
 
     // Restore modified SDL_Renderer state
     SDL_SetRenderViewport(renderer, old.ViewportEnabled ? &old.Viewport : nullptr);
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index 69f4937629cb..1491ccabf49c 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -611,7 +611,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
         global_idx_offset += draw_list->IdxBuffer.Size;
         global_vtx_offset += draw_list->VtxBuffer.Size;
     }
-    platform_io.Renderer_RenderState = NULL;
+    platform_io.Renderer_RenderState = nullptr;
 
     // Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
     // Our last values will leak into user/application rendering IF:
@@ -969,7 +969,7 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
     if (bd->VulkanInitInfo.UseDynamicRendering)
     {
         IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR");
-        IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo pNext must be NULL");
+        IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo pNext must be nullptr");
         info.pNext = &bd->VulkanInitInfo.PipelineRenderingCreateInfo;
         info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr.
     }
diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp
index 075f74734a1f..02a8caeb4c50 100644
--- a/backends/imgui_impl_wgpu.cpp
+++ b/backends/imgui_impl_wgpu.cpp
@@ -518,7 +518,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
         global_idx_offset += draw_list->IdxBuffer.Size;
         global_vtx_offset += draw_list->VtxBuffer.Size;
     }
-    platform_io.Renderer_RenderState = NULL;
+    platform_io.Renderer_RenderState = nullptr;
 }
 
 static void ImGui_ImplWGPU_CreateFontsTexture()
diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp
index 687bc5a18d61..843ef161bfe0 100644
--- a/backends/imgui_impl_win32.cpp
+++ b/backends/imgui_impl_win32.cpp
@@ -588,7 +588,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
 {
     // Most backends don't have silent checks like this one, but we need it because WndProc are called early in CreateWindow().
     // We silently allow both context or just only backend data to be nullptr.
-    if (ImGui::GetCurrentContext() == NULL)
+    if (ImGui::GetCurrentContext() == nullptr)
         return 0;
     return ImGui_ImplWin32_WndProcHandlerEx(hwnd, msg, wParam, lParam, ImGui::GetIO());
 }
@@ -597,7 +597,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
 IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, ImGuiIO& io)
 {
     ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(io);
-    if (bd == NULL)
+    if (bd == nullptr)
         return 0;
     switch (msg)
     {
diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp
index 257410e2cb2e..eeff99c1be8b 100644
--- a/examples/example_win32_directx12/main.cpp
+++ b/examples/example_win32_directx12/main.cpp
@@ -58,7 +58,7 @@ struct ExampleDescriptorHeapAllocator
     }
     void Destroy()
     {
-        Heap = NULL;
+        Heap = nullptr;
         FreeIndices.clear();
     }
     void Alloc(D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_desc_handle)
diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp
index 1bd3be65ad7a..aeab6dfa0689 100644
--- a/misc/freetype/imgui_freetype.cpp
+++ b/misc/freetype/imgui_freetype.cpp
@@ -10,7 +10,7 @@
 //  2023/11/13: added support for ImFontConfig::RasterizationDensity field for scaling render density without scaling metrics.
 //  2023/08/01: added support for SVG fonts, enable by using '#define IMGUI_ENABLE_FREETYPE_LUNASVG'. (#6591)
 //  2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly.
-//  2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL.
+//  2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns nullptr.
 //  2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
 //  2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a preferred texture format.
 //  2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).

From 43fbd7ce8405d48caa90cd2d2b244c059288744d Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 5 Dec 2024 12:43:04 +0100
Subject: [PATCH 291/548] Backends: standardized top of file comments.

---
 backends/imgui_impl_allegro5.cpp     | 6 +++---
 backends/imgui_impl_allegro5.h       | 6 +++---
 backends/imgui_impl_android.cpp      | 4 ++--
 backends/imgui_impl_android.h        | 4 ++--
 backends/imgui_impl_dx10.cpp         | 2 +-
 backends/imgui_impl_dx10.h           | 2 +-
 backends/imgui_impl_dx11.cpp         | 2 +-
 backends/imgui_impl_dx11.h           | 2 +-
 backends/imgui_impl_dx12.cpp         | 2 +-
 backends/imgui_impl_dx12.h           | 2 +-
 backends/imgui_impl_dx9.cpp          | 4 ++--
 backends/imgui_impl_dx9.h            | 4 ++--
 backends/imgui_impl_glfw.cpp         | 2 +-
 backends/imgui_impl_glfw.h           | 2 +-
 backends/imgui_impl_glut.cpp         | 2 +-
 backends/imgui_impl_glut.h           | 2 +-
 backends/imgui_impl_metal.h          | 2 +-
 backends/imgui_impl_metal.mm         | 2 +-
 backends/imgui_impl_opengl2.cpp      | 2 ++
 backends/imgui_impl_opengl2.h        | 2 ++
 backends/imgui_impl_opengl3.cpp      | 2 +-
 backends/imgui_impl_opengl3.h        | 2 +-
 backends/imgui_impl_osx.h            | 4 ++--
 backends/imgui_impl_osx.mm           | 4 ++--
 backends/imgui_impl_sdl2.cpp         | 2 +-
 backends/imgui_impl_sdl2.h           | 2 +-
 backends/imgui_impl_sdl3.cpp         | 3 ++-
 backends/imgui_impl_sdl3.h           | 3 ++-
 backends/imgui_impl_sdlrenderer2.cpp | 2 +-
 backends/imgui_impl_sdlrenderer2.h   | 2 +-
 backends/imgui_impl_sdlrenderer3.cpp | 2 +-
 backends/imgui_impl_sdlrenderer3.h   | 2 +-
 backends/imgui_impl_vulkan.cpp       | 4 ++--
 backends/imgui_impl_vulkan.h         | 4 ++--
 backends/imgui_impl_wgpu.cpp         | 2 +-
 backends/imgui_impl_wgpu.h           | 2 +-
 backends/imgui_impl_win32.cpp        | 2 +-
 backends/imgui_impl_win32.h          | 2 +-
 38 files changed, 54 insertions(+), 48 deletions(-)

diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp
index 3e6d766470e0..28d1b1536f47 100644
--- a/backends/imgui_impl_allegro5.cpp
+++ b/backends/imgui_impl_allegro5.cpp
@@ -4,9 +4,9 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy ALLEGRO_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
-//  [X] Platform: Clipboard support (from Allegro 5.1.12)
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
-// Issues:
+//  [X] Platform: Clipboard support (from Allegro 5.1.12).
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// Missing features or Issues:
 //  [ ] Renderer: The renderer is suboptimal as we need to convert vertices manually.
 //  [ ] Platform: Missing gamepad support.
 
diff --git a/backends/imgui_impl_allegro5.h b/backends/imgui_impl_allegro5.h
index aba5c47701ea..356ec7d0a9f4 100644
--- a/backends/imgui_impl_allegro5.h
+++ b/backends/imgui_impl_allegro5.h
@@ -4,9 +4,9 @@
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID!
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy ALLEGRO_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
-//  [X] Platform: Clipboard support (from Allegro 5.1.12)
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
-// Issues:
+//  [X] Platform: Clipboard support (from Allegro 5.1.12).
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// Missing features or Issues:
 //  [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually.
 //  [ ] Platform: Missing gamepad support.
 
diff --git a/backends/imgui_impl_android.cpp b/backends/imgui_impl_android.cpp
index 05939293cb84..1c2d62476002 100644
--- a/backends/imgui_impl_android.cpp
+++ b/backends/imgui_impl_android.cpp
@@ -4,10 +4,10 @@
 // Implemented features:
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
-// Missing features:
+// Missing features or Issues:
 //  [ ] Platform: Clipboard support.
 //  [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-//  [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
+//  [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
 // Important:
 //  - Consider using SDL or GLFW backend on Android, which will be more full-featured than this.
 //  - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
diff --git a/backends/imgui_impl_android.h b/backends/imgui_impl_android.h
index efe27dcb9568..3eaeca7253ae 100644
--- a/backends/imgui_impl_android.h
+++ b/backends/imgui_impl_android.h
@@ -4,10 +4,10 @@
 // Implemented features:
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy AKEYCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
-// Missing features:
+// Missing features or Issues:
 //  [ ] Platform: Clipboard support.
 //  [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-//  [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
+//  [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
 // Important:
 //  - Consider using SDL or GLFW backend on Android, which will be more full-featured than this.
 //  - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp
index 2638caf9cadb..f160803ee6a1 100644
--- a/backends/imgui_impl_dx10.cpp
+++ b/backends/imgui_impl_dx10.cpp
@@ -3,7 +3,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_dx10.h b/backends/imgui_impl_dx10.h
index 667f296f17bd..29f339370f53 100644
--- a/backends/imgui_impl_dx10.h
+++ b/backends/imgui_impl_dx10.h
@@ -3,7 +3,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp
index 4a87c23a17cc..a2c67ec43f9e 100644
--- a/backends/imgui_impl_dx11.cpp
+++ b/backends/imgui_impl_dx11.cpp
@@ -3,7 +3,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_dx11.h b/backends/imgui_impl_dx11.h
index c3b8379b14b7..69ae493586fb 100644
--- a/backends/imgui_impl_dx11.h
+++ b/backends/imgui_impl_dx11.h
@@ -3,7 +3,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index a020941286b6..bad823c4a9ba 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -3,7 +3,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // The aim of imgui_impl_dx12.h/.cpp is to be usable in your engine without any modification.
diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h
index 34938fb56347..0ade2ac99b36 100644
--- a/backends/imgui_impl_dx12.h
+++ b/backends/imgui_impl_dx12.h
@@ -3,7 +3,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // The aim of imgui_impl_dx12.h/.cpp is to be usable in your engine without any modification.
diff --git a/backends/imgui_impl_dx9.cpp b/backends/imgui_impl_dx9.cpp
index ee0e239409b6..2cc8681a6d06 100644
--- a/backends/imgui_impl_dx9.cpp
+++ b/backends/imgui_impl_dx9.cpp
@@ -3,8 +3,8 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
-//  [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR is supported, as this is the optimal color encoding for DirectX9.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
+//  [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR support, as this is the optimal color encoding for DirectX9.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_dx9.h b/backends/imgui_impl_dx9.h
index c096b3398e3c..b693054d9b6b 100644
--- a/backends/imgui_impl_dx9.h
+++ b/backends/imgui_impl_dx9.h
@@ -3,8 +3,8 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
-//  [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR is supported, as this is the optimal color encoding for DirectX9.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
+//  [X] Renderer: IMGUI_USE_BGRA_PACKED_COLOR support, as this is the optimal color encoding for DirectX9.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp
index 1cdb2534fe5c..01a6a5566397 100644
--- a/backends/imgui_impl_glfw.cpp
+++ b/backends/imgui_impl_glfw.cpp
@@ -8,7 +8,7 @@
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h
index 5d8940a0c98e..53a22415d87c 100644
--- a/backends/imgui_impl_glfw.h
+++ b/backends/imgui_impl_glfw.h
@@ -7,7 +7,7 @@
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only).
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp
index 6bb9eae7eeea..ef7f17922ec5 100644
--- a/backends/imgui_impl_glut.cpp
+++ b/backends/imgui_impl_glut.cpp
@@ -7,7 +7,7 @@
 
 // Implemented features:
 //  [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values are obsolete since 1.87 and not supported since 1.91.5]
-// Issues:
+// Missing features or Issues:
 //  [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
 //  [ ] Platform: Missing horizontal mouse wheel support.
 //  [ ] Platform: Missing mouse cursor shape/visibility support.
diff --git a/backends/imgui_impl_glut.h b/backends/imgui_impl_glut.h
index feeca8b3fcd0..20e77dbceb70 100644
--- a/backends/imgui_impl_glut.h
+++ b/backends/imgui_impl_glut.h
@@ -7,7 +7,7 @@
 
 // Implemented features:
 //  [X] Platform: Partial keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLUT values are obsolete since 1.87 and not supported since 1.91.5]
-// Issues:
+// Missing features or Issues:
 //  [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
 //  [ ] Platform: Missing horizontal mouse wheel support.
 //  [ ] Platform: Missing mouse cursor shape/visibility support.
diff --git a/backends/imgui_impl_metal.h b/backends/imgui_impl_metal.h
index 2402c02c62c8..351c2eff735c 100644
--- a/backends/imgui_impl_metal.h
+++ b/backends/imgui_impl_metal.h
@@ -3,7 +3,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm
index 12dc3d50f52c..5680dea9d40c 100644
--- a/backends/imgui_impl_metal.mm
+++ b/backends/imgui_impl_metal.mm
@@ -3,7 +3,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp
index 789d74afb2b6..767731fb39ea 100644
--- a/backends/imgui_impl_opengl2.cpp
+++ b/backends/imgui_impl_opengl2.cpp
@@ -3,6 +3,8 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
+// Missing features or Issues:
+//  [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_opengl2.h b/backends/imgui_impl_opengl2.h
index e7f7a58c1f0e..5832a176599f 100644
--- a/backends/imgui_impl_opengl2.h
+++ b/backends/imgui_impl_opengl2.h
@@ -3,6 +3,8 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
+// Missing features or Issues:
+//  [ ] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp
index 8f3177837423..efcfb8217358 100644
--- a/backends/imgui_impl_opengl3.cpp
+++ b/backends/imgui_impl_opengl3.cpp
@@ -5,7 +5,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
-//  [x] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only).
+//  [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
 
 // About WebGL/ES:
 // - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
diff --git a/backends/imgui_impl_opengl3.h b/backends/imgui_impl_opengl3.h
index 54545f957b91..5de51cfddaf9 100644
--- a/backends/imgui_impl_opengl3.h
+++ b/backends/imgui_impl_opengl3.h
@@ -5,7 +5,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
-//  [x] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only).
+//  [x] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset) [Desktop OpenGL only!]
 
 // About WebGL/ES:
 // - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES.
diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h
index 4caab8ff5f73..2e7eabb2b415 100644
--- a/backends/imgui_impl_osx.h
+++ b/backends/imgui_impl_osx.h
@@ -4,11 +4,11 @@
 // - Requires linking with the GameController framework ("-framework GameController").
 
 // Implemented features:
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+//  [X] Platform: Clipboard support is part of core Dear ImGui (no specific code in this backend).
 //  [X] Platform: Mouse support. Can discriminate Mouse/Pen.
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values are obsolete since 1.87 and not supported since 1.91.5]
-//  [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 //  [X] Platform: IME support.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm
index c99ba1f06cab..c2a5f6378a45 100644
--- a/backends/imgui_impl_osx.mm
+++ b/backends/imgui_impl_osx.mm
@@ -4,11 +4,11 @@
 // - Requires linking with the GameController framework ("-framework GameController").
 
 // Implemented features:
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+//  [X] Platform: Clipboard support is part of core Dear ImGui (no specific code in this backend).
 //  [X] Platform: Mouse support. Can discriminate Mouse/Pen.
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy kVK_* values are obsolete since 1.87 and not supported since 1.91.5]
-//  [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 //  [X] Platform: IME support.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp
index af5f6b0132cb..e937b5496654 100644
--- a/backends/imgui_impl_sdl2.cpp
+++ b/backends/imgui_impl_sdl2.cpp
@@ -8,7 +8,7 @@
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 //  [X] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h
index e071e97155e2..3c477569777c 100644
--- a/backends/imgui_impl_sdl2.h
+++ b/backends/imgui_impl_sdl2.h
@@ -7,7 +7,7 @@
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 //  [X] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp
index 0955859a5534..a167c74cd617 100644
--- a/backends/imgui_impl_sdl3.cpp
+++ b/backends/imgui_impl_sdl3.cpp
@@ -9,7 +9,8 @@
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+//  [X] Platform: IME support.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h
index b86aa1901839..0d906a65cd32 100644
--- a/backends/imgui_impl_sdl3.h
+++ b/backends/imgui_impl_sdl3.h
@@ -9,7 +9,8 @@
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+//  [X] Platform: IME support.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp
index 485adabb3438..6d0ee564f1b3 100644
--- a/backends/imgui_impl_sdlrenderer2.cpp
+++ b/backends/imgui_impl_sdlrenderer2.cpp
@@ -9,7 +9,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_sdlrenderer2.h b/backends/imgui_impl_sdlrenderer2.h
index 804ca183d14a..7aed18d21809 100644
--- a/backends/imgui_impl_sdlrenderer2.h
+++ b/backends/imgui_impl_sdlrenderer2.h
@@ -9,7 +9,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp
index 1238246c2fb4..1bcf7a228b0a 100644
--- a/backends/imgui_impl_sdlrenderer3.cpp
+++ b/backends/imgui_impl_sdlrenderer3.cpp
@@ -11,7 +11,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_sdlrenderer3.h b/backends/imgui_impl_sdlrenderer3.h
index 7d4c609e8b25..3a7a51ee545e 100644
--- a/backends/imgui_impl_sdlrenderer3.h
+++ b/backends/imgui_impl_sdlrenderer3.h
@@ -11,7 +11,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index 1491ccabf49c..b419703048e0 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -2,8 +2,8 @@
 // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
 
 // Implemented features:
-//  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h
index 8d9e19f9a7ee..37f700b62160 100644
--- a/backends/imgui_impl_vulkan.h
+++ b/backends/imgui_impl_vulkan.h
@@ -2,8 +2,8 @@
 // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
 
 // Implemented features:
-//  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Call ImGui_ImplVulkan_AddTexture() to register one. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp
index 02a8caeb4c50..2f34c0e0b345 100644
--- a/backends/imgui_impl_wgpu.cpp
+++ b/backends/imgui_impl_wgpu.cpp
@@ -4,7 +4,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h
index f9fb037764f6..7efb02afe109 100644
--- a/backends/imgui_impl_wgpu.h
+++ b/backends/imgui_impl_wgpu.h
@@ -11,7 +11,7 @@
 
 // Implemented features:
 //  [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
-//  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices.
+//  [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset).
 //  [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp
index 843ef161bfe0..f1cf6eccc52b 100644
--- a/backends/imgui_impl_win32.cpp
+++ b/backends/imgui_impl_win32.cpp
@@ -6,7 +6,7 @@
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
diff --git a/backends/imgui_impl_win32.h b/backends/imgui_impl_win32.h
index 0dfd56a801be..083fe385f6fa 100644
--- a/backends/imgui_impl_win32.h
+++ b/backends/imgui_impl_win32.h
@@ -6,7 +6,7 @@
 //  [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen.
 //  [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values are obsolete since 1.87 and not supported since 1.91.5]
 //  [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
-//  [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+//  [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
 
 // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.

From 18e5d769fd7fc48b809ee3b8f6bef6906289251d Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 5 Dec 2024 13:08:33 +0100
Subject: [PATCH 292/548] Backends: DX10: create sampler outside of
 ImGui_ImplDX11_CreateFontsTexture().

Analoguous to 90dd510 for DX11.
---
 backends/imgui_impl_dx10.cpp | 42 +++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 15 deletions(-)

diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp
index f160803ee6a1..15f0bb323f5d 100644
--- a/backends/imgui_impl_dx10.cpp
+++ b/backends/imgui_impl_dx10.cpp
@@ -341,21 +341,16 @@ static void ImGui_ImplDX10_CreateFontsTexture()
 
     // Store our identifier
     io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
+}
 
-    // Create texture sampler
-    // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
+static void ImGui_ImplDX10_DestroyFontsTexture()
+{
+    ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
+    if (bd->pFontTextureView)
     {
-        D3D10_SAMPLER_DESC desc;
-        ZeroMemory(&desc, sizeof(desc));
-        desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
-        desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;
-        desc.AddressV = D3D10_TEXTURE_ADDRESS_CLAMP;
-        desc.AddressW = D3D10_TEXTURE_ADDRESS_CLAMP;
-        desc.MipLODBias = 0.f;
-        desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
-        desc.MinLOD = 0.f;
-        desc.MaxLOD = 0.f;
-        bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
+        bd->pFontTextureView->Release();
+        bd->pFontTextureView = nullptr;
+        ImGui::GetIO().Fonts->SetTexID(0); // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
     }
 }
 
@@ -508,6 +503,22 @@ bool    ImGui_ImplDX10_CreateDeviceObjects()
         bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
     }
 
+    // Create texture sampler
+    // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
+    {
+        D3D10_SAMPLER_DESC desc;
+        ZeroMemory(&desc, sizeof(desc));
+        desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
+        desc.AddressU = D3D10_TEXTURE_ADDRESS_CLAMP;
+        desc.AddressV = D3D10_TEXTURE_ADDRESS_CLAMP;
+        desc.AddressW = D3D10_TEXTURE_ADDRESS_CLAMP;
+        desc.MipLODBias = 0.f;
+        desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
+        desc.MinLOD = 0.f;
+        desc.MaxLOD = 0.f;
+        bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
+    }
+
     ImGui_ImplDX10_CreateFontsTexture();
 
     return true;
@@ -519,8 +530,9 @@ void    ImGui_ImplDX10_InvalidateDeviceObjects()
     if (!bd->pd3dDevice)
         return;
 
+    ImGui_ImplDX10_DestroyFontsTexture();
+
     if (bd->pFontSampler)           { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
-    if (bd->pFontTextureView)       { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
     if (bd->pIB)                    { bd->pIB->Release(); bd->pIB = nullptr; }
     if (bd->pVB)                    { bd->pVB->Release(); bd->pVB = nullptr; }
     if (bd->pBlendState)            { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
@@ -582,7 +594,7 @@ void ImGui_ImplDX10_NewFrame()
     ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
     IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX10_Init()?");
 
-    if (!bd->pFontSampler)
+    if (!bd->pVertexShader)
         ImGui_ImplDX10_CreateDeviceObjects();
 }
 

From 3f3c62a3c999ae7004d6871c504c0694c9b9e2b1 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 9 Dec 2024 11:43:00 +0100
Subject: [PATCH 293/548] ScrollbarEx: clarify use of flags and make them
 optional. (#8215)

---
 imgui_internal.h  | 2 +-
 imgui_widgets.cpp | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/imgui_internal.h b/imgui_internal.h
index fd8a185a597d..147e30c3569c 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -3398,7 +3398,7 @@ namespace ImGui
     IMGUI_API bool          CloseButton(ImGuiID id, const ImVec2& pos);
     IMGUI_API bool          CollapseButton(ImGuiID id, const ImVec2& pos);
     IMGUI_API void          Scrollbar(ImGuiAxis axis);
-    IMGUI_API bool          ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 avail_v, ImS64 contents_v, ImDrawFlags flags);
+    IMGUI_API bool          ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 avail_v, ImS64 contents_v, ImDrawFlags draw_rounding_flags = 0);
     IMGUI_API ImRect        GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis);
     IMGUI_API ImGuiID       GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
     IMGUI_API ImGuiID       GetWindowResizeCornerID(ImGuiWindow* window, int n); // 0..3: corners
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index f9939cec430f..cf6891ea18d7 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -950,7 +950,7 @@ void ImGui::Scrollbar(ImGuiAxis axis)
 // - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar
 // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.
 // Still, the code should probably be made simpler..
-bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 size_visible_v, ImS64 size_contents_v, ImDrawFlags flags)
+bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 size_visible_v, ImS64 size_contents_v, ImDrawFlags draw_rounding_flags)
 {
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
@@ -1041,7 +1041,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
     // Render
     const ImU32 bg_col = GetColorU32(ImGuiCol_ScrollbarBg);
     const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha);
-    window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, bg_col, window->WindowRounding, flags);
+    window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, bg_col, window->WindowRounding, draw_rounding_flags);
     ImRect grab_rect;
     if (axis == ImGuiAxis_X)
         grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y);

From 2671f68f7f8cb77bf951779c0c8e437f6171a324 Mon Sep 17 00:00:00 2001
From: slowriot 
Date: Fri, 6 Dec 2024 17:50:44 +0000
Subject: [PATCH 294/548] Don't enable SSE4 under Emscripten (#8213, #8169,
 #4933)

Amend 326dc95f9
---
 imgui.cpp        | 10 +++++-----
 imgui_internal.h |  4 ++++
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 5f6c859007c5..5833691dbf14 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -2150,7 +2150,7 @@ void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end,
     }
 }
 
-#ifndef IMGUI_ENABLE_SSE4_2
+#ifndef IMGUI_ENABLE_SSE4_2_CRC
 // CRC32 needs a 1KB lookup table (not cache friendly)
 // Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily:
 // - avoid an unnecessary branch/memory tap, - keep the ImHashXXX functions usable by static constructors, - make it thread-safe.
@@ -2184,7 +2184,7 @@ ImGuiID ImHashData(const void* data_p, size_t data_size, ImGuiID seed)
     ImU32 crc = ~seed;
     const unsigned char* data = (const unsigned char*)data_p;
     const unsigned char *data_end = (const unsigned char*)data_p + data_size;
-#ifndef IMGUI_ENABLE_SSE4_2
+#ifndef IMGUI_ENABLE_SSE4_2_CRC
     const ImU32* crc32_lut = GCrc32LookupTable;
     while (data < data_end)
         crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
@@ -2212,7 +2212,7 @@ ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed)
     seed = ~seed;
     ImU32 crc = seed;
     const unsigned char* data = (const unsigned char*)data_p;
-#ifndef IMGUI_ENABLE_SSE4_2
+#ifndef IMGUI_ENABLE_SSE4_2_CRC
     const ImU32* crc32_lut = GCrc32LookupTable;
 #endif
     if (data_size != 0)
@@ -2222,7 +2222,7 @@ ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed)
             unsigned char c = *data++;
             if (c == '#' && data_size >= 2 && data[0] == '#' && data[1] == '#')
                 crc = seed;
-#ifndef IMGUI_ENABLE_SSE4_2
+#ifndef IMGUI_ENABLE_SSE4_2_CRC
             crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
 #else
             crc = _mm_crc32_u8(crc, c);
@@ -2235,7 +2235,7 @@ ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed)
         {
             if (c == '#' && data[0] == '#' && data[1] == '#')
                 crc = seed;
-#ifndef IMGUI_ENABLE_SSE4_2
+#ifndef IMGUI_ENABLE_SSE4_2_CRC
             crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
 #else
             crc = _mm_crc32_u8(crc, c);
diff --git a/imgui_internal.h b/imgui_internal.h
index 147e30c3569c..f11f272c3c03 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -66,6 +66,10 @@ Index of this file:
 #include 
 #endif
 #endif
+// Emscripten has partial SSE 4.2 support where _mm_crc32_u32 is not available. See https://emscripten.org/docs/porting/simd.html#id11 and #8213
+#if defined(IMGUI_ENABLE_SSE4_2) || !defined(__EMSCRIPTEN__)
+#define IMGUI_ENABLE_SSE4_2_CRC
+#endif
 
 // Visual Studio warnings
 #ifdef _MSC_VER

From 53dd7552dcbef379a57f33bb5e35f12ae04a3d8d Mon Sep 17 00:00:00 2001
From: bmarques1995 
Date: Mon, 9 Dec 2024 01:19:23 -0300
Subject: [PATCH 295/548] Backends: DX12: let the user specifies the
 DepthStencilView format. (#8217)

This is particullarly important for those who use RenderPasses.
---
 backends/imgui_impl_dx12.cpp              | 4 ++++
 backends/imgui_impl_dx12.h                | 3 ++-
 docs/CHANGELOG.txt                        | 2 ++
 examples/example_win32_directx12/main.cpp | 1 +
 4 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp
index bad823c4a9ba..16dcf5392ffe 100644
--- a/backends/imgui_impl_dx12.cpp
+++ b/backends/imgui_impl_dx12.cpp
@@ -19,6 +19,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-12-09: DirectX12: Let user specifies the DepthStencilView format by setting ImGui_ImplDX12_InitInfo::DSVFormat. 
 //  2024-11-15: DirectX12: *BREAKING CHANGE* Changed ImGui_ImplDX12_Init() signature to take a ImGui_ImplDX12_InitInfo struct. Legacy ImGui_ImplDX12_Init() signature is still supported (will obsolete).
 //  2024-11-15: DirectX12: *BREAKING CHANGE* User is now required to pass function pointers to allocate/free SRV Descriptors. We provide convenience legacy fields to pass a single descriptor, matching the old API, but upcoming features will want multiple.
 //  2024-10-23: DirectX12: Unmap() call specify written range. The range is informational and may be used by debug tools.
@@ -72,6 +73,7 @@ struct ImGui_ImplDX12_Data
     ID3D12RootSignature*        pRootSignature;
     ID3D12PipelineState*        pPipelineState;
     DXGI_FORMAT                 RTVFormat;
+    DXGI_FORMAT                 DSVFormat;
     ID3D12DescriptorHeap*       pd3dSrvDescHeap;
     UINT                        numFramesInFlight;
 
@@ -569,6 +571,7 @@ bool    ImGui_ImplDX12_CreateDeviceObjects()
     psoDesc.SampleMask = UINT_MAX;
     psoDesc.NumRenderTargets = 1;
     psoDesc.RTVFormats[0] = bd->RTVFormat;
+    psoDesc.DSVFormat = bd->DSVFormat;
     psoDesc.SampleDesc.Count = 1;
     psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
 
@@ -735,6 +738,7 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
 
     bd->pd3dDevice = init_info->Device;
     bd->RTVFormat = init_info->RTVFormat;
+    bd->DSVFormat = init_info->DSVFormat;
     bd->numFramesInFlight = init_info->NumFramesInFlight;
     bd->pd3dSrvDescHeap = init_info->SrvDescriptorHeap;
 
diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h
index 0ade2ac99b36..644c022fffbd 100644
--- a/backends/imgui_impl_dx12.h
+++ b/backends/imgui_impl_dx12.h
@@ -29,7 +29,8 @@ struct ImGui_ImplDX12_InitInfo
     ID3D12Device*               Device;
     ID3D12CommandQueue*         CommandQueue;
     int                         NumFramesInFlight;
-    DXGI_FORMAT                 RTVFormat;
+    DXGI_FORMAT                 RTVFormat;          // RenderTarget format.
+    DXGI_FORMAT                 DSVFormat;          // DepthStencilView format.
     void*                       UserData;
 
     // Allocating SRV descriptors for textures is up to the application, so we provide callbacks.
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 874c7502f5bb..8a1cc931eefd 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -67,6 +67,8 @@ Other changes:
 - Fonts: fixed AddCustomRect() not being packed with TexGlyphPadding + not accounted
   for surface area used to determine best-guess texture size. (#8107) [@YarikTH, @ocornut]
 - Misc: use SSE 4.2 crc32 instructions when available. (#8169, #4933) [@Teselka]
+- Backends: DirectX12: Let user specifies the DepthStencilView format by setting 
+  ImGui_ImplDX12_InitInfo::DSVFormat. (#8217) [@bmarques1995]
 - Backends: Vulkan: Make user-provided descriptor pool optional. As a convenience,
   when setting init_info->DescriptorPoolSize then the backend will create and manage
   one itself. (#8172, #4867) [@zeux]
diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp
index eeff99c1be8b..392ba18aab14 100644
--- a/examples/example_win32_directx12/main.cpp
+++ b/examples/example_win32_directx12/main.cpp
@@ -146,6 +146,7 @@ int main(int, char**)
     init_info.CommandQueue = g_pd3dCommandQueue;
     init_info.NumFramesInFlight = APP_NUM_FRAMES_IN_FLIGHT;
     init_info.RTVFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+    init_info.DSVFormat = DXGI_FORMAT_UNKNOWN;
     // Allocating SRV descriptors (for textures) is up to the application, so we provide callbacks.
     // (current version of the backend will only allocate one descriptor, future versions will need to allocate more)
     init_info.SrvDescriptorHeap = g_pd3dSrvDescHeap;

From fce07bb1cb4cdd64dbf825223b74be1d9b28b76b Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 9 Dec 2024 12:43:49 +0100
Subject: [PATCH 296/548] Don't enable SSE4 under Emscripten - Fix. (#8213,
 #8169, #4933)

---
 imgui_internal.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/imgui_internal.h b/imgui_internal.h
index f11f272c3c03..cccecf702943 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -67,7 +67,7 @@ Index of this file:
 #endif
 #endif
 // Emscripten has partial SSE 4.2 support where _mm_crc32_u32 is not available. See https://emscripten.org/docs/porting/simd.html#id11 and #8213
-#if defined(IMGUI_ENABLE_SSE4_2) || !defined(__EMSCRIPTEN__)
+#if defined(IMGUI_ENABLE_SSE4_2) && !defined(__EMSCRIPTEN__)
 #define IMGUI_ENABLE_SSE4_2_CRC
 #endif
 

From 6b348622bb8c0cd4adf5b5f4ec6da5d24ba55a93 Mon Sep 17 00:00:00 2001
From: Thomas Hope 
Date: Sat, 30 Nov 2024 16:55:46 +0100
Subject: [PATCH 297/548] Examples: SDL2+OpenGL3: Provide ES3 context creation
 code + failure handling. (#8197)

---
 examples/example_sdl2_opengl3/main.cpp | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/examples/example_sdl2_opengl3/main.cpp b/examples/example_sdl2_opengl3/main.cpp
index 2a4d7b9e7d9a..cb0ade097ac3 100644
--- a/examples/example_sdl2_opengl3/main.cpp
+++ b/examples/example_sdl2_opengl3/main.cpp
@@ -35,12 +35,19 @@ int main(int, char**)
 
     // Decide GL+GLSL versions
 #if defined(IMGUI_IMPL_OPENGL_ES2)
-    // GL ES 2.0 + GLSL 100
+    // GL ES 2.0 + GLSL 100 (WebGL 1.0)
     const char* glsl_version = "#version 100";
     SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
     SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+#elif defined(IMGUI_IMPL_OPENGL_ES3)
+    // GL ES 3.0 + GLSL 300 es (WebGL 2.0)
+    const char* glsl_version = "#version 300 es";
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
 #elif defined(__APPLE__)
     // GL 3.2 Core + GLSL 150
     const char* glsl_version = "#version 150";
@@ -75,6 +82,12 @@ int main(int, char**)
     }
 
     SDL_GLContext gl_context = SDL_GL_CreateContext(window);
+    if (gl_context == nullptr)
+    {
+        printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError());
+        return -1;
+    }
+    
     SDL_GL_MakeCurrent(window, gl_context);
     SDL_GL_SetSwapInterval(1); // Enable vsync
 

From 921c22f5adce8b5941cbf47bb7efcd02e6cc8fe5 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 9 Dec 2024 12:55:33 +0100
Subject: [PATCH 298/548] Examples: GLFW+OpenGL3, SDL3+OpenGL3: Provide ES3
 context creation code + failure handling. (#8197)

Untested for GLFW example.
---
 examples/example_glfw_opengl3/main.cpp |  8 +++++++-
 examples/example_sdl3_opengl3/main.cpp | 15 ++++++++++++++-
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/examples/example_glfw_opengl3/main.cpp b/examples/example_glfw_opengl3/main.cpp
index 3afe251e3750..e5f29d40578d 100644
--- a/examples/example_glfw_opengl3/main.cpp
+++ b/examples/example_glfw_opengl3/main.cpp
@@ -43,11 +43,17 @@ int main(int, char**)
 
     // Decide GL+GLSL versions
 #if defined(IMGUI_IMPL_OPENGL_ES2)
-    // GL ES 2.0 + GLSL 100
+    // GL ES 2.0 + GLSL 100 (WebGL 1.0)
     const char* glsl_version = "#version 100";
     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
     glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
+#elif defined(IMGUI_IMPL_OPENGL_ES3)
+    // GL ES 3.0 + GLSL 300 es (WebGL 2.0)
+    const char* glsl_version = "#version 300 es";
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+    glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
 #elif defined(__APPLE__)
     // GL 3.2 + GLSL 150
     const char* glsl_version = "#version 150";
diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp
index e7f239f4769b..5520a7da9293 100644
--- a/examples/example_sdl3_opengl3/main.cpp
+++ b/examples/example_sdl3_opengl3/main.cpp
@@ -35,12 +35,19 @@ int main(int, char**)
 
     // Decide GL+GLSL versions
 #if defined(IMGUI_IMPL_OPENGL_ES2)
-    // GL ES 2.0 + GLSL 100
+    // GL ES 2.0 + GLSL 100 (WebGL 1.0)
     const char* glsl_version = "#version 100";
     SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
     SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+#elif defined(IMGUI_IMPL_OPENGL_ES3)
+    // GL ES 3.0 + GLSL 300 es (WebGL 2.0)
+    const char* glsl_version = "#version 300 es";
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
 #elif defined(__APPLE__)
     // GL 3.2 Core + GLSL 150
     const char* glsl_version = "#version 150";
@@ -70,6 +77,12 @@ int main(int, char**)
     }
     SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
     SDL_GLContext gl_context = SDL_GL_CreateContext(window);
+    if (gl_context == nullptr)
+    {
+        printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError());
+        return -1;
+    }
+
     SDL_GL_MakeCurrent(window, gl_context);
     SDL_GL_SetSwapInterval(1); // Enable vsync
     SDL_ShowWindow(window);

From f3147f446a7f3ad79f642421a56d2742e6bd210d Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 9 Dec 2024 12:58:32 +0100
Subject: [PATCH 299/548] Backends: OpenGL3: call glGetString(GL_VERSION) even
 in GS ES 2.0 path. (#8197)

Apparently as per specs works. I reckon the best way to confirm it is to try.
---
 backends/imgui_impl_opengl3.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp
index efcfb8217358..b47ac9ab1c97 100644
--- a/backends/imgui_impl_opengl3.cpp
+++ b/backends/imgui_impl_opengl3.cpp
@@ -297,15 +297,13 @@ bool    ImGui_ImplOpenGL3_Init(const char* glsl_version)
     io.BackendRendererName = "imgui_impl_opengl3";
 
     // Query for GL version (e.g. 320 for GL 3.2)
+    const char* gl_version_str = (const char*)glGetString(GL_VERSION);
 #if defined(IMGUI_IMPL_OPENGL_ES2)
     // GLES 2
-    const char* gl_version_str = "";
-    IM_UNUSED(gl_version_str); // For IMGUI_IMPL_OPENGL_DEBUG block below.
     bd->GlVersion = 200;
     bd->GlProfileIsES2 = true;
 #else
     // Desktop or GLES 3
-    const char* gl_version_str = (const char*)glGetString(GL_VERSION);
     GLint major = 0;
     GLint minor = 0;
     glGetIntegerv(GL_MAJOR_VERSION, &major);

From d2645423de8eb035a70de3cf1bed016d5c10161e Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 9 Dec 2024 14:26:53 +0100
Subject: [PATCH 300/548] InputText: reactivating last activated InputText()
 doesn't restore horizontal scrolling.

Honestly not sure if the opposite is preferable or not (added commented out in the inactivate render path to test that).
Current behavior added along with recycling: f9928e96c7c762f97bbdf8cf48e04097b56da84a
---
 docs/CHANGELOG.txt | 2 ++
 imgui_widgets.cpp  | 5 +++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 8a1cc931eefd..42026c9cd514 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -58,6 +58,8 @@ Other changes:
   processing errors outside of the NewFrame()..EndFrame() scope. (#1651)
 - Tables: fixed SetNextWindowScroll() value being ignored by BeginTable() during
   the first frame or when scrolling flags have changed. (#8196)
+- InputText: reactivating last activated InputText() doesn't restore horizontal scrolling
+  (which was disabled during deactivation anyway).
 - Misc: changed embedded ProggyClean encoding to save a bit of binary space (~12kb to 9.5kb).
 - Misc: added IMGUI_DISABLE_DEFAULT_FONT to strip embedded font from binary. (#8161)
   [@demonese]
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index cf6891ea18d7..65a58d53ba48 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4537,6 +4537,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         state->TextA.resize(buf_size + 1);          // we use +1 to make sure that .Data is always pointing to at least an empty string.
         state->TextLen = (int)strlen(buf);
         memcpy(state->TextA.Data, buf, state->TextLen + 1);
+        state->Scroll = ImVec2(0.0f, 0.0f);
 
         if (recycle_state)
         {
@@ -4546,7 +4547,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         }
         else
         {
-            state->Scroll = ImVec2(0.0f, 0.0f);
             stb_textedit_initialize_state(state->Stb, !is_multiline);
         }
 
@@ -5287,8 +5287,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
 
         if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
         {
+            const ImVec2 draw_scroll = /*state ? ImVec2(state->Scroll.x, 0.0f) :*/ ImVec2(0.0f, 0.0f); // Preserve scroll when inactive?
             ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
-            draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
+            draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
         }
     }
 

From d78e823449f491dbd3cd158b72fdee7cd4d72aa6 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 9 Dec 2024 14:31:28 +0100
Subject: [PATCH 301/548] InputText: added ImGuiInputTextFlags_ElideLeft.
 (#1442, #1440, #4391, #7208, #8216)

---
 docs/CHANGELOG.txt |  3 +++
 imgui.h            | 17 ++++++++++-------
 imgui_demo.cpp     | 10 ++++++++++
 imgui_widgets.cpp  |  9 +++++++++
 4 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 42026c9cd514..70dfb7b9d97f 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -58,6 +58,9 @@ Other changes:
   processing errors outside of the NewFrame()..EndFrame() scope. (#1651)
 - Tables: fixed SetNextWindowScroll() value being ignored by BeginTable() during
   the first frame or when scrolling flags have changed. (#8196)
+- InputText: added ImGuiInputTextFlags_ElideLeft to elide left side and ensure right side
+  of contents is visible when whole text is not fitting (useful for paths/filenames).
+  (#1442, #1440, #4391, #7208, #8216) [@kucoman, @ocornut]
 - InputText: reactivating last activated InputText() doesn't restore horizontal scrolling
   (which was disabled during deactivation anyway).
 - Misc: changed embedded ProggyClean encoding to save a bit of binary space (~12kb to 9.5kb).
diff --git a/imgui.h b/imgui.h
index b86c7d4e5d89..c9b42e4c7511 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.6 WIP"
-#define IMGUI_VERSION_NUM   19152
+#define IMGUI_VERSION_NUM   19153
 #define IMGUI_HAS_TABLE
 
 /*
@@ -1171,13 +1171,16 @@ enum ImGuiInputTextFlags_
     ImGuiInputTextFlags_NoHorizontalScroll  = 1 << 15,  // Disable following the cursor horizontally
     ImGuiInputTextFlags_NoUndoRedo          = 1 << 16,  // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
 
+    // Elide display / Alignment
+    ImGuiInputTextFlags_ElideLeft			= 1 << 17,	// When text doesn't fit, elide left side to ensure right side stays visible. Useful for path/filenames. Single-line only!
+
     // Callback features
-    ImGuiInputTextFlags_CallbackCompletion  = 1 << 17,  // Callback on pressing TAB (for completion handling)
-    ImGuiInputTextFlags_CallbackHistory     = 1 << 18,  // Callback on pressing Up/Down arrows (for history handling)
-    ImGuiInputTextFlags_CallbackAlways      = 1 << 19,  // Callback on each iteration. User code may query cursor position, modify text buffer.
-    ImGuiInputTextFlags_CallbackCharFilter  = 1 << 20,  // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
-    ImGuiInputTextFlags_CallbackResize      = 1 << 21,  // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
-    ImGuiInputTextFlags_CallbackEdit        = 1 << 22,  // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
+    ImGuiInputTextFlags_CallbackCompletion  = 1 << 18,  // Callback on pressing TAB (for completion handling)
+    ImGuiInputTextFlags_CallbackHistory     = 1 << 19,  // Callback on pressing Up/Down arrows (for history handling)
+    ImGuiInputTextFlags_CallbackAlways      = 1 << 20,  // Callback on each iteration. User code may query cursor position, modify text buffer.
+    ImGuiInputTextFlags_CallbackCharFilter  = 1 << 21,  // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
+    ImGuiInputTextFlags_CallbackResize      = 1 << 22,  // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
+    ImGuiInputTextFlags_CallbackEdit        = 1 << 23,  // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
 
     // Obsolete names
     //ImGuiInputTextFlags_AlwaysInsertMode  = ImGuiInputTextFlags_AlwaysOverwrite   // [renamed in 1.82] name was not matching behavior
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 5efbe6304538..ae91761a3db2 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1830,6 +1830,16 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
             ImGui::TreePop();
         }
 
+        IMGUI_DEMO_MARKER("Widgets/Text Input/Eliding, Alignment");
+        if (ImGui::TreeNode("Eliding, Alignment"))
+        {
+            static char buf1[128] = "/path/to/some/folder/with/long/filename.cpp";
+            static ImGuiInputTextFlags flags = ImGuiInputTextFlags_ElideLeft;
+            ImGui::CheckboxFlags("ImGuiInputTextFlags_ElideLeft", &flags, ImGuiInputTextFlags_ElideLeft);
+            ImGui::InputText("Path", buf1, IM_ARRAYSIZE(buf1), flags);
+            ImGui::TreePop();
+        }
+
         IMGUI_DEMO_MARKER("Widgets/Text Input/Miscellaneous");
         if (ImGui::TreeNode("Miscellaneous"))
         {
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 65a58d53ba48..4a579d4e3f15 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4403,6 +4403,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     IM_ASSERT(buf != NULL && buf_size >= 0);
     IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline)));        // Can't use both together (they both use up/down keys)
     IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key)
+    IM_ASSERT(!((flags & ImGuiInputTextFlags_ElideLeft) && (flags & ImGuiInputTextFlags_Multiline)));               // Multiline will not work with left-trimming
 
     ImGuiContext& g = *GImGui;
     ImGuiIO& io = g.IO;
@@ -4537,7 +4538,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         state->TextA.resize(buf_size + 1);          // we use +1 to make sure that .Data is always pointing to at least an empty string.
         state->TextLen = (int)strlen(buf);
         memcpy(state->TextA.Data, buf, state->TextLen + 1);
+
+        // Find initial scroll position for right alignment
         state->Scroll = ImVec2(0.0f, 0.0f);
+        if (flags & ImGuiInputTextFlags_ElideLeft)
+            state->Scroll.x += ImMax(0.0f, CalcTextSize(buf).x - frame_size.x + style.FramePadding.x * 2.0f);
 
         if (recycle_state)
         {
@@ -5287,6 +5292,10 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
 
         if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
         {
+            // Find render position for right alignment
+            if (flags & ImGuiInputTextFlags_ElideLeft)
+                draw_pos.x = ImMin(draw_pos.x, frame_bb.Max.x - CalcTextSize(buf_display, NULL).x - style.FramePadding.x);
+
             const ImVec2 draw_scroll = /*state ? ImVec2(state->Scroll.x, 0.0f) :*/ ImVec2(0.0f, 0.0f); // Preserve scroll when inactive?
             ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
             draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);

From c3ffd4c53e90276f5ad1504553bf5c628f15c9ec Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 11 Dec 2024 12:13:28 +0100
Subject: [PATCH 302/548] Misc: Added IMGUI_USE_LEGACY_CRC32_ADLER to use old
 tables. (#8169, #4933)

---
 docs/CHANGELOG.txt | 11 ++++++++---
 imconfig.h         |  3 +++
 imgui.cpp          | 26 ++++++++++++++++++++++++--
 imgui.h            |  2 +-
 imgui_internal.h   |  2 +-
 5 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 70dfb7b9d97f..7ef8580b8157 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -48,9 +48,14 @@ Breaking changes:
   - We provide convenience legacy fields to pass a single descriptor,
     matching the old API, but upcoming features will want multiple.
   - Legacy ImGui_ImplDX12_Init() signature is still supported (will obsolete).
-- Misc: changed CRC32 table to use CRC32c polynomial in order to be compatible
-  with the result of SSE 4.2 instructions. As a result, old .ini data may be
-  partially lost. (#8169, #4933) [@Teselka]
+- Misc: changed CRC32 table from CRC32-adler to CRC32c polynomial in order to 
+  be compatible with the result of SSE 4.2 instructions. (#8169, #4933) [@Teselka]
+  - As a result, some .ini data may be partially lost when storing checksums
+    (docking and tables information particularly). 
+  - Because some users have crafted and storing .ini data as a way to workaround 
+    limitations of the docking API, we are providing a '#define IMGUI_USE_LEGACY_CRC32_ADLER'
+    compile-time option to keep using old CRC32 tables if you cannot afford invalidating
+    old .ini data.
 
 Other changes:
 
diff --git a/imconfig.h b/imconfig.h
index 6790f147ac85..8f8bc3b9a9bb 100644
--- a/imconfig.h
+++ b/imconfig.h
@@ -62,6 +62,9 @@
 //---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support.
 //#define IMGUI_USE_BGRA_PACKED_COLOR
 
+//---- Use legacy CRC32-adler tables (used before 1.91.6), in order to preserve old .ini data that you cannot afford to invalidate.
+//#define IMGUI_USE_LEGACY_CRC32_ADLER
+
 //---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
 //#define IMGUI_USE_WCHAR32
 
diff --git a/imgui.cpp b/imgui.cpp
index 5833691dbf14..e4199c2b07af 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -429,7 +429,9 @@ 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.
 
- - 2024/11/27 (1.91.6) - changed CRC32 table to use CRC32c polynomial in order to be compatible with the result of SSE 4.2 instructions. As a result, old .ini data may be partially lost.
+ - 2024/11/27 (1.91.6) - changed CRC32 table from CRC32-adler to CRC32c polynomial in order to be compatible with the result of SSE 4.2 instructions.
+                         As a result, old .ini data may be partially lost (docking and tables information particularly).
+                         Because some users have crafted and storing .ini data as a way to workaround limitations of the docking API, we are providing a '#define IMGUI_USE_LEGACY_CRC32_ADLER' compile-time option to keep using old CRC32 tables if you cannot afford invalidating old .ini data.
  - 2024/11/06 (1.91.5) - commented/obsoleted out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before)
                             - io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022).
                             - io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022).
@@ -2154,9 +2156,28 @@ void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end,
 // CRC32 needs a 1KB lookup table (not cache friendly)
 // Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily:
 // - avoid an unnecessary branch/memory tap, - keep the ImHashXXX functions usable by static constructors, - make it thread-safe.
-// On 2024/11/27 this was changed from crc32-adler to crc32c (polynomial 0x1EDC6F41), which invalidated some hashes stored in .ini files.
 static const ImU32 GCrc32LookupTable[256] =
 {
+#ifdef IMGUI_USE_LEGACY_CRC32_ADLER
+    // Legacy CRC32-adler table used pre 1.91.6 (before 2024/11/27). Only use if you cannot afford invalidating old .ini data.
+    0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
+    0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
+    0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
+    0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
+    0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
+    0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
+    0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
+    0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
+    0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
+    0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
+    0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
+    0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
+    0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
+    0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
+    0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
+    0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
+#else
+    // CRC32c table compatible with SSE 4.2 instructions
     0x00000000,0xF26B8303,0xE13B70F7,0x1350F3F4,0xC79A971F,0x35F1141C,0x26A1E7E8,0xD4CA64EB,0x8AD958CF,0x78B2DBCC,0x6BE22838,0x9989AB3B,0x4D43CFD0,0xBF284CD3,0xAC78BF27,0x5E133C24,
     0x105EC76F,0xE235446C,0xF165B798,0x030E349B,0xD7C45070,0x25AFD373,0x36FF2087,0xC494A384,0x9A879FA0,0x68EC1CA3,0x7BBCEF57,0x89D76C54,0x5D1D08BF,0xAF768BBC,0xBC267848,0x4E4DFB4B,
     0x20BD8EDE,0xD2D60DDD,0xC186FE29,0x33ED7D2A,0xE72719C1,0x154C9AC2,0x061C6936,0xF477EA35,0xAA64D611,0x580F5512,0x4B5FA6E6,0xB93425E5,0x6DFE410E,0x9F95C20D,0x8CC531F9,0x7EAEB2FA,
@@ -2173,6 +2194,7 @@ static const ImU32 GCrc32LookupTable[256] =
     0xD3D3E1AB,0x21B862A8,0x32E8915C,0xC083125F,0x144976B4,0xE622F5B7,0xF5720643,0x07198540,0x590AB964,0xAB613A67,0xB831C993,0x4A5A4A90,0x9E902E7B,0x6CFBAD78,0x7FAB5E8C,0x8DC0DD8F,
     0xE330A81A,0x115B2B19,0x020BD8ED,0xF0605BEE,0x24AA3F05,0xD6C1BC06,0xC5914FF2,0x37FACCF1,0x69E9F0D5,0x9B8273D6,0x88D28022,0x7AB90321,0xAE7367CA,0x5C18E4C9,0x4F48173D,0xBD23943E,
     0xF36E6F75,0x0105EC76,0x12551F82,0xE03E9C81,0x34F4F86A,0xC69F7B69,0xD5CF889D,0x27A40B9E,0x79B737BA,0x8BDCB4B9,0x988C474D,0x6AE7C44E,0xBE2DA0A5,0x4C4623A6,0x5F16D052,0xAD7D5351
+#endif
 };
 #endif
 
diff --git a/imgui.h b/imgui.h
index c9b42e4c7511..8b5c358a9fc5 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.6 WIP"
-#define IMGUI_VERSION_NUM   19153
+#define IMGUI_VERSION_NUM   19154
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index cccecf702943..379f6cb14c13 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -67,7 +67,7 @@ Index of this file:
 #endif
 #endif
 // Emscripten has partial SSE 4.2 support where _mm_crc32_u32 is not available. See https://emscripten.org/docs/porting/simd.html#id11 and #8213
-#if defined(IMGUI_ENABLE_SSE4_2) && !defined(__EMSCRIPTEN__)
+#if defined(IMGUI_ENABLE_SSE4_2) && !defined(IMGUI_USE_LEGACY_CRC32_ADLER) && !defined(__EMSCRIPTEN__)
 #define IMGUI_ENABLE_SSE4_2_CRC
 #endif
 

From 2ca83f0bc72fcaca5631766b5fcb05fd3d0e102d Mon Sep 17 00:00:00 2001
From: Stewart Mccready 
Date: Wed, 11 Dec 2024 13:14:46 +0000
Subject: [PATCH 303/548] Fixed missing symbols when using
 IMGUI_DISABLE_DEMO_WINDOWS (e.g. with ImPlot) (#8221)

---
 imgui_demo.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index ae91761a3db2..9e5c03fa37c7 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -10397,6 +10397,8 @@ void ImGui::ShowAboutWindow(bool*) {}
 void ImGui::ShowDemoWindow(bool*) {}
 void ImGui::ShowUserGuide() {}
 void ImGui::ShowStyleEditor(ImGuiStyle*) {}
+bool ImGui::ShowStyleSelector(const char* label) { return false; }
+void ImGui::ShowFontSelector(const char* label) {}
 
 #endif
 

From 993fa347495860ed44b83574254ef2a317d0c14f Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 11 Dec 2024 14:17:45 +0100
Subject: [PATCH 304/548] Version 1.91.6

---
 docs/CHANGELOG.txt | 14 +++++++-------
 docs/README.md     |  2 +-
 imgui.cpp          |  6 +++---
 imgui.h            | 16 ++++++++--------
 imgui_demo.cpp     |  2 +-
 imgui_draw.cpp     |  4 ++--
 imgui_internal.h   | 10 ++++------
 imgui_tables.cpp   |  2 +-
 imgui_widgets.cpp  |  8 ++++----
 9 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 7ef8580b8157..2d04ee093390 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -36,7 +36,7 @@ HOW TO UPDATE?
 - Please report any issue!
 
 -----------------------------------------------------------------------
- VERSION 1.91.6 WIP (In Progress)
+ VERSION 1.91.6 (Released 2024-12-11)
 -----------------------------------------------------------------------
 
 Breaking changes:
@@ -48,18 +48,18 @@ Breaking changes:
   - We provide convenience legacy fields to pass a single descriptor,
     matching the old API, but upcoming features will want multiple.
   - Legacy ImGui_ImplDX12_Init() signature is still supported (will obsolete).
-- Misc: changed CRC32 table from CRC32-adler to CRC32c polynomial in order to 
+- Misc: changed CRC32 table from CRC32-adler to CRC32c polynomial in order to
   be compatible with the result of SSE 4.2 instructions. (#8169, #4933) [@Teselka]
   - As a result, some .ini data may be partially lost when storing checksums
-    (docking and tables information particularly). 
-  - Because some users have crafted and storing .ini data as a way to workaround 
+    (docking and tables information particularly).
+  - Because some users have crafted and storing .ini data as a way to workaround
     limitations of the docking API, we are providing a '#define IMGUI_USE_LEGACY_CRC32_ADLER'
     compile-time option to keep using old CRC32 tables if you cannot afford invalidating
     old .ini data.
 
 Other changes:
 
-- Error Handling: fixed cases where recoverable error handling would crash when 
+- Error Handling: fixed cases where recoverable error handling would crash when
   processing errors outside of the NewFrame()..EndFrame() scope. (#1651)
 - Tables: fixed SetNextWindowScroll() value being ignored by BeginTable() during
   the first frame or when scrolling flags have changed. (#8196)
@@ -71,13 +71,13 @@ Other changes:
 - Misc: changed embedded ProggyClean encoding to save a bit of binary space (~12kb to 9.5kb).
 - Misc: added IMGUI_DISABLE_DEFAULT_FONT to strip embedded font from binary. (#8161)
   [@demonese]
-- Tools: binary_to_compressed_c: added -u8/-u32/-base85 export options.
 - Demo: example tree used by Property Editor & Selection demos properly freed
   on application closure. (#8158) [@Legulysse]
 - Fonts: fixed AddCustomRect() not being packed with TexGlyphPadding + not accounted
   for surface area used to determine best-guess texture size. (#8107) [@YarikTH, @ocornut]
 - Misc: use SSE 4.2 crc32 instructions when available. (#8169, #4933) [@Teselka]
-- Backends: DirectX12: Let user specifies the DepthStencilView format by setting 
+- Tools: binary_to_compressed_c: added -u8/-u32/-base85 export options.
+- Backends: DirectX12: Let user specifies the DepthStencilView format by setting
   ImGui_ImplDX12_InitInfo::DSVFormat. (#8217) [@bmarques1995]
 - Backends: Vulkan: Make user-provided descriptor pool optional. As a convenience,
   when setting init_info->DescriptorPoolSize then the backend will create and manage
diff --git a/docs/README.md b/docs/README.md
index c47f03b9bc5c..388d8eac63af 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -110,7 +110,7 @@ Reading the changelogs is a good way to keep up to date with the things Dear ImG
 Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing a variety of features and examples. The code is always available for reference in `imgui_demo.cpp`. [Here's how the demo looks](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png).
 
 You should be able to build the examples from sources. If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
-- [imgui-demo-binaries-20240105.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20240105.zip) (Windows, 1.90.1 WIP, built 2024/01/05, master) or [older binaries](https://www.dearimgui.com/binaries).
+- [imgui-demo-binaries-20241211.zip](https://www.dearimgui.com/binaries/imgui-demo-binaries-20241211.zip) (Windows, 1.91.6, built 2024/11/11, master) or [older binaries](https://www.dearimgui.com/binaries).
 
 The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at a different scale and scale your style with `style.ScaleAllSizes()` (see [FAQ](https://www.dearimgui.com/faq)).
 
diff --git a/imgui.cpp b/imgui.cpp
index e4199c2b07af..26e56b80407e 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6 WIP
+// dear imgui, v1.91.6
 // (main code and documentation)
 
 // Help:
@@ -4748,15 +4748,15 @@ void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr
     }
     if (size != (size_t)-1)
     {
+        //printf("[%05d] MemAlloc(%d) -> 0x%p\n", frame_count, (int)size, ptr);
         entry->AllocCount++;
         info->TotalAllocCount++;
-        //printf("[%05d] MemAlloc(%d) -> 0x%p\n", frame_count, size, ptr);
     }
     else
     {
+        //printf("[%05d] MemFree(0x%p)\n", frame_count, ptr);
         entry->FreeCount++;
         info->TotalFreeCount++;
-        //printf("[%05d] MemFree(0x%p)\n", frame_count, ptr);
     }
 }
 
diff --git a/imgui.h b/imgui.h
index 8b5c358a9fc5..64be995cb21a 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6 WIP
+// dear imgui, v1.91.6
 // (headers)
 
 // Help:
@@ -28,8 +28,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.6 WIP"
-#define IMGUI_VERSION_NUM   19154
+#define IMGUI_VERSION       "1.91.6"
+#define IMGUI_VERSION_NUM   19160
 #define IMGUI_HAS_TABLE
 
 /*
@@ -3429,24 +3429,24 @@ struct ImFontAtlas
 // ImFontAtlas automatically loads a default embedded font for you when you call GetTexDataAsAlpha8() or GetTexDataAsRGBA32().
 struct ImFont
 {
-    // Members: Hot ~20/24 bytes (for CalcTextSize)
+    // [Internal] Members: Hot ~20/24 bytes (for CalcTextSize)
     ImVector             IndexAdvanceX;      // 12-16 // out //            // Sparse. Glyphs->AdvanceX in a directly indexable way (cache-friendly for CalcTextSize functions which only this info, and are often bottleneck in large UI).
     float                       FallbackAdvanceX;   // 4     // out // = FallbackGlyph->AdvanceX
     float                       FontSize;           // 4     // in  //            // Height of characters/line, set during loading (don't change after loading)
 
-    // Members: Hot ~28/40 bytes (for CalcTextSize + render loop)
+    // [Internal] Members: Hot ~28/40 bytes (for RenderText loop)
     ImVector           IndexLookup;        // 12-16 // out //            // Sparse. Index glyphs by Unicode code-point.
     ImVector       Glyphs;             // 12-16 // out //            // All glyphs.
     const ImFontGlyph*          FallbackGlyph;      // 4-8   // out // = FindGlyph(FontFallbackChar)
 
-    // Members: Cold ~32/40 bytes
+    // [Internal] Members: Cold ~32/40 bytes
     // Conceptually ConfigData[] is the list of font sources merged to create this font.
     ImFontAtlas*                ContainerAtlas;     // 4-8   // out //            // What we has been loaded into
     const ImFontConfig*         ConfigData;         // 4-8   // in  //            // Pointer within ContainerAtlas->ConfigData to ConfigDataCount instances
     short                       ConfigDataCount;    // 2     // in  // ~ 1        // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont.
-    ImWchar                     FallbackChar;       // 2     // out // = FFFD/'?' // Character used if a glyph isn't found.
-    ImWchar                     EllipsisChar;       // 2     // out // = '...'/'.'// Character used for ellipsis rendering.
     short                       EllipsisCharCount;  // 1     // out // 1 or 3
+    ImWchar                     EllipsisChar;       // 2-4   // out // = '...'/'.'// Character used for ellipsis rendering.
+    ImWchar                     FallbackChar;       // 2-4   // out // = FFFD/'?' // Character used if a glyph isn't found.
     float                       EllipsisWidth;      // 4     // out               // Width
     float                       EllipsisCharStep;   // 4     // out               // Step between characters when EllipsisCount > 0
     bool                        DirtyLookupTables;  // 1     // out //
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 9e5c03fa37c7..a9f9d832ba11 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6 WIP
+// dear imgui, v1.91.6
 // (demo code)
 
 // Help:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 631472a71dd6..9ae0162e42ff 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6 WIP
+// dear imgui, v1.91.6
 // (drawing and font code)
 
 /*
@@ -396,7 +396,7 @@ void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
 
 ImDrawList::ImDrawList(ImDrawListSharedData* shared_data)
 {
-    memset(this, 0, sizeof(*this)); 
+    memset(this, 0, sizeof(*this));
     _Data = shared_data;
 }
 
diff --git a/imgui_internal.h b/imgui_internal.h
index 379f6cb14c13..45715cc31c1e 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6 WIP
+// dear imgui, v1.91.6
 // (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.
@@ -778,11 +778,9 @@ struct IMGUI_API ImDrawListSharedData
     float           CircleSegmentMaxError;      // Number of circle segments to use per pixel of radius for AddCircle() etc
     ImVec4          ClipRectFullscreen;         // Value for PushClipRectFullscreen()
     ImDrawListFlags InitialFlags;               // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
+    ImVector TempBuffer;                // Temporary write buffer
 
-    // [Internal] Temp write buffer
-    ImVector TempBuffer;
-
-    // [Internal] Lookup tables
+    // Lookup tables
     ImVec2          ArcFastVtx[IM_DRAWLIST_ARCFAST_TABLE_SIZE]; // Sample points on the quarter of the circle.
     float           ArcFastRadiusCutoff;                        // Cutoff radius after which arc drawing will fallback to slower PathArcTo()
     ImU8            CircleSegmentCounts[64];    // Precomputed segment count for given radius before we calculate it dynamically (to avoid calculation overhead)
@@ -3392,7 +3390,7 @@ namespace ImGui
     IMGUI_API void          TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
     IMGUI_API bool          ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
     IMGUI_API bool          ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
-    IMGUI_API bool          ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
+    IMGUI_API bool          ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0);
     IMGUI_API void          SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f);
     IMGUI_API void          SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width);
     IMGUI_API bool          CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index db34aa347d00..f4e76225a828 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6 WIP
+// dear imgui, v1.91.6
 // (tables and columns code)
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 4a579d4e3f15..3fc500ab83f9 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6 WIP
+// dear imgui, v1.91.6
 // (widgets code)
 
 /*
@@ -1073,7 +1073,7 @@ void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const I
     window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
 }
 
-bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
+bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
 {
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = GetCurrentWindow();
@@ -1095,7 +1095,7 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& imag
     RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
     if (bg_col.w > 0.0f)
         window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
-    window->DrawList->AddImage(texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
+    window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
 
     return pressed;
 }
@@ -1114,7 +1114,7 @@ bool ImGui::ImageButton(const char* str_id, ImTextureID user_texture_id, const I
 
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
 // Legacy API obsoleted in 1.89. Two differences with new ImageButton()
-// - old ImageButton() used ImTextureId as item id (created issue with multiple buttons with same image, transient texture id values, opaque computation of ID)
+// - old ImageButton() used ImTextureID as item id (created issue with multiple buttons with same image, transient texture id values, opaque computation of ID)
 // - new ImageButton() requires an explicit 'const char* str_id'
 // - old ImageButton() had frame_padding' override argument.
 // - new ImageButton() always use style.FramePadding.

From f25665f36003abb5fa856b040b312344483f0031 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 11 Dec 2024 15:37:16 +0100
Subject: [PATCH 305/548] Version 1.91.7 WIP

---
 docs/CHANGELOG.txt | 11 +++++++++++
 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, 20 insertions(+), 9 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 2d04ee093390..68f5d8d4c34f 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -35,10 +35,21 @@ 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.7 WIP (In Progress)
+-----------------------------------------------------------------------
+
+Breaking changes:
+
+Other changes:
+
+
 -----------------------------------------------------------------------
  VERSION 1.91.6 (Released 2024-12-11)
 -----------------------------------------------------------------------
 
+Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.6
+
 Breaking changes:
 
 - Backends: DX12: Changed ImGui_ImplDX12_Init() signature to take a
diff --git a/imgui.cpp b/imgui.cpp
index 26e56b80407e..7325c1952795 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6
+// dear imgui, v1.91.7 WIP
 // (main code and documentation)
 
 // Help:
diff --git a/imgui.h b/imgui.h
index 64be995cb21a..0a61b1deaabc 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6
+// dear imgui, v1.91.7 WIP
 // (headers)
 
 // Help:
@@ -28,8 +28,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.6"
-#define IMGUI_VERSION_NUM   19160
+#define IMGUI_VERSION       "1.91.7 WIP"
+#define IMGUI_VERSION_NUM   19161
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index a9f9d832ba11..6010aad4409c 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6
+// dear imgui, v1.91.7 WIP
 // (demo code)
 
 // Help:
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 9ae0162e42ff..b231764b6e2e 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6
+// dear imgui, v1.91.7 WIP
 // (drawing and font code)
 
 /*
diff --git a/imgui_internal.h b/imgui_internal.h
index 45715cc31c1e..1f7426696b22 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6
+// dear imgui, v1.91.7 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 f4e76225a828..7dd97c6f214a 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6
+// dear imgui, v1.91.7 WIP
 // (tables and columns code)
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 3fc500ab83f9..2d0fed4e0a04 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1,4 +1,4 @@
-// dear imgui, v1.91.6
+// dear imgui, v1.91.7 WIP
 // (widgets code)
 
 /*

From e487eb9da0805519261687339da2e77686ed9efc Mon Sep 17 00:00:00 2001
From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com>
Date: Wed, 11 Dec 2024 13:30:35 +0000
Subject: [PATCH 306/548] Backends: Vulkan: Fixed setting
 VkSwapchainCreateInfoKHR::preTransform for platforms not supporting
 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222)

---
 backends/imgui_impl_vulkan.cpp | 11 ++++++-----
 docs/CHANGELOG.txt             |  3 +++
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp
index b419703048e0..1de6e2353879 100644
--- a/backends/imgui_impl_vulkan.cpp
+++ b/backends/imgui_impl_vulkan.cpp
@@ -26,6 +26,7 @@
 
 // CHANGELOG
 // (minor and older changes stripped away, please see git history for details)
+//  2024-12-11: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222)
 //  2024-11-27: Vulkan: Make user-provided descriptor pool optional. As a convenience, when setting init_info->DescriptorPoolSize the backend will create one itself. (#8172, #4867)
 //  2024-10-07: Vulkan: Changed default texture sampler to Clamp instead of Repeat/Wrap.
 //  2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
@@ -1426,6 +1427,10 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
 
     // Create Swapchain
     {
+        VkSurfaceCapabilitiesKHR cap;
+        err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap);
+        check_vk_result(err);
+
         VkSwapchainCreateInfoKHR info = {};
         info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
         info.surface = wd->Surface;
@@ -1435,19 +1440,15 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
         info.imageArrayLayers = 1;
         info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
         info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;           // Assume that graphics family == present family
-        info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+        info.preTransform = (cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform;
         info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
         info.presentMode = wd->PresentMode;
         info.clipped = VK_TRUE;
         info.oldSwapchain = old_swapchain;
-        VkSurfaceCapabilitiesKHR cap;
-        err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap);
-        check_vk_result(err);
         if (info.minImageCount < cap.minImageCount)
             info.minImageCount = cap.minImageCount;
         else if (cap.maxImageCount != 0 && info.minImageCount > cap.maxImageCount)
             info.minImageCount = cap.maxImageCount;
-
         if (cap.currentExtent.width == 0xffffffff)
         {
             info.imageExtent.width = wd->Width = w;
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 68f5d8d4c34f..d95012d9f72b 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,9 @@ Breaking changes:
 
 Other changes:
 
+- Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for
+  platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF]
+
 
 -----------------------------------------------------------------------
  VERSION 1.91.6 (Released 2024-12-11)

From 1d069cf43527bdf81b42289f7c385efac129c3a0 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 11 Dec 2024 16:43:29 +0100
Subject: [PATCH 307/548] Fonts: store 0 for unset EllipsisChar/FallbackChar.
 Pull config in BuildLookupTable().

---
 imgui.h        |  2 +-
 imgui_draw.cpp | 19 ++++++++-----------
 2 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/imgui.h b/imgui.h
index 0a61b1deaabc..7fbb610f2dbe 100644
--- a/imgui.h
+++ b/imgui.h
@@ -3244,7 +3244,7 @@ struct ImFontConfig
     unsigned int    FontBuilderFlags;       // 0        // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure.
     float           RasterizerMultiply;     // 1.0f     // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future.
     float           RasterizerDensity;      // 1.0f     // DPI scale for rasterization, not altering other font metrics: make it easy to swap between e.g. a 100% and a 400% fonts for a zooming display. IMPORTANT: If you increase this it is expected that you increase font scale accordingly, otherwise quality may look lowered.
-    ImWchar         EllipsisChar;           // -1       // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
+    ImWchar         EllipsisChar;           // 0        // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
 
     // [Internal]
     char            Name[40];               // Name (strictly to ease debugging)
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index b231764b6e2e..f51fff3a6357 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -2377,7 +2377,7 @@ ImFontConfig::ImFontConfig()
     GlyphMaxAdvanceX = FLT_MAX;
     RasterizerMultiply = 1.0f;
     RasterizerDensity = 1.0f;
-    EllipsisChar = (ImWchar)-1;
+    EllipsisChar = 0;
 }
 
 //-----------------------------------------------------------------------------
@@ -2564,9 +2564,6 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
     // - We may support it better later and remove this rounding.
     new_font_cfg.SizePixels = ImTrunc(new_font_cfg.SizePixels);
 
-    if (new_font_cfg.DstFont->EllipsisChar == (ImWchar)-1)
-        new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar;
-
     // Pointers to ConfigData and BuilderData are otherwise dangling
     ImFontAtlasUpdateConfigDataPointers(this);
 
@@ -3635,8 +3632,8 @@ ImFont::ImFont()
 {
     FontSize = 0.0f;
     FallbackAdvanceX = 0.0f;
-    FallbackChar = (ImWchar)-1;
-    EllipsisChar = (ImWchar)-1;
+    FallbackChar = 0;
+    EllipsisChar = 0;
     EllipsisWidth = EllipsisCharStep = 0.0f;
     EllipsisCharCount = 0;
     FallbackGlyph = NULL;
@@ -3675,7 +3672,7 @@ static ImWchar FindFirstExistingGlyph(ImFont* font, const ImWchar* candidate_cha
     for (int n = 0; n < candidate_chars_count; n++)
         if (font->FindGlyphNoFallback(candidate_chars[n]) != NULL)
             return candidate_chars[n];
-    return (ImWchar)-1;
+    return 0;
 }
 
 void ImFont::BuildLookupTable()
@@ -3742,17 +3739,17 @@ void ImFont::BuildLookupTable()
     // Setup Ellipsis character. It is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis).
     // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character.
     // FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots.
-    const ImWchar ellipsis_chars[] = { (ImWchar)0x2026, (ImWchar)0x0085 };
+    const ImWchar ellipsis_chars[] = { ConfigData->EllipsisChar, (ImWchar)0x2026, (ImWchar)0x0085 };
     const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E };
-    if (EllipsisChar == (ImWchar)-1)
+    if (EllipsisChar == 0)
         EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars));
     const ImWchar dot_char = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars));
-    if (EllipsisChar != (ImWchar)-1)
+    if (EllipsisChar != 0)
     {
         EllipsisCharCount = 1;
         EllipsisWidth = EllipsisCharStep = FindGlyph(EllipsisChar)->X1;
     }
-    else if (dot_char != (ImWchar)-1)
+    else if (dot_char != 0)
     {
         const ImFontGlyph* glyph = FindGlyph(dot_char);
         EllipsisChar = dot_char;

From 4cc464eadc12a158fb7ccd9b2843277ee894f163 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 12 Dec 2024 15:14:14 +0100
Subject: [PATCH 308/548] BeginListBox(): Comments (#8220)

---
 imgui.h           |  1 +
 imgui_widgets.cpp | 11 +++--------
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/imgui.h b/imgui.h
index 7fbb610f2dbe..69f106dd6e90 100644
--- a/imgui.h
+++ b/imgui.h
@@ -692,6 +692,7 @@ namespace ImGui
 
     // Widgets: List Boxes
     // - This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
+    // - If you don't need a label you can probably simply use BeginChild() with the ImGuiChildFlags_FrameStyle flag for the same result.
     // - You can submit contents and manage your selection state however you want it, by creating e.g. Selectable() or any other items.
     // - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analoguous to how Combos are created.
     // - Choose frame width:   size.x > 0.0f: custom  /  size.x < 0.0f or -FLT_MIN: right-align   /  size.x = 0.0f (default): use current ItemWidth
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 2d0fed4e0a04..9f4baef0fdf9 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -8206,15 +8206,10 @@ void ImGuiSelectionExternalStorage::ApplyRequests(ImGuiMultiSelectIO* ms_io)
 //-------------------------------------------------------------------------
 
 // This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
-// This handle some subtleties with capturing info from the label, but for 99% uses it could essentially be rewritten as:
-//    if (ImGui::BeginChild("...", ImVec2(ImGui::CalcItemWidth(), ImGui::GetTextLineHeight() * 7.5f), ImGuiChildFlags_FrameStyle))
-//        { .... }
-//    ImGui::EndChild();
-//    ImGui::SameLine();
-//    ImGui::AlignTextToFramePadding();
-//    ImGui::Text("Label");
+// This handle some subtleties with capturing info from the label.
+// If you don't need a label you can pretty much directly use ImGui::BeginChild() with ImGuiChildFlags_FrameStyle.
 // Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty"
-// Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.25 * item_height).
+// Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.5f * item_height).
 bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
 {
     ImGuiContext& g = *GImGui;

From f9f4e22f6f7d08e31152e9219d8533e4c265f4de Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 12 Dec 2024 16:40:08 +0100
Subject: [PATCH 309/548] InputText: some tidying up. (#7925)

---
 imgui_internal.h  |  5 +++--
 imgui_widgets.cpp | 49 +++++++++++++++++------------------------------
 2 files changed, 21 insertions(+), 33 deletions(-)

diff --git a/imgui_internal.h b/imgui_internal.h
index 1f7426696b22..fed655e03a42 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1121,6 +1121,7 @@ struct IMGUI_API ImGuiInputTextState
 {
     ImGuiContext*           Ctx;                    // parent UI context (needs to be set explicitly by parent).
     ImStbTexteditState*     Stb;                    // State for stb_textedit.h
+    ImGuiInputTextFlags     Flags;                  // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
     ImGuiID                 ID;                     // widget id owning the text state
     int                     TextLen;                // UTF-8 length of the string in TextA (in bytes)
     ImVector          TextA;                  // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1).
@@ -1132,9 +1133,8 @@ struct IMGUI_API ImGuiInputTextState
     bool                    CursorFollow;           // set when we want scrolling to follow the current cursor position (not always!)
     bool                    SelectedAllMouseLock;   // after a double-click to select all, we ignore further mouse drags to update selection
     bool                    Edited;                 // edited this frame
-    ImGuiInputTextFlags     Flags;                  // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
     bool                    ReloadUserBuf;          // force a reload of user buf so it may be modified externally. may be automatic in future version.
-    int                     ReloadSelectionStart;   // POSITIONS ARE IN IMWCHAR units *NOT* UTF-8 this is why this is not exposed yet.
+    int                     ReloadSelectionStart;
     int                     ReloadSelectionEnd;
 
     ImGuiInputTextState();
@@ -1159,6 +1159,7 @@ struct IMGUI_API ImGuiInputTextState
     //   strcpy(my_buf, "hello");
     //   if (ImGuiInputTextState* state = ImGui::GetInputTextState(id)) // id may be ImGui::GetItemID() is last item
     //       state->ReloadUserBufAndSelectAll();
+    // THIS CURRENTLY RESETS THE UNDO STACK.
     void        ReloadUserBufAndSelectAll();
     void        ReloadUserBufAndKeepSelection();
     void        ReloadUserBufAndMoveToEnd();
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 9f4baef0fdf9..efe0c8f7647a 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4041,16 +4041,12 @@ static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx)
 
 static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
 {
+    // Offset remaining text (+ copy zero terminator)
     char* dst = obj->TextA.Data + pos;
-
+    char* src = obj->TextA.Data + pos + n;
+    memmove(dst, src, obj->TextLen - n - pos + 1);
     obj->Edited = true;
     obj->TextLen -= n;
-
-    // Offset remaining text (FIXME-OPT: Use memmove)
-    const char* src = obj->TextA.Data + pos + n;
-    while (char c = *src++)
-        *dst++ = c;
-    *dst = '\0';
 }
 
 static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const char* new_text, int new_text_len)
@@ -4174,17 +4170,16 @@ ImGuiInputTextCallbackData::ImGuiInputTextCallbackData()
     memset(this, 0, sizeof(*this));
 }
 
-// Public API to manipulate UTF-8 text
-// We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)
+// Public API to manipulate UTF-8 text from within a callback.
 // FIXME: The existence of this rarely exercised code path is a bit of a nuisance.
+// Historically they existed because STB_TEXTEDIT_INSERTCHARS() etc. worked on our ImWchar
+// buffer, but nowadays they both work on UTF-8 data. Should aim to merge both.
 void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count)
 {
     IM_ASSERT(pos + bytes_count <= BufTextLen);
     char* dst = Buf + pos;
     const char* src = Buf + pos + bytes_count;
-    while (char c = *src++)
-        *dst++ = c;
-    *dst = '\0';
+    memmove(dst, src, BufTextLen - bytes_count - pos + 1);
 
     if (CursorPos >= pos + bytes_count)
         CursorPos -= bytes_count;
@@ -4209,7 +4204,6 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
         if (!is_resizable)
             return;
 
-        // Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the mildly similar code (until we remove the U16 buffer altogether!)
         ImGuiContext& g = *Ctx;
         ImGuiInputTextState* edit_state = &g.InputTextState;
         IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
@@ -4333,26 +4327,23 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im
     return true;
 }
 
-// Find the shortest single replacement we can make to get the new text from the old text.
-// Important: needs to be run before TextW is rewritten with the new characters because calling STB_TEXTEDIT_GETCHAR() at the end.
+// Find the shortest single replacement we can make to get from old_buf to new_buf
+// Note that this doesn't directly alter state->TextA, state->TextLen. They are expected to be made valid separately.
 // FIXME: Ideally we should transition toward (1) making InsertChars()/DeleteChars() update undo-stack (2) discourage (and keep reconcile) or obsolete (and remove reconcile) accessing buffer directly.
-static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* state, const char* new_buf_a, int new_length_a)
+static void InputTextReconcileUndoState(ImGuiInputTextState* state, const char* old_buf, int old_length, const char* new_buf, int new_length)
 {
-    const char* old_buf = state->CallbackTextBackup.Data;
-    const int old_length = state->CallbackTextBackup.Size - 1;
-
-    const int shorter_length = ImMin(old_length, new_length_a);
+    const int shorter_length = ImMin(old_length, new_length);
     int first_diff;
     for (first_diff = 0; first_diff < shorter_length; first_diff++)
-        if (old_buf[first_diff] != new_buf_a[first_diff])
+        if (old_buf[first_diff] != new_buf[first_diff])
             break;
-    if (first_diff == old_length && first_diff == new_length_a)
+    if (first_diff == old_length && first_diff == new_length)
         return;
 
     int old_last_diff = old_length   - 1;
-    int new_last_diff = new_length_a - 1;
+    int new_last_diff = new_length - 1;
     for (; old_last_diff >= first_diff && new_last_diff >= first_diff; old_last_diff--, new_last_diff--)
-        if (old_buf[old_last_diff] != new_buf_a[new_last_diff])
+        if (old_buf[old_last_diff] != new_buf[new_last_diff])
             break;
 
     const int insert_len = new_last_diff - first_diff + 1;
@@ -4544,16 +4535,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         if (flags & ImGuiInputTextFlags_ElideLeft)
             state->Scroll.x += ImMax(0.0f, CalcTextSize(buf).x - frame_size.x + style.FramePadding.x * 2.0f);
 
+        // Recycle existing cursor/selection/undo stack but clamp position
+        // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
         if (recycle_state)
-        {
-            // Recycle existing cursor/selection/undo stack but clamp position
-            // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
             state->CursorClamp();
-        }
         else
-        {
             stb_textedit_initialize_state(state->Stb, !is_multiline);
-        }
 
         if (init_reload_from_user_buf)
         {
@@ -5039,7 +5026,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                     {
                         // Callback may update buffer and thus set buf_dirty even in read-only mode.
                         IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
-                        InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ?
+                        InputTextReconcileUndoState(state, state->CallbackTextBackup.Data, state->CallbackTextBackup.Size - 1, callback_data.Buf, callback_data.BufTextLen);
                         state->TextLen = callback_data.BufTextLen;  // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
                         state->CursorAnimReset();
                     }

From 4ad5496474b006376c2b5b55b54519335eadb873 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 12 Dec 2024 18:39:28 +0100
Subject: [PATCH 310/548] Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to
 disable keyboard modifiers altering the tweak speed. (#8223)

---
 docs/CHANGELOG.txt | 3 +++
 imgui.h            | 1 +
 imgui_demo.cpp     | 2 ++
 imgui_widgets.cpp  | 6 +++---
 4 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index d95012d9f72b..21a927f4bf67 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,9 @@ Breaking changes:
 
 Other changes:
 
+- Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to disable keyboard
+  modifiers altering the tweak speed. Useful if you want to alter tweak speed
+  yourself based on your own logic. (#8223)
 - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for
   platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF]
 
diff --git a/imgui.h b/imgui.h
index 69f106dd6e90..eec3dce65ce2 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1788,6 +1788,7 @@ enum ImGuiSliderFlags_
     ImGuiSliderFlags_WrapAround         = 1 << 8,       // Enable wrapping around from max to min and from min to max. Only supported by DragXXX() functions for now.
     ImGuiSliderFlags_ClampOnInput       = 1 << 9,       // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.
     ImGuiSliderFlags_ClampZeroRange     = 1 << 10,      // Clamp even if min==max==0.0f. Otherwise due to legacy reason DragXXX functions don't clamp with those values. When your clamping limits are dynamic you almost always want to use it.
+    ImGuiSliderFlags_NoSpeedTweaks      = 1 << 11,      // Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic.
     ImGuiSliderFlags_AlwaysClamp        = ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_ClampZeroRange,
     ImGuiSliderFlags_InvalidMask_       = 0x7000000F,   // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed.
 };
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 6010aad4409c..c09c8eca7af7 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -2310,6 +2310,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
         ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits).");
         ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput);
         ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget.");
+        ImGui::CheckboxFlags("ImGuiSliderFlags_NoSpeedTweaks", &flags, ImGuiSliderFlags_NoSpeedTweaks);
+        ImGui::SameLine(); HelpMarker("Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic.");
         ImGui::CheckboxFlags("ImGuiSliderFlags_WrapAround", &flags, ImGuiSliderFlags_WrapAround);
         ImGui::SameLine(); HelpMarker("Enable wrapping around from max to min and from min to max (only supported by DragXXX() functions)");
 
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index efe0c8f7647a..82b5714fcbf5 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -2434,9 +2434,9 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
     if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR))
     {
         adjust_delta = g.IO.MouseDelta[axis];
-        if (g.IO.KeyAlt)
+        if (g.IO.KeyAlt && !(flags & ImGuiSliderFlags_NoSpeedTweaks))
             adjust_delta *= 1.0f / 100.0f;
-        if (g.IO.KeyShift)
+        if (g.IO.KeyShift && !(flags & ImGuiSliderFlags_NoSpeedTweaks))
             adjust_delta *= 10.0f;
     }
     else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
@@ -2444,7 +2444,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
         const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
         const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow);
         const bool tweak_fast = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakFast : ImGuiKey_NavKeyboardTweakFast);
-        const float tweak_factor = tweak_slow ? 1.0f / 10.0f : tweak_fast ? 10.0f : 1.0f;
+        const float tweak_factor = (flags & ImGuiSliderFlags_NoSpeedTweaks) ? 1.0f : tweak_slow ? 1.0f / 10.0f : tweak_fast ? 10.0f : 1.0f;
         adjust_delta = GetNavTweakPressedAmount(axis) * tweak_factor;
         v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision));
     }

From 8237ab450e3825e0888892c23d657b2bfaf18e47 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 12 Dec 2024 18:48:42 +0100
Subject: [PATCH 311/548] Drags, Sliders: store initial value on activation, as
 a convenience for some mods. (#8223)

---
 imgui.cpp         | 1 +
 imgui_internal.h  | 1 +
 imgui_widgets.cpp | 8 ++++++++
 3 files changed, 10 insertions(+)

diff --git a/imgui.cpp b/imgui.cpp
index 7325c1952795..3aa3b1fbf7c0 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3927,6 +3927,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
     ActiveIdPreviousFrameIsAlive = false;
     ActiveIdPreviousFrameHasBeenEditedBefore = false;
     ActiveIdPreviousFrameWindow = NULL;
+    memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation));
     LastActiveId = 0;
     LastActiveIdTimer = 0.0f;
 
diff --git a/imgui_internal.h b/imgui_internal.h
index fed655e03a42..14fea369115e 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2109,6 +2109,7 @@ struct ImGuiContext
     bool                    ActiveIdPreviousFrameIsAlive;
     bool                    ActiveIdPreviousFrameHasBeenEditedBefore;
     ImGuiWindow*            ActiveIdPreviousFrameWindow;
+    ImGuiDataTypeStorage    ActiveIdValueOnActivation;          // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
     ImGuiID                 LastActiveId;                       // Store the last non-zero ActiveId, useful for animation.
     float                   LastActiveIdTimer;                  // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
 
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 82b5714fcbf5..4074a9d73eb3 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -2632,6 +2632,10 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
                 temp_input_is_active = true;
             }
 
+        // Store initial value (not used by main lib but available as a convenience but some mods e.g. to revert)
+        if (make_active)
+            memcpy(&g.ActiveIdValueOnActivation, p_data, DataTypeGetInfo(data_type)->Size);
+
         if (make_active && !temp_input_is_active)
         {
             SetActiveID(id, window);
@@ -3222,6 +3226,10 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
             if ((clicked && g.IO.KeyCtrl) || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput)))
                 temp_input_is_active = true;
 
+        // Store initial value (not used by main lib but available as a convenience but some mods e.g. to revert)
+        if (make_active)
+            memcpy(&g.ActiveIdValueOnActivation, p_data, DataTypeGetInfo(data_type)->Size);
+
         if (make_active && !temp_input_is_active)
         {
             SetActiveID(id, window);

From 324d4bb1402e0d075a30f17b3d3859f813292bb7 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Thu, 12 Dec 2024 17:19:56 +0100
Subject: [PATCH 312/548] InputText: calling ReloadUserBuf doesn't clear undo
 stack. (#2890)

---
 imgui_internal.h  |  3 +--
 imgui_widgets.cpp | 42 ++++++++++++++++++++++--------------------
 2 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/imgui_internal.h b/imgui_internal.h
index 14fea369115e..d371ab9e674b 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1133,7 +1133,7 @@ struct IMGUI_API ImGuiInputTextState
     bool                    CursorFollow;           // set when we want scrolling to follow the current cursor position (not always!)
     bool                    SelectedAllMouseLock;   // after a double-click to select all, we ignore further mouse drags to update selection
     bool                    Edited;                 // edited this frame
-    bool                    ReloadUserBuf;          // force a reload of user buf so it may be modified externally. may be automatic in future version.
+    bool                    WantReloadUserBuf;      // force a reload of user buf so it may be modified externally. may be automatic in future version.
     int                     ReloadSelectionStart;
     int                     ReloadSelectionEnd;
 
@@ -1159,7 +1159,6 @@ struct IMGUI_API ImGuiInputTextState
     //   strcpy(my_buf, "hello");
     //   if (ImGuiInputTextState* state = ImGui::GetInputTextState(id)) // id may be ImGui::GetItemID() is last item
     //       state->ReloadUserBufAndSelectAll();
-    // THIS CURRENTLY RESETS THE UNDO STACK.
     void        ReloadUserBufAndSelectAll();
     void        ReloadUserBufAndKeepSelection();
     void        ReloadUserBufAndMoveToEnd();
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 4074a9d73eb3..871759cec515 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4169,9 +4169,9 @@ int  ImGuiInputTextState::GetCursorPos() const              { return Stb->cursor
 int  ImGuiInputTextState::GetSelectionStart() const         { return Stb->select_start; }
 int  ImGuiInputTextState::GetSelectionEnd() const           { return Stb->select_end; }
 void ImGuiInputTextState::SelectAll()                       { Stb->select_start = 0; Stb->cursor = Stb->select_end = TextLen; Stb->has_preferred_x = 0; }
-void ImGuiInputTextState::ReloadUserBufAndSelectAll()       { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; }
-void ImGuiInputTextState::ReloadUserBufAndKeepSelection()   { ReloadUserBuf = true; ReloadSelectionStart = Stb->select_start; ReloadSelectionEnd = Stb->select_end; }
-void ImGuiInputTextState::ReloadUserBufAndMoveToEnd()       { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; }
+void ImGuiInputTextState::ReloadUserBufAndSelectAll()       { WantReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; }
+void ImGuiInputTextState::ReloadUserBufAndKeepSelection()   { WantReloadUserBuf = true; ReloadSelectionStart = Stb->select_start; ReloadSelectionEnd = Stb->select_end; }
+void ImGuiInputTextState::ReloadUserBufAndMoveToEnd()       { WantReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; }
 
 ImGuiInputTextCallbackData::ImGuiInputTextCallbackData()
 {
@@ -4503,32 +4503,40 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
 
     float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
 
-    const bool init_reload_from_user_buf = (state != NULL && state->ReloadUserBuf);
+    const bool init_reload_from_user_buf = (state != NULL && state->WantReloadUserBuf);
     const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state.
     const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav);
     const bool init_state = (init_make_active || user_scroll_active);
-    if ((init_state && g.ActiveId != id) || init_changed_specs || init_reload_from_user_buf)
+    if (init_reload_from_user_buf)
+    {
+        int new_len = (int)strlen(buf);
+        state->WantReloadUserBuf = false;
+        InputTextReconcileUndoState(state, state->TextA.Data, state->TextLen, buf, new_len);
+        state->TextA.resize(buf_size + 1);          // we use +1 to make sure that .Data is always pointing to at least an empty string.
+        state->TextLen = new_len;
+        memcpy(state->TextA.Data, buf, state->TextLen + 1);
+        state->Stb->select_start = state->ReloadSelectionStart;
+        state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd;
+        state->CursorClamp();
+    }
+    else if ((init_state && g.ActiveId != id) || init_changed_specs)
     {
         // Access state even if we don't own it yet.
         state = &g.InputTextState;
         state->CursorAnimReset();
-        state->ReloadUserBuf = false;
 
         // Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714)
         InputTextDeactivateHook(state->ID);
 
+        // Take a copy of the initial buffer value.
         // From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode)
         const int buf_len = (int)strlen(buf);
-        if (!init_reload_from_user_buf)
-        {
-            // Take a copy of the initial buffer value.
-            state->TextToRevertTo.resize(buf_len + 1);    // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
-            memcpy(state->TextToRevertTo.Data, buf, buf_len + 1);
-        }
+        state->TextToRevertTo.resize(buf_len + 1);    // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
+        memcpy(state->TextToRevertTo.Data, buf, buf_len + 1);
 
         // Preserve cursor position and undo/redo stack if we come back to same widget
         // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
-        bool recycle_state = (state->ID == id && !init_changed_specs && !init_reload_from_user_buf);
+        bool recycle_state = (state->ID == id && !init_changed_specs);
         if (recycle_state && (state->TextLen != buf_len || (strncmp(state->TextA.Data, buf, buf_len) != 0)))
             recycle_state = false;
 
@@ -4550,13 +4558,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         else
             stb_textedit_initialize_state(state->Stb, !is_multiline);
 
-        if (init_reload_from_user_buf)
-        {
-            state->Stb->select_start = state->ReloadSelectionStart;
-            state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd;
-            state->CursorClamp();
-        }
-        else if (!is_multiline)
+        if (!is_multiline)
         {
             if (flags & ImGuiInputTextFlags_AutoSelectAll)
                 select_all = true;

From f5f11e94be35078c3bbb5196f55269f88634b9bd Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Sun, 15 Dec 2024 15:46:33 +0100
Subject: [PATCH 313/548] InputText: Fixed a bug where character replacements
 performed from a callback were not applied when pasting from clipbard.
 (#8229)

---
 docs/CHANGELOG.txt |  2 ++
 imgui_widgets.cpp  | 22 ++++++++++++----------
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 21a927f4bf67..b266f3a15360 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -43,6 +43,8 @@ Breaking changes:
 
 Other changes:
 
+- InputText: Fixed a bug where character replacements performed from a callback
+  were not applied when pasting from clipbard. (#8229)
 - Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to disable keyboard
   modifiers altering the tweak speed. Useful if you want to alter tweak speed
   yourself based on your own logic. (#8223)
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 871759cec515..09c625d3d08d 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4895,25 +4895,27 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             {
                 // Filter pasted buffer
                 const int clipboard_len = (int)strlen(clipboard);
-                char* clipboard_filtered = (char*)IM_ALLOC(clipboard_len + 1);
-                int clipboard_filtered_len = 0;
+                ImVector clipboard_filtered;
+                clipboard_filtered.reserve(clipboard_len + 1);
                 for (const char* s = clipboard; *s != 0; )
                 {
                     unsigned int c;
-                    int len = ImTextCharFromUtf8(&c, s, NULL);
-                    s += len;
+                    int in_len = ImTextCharFromUtf8(&c, s, NULL);
+                    s += in_len;
                     if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, true))
                         continue;
-                    memcpy(clipboard_filtered + clipboard_filtered_len, s - len, len);
-                    clipboard_filtered_len += len;
+                    char c_utf8[5];
+                    ImTextCharToUtf8(c_utf8, c);
+                    int out_len = (int)strlen(c_utf8);
+                    clipboard_filtered.resize(clipboard_filtered.Size + out_len);
+                    memcpy(clipboard_filtered.Data + clipboard_filtered.Size - out_len, c_utf8, out_len);
                 }
-                clipboard_filtered[clipboard_filtered_len] = 0;
-                if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation
+                if (clipboard_filtered.Size > 0) // If everything was filtered, ignore the pasting operation
                 {
-                    stb_textedit_paste(state, state->Stb, clipboard_filtered, clipboard_filtered_len);
+                    clipboard_filtered.push_back(0);
+                    stb_textedit_paste(state, state->Stb, clipboard_filtered.Data, clipboard_filtered.Size - 1);
                     state->CursorFollow = true;
                 }
-                MemFree(clipboard_filtered);
             }
         }
 

From 13c4084362b35ce58a25be70b9f1710dfe3377e9 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Mon, 16 Dec 2024 10:51:33 +0100
Subject: [PATCH 314/548] Nav: Fixed an issue where Alt key would clear current
 active item on windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231)

---
 docs/CHANGELOG.txt |  2 ++
 imgui.cpp          | 21 +++++++++++----------
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index b266f3a15360..eb3db490932a 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -48,6 +48,8 @@ Other changes:
 - Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to disable keyboard
   modifiers altering the tweak speed. Useful if you want to alter tweak speed
   yourself based on your own logic. (#8223)
+- Nav: Fixed an issue where Alt key would clear current active item on
+  windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231)
 - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for
   platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF]
 
diff --git a/imgui.cpp b/imgui.cpp
index 3aa3b1fbf7c0..896830575b96 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -4356,7 +4356,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
 
         // This could be written in a more general way (e.g associate a hook to ActiveId),
         // but since this is currently quite an exception we'll leave it as is.
-        // One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveId()
+        // One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveID()
         if (g.InputTextState.ID == g.ActiveId)
             InputTextDeactivateHook(g.ActiveId);
     }
@@ -13625,15 +13625,16 @@ static void ImGui::NavUpdateWindowing()
     // Keyboard: Press and Release ALT to toggle menu layer
     const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt };
     bool windowing_toggle_layer_start = false;
-    for (ImGuiKey windowing_toggle_key : windowing_toggle_keys)
-        if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, 0, ImGuiKeyOwner_NoOwner))
-        {
-            windowing_toggle_layer_start = true;
-            g.NavWindowingToggleLayer = true;
-            g.NavWindowingToggleKey = windowing_toggle_key;
-            g.NavInputSource = ImGuiInputSource_Keyboard;
-            break;
-        }
+    if (g.NavWindow != NULL && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
+        for (ImGuiKey windowing_toggle_key : windowing_toggle_keys)
+            if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, 0, ImGuiKeyOwner_NoOwner))
+            {
+                windowing_toggle_layer_start = true;
+                g.NavWindowingToggleLayer = true;
+                g.NavWindowingToggleKey = windowing_toggle_key;
+                g.NavInputSource = ImGuiInputSource_Keyboard;
+                break;
+            }
     if (g.NavWindowingToggleLayer && g.NavInputSource == ImGuiInputSource_Keyboard)
     {
         // We cancel toggling nav layer when any text has been typed (generally while holding Alt). (See #370)

From f31d53093b5031a1de0d43adc2a82c0e93d4d0f6 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 18 Dec 2024 13:02:48 +0100
Subject: [PATCH 315/548] TestEngine: for consistency, title bar / window items
 are registered in _Menu layer.

---
 imgui.cpp | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/imgui.cpp b/imgui.cpp
index 896830575b96..87d0aaa47be7 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -7391,9 +7391,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
         {
             IM_ASSERT(window->IDStack.Size == 1);
             window->IDStack.Size = 0; // As window->IDStack[0] == window->ID here, make sure TestEngine doesn't erroneously see window as parent of itself.
+            window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
             IMGUI_TEST_ENGINE_ITEM_ADD(window->ID, window->Rect(), NULL);
             IMGUI_TEST_ENGINE_ITEM_INFO(window->ID, window->Name, (g.HoveredWindow == window) ? ImGuiItemStatusFlags_HoveredRect : 0);
             window->IDStack.Size = 1;
+            window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
+
         }
 #endif
 
@@ -7653,7 +7656,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
         // [Test Engine] Register title bar / tab with MoveId.
 #ifdef IMGUI_ENABLE_TEST_ENGINE
         if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
+        {
+            window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
             IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.ID, g.LastItemData.Rect, &g.LastItemData);
+            window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
+        }
 #endif
     }
     else

From e900571ac24039d41ebe934cd20d1d3bea7a8118 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 18 Dec 2024 16:14:04 +0100
Subject: [PATCH 316/548] InputText: Fixed issue when activating a ReadOnly
 field when the underlying value is being modified. (#8242)

---
 docs/CHANGELOG.txt |  2 ++
 imgui.h            |  2 +-
 imgui_widgets.cpp  | 41 ++++++++++++++++++++++++++++++++++-------
 3 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index eb3db490932a..25649c16f28d 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -45,6 +45,8 @@ Other changes:
 
 - InputText: Fixed a bug where character replacements performed from a callback
   were not applied when pasting from clipbard. (#8229)
+- InputText: Fixed issue when activating a ReadOnly field when the underlying
+  value is being modified. (#8242)
 - Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to disable keyboard
   modifiers altering the tweak speed. Useful if you want to alter tweak speed
   yourself based on your own logic. (#8223)
diff --git a/imgui.h b/imgui.h
index eec3dce65ce2..98f0a4d20573 100644
--- a/imgui.h
+++ b/imgui.h
@@ -29,7 +29,7 @@
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.91.7 WIP"
-#define IMGUI_VERSION_NUM   19161
+#define IMGUI_VERSION_NUM   19162
 #define IMGUI_HAS_TABLE
 
 /*
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 09c625d3d08d..3d135dca923b 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4507,12 +4507,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state.
     const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav);
     const bool init_state = (init_make_active || user_scroll_active);
+    bool readonly_swapped_text_data = false;
     if (init_reload_from_user_buf)
     {
         int new_len = (int)strlen(buf);
         state->WantReloadUserBuf = false;
         InputTextReconcileUndoState(state, state->TextA.Data, state->TextLen, buf, new_len);
-        state->TextA.resize(buf_size + 1);          // we use +1 to make sure that .Data is always pointing to at least an empty string.
+        state->TextA.resize(buf_size + 1); // we use +1 to make sure that .Data is always pointing to at least an empty string.
         state->TextLen = new_len;
         memcpy(state->TextA.Data, buf, state->TextLen + 1);
         state->Stb->select_start = state->ReloadSelectionStart;
@@ -4537,14 +4538,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         // Preserve cursor position and undo/redo stack if we come back to same widget
         // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
         bool recycle_state = (state->ID == id && !init_changed_specs);
-        if (recycle_state && (state->TextLen != buf_len || (strncmp(state->TextA.Data, buf, buf_len) != 0)))
+        if (recycle_state && (state->TextLen != buf_len || (state->TextA.Data == NULL || strncmp(state->TextA.Data, buf, buf_len) != 0)))
             recycle_state = false;
 
         // Start edition
         state->ID = id;
-        state->TextA.resize(buf_size + 1);          // we use +1 to make sure that .Data is always pointing to at least an empty string.
         state->TextLen = (int)strlen(buf);
-        memcpy(state->TextA.Data, buf, state->TextLen + 1);
+        if (!is_readonly)
+        {
+            state->TextA.resize(buf_size + 1); // we use +1 to make sure that .Data is always pointing to at least an empty string.
+            memcpy(state->TextA.Data, buf, state->TextLen + 1);
+        }
 
         // Find initial scroll position for right alignment
         state->Scroll = ImVec2(0.0f, 0.0f);
@@ -4610,6 +4614,21 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             state->Scroll.y = draw_window->Scroll.y;
     }
 
+    if (g.ActiveId == id && is_readonly)
+    {
+        // FIXME: Refresh buffer because cursor/selection code uses that data (see repro #8242)
+        // The "simple" way would be to copy buf into state->TextA, like in the block above.
+        // But because we like to live dangerously, we do a little swap....
+        // Removing the swap and only doing a TextA.clear() is a way to identify who's using TextA.Data.
+        state->TextLen = (int)strlen(buf);
+        state->TextA.clear();
+        state->TextA.Data = buf; // Ouch
+        state->TextA.Size = state->TextLen + 1;
+        readonly_swapped_text_data = true; // Need to always ensure that every code path below lead to this being handled
+        //state->TextA.resize(buf_size + 1);
+        //memcpy(state->TextA.Data, buf, state->TextLen + 1);
+    }
+
     // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function)
     if (g.ActiveId == id && state == NULL)
         ClearActiveID();
@@ -5008,10 +5027,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
                     callback_data.UserData = callback_user_data;
 
                     // FIXME-OPT: Undo stack reconcile needs a backup of the data until we rework API, see #7925
+                    char* callback_buf = is_readonly ? buf : state->TextA.Data;
+
                     state->CallbackTextBackup.resize(state->TextLen + 1);
-                    memcpy(state->CallbackTextBackup.Data, state->TextA.Data, state->TextLen + 1);
+                    memcpy(state->CallbackTextBackup.Data, callback_buf, state->TextLen + 1);
 
-                    char* callback_buf = is_readonly ? buf : state->TextA.Data;
                     callback_data.EventKey = event_key;
                     callback_data.Buf = callback_buf;
                     callback_data.BufTextLen = state->TextLen;
@@ -5142,7 +5162,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         // - Measure text height (for scrollbar)
         // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
         // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
-        const char* text_begin = state->TextA.Data;
+        const char* text_begin = buf_display;
         const char* text_end = text_begin + state->TextLen;
         ImVec2 cursor_offset, select_start_offset;
 
@@ -5304,6 +5324,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     if (is_password && !is_displaying_hint)
         PopFont();
 
+    if (readonly_swapped_text_data)
+    {
+        IM_ASSERT(state->TextA.Data == buf);
+        state->TextA.Size = 0;
+        state->TextA.Data = NULL;
+    }
+
     if (is_multiline)
     {
         // For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (see #4761, #7870)...

From 32f11402f96f516be68b56f9eb338f382c544819 Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 18 Dec 2024 16:47:02 +0100
Subject: [PATCH 317/548] InputText: use TextSrc more consistently to
 facilitate accessing user buffer in text processing code. (#8242)

Followup to e900571
Removed SetClipboardText() trick used in abd07f6d (#7925)
---
 imgui_internal.h  |  1 +
 imgui_widgets.cpp | 79 +++++++++++++++++++++--------------------------
 2 files changed, 36 insertions(+), 44 deletions(-)

diff --git a/imgui_internal.h b/imgui_internal.h
index d371ab9e674b..6be907bb573b 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1124,6 +1124,7 @@ struct IMGUI_API ImGuiInputTextState
     ImGuiInputTextFlags     Flags;                  // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
     ImGuiID                 ID;                     // widget id owning the text state
     int                     TextLen;                // UTF-8 length of the string in TextA (in bytes)
+    const char*             TextSrc;                // == TextA.Data unless read-only, in which case == buf passed to InputText(). Field only set and valid _inside_ the call InputText() call.
     ImVector          TextA;                  // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1).
     ImVector          TextToRevertTo;         // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered)
     ImVector          CallbackTextBackup;     // temporary storage for callback to support automatic reconcile of undo-stack
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 3d135dca923b..b0f28903ae1d 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -3938,12 +3938,12 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
 namespace ImStb
 {
 static int     STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj)                             { return obj->TextLen; }
-static char    STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx <= obj->TextLen); return obj->TextA[idx]; }
-static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
+static char    STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx <= obj->TextLen); return obj->TextSrc[idx]; }
+static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
 static char    STB_TEXTEDIT_NEWLINE = '\n';
 static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
 {
-    const char* text = obj->TextA.Data;
+    const char* text = obj->TextSrc;
     const char* text_remaining = NULL;
     const ImVec2 size = InputTextCalcTextSize(obj->Ctx, text + line_start_idx, text + obj->TextLen, &text_remaining, NULL, true);
     r->x0 = 0.0f;
@@ -3962,15 +3962,15 @@ static int IMSTB_TEXTEDIT_GETNEXTCHARINDEX_IMPL(ImGuiInputTextState* obj, int id
     if (idx >= obj->TextLen)
         return obj->TextLen + 1;
     unsigned int c;
-    return idx + ImTextCharFromUtf8(&c, obj->TextA.Data + idx, obj->TextA.Data + obj->TextLen);
+    return idx + ImTextCharFromUtf8(&c, obj->TextSrc + idx, obj->TextSrc + obj->TextLen);
 }
 
 static int IMSTB_TEXTEDIT_GETPREVCHARINDEX_IMPL(ImGuiInputTextState* obj, int idx)
 {
     if (idx <= 0)
         return -1;
-    const char* p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, obj->TextA.Data + idx);
-    return (int)(p - obj->TextA.Data);
+    const char* p = ImTextFindPreviousUtf8Codepoint(obj->TextSrc, obj->TextSrc + idx);
+    return (int)(p - obj->TextSrc);
 }
 
 static bool ImCharIsSeparatorW(unsigned int c)
@@ -3993,10 +3993,10 @@ static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)
     if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
         return 0;
 
-    const char* curr_p = obj->TextA.Data + idx;
-    const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, curr_p);
-    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, curr_p, obj->TextA.Data + obj->TextLen);
-    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, prev_p, obj->TextA.Data + obj->TextLen);
+    const char* curr_p = obj->TextSrc + idx;
+    const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextSrc, curr_p);
+    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, curr_p, obj->TextSrc + obj->TextLen);
+    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, prev_p, obj->TextSrc + obj->TextLen);
 
     bool prev_white = ImCharIsBlankW(prev_c);
     bool prev_separ = ImCharIsSeparatorW(prev_c);
@@ -4009,10 +4009,10 @@ static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)
     if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0)
         return 0;
 
-    const char* curr_p = obj->TextA.Data + idx;
-    const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextA.Data, curr_p);
-    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, curr_p, obj->TextA.Data + obj->TextLen);
-    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, prev_p, obj->TextA.Data + obj->TextLen);
+    const char* curr_p = obj->TextSrc + idx;
+    const char* prev_p = ImTextFindPreviousUtf8Codepoint(obj->TextSrc, curr_p);
+    unsigned int prev_c; ImTextCharFromUtf8(&prev_c, curr_p, obj->TextSrc + obj->TextLen);
+    unsigned int curr_c; ImTextCharFromUtf8(&curr_c, prev_p, obj->TextSrc + obj->TextLen);
 
     bool prev_white = ImCharIsBlankW(prev_c);
     bool prev_separ = ImCharIsSeparatorW(prev_c);
@@ -4050,6 +4050,7 @@ static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx)
 static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
 {
     // Offset remaining text (+ copy zero terminator)
+    IM_ASSERT(obj->TextSrc == obj->TextA.Data);
     char* dst = obj->TextA.Data + pos;
     char* src = obj->TextA.Data + pos + n;
     memmove(dst, src, obj->TextLen - n - pos + 1);
@@ -4067,11 +4068,13 @@ static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ch
         return false;
 
     // Grow internal buffer if needed
+    IM_ASSERT(obj->TextSrc == obj->TextA.Data);
     if (new_text_len + text_len + 1 > obj->TextA.Size)
     {
         if (!is_resizable)
             return false;
         obj->TextA.resize(text_len + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1);
+        obj->TextSrc = obj->TextA.Data;
     }
 
     char* text = obj->TextA.Data;
@@ -4218,6 +4221,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
         IM_ASSERT(Buf == edit_state->TextA.Data);
         int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
         edit_state->TextA.resize(new_buf_size + 1);
+        edit_state->TextSrc = edit_state->TextA.Data;
         Buf = edit_state->TextA.Data;
         BufSize = edit_state->BufCapacity = new_buf_size;
     }
@@ -4507,7 +4511,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state.
     const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav);
     const bool init_state = (init_make_active || user_scroll_active);
-    bool readonly_swapped_text_data = false;
     if (init_reload_from_user_buf)
     {
         int new_len = (int)strlen(buf);
@@ -4612,22 +4615,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         // Expose scroll in a manner that is agnostic to us using a child window
         if (is_multiline && state != NULL)
             state->Scroll.y = draw_window->Scroll.y;
-    }
 
-    if (g.ActiveId == id && is_readonly)
-    {
-        // FIXME: Refresh buffer because cursor/selection code uses that data (see repro #8242)
-        // The "simple" way would be to copy buf into state->TextA, like in the block above.
-        // But because we like to live dangerously, we do a little swap....
-        // Removing the swap and only doing a TextA.clear() is a way to identify who's using TextA.Data.
-        state->TextLen = (int)strlen(buf);
-        state->TextA.clear();
-        state->TextA.Data = buf; // Ouch
-        state->TextA.Size = state->TextLen + 1;
-        readonly_swapped_text_data = true; // Need to always ensure that every code path below lead to this being handled
-        //state->TextA.resize(buf_size + 1);
-        //memcpy(state->TextA.Data, buf, state->TextLen + 1);
+        // Read-only mode always ever read from source buffer. Refresh TextLen when active.
+        if (is_readonly && state != NULL)
+            state->TextLen = (int)strlen(buf);
+        //if (is_readonly && state != NULL)
+        //    state->TextA.clear(); // Uncomment to facilitate debugging, but we otherwise prefer to keep/amortize th allocation.
     }
+    if (state != NULL)
+        state->TextSrc = is_readonly ? buf : state->TextA.Data;
 
     // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function)
     if (g.ActiveId == id && state == NULL)
@@ -4892,13 +4888,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             // Cut, Copy
             if (g.PlatformIO.Platform_SetClipboardTextFn != NULL)
             {
+                // SetClipboardText() only takes null terminated strings + state->TextSrc may point to read-only user buffer, so we need to make a copy.
                 const int ib = state->HasSelection() ? ImMin(state->Stb->select_start, state->Stb->select_end) : 0;
                 const int ie = state->HasSelection() ? ImMax(state->Stb->select_start, state->Stb->select_end) : state->TextLen;
-
-                char backup = state->TextA.Data[ie];
-                state->TextA.Data[ie] = 0; // A bit of a hack since SetClipboardText only takes null terminated strings
-                SetClipboardText(state->TextA.Data + ib);
-                state->TextA.Data[ie] = backup;
+                g.TempBuffer.reserve(ie - ib + 1);
+                memcpy(g.TempBuffer.Data, state->TextSrc, ie - ib);
+                g.TempBuffer.Data[ie] = 0;
+                SetClipboardText(g.TempBuffer.Data);
             }
             if (is_cut)
             {
@@ -5028,7 +5024,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
 
                     // FIXME-OPT: Undo stack reconcile needs a backup of the data until we rework API, see #7925
                     char* callback_buf = is_readonly ? buf : state->TextA.Data;
-
+                    IM_ASSERT(callback_buf == state->TextSrc);
                     state->CallbackTextBackup.resize(state->TextLen + 1);
                     memcpy(state->CallbackTextBackup.Data, callback_buf, state->TextLen + 1);
 
@@ -5066,9 +5062,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             }
 
             // Will copy result string if modified
-            if (!is_readonly && strcmp(state->TextA.Data, buf) != 0)
+            if (!is_readonly && strcmp(state->TextSrc, buf) != 0)
             {
-                apply_new_text = state->TextA.Data;
+                apply_new_text = state->TextSrc;
                 apply_new_text_length = state->TextLen;
                 value_changed = true;
             }
@@ -5324,13 +5320,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     if (is_password && !is_displaying_hint)
         PopFont();
 
-    if (readonly_swapped_text_data)
-    {
-        IM_ASSERT(state->TextA.Data == buf);
-        state->TextA.Size = 0;
-        state->TextA.Data = NULL;
-    }
-
     if (is_multiline)
     {
         // For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (see #4761, #7870)...
@@ -5349,6 +5338,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             g.LastItemData.StatusFlags = item_data_backup.StatusFlags;
         }
     }
+    if (state)
+        state->TextSrc = NULL;
 
     // Log as text
     if (g.LogEnabled && (!is_password || is_displaying_hint))

From cd6c83cdccb78fa1ab20cece35ccc8c3317ecdc8 Mon Sep 17 00:00:00 2001
From: Raffaello Bertini 
Date: Wed, 18 Dec 2024 10:54:16 +0100
Subject: [PATCH 318/548] Fixes GCC warnings (#8241)

---
 imgui.cpp         | 6 ++++--
 imgui.h           | 1 +
 imgui_demo.cpp    | 3 +++
 imgui_draw.cpp    | 6 ++++--
 imgui_internal.h  | 3 ++-
 imgui_tables.cpp  | 3 +++
 imgui_widgets.cpp | 4 ++++
 7 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/imgui.cpp b/imgui.cpp
index 87d0aaa47be7..cf59a5a531d4 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1095,7 +1095,7 @@ CODE
 #else
 #include 
 #endif
-#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP || WINAPI_FAMILY == WINAPI_FAMILY_GAMES)
+#if defined(WINAPI_FAMILY) && ((defined(WINAPI_FAMILY_APP) && WINAPI_FAMILY == WINAPI_FAMILY_APP) || (defined(WINAPI_FAMILY_GAMES) && WINAPI_FAMILY == WINAPI_FAMILY_GAMES))
 // The UWP and GDK Win32 API subsets don't support clipboard nor IME functions
 #define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
 #define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
@@ -1144,12 +1144,14 @@ CODE
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
 #pragma GCC diagnostic ignored "-Wunused-function"                  // warning: 'xxxx' defined but not used
 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"              // warning: cast to pointer from integer of different size
-#pragma GCC diagnostic ignored "-Wformat"                           // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'
+#pragma GCC diagnostic ignored "-Wfloat-equal"                      // warning: comparing floating-point with '==' or '!=' is unsafe
+#pragma GCC diagnostic ignored "-Wformat"                           // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
 #pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
 #pragma GCC diagnostic ignored "-Wconversion"                       // warning: conversion to 'xxxx' from 'xxxx' may alter its value
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"                // warning: format not a string literal, format string not checked
 #pragma GCC diagnostic ignored "-Wstrict-overflow"                  // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
 #pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#pragma GCC diagnostic ignored "-Wcast-qual"                        // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
 #endif
 
 // Debug options
diff --git a/imgui.h b/imgui.h
index 98f0a4d20573..e1b8796f3623 100644
--- a/imgui.h
+++ b/imgui.h
@@ -139,6 +139,7 @@ Index of this file:
 #elif defined(__GNUC__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wfloat-equal"                      // warning: comparing floating-point with '==' or '!=' is unsafe
 #pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #endif
 
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index c09c8eca7af7..6425e318e6e7 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -146,11 +146,14 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
 #elif defined(__GNUC__)
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wfloat-equal"                      // warning: comparing floating-point with '==' or '!=' is unsafe
 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"              // warning: cast to pointer from integer of different size
+#pragma GCC diagnostic ignored "-Wformat"                           // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
 #pragma GCC diagnostic ignored "-Wformat-security"                  // warning: format string is not a string literal (potentially insecure)
 #pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
 #pragma GCC diagnostic ignored "-Wconversion"                       // warning: conversion to 'xxxx' from 'xxxx' may alter its value
 #pragma GCC diagnostic ignored "-Wmisleading-indentation"           // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on GitHub.
+#pragma GCC diagnostic ignored "-Wcast-qual"                        // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
 #endif
 
 // Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index f51fff3a6357..2b1e10c4e9eb 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -67,13 +67,16 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wreserved-identifier"            // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
 #pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
+#pragma clang diagnostic ignored "-Wcast-qual"                      // warning: cast from 'const xxxx *' to 'xxx *' drops const qualifier
 #elif defined(__GNUC__)
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
 #pragma GCC diagnostic ignored "-Wunused-function"                  // warning: 'xxxx' defined but not used
+#pragma GCC diagnostic ignored "-Wfloat-equal"                      // warning: comparing floating-point with '==' or '!=' is unsafe
 #pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
 #pragma GCC diagnostic ignored "-Wconversion"                       // warning: conversion to 'xxxx' from 'xxxx' may alter its value
 #pragma GCC diagnostic ignored "-Wstack-protector"                  // warning: stack protector not protecting local variables: variable length buffer
 #pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#pragma GCC diagnostic ignored "-Wcast-qual"                        // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
 #endif
 
 //-------------------------------------------------------------------------
@@ -105,13 +108,12 @@ namespace IMGUI_STB_NAMESPACE
 #pragma clang diagnostic ignored "-Wunused-function"        // warning: 'xxxx' defined but not used
 #pragma clang diagnostic ignored "-Wmissing-prototypes"
 #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
-#pragma clang diagnostic ignored "-Wcast-qual"              // warning: cast from 'const xxxx *' to 'xxx *' drops const qualifier
 #endif
 
 #if defined(__GNUC__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wtype-limits"              // warning: comparison is always true due to limited range of data type [-Wtype-limits]
-#pragma GCC diagnostic ignored "-Wcast-qual"                // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"     // warning: this statement may fall through
 #endif
 
 #ifndef STB_RECT_PACK_IMPLEMENTATION                        // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
diff --git a/imgui_internal.h b/imgui_internal.h
index 6be907bb573b..947277489740 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -101,6 +101,7 @@ Index of this file:
 #elif defined(__GNUC__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wfloat-equal"                      // warning: comparing floating-point with '==' or '!=' is unsafe
 #pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion"  // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
 #endif
@@ -460,7 +461,7 @@ static inline double ImRsqrt(double x)          { return 1.0 / sqrt(x); }
 template static inline T ImMin(T lhs, T rhs)                        { return lhs < rhs ? lhs : rhs; }
 template static inline T ImMax(T lhs, T rhs)                        { return lhs >= rhs ? lhs : rhs; }
 template static inline T ImClamp(T v, T mn, T mx)                   { return (v < mn) ? mn : (v > mx) ? mx : v; }
-template static inline T ImLerp(T a, T b, float t)                  { return (T)(a + (b - a) * t); }
+template static inline T ImLerp(T a, T b, float t)                  { return (T)(a + (b - a) * (T)t); }
 template static inline void ImSwap(T& a, T& b)                      { T tmp = a; a = b; b = tmp; }
 template static inline T ImAddClampOverflow(T a, T b, T mn, T mx)   { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; }
 template static inline T ImSubClampOverflow(T a, T b, T mn, T mx)   { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; }
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index 7dd97c6f214a..96e46141809e 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -232,8 +232,11 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
 #elif defined(__GNUC__)
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wfloat-equal"                      // warning: comparing floating-point with '==' or '!=' is unsafe
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"                // warning: format not a string literal, format string not checked
 #pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wformat"                           // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
 #endif
 
 //-----------------------------------------------------------------------------
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index b0f28903ae1d..4e6cbee9acf5 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -82,9 +82,13 @@ Index of this file:
 #pragma clang diagnostic ignored "-Wnontrivial-memaccess"           // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
 #elif defined(__GNUC__)
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wfloat-equal"                      // warning: comparing floating-point with '==' or '!=' is unsafe
+#pragma GCC diagnostic ignored "-Wformat"                           // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"                // warning: format not a string literal, format string not checked
 #pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion"  // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
+#pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wcast-qual"                        // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
 #endif
 
 //-------------------------------------------------------------------------

From 457fae24e7a9fd30ad24b35e2f2ac714bca522bd Mon Sep 17 00:00:00 2001
From: ocornut 
Date: Wed, 18 Dec 2024 18:13:55 +0100
Subject: [PATCH 319/548] Silence more zealous GCC warning. (#8241)

---
 backends/imgui_impl_opengl3.cpp | 1 +
 imgui_demo.cpp                  | 1 +
 imgui_draw.cpp                  | 1 +
 imgui_tables.cpp                | 3 ++-
 imgui_widgets.cpp               | 3 ++-
 5 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp
index b47ac9ab1c97..efc1a3c49283 100644
--- a/backends/imgui_impl_opengl3.cpp
+++ b/backends/imgui_impl_opengl3.cpp
@@ -137,6 +137,7 @@
 #pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
 #pragma GCC diagnostic ignored "-Wunknown-warning-option"   // warning: unknown warning group 'xxx'
 #pragma GCC diagnostic ignored "-Wcast-function-type"       // warning: cast between incompatible function types (for loader)
+#pragma GCC diagnostic ignored "-Wstrict-overflow"          // warning: assuming signed overflow does not occur when simplifying division / ..when changing X +- C1 cmp C2 to X cmp C2 -+ C1
 #endif
 
 // GL includes
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 6425e318e6e7..621fc4f434b3 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -153,6 +153,7 @@ Index of this file:
 #pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
 #pragma GCC diagnostic ignored "-Wconversion"                       // warning: conversion to 'xxxx' from 'xxxx' may alter its value
 #pragma GCC diagnostic ignored "-Wmisleading-indentation"           // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on GitHub.
+#pragma GCC diagnostic ignored "-Wstrict-overflow"                  // warning: assuming signed overflow does not occur when simplifying division / ..when changing X +- C1 cmp C2 to X cmp C2 -+ C1
 #pragma GCC diagnostic ignored "-Wcast-qual"                        // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
 #endif
 
diff --git a/imgui_draw.cpp b/imgui_draw.cpp
index 2b1e10c4e9eb..6caba22fa5bd 100644
--- a/imgui_draw.cpp
+++ b/imgui_draw.cpp
@@ -75,6 +75,7 @@ Index of this file:
 #pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
 #pragma GCC diagnostic ignored "-Wconversion"                       // warning: conversion to 'xxxx' from 'xxxx' may alter its value
 #pragma GCC diagnostic ignored "-Wstack-protector"                  // warning: stack protector not protecting local variables: variable length buffer
+#pragma GCC diagnostic ignored "-Wstrict-overflow"                  // warning: assuming signed overflow does not occur when simplifying division / ..when changing X +- C1 cmp C2 to X cmp C2 -+ C1
 #pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #pragma GCC diagnostic ignored "-Wcast-qual"                        // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
 #endif
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index 96e46141809e..e90da3ec73ad 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -234,9 +234,10 @@ Index of this file:
 #pragma GCC diagnostic ignored "-Wpragmas"                          // warning: unknown option after '#pragma GCC diagnostic' kind
 #pragma GCC diagnostic ignored "-Wfloat-equal"                      // warning: comparing floating-point with '==' or '!=' is unsafe
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"                // warning: format not a string literal, format string not checked
-#pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
 #pragma GCC diagnostic ignored "-Wformat"                           // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
+#pragma GCC diagnostic ignored "-Wstrict-overflow"
+#pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #endif
 
 //-----------------------------------------------------------------------------
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 4e6cbee9acf5..b8680ab34714 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -85,9 +85,10 @@ Index of this file:
 #pragma GCC diagnostic ignored "-Wfloat-equal"                      // warning: comparing floating-point with '==' or '!=' is unsafe
 #pragma GCC diagnostic ignored "-Wformat"                           // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"                // warning: format not a string literal, format string not checked
-#pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion"  // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
 #pragma GCC diagnostic ignored "-Wdouble-promotion"                 // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wstrict-overflow"                  // warning: assuming signed overflow does not occur when simplifying division / ..when changing X +- C1 cmp C2 to X cmp C2 -+ C1
+#pragma GCC diagnostic ignored "-Wclass-memaccess"                  // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
 #pragma GCC diagnostic ignored "-Wcast-qual"                        // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
 #endif
 

From ae839620b9670ee5303860a0adbb76c9780eb856 Mon Sep 17 00:00:00 2001
From: Tiamat-Defender <166345691+Tiamat-Defender@users.noreply.github.com>
Date: Thu, 19 Dec 2024 08:22:56 -0500
Subject: [PATCH 320/548] Docs: Updated EXAMPLES.md (#8246)

---
 docs/EXAMPLES.md | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md
index 66ad24ef7f81..f84f9497b6dd 100644
--- a/docs/EXAMPLES.md
+++ b/docs/EXAMPLES.md
@@ -175,7 +175,7 @@ Raw Windows + OpenGL3 + example (modern, programmable pipeline) 
**Building** -Unfortunately nowadays it is still tedious to create and maintain portable build files using external +Unfortunately, nowadays it is still tedious to create and maintain portable build files using external libraries (the kind we're using here to create a window and render 3D triangles) without relying on third party software and build systems. For most examples here we choose to provide: - Makefiles for Linux/OSX @@ -191,22 +191,22 @@ If you are interested in using Cmake to build and links examples, see: **About mouse cursor latency** -Dear ImGui has no particular extra lag for most behaviors, +Dear ImGui does not introduce significant extra lag for most behaviors, e.g. the last value passed to 'io.AddMousePosEvent()' before NewFrame() will result in windows being moved to the right spot at the time of EndFrame()/Render(). At 60 FPS your experience should be pleasant. -However, consider that OS mouse cursors are typically drawn through a very specific hardware accelerated -path and will feel smoother than the majority of contents rendered via regular graphics API (including, +However, consider that OS mouse cursors are typically rendered through a very specific hardware-accelerated +path, which makes them feel smoother than the majority of content rendered via regular graphics API (including, but not limited to Dear ImGui windows). Because UI rendering and interaction happens on the same plane as the mouse, that disconnect may be jarring to particularly sensitive users. You may experiment with enabling the io.MouseDrawCursor flag to request Dear ImGui to draw a mouse cursor using the regular graphics API, to help you visualize the difference between a "hardware" cursor and a regularly rendered software cursor. -However, rendering a mouse cursor at 60 FPS will feel sluggish so you likely won't want to enable that at +However, rendering a mouse cursor at 60 FPS will feel sluggish, so you likely won't want to enable that at all times. It might be beneficial for the user experience to switch to a software rendered cursor _only_ when an interactive drag is in progress. -Note that some setup or GPU drivers are likely to be causing extra display lag depending on their settings. -If you feel that dragging windows feels laggy and you are not sure what the cause is: try to build a simple -drawing a flat 2D shape directly under the mouse cursor! +Note that some setup configurations or GPU drivers may introduce additional display lag depending on their settings. +If you notice that dragging windows is laggy and you are not sure what the cause is: try drawing a simple +2D shape directly under the mouse cursor to help identify the issue! From 9b0e61aaaa7af2e39b8963d16542e2924813d3f5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 19 Dec 2024 15:10:44 +0100 Subject: [PATCH 321/548] InputText: sanity checks to e.g. detect non zero-terminated buffers + removed a redundant strlen() call during activation. --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 25649c16f28d..b6365be59053 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,8 @@ Other changes: were not applied when pasting from clipbard. (#8229) - InputText: Fixed issue when activating a ReadOnly field when the underlying value is being modified. (#8242) +- InputText: Added sanity check to detect some cases of passing a non + zero-terminated input buffer. - Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to disable keyboard modifiers altering the tweak speed. Useful if you want to alter tweak speed yourself based on your own logic. (#8223) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index b8680ab34714..335ab4cde32c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4389,6 +4389,7 @@ void ImGui::InputTextDeactivateHook(ImGuiID id) else { IM_ASSERT(state->TextA.Data != 0); + IM_ASSERT(state->TextA[state->TextLen] == 0); g.InputTextDeactivatedState.TextA.resize(state->TextLen + 1); memcpy(g.InputTextDeactivatedState.TextA.Data, state->TextA.Data, state->TextLen + 1); } @@ -4519,6 +4520,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (init_reload_from_user_buf) { int new_len = (int)strlen(buf); + IM_ASSERT(new_len + 1 <= buf_size && "Is your input buffer properly zero-terminated?"); state->WantReloadUserBuf = false; InputTextReconcileUndoState(state, state->TextA.Data, state->TextLen, buf, new_len); state->TextA.resize(buf_size + 1); // we use +1 to make sure that .Data is always pointing to at least an empty string. @@ -4540,6 +4542,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Take a copy of the initial buffer value. // From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode) const int buf_len = (int)strlen(buf); + IM_ASSERT(buf_len + 1 <= buf_size && "Is your input buffer properly zero-terminated?"); state->TextToRevertTo.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string. memcpy(state->TextToRevertTo.Data, buf, buf_len + 1); @@ -4551,7 +4554,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Start edition state->ID = id; - state->TextLen = (int)strlen(buf); + state->TextLen = buf_len; if (!is_readonly) { state->TextA.resize(buf_size + 1); // we use +1 to make sure that .Data is always pointing to at least an empty string. From fd932297703c6da24b953f0be8e0733e0db4d9cf Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 19 Dec 2024 18:14:22 +0100 Subject: [PATCH 322/548] Tables, MultiSelect: Fixed an issue where column width may be mismeasured when calling BeginMultiSelect() while inside a table. (#8250) --- docs/CHANGELOG.txt | 2 ++ imgui.h | 2 +- imgui_widgets.cpp | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b6365be59053..afd6c57c122a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,6 +49,8 @@ Other changes: value is being modified. (#8242) - InputText: Added sanity check to detect some cases of passing a non zero-terminated input buffer. +- Tables, MultiSelect: Fixed an issue where column width may be mismeasured + when calling BeginMultiSelect() while inside a table. (#8250) - Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to disable keyboard modifiers altering the tweak speed. Useful if you want to alter tweak speed yourself based on your own logic. (#8223) diff --git a/imgui.h b/imgui.h index e1b8796f3623..68558fb4d336 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.7 WIP" -#define IMGUI_VERSION_NUM 19162 +#define IMGUI_VERSION_NUM 19163 #define IMGUI_HAS_TABLE /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 335ab4cde32c..0fef03ab5a8d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7518,6 +7518,12 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel if (flags & ImGuiMultiSelectFlags_BoxSelect2d) flags &= ~ImGuiMultiSelectFlags_BoxSelect1d; + // FIXME: Workaround to the fact we override CursorMaxPos, meaning size measurement are lost. (#8250) + // They should perhaps be stacked properly? + if (ImGuiTable* table = g.CurrentTable) + if (table->CurrentColumn != -1) + TableEndCell(table); // This is currently safe to call multiple time. If that properly is lost we can extract the "save measurement" part of it. + // FIXME: BeginFocusScope() const ImGuiID id = window->IDStack.back(); ms->Clear(); From eed95027956805f83caddc0fd82dd05cdb2ee082 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 20 Dec 2024 14:28:04 +0100 Subject: [PATCH 323/548] Error Handling: Fixed bugs recovering from within a table that created a child window, and from nested child windows. (#1651) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 29 +++++++++++++++++++---------- imgui_internal.h | 2 +- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index afd6c57c122a..f91342903eb8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,8 @@ Breaking changes: Other changes: +- Error Handling: Fixed bugs recovering from within a table that created + a child window, and from nested child windows. (#1651) - InputText: Fixed a bug where character replacements performed from a callback were not applied when pasting from clipbard. (#8229) - InputText: Fixed issue when activating a ReadOnly field when the underlying diff --git a/imgui.cpp b/imgui.cpp index cf59a5a531d4..c5ede70a3284 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3884,7 +3884,8 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas) Time = 0.0f; FrameCount = 0; FrameCountEnded = FrameCountRendered = -1; - WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false; + WithinEndChildID = 0; + WithinFrameScope = WithinFrameScopeWithImplicitWindow = false; GcCompactAll = false; TestEngineHookItems = false; TestEngine = NULL; @@ -6106,10 +6107,10 @@ void ImGui::EndChild() ImGuiContext& g = *GImGui; ImGuiWindow* child_window = g.CurrentWindow; - IM_ASSERT(g.WithinEndChild == false); + const ImGuiID backup_within_end_child_id = g.WithinEndChildID; IM_ASSERT(child_window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() calls - g.WithinEndChild = true; + g.WithinEndChildID = child_window->ID; ImVec2 child_size = child_window->Size; End(); if (child_window->BeginCount == 1) @@ -6141,7 +6142,7 @@ void ImGui::EndChild() if (g.HoveredWindow == child_window) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; } - g.WithinEndChild = false; + g.WithinEndChildID = backup_within_end_child_id; g.LogLinePosY = -FLT_MAX; // To enforce a carriage return } @@ -7773,7 +7774,7 @@ void ImGui::End() // Error checking: verify that user doesn't directly call End() on a child window. if (window->Flags & ImGuiWindowFlags_ChildWindow) - IM_ASSERT_USER_ERROR(g.WithinEndChild, "Must call EndChild() and not End()!"); + IM_ASSERT_USER_ERROR(g.WithinEndChildID == window->ID, "Must call EndChild() and not End()!"); // Close anything that is open if (window->DC.CurrentColumns) @@ -10485,8 +10486,16 @@ void ImGui::ErrorRecoveryTryToRecoverState(const ImGuiErrorRecoveryState* state_ ImGuiWindow* window = g.CurrentWindow; if (window->Flags & ImGuiWindowFlags_ChildWindow) { - IM_ASSERT_USER_ERROR(0, "Missing EndChild()"); - EndChild(); + if (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow) + { + IM_ASSERT_USER_ERROR(0, "Missing EndTable()"); + EndTable(); + } + else + { + IM_ASSERT_USER_ERROR(0, "Missing EndChild()"); + EndChild(); + } } else { @@ -11921,11 +11930,11 @@ void ImGui::EndPopup() NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY); // Child-popups don't need to be laid out - IM_ASSERT(g.WithinEndChild == false); + const ImGuiID backup_within_end_child_id = g.WithinEndChildID; if (window->Flags & ImGuiWindowFlags_ChildWindow) - g.WithinEndChild = true; + g.WithinEndChildID = window->ID; End(); - g.WithinEndChild = false; + g.WithinEndChildID = backup_within_end_child_id; } // Helper to open a popup if mouse button is released over the item diff --git a/imgui_internal.h b/imgui_internal.h index 947277489740..316ac1844441 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2045,9 +2045,9 @@ struct ImGuiContext int FrameCount; int FrameCountEnded; int FrameCountRendered; + ImGuiID WithinEndChildID; // Set within EndChild() bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame() bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed - bool WithinEndChild; // Set within EndChild() bool GcCompactAll; // Request full GC bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log() void* TestEngine; // Test engine user data From 91e8f2b0febbbcb2c7eddf3f4f500fda71089118 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 20 Dec 2024 15:13:49 +0100 Subject: [PATCH 324/548] Debug Tools: Debug Log: hovering 0xXXXXXXXX values in log is allowed even if a popup is blocking mouse access to the debug log window. (#5855) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f91342903eb8..8ecf76cde4e4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -58,6 +58,8 @@ Other changes: yourself based on your own logic. (#8223) - Nav: Fixed an issue where Alt key would clear current active item on windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231) +- Debug Tools: Debug Log: hovering 0xXXXXXXXX values in log is allowed even + if a popup is blocking mouse access to the debug log window. (#5855) - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF] diff --git a/imgui.cpp b/imgui.cpp index c5ede70a3284..7d324a194464 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16501,7 +16501,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open) void ImGui::DebugTextUnformattedWithLocateItem(const char* line_begin, const char* line_end) { TextUnformatted(line_begin, line_end); - if (!IsItemHovered()) + if (!IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) return; ImGuiContext& g = *GImGui; ImRect text_rect = g.LastItemData.Rect; From d30e102f3adab20865fd74864ddadd94d7559973 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 20 Dec 2024 15:22:34 +0100 Subject: [PATCH 325/548] Scrollbar, TestEngine: for consistency, scrollbars are registered in _Menu layer. Amend f31d530. --- imgui.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 7d324a194464..797f968d9ec7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6731,9 +6731,10 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar ImGuiStyle& style = g.Style; ImGuiWindowFlags flags = window->Flags; - // Ensure that ScrollBar doesn't read last frame's SkipItems + // Ensure that Scrollbar() doesn't read last frame's SkipItems IM_ASSERT(window->BeginCount == 0); window->SkipItems = false; + window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; // Draw window + handle manual resize // As we highlight the title bar when want_focus is set, multiple reappearing windows will have their title bar highlighted on their reappearing frame. @@ -6810,6 +6811,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar if (handle_borders_and_resize_grips) RenderWindowOuterBorders(window); } + window->DC.NavLayerCurrent = ImGuiNavLayer_Main; } // Render title text, collapse button, close button From 61d4bf95dc5345c77b97b279011fce2c46efcaa8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 20 Dec 2024 17:17:40 +0100 Subject: [PATCH 326/548] Fonts: Allowing PushFont()/PopFont() to be called outside the imgui frame scope. (#3621) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8ecf76cde4e4..8a091be6a411 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -58,6 +58,7 @@ Other changes: yourself based on your own logic. (#8223) - Nav: Fixed an issue where Alt key would clear current active item on windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231) +- Fonts: Allowing PushFont()/PopFont() to be called outside the imgui frame scope. (#3621) - Debug Tools: Debug Log: hovering 0xXXXXXXXX values in log is allowed even if a popup is blocking mouse access to the debug log window. (#5855) - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for diff --git a/imgui.cpp b/imgui.cpp index 797f968d9ec7..f074f4fe50cf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8018,7 +8018,8 @@ void ImGui::PushFont(ImFont* font) font = GetDefaultFont(); g.FontStack.push_back(font); SetCurrentFont(font); - g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID); + if (ImGuiWindow* window = g.CurrentWindow) + window->DrawList->_SetTextureID(font->ContainerAtlas->TexID); } void ImGui::PopFont() @@ -8032,7 +8033,8 @@ void ImGui::PopFont() g.FontStack.pop_back(); ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back(); SetCurrentFont(font); - g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID); + if (ImGuiWindow* window = g.CurrentWindow) + window->DrawList->_SetTextureID(font->ContainerAtlas->TexID); } void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) From 7219fa65c0212de1d352b5db8f7dfe43b11f00c9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 20 Dec 2024 17:20:57 +0100 Subject: [PATCH 327/548] Revert "Fonts: Allowing PushFont()/PopFont() to be called outside the imgui frame scope. (#3621)" This reverts commit 61d4bf95dc5345c77b97b279011fce2c46efcaa8. --- docs/CHANGELOG.txt | 1 - imgui.cpp | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8a091be6a411..8ecf76cde4e4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -58,7 +58,6 @@ Other changes: yourself based on your own logic. (#8223) - Nav: Fixed an issue where Alt key would clear current active item on windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231) -- Fonts: Allowing PushFont()/PopFont() to be called outside the imgui frame scope. (#3621) - Debug Tools: Debug Log: hovering 0xXXXXXXXX values in log is allowed even if a popup is blocking mouse access to the debug log window. (#5855) - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for diff --git a/imgui.cpp b/imgui.cpp index f074f4fe50cf..797f968d9ec7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8018,8 +8018,7 @@ void ImGui::PushFont(ImFont* font) font = GetDefaultFont(); g.FontStack.push_back(font); SetCurrentFont(font); - if (ImGuiWindow* window = g.CurrentWindow) - window->DrawList->_SetTextureID(font->ContainerAtlas->TexID); + g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID); } void ImGui::PopFont() @@ -8033,8 +8032,7 @@ void ImGui::PopFont() g.FontStack.pop_back(); ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back(); SetCurrentFont(font); - if (ImGuiWindow* window = g.CurrentWindow) - window->DrawList->_SetTextureID(font->ContainerAtlas->TexID); + g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID); } void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) From 006721fbd6b0ee0f08256b89282e4b62e3378a79 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 11 Dec 2024 18:15:28 +0100 Subject: [PATCH 328/548] Added ImFontAtlas section index in comments + minor tweaks to DX12 backends. --- backends/imgui_impl_dx12.cpp | 8 +++---- imgui_draw.cpp | 42 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 16dcf5392ffe..24fdb7aa0025 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -19,7 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-12-09: DirectX12: Let user specifies the DepthStencilView format by setting ImGui_ImplDX12_InitInfo::DSVFormat. +// 2024-12-09: DirectX12: Let user specifies the DepthStencilView format by setting ImGui_ImplDX12_InitInfo::DSVFormat. // 2024-11-15: DirectX12: *BREAKING CHANGE* Changed ImGui_ImplDX12_Init() signature to take a ImGui_ImplDX12_InitInfo struct. Legacy ImGui_ImplDX12_Init() signature is still supported (will obsolete). // 2024-11-15: DirectX12: *BREAKING CHANGE* User is now required to pass function pointers to allocate/free SRV Descriptors. We provide convenience legacy fields to pass a single descriptor, matching the old API, but upcoming features will want multiple. // 2024-10-23: DirectX12: Unmap() call specify written range. The range is informational and may be used by debug tools. @@ -409,7 +409,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); IM_ASSERT(SUCCEEDED(hr)); - HANDLE event = CreateEvent(0, 0, 0, 0); + HANDLE event = ::CreateEvent(0, 0, 0, 0); IM_ASSERT(event != nullptr); D3D12_COMMAND_QUEUE_DESC queueDesc = {}; @@ -440,12 +440,12 @@ static void ImGui_ImplDX12_CreateFontsTexture() IM_ASSERT(SUCCEEDED(hr)); fence->SetEventOnCompletion(1, event); - WaitForSingleObject(event, INFINITE); + ::WaitForSingleObject(event, INFINITE); cmdList->Release(); cmdAlloc->Release(); cmdQueue->Release(); - CloseHandle(event); + ::CloseHandle(event); fence->Release(); uploadBuffer->Release(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 6caba22fa5bd..42bfb71625cf 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2386,6 +2386,38 @@ ImFontConfig::ImFontConfig() //----------------------------------------------------------------------------- // [SECTION] ImFontAtlas //----------------------------------------------------------------------------- +// - Default texture data encoded in ASCII +// - ImFontAtlas::ClearInputData() +// - ImFontAtlas::ClearTexData() +// - ImFontAtlas::ClearFonts() +// - ImFontAtlas::Clear() +// - ImFontAtlas::GetTexDataAsAlpha8() +// - ImFontAtlas::GetTexDataAsRGBA32() +// - ImFontAtlas::AddFont() +// - ImFontAtlas::AddFontDefault() +// - ImFontAtlas::AddFontFromFileTTF() +// - ImFontAtlas::AddFontFromMemoryTTF() +// - ImFontAtlas::AddFontFromMemoryCompressedTTF() +// - ImFontAtlas::AddFontFromMemoryCompressedBase85TTF() +// - ImFontAtlas::AddCustomRectRegular() +// - ImFontAtlas::AddCustomRectFontGlyph() +// - ImFontAtlas::CalcCustomRectUV() +// - ImFontAtlas::GetMouseCursorTexData() +// - ImFontAtlas::Build() +// - ImFontAtlasBuildMultiplyCalcLookupTable() +// - ImFontAtlasBuildMultiplyRectAlpha8() +// - ImFontAtlasBuildWithStbTruetype() +// - ImFontAtlasGetBuilderForStbTruetype() +// - ImFontAtlasUpdateConfigDataPointers() +// - ImFontAtlasBuildSetupFont() +// - ImFontAtlasBuildPackCustomRects() +// - ImFontAtlasBuildRender8bppRectFromString() +// - ImFontAtlasBuildRender32bppRectFromString() +// - ImFontAtlasBuildRenderDefaultTexData() +// - ImFontAtlasBuildRenderLinesTexData() +// - ImFontAtlasBuildInit() +// - ImFontAtlasBuildFinish() +//----------------------------------------------------------------------------- // A work of art lies ahead! (. = white layer, X = black layer, others are blank) // The 2x2 white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes. @@ -3327,6 +3359,16 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas) //------------------------------------------------------------------------- // [SECTION] ImFontAtlas: glyph ranges helpers //------------------------------------------------------------------------- +// - GetGlyphRangesDefault() +// - GetGlyphRangesGreek() +// - GetGlyphRangesKorean() +// - GetGlyphRangesChineseFull() +// - GetGlyphRangesChineseSimplifiedCommon() +// - GetGlyphRangesJapanese() +// - GetGlyphRangesCyrillic() +// - GetGlyphRangesThai() +// - GetGlyphRangesVietnamese() +//----------------------------------------------------------------------------- // Retrieve list of range (2 int per range, values are inclusive) const ImWchar* ImFontAtlas::GetGlyphRangesDefault() From 2a600bddcbe20fb7832cb0dfafb305704c0422be Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 20 Dec 2024 23:11:37 +0100 Subject: [PATCH 329/548] ImGuiDebugLogFlags_EventFont should not be set by default (had no effect on master tho) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 797f968d9ec7..efa9c450130a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4062,7 +4062,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas) StackSizesInBeginForCurrentWindow = NULL; DebugDrawIdConflictsCount = 0; - DebugLogFlags = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_OutputToTTY | ImGuiDebugLogFlags_EventFont; + DebugLogFlags = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_OutputToTTY; DebugLocateId = 0; DebugLogSkippedErrors = 0; DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None; From 18929bd6d6cffbacdae7a10732f58de9fdb540a0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 20 Dec 2024 23:26:21 +0100 Subject: [PATCH 330/548] Internals: merge ScaleWindowsInViewport() from docking branch. --- imgui.cpp | 19 +++++++++++++++++++ imgui_internal.h | 1 + 2 files changed, 20 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index efa9c450130a..47ac6046aa3c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -14788,6 +14788,7 @@ void ImGui::LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count) //----------------------------------------------------------------------------- // - GetMainViewport() // - SetWindowViewport() [Internal] +// - ScaleWindowsInViewport() [Internal] // - UpdateViewportsNewFrame() [Internal] // (this section is more complete in the 'docking' branch) //----------------------------------------------------------------------------- @@ -14803,6 +14804,24 @@ void ImGui::SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport) window->Viewport = viewport; } +static void ScaleWindow(ImGuiWindow* window, float scale) +{ + ImVec2 origin = window->Viewport->Pos; + window->Pos = ImFloor((window->Pos - origin) * scale + origin); + window->Size = ImTrunc(window->Size * scale); + window->SizeFull = ImTrunc(window->SizeFull * scale); + window->ContentSize = ImTrunc(window->ContentSize * scale); +} + +// Scale all windows (position, size). Use when e.g. changing DPI. (This is a lossy operation!) +void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale) +{ + ImGuiContext& g = *GImGui; + for (ImGuiWindow* window : g.Windows) + if (window->Viewport == viewport) + ScaleWindow(window, scale); +} + // Update viewports and monitor infos static void ImGui::UpdateViewportsNewFrame() { diff --git a/imgui_internal.h b/imgui_internal.h index 316ac1844441..881e2ffd654f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3020,6 +3020,7 @@ namespace ImGui IMGUI_API void CallContextHooks(ImGuiContext* context, ImGuiContextHookType type); // Viewports + IMGUI_API void ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale); IMGUI_API void SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport); // Settings From 6982ce43f5b143c5dce5fab0ce07dd4867b705ae Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 22 Dec 2024 17:53:09 +0100 Subject: [PATCH 331/548] InputText: fixed badly broken clipboard copy/bug (#8254, #8242) Broken by 32f1140 --- imgui_widgets.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 0fef03ab5a8d..e19974f665b4 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4900,8 +4900,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const int ib = state->HasSelection() ? ImMin(state->Stb->select_start, state->Stb->select_end) : 0; const int ie = state->HasSelection() ? ImMax(state->Stb->select_start, state->Stb->select_end) : state->TextLen; g.TempBuffer.reserve(ie - ib + 1); - memcpy(g.TempBuffer.Data, state->TextSrc, ie - ib); - g.TempBuffer.Data[ie] = 0; + memcpy(g.TempBuffer.Data, state->TextSrc + ib, ie - ib); + g.TempBuffer.Data[ie - ib] = 0; SetClipboardText(g.TempBuffer.Data); } if (is_cut) From 87f3109c1af835be0e5b4b4410baa1c66ced7b33 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Fri, 3 Jan 2025 21:07:42 +0100 Subject: [PATCH 332/548] Fix capitalization of ImGuiID in comment. (#8283) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 68558fb4d336..ca9d9bf3769f 100644 --- a/imgui.h +++ b/imgui.h @@ -2895,7 +2895,7 @@ struct ImGuiSelectionBasicStorage IMGUI_API void Clear(); // Clear selection IMGUI_API void Swap(ImGuiSelectionBasicStorage& r); // Swap two selections IMGUI_API void SetItemSelected(ImGuiID id, bool selected); // Add/remove an item from selection (generally done by ApplyRequests() function) - IMGUI_API bool GetNextSelectedItem(void** opaque_it, ImGuiID* out_id); // Iterate selection with 'void* it = NULL; ImGuiId id; while (selection.GetNextSelectedItem(&it, &id)) { ... }' + IMGUI_API bool GetNextSelectedItem(void** opaque_it, ImGuiID* out_id); // Iterate selection with 'void* it = NULL; ImGuiID id; while (selection.GetNextSelectedItem(&it, &id)) { ... }' inline ImGuiID GetStorageIdFromIndex(int idx) { return AdapterIndexToStorageId(this, idx); } // Convert index to item id based on provided adapter. }; From 2d2c7d3f9557074d7a24de4a5b8724ef09fad118 Mon Sep 17 00:00:00 2001 From: Helodity Date: Sun, 22 Dec 2024 22:48:07 -0500 Subject: [PATCH 333/548] Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). --- backends/imgui_impl_allegro5.cpp | 14 ++++++++++++-- docs/CHANGELOG.txt | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 28d1b1536f47..3718b64eace4 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-01-06: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). // 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: // - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn // - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn @@ -95,6 +96,7 @@ struct ImGui_ImplAllegro5_Data ALLEGRO_MOUSE_CURSOR* MouseCursorInvisible; ALLEGRO_VERTEX_DECL* VertexDecl; char* ClipboardTextData; + ImGuiMouseCursor LastCursor; ImVector BufVertices; ImVector BufIndices; @@ -438,6 +440,7 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display) io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) bd->Display = display; + bd->LastCursor = ALLEGRO_SYSTEM_MOUSE_CURSOR_NONE; // Create custom vertex declaration. // Unfortunately Allegro doesn't support 32-bit packed colors so we have to convert them to 4 floats. @@ -568,9 +571,16 @@ static void ImGui_ImplAllegro5_UpdateMouseCursor() ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData(); ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); - if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) + + // Hide OS mouse cursor if imgui is drawing it + if (io.MouseDrawCursor) + imgui_cursor = ImGuiMouseCursor_None; + + if (bd->LastCursor == imgui_cursor) + return; + bd->LastCursor = imgui_cursor; + if (imgui_cursor == ImGuiMouseCursor_None) { - // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor al_set_mouse_cursor(bd->Display, bd->MouseCursorInvisible); } else diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8ecf76cde4e4..1ef576c3d80d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,8 @@ Other changes: windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231) - Debug Tools: Debug Log: hovering 0xXXXXXXXX values in log is allowed even if a popup is blocking mouse access to the debug log window. (#5855) +- Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears + to leak on on X11 (#8256). [@Helodity] - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF] From c147a59bb0e9ad57ee0cac0056a744ff2d97bb3e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 13:58:02 +0100 Subject: [PATCH 334/548] Clarified alternative for ImGuiButtonFlags_Repeat being ImGuiItemFlags_ButtonRepeat. (#8293) --- imgui_internal.h | 2 +- imgui_widgets.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 881e2ffd654f..db3c089ebb24 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -914,7 +914,7 @@ enum ImGuiButtonFlagsPrivate_ ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release) ImGuiButtonFlags_PressedOnDoubleClick = 1 << 8, // return true on double-click (default requires click+release) ImGuiButtonFlags_PressedOnDragDropHold = 1 << 9, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers) - //ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat + //ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat -> use ImGuiItemFlags_ButtonRepeat instead. ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping ImGuiButtonFlags_AllowOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable. //ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e19974f665b4..f8c5ad7a937d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -477,7 +477,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args) // - PressedOnDragDropHold can generally be associated with any flag. // - PressedOnDoubleClick can be associated by PressedOnClickRelease/PressedOnRelease, in which case the second release event won't be reported. //------------------------------------------------------------------------------------------------------------------------------------------------ -// The behavior of the return-value changes when ImGuiButtonFlags_Repeat is set: +// The behavior of the return-value changes when ImGuiItemFlags_ButtonRepeat is set: // Repeat+ Repeat+ Repeat+ Repeat+ // PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick //------------------------------------------------------------------------------------------------------------------------------------------------- From a0f907933d8def4ffcb29fffe887889339c82f11 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 14:07:06 +0100 Subject: [PATCH 335/548] Happy new year! --- LICENSE.txt | 2 +- imgui.cpp | 2 +- imgui.h | 1 + imgui_demo.cpp | 3 ++- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 3282f5b5b105..00ae473abe62 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2024 Omar Cornut +Copyright (c) 2014-2025 Omar Cornut Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/imgui.cpp b/imgui.cpp index 47ac6046aa3c..3bb95bfcea05 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -25,7 +25,7 @@ // please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above. // Everything else should be asked in 'Issues'! We are building a database of cross-linked knowledge there. -// Copyright (c) 2014-2024 Omar Cornut +// Copyright (c) 2014-2025 Omar Cornut // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // See LICENSE.txt for copyright and licensing details (standard MIT License). // This library is free but needs your support to sustain development and maintenance. diff --git a/imgui.h b/imgui.h index ca9d9bf3769f..294eaee009ab 100644 --- a/imgui.h +++ b/imgui.h @@ -2694,6 +2694,7 @@ struct ImGuiListClipper // - It is important that we are keeping those disabled by default so they don't leak in user space. // - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h) // - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4. +// - We intentionally provide ImVec2*float but not float*ImVec2: this is rare enough and we want to reduce the surface for possible user mistake. #ifdef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED IM_MSVC_RUNTIME_CHECKS_OFF diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 621fc4f434b3..c4d93bb74a97 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7692,7 +7692,8 @@ void ImGui::ShowAboutWindow(bool* p_open) ImGui::TextLinkOpenURL("Funding", "https://github.com/ocornut/imgui/wiki/Funding"); ImGui::Separator(); - ImGui::Text("By Omar Cornut and all Dear ImGui contributors."); + ImGui::Text("(c) 2014-2025 Omar Cornut"); + ImGui::Text("Developed by Omar Cornut and all Dear ImGui contributors."); ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information."); ImGui::Text("If your company uses this, please consider funding the project."); From f169102c8eac86efba55aeca33bce5cc77626ae4 Mon Sep 17 00:00:00 2001 From: juur Date: Mon, 6 Jan 2025 12:58:05 +0000 Subject: [PATCH 336/548] Misc: fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) --- docs/CHANGELOG.txt | 1 + misc/cpp/imgui_stdlib.cpp | 3 +++ misc/cpp/imgui_stdlib.h | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1ef576c3d80d..aa5f96e0f7db 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,7 @@ Other changes: windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231) - Debug Tools: Debug Log: hovering 0xXXXXXXXX values in log is allowed even if a popup is blocking mouse access to the debug log window. (#5855) +- Misc: fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] - Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). [@Helodity] - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for diff --git a/misc/cpp/imgui_stdlib.cpp b/misc/cpp/imgui_stdlib.cpp index cf69aa89a630..c04d487cc77a 100644 --- a/misc/cpp/imgui_stdlib.cpp +++ b/misc/cpp/imgui_stdlib.cpp @@ -8,6 +8,7 @@ // https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness #include "imgui.h" +#ifndef IMGUI_DISABLE #include "imgui_stdlib.h" // Clang warnings with -Weverything @@ -83,3 +84,5 @@ bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* #if defined(__clang__) #pragma clang diagnostic pop #endif + +#endif // #ifndef IMGUI_DISABLE diff --git a/misc/cpp/imgui_stdlib.h b/misc/cpp/imgui_stdlib.h index 835a808f2fae..697fc34ad2d3 100644 --- a/misc/cpp/imgui_stdlib.h +++ b/misc/cpp/imgui_stdlib.h @@ -9,6 +9,8 @@ #pragma once +#ifndef IMGUI_DISABLE + #include namespace ImGui @@ -19,3 +21,5 @@ namespace ImGui IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr); IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr); } + +#endif // #ifndef IMGUI_DISABLE From 80aafbc81b0956f9d657ab80838b6fcb2116a8b3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 14:22:03 +0100 Subject: [PATCH 337/548] Data types: moved ImGuiDataType_String to public API as a convenience enum value only. (#8266) --- imgui.h | 3 ++- imgui_internal.h | 3 +-- imgui_widgets.cpp | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/imgui.h b/imgui.h index 294eaee009ab..0f7a99862432 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.7 WIP" -#define IMGUI_VERSION_NUM 19163 +#define IMGUI_VERSION_NUM 19164 #define IMGUI_HAS_TABLE /* @@ -1399,6 +1399,7 @@ enum ImGuiDataType_ ImGuiDataType_Float, // float ImGuiDataType_Double, // double ImGuiDataType_Bool, // bool (provided for user convenience, not supported by scalar widgets) + ImGuiDataType_String, // char* (provided for user convenience, not supported by scalar widgets) ImGuiDataType_COUNT }; diff --git a/imgui_internal.h b/imgui_internal.h index db3c089ebb24..850136b0db2a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -827,8 +827,7 @@ struct ImGuiDataTypeInfo // Extend ImGuiDataType_ enum ImGuiDataTypePrivate_ { - ImGuiDataType_String = ImGuiDataType_COUNT + 1, - ImGuiDataType_Pointer, + ImGuiDataType_Pointer = ImGuiDataType_COUNT + 1, ImGuiDataType_ID, }; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f8c5ad7a937d..854f09634bd0 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2171,6 +2171,7 @@ static const ImGuiDataTypeInfo GDataTypeInfo[] = { sizeof(float), "float", "%.3f","%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg) { sizeof(double), "double","%f", "%lf" }, // ImGuiDataType_Double { sizeof(bool), "bool", "%d", "%d" }, // ImGuiDataType_Bool + { 0, "char*","%s", "%s" }, // ImGuiDataType_String }; IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT); From 2f1194a29618b9ca19d8902643deb6efafe2769c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 14:35:57 +0100 Subject: [PATCH 338/548] Demo: Added label edition to Property Editor demo + fix an ID issue. (#8266) --- docs/CHANGELOG.txt | 3 ++- imgui_demo.cpp | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index aa5f96e0f7db..ab226ebaa0ad 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,7 +60,8 @@ Other changes: windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231) - Debug Tools: Debug Log: hovering 0xXXXXXXXX values in log is allowed even if a popup is blocking mouse access to the debug log window. (#5855) -- Misc: fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] +- Demo: Added label edition to Property Editor demo + fix an ID issue. (#8266) [@moritz-h] +- Misc: Fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] - Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). [@Helodity] - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c4d93bb74a97..36d8f441584b 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -295,6 +295,7 @@ struct ExampleMemberInfo // Metadata description of ExampleTreeNode struct. static const ExampleMemberInfo ExampleTreeNodeMemberInfos[] { + { "MyName", ImGuiDataType_String, 1, offsetof(ExampleTreeNode, Name) }, { "MyBool", ImGuiDataType_Bool, 1, offsetof(ExampleTreeNode, DataMyBool) }, { "MyInt", ImGuiDataType_S32, 1, offsetof(ExampleTreeNode, DataMyInt) }, { "MyVec2", ImGuiDataType_Float, 2, offsetof(ExampleTreeNode, DataMyVec2) }, @@ -8957,6 +8958,8 @@ struct ExampleAppPropertyEditor ImGui::Separator(); if (ImGui::BeginTable("##properties", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY)) { + // Push object ID after we entered the table, so table is shared for all objects + ImGui::PushID((int)node->UID); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 2.0f); // Default twice larger if (node->HasData) @@ -8995,10 +8998,16 @@ struct ExampleAppPropertyEditor ImGui::SliderScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, &v_min, &v_max); break; } + case ImGuiDataType_String: + { + ImGui::InputText("##Editor", reinterpret_cast(field_ptr), 28); + break; + } } ImGui::PopID(); } } + ImGui::PopID(); ImGui::EndTable(); } } From d0021e16215309e3b4f5180cdd35f916ebc7c12a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 15:01:59 +0100 Subject: [PATCH 339/548] Backends: Metal: Fixed resource leak when using multiple contexts. (#7419) --- backends/imgui_impl_metal.mm | 11 ++++------- docs/CHANGELOG.txt | 1 + 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 5680dea9d40c..edd7fa181e29 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -306,17 +306,14 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData, id c indexBufferOffset += (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx); } + __block MetalContext* sharedMetalContext = bd->SharedMetalContext; [commandBuffer addCompletedHandler:^(id) { dispatch_async(dispatch_get_main_queue(), ^{ - ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); - if (bd != nullptr) + @synchronized(bd->SharedMetalContext.bufferCache) { - @synchronized(bd->SharedMetalContext.bufferCache) - { - [bd->SharedMetalContext.bufferCache addObject:vertexBuffer]; - [bd->SharedMetalContext.bufferCache addObject:indexBuffer]; - } + [sharedMetalContext.bufferCache addObject:vertexBuffer]; + [sharedMetalContext.bufferCache addObject:indexBuffer]; } }); }]; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ab226ebaa0ad..da95a1aacc2a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,7 @@ Other changes: - Misc: Fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] - Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). [@Helodity] +- Backends: Metal: Fixed resource leak when using multiple contexts. (#7419) [@anszom] - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF] From e7e898ea179cfeb5a4d62f2387691e8e28395d5e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 16:12:33 +0100 Subject: [PATCH 340/548] Tables: Fixed TableAngledHeadersRow() creating an infinite horizontal scrolling region when the table is hosted in a viewport with negative coordinates. --- docs/CHANGELOG.txt | 3 +++ imgui_tables.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index da95a1aacc2a..f440a7c63b00 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,9 @@ Other changes: value is being modified. (#8242) - InputText: Added sanity check to detect some cases of passing a non zero-terminated input buffer. +- Tables: Fixed TableAngledHeadersRow() creating an infinite horizontal + scrolling region when the table is hosted in a viewport with negative + coordinates. - Tables, MultiSelect: Fixed an issue where column width may be mismeasured when calling BeginMultiSelect() while inside a table. (#8250) - Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to disable keyboard diff --git a/imgui_tables.cpp b/imgui_tables.cpp index e90da3ec73ad..1ab9c703ec5d 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3299,7 +3299,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label const ImVec2 align = g.Style.TableAngledHeadersTextAlign; // Draw background and labels in first pass, then all borders. - float max_x = 0.0f; + float max_x = -FLT_MAX; for (int pass = 0; pass < 2; pass++) for (int order_n = 0; order_n < data_count; order_n++) { From dbf76f62f9e1fbbc38d5cd2c50661994ff4956a1 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 6 Jan 2025 17:17:48 +0100 Subject: [PATCH 341/548] Update issue_template.yml --- .github/ISSUE_TEMPLATE/issue_template.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/issue_template.yml b/.github/ISSUE_TEMPLATE/issue_template.yml index 792d8f63ed49..c1b57de4b739 100644 --- a/.github/ISSUE_TEMPLATE/issue_template.yml +++ b/.github/ISSUE_TEMPLATE/issue_template.yml @@ -5,9 +5,11 @@ body: attributes: value: | FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING or LOADING FONTS, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions) - For anything else: we are happy to use 'GitHub Issues' for many types of open-ended questions. We are encouraging 'Issues' becoming a large, centralized and cross-referenced database of Dear ImGui contents. + For anything else: **we are happy to use 'GitHub Issues' for many types of open-ended questions**. We are encouraging 'Issues' becoming a large, centralized, tagged, cross-referenced database of Dear ImGui contents. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users. + + **If you are using Dear ImGui as part of a job that you are being well-paid for** and your company is not a sponsor. Please be mindful that this is a Free Software and you might be about to ask volunteers to help you doing your job. Please put extra effort describing your issue or question properly. If your company is wealthy, please read [Funding](https://github.com/ocornut/imgui/wiki/Funding) and consider getting in touch. - type: markdown attributes: value: | From a2e21727c0196beb3848b77483662f70f9245c5c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 17:29:04 +0100 Subject: [PATCH 342/548] Backends: Vulkan: moved helpers to backend: ImGui_ImplVulkanH_SelectPhysicalDevice(), ImGui_ImplVulkanH_SelectQueueFamilyIndex(). (#8180) --- backends/imgui_impl_vulkan.cpp | 44 +++++++++++++++++++++++ backends/imgui_impl_vulkan.h | 18 +++++++--- docs/CHANGELOG.txt | 2 ++ examples/example_glfw_vulkan/main.cpp | 48 +++----------------------- examples/example_sdl2_opengl3/main.cpp | 2 +- examples/example_sdl2_vulkan/main.cpp | 48 +++----------------------- examples/example_sdl3_vulkan/main.cpp | 48 +++----------------------- 7 files changed, 72 insertions(+), 138 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 1de6e2353879..1953288d92cf 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -26,6 +26,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-01-06: Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples. // 2024-12-11: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) // 2024-11-27: Vulkan: Make user-provided descriptor pool optional. As a convenience, when setting init_info->DescriptorPoolSize the backend will create one itself. (#8172, #4867) // 2024-10-07: Vulkan: Changed default texture sampler to Clamp instead of Repeat/Wrap. @@ -1334,6 +1335,49 @@ VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_d return VK_PRESENT_MODE_FIFO_KHR; // Always available } +VkPhysicalDevice ImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance) +{ + uint32_t gpu_count; + VkResult err = vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr); + check_vk_result(err); + IM_ASSERT(gpu_count > 0); + + ImVector gpus; + gpus.resize(gpu_count); + err = vkEnumeratePhysicalDevices(instance, &gpu_count, gpus.Data); + check_vk_result(err); + + // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers + // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple + // dedicated GPUs) is out of scope of this sample. + for (VkPhysicalDevice& device : gpus) + { + VkPhysicalDeviceProperties properties; + vkGetPhysicalDeviceProperties(device, &properties); + if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) + return device; + } + + // Use first GPU (Integrated) is a Discrete one is not available. + if (gpu_count > 0) + return gpus[0]; + return VK_NULL_HANDLE; +} + + +uint32_t ImGui_ImplVulkanH_SelectQueueFamilyIndex(VkPhysicalDevice physical_device) +{ + uint32_t count; + vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, nullptr); + ImVector queues_properties; + queues_properties.resize((int)count); + vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, queues_properties.Data); + for (uint32_t i = 0; i < count; i++) + if (queues_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) + return i; + return (uint32_t)-1; +} + void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator) { IM_ASSERT(physical_device != VK_NULL_HANDLE && device != VK_NULL_HANDLE); diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 37f700b62160..5621acbddb64 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -135,18 +135,24 @@ struct ImGui_ImplVulkan_RenderState //------------------------------------------------------------------------- // Internal / Miscellaneous Vulkan Helpers -// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.) //------------------------------------------------------------------------- +// Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app. +// // You probably do NOT need to use or care about those functions. // Those functions only exist because: // 1) they facilitate the readability and maintenance of the multiple main.cpp examples files. // 2) the multi-viewport / platform window implementation needs them internally. -// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings, +// Generally we avoid exposing any kind of superfluous high-level helpers in the backends, // but it is too much code to duplicate everywhere so we exceptionally expose them. // -// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.). -// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work. -// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions) +// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, +// render pass, frame buffers, etc.). You may read this code if you are curious, but +// it is recommended you use you own custom tailored code to do equivalent work. +// +// We don't provide a strong guarantee that we won't change those functions API. +// +// The ImGui_ImplVulkanH_XXX functions should NOT interact with any of the state used +// by the regular ImGui_ImplVulkan_XXX functions). //------------------------------------------------------------------------- struct ImGui_ImplVulkanH_Frame; @@ -157,6 +163,8 @@ IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkIns IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator); IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space); IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count); +IMGUI_IMPL_API VkPhysicalDevice ImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance); +IMGUI_IMPL_API uint32_t ImGui_ImplVulkanH_SelectQueueFamilyIndex(VkPhysicalDevice physical_device); IMGUI_IMPL_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode); // Helper structure to hold the data needed by one rendering frame diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f440a7c63b00..01d00e0ca27c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -70,6 +70,8 @@ Other changes: - Backends: Metal: Fixed resource leak when using multiple contexts. (#7419) [@anszom] - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF] +- Backends: Vulkan: Added a few more ImGui_ImplVulkanH_XXX helper functions + primarily for the purpose of making our examples simpler. ----------------------------------------------------------------------- diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 901b46c4cfd7..1197ca4e6c8b 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -85,35 +85,6 @@ static bool IsExtensionAvailable(const ImVector& properti return false; } -static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice() -{ - uint32_t gpu_count; - VkResult err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr); - check_vk_result(err); - IM_ASSERT(gpu_count > 0); - - ImVector gpus; - gpus.resize(gpu_count); - err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus.Data); - check_vk_result(err); - - // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers - // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple - // dedicated GPUs) is out of scope of this sample. - for (VkPhysicalDevice& device : gpus) - { - VkPhysicalDeviceProperties properties; - vkGetPhysicalDeviceProperties(device, &properties); - if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) - return device; - } - - // Use first GPU (Integrated) is a Discrete one is not available. - if (gpu_count > 0) - return gpus[0]; - return VK_NULL_HANDLE; -} - static void SetupVulkan(ImVector instance_extensions) { VkResult err; @@ -177,23 +148,12 @@ static void SetupVulkan(ImVector instance_extensions) } // Select Physical Device (GPU) - g_PhysicalDevice = SetupVulkan_SelectPhysicalDevice(); + g_PhysicalDevice = ImGui_ImplVulkanH_SelectPhysicalDevice(g_Instance); + IM_ASSERT(g_PhysicalDevice != VK_NULL_HANDLE); // Select graphics queue family - { - uint32_t count; - vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, nullptr); - VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues); - for (uint32_t i = 0; i < count; i++) - if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) - { - g_QueueFamily = i; - break; - } - free(queues); - IM_ASSERT(g_QueueFamily != (uint32_t)-1); - } + g_QueueFamily = ImGui_ImplVulkanH_SelectQueueFamilyIndex(g_PhysicalDevice); + IM_ASSERT(g_QueueFamily != (uint32_t)-1); // Create Logical Device (with 1 queue) { diff --git a/examples/example_sdl2_opengl3/main.cpp b/examples/example_sdl2_opengl3/main.cpp index cb0ade097ac3..51add5c1ffaa 100644 --- a/examples/example_sdl2_opengl3/main.cpp +++ b/examples/example_sdl2_opengl3/main.cpp @@ -87,7 +87,7 @@ int main(int, char**) printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError()); return -1; } - + SDL_GL_MakeCurrent(window, gl_context); SDL_GL_SetSwapInterval(1); // Enable vsync diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index cb116b76eb29..fafa8ea42a76 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -73,35 +73,6 @@ static bool IsExtensionAvailable(const ImVector& properti return false; } -static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice() -{ - uint32_t gpu_count; - VkResult err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr); - check_vk_result(err); - IM_ASSERT(gpu_count > 0); - - ImVector gpus; - gpus.resize(gpu_count); - err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus.Data); - check_vk_result(err); - - // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers - // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple - // dedicated GPUs) is out of scope of this sample. - for (VkPhysicalDevice& device : gpus) - { - VkPhysicalDeviceProperties properties; - vkGetPhysicalDeviceProperties(device, &properties); - if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) - return device; - } - - // Use first GPU (Integrated) is a Discrete one is not available. - if (gpu_count > 0) - return gpus[0]; - return VK_NULL_HANDLE; -} - static void SetupVulkan(ImVector instance_extensions) { VkResult err; @@ -165,23 +136,12 @@ static void SetupVulkan(ImVector instance_extensions) } // Select Physical Device (GPU) - g_PhysicalDevice = SetupVulkan_SelectPhysicalDevice(); + g_PhysicalDevice = ImGui_ImplVulkanH_SelectPhysicalDevice(g_Instance); + IM_ASSERT(g_PhysicalDevice != VK_NULL_HANDLE); // Select graphics queue family - { - uint32_t count; - vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, nullptr); - VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues); - for (uint32_t i = 0; i < count; i++) - if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) - { - g_QueueFamily = i; - break; - } - free(queues); - IM_ASSERT(g_QueueFamily != (uint32_t)-1); - } + g_QueueFamily = ImGui_ImplVulkanH_SelectQueueFamilyIndex(g_PhysicalDevice); + IM_ASSERT(g_QueueFamily != (uint32_t)-1); // Create Logical Device (with 1 queue) { diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index dde3c0d4c1f1..569eaeffb871 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -78,35 +78,6 @@ static bool IsExtensionAvailable(const ImVector& properti return false; } -static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice() -{ - uint32_t gpu_count; - VkResult err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr); - check_vk_result(err); - IM_ASSERT(gpu_count > 0); - - ImVector gpus; - gpus.resize(gpu_count); - err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus.Data); - check_vk_result(err); - - // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers - // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple - // dedicated GPUs) is out of scope of this sample. - for (VkPhysicalDevice& device : gpus) - { - VkPhysicalDeviceProperties properties; - vkGetPhysicalDeviceProperties(device, &properties); - if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) - return device; - } - - // Use first GPU (Integrated) is a Discrete one is not available. - if (gpu_count > 0) - return gpus[0]; - return VK_NULL_HANDLE; -} - static void SetupVulkan(ImVector instance_extensions) { VkResult err; @@ -170,23 +141,12 @@ static void SetupVulkan(ImVector instance_extensions) } // Select Physical Device (GPU) - g_PhysicalDevice = SetupVulkan_SelectPhysicalDevice(); + g_PhysicalDevice = ImGui_ImplVulkanH_SelectPhysicalDevice(g_Instance); + IM_ASSERT(g_PhysicalDevice != VK_NULL_HANDLE); // Select graphics queue family - { - uint32_t count; - vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, nullptr); - VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues); - for (uint32_t i = 0; i < count; i++) - if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) - { - g_QueueFamily = i; - break; - } - free(queues); - IM_ASSERT(g_QueueFamily != (uint32_t)-1); - } + g_QueueFamily = ImGui_ImplVulkanH_SelectQueueFamilyIndex(g_PhysicalDevice); + IM_ASSERT(g_QueueFamily != (uint32_t)-1); // Create Logical Device (with 1 queue) { From 38e606a153b9e52f166ccfbd4ae105627fb12ae7 Mon Sep 17 00:00:00 2001 From: Jovan Ristic Date: Sat, 23 Nov 2024 12:41:19 -0800 Subject: [PATCH 343/548] Examples: Add Win32+Vulkan example. (#8180) --- examples/example_win32_vulkan/build_win32.bat | 9 + examples/example_win32_vulkan/build_win64.bat | 9 + .../example_win32_vulkan.vcxproj | 180 ++++++ .../example_win32_vulkan.vcxproj.filters | 65 ++ examples/example_win32_vulkan/main.cpp | 600 ++++++++++++++++++ examples/imgui_examples.sln | 10 + 6 files changed, 873 insertions(+) create mode 100644 examples/example_win32_vulkan/build_win32.bat create mode 100644 examples/example_win32_vulkan/build_win64.bat create mode 100644 examples/example_win32_vulkan/example_win32_vulkan.vcxproj create mode 100644 examples/example_win32_vulkan/example_win32_vulkan.vcxproj.filters create mode 100644 examples/example_win32_vulkan/main.cpp diff --git a/examples/example_win32_vulkan/build_win32.bat b/examples/example_win32_vulkan/build_win32.bat new file mode 100644 index 000000000000..4bfb7cafc68b --- /dev/null +++ b/examples/example_win32_vulkan/build_win32.bat @@ -0,0 +1,9 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +@set OUT_DIR=Debug +@set OUT_EXE=example_win32_vulkan +@set INCLUDES=/I..\.. /I..\..\backends /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I %VULKAN_SDK%\include +@set SOURCES=main.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_win32.cpp ..\..\imgui*.cpp +@set LIBS=/libpath:%VULKAN_SDK%\lib32 vulkan-1.lib + +mkdir %OUT_DIR% +cl /nologo /Zi /MD /utf-8 %INCLUDES% /D UNICODE /D _UNICODE %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% diff --git a/examples/example_win32_vulkan/build_win64.bat b/examples/example_win32_vulkan/build_win64.bat new file mode 100644 index 000000000000..f8c66f799531 --- /dev/null +++ b/examples/example_win32_vulkan/build_win64.bat @@ -0,0 +1,9 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +@set OUT_DIR=Debug +@set OUT_EXE=example_win32_vulkan +@set INCLUDES=/I..\.. /I..\..\backends /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I %VULKAN_SDK%\include +@set SOURCES=main.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_win32.cpp ..\..\imgui*.cpp +@set LIBS=/libpath:%VULKAN_SDK%\lib vulkan-1.lib + +mkdir %OUT_DIR% +cl /nologo /Zi /MD /utf-8 %INCLUDES% /D UNICODE /D _UNICODE %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% diff --git a/examples/example_win32_vulkan/example_win32_vulkan.vcxproj b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj new file mode 100644 index 000000000000..cbf01a4ab2b3 --- /dev/null +++ b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj @@ -0,0 +1,180 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {4CB8C22A-96F8-4D31-B747-FDAA6B742E47} + example_win32_vulkan + 10.0 + + + + Application + true + Unicode + v143 + + + Application + true + Unicode + v143 + + + Application + false + true + Unicode + v143 + + + Application + false + true + Unicode + v143 + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + + Level4 + Disabled + ..\..;..\..\backends;%VULKAN_SDK%\include;%(AdditionalIncludeDirectories) + _UNICODE;UNICODE;%(PreprocessorDefinitions) + /utf-8 %(AdditionalOptions) + + + true + vulkan-1.lib;%(AdditionalDependencies) + %VULKAN_SDK%\lib32;%(AdditionalLibraryDirectories) + Console + + + + + Level4 + Disabled + ..\..;..\..\backends;%VULKAN_SDK%\include;%(AdditionalIncludeDirectories) + _UNICODE;UNICODE;%(PreprocessorDefinitions) + /utf-8 %(AdditionalOptions) + + + true + vulkan-1.lib;%(AdditionalDependencies) + %VULKAN_SDK%\lib;%(AdditionalLibraryDirectories) + Console + + + + + Level4 + MaxSpeed + true + true + ..\..;..\..\backends;%VULKAN_SDK%\include;%(AdditionalIncludeDirectories) + _UNICODE;UNICODE;%(PreprocessorDefinitions) + /utf-8 %(AdditionalOptions) + + + true + true + true + vulkan-1.lib;%(AdditionalDependencies) + %VULKAN_SDK%\lib32;%(AdditionalLibraryDirectories) + Console + + + + + Level4 + MaxSpeed + true + true + ..\..;..\..\backends;%VULKAN_SDK%\include;%(AdditionalIncludeDirectories) + _UNICODE;UNICODE;%(PreprocessorDefinitions) + /utf-8 %(AdditionalOptions) + + + true + true + true + vulkan-1.lib;%(AdditionalDependencies) + %VULKAN_SDK%\lib;%(AdditionalLibraryDirectories) + Console + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/example_win32_vulkan/example_win32_vulkan.vcxproj.filters b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj.filters new file mode 100644 index 000000000000..a514e6830653 --- /dev/null +++ b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj.filters @@ -0,0 +1,65 @@ + + + + + {fb3d294f-51ec-478e-a627-25831c80fefd} + + + {4f33ddea-9910-456d-b868-4267eb3c2b19} + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + + + imgui + + + sources + + + imgui + + + imgui + + + sources + + + sources + + + imgui + + + imgui + + + + + + imgui + + + + + imgui + + + \ No newline at end of file diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp new file mode 100644 index 000000000000..f3f6367b04c7 --- /dev/null +++ b/examples/example_win32_vulkan/main.cpp @@ -0,0 +1,600 @@ +// Dear ImGui: standalone example application for Vulkan + +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). +// - Introduction, links and more at the top of imgui.cpp + +// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app. +// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h. +// You will use those if you want to use this rendering backend in your engine/app. +// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by +// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code. +// Read comments in imgui_impl_vulkan.h. + +#include "imgui.h" +#include "imgui_impl_win32.h" +#define VK_USE_PLATFORM_WIN32_KHR +#include "imgui_impl_vulkan.h" +#include +#include // printf, fprintf +#include // abort +#include + +// Volk headers +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK +#define VOLK_IMPLEMENTATION +#include +#endif + +//#define APP_USE_UNLIMITED_FRAME_RATE +#ifdef _DEBUG +#define APP_USE_VULKAN_DEBUG_REPORT +#endif + +// Data +static VkAllocationCallbacks* g_Allocator = nullptr; +static VkInstance g_Instance = VK_NULL_HANDLE; +static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static uint32_t g_QueueFamily = (uint32_t)-1; +static VkQueue g_Queue = VK_NULL_HANDLE; +static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; + +static ImGui_ImplVulkanH_Window g_MainWindowData; +static uint32_t g_MinImageCount = 2; +static bool g_SwapChainRebuild = false; + +static void check_vk_result(VkResult err) +{ + if (err == 0) + return; + fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err); + if (err < 0) + abort(); +} + +#ifdef APP_USE_VULKAN_DEBUG_REPORT +static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) +{ + (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments + fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage); + return VK_FALSE; +} +#endif // APP_USE_VULKAN_DEBUG_REPORT + +static bool IsExtensionAvailable(const ImVector& properties, const char* extension) +{ + for (const VkExtensionProperties& p : properties) + if (strcmp(p.extensionName, extension) == 0) + return true; + return false; +} + +static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice() +{ + uint32_t gpu_count; + VkResult err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr); + check_vk_result(err); + IM_ASSERT(gpu_count > 0); + + ImVector gpus; + gpus.resize(gpu_count); + err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus.Data); + check_vk_result(err); + + // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers + // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple + // dedicated GPUs) is out of scope of this sample. + for (VkPhysicalDevice& device : gpus) + { + VkPhysicalDeviceProperties properties; + vkGetPhysicalDeviceProperties(device, &properties); + if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) + return device; + } + + // Use first GPU (Integrated) is a Discrete one is not available. + if (gpu_count > 0) + return gpus[0]; + return VK_NULL_HANDLE; +} + +static void SetupVulkan(ImVector instance_extensions) +{ + VkResult err; +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK + volkInitialize(); +#endif + + // Create Vulkan Instance + { + VkInstanceCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + + // Enumerate available extensions + uint32_t properties_count; + ImVector properties; + vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, nullptr); + properties.resize(properties_count); + err = vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, properties.Data); + check_vk_result(err); + + // Enable required extensions + if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) + instance_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); +#ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME + if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) + { + instance_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + } +#endif + + // Enabling validation layers +#ifdef APP_USE_VULKAN_DEBUG_REPORT + const char* layers[] = { "VK_LAYER_KHRONOS_validation" }; + create_info.enabledLayerCount = 1; + create_info.ppEnabledLayerNames = layers; + instance_extensions.push_back("VK_EXT_debug_report"); +#endif + + // Create Vulkan Instance + create_info.enabledExtensionCount = (uint32_t)instance_extensions.Size; + create_info.ppEnabledExtensionNames = instance_extensions.Data; + err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); + check_vk_result(err); +#ifdef IMGUI_IMPL_VULKAN_USE_VOLK + volkLoadInstance(g_Instance); +#endif + + // Setup the debug report callback +#ifdef APP_USE_VULKAN_DEBUG_REPORT + auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); + IM_ASSERT(f_vkCreateDebugReportCallbackEXT != nullptr); + VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; + debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; + debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; + debug_report_ci.pfnCallback = debug_report; + debug_report_ci.pUserData = nullptr; + err = f_vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport); + check_vk_result(err); +#endif + } + + // Select Physical Device (GPU) + g_PhysicalDevice = SetupVulkan_SelectPhysicalDevice(); + + // Select graphics queue family + { + uint32_t count; + vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, nullptr); + VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count); + vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues); + for (uint32_t i = 0; i < count; i++) + if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + g_QueueFamily = i; + break; + } + free(queues); + IM_ASSERT(g_QueueFamily != (uint32_t)-1); + } + + // Create Logical Device (with 1 queue) + { + ImVector device_extensions; + device_extensions.push_back("VK_KHR_swapchain"); + + // Enumerate physical device extension + uint32_t properties_count; + ImVector properties; + vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, nullptr); + properties.resize(properties_count); + vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, properties.Data); +#ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME + if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) + device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); +#endif + + const float queue_priority[] = { 1.0f }; + VkDeviceQueueCreateInfo queue_info[1] = {}; + queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_info[0].queueFamilyIndex = g_QueueFamily; + queue_info[0].queueCount = 1; + queue_info[0].pQueuePriorities = queue_priority; + VkDeviceCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]); + create_info.pQueueCreateInfos = queue_info; + create_info.enabledExtensionCount = (uint32_t)device_extensions.Size; + create_info.ppEnabledExtensionNames = device_extensions.Data; + err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device); + check_vk_result(err); + vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue); + } + + // Create Descriptor Pool + // The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that) + // If you wish to load e.g. additional textures you may need to alter pools sizes. + { + VkDescriptorPoolSize pool_sizes[] = + { + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 }, + }; + VkDescriptorPoolCreateInfo pool_info = {}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; + pool_info.maxSets = 1; + pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); + pool_info.pPoolSizes = pool_sizes; + err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); + check_vk_result(err); + } +} + +// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo. +// Your real engine/app may not use them. +static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height) +{ + wd->Surface = surface; + + // Check for WSI support + VkBool32 res; + vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res); + if (res != VK_TRUE) + { + fprintf(stderr, "Error no WSI support on physical device 0\n"); + exit(-1); + } + + // Select Surface Format + const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; + const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; + wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); + + // Select Present Mode +#ifdef APP_UNLIMITED_FRAME_RATE + VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR }; +#else + VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; +#endif + wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes)); + //printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode); + + // Create SwapChain, RenderPass, Framebuffer, etc. + IM_ASSERT(g_MinImageCount >= 2); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount); +} + +static void CleanupVulkan() +{ + vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator); + +#ifdef APP_USE_VULKAN_DEBUG_REPORT + // Remove the debug report callback + auto f_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); + f_vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); +#endif // APP_USE_VULKAN_DEBUG_REPORT + + vkDestroyDevice(g_Device, g_Allocator); + vkDestroyInstance(g_Instance, g_Allocator); +} + +static void CleanupVulkanWindow() +{ + ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator); +} + +static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data) +{ + VkResult err; + + VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; + VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; + err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); + if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) + { + g_SwapChainRebuild = true; + return; + } + check_vk_result(err); + + ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; + { + err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking + check_vk_result(err); + + err = vkResetFences(g_Device, 1, &fd->Fence); + check_vk_result(err); + } + { + err = vkResetCommandPool(g_Device, fd->CommandPool, 0); + check_vk_result(err); + VkCommandBufferBeginInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + err = vkBeginCommandBuffer(fd->CommandBuffer, &info); + check_vk_result(err); + } + { + VkRenderPassBeginInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + info.renderPass = wd->RenderPass; + info.framebuffer = fd->Framebuffer; + info.renderArea.extent.width = wd->Width; + info.renderArea.extent.height = wd->Height; + info.clearValueCount = 1; + info.pClearValues = &wd->ClearValue; + vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE); + } + + // Record dear imgui primitives into command buffer + ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer); + + // Submit command buffer + vkCmdEndRenderPass(fd->CommandBuffer); + { + VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + info.waitSemaphoreCount = 1; + info.pWaitSemaphores = &image_acquired_semaphore; + info.pWaitDstStageMask = &wait_stage; + info.commandBufferCount = 1; + info.pCommandBuffers = &fd->CommandBuffer; + info.signalSemaphoreCount = 1; + info.pSignalSemaphores = &render_complete_semaphore; + + err = vkEndCommandBuffer(fd->CommandBuffer); + check_vk_result(err); + err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence); + check_vk_result(err); + } +} + +static void FramePresent(ImGui_ImplVulkanH_Window* wd) +{ + if (g_SwapChainRebuild) + return; + VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; + VkPresentInfoKHR info = {}; + info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + info.waitSemaphoreCount = 1; + info.pWaitSemaphores = &render_complete_semaphore; + info.swapchainCount = 1; + info.pSwapchains = &wd->Swapchain; + info.pImageIndices = &wd->FrameIndex; + VkResult err = vkQueuePresentKHR(g_Queue, &info); + if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) + { + g_SwapChainRebuild = true; + return; + } + check_vk_result(err); + wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores +} + +LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +// Main code +int main(int, char**) +{ + // Create application window + //ImGui_ImplWin32_EnableDpiAwareness(); + WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr }; + ::RegisterClassExW(&wc); + HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui Vulkan Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr); + + ImVector extensions; + extensions.push_back("VK_KHR_surface"); + extensions.push_back("VK_KHR_win32_surface"); + SetupVulkan(extensions); + + // Create Window Surface + VkSurfaceKHR surface; + VkResult err; + VkWin32SurfaceCreateInfoKHR createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + createInfo.hwnd = hwnd; + createInfo.hinstance = GetModuleHandle(nullptr); + if (vkCreateWin32SurfaceKHR(g_Instance, &createInfo, nullptr, &surface) != VK_SUCCESS) + { + printf("Failed to create Vulkan surface.\n"); + return 1; + } + + // Show the window + ImGui_ImplVulkanH_Window* wd = &g_MainWindowData; + SetupVulkanWindow(wd, surface, 1280, 800); + ::ShowWindow(hwnd, SW_SHOWDEFAULT); + ::UpdateWindow(hwnd); + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + // Setup Platform/Renderer backends + ImGui_ImplWin32_Init(hwnd); + ImGui_ImplVulkan_InitInfo init_info = {}; + init_info.Instance = g_Instance; + init_info.PhysicalDevice = g_PhysicalDevice; + init_info.Device = g_Device; + init_info.QueueFamily = g_QueueFamily; + init_info.Queue = g_Queue; + init_info.PipelineCache = g_PipelineCache; + init_info.DescriptorPool = g_DescriptorPool; + init_info.RenderPass = wd->RenderPass; + init_info.Subpass = 0; + init_info.MinImageCount = g_MinImageCount; + init_info.ImageCount = wd->ImageCount; + init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + init_info.Allocator = g_Allocator; + init_info.CheckVkResultFn = check_vk_result; + ImGui_ImplVulkan_Init(&init_info); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. + // - Read 'docs/FONTS.md' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != nullptr); + + // Our state + bool show_demo_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // Main loop + bool done = false; + while (!done) + { + // Poll and handle messages (inputs, window resize, etc.) + // See the WndProc() function below for our to dispatch events to the Win32 backend. + MSG msg; + while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE)) + { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + if (msg.message == WM_QUIT) + done = true; + } + if (done) + break; + + // Start the Dear ImGui frame + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplWin32_NewFrame(); + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + + ImDrawData* draw_data = ImGui::GetDrawData(); + const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f); + if (!is_minimized) + { + wd->ClearValue.color.float32[0] = clear_color.x * clear_color.w; + wd->ClearValue.color.float32[1] = clear_color.y * clear_color.w; + wd->ClearValue.color.float32[2] = clear_color.z * clear_color.w; + wd->ClearValue.color.float32[3] = clear_color.w; + FrameRender(wd, draw_data); + FramePresent(wd); + } + } + + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + + // Cleanup + ImGui_ImplVulkan_Shutdown(); + ImGui_ImplWin32_Shutdown(); + ImGui::DestroyContext(); + + CleanupVulkanWindow(); + CleanupVulkan(); + + ::DestroyWindow(hwnd); + ::UnregisterClassW(wc.lpszClassName, wc.hInstance); + + return 0; +} + +// Helper functions + +// Forward declare message handler from imgui_impl_win32.cpp +extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +// Win32 message handler +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. +// - 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. +LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) + return true; + + switch (msg) + { + case WM_SIZE: + if (g_Device != VK_NULL_HANDLE && wParam != SIZE_MINIMIZED) + { + // Resize swap chain + int fb_width = (UINT)LOWORD(lParam); + int fb_height = (UINT)HIWORD(lParam); + if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) + { + ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount); + g_MainWindowData.FrameIndex = 0; + g_SwapChainRebuild = false; + } + } + return 0; + case WM_SYSCOMMAND: + if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu + return 0; + break; + case WM_DESTROY: + ::PostQuitMessage(0); + return 0; + } + return ::DefWindowProcW(hWnd, msg, wParam, lParam); +} diff --git a/examples/imgui_examples.sln b/examples/imgui_examples.sln index ea9f65cbd3e9..3a856462a490 100644 --- a/examples/imgui_examples.sln +++ b/examples/imgui_examples.sln @@ -35,6 +35,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_sdlrenderer3", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_vulkan", "example_sdl3_vulkan\example_sdl3_vulkan.vcxproj", "{663A7E89-1E42-4222-921C-177F5B5910DF}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_vulkan", "example_win32_vulkan\example_win32_vulkan.vcxproj", "{4CB8C22A-96F8-4D31-B747-FDAA6B742E47}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -171,6 +173,14 @@ Global {663A7E89-1E42-4222-921C-177F5B5910DF}.Release|Win32.Build.0 = Release|Win32 {663A7E89-1E42-4222-921C-177F5B5910DF}.Release|x64.ActiveCfg = Release|x64 {663A7E89-1E42-4222-921C-177F5B5910DF}.Release|x64.Build.0 = Release|x64 + {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Debug|Win32.ActiveCfg = Debug|Win32 + {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Debug|Win32.Build.0 = Debug|Win32 + {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Debug|x64.ActiveCfg = Debug|x64 + {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Debug|x64.Build.0 = Debug|x64 + {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Release|Win32.ActiveCfg = Release|Win32 + {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Release|Win32.Build.0 = Release|Win32 + {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Release|x64.ActiveCfg = Release|x64 + {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 93a93071a27fc733c96368d179c51bb8e43ddc86 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 17:43:52 +0100 Subject: [PATCH 344/548] Examples: Add Win32+Vulkan example, amends. (#8180) --- docs/CHANGELOG.txt | 1 + docs/EXAMPLES.md | 6 +- examples/example_glfw_vulkan/main.cpp | 2 +- .../example_win32_vulkan.vcxproj | 18 +++--- .../example_win32_vulkan.vcxproj.filters | 26 ++++---- examples/example_win32_vulkan/main.cpp | 61 +++---------------- examples/imgui_examples.sln | 18 +++--- 7 files changed, 46 insertions(+), 86 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 01d00e0ca27c..412ddabdac8c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -72,6 +72,7 @@ Other changes: platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF] - Backends: Vulkan: Added a few more ImGui_ImplVulkanH_XXX helper functions primarily for the purpose of making our examples simpler. +- Examples: Added Win32+Vulkan example for completeness. (#8180) [@jristic] ----------------------------------------------------------------------- diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index f84f9497b6dd..224beb1c16a0 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -167,9 +167,13 @@ DirectX12 example, Windows only.
This is quite long and tedious, because: DirectX12. [example_win32_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_opengl3/)
-Raw Windows + OpenGL3 + example (modern, programmable pipeline)
+Raw Windows + OpenGL3 example (modern, programmable pipeline)
= main.cpp + imgui_impl_win32.cpp + imgui_impl_opengl3.cpp
+[example_win32_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_vulkan/)
+Raw Windows + Vulkan example
+= main.cpp + imgui_impl_win32.cpp + imgui_impl_vulkan.cpp
+ ### Miscellaneous diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 1197ca4e6c8b..9f8dced2f18d 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -52,7 +52,7 @@ static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; -static int g_MinImageCount = 2; +static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; static void glfw_error_callback(int error, const char* description) diff --git a/examples/example_win32_vulkan/example_win32_vulkan.vcxproj b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj index cbf01a4ab2b3..dab8afd4ed71 100644 --- a/examples/example_win32_vulkan/example_win32_vulkan.vcxproj +++ b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj @@ -19,36 +19,35 @@ - {4CB8C22A-96F8-4D31-B747-FDAA6B742E47} - example_win32_vulkan - 10.0 + {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88} + example_win32_directx11 Application true Unicode - v143 + v140 Application true Unicode - v143 + v140 Application false true Unicode - v143 + v140 Application false true Unicode - v143 + v140 @@ -120,6 +119,7 @@ true ..\..;..\..\backends;%VULKAN_SDK%\include;%(AdditionalIncludeDirectories) _UNICODE;UNICODE;%(PreprocessorDefinitions) + false /utf-8 %(AdditionalOptions) @@ -169,11 +169,9 @@ + - - - diff --git a/examples/example_win32_vulkan/example_win32_vulkan.vcxproj.filters b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj.filters index a514e6830653..c91a95810cc1 100644 --- a/examples/example_win32_vulkan/example_win32_vulkan.vcxproj.filters +++ b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj.filters @@ -2,10 +2,10 @@ - {fb3d294f-51ec-478e-a627-25831c80fefd} + {0587d7a3-f2ce-4d56-b84f-a0005d3bfce6} - {4f33ddea-9910-456d-b868-4267eb3c2b19} + {08e36723-ce4f-4cff-9662-c40801cf1acf} @@ -18,10 +18,10 @@ imgui - + sources - + sources @@ -38,28 +38,26 @@ imgui - - sources + + imgui sources - - imgui + + sources - + imgui - + imgui - - - + imgui - + \ No newline at end of file diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp index f3f6367b04c7..3fabf7a2dec5 100644 --- a/examples/example_win32_vulkan/main.cpp +++ b/examples/example_win32_vulkan/main.cpp @@ -1,4 +1,4 @@ -// Dear ImGui: standalone example application for Vulkan +// Dear ImGui: standalone example application for Win32 + Vulkan // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq @@ -74,35 +74,6 @@ static bool IsExtensionAvailable(const ImVector& properti return false; } -static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice() -{ - uint32_t gpu_count; - VkResult err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr); - check_vk_result(err); - IM_ASSERT(gpu_count > 0); - - ImVector gpus; - gpus.resize(gpu_count); - err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus.Data); - check_vk_result(err); - - // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers - // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple - // dedicated GPUs) is out of scope of this sample. - for (VkPhysicalDevice& device : gpus) - { - VkPhysicalDeviceProperties properties; - vkGetPhysicalDeviceProperties(device, &properties); - if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) - return device; - } - - // Use first GPU (Integrated) is a Discrete one is not available. - if (gpu_count > 0) - return gpus[0]; - return VK_NULL_HANDLE; -} - static void SetupVulkan(ImVector instance_extensions) { VkResult err; @@ -166,23 +137,12 @@ static void SetupVulkan(ImVector instance_extensions) } // Select Physical Device (GPU) - g_PhysicalDevice = SetupVulkan_SelectPhysicalDevice(); + g_PhysicalDevice = ImGui_ImplVulkanH_SelectPhysicalDevice(g_Instance); + IM_ASSERT(g_PhysicalDevice != VK_NULL_HANDLE); // Select graphics queue family - { - uint32_t count; - vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, nullptr); - VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues); - for (uint32_t i = 0; i < count; i++) - if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) - { - g_QueueFamily = i; - break; - } - free(queues); - IM_ASSERT(g_QueueFamily != (uint32_t)-1); - } + g_QueueFamily = ImGui_ImplVulkanH_SelectQueueFamilyIndex(g_PhysicalDevice); + IM_ASSERT(g_QueueFamily != (uint32_t)-1); // Create Logical Device (with 1 queue) { @@ -257,7 +217,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); // Select Present Mode -#ifdef APP_UNLIMITED_FRAME_RATE +#ifdef APP_USE_UNLIMITED_FRAME_RATE VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR }; #else VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; @@ -387,7 +347,7 @@ int main(int, char**) //ImGui_ImplWin32_EnableDpiAwareness(); WNDCLASSEXW wc = { sizeof(wc), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr }; ::RegisterClassExW(&wc); - HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui Vulkan Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr); + HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Dear ImGui Win32+Vulkan Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr); ImVector extensions; extensions.push_back("VK_KHR_surface"); @@ -400,7 +360,7 @@ int main(int, char**) VkWin32SurfaceCreateInfoKHR createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; createInfo.hwnd = hwnd; - createInfo.hinstance = GetModuleHandle(nullptr); + createInfo.hinstance = ::GetModuleHandle(nullptr); if (vkCreateWin32SurfaceKHR(g_Instance, &createInfo, nullptr, &surface) != VK_SUCCESS) { printf("Failed to create Vulkan surface.\n"); @@ -408,6 +368,7 @@ int main(int, char**) } // Show the window + // FIXME: Retrieve client size from window itself. ImGui_ImplVulkanH_Window* wd = &g_MainWindowData; SetupVulkanWindow(wd, surface, 1280, 800); ::ShowWindow(hwnd, SW_SHOWDEFAULT); @@ -525,7 +486,6 @@ int main(int, char**) // Rendering ImGui::Render(); - ImDrawData* draw_data = ImGui::GetDrawData(); const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f); if (!is_minimized) @@ -539,10 +499,9 @@ int main(int, char**) } } + // Cleanup err = vkDeviceWaitIdle(g_Device); check_vk_result(err); - - // Cleanup ImGui_ImplVulkan_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); diff --git a/examples/imgui_examples.sln b/examples/imgui_examples.sln index 3a856462a490..85f7451d4f61 100644 --- a/examples/imgui_examples.sln +++ b/examples/imgui_examples.sln @@ -35,7 +35,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_sdlrenderer3", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_vulkan", "example_sdl3_vulkan\example_sdl3_vulkan.vcxproj", "{663A7E89-1E42-4222-921C-177F5B5910DF}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_vulkan", "example_win32_vulkan\example_win32_vulkan.vcxproj", "{4CB8C22A-96F8-4D31-B747-FDAA6B742E47}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_vulkan", "example_win32_vulkan\example_win32_vulkan.vcxproj", "{0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -173,14 +173,14 @@ Global {663A7E89-1E42-4222-921C-177F5B5910DF}.Release|Win32.Build.0 = Release|Win32 {663A7E89-1E42-4222-921C-177F5B5910DF}.Release|x64.ActiveCfg = Release|x64 {663A7E89-1E42-4222-921C-177F5B5910DF}.Release|x64.Build.0 = Release|x64 - {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Debug|Win32.ActiveCfg = Debug|Win32 - {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Debug|Win32.Build.0 = Debug|Win32 - {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Debug|x64.ActiveCfg = Debug|x64 - {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Debug|x64.Build.0 = Debug|x64 - {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Release|Win32.ActiveCfg = Release|Win32 - {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Release|Win32.Build.0 = Release|Win32 - {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Release|x64.ActiveCfg = Release|x64 - {4CB8C22A-96F8-4D31-B747-FDAA6B742E47}.Release|x64.Build.0 = Release|x64 + {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Debug|Win32.ActiveCfg = Debug|Win32 + {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Debug|Win32.Build.0 = Debug|Win32 + {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Debug|x64.ActiveCfg = Debug|x64 + {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Debug|x64.Build.0 = Debug|x64 + {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Release|Win32.ActiveCfg = Release|Win32 + {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Release|Win32.Build.0 = Release|Win32 + {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Release|x64.ActiveCfg = Release|x64 + {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From af271e733039548d62eb7b56e94fd3672304f343 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 18:20:56 +0100 Subject: [PATCH 345/548] Backends: DX11: Expose vertex constant buffer in ImGui_ImplDX11_RenderState. DX9 and DX12 users can already alter the projection matrix (in undocumented ways, but possible) --- backends/imgui_impl_dx11.cpp | 45 ++++++++++++++++++------------------ backends/imgui_impl_dx11.h | 2 ++ docs/CHANGELOG.txt | 2 ++ 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index a2c67ec43f9e..bbd1633a2c95 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-01-06: DirectX11: Expose VertexConstantBuffer in ImGui_ImplDX11_RenderState. Reset projection matrix in ImDrawCallback_ResetRenderState handler. // 2024-10-07: DirectX11: Changed default texture sampler to Clamp instead of Repeat/Wrap. // 2024-10-07: DirectX11: Expose selected render state in ImGui_ImplDX11_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. @@ -98,6 +99,27 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC vp.TopLeftX = vp.TopLeftY = 0; device_ctx->RSSetViewports(1, &vp); + // Setup orthographic projection matrix into our constant buffer + // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (device_ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) == S_OK) + { + VERTEX_CONSTANT_BUFFER_DX11* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX11*)mapped_resource.pData; + float L = draw_data->DisplayPos.x; + float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; + float T = draw_data->DisplayPos.y; + float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; + float mvp[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.5f, 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, + }; + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + device_ctx->Unmap(bd->pVertexConstantBuffer, 0); + } + // Setup shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; @@ -179,28 +201,6 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) device->Unmap(bd->pVB, 0); device->Unmap(bd->pIB, 0); - // Setup orthographic projection matrix into our constant buffer - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. - { - D3D11_MAPPED_SUBRESOURCE mapped_resource; - if (device->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) - return; - VERTEX_CONSTANT_BUFFER_DX11* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX11*)mapped_resource.pData; - float L = draw_data->DisplayPos.x; - float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; - float T = draw_data->DisplayPos.y; - float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; - float mvp[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.5f, 0.0f }, - { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, - }; - memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); - device->Unmap(bd->pVertexConstantBuffer, 0); - } - // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) struct BACKUP_DX11_STATE { @@ -255,6 +255,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) render_state.Device = bd->pd3dDevice; render_state.DeviceContext = bd->pd3dDeviceContext; render_state.SamplerDefault = bd->pFontSampler; + render_state.VertexConstantBuffer = bd->pVertexConstantBuffer; platform_io.Renderer_RenderState = &render_state; // Render command lists diff --git a/backends/imgui_impl_dx11.h b/backends/imgui_impl_dx11.h index 69ae493586fb..772c1b920c05 100644 --- a/backends/imgui_impl_dx11.h +++ b/backends/imgui_impl_dx11.h @@ -21,6 +21,7 @@ struct ID3D11Device; struct ID3D11DeviceContext; struct ID3D11SamplerState; +struct ID3D11Buffer; // Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); @@ -40,6 +41,7 @@ struct ImGui_ImplDX11_RenderState ID3D11Device* Device; ID3D11DeviceContext* DeviceContext; ID3D11SamplerState* SamplerDefault; + ID3D11Buffer* VertexConstantBuffer; }; #endif // #ifndef IMGUI_DISABLE diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 412ddabdac8c..4500f5a1f498 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -72,6 +72,8 @@ Other changes: platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF] - Backends: Vulkan: Added a few more ImGui_ImplVulkanH_XXX helper functions primarily for the purpose of making our examples simpler. +- Backends: DX11: Expose vertex constant buffer in ImGui_ImplDX11_RenderState. + Reset projection matrix in ImDrawCallback_ResetRenderState handlers. (#6969, #5834, #7468, #3590) - Examples: Added Win32+Vulkan example for completeness. (#8180) [@jristic] From f04d3cbdaaf037e5f57bc39c0bd3f0d0c43b98fc Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 18:28:01 +0100 Subject: [PATCH 346/548] Backends: DirectX10: Expose selected render state in ImGui_ImplDX10_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. (#6969, #5834, #7468, #3590) Amend e94f95d --- backends/imgui_impl_dx10.cpp | 56 ++++++++++++++++++++---------------- backends/imgui_impl_dx10.h | 12 ++++++++ backends/imgui_impl_dx11.cpp | 2 +- docs/CHANGELOG.txt | 1 + 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 15f0bb323f5d..89499af0cbaa 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -15,6 +15,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-01-06: DirectX10: Expose selected render state in ImGui_ImplDX10_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 2024-10-07: DirectX10: Changed default texture sampler to Clamp instead of Repeat/Wrap. // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). @@ -95,7 +96,28 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* vp.TopLeftX = vp.TopLeftY = 0; device->RSSetViewports(1, &vp); - // Bind shader and vertex buffers + // Setup orthographic projection matrix into our constant buffer + // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. + void* mapped_resource; + if (bd->pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) == S_OK) + { + VERTEX_CONSTANT_BUFFER_DX10* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX10*)mapped_resource; + float L = draw_data->DisplayPos.x; + float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; + float T = draw_data->DisplayPos.y; + float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; + float mvp[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.5f, 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, + }; + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + bd->pVertexConstantBuffer->Unmap(); + } + + // Setup shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; device->IASetInputLayout(bd->pInputLayout); @@ -171,28 +193,6 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) bd->pVB->Unmap(); bd->pIB->Unmap(); - // Setup orthographic projection matrix into our constant buffer - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. - { - void* mapped_resource; - if (bd->pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) - return; - VERTEX_CONSTANT_BUFFER_DX10* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX10*)mapped_resource; - float L = draw_data->DisplayPos.x; - float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; - float T = draw_data->DisplayPos.y; - float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; - float mvp[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.5f, 0.0f }, - { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, - }; - memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); - bd->pVertexConstantBuffer->Unmap(); - } - // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) struct BACKUP_DX10_STATE { @@ -236,6 +236,13 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) // Setup desired DX state ImGui_ImplDX10_SetupRenderState(draw_data, device); + // Setup render state structure (for callbacks and custom texture bindings) + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + ImGui_ImplDX10_RenderState render_state; + render_state.Device = bd->pd3dDevice; + render_state.SamplerDefault = bd->pFontSampler; + render_state.VertexConstantBuffer = bd->pVertexConstantBuffer; + platform_io.Renderer_RenderState = &render_state; // Render command lists // (Because we merged all buffers into a single one, we maintain our own offset into them) @@ -248,7 +255,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback) + if (pcmd->UserCallback != nullptr) { // User callback, registered via ImDrawList::AddCallback() // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) @@ -278,6 +285,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) global_idx_offset += draw_list->IdxBuffer.Size; global_vtx_offset += draw_list->VtxBuffer.Size; } + platform_io.Renderer_RenderState = nullptr; // Restore modified DX state device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); diff --git a/backends/imgui_impl_dx10.h b/backends/imgui_impl_dx10.h index 29f339370f53..d9f29987d7ee 100644 --- a/backends/imgui_impl_dx10.h +++ b/backends/imgui_impl_dx10.h @@ -18,6 +18,8 @@ #ifndef IMGUI_DISABLE struct ID3D10Device; +struct ID3D10SamplerState; +struct ID3D10Buffer; // Follow "Getting Started" link and check examples/ folder to learn about using backends! IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device); @@ -29,4 +31,14 @@ IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data); IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects(); IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects(); +// [BETA] Selected render state data shared with callbacks. +// This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplDX10_RenderDrawData() call. +// (Please open an issue if you feel you need access to more data) +struct ImGui_ImplDX10_RenderState +{ + ID3D10Device* Device; + ID3D10SamplerState* SamplerDefault; + ID3D10Buffer* VertexConstantBuffer; +}; + #endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index bbd1633a2c95..b38fece264b5 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -136,7 +136,7 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC device_ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. device_ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. - // Setup blend state + // Setup render state const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; device_ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff); device_ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 4500f5a1f498..81763b99c901 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -74,6 +74,7 @@ Other changes: primarily for the purpose of making our examples simpler. - Backends: DX11: Expose vertex constant buffer in ImGui_ImplDX11_RenderState. Reset projection matrix in ImDrawCallback_ResetRenderState handlers. (#6969, #5834, #7468, #3590) +- Backends: DX10: Expose ImGui_ImplDX10_RenderState for completeness. (#6969, #5834, #7468, #3590) - Examples: Added Win32+Vulkan example for completeness. (#8180) [@jristic] From cec8ff1885deb4728cafca5b37bf532f68572e66 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 6 Jan 2025 18:41:17 +0100 Subject: [PATCH 347/548] Backends: Vulkan: Fixed building with using VK_NO_PROTOTYPES. (#8180) Broken by a2e2172 --- backends/imgui_impl_vulkan.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 1953288d92cf..de4c5a4aa7e8 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -164,6 +164,7 @@ static bool g_FunctionsLoaded = true; IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySurfaceKHR) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySwapchainKHR) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDeviceWaitIdle) \ + IMGUI_VULKAN_FUNC_MAP_MACRO(vkEnumeratePhysicalDevices) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkEndCommandBuffer) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkFlushMappedMemoryRanges) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeCommandBuffers) \ @@ -171,7 +172,9 @@ static bool g_FunctionsLoaded = true; IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeMemory) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetBufferMemoryRequirements) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetImageMemoryRequirements) \ + IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceProperties) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceMemoryProperties) \ + IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceQueueFamilyProperties) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceFormatsKHR) \ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfacePresentModesKHR) \ From 3115ae081591fe75b98747a7737eab065f2628f8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 27 Dec 2024 11:49:39 +0100 Subject: [PATCH 348/548] Demo: Font selector combo sets default focus. --- imgui_demo.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 36d8f441584b..c9a21759d456 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7851,6 +7851,8 @@ void ImGui::ShowFontSelector(const char* label) ImGui::PushID((void*)font); if (ImGui::Selectable(font->GetDebugName(), font == font_current)) io.FontDefault = font; + if (font == font_current) + ImGui::SetItemDefaultFocus(); ImGui::PopID(); } ImGui::EndCombo(); From 0514332474fc3ffbb19e886de1b3b167e6aac521 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 8 Jan 2025 11:44:00 +0100 Subject: [PATCH 349/548] Avoid clang/gcc warnings: -Wnontrivial-memaccess in backends. (#8295, #8129, #8135) --- backends/imgui_impl_dx12.h | 2 +- backends/imgui_impl_vulkan.cpp | 2 +- misc/freetype/imgui_freetype.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h index 644c022fffbd..a57c1694d36e 100644 --- a/backends/imgui_impl_dx12.h +++ b/backends/imgui_impl_dx12.h @@ -43,7 +43,7 @@ struct ImGui_ImplDX12_InitInfo D3D12_GPU_DESCRIPTOR_HANDLE LegacySingleSrvGpuDescriptor; #endif - ImGui_ImplDX12_InitInfo() { memset(this, 0, sizeof(*this)); } + ImGui_ImplDX12_InitInfo() { memset((void*)this, 0, sizeof(*this)); } }; // Follow "Getting Started" link and check examples/ folder to learn about using backends! diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index de4c5a4aa7e8..4345f2b11554 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -225,7 +225,7 @@ struct ImGui_ImplVulkan_Texture VkImageView ImageView; VkDescriptorSet DescriptorSet; - ImGui_ImplVulkan_Texture() { memset(this, 0, sizeof(*this)); } + ImGui_ImplVulkan_Texture() { memset((void*)this, 0, sizeof(*this)); } }; // Vulkan data diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index aeab6dfa0689..997bc4340bd5 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -169,7 +169,7 @@ namespace const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint); const FT_Bitmap* RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info); void BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = nullptr); - FreeTypeFont() { memset(this, 0, sizeof(*this)); } + FreeTypeFont() { memset((void*)this, 0, sizeof(*this)); } ~FreeTypeFont() { CloseFont(); } // [Internals] From e6a7c7689f57038b2519fe43e55e3d57103ad0f7 Mon Sep 17 00:00:00 2001 From: Selim Sandal <49725809+selimsandal@users.noreply.github.com> Date: Wed, 8 Jan 2025 12:00:40 +0100 Subject: [PATCH 350/548] Backends: Metal: Fixed memory leaks. (#8276, #8166) --- backends/imgui_impl_metal.mm | 10 ++++++++-- docs/CHANGELOG.txt | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index edd7fa181e29..3ff905a60cef 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -15,6 +15,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-01-08: Metal: Fixed memory leaks when using metal-cpp (#8276, #8166) or when using multiple contexts (#7419). // 2022-08-23: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'. // 2022-07-05: Metal: Add dispatch synchronization. // 2022-06-30: Metal: Use __bridge for ARC based systems. @@ -156,8 +157,11 @@ void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor) { ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); IM_ASSERT(bd != nil && "Context or backend not initialized! Did you call ImGui_ImplMetal_Init()?"); +#ifdef IMGUI_IMPL_METAL_CPP + bd->SharedMetalContext.framebufferDescriptor = [[[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor]autorelease]; +#else bd->SharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor]; - +#endif if (bd->SharedMetalContext.depthStencilState == nil) ImGui_ImplMetal_CreateDeviceObjects(bd->SharedMetalContext.device); } @@ -364,8 +368,10 @@ bool ImGui_ImplMetal_CreateDeviceObjects(id device) depthStencilDescriptor.depthWriteEnabled = NO; depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways; bd->SharedMetalContext.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor]; +#ifdef IMGUI_IMPL_METAL_CPP + [depthStencilDescriptor release]; +#endif ImGui_ImplMetal_CreateFontsTexture(device); - return true; } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 81763b99c901..a24d6ea4ea9f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -67,6 +67,7 @@ Other changes: - Misc: Fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] - Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). [@Helodity] +- Backends: Metal: Fixed leaks when using metal-cpp. (#8276, #8166) [@selimsandal] - Backends: Metal: Fixed resource leak when using multiple contexts. (#7419) [@anszom] - Backends: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF] From bbbdc70f26b15db176a0b93f9dde3cd5f6d84d8c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 8 Jan 2025 12:43:56 +0100 Subject: [PATCH 351/548] Refactor: moved FindBlockingModal() in its section. --- imgui.cpp | 96 ++++++++++++++++++++++++++----------------------------- 1 file changed, 45 insertions(+), 51 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3bb95bfcea05..00d66f857abf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3542,7 +3542,6 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) return "Unknown"; } - //----------------------------------------------------------------------------- // [SECTION] RENDER HELPERS // Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change, @@ -4252,7 +4251,6 @@ void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type) hook.Callback(&g, &hook); } - //----------------------------------------------------------------------------- // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) //----------------------------------------------------------------------------- @@ -6957,42 +6955,6 @@ static void SetWindowActiveForSkipRefresh(ImGuiWindow* window) } } -// When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing) -// should be positioned behind that modal window, unless the window was created inside the modal begin-stack. -// In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent. -// - WindowA // FindBlockingModal() returns Modal1 -// - WindowB // .. returns Modal1 -// - Modal1 // .. returns Modal2 -// - WindowC // .. returns Modal2 -// - WindowD // .. returns Modal2 -// - Modal2 // .. returns Modal2 -// - WindowE // .. returns NULL -// Notes: -// - FindBlockingModal(NULL) == NULL is generally equivalent to GetTopMostPopupModal() == NULL. -// Only difference is here we check for ->Active/WasActive but it may be unnecessary. -ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - if (g.OpenPopupStack.Size <= 0) - return NULL; - - // Find a modal that has common parent with specified window. Specified window should be positioned behind that modal. - for (ImGuiPopupData& popup_data : g.OpenPopupStack) - { - ImGuiWindow* popup_window = popup_data.Window; - if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal)) - continue; - if (!popup_window->Active && !popup_window->WasActive) // Check WasActive, because this code may run before popup renders on current frame, also check Active to handle newly created windows. - continue; - if (window == NULL) // FindBlockingModal(NULL) test for if FocusWindow(NULL) is naturally possible via a mouse click. - return popup_window; - if (IsWindowWithinBeginStackOf(window, popup_window)) // Window may be over modal - continue; - return popup_window; // Place window right below first block modal - } - return NULL; -} - // Push a new Dear ImGui window to add widgets to. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. @@ -8276,14 +8238,6 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) return (ref_window == cur_window); } -// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) -// Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmatically. -// If you want a window to never be focused, you may use the e.g. NoInputs flag. -bool ImGui::IsWindowNavFocusable(ImGuiWindow* window) -{ - return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus); -} - float ImGui::GetWindowWidth() { ImGuiWindow* window = GImGui->CurrentWindow; @@ -10308,7 +10262,6 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own return true; } - //----------------------------------------------------------------------------- // [SECTION] ERROR CHECKING, STATE RECOVERY //----------------------------------------------------------------------------- @@ -11655,6 +11608,43 @@ ImGuiWindow* ImGui::GetTopMostAndVisiblePopupModal() return NULL; } + +// When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing) +// should be positioned behind that modal window, unless the window was created inside the modal begin-stack. +// In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent. +// - WindowA // FindBlockingModal() returns Modal1 +// - WindowB // .. returns Modal1 +// - Modal1 // .. returns Modal2 +// - WindowC // .. returns Modal2 +// - WindowD // .. returns Modal2 +// - Modal2 // .. returns Modal2 +// - WindowE // .. returns NULL +// Notes: +// - FindBlockingModal(NULL) == NULL is generally equivalent to GetTopMostPopupModal() == NULL. +// Only difference is here we check for ->Active/WasActive but it may be unnecessary. +ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if (g.OpenPopupStack.Size <= 0) + return NULL; + + // Find a modal that has common parent with specified window. Specified window should be positioned behind that modal. + for (ImGuiPopupData& popup_data : g.OpenPopupStack) + { + ImGuiWindow* popup_window = popup_data.Window; + if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal)) + continue; + if (!popup_window->Active && !popup_window->WasActive) // Check WasActive, because this code may run before popup renders on current frame, also check Active to handle newly created windows. + continue; + if (window == NULL) // FindBlockingModal(NULL) test for if FocusWindow(NULL) is naturally possible via a mouse click. + return popup_window; + if (IsWindowWithinBeginStackOf(window, popup_window)) // Window may be over modal + continue; + return popup_window; // Place window right below first block modal + } + return NULL; +} + void ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; @@ -13524,6 +13514,14 @@ static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) return order; } +// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) +// Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmatically. +// If you want a window to never be focused, you may use the e.g. NoInputs flag. +bool ImGui::IsWindowNavFocusable(ImGuiWindow* window) +{ + return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus); +} + static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N) { ImGuiContext& g = *GImGui; @@ -13801,7 +13799,6 @@ void ImGui::NavUpdateWindowingOverlay() PopStyleVar(); } - //----------------------------------------------------------------------------- // [SECTION] DRAG AND DROP //----------------------------------------------------------------------------- @@ -14410,7 +14407,6 @@ void ImGui::LogButtons() LogToClipboard(); } - //----------------------------------------------------------------------------- // [SECTION] SETTINGS //----------------------------------------------------------------------------- @@ -14770,7 +14766,6 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl } } - //----------------------------------------------------------------------------- // [SECTION] LOCALIZATION //----------------------------------------------------------------------------- @@ -14782,7 +14777,6 @@ void ImGui::LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count) g.LocalizationTable[entries[n].Key] = entries[n].Text; } - //----------------------------------------------------------------------------- // [SECTION] VIEWPORTS, PLATFORM WINDOWS //----------------------------------------------------------------------------- From 2b8545684caea55032b48c7c62d493e7cf169e01 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 8 Jan 2025 14:22:37 +0100 Subject: [PATCH 352/548] Refactor: moved Window Focus related functions to a dedicated section. --- imgui.cpp | 522 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 272 insertions(+), 250 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 00d66f857abf..5f898a389eac 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -85,6 +85,7 @@ CODE // [SECTION] SCROLLING // [SECTION] TOOLTIPS // [SECTION] POPUPS +// [SECTION] WINDOW FOCUS // [SECTION] KEYBOARD/GAMEPAD NAVIGATION // [SECTION] DRAG AND DROP // [SECTION] LOGGING/CAPTURING @@ -1202,6 +1203,10 @@ namespace ImGui // Item static void ItemHandleShortcut(ImGuiID id); +// Window Focus +static int FindWindowFocusIndex(ImGuiWindow* window); +static void UpdateWindowInFocusOrderList(ImGuiWindow* window, bool just_created, ImGuiWindowFlags new_flags); + // Navigation static void NavUpdate(); static void NavUpdateWindowing(); @@ -1222,7 +1227,6 @@ static ImVec2 NavCalcPreferredRefPos(); static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window); static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window); static void NavRestoreLayer(ImGuiNavLayer layer); -static int FindWindowFocusIndex(ImGuiWindow* window); // Error Checking and Debug Tools static void ErrorCheckNewFrameSanityChecks(); @@ -6171,29 +6175,6 @@ static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settin window->Collapsed = settings->Collapsed; } -static void UpdateWindowInFocusOrderList(ImGuiWindow* window, bool just_created, ImGuiWindowFlags new_flags) -{ - ImGuiContext& g = *GImGui; - - const bool new_is_explicit_child = (new_flags & ImGuiWindowFlags_ChildWindow) != 0 && ((new_flags & ImGuiWindowFlags_Popup) == 0 || (new_flags & ImGuiWindowFlags_ChildMenu) != 0); - const bool child_flag_changed = new_is_explicit_child != window->IsExplicitChild; - if ((just_created || child_flag_changed) && !new_is_explicit_child) - { - IM_ASSERT(!g.WindowsFocusOrder.contains(window)); - g.WindowsFocusOrder.push_back(window); - window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1); - } - else if (!just_created && child_flag_changed && new_is_explicit_child) - { - IM_ASSERT(g.WindowsFocusOrder[window->FocusOrder] == window); - for (int n = window->FocusOrder + 1; n < g.WindowsFocusOrder.Size; n++) - g.WindowsFocusOrder[n]->FocusOrder--; - g.WindowsFocusOrder.erase(g.WindowsFocusOrder.Data + window->FocusOrder); - window->FocusOrder = -1; - } - window->IsExplicitChild = new_is_explicit_child; -} - static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings) { // Initial window state with e.g. default/arbitrary window position @@ -7777,176 +7758,6 @@ void ImGui::End() SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window); } -void ImGui::BringWindowToFocusFront(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(window == window->RootWindow); - - const int cur_order = window->FocusOrder; - IM_ASSERT(g.WindowsFocusOrder[cur_order] == window); - if (g.WindowsFocusOrder.back() == window) - return; - - const int new_order = g.WindowsFocusOrder.Size - 1; - for (int n = cur_order; n < new_order; n++) - { - g.WindowsFocusOrder[n] = g.WindowsFocusOrder[n + 1]; - g.WindowsFocusOrder[n]->FocusOrder--; - IM_ASSERT(g.WindowsFocusOrder[n]->FocusOrder == n); - } - g.WindowsFocusOrder[new_order] = window; - window->FocusOrder = (short)new_order; -} - -void ImGui::BringWindowToDisplayFront(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* current_front_window = g.Windows.back(); - if (current_front_window == window || current_front_window->RootWindow == window) // Cheap early out (could be better) - return; - for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window - if (g.Windows[i] == window) - { - memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*)); - g.Windows[g.Windows.Size - 1] = window; - break; - } -} - -void ImGui::BringWindowToDisplayBack(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - if (g.Windows[0] == window) - return; - for (int i = 0; i < g.Windows.Size; i++) - if (g.Windows[i] == window) - { - memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*)); - g.Windows[0] = window; - break; - } -} - -void ImGui::BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* behind_window) -{ - IM_ASSERT(window != NULL && behind_window != NULL); - ImGuiContext& g = *GImGui; - window = window->RootWindow; - behind_window = behind_window->RootWindow; - int pos_wnd = FindWindowDisplayIndex(window); - int pos_beh = FindWindowDisplayIndex(behind_window); - if (pos_wnd < pos_beh) - { - size_t copy_bytes = (pos_beh - pos_wnd - 1) * sizeof(ImGuiWindow*); - memmove(&g.Windows.Data[pos_wnd], &g.Windows.Data[pos_wnd + 1], copy_bytes); - g.Windows[pos_beh - 1] = window; - } - else - { - size_t copy_bytes = (pos_wnd - pos_beh) * sizeof(ImGuiWindow*); - memmove(&g.Windows.Data[pos_beh + 1], &g.Windows.Data[pos_beh], copy_bytes); - g.Windows[pos_beh] = window; - } -} - -int ImGui::FindWindowDisplayIndex(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - return g.Windows.index_from_ptr(g.Windows.find(window)); -} - -// Moving window to front of display and set focus (which happens to be back of our sorted list) -void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags) -{ - ImGuiContext& g = *GImGui; - - // Modal check? - if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window)) // Early out in common case. - if (ImGuiWindow* blocking_modal = FindBlockingModal(window)) - { - // This block would typically be reached in two situations: - // - API call to FocusWindow() with a window under a modal and ImGuiFocusRequestFlags_UnlessBelowModal flag. - // - User clicking on void or anything behind a modal while a modal is open (window == NULL) - IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "", blocking_modal->Name); - if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0) - BringWindowToDisplayBehind(window, blocking_modal); // Still bring right under modal. (FIXME: Could move in focus list too?) - ClosePopupsOverWindow(GetTopMostPopupModal(), false); // Note how we need to use GetTopMostPopupModal() aad NOT blocking_modal, to handle nested modals - return; - } - - // Find last focused child (if any) and focus it instead. - if ((flags & ImGuiFocusRequestFlags_RestoreFocusedChild) && window != NULL) - window = NavRestoreLastChildNavWindow(window); - - // Apply focus - if (g.NavWindow != window) - { - SetNavWindow(window); - if (window && g.NavHighlightItemUnderNav) - g.NavMousePosDirty = true; - g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId - g.NavLayer = ImGuiNavLayer_Main; - SetNavFocusScope(window ? window->NavRootFocusScopeId : 0); - g.NavIdIsAlive = false; - g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; - - // Close popups if any - ClosePopupsOverWindow(window, false); - } - - // Move the root window to the top of the pile - IM_ASSERT(window == NULL || window->RootWindow != NULL); - ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL; // NB: In docking branch this is window->RootWindowDockStop - ImGuiWindow* display_front_window = window ? window->RootWindow : NULL; - - // Steal active widgets. Some of the cases it triggers includes: - // - Focus a window while an InputText in another window is active, if focus happens before the old InputText can run. - // - When using Nav to activate menu items (due to timing of activating on press->new window appears->losing ActiveId) - if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window) - if (!g.ActiveIdNoClearOnFocusLoss) - ClearActiveID(); - - // Passing NULL allow to disable keyboard focus - if (!window) - return; - - // Bring to front - BringWindowToFocusFront(focus_front_window); - if (((window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0) - BringWindowToDisplayFront(display_front_window); -} - -void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags) -{ - ImGuiContext& g = *GImGui; - IM_UNUSED(filter_viewport); // Unused in master branch. - int start_idx = g.WindowsFocusOrder.Size - 1; - if (under_this_window != NULL) - { - // Aim at root window behind us, if we are in a child window that's our own root (see #4640) - int offset = -1; - while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow) - { - under_this_window = under_this_window->ParentWindow; - offset = 0; - } - start_idx = FindWindowFocusIndex(under_this_window) + offset; - } - for (int i = start_idx; i >= 0; i--) - { - // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user. - ImGuiWindow* window = g.WindowsFocusOrder[i]; - if (window == ignore_window || !window->WasActive) - continue; - if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) - { - FocusWindow(window, flags); - return; - } - } - FocusWindow(NULL, flags); -} - // Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only. void ImGui::SetCurrentFont(ImFont* font) { @@ -8216,28 +8027,6 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) return true; } -bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* ref_window = g.NavWindow; - ImGuiWindow* cur_window = g.CurrentWindow; - - if (ref_window == NULL) - return false; - if (flags & ImGuiFocusedFlags_AnyWindow) - return true; - - IM_ASSERT(cur_window); // Not inside a Begin()/End() - const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0; - if (flags & ImGuiHoveredFlags_RootWindow) - cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy); - - if (flags & ImGuiHoveredFlags_ChildWindows) - return IsWindowChildOf(ref_window, cur_window, popup_hierarchy); - else - return (ref_window == cur_window); -} - float ImGui::GetWindowWidth() { ImGuiWindow* window = GImGui->CurrentWindow; @@ -8385,24 +8174,6 @@ void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond) SetWindowCollapsed(window, collapsed, cond); } -void ImGui::SetWindowFocus() -{ - FocusWindow(GImGui->CurrentWindow); -} - -void ImGui::SetWindowFocus(const char* name) -{ - if (name) - { - if (ImGuiWindow* window = FindWindowByName(name)) - FocusWindow(window); - } - else - { - FocusWindow(NULL); - } -} - void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot) { ImGuiContext& g = *GImGui; @@ -8460,12 +8231,6 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always; } -void ImGui::SetNextWindowFocus() -{ - ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus; -} - void ImGui::SetNextWindowBgAlpha(float alpha) { ImGuiContext& g = *GImGui; @@ -12148,6 +11913,273 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) return window->Pos; } +//----------------------------------------------------------------------------- +// [SECTION] WINDOW FOCUS +//---------------------------------------------------------------------------- +// - SetWindowFocus() +// - SetNextWindowFocus() +// - IsWindowFocused() +// - UpdateWindowInFocusOrderList() [Internal] +// - BringWindowToFocusFront() [Internal] +// - BringWindowToDisplayFront() [Internal] +// - BringWindowToDisplayBack() [Internal] +// - BringWindowToDisplayBehind() [Internal] +// - FindWindowDisplayIndex() [Internal] +// - FocusWindow() [Internal] +// - FocusTopMostWindowUnderOne() [Internal] +//----------------------------------------------------------------------------- + +void ImGui::SetWindowFocus() +{ + FocusWindow(GImGui->CurrentWindow); +} + +void ImGui::SetWindowFocus(const char* name) +{ + if (name) + { + if (ImGuiWindow* window = FindWindowByName(name)) + FocusWindow(window); + } + else + { + FocusWindow(NULL); + } +} + +void ImGui::SetNextWindowFocus() +{ + ImGuiContext& g = *GImGui; + g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus; +} + +// Similar to IsWindowHovered() +bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* ref_window = g.NavWindow; + ImGuiWindow* cur_window = g.CurrentWindow; + + if (ref_window == NULL) + return false; + if (flags & ImGuiFocusedFlags_AnyWindow) + return true; + + IM_ASSERT(cur_window); // Not inside a Begin()/End() + const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0; + if (flags & ImGuiHoveredFlags_RootWindow) + cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy); + + if (flags & ImGuiHoveredFlags_ChildWindows) + return IsWindowChildOf(ref_window, cur_window, popup_hierarchy); + else + return (ref_window == cur_window); +} + +static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + IM_UNUSED(g); + int order = window->FocusOrder; + IM_ASSERT(window->RootWindow == window); // No child window (not testing _ChildWindow because of docking) + IM_ASSERT(g.WindowsFocusOrder[order] == window); + return order; +} + +static void ImGui::UpdateWindowInFocusOrderList(ImGuiWindow* window, bool just_created, ImGuiWindowFlags new_flags) +{ + ImGuiContext& g = *GImGui; + + const bool new_is_explicit_child = (new_flags & ImGuiWindowFlags_ChildWindow) != 0 && ((new_flags & ImGuiWindowFlags_Popup) == 0 || (new_flags & ImGuiWindowFlags_ChildMenu) != 0); + const bool child_flag_changed = new_is_explicit_child != window->IsExplicitChild; + if ((just_created || child_flag_changed) && !new_is_explicit_child) + { + IM_ASSERT(!g.WindowsFocusOrder.contains(window)); + g.WindowsFocusOrder.push_back(window); + window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1); + } + else if (!just_created && child_flag_changed && new_is_explicit_child) + { + IM_ASSERT(g.WindowsFocusOrder[window->FocusOrder] == window); + for (int n = window->FocusOrder + 1; n < g.WindowsFocusOrder.Size; n++) + g.WindowsFocusOrder[n]->FocusOrder--; + g.WindowsFocusOrder.erase(g.WindowsFocusOrder.Data + window->FocusOrder); + window->FocusOrder = -1; + } + window->IsExplicitChild = new_is_explicit_child; +} + +void ImGui::BringWindowToFocusFront(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(window == window->RootWindow); + + const int cur_order = window->FocusOrder; + IM_ASSERT(g.WindowsFocusOrder[cur_order] == window); + if (g.WindowsFocusOrder.back() == window) + return; + + const int new_order = g.WindowsFocusOrder.Size - 1; + for (int n = cur_order; n < new_order; n++) + { + g.WindowsFocusOrder[n] = g.WindowsFocusOrder[n + 1]; + g.WindowsFocusOrder[n]->FocusOrder--; + IM_ASSERT(g.WindowsFocusOrder[n]->FocusOrder == n); + } + g.WindowsFocusOrder[new_order] = window; + window->FocusOrder = (short)new_order; +} + +// Note technically focus related but rather adjacent and close to BringWindowToFocusFront() +void ImGui::BringWindowToDisplayFront(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* current_front_window = g.Windows.back(); + if (current_front_window == window || current_front_window->RootWindow == window) // Cheap early out (could be better) + return; + for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window + if (g.Windows[i] == window) + { + memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*)); + g.Windows[g.Windows.Size - 1] = window; + break; + } +} + +void ImGui::BringWindowToDisplayBack(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if (g.Windows[0] == window) + return; + for (int i = 0; i < g.Windows.Size; i++) + if (g.Windows[i] == window) + { + memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*)); + g.Windows[0] = window; + break; + } +} + +void ImGui::BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* behind_window) +{ + IM_ASSERT(window != NULL && behind_window != NULL); + ImGuiContext& g = *GImGui; + window = window->RootWindow; + behind_window = behind_window->RootWindow; + int pos_wnd = FindWindowDisplayIndex(window); + int pos_beh = FindWindowDisplayIndex(behind_window); + if (pos_wnd < pos_beh) + { + size_t copy_bytes = (pos_beh - pos_wnd - 1) * sizeof(ImGuiWindow*); + memmove(&g.Windows.Data[pos_wnd], &g.Windows.Data[pos_wnd + 1], copy_bytes); + g.Windows[pos_beh - 1] = window; + } + else + { + size_t copy_bytes = (pos_wnd - pos_beh) * sizeof(ImGuiWindow*); + memmove(&g.Windows.Data[pos_beh + 1], &g.Windows.Data[pos_beh], copy_bytes); + g.Windows[pos_beh] = window; + } +} + +int ImGui::FindWindowDisplayIndex(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + return g.Windows.index_from_ptr(g.Windows.find(window)); +} + +// Moving window to front of display and set focus (which happens to be back of our sorted list) +void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags) +{ + ImGuiContext& g = *GImGui; + + // Modal check? + if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window)) // Early out in common case. + if (ImGuiWindow* blocking_modal = FindBlockingModal(window)) + { + // This block would typically be reached in two situations: + // - API call to FocusWindow() with a window under a modal and ImGuiFocusRequestFlags_UnlessBelowModal flag. + // - User clicking on void or anything behind a modal while a modal is open (window == NULL) + IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "", blocking_modal->Name); + if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0) + BringWindowToDisplayBehind(window, blocking_modal); // Still bring right under modal. (FIXME: Could move in focus list too?) + ClosePopupsOverWindow(GetTopMostPopupModal(), false); // Note how we need to use GetTopMostPopupModal() aad NOT blocking_modal, to handle nested modals + return; + } + + // Find last focused child (if any) and focus it instead. + if ((flags & ImGuiFocusRequestFlags_RestoreFocusedChild) && window != NULL) + window = NavRestoreLastChildNavWindow(window); + + // Apply focus + if (g.NavWindow != window) + { + SetNavWindow(window); + if (window && g.NavHighlightItemUnderNav) + g.NavMousePosDirty = true; + g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId + g.NavLayer = ImGuiNavLayer_Main; + SetNavFocusScope(window ? window->NavRootFocusScopeId : 0); + g.NavIdIsAlive = false; + g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; + + // Close popups if any + ClosePopupsOverWindow(window, false); + } + + // Move the root window to the top of the pile + IM_ASSERT(window == NULL || window->RootWindow != NULL); + ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL; // NB: In docking branch this is window->RootWindowDockStop + ImGuiWindow* display_front_window = window ? window->RootWindow : NULL; + + // Steal active widgets. Some of the cases it triggers includes: + // - Focus a window while an InputText in another window is active, if focus happens before the old InputText can run. + // - When using Nav to activate menu items (due to timing of activating on press->new window appears->losing ActiveId) + if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window) + if (!g.ActiveIdNoClearOnFocusLoss) + ClearActiveID(); + + // Passing NULL allow to disable keyboard focus + if (!window) + return; + + // Bring to front + BringWindowToFocusFront(focus_front_window); + if (((window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0) + BringWindowToDisplayFront(display_front_window); +} + +void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags) +{ + ImGuiContext& g = *GImGui; + IM_UNUSED(filter_viewport); // Unused in master branch. + int start_idx = g.WindowsFocusOrder.Size - 1; + if (under_this_window != NULL) + { + // Aim at root window behind us, if we are in a child window that's our own root (see #4640) + int offset = -1; + while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow) + { + under_this_window = under_this_window->ParentWindow; + offset = 0; + } + start_idx = FindWindowFocusIndex(under_this_window) + offset; + } + for (int i = start_idx; i >= 0; i--) + { + // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user. + ImGuiWindow* window = g.WindowsFocusOrder[i]; + if (window == ignore_window || !window->WasActive) + continue; + if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) + { + FocusWindow(window, flags); + return; + } + } + FocusWindow(NULL, flags); +} + //----------------------------------------------------------------------------- // [SECTION] KEYBOARD/GAMEPAD NAVIGATION //----------------------------------------------------------------------------- @@ -13504,16 +13536,6 @@ static void ImGui::NavUpdateCreateWrappingRequest() NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags); } -static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - IM_UNUSED(g); - int order = window->FocusOrder; - IM_ASSERT(window->RootWindow == window); // No child window (not testing _ChildWindow because of docking) - IM_ASSERT(g.WindowsFocusOrder[order] == window); - return order; -} - // Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) // Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmatically. // If you want a window to never be focused, you may use the e.g. NoInputs flag. From 1c67a3412e1540700494f4c0d76d389d0232606f Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 8 Jan 2025 14:55:51 +0100 Subject: [PATCH 353/548] BeginChild: also caller to manually set ImGuiNextWindowDataFlags_HasChildFlags / ChildFlags. (#8280) --- imgui.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5f898a389eac..ededc3d00247 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6049,9 +6049,12 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I } SetNextWindowSize(size); - // Forward child flags + // Forward child flags (we allow prior settings to merge but it'll only work for adding flags) + if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasChildFlags) + g.NextWindowData.ChildFlags |= child_flags; + else + g.NextWindowData.ChildFlags = child_flags; g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags; - g.NextWindowData.ChildFlags = child_flags; // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value. // FIXME: 2023/11/14: commented out shorted version. We had an issue with multiple ### in child window path names, which the trailing hash helped workaround. From 90094a871a5379d78a1b38b8364e0bd2ee65f796 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 8 Jan 2025 18:13:53 +0100 Subject: [PATCH 354/548] Fonts: Fixed miscalculation of Ellipsis ("...") character width when automatically created from a single comma character. --- docs/CHANGELOG.txt | 2 ++ imgui_draw.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a24d6ea4ea9f..89c4140b5df0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,6 +63,8 @@ Other changes: windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231) - Debug Tools: Debug Log: hovering 0xXXXXXXXX values in log is allowed even if a popup is blocking mouse access to the debug log window. (#5855) +- Fonts: Fixed miscalculation of Ellipsis ("...") character width when automatically + created from a single comma character, affecting some fonts/settings (not all). - Demo: Added label edition to Property Editor demo + fix an ID issue. (#8266) [@moritz-h] - Misc: Fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] - Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 42bfb71625cf..9e155f592023 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3799,8 +3799,8 @@ void ImFont::BuildLookupTable() const ImFontGlyph* glyph = FindGlyph(dot_char); EllipsisChar = dot_char; EllipsisCharCount = 3; - EllipsisCharStep = (glyph->X1 - glyph->X0) + 1.0f; - EllipsisWidth = EllipsisCharStep * 3.0f - 1.0f; + EllipsisCharStep = (float)(int)(glyph->X1 - glyph->X0) + 1.0f; + EllipsisWidth = glyph->X0 + EllipsisCharStep * 3.0f - 1.0f; } } From c7983115e9f7bdee8bc76ec17612ef1a45bdc05e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 8 Jan 2025 18:27:01 +0100 Subject: [PATCH 355/548] Fonts: Further tweaks for Ellipsis ("...") character width when automatically created from a single comma character: use AdvanceX as min. --- imgui_draw.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 9e155f592023..8baaf8b11767 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3796,11 +3796,11 @@ void ImFont::BuildLookupTable() } else if (dot_char != 0) { - const ImFontGlyph* glyph = FindGlyph(dot_char); + const ImFontGlyph* dot_glyph = FindGlyph(dot_char); EllipsisChar = dot_char; EllipsisCharCount = 3; - EllipsisCharStep = (float)(int)(glyph->X1 - glyph->X0) + 1.0f; - EllipsisWidth = glyph->X0 + EllipsisCharStep * 3.0f - 1.0f; + EllipsisCharStep = (float)(int)(dot_glyph->X1 - dot_glyph->X0) + 1.0f; + EllipsisWidth = ImMax(dot_glyph->AdvanceX, dot_glyph->X0 + EllipsisCharStep * 3.0f - 1.0f); // FIXME: Slightly odd for normally mono-space fonts but since this is used for trailing contents. } } From 940d9540f3f7efc9e79fdcba859a24162b383a6f Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 9 Jan 2025 15:28:48 +0100 Subject: [PATCH 356/548] Fixed MinGW builds uses UTF-8 friendly _wfopen(). (#8300) Amend bbd0a37bd, 40db2ca09 --- docs/CHANGELOG.txt | 1 + imgui.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 89c4140b5df0..00df8a746418 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -67,6 +67,7 @@ Other changes: created from a single comma character, affecting some fonts/settings (not all). - Demo: Added label edition to Property Editor demo + fix an ID issue. (#8266) [@moritz-h] - Misc: Fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] +- Misc: Fixed MinGW builds uses UTF-8 friendly _wfopen(). (#8300) - Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). [@Helodity] - Backends: Metal: Fixed leaks when using metal-cpp. (#8276, #8166) [@selimsandal] diff --git a/imgui.cpp b/imgui.cpp index ededc3d00247..bad766f030eb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2282,7 +2282,7 @@ ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed) ImFileHandle ImFileOpen(const char* filename, const char* mode) { -#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__) +#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && (defined(__MINGW32__) || (!defined(__CYGWIN__) && !defined(__GNUC__))) // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. // Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32! const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0); From 8bbccf7a9779c45c15e201c18eb3971d40fc0e76 Mon Sep 17 00:00:00 2001 From: Delta <98419797+DeltaW0x@users.noreply.github.com> Date: Thu, 9 Jan 2025 15:37:13 +0100 Subject: [PATCH 357/548] Backends: SDLGPU3: Added sdl_gpu backend. (#8163, #7998, #7988) +Squashed: Optimized shader source code encoding by ocornut (#8163, #7998, #7988) (squashed to avoid storing both in git history, 130 KB->62 KB) --- backends/imgui_impl_sdlgpu3.cpp | 630 ++++++++++++++++++ backends/imgui_impl_sdlgpu3.h | 46 ++ backends/imgui_impl_sdlgpu3_shaders.h | 372 +++++++++++ backends/sdlgpu3/build_instructions.txt | 36 + backends/sdlgpu3/shader.frag | 14 + backends/sdlgpu3/shader.vert | 22 + examples/example_sdl3_sdlgpu3/Makefile | 73 ++ examples/example_sdl3_sdlgpu3/build_win64.bat | 14 + .../example_sdl3_sdlgpu3.vcxproj | 189 ++++++ .../example_sdl3_sdlgpu3.vcxproj.filters | 60 ++ examples/example_sdl3_sdlgpu3/main.cpp | 210 ++++++ examples/imgui_examples.sln | 10 + 12 files changed, 1676 insertions(+) create mode 100644 backends/imgui_impl_sdlgpu3.cpp create mode 100644 backends/imgui_impl_sdlgpu3.h create mode 100644 backends/imgui_impl_sdlgpu3_shaders.h create mode 100644 backends/sdlgpu3/build_instructions.txt create mode 100644 backends/sdlgpu3/shader.frag create mode 100644 backends/sdlgpu3/shader.vert create mode 100644 examples/example_sdl3_sdlgpu3/Makefile create mode 100644 examples/example_sdl3_sdlgpu3/build_win64.bat create mode 100644 examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj create mode 100644 examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj.filters create mode 100644 examples/example_sdl3_sdlgpu3/main.cpp diff --git a/backends/imgui_impl_sdlgpu3.cpp b/backends/imgui_impl_sdlgpu3.cpp new file mode 100644 index 000000000000..31e899b77d92 --- /dev/null +++ b/backends/imgui_impl_sdlgpu3.cpp @@ -0,0 +1,630 @@ +// dear imgui: Renderer Backend for SDL_Gpu +// This needs to be used along with the SDL3 Platform Backend + +// Implemented features: +// [X] Renderer: User texture binding. Use simply cast a reference to your SDL_GPUTextureSamplerBinding to ImTextureID. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. + +// The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification. +// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/ + +// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). +// - Introduction, links and more at the top of imgui.cpp + +// Important note to the reader who wish to integrate imgui_impl_sdlgpu3.cpp/.h in their own engine/app. +// - Unline other backends, the user must call the function Imgui_ImplSDLGPU_PrepareDrawData BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData. +// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info. + +// CHANGELOG +// 2024-11-18: SDL_Gpu: Added the SDL_Gpu backend. + +#include "imgui.h" +#ifndef IMGUI_DISABLE +#include "imgui_impl_sdlgpu3.h" +#include "imgui_impl_sdlgpu3_shaders.h" + +// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplSDLGPU_RenderDrawData() +struct ImGui_ImplSDLGPU_FrameData +{ + SDL_GPUBuffer* VertexBuffer = nullptr; + SDL_GPUBuffer* IndexBuffer = nullptr; + uint32_t VertexBufferSize = 0; + uint32_t IndexBufferSize = 0; +}; + +// SDL_Gpu Data +struct ImGui_ImplSDLGPU_Data +{ + ImGui_ImplSDLGPU_InitInfo GPUInitInfo; + + // Graphics pipeline & shaders + SDL_GPUShader* VertexShader = nullptr; + SDL_GPUShader* FragmentShader = nullptr; + SDL_GPUGraphicsPipeline* Pipeline = nullptr; + + // Font data + SDL_GPUSampler* FontSampler = nullptr; + SDL_GPUTexture* FontTexture = nullptr; + SDL_GPUTextureSamplerBinding FontBinding = {nullptr,nullptr}; + + // Frame data for main window + ImGui_ImplSDLGPU_FrameData MainWindowFrameData; +}; + +// Forward Declarations +static bool ImGui_ImplSDLGPU_CreateDeviceObjects(); +static void ImGui_ImplSDLGPU_DestroyDeviceObjects(); +static void ImGui_ImplSDLGPU_DestroyFrameData(); + +//----------------------------------------------------------------------------- +// FUNCTIONS +//----------------------------------------------------------------------------- + +// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts +// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. +// FIXME: multi-context support has never been tested. +static ImGui_ImplSDLGPU_Data* ImGui_ImplSDLGPU_GetBackendData() +{ + return ImGui::GetCurrentContext() ? (ImGui_ImplSDLGPU_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; +} + +static void CreateOrResizeBuffer(SDL_GPUBuffer** buffer,uint32_t* old_size, uint32_t new_size,SDL_GPUBufferUsageFlags usage) +{ + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + + SDL_WaitForGPUIdle(v->GpuDevice); + SDL_ReleaseGPUBuffer(v->GpuDevice, *buffer); + + SDL_GPUBufferCreateInfo buffer_info = {}; + buffer_info.usage = usage; + buffer_info.size = new_size; + buffer_info.props = 0; + *buffer = SDL_CreateGPUBuffer(v->GpuDevice,&buffer_info); + *old_size = new_size; + IM_ASSERT(*buffer != nullptr && "Failed to create GPU Buffer, call SDL_GetError() for more information"); +} + +static void ImGui_ImplSDLGPU_SetupRenderState(ImDrawData* draw_data,SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer,SDL_GPURenderPass * render_pass, ImGui_ImplSDLGPU_FrameData* fd, uint32_t fb_width, uint32_t fb_height) +{ + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + + // Bind graphics pipeline: + { + SDL_BindGPUGraphicsPipeline(render_pass,pipeline); + } + + // Bind Vertex And Index Buffers: + if (draw_data->TotalVtxCount > 0) + { + SDL_GPUBufferBinding vertex_buffer_binding = {}; + vertex_buffer_binding.buffer = fd->VertexBuffer; + vertex_buffer_binding.offset = 0; + SDL_GPUBufferBinding index_buffer_binding = {}; + index_buffer_binding.buffer = fd->IndexBuffer; + index_buffer_binding.offset = 0; + SDL_BindGPUVertexBuffers(render_pass,0,&vertex_buffer_binding,1); + SDL_BindGPUIndexBuffer(render_pass,&index_buffer_binding,sizeof(ImDrawIdx) == 2 ? SDL_GPU_INDEXELEMENTSIZE_16BIT : SDL_GPU_INDEXELEMENTSIZE_32BIT); + } + + // Setup viewport: + { + SDL_GPUViewport viewport = {}; + viewport.x = 0; + viewport.y = 0; + viewport.w = fb_width; + viewport.h = fb_height; + viewport.min_depth = 0.0f; + viewport.min_depth = 1.0f; + SDL_SetGPUViewport(render_pass,&viewport); + } + + // Setup scale and translation: + // Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. + { + struct UBO{ + float scale[2]; + float translation[2]; + } ubo; + ubo.scale[0] = 2.0f / draw_data->DisplaySize.x; + ubo.scale[1] = 2.0f / draw_data->DisplaySize.y; + ubo.translation[0] = -1.0f - draw_data->DisplayPos.x * ubo.scale[0]; + ubo.translation[1] = -1.0f - draw_data->DisplayPos.y * ubo.scale[1]; + SDL_PushGPUVertexUniformData(command_buffer,0,&ubo,sizeof(UBO)); + } +} + +// SDL_GPU doesn't allow copy passes to occur while a render or compute pass is bound +// The only way to allow a user to supply their own RenderPass (to render to a texture instead of the window for example), +// is to split the upload part of ImGui_ImplSDLGPU_RenderDrawData to another function that needs to be called by the user before rendering +void Imgui_ImplSDLGPU_PrepareDrawData(ImDrawData* draw_data,SDL_GPUCommandBuffer* command_buffer) +{ + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); + int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); + if(fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount <= 0) + return; + + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU_FrameData* fd = &bd->MainWindowFrameData; + + uint32_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); + uint32_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + + if(fd->VertexBuffer == nullptr || fd->VertexBufferSize < vertex_size) + CreateOrResizeBuffer(&fd->VertexBuffer,&fd->VertexBufferSize,vertex_size, SDL_GPU_BUFFERUSAGE_VERTEX); + if (fd->IndexBuffer == nullptr || fd->IndexBufferSize < index_size) + CreateOrResizeBuffer(&fd->IndexBuffer,&fd->IndexBufferSize,index_size, SDL_GPU_BUFFERUSAGE_INDEX); + + SDL_GPUTransferBufferCreateInfo vertex_transferbuffer_info = {}; + vertex_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; + vertex_transferbuffer_info.size = vertex_size; + SDL_GPUTransferBufferCreateInfo index_transferbuffer_info = {}; + index_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; + index_transferbuffer_info.size = index_size; + + SDL_GPUTransferBuffer* vertex_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice,&vertex_transferbuffer_info); + IM_ASSERT(vertex_transferbuffer != nullptr && "Failed to create the vertex transfer buffer, call SDL_GetError() for more information"); + SDL_GPUTransferBuffer* index_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice,&index_transferbuffer_info); + IM_ASSERT(index_transferbuffer != nullptr && "Failed to create the index transfer buffer, call SDL_GetError() for more information"); + + ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer(v->GpuDevice,vertex_transferbuffer,true); + ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer(v->GpuDevice,index_transferbuffer,true); + for(int n = 0; n < draw_data->CmdListsCount; n++){ + const ImDrawList* draw_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + vtx_dst += draw_list->VtxBuffer.Size; + idx_dst += draw_list->IdxBuffer.Size; + } + SDL_UnmapGPUTransferBuffer(v->GpuDevice,vertex_transferbuffer); + SDL_UnmapGPUTransferBuffer(v->GpuDevice,index_transferbuffer); + + SDL_GPUTransferBufferLocation vertex_buffer_location = {}; + vertex_buffer_location.offset = 0; + vertex_buffer_location.transfer_buffer = vertex_transferbuffer; + SDL_GPUTransferBufferLocation index_buffer_location = {}; + index_buffer_location.offset = 0; + index_buffer_location.transfer_buffer = index_transferbuffer; + + SDL_GPUBufferRegion vertex_buffer_region = {}; + vertex_buffer_region.buffer = fd->VertexBuffer; + vertex_buffer_region.offset = 0; + vertex_buffer_region.size = vertex_size; + SDL_GPUBufferRegion index_buffer_region = {}; + index_buffer_region.buffer = fd->IndexBuffer; + index_buffer_region.offset = 0; + index_buffer_region.size = index_size; + + SDL_GPUCopyPass* copy_pass = SDL_BeginGPUCopyPass(command_buffer); + SDL_UploadToGPUBuffer(copy_pass,&vertex_buffer_location,&vertex_buffer_region,true); + SDL_UploadToGPUBuffer(copy_pass,&index_buffer_location,&index_buffer_region,true); + SDL_EndGPUCopyPass(copy_pass); + SDL_ReleaseGPUTransferBuffer(v->GpuDevice, index_transferbuffer); + SDL_ReleaseGPUTransferBuffer(v->GpuDevice, vertex_transferbuffer); +} + +void ImGui_ImplSDLGPU_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline) +{ + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); + int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); + if(fb_width <= 0 || fb_height <= 0) + return; + + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU_FrameData* fd = &bd->MainWindowFrameData; + + if (pipeline == nullptr) + pipeline = bd->Pipeline; + + ImGui_ImplSDLGPU_SetupRenderState(draw_data,pipeline,command_buffer,render_pass,fd,fb_width,fb_height); + + // Will project scissor/clipping rectangles into framebuffer space + ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports + ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) + + // Render command lists + // (Because we merged all buffers into a single one, we maintain our own offset into them) + int global_vtx_offset = 0; + int global_idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* draw_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback != nullptr) + { + pcmd->UserCallback(draw_list, pcmd); + } + else + { + // Project scissor/clipping rectangles into framebuffer space + ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); + ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); + + // Clamp to viewport as SDL_SetGPUScissor() won't accept values that are off bounds + if (clip_min.x < 0.0f) { clip_min.x = 0.0f; } + if (clip_min.y < 0.0f) { clip_min.y = 0.0f; } + if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; } + if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; } + if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) + continue; + + // Apply scissor/clipping rectangle + SDL_Rect scissor_rect = {}; + scissor_rect.x = (int)clip_min.x; + scissor_rect.y = (int)clip_min.y; + scissor_rect.w = (int)(clip_max.x - clip_min.x); + scissor_rect.h = (int)(clip_max.y - clip_min.y); + SDL_SetGPUScissor(render_pass,&scissor_rect); + + // Bind DescriptorSet with font or user texture + SDL_BindGPUFragmentSamplers(render_pass,0,(SDL_GPUTextureSamplerBinding*)pcmd->GetTexID(),1); + + // Draw + SDL_DrawGPUIndexedPrimitives(render_pass,pcmd->ElemCount,1,pcmd->IdxOffset + global_idx_offset,pcmd->VtxOffset + global_vtx_offset,0); + } + } + global_idx_offset += draw_list->IdxBuffer.Size; + global_vtx_offset += draw_list->VtxBuffer.Size; + } + + // Note: at this point both SDL_SetGPUViewport() and SDL_SetGPUScissor() have been called. + // Our last values will leak into user/application rendering if you forgot to call SDL_SetGPUViewport() and SDL_SetGPUScissor() yourself to explicitly set that state + // In theory we should aim to backup/restore those values but I am not sure this is possible. + // We perform a call to SDL_SetGPUScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644) + SDL_Rect scissor_rect {0,0,fb_width,fb_height}; + SDL_SetGPUScissor(render_pass,&scissor_rect); +} + +bool ImGui_ImplSDLGPU_CreateFontsTexture() +{ + ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + + // Destroy existing texture (if any) + if (bd->FontTexture) + { + SDL_WaitForGPUIdle(v->GpuDevice); + ImGui_ImplSDLGPU_DestroyFontsTexture(); + } + + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + uint32_t upload_size = width * height * 4 * sizeof(char); + + // Create the Image: + { + SDL_GPUTextureCreateInfo texture_info = {}; + texture_info.type = SDL_GPU_TEXTURETYPE_2D; + texture_info.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; + texture_info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER; + texture_info.width = width; + texture_info.height = height; + texture_info.layer_count_or_depth = 1; + texture_info.num_levels = 1; + texture_info.sample_count = SDL_GPU_SAMPLECOUNT_1; + + bd->FontTexture = SDL_CreateGPUTexture(v->GpuDevice,&texture_info); + IM_ASSERT(bd->FontTexture && "Failed to create font texture, call SDL_GetError() for more info"); + } + + // Assign the texture to the TextureSamplerBinding + bd->FontBinding.texture = bd->FontTexture; + + // Create all the upload structures and upload: + { + SDL_GPUTransferBufferCreateInfo font_transferbuffer_info = {}; + font_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; + font_transferbuffer_info.size = upload_size; + + SDL_GPUTransferBuffer* font_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice,&font_transferbuffer_info); + IM_ASSERT(font_transferbuffer != nullptr && "Failed to create font transfer buffer, call SDL_GetError() for more information"); + + void* texture_ptr = SDL_MapGPUTransferBuffer(v->GpuDevice,font_transferbuffer,false); + memcpy(texture_ptr,pixels,upload_size); + SDL_UnmapGPUTransferBuffer(v->GpuDevice,font_transferbuffer); + + SDL_GPUTextureTransferInfo font_transfer_info = {}; + font_transfer_info.offset = 0; + font_transfer_info.transfer_buffer = font_transferbuffer; + + SDL_GPUTextureRegion font_texture_region = {}; + font_texture_region.texture = bd->FontTexture; + font_texture_region.w = width; + font_texture_region.h = height; + font_texture_region.d = 1; + + SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(v->GpuDevice); + SDL_GPUCopyPass* copy_pass = SDL_BeginGPUCopyPass(cmd); + SDL_UploadToGPUTexture(copy_pass,&font_transfer_info,&font_texture_region,false); + SDL_EndGPUCopyPass(copy_pass); + SDL_SubmitGPUCommandBuffer(cmd); + SDL_ReleaseGPUTransferBuffer(v->GpuDevice, font_transferbuffer); + } + + // Store our identifier + io.Fonts->SetTexID((ImTextureID)&bd->FontBinding); + + return true; +} + +// You probably never need to call this, as it is called by ImGui_ImplSDLGPU_CreateFontsTexture() and ImGui_ImplSDLGPU_Shutdown(). +void ImGui_ImplSDLGPU_DestroyFontsTexture() +{ + ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + + if(bd->FontTexture) + { + SDL_ReleaseGPUTexture(v->GpuDevice,bd->FontTexture); + bd->FontBinding.texture = nullptr; + bd->FontTexture = nullptr; + } + + io.Fonts->SetTexID(0); +} + +static void Imgui_ImplSDLGPU_CreateShaders() +{ + // Create the shader modules + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + + const char* driver = SDL_GetGPUDeviceDriver(v->GpuDevice); + + SDL_GPUShaderCreateInfo vertex_shader_info = {}; + vertex_shader_info.entrypoint = "main"; + vertex_shader_info.stage = SDL_GPU_SHADERSTAGE_VERTEX; + vertex_shader_info.num_uniform_buffers = 1; + vertex_shader_info.num_storage_buffers = 0; + vertex_shader_info.num_storage_textures = 0; + vertex_shader_info.num_samplers = 0; + + SDL_GPUShaderCreateInfo fragment_shader_info = {}; + fragment_shader_info.entrypoint = "main"; + fragment_shader_info.stage = SDL_GPU_SHADERSTAGE_FRAGMENT; + fragment_shader_info.num_samplers = 1; + fragment_shader_info.num_storage_buffers = 0; + fragment_shader_info.num_storage_textures = 0; + fragment_shader_info.num_uniform_buffers = 0; + + if(strcmp(driver,"vulkan") == 0) + { + vertex_shader_info.format = SDL_GPU_SHADERFORMAT_SPIRV; + vertex_shader_info.code = spirv_vertex; + vertex_shader_info.code_size = sizeof(spirv_vertex); + + fragment_shader_info.format = SDL_GPU_SHADERFORMAT_SPIRV; + fragment_shader_info.code = spirv_fragment; + fragment_shader_info.code_size = sizeof(spirv_fragment); + } + else if (strcmp(driver,"direct3d12") == 0) + { + vertex_shader_info.format = SDL_GPU_SHADERFORMAT_DXBC; + vertex_shader_info.code = dxbc_vertex; + vertex_shader_info.code_size = sizeof(dxbc_vertex); + + fragment_shader_info.format = SDL_GPU_SHADERFORMAT_DXBC; + fragment_shader_info.code = dxbc_fragment; + fragment_shader_info.code_size = sizeof(dxbc_fragment); + } +#ifdef __APPLE__ + else + { + vertex_shader_info.entrypoint = "main0"; + vertex_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB; + vertex_shader_info.code = metallib_vertex; + vertex_shader_info.code_size = sizeof(metallib_vertex); + + fragment_shader_info.entrypoint = "main0"; + fragment_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB; + fragment_shader_info.code = metallib_fragment; + fragment_shader_info.code_size = sizeof(metallib_fragment); + } +#endif + bd->VertexShader = SDL_CreateGPUShader(v->GpuDevice,&vertex_shader_info); + bd->FragmentShader = SDL_CreateGPUShader(v->GpuDevice,&fragment_shader_info); + + IM_ASSERT(bd->VertexShader != nullptr && "Failed to create vertex shader, call SDL_GetError() for more information"); + IM_ASSERT(bd->FragmentShader != nullptr && "Failed to create fragment shader, call SDL_GetError() for more information"); +} + +static void ImGui_ImplSDLGPU_CreateGraphicsPipeline() +{ + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + Imgui_ImplSDLGPU_CreateShaders(); + + SDL_GPUVertexBufferDescription vertex_buffer_desc[1]; + vertex_buffer_desc[0].slot = 0; + vertex_buffer_desc[0].input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX; + vertex_buffer_desc[0].instance_step_rate = 0; + vertex_buffer_desc[0].pitch = sizeof(ImDrawVert); + + SDL_GPUVertexAttribute vertex_attributes[3]; + vertex_attributes[0].buffer_slot = 0; + vertex_attributes[0].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2; + vertex_attributes[0].location = 0; + vertex_attributes[0].offset = offsetof(ImDrawVert,pos); + + vertex_attributes[1].buffer_slot = 0; + vertex_attributes[1].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2; + vertex_attributes[1].location = 1; + vertex_attributes[1].offset = offsetof(ImDrawVert, uv); + + vertex_attributes[2].buffer_slot = 0; + vertex_attributes[2].format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM; + vertex_attributes[2].location = 2; + vertex_attributes[2].offset = offsetof(ImDrawVert, col); + + SDL_GPUVertexInputState vertex_input_state = {}; + vertex_input_state.num_vertex_attributes = 3; + vertex_input_state.vertex_attributes = vertex_attributes; + vertex_input_state.num_vertex_buffers = 1; + vertex_input_state.vertex_buffer_descriptions = vertex_buffer_desc; + + SDL_GPURasterizerState rasterizer_state = {}; + rasterizer_state.fill_mode = SDL_GPU_FILLMODE_FILL; + rasterizer_state.cull_mode = SDL_GPU_CULLMODE_NONE; + rasterizer_state.front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE; + rasterizer_state.enable_depth_bias = false; + rasterizer_state.enable_depth_clip = false; + + SDL_GPUMultisampleState multisample_state = {}; + multisample_state.sample_count = v->MSAASamples; + multisample_state.enable_mask = false; + + SDL_GPUDepthStencilState depth_stencil_state = {}; + depth_stencil_state.enable_depth_test = false; + depth_stencil_state.enable_depth_write = false; + depth_stencil_state.enable_stencil_test = false; + + SDL_GPUColorTargetBlendState blend_state = {}; + blend_state.enable_blend = true; + blend_state.src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA; + blend_state.dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA; + blend_state.color_blend_op = SDL_GPU_BLENDOP_ADD; + blend_state.src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE; + blend_state.dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA; + blend_state.alpha_blend_op = SDL_GPU_BLENDOP_ADD; + blend_state.color_write_mask = SDL_GPU_COLORCOMPONENT_R | SDL_GPU_COLORCOMPONENT_G | SDL_GPU_COLORCOMPONENT_B | SDL_GPU_COLORCOMPONENT_A; + + SDL_GPUColorTargetDescription color_target_desc[1]; + color_target_desc[0].format = v->ColorTargetFormat; + color_target_desc[0].blend_state = blend_state; + + SDL_GPUGraphicsPipelineTargetInfo target_info = {}; + target_info.num_color_targets = 1; + target_info.color_target_descriptions = color_target_desc; + target_info.has_depth_stencil_target = false; + + SDL_GPUGraphicsPipelineCreateInfo pipeline_info = {}; + pipeline_info.vertex_shader = bd->VertexShader; + pipeline_info.fragment_shader = bd->FragmentShader; + pipeline_info.vertex_input_state = vertex_input_state; + pipeline_info.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST; + pipeline_info.rasterizer_state = rasterizer_state; + pipeline_info.multisample_state = multisample_state; + pipeline_info.depth_stencil_state = depth_stencil_state; + pipeline_info.target_info = target_info; + + bd->Pipeline = SDL_CreateGPUGraphicsPipeline(v->GpuDevice,&pipeline_info); + IM_ASSERT(bd->Pipeline != nullptr && "Failed to create graphics pipeline, call SDL_GetError() for more information"); +} + +bool ImGui_ImplSDLGPU_CreateDeviceObjects() +{ + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + + if (!bd->FontSampler) + { + // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling. + SDL_GPUSamplerCreateInfo sampler_info = {}; + sampler_info.min_filter = SDL_GPU_FILTER_LINEAR; + sampler_info.mag_filter = SDL_GPU_FILTER_LINEAR; + sampler_info.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR; + sampler_info.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + sampler_info.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + sampler_info.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + sampler_info.mip_lod_bias = 0.0f; + sampler_info.min_lod = -1000.0f; + sampler_info.max_lod = 1000.0f; + sampler_info.enable_anisotropy = true; + sampler_info.max_anisotropy = 1.0f; + sampler_info.enable_compare = false; + + bd->FontSampler = SDL_CreateGPUSampler(v->GpuDevice,&sampler_info); + bd->FontBinding.sampler = bd->FontSampler; + IM_ASSERT(bd->FontSampler != nullptr && "Failed to create font sampler, call SDL_GetError() for more information"); + } + + ImGui_ImplSDLGPU_CreateGraphicsPipeline(); + + return true; +} + +void ImGui_ImplSDLGPU_DestroyFrameData() +{ + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + + SDL_ReleaseGPUBuffer(v->GpuDevice,bd->MainWindowFrameData.VertexBuffer); + SDL_ReleaseGPUBuffer(v->GpuDevice,bd->MainWindowFrameData.IndexBuffer); + bd->MainWindowFrameData.VertexBuffer = nullptr; + bd->MainWindowFrameData.IndexBuffer = nullptr; + bd->MainWindowFrameData.VertexBufferSize = 0; + bd->MainWindowFrameData.IndexBufferSize = 0; +} + +void ImGui_ImplSDLGPU_DestroyDeviceObjects() +{ + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + + ImGui_ImplSDLGPU_DestroyFrameData(); + ImGui_ImplSDLGPU_DestroyFontsTexture(); + + if(bd->VertexShader) { SDL_ReleaseGPUShader(v->GpuDevice,bd->VertexShader); bd->VertexShader = nullptr;} + if(bd->FragmentShader) { SDL_ReleaseGPUShader(v->GpuDevice,bd->FragmentShader); bd->FragmentShader = nullptr;} + if(bd->FontSampler) { SDL_ReleaseGPUSampler(v->GpuDevice, bd->FontSampler); bd->FontSampler = nullptr;} + if(bd->Pipeline) { SDL_ReleaseGPUGraphicsPipeline(v->GpuDevice,bd->Pipeline); bd->Pipeline = nullptr;} +} + +bool ImGui_ImplSDLGPU_Init(ImGui_ImplSDLGPU_InitInfo* info) +{ + ImGuiIO& io = ImGui::GetIO(); + IMGUI_CHECKVERSION(); + IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); + + // Setup backend capabilities flags + ImGui_ImplSDLGPU_Data* bd = IM_NEW(ImGui_ImplSDLGPU_Data)(); + io.BackendRendererUserData = (void*)bd; + io.BackendRendererName = "imgui_impl_sdlgpu"; + io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. + + IM_ASSERT(info->GpuDevice != nullptr); + IM_ASSERT(info->ColorTargetFormat != SDL_GPU_TEXTUREFORMAT_INVALID); + + bd->GPUInitInfo = *info; + + ImGui_ImplSDLGPU_CreateDeviceObjects(); + + return true; +} + +void ImGui_ImplSDLGPU_Shutdown() +{ + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); + ImGuiIO& io = ImGui::GetIO(); + + ImGui_ImplSDLGPU_DestroyDeviceObjects(); + io.BackendRendererName = nullptr; + io.BackendRendererUserData = nullptr; + io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset; + IM_DELETE(bd); +} + +void ImGui_ImplSDLGPU_NewFrame() +{ + ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplVulkan_Init()?"); + + if(!bd->FontTexture) + ImGui_ImplSDLGPU_CreateFontsTexture(); +} + +#endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_sdlgpu3.h b/backends/imgui_impl_sdlgpu3.h new file mode 100644 index 000000000000..18d3001e400c --- /dev/null +++ b/backends/imgui_impl_sdlgpu3.h @@ -0,0 +1,46 @@ +// dear imgui: Renderer Backend for SDL_Gpu +// This needs to be used along with the SDL3 Platform Backend + +// Implemented features: +// [X] Renderer: User texture binding. Use simply cast a reference to your SDL_GPUTextureSamplerBinding to ImTextureID. +// [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. + +// The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification. +// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/ + +// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. +// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). +// - Introduction, links and more at the top of imgui.cpp + +// Important note to the reader who wish to integrate imgui_impl_sdlgpu3.cpp/.h in their own engine/app. +// - Unline other backends, the user must call the function Imgui_ImplSDLGPU_PrepareDrawData BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData. +// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info. + +#pragma once +#include "imgui.h" // IMGUI_IMPL_API +#ifndef IMGUI_DISABLE +#include + +// Initialization data, for ImGui_ImplSDLGPU_Init() +// - Remember to set ColorTargetFormat to the correct format. If you're rendering to the swapchain, call SDL_GetGPUSwapchainTextureFormat to query the right value +struct ImGui_ImplSDLGPU_InitInfo +{ + SDL_GPUDevice* GpuDevice = nullptr; + SDL_GPUTextureFormat ColorTargetFormat = SDL_GPU_TEXTUREFORMAT_INVALID; + SDL_GPUSampleCount MSAASamples = SDL_GPU_SAMPLECOUNT_1; +}; + +// Follow "Getting Started" link and check examples/ folder to learn about using backends! +IMGUI_IMPL_API bool ImGui_ImplSDLGPU_Init(ImGui_ImplSDLGPU_InitInfo* info); +IMGUI_IMPL_API void ImGui_ImplSDLGPU_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplSDLGPU_NewFrame(); +IMGUI_IMPL_API void Imgui_ImplSDLGPU_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer); +IMGUI_IMPL_API void ImGui_ImplSDLGPU_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline = nullptr); +IMGUI_IMPL_API bool ImGui_ImplSDLGPU_CreateFontsTexture(); +IMGUI_IMPL_API void ImGui_ImplSDLGPU_DestroyFontsTexture(); + +#endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_sdlgpu3_shaders.h b/backends/imgui_impl_sdlgpu3_shaders.h new file mode 100644 index 000000000000..f792aa6abd77 --- /dev/null +++ b/backends/imgui_impl_sdlgpu3_shaders.h @@ -0,0 +1,372 @@ +#pragma once +#ifndef IMGUI_DISABLE +#include + +// Data exported using +// misc/fonts/binary_to_compressed_c.exe -u8 -nocompress filename symbolname >filename.h +// With some manual pasting. + +// Check sdlgpu3/ folder for the shaders' source code and instruction on how to build them +const uint8_t spirv_vertex[1732] = { + 3,2,35,7,0,0,1,0,11,0,13,0,55,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,1,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,10,0,0,0,0,0,4,0,0,0,109, + 97,105,110,0,0,0,0,11,0,0,0,15,0,0,0,21,0,0,0,30,0,0,0,31,0,0,0,3,0,3,0,2,0,0,0,194,1,0,0,4,0,10,0,71,76,95,71,79,79,71,76,69,95,99,112,112,95,115,116,121,108,101,95,108,105,110,101, + 95,100,105,114,101,99,116,105,118,101,0,0,4,0,8,0,71,76,95,71,79,79,71,76,69,95,105,110,99,108,117,100,101,95,100,105,114,101,99,116,105,118,101,0,5,0,4,0,4,0,0,0,109,97,105,110,0, + 0,0,0,5,0,3,0,9,0,0,0,0,0,0,0,6,0,5,0,9,0,0,0,0,0,0,0,67,111,108,111,114,0,0,0,6,0,4,0,9,0,0,0,1,0,0,0,85,86,0,0,5,0,3,0,11,0,0,0,79,117,116,0,5,0,4,0,15,0,0,0,97,67,111,108,111,114, + 0,0,5,0,3,0,21,0,0,0,97,85,86,0,5,0,6,0,28,0,0,0,103,108,95,80,101,114,86,101,114,116,101,120,0,0,0,0,6,0,6,0,28,0,0,0,0,0,0,0,103,108,95,80,111,115,105,116,105,111,110,0,6,0,7,0,28, + 0,0,0,1,0,0,0,103,108,95,80,111,105,110,116,83,105,122,101,0,0,0,0,6,0,7,0,28,0,0,0,2,0,0,0,103,108,95,67,108,105,112,68,105,115,116,97,110,99,101,0,6,0,7,0,28,0,0,0,3,0,0,0,103,108, + 95,67,117,108,108,68,105,115,116,97,110,99,101,0,5,0,3,0,30,0,0,0,0,0,0,0,5,0,4,0,31,0,0,0,97,80,111,115,0,0,0,0,5,0,6,0,33,0,0,0,117,80,117,115,104,67,111,110,115,116,97,110,116,0, + 0,0,6,0,5,0,33,0,0,0,0,0,0,0,117,83,99,97,108,101,0,0,6,0,6,0,33,0,0,0,1,0,0,0,117,84,114,97,110,115,108,97,116,101,0,0,5,0,3,0,35,0,0,0,112,99,0,0,71,0,4,0,11,0,0,0,30,0,0,0,0,0,0, + 0,71,0,4,0,15,0,0,0,30,0,0,0,2,0,0,0,71,0,4,0,21,0,0,0,30,0,0,0,1,0,0,0,71,0,3,0,28,0,0,0,2,0,0,0,72,0,5,0,28,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,72,0,5,0,28,0,0,0,1,0,0,0,11,0,0,0,1,0, + 0,0,72,0,5,0,28,0,0,0,2,0,0,0,11,0,0,0,3,0,0,0,72,0,5,0,28,0,0,0,3,0,0,0,11,0,0,0,4,0,0,0,71,0,4,0,31,0,0,0,30,0,0,0,0,0,0,0,71,0,3,0,33,0,0,0,2,0,0,0,72,0,5,0,33,0,0,0,0,0,0,0,35, + 0,0,0,0,0,0,0,72,0,5,0,33,0,0,0,1,0,0,0,35,0,0,0,8,0,0,0,71,0,4,0,35,0,0,0,33,0,0,0,0,0,0,0,71,0,4,0,35,0,0,0,34,0,0,0,1,0,0,0,19,0,2,0,2,0,0,0,33,0,3,0,3,0,0,0,2,0,0,0,22,0,3,0,6, + 0,0,0,32,0,0,0,23,0,4,0,7,0,0,0,6,0,0,0,4,0,0,0,23,0,4,0,8,0,0,0,6,0,0,0,2,0,0,0,30,0,4,0,9,0,0,0,7,0,0,0,8,0,0,0,32,0,4,0,10,0,0,0,3,0,0,0,9,0,0,0,59,0,4,0,10,0,0,0,11,0,0,0,3,0,0, + 0,21,0,4,0,12,0,0,0,32,0,0,0,1,0,0,0,43,0,4,0,12,0,0,0,13,0,0,0,0,0,0,0,32,0,4,0,14,0,0,0,1,0,0,0,7,0,0,0,59,0,4,0,14,0,0,0,15,0,0,0,1,0,0,0,32,0,4,0,17,0,0,0,3,0,0,0,7,0,0,0,43,0, + 4,0,12,0,0,0,19,0,0,0,1,0,0,0,32,0,4,0,20,0,0,0,1,0,0,0,8,0,0,0,59,0,4,0,20,0,0,0,21,0,0,0,1,0,0,0,32,0,4,0,23,0,0,0,3,0,0,0,8,0,0,0,21,0,4,0,25,0,0,0,32,0,0,0,0,0,0,0,43,0,4,0,25, + 0,0,0,26,0,0,0,1,0,0,0,28,0,4,0,27,0,0,0,6,0,0,0,26,0,0,0,30,0,6,0,28,0,0,0,7,0,0,0,6,0,0,0,27,0,0,0,27,0,0,0,32,0,4,0,29,0,0,0,3,0,0,0,28,0,0,0,59,0,4,0,29,0,0,0,30,0,0,0,3,0,0,0, + 59,0,4,0,20,0,0,0,31,0,0,0,1,0,0,0,30,0,4,0,33,0,0,0,8,0,0,0,8,0,0,0,32,0,4,0,34,0,0,0,2,0,0,0,33,0,0,0,59,0,4,0,34,0,0,0,35,0,0,0,2,0,0,0,32,0,4,0,36,0,0,0,2,0,0,0,8,0,0,0,43,0,4, + 0,6,0,0,0,43,0,0,0,0,0,0,0,43,0,4,0,6,0,0,0,44,0,0,0,0,0,128,63,43,0,4,0,6,0,0,0,49,0,0,0,0,0,128,191,32,0,4,0,50,0,0,0,3,0,0,0,6,0,0,0,54,0,5,0,2,0,0,0,4,0,0,0,0,0,0,0,3,0,0,0,248, + 0,2,0,5,0,0,0,61,0,4,0,7,0,0,0,16,0,0,0,15,0,0,0,65,0,5,0,17,0,0,0,18,0,0,0,11,0,0,0,13,0,0,0,62,0,3,0,18,0,0,0,16,0,0,0,61,0,4,0,8,0,0,0,22,0,0,0,21,0,0,0,65,0,5,0,23,0,0,0,24,0,0, + 0,11,0,0,0,19,0,0,0,62,0,3,0,24,0,0,0,22,0,0,0,61,0,4,0,8,0,0,0,32,0,0,0,31,0,0,0,65,0,5,0,36,0,0,0,37,0,0,0,35,0,0,0,13,0,0,0,61,0,4,0,8,0,0,0,38,0,0,0,37,0,0,0,133,0,5,0,8,0,0,0, + 39,0,0,0,32,0,0,0,38,0,0,0,65,0,5,0,36,0,0,0,40,0,0,0,35,0,0,0,19,0,0,0,61,0,4,0,8,0,0,0,41,0,0,0,40,0,0,0,129,0,5,0,8,0,0,0,42,0,0,0,39,0,0,0,41,0,0,0,81,0,5,0,6,0,0,0,45,0,0,0,42, + 0,0,0,0,0,0,0,81,0,5,0,6,0,0,0,46,0,0,0,42,0,0,0,1,0,0,0,80,0,7,0,7,0,0,0,47,0,0,0,45,0,0,0,46,0,0,0,43,0,0,0,44,0,0,0,65,0,5,0,17,0,0,0,48,0,0,0,30,0,0,0,13,0,0,0,62,0,3,0,48,0,0, + 0,47,0,0,0,65,0,6,0,50,0,0,0,51,0,0,0,30,0,0,0,13,0,0,0,26,0,0,0,61,0,4,0,6,0,0,0,52,0,0,0,51,0,0,0,133,0,5,0,6,0,0,0,53,0,0,0,52,0,0,0,49,0,0,0,65,0,6,0,50,0,0,0,54,0,0,0,30,0,0,0, + 13,0,0,0,26,0,0,0,62,0,3,0,54,0,0,0,53,0,0,0,253,0,1,0,56,0,1,0, +}; +const uint8_t spirv_fragment[844] = { + 3,2,35,7,0,0,1,0,11,0,13,0,30,0,0,0,0,0,0,0,17,0,2,0,1,0,0,0,11,0,6,0,1,0,0,0,71,76,83,76,46,115,116,100,46,52,53,48,0,0,0,0,14,0,3,0,0,0,0,0,1,0,0,0,15,0,7,0,4,0,0,0,4,0,0,0,109,97, + 105,110,0,0,0,0,9,0,0,0,13,0,0,0,16,0,3,0,4,0,0,0,7,0,0,0,3,0,3,0,2,0,0,0,194,1,0,0,4,0,10,0,71,76,95,71,79,79,71,76,69,95,99,112,112,95,115,116,121,108,101,95,108,105,110,101,95,100, + 105,114,101,99,116,105,118,101,0,0,4,0,8,0,71,76,95,71,79,79,71,76,69,95,105,110,99,108,117,100,101,95,100,105,114,101,99,116,105,118,101,0,5,0,4,0,4,0,0,0,109,97,105,110,0,0,0,0,5, + 0,4,0,9,0,0,0,102,67,111,108,111,114,0,0,5,0,3,0,11,0,0,0,0,0,0,0,6,0,5,0,11,0,0,0,0,0,0,0,67,111,108,111,114,0,0,0,6,0,4,0,11,0,0,0,1,0,0,0,85,86,0,0,5,0,3,0,13,0,0,0,73,110,0,0,5, + 0,5,0,22,0,0,0,115,84,101,120,116,117,114,101,0,0,0,0,71,0,4,0,9,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,13,0,0,0,30,0,0,0,0,0,0,0,71,0,4,0,22,0,0,0,33,0,0,0,0,0,0,0,71,0,4,0,22,0,0,0,34,0, + 0,0,2,0,0,0,19,0,2,0,2,0,0,0,33,0,3,0,3,0,0,0,2,0,0,0,22,0,3,0,6,0,0,0,32,0,0,0,23,0,4,0,7,0,0,0,6,0,0,0,4,0,0,0,32,0,4,0,8,0,0,0,3,0,0,0,7,0,0,0,59,0,4,0,8,0,0,0,9,0,0,0,3,0,0,0,23, + 0,4,0,10,0,0,0,6,0,0,0,2,0,0,0,30,0,4,0,11,0,0,0,7,0,0,0,10,0,0,0,32,0,4,0,12,0,0,0,1,0,0,0,11,0,0,0,59,0,4,0,12,0,0,0,13,0,0,0,1,0,0,0,21,0,4,0,14,0,0,0,32,0,0,0,1,0,0,0,43,0,4,0, + 14,0,0,0,15,0,0,0,0,0,0,0,32,0,4,0,16,0,0,0,1,0,0,0,7,0,0,0,25,0,9,0,19,0,0,0,6,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,27,0,3,0,20,0,0,0,19,0,0,0,32,0,4,0,21,0,0,0,0, + 0,0,0,20,0,0,0,59,0,4,0,21,0,0,0,22,0,0,0,0,0,0,0,43,0,4,0,14,0,0,0,24,0,0,0,1,0,0,0,32,0,4,0,25,0,0,0,1,0,0,0,10,0,0,0,54,0,5,0,2,0,0,0,4,0,0,0,0,0,0,0,3,0,0,0,248,0,2,0,5,0,0,0,65, + 0,5,0,16,0,0,0,17,0,0,0,13,0,0,0,15,0,0,0,61,0,4,0,7,0,0,0,18,0,0,0,17,0,0,0,61,0,4,0,20,0,0,0,23,0,0,0,22,0,0,0,65,0,5,0,25,0,0,0,26,0,0,0,13,0,0,0,24,0,0,0,61,0,4,0,10,0,0,0,27,0, + 0,0,26,0,0,0,87,0,5,0,7,0,0,0,28,0,0,0,23,0,0,0,27,0,0,0,133,0,5,0,7,0,0,0,29,0,0,0,18,0,0,0,28,0,0,0,62,0,3,0,9,0,0,0,29,0,0,0,253,0,1,0,56,0,1,0, +}; + +const uint8_t dxbc_vertex[1064] = { + 68,88,66,67,32,50,127,204,241,196,165,104,216,114,216,116,220,164,29,45,1,0,0,0,40,4,0,0,5,0,0,0,52,0,0,0,136,1,0,0,236,1,0,0,92,2,0,0,140,3,0,0,82,68,69,70,76,1,0,0,1,0,0,0,116,0, + 0,0,1,0,0,0,60,0,0,0,1,5,254,255,0,5,0,0,34,1,0,0,19,19,68,37,60,0,0,0,24,0,0,0,40,0,0,0,40,0,0,0,36,0,0,0,12,0,0,0,0,0,0,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, + 0,1,0,0,0,1,0,0,0,0,0,0,0,117,80,117,115,104,67,111,110,115,116,97,110,116,0,171,171,100,0,0,0,2,0,0,0,140,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,220,0,0,0,0,0,0,0,8,0,0,0,2,0,0,0,240,0,0, + 0,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,20,1,0,0,8,0,0,0,8,0,0,0,2,0,0,0,240,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,255,255,255,255,0,0,0,0,112,99,95,117,83,99,97, + 108,101,0,102,108,111,97,116,50,0,171,171,171,1,0,3,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,0,0,0,112,99,95,117,84,114,97,110,115,108,97,116,101,0,77,105,99,114, + 111,115,111,102,116,32,40,82,41,32,72,76,83,76,32,83,104,97,100,101,114,32,67,111,109,112,105,108,101,114,32,49,48,46,49,0,171,171,73,83,71,78,92,0,0,0,3,0,0,0,8,0,0,0,80,0,0,0,0,0, + 0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,3,0,0,80,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,3,3,0,0,80,0,0,0,2,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,15,15,0,0,84,69,88,67,79,79,82,68,0,171,171,171,79,83, + 71,78,104,0,0,0,3,0,0,0,8,0,0,0,80,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,15,0,0,0,80,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,3,12,0,0,89,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,2,0,0,0,15,0,0, + 0,84,69,88,67,79,79,82,68,0,83,86,95,80,111,115,105,116,105,111,110,0,171,171,171,83,72,69,88,40,1,0,0,81,0,1,0,74,0,0,0,106,8,0,1,89,0,0,7,70,142,48,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, + 0,0,1,0,0,0,95,0,0,3,50,16,16,0,0,0,0,0,95,0,0,3,50,16,16,0,1,0,0,0,95,0,0,3,242,16,16,0,2,0,0,0,101,0,0,3,242,32,16,0,0,0,0,0,101,0,0,3,50,32,16,0,1,0,0,0,103,0,0,4,242,32,16,0,2, + 0,0,0,1,0,0,0,104,0,0,2,1,0,0,0,50,0,0,13,50,0,16,0,0,0,0,0,70,16,16,0,0,0,0,0,70,128,48,0,0,0,0,0,0,0,0,0,0,0,0,0,230,138,48,0,0,0,0,0,0,0,0,0,0,0,0,0,54,0,0,6,34,32,16,0,2,0,0,0, + 26,0,16,128,65,0,0,0,0,0,0,0,54,0,0,5,242,32,16,0,0,0,0,0,70,30,16,0,2,0,0,0,54,0,0,5,18,32,16,0,2,0,0,0,10,0,16,0,0,0,0,0,54,0,0,8,194,32,16,0,2,0,0,0,2,64,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,128,63,54,0,0,5,50,32,16,0,1,0,0,0,70,16,16,0,1,0,0,0,62,0,0,1,83,84,65,84,148,0,0,0,7,0,0,0,1,0,0,0,0,0,0,0,6,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; +const uint8_t dxbc_fragment[744] = { + 68,88,66,67,235,219,43,109,38,151,39,223,98,41,193,28,215,98,67,110,1,0,0,0,232,2,0,0,5,0,0,0,52,0,0,0,12,1,0,0,88,1,0,0,140,1,0,0,76,2,0,0,82,68,69,70,208,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,60,0,0,0,1,5,255,255,0,5,0,0,167,0,0,0,19,19,68,37,60,0,0,0,24,0,0,0,40,0,0,0,40,0,0,0,36,0,0,0,12,0,0,0,0,0,0,0,140,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0, + 0,0,2,0,0,0,0,0,0,0,158,0,0,0,2,0,0,0,5,0,0,0,4,0,0,0,255,255,255,255,0,0,0,0,1,0,0,0,12,0,0,0,2,0,0,0,0,0,0,0,95,115,84,101,120,116,117,114,101,95,115,97,109,112,108,101,114,0,115, + 84,101,120,116,117,114,101,0,77,105,99,114,111,115,111,102,116,32,40,82,41,32,72,76,83,76,32,83,104,97,100,101,114,32,67,111,109,112,105,108,101,114,32,49,48,46,49,0,171,73,83,71,78, + 68,0,0,0,2,0,0,0,8,0,0,0,56,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,15,15,0,0,56,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,3,3,0,0,84,69,88,67,79,79,82,68,0,171,171,171,79,83,71,78,44,0, + 0,0,1,0,0,0,8,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,15,0,0,0,83,86,95,84,97,114,103,101,116,0,171,171,83,72,69,88,184,0,0,0,81,0,0,0,46,0,0,0,106,8,0,1,90,0,0,6,70,110,48, + 0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,88,24,0,7,70,126,48,0,0,0,0,0,0,0,0,0,0,0,0,0,85,85,0,0,2,0,0,0,98,16,0,3,242,16,16,0,0,0,0,0,98,16,0,3,50,16,16,0,1,0,0,0,101,0,0,3,242,32,16,0,0, + 0,0,0,104,0,0,2,1,0,0,0,69,0,0,11,242,0,16,0,0,0,0,0,70,16,16,0,1,0,0,0,70,126,32,0,0,0,0,0,0,0,0,0,0,96,32,0,0,0,0,0,0,0,0,0,56,0,0,7,242,32,16,0,0,0,0,0,70,14,16,0,0,0,0,0,70,30, + 16,0,0,0,0,0,62,0,0,1,83,84,65,84,148,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +#ifdef __APPLE__ +#include +#if TARGET_OS_MAC +const uint8_t metallib_vertex[3892] = { + 77,84,76,66,1,128,2,0,7,0,0,129,14,0,0,0,52,15,0,0,0,0,0,0,88,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,49,0,0,0,0,0,0,0,12,1,0,0,0,0,0,0,8,0,0,0,0,0,0,0,20,1,0,0,0,0,0,0,32, + 14,0,0,0,0,0,0,1,0,0,0,123,0,0,0,78,65,77,69,6,0,109,97,105,110,48,0,84,89,80,69,1,0,0,72,65,83,72,32,0,62,81,190,157,8,240,236,158,164,213,65,62,170,226,96,136,231,243,238,160,100, + 26,13,254,254,64,19,129,180,3,149,75,77,68,83,90,8,0,32,14,0,0,0,0,0,0,79,70,70,84,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,86,69,82,83,8,0,2,0,6,0,3,0,1,0,69,78,68,84, + 69,78,68,84,45,0,0,0,86,65,84,84,24,0,3,0,97,80,111,115,0,0,128,97,85,86,0,1,128,97,67,111,108,111,114,0,2,128,86,65,84,89,5,0,3,0,4,4,6,69,78,68,84,4,0,0,0,69,78,68,84,222,192,23, + 11,0,0,0,0,20,0,0,0,8,14,0,0,255,255,255,255,66,67,192,222,53,20,0,0,3,0,0,0,98,12,48,36,128,16,5,200,20,0,0,0,33,12,0,0,74,3,0,0,11,2,33,0,2,0,0,0,22,0,0,0,7,129,35,145,65,200,4,73, + 6,16,50,57,146,1,132,12,37,5,8,25,30,4,139,98,128,16,69,2,66,146,11,66,132,16,50,20,56,8,24,75,10,50,66,136,72,112,196,33,35,68,18,135,140,16,65,146,2,100,200,8,177,20,32,67,70,136, + 32,201,1,50,66,132,24,42,40,42,144,49,124,176,92,145,32,196,200,0,0,0,137,32,0,0,24,0,0,0,50,34,8,9,32,98,70,0,33,43,36,152,16,33,37,36,152,16,25,39,12,133,164,144,96,66,100,92,32, + 36,100,130,224,153,1,24,70,32,128,97,4,1,184,67,72,32,37,77,17,37,76,62,149,82,210,193,57,141,52,1,205,148,4,145,65,4,66,48,197,136,68,145,13,4,204,17,128,129,10,228,28,1,40,12,34, + 8,194,48,2,145,140,0,0,0,0,0,81,24,0,0,100,0,0,0,27,246,35,248,255,255,255,255,1,48,5,192,15,0,56,0,254,0,144,0,10,232,3,34,28,224,1,30,228,225,29,240,161,13,204,161,30,220,97,28,218, + 192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,128,48,7,121,8,135,118,40,135,54,128,135,119,72,7,119,160,135,114,144,7,32,28,216,129,29,0,162,29,210,193,29,218,128,29, + 202,225,28,194,129,29,218,192,30,202,97,28,232,225,29,228,161,13,238,33,29,200,129,30,208,1,136,3,57,192,3,96,112,135,119,104,3,113,168,135,116,96,7,122,72,7,119,152,7,128,112,135, + 119,104,131,116,112,7,115,152,135,54,48,7,120,104,131,118,8,7,122,64,7,128,30,228,161,30,202,1,32,220,225,29,218,192,29,194,193,29,230,161,13,204,1,30,218,160,29,194,129,30,208,1,160, + 7,121,168,135,114,0,8,119,120,135,54,152,135,116,56,7,119,40,7,114,104,3,125,40,7,121,120,135,121,104,3,115,128,135,54,104,135,112,160,7,116,0,232,65,30,234,161,28,0,194,29,222,161, + 13,232,65,30,194,1,30,224,33,29,220,225,28,218,160,29,194,129,30,208,1,160,7,121,168,135,114,0,136,121,160,135,112,24,135,117,104,3,120,144,135,119,160,135,114,24,7,122,120,7,121,104, + 3,113,168,7,115,48,135,114,144,135,54,152,135,116,208,135,114,0,240,0,32,234,193,29,230,33,28,204,161,28,218,192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,96,195,24,8, + 4,176,0,164,0,84,65,128,4,105,0,13,225,144,14,242,208,6,226,80,15,230,96,14,229,32,15,109,224,14,239,208,6,225,192,14,233,16,14,243,0,0,0,73,24,0,0,1,0,0,0,19,132,64,0,19,176,112,72, + 7,121,176,3,58,104,131,112,128,7,120,96,135,114,104,131,118,8,135,113,120,135,121,192,135,56,160,3,55,128,3,55,128,131,13,183,81,14,109,0,15,122,96,7,116,160,7,118,64,7,122,96,7,116, + 208,6,233,16,7,122,128,7,122,128,7,109,144,14,120,160,7,120,160,7,120,208,6,233,16,7,118,160,7,113,96,7,122,16,7,118,208,6,233,48,7,114,160,7,115,32,7,122,48,7,114,208,6,233,96,7,116, + 160,7,118,64,7,122,96,7,116,208,6,230,48,7,114,160,7,115,32,7,122,48,7,114,208,6,230,96,7,116,160,7,118,64,7,122,96,7,116,208,6,246,16,7,118,160,7,113,96,7,122,16,7,118,208,6,246,32, + 7,116,160,7,115,32,7,122,48,7,114,208,6,246,48,7,114,160,7,115,32,7,122,48,7,114,208,6,246,64,7,120,160,7,118,64,7,122,96,7,116,208,6,246,96,7,116,160,7,118,64,7,122,96,7,116,208,6, + 246,144,7,118,160,7,113,32,7,120,160,7,113,32,7,120,208,6,246,16,7,114,128,7,122,16,7,114,128,7,122,16,7,114,128,7,109,96,15,113,144,7,114,160,7,114,80,7,118,160,7,114,80,7,118,208, + 6,246,32,7,117,96,7,122,32,7,117,96,7,122,32,7,117,96,7,109,96,15,117,16,7,114,160,7,117,16,7,114,160,7,117,16,7,114,208,6,246,16,7,112,32,7,116,160,7,113,0,7,114,64,7,122,16,7,112, + 32,7,116,208,6,238,128,7,122,16,7,118,160,7,115,32,7,26,33,12,89,48,0,210,208,67,42,160,48,0,0,8,0,0,0,4,0,0,0,0,0,10,64,98,131,64,81,166,1,0,128,44,16,0,11,0,0,0,50,30,152,16,25,17, + 76,144,140,9,38,71,198,4,67,202,34,40,129,66,40,135,242,41,64,129,130,40,144,98,24,1,40,3,218,17,0,210,177,132,39,0,0,0,177,24,0,0,165,0,0,0,51,8,128,28,196,225,28,102,20,1,61,136, + 67,56,132,195,140,66,128,7,121,120,7,115,152,113,12,230,0,15,237,16,14,244,128,14,51,12,66,30,194,193,29,206,161,28,102,48,5,61,136,67,56,132,131,27,204,3,61,200,67,61,140,3,61,204, + 120,140,116,112,7,123,8,7,121,72,135,112,112,7,122,112,3,118,120,135,112,32,135,25,204,17,14,236,144,14,225,48,15,110,48,15,227,240,14,240,80,14,51,16,196,29,222,33,28,216,33,29,194, + 97,30,102,48,137,59,188,131,59,208,67,57,180,3,60,188,131,60,132,3,59,204,240,20,118,96,7,123,104,7,55,104,135,114,104,7,55,128,135,112,144,135,112,96,7,118,40,7,118,248,5,118,120, + 135,119,128,135,95,8,135,113,24,135,114,152,135,121,152,129,44,238,240,14,238,224,14,245,192,14,236,48,3,98,200,161,28,228,161,28,204,161,28,228,161,28,220,97,28,202,33,28,196,129, + 29,202,97,6,214,144,67,57,200,67,57,152,67,57,200,67,57,184,195,56,148,67,56,136,3,59,148,195,47,188,131,60,252,130,59,212,3,59,176,195,12,199,105,135,112,88,135,114,112,131,116,104, + 7,120,96,135,116,24,135,116,160,135,25,206,83,15,238,0,15,242,80,14,228,144,14,227,64,15,225,32,14,236,80,14,51,32,40,29,220,193,30,194,65,30,210,33,28,220,129,30,220,224,28,228,225, + 29,234,1,30,102,24,81,56,176,67,58,156,131,59,204,80,36,118,96,7,123,104,7,55,96,135,119,120,7,120,152,81,76,244,144,15,240,80,14,51,30,106,30,202,97,28,232,33,29,222,193,29,126,1, + 30,228,161,28,204,33,29,240,97,6,84,133,131,56,204,195,59,176,67,61,208,67,57,252,194,60,228,67,59,136,195,59,176,195,140,197,10,135,121,152,135,119,24,135,116,8,7,122,40,7,114,152, + 129,92,227,16,14,236,192,14,229,80,14,243,48,35,193,210,65,30,228,225,23,216,225,29,222,1,30,102,72,25,59,176,131,61,180,131,27,132,195,56,140,67,57,204,195,60,184,193,57,200,195,59, + 212,3,60,204,72,180,113,8,7,118,96,7,113,8,135,113,88,135,25,219,198,14,236,96,15,237,224,6,240,32,15,229,48,15,229,32,15,246,80,14,110,16,14,227,48,14,229,48,15,243,224,6,233,224, + 14,228,80,14,248,48,35,226,236,97,28,194,129,29,216,225,23,236,33,29,230,33,29,196,33,29,216,33,29,232,33,31,102,32,157,59,188,67,61,184,3,57,148,131,57,204,88,188,112,112,7,119,120, + 7,122,8,7,122,72,135,119,112,135,25,206,135,14,229,16,14,240,16,14,236,192,14,239,48,14,243,144,14,244,80,14,51,40,48,8,135,116,144,7,55,48,135,122,112,135,113,160,135,116,120,7,119, + 248,133,115,144,135,119,168,7,120,152,7,0,0,0,0,121,32,0,0,26,1,0,0,114,30,72,32,67,136,12,25,9,114,50,72,32,35,129,140,145,145,209,68,160,16,40,100,60,49,50,66,142,144,33,163,152, + 6,100,208,82,0,0,0,139,210,88,216,6,109,80,28,20,27,71,6,209,18,25,76,178,24,6,179,64,18,49,24,202,131,68,148,161,68,87,35,0,0,0,0,83,68,75,32,86,101,114,115,105,111,110,119,99,104, + 97,114,95,115,105,122,101,102,114,97,109,101,45,112,111,105,110,116,101,114,97,105,114,46,109,97,120,95,100,101,118,105,99,101,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120, + 95,99,111,110,115,116,97,110,116,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,104,114,101,97,100,103,114,111,117,112,95,98,117,102,102,101,114,115,97,105,114,46,109, + 97,120,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,114,101,97,100,95,119,114,105,116,101,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,115,97,109, + 112,108,101,114,115,65,112,112,108,101,32,109,101,116,97,108,32,118,101,114,115,105,111,110,32,51,50,48,50,51,46,51,54,56,32,40,109,101,116,97,108,102,101,45,51,50,48,50,51,46,51,54, + 56,41,77,101,116,97,108,97,105,114,46,99,111,109,112,105,108,101,46,100,101,110,111,114,109,115,95,100,105,115,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,97,115, + 116,95,109,97,116,104,95,101,110,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,114,97,109,101,98,117,102,102,101,114,95,102,101,116,99,104,95,101,110,97,98,108,101, + 97,105,114,46,118,101,114,116,101,120,95,111,117,116,112,117,116,117,115,101,114,40,108,111,99,110,48,41,97,105,114,46,97,114,103,95,116,121,112,101,95,110,97,109,101,102,108,111,97, + 116,52,97,105,114,46,97,114,103,95,110,97,109,101,79,117,116,95,67,111,108,111,114,117,115,101,114,40,108,111,99,110,49,41,102,108,111,97,116,50,79,117,116,95,85,86,97,105,114,46,112, + 111,115,105,116,105,111,110,103,108,95,80,111,115,105,116,105,111,110,97,105,114,46,118,101,114,116,101,120,95,105,110,112,117,116,97,105,114,46,108,111,99,97,116,105,111,110,95,105, + 110,100,101,120,97,80,111,115,97,85,86,97,67,111,108,111,114,97,105,114,46,98,117,102,102,101,114,97,105,114,46,98,117,102,102,101,114,95,115,105,122,101,97,105,114,46,114,101,97,100, + 97,105,114,46,97,100,100,114,101,115,115,95,115,112,97,99,101,97,105,114,46,115,116,114,117,99,116,95,116,121,112,101,95,105,110,102,111,117,83,99,97,108,101,117,84,114,97,110,115, + 108,97,116,101,97,105,114,46,97,114,103,95,116,121,112,101,95,115,105,122,101,97,105,114,46,97,114,103,95,116,121,112,101,95,97,108,105,103,110,95,115,105,122,101,117,80,117,115,104, + 67,111,110,115,116,97,110,116,112,99,0,0,0,166,119,0,0,0,0,0,0,48,130,144,4,35,8,74,51,130,144,8,35,8,201,48,130,144,16,35,8,73,49,130,144,24,35,8,201,49,130,144,32,35,8,73,50,130, + 144,40,35,8,201,50,130,112,0,51,12,106,16,172,193,12,3,27,8,109,48,195,224,6,131,26,204,48,184,1,241,6,51,12,110,80,188,193,12,131,27,24,111,48,195,224,6,7,28,204,48,184,1,18,7,51, + 12,110,144,200,193,12,129,50,195,160,6,115,64,7,51,16,75,29,176,1,29,204,16,48,51,4,205,12,129,51,131,241,64,145,52,81,51,24,79,21,89,211,53,67,129,69,210,148,205,48,152,194,41,160, + 194,12,9,29,104,27,29,176,65,100,77,220,12,9,27,104,27,27,176,65,100,77,221,12,137,26,104,155,26,176,65,36,77,222,12,10,29,196,1,29,88,100,16,7,113,64,7,86,25,204,64,213,193,7,6,114, + 176,209,1,27,132,129,24,168,193,24,180,130,25,200,193,25,196,65,132,6,83,26,204,64,168,194,42,176,130,43,204,48,216,65,42,188,194,157,1,192,113,28,199,113,28,199,113,28,199,185,129, + 27,184,129,27,184,129,27,184,129,27,184,129,69,7,122,96,89,22,29,208,129,27,208,1,46,224,2,46,240,3,122,128,130,140,4,38,40,35,54,54,187,54,151,182,55,178,58,182,50,23,51,182,176,179, + 185,81,18,59,184,3,60,200,3,61,216,3,62,232,3,63,72,133,141,205,174,205,37,141,172,204,141,110,148,224,15,114,9,75,147,115,177,43,147,155,75,123,115,27,37,0,133,164,194,210,228,92, + 216,194,220,206,234,194,206,202,190,236,202,228,230,210,222,220,70,9,66,33,167,176,52,57,151,177,183,54,184,52,182,178,175,55,56,186,180,55,183,185,81,6,81,24,5,82,72,37,44,77,206, + 197,174,76,142,174,12,111,148,224,21,0,0,0,169,24,0,0,37,0,0,0,11,10,114,40,135,119,128,7,122,88,112,152,67,61,184,195,56,176,67,57,208,195,130,230,28,198,161,13,232,65,30,194,193, + 29,230,33,29,232,33,29,222,193,29,22,52,227,96,14,231,80,15,225,32,15,228,64,15,225,32,15,231,80,14,244,176,128,129,7,121,40,135,112,96,7,118,120,135,113,8,7,122,40,7,114,88,112,156, + 195,56,180,1,59,164,131,61,148,195,2,107,28,216,33,28,220,225,28,220,32,28,228,97,28,220,32,28,232,129,30,194,97,28,208,161,28,200,97,28,194,129,29,216,97,193,1,15,244,32,15,225,80, + 15,244,128,14,0,0,0,0,209,16,0,0,6,0,0,0,7,204,60,164,131,59,156,3,59,148,3,61,160,131,60,148,67,56,144,195,1,0,0,0,97,32,0,0,68,0,0,0,19,4,65,44,16,0,0,0,11,0,0,0,148,51,0,180,37, + 64,61,7,161,72,146,52,7,161,72,9,65,48,26,48,2,48,70,0,130,32,136,127,20,115,16,150,117,97,36,163,1,52,51,0,0,0,0,0,241,48,0,0,32,0,0,0,34,71,200,144,81,18,196,43,0,0,0,0,207,115,89, + 0,111,109,110,105,112,111,116,101,110,116,32,99,104,97,114,83,105,109,112,108,101,32,67,43,43,32,84,66,65,65,97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,115,40,109,97,105, + 110,48,41,97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,45,97,114,103,40,51,41,0,19,132,133,89,33,216,194,44,172,24,110,193,22,104,97,67,32,11,27,134,88,192,133,90,216,48,228, + 66,46,212,194,134,224,22,0,0,157,134,5,146,40,16,130,1,36,254,157,6,103,234,40,16,130,67,0,254,131,12,1,226,12,50,4,138,51,134,48,68,22,128,255,28,195,16,76,179,13,204,5,204,54,4,89, + 48,219,16,12,194,6,1,49,0,4,0,0,0,91,138,32,200,133,67,23,182,20,68,144,11,135,46,0,0,0,0,0,0,113,32,0,0,3,0,0,0,50,14,16,34,132,0,134,6,0,0,0,0,0,0,0,0,101,12,0,0,31,0,0,0,18,3,148, + 240,0,0,0,0,3,0,0,0,5,0,0,0,9,0,0,0,76,0,0,0,1,0,0,0,88,0,0,0,0,0,0,0,88,0,0,0,1,0,0,0,112,0,0,0,0,0,0,0,14,0,0,0,24,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,112,0,0,0,0,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,255,255,255,255,0,36,0,0,0,0,0,0,93,12,0,0,13,0,0,0,18,3,148,102,0,0,0,0,109,97,105,110,48,51,50,48,50,51,46,51,54,56,97,105,114,54, + 52,45,97,112,112,108,101,45,109,97,99,111,115,120,49,52,46,48,46,48,0,0,0,0,0,0,0,0,0,0, +}; +const uint8_t metallib_fragment[3787] = { + 77,84,76,66,1,128,2,0,7,0,0,129,14,0,0,0,203,14,0,0,0,0,0,0,88,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,227,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,235,0,0,0,0,0,0,0, + 224,13,0,0,0,0,0,0,1,0,0,0,123,0,0,0,78,65,77,69,6,0,109,97,105,110,48,0,84,89,80,69,1,0,1,72,65,83,72,32,0,201,103,233,140,10,95,185,107,79,93,85,82,78,218,248,8,95,184,8,139,191, + 155,174,56,51,95,203,135,255,117,44,62,77,68,83,90,8,0,224,13,0,0,0,0,0,0,79,70,70,84,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,86,69,82,83,8,0,2,0,6,0,3,0,1,0,69,78,68, + 84,69,78,68,84,4,0,0,0,69,78,68,84,4,0,0,0,69,78,68,84,222,192,23,11,0,0,0,0,20,0,0,0,196,13,0,0,255,255,255,255,66,67,192,222,53,20,0,0,3,0,0,0,98,12,48,36,128,16,5,200,20,0,0,0,33, + 12,0,0,44,3,0,0,11,2,33,0,2,0,0,0,22,0,0,0,7,129,35,145,65,200,4,73,6,16,50,57,146,1,132,12,37,5,8,25,30,4,139,98,128,20,69,2,66,146,11,66,164,16,50,20,56,8,24,75,10,50,82,136,72,112, + 196,33,35,68,18,135,140,16,65,146,2,100,200,8,177,20,32,67,70,136,32,201,1,50,82,132,24,42,40,42,144,49,124,176,92,145,32,197,200,0,0,0,137,32,0,0,31,0,0,0,50,34,72,9,32,98,70,0,33, + 43,36,152,20,33,37,36,152,20,25,39,12,133,164,144,96,82,100,92,32,36,101,130,128,154,1,24,70,32,128,27,132,97,4,1,64,74,154,34,74,152,252,127,34,174,137,138,136,223,30,254,105,140, + 0,24,68,32,2,140,164,41,162,132,201,255,37,128,121,22,34,250,167,49,2,96,16,193,16,76,33,194,40,135,208,28,1,114,132,160,230,8,130,57,2,48,24,70,16,26,163,172,114,6,115,12,128,70,111, + 32,64,5,218,8,0,0,81,24,0,0,105,0,0,0,27,246,35,248,255,255,255,255,1,104,3,96,13,0,83,0,252,0,144,128,10,232,3,34,28,224,1,30,228,225,29,240,161,13,204,161,30,220,97,28,218,192,28, + 224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,128,48,7,121,8,135,118,40,135,54,128,135,119,72,7,119,160,135,114,144,7,32,28,216,129,29,0,162,29,210,193,29,218,128,29,202,225, + 28,194,129,29,218,192,30,202,97,28,232,225,29,228,161,13,238,33,29,200,129,30,208,1,136,3,57,192,3,96,112,135,119,104,3,113,168,135,116,96,7,122,72,7,119,152,7,128,112,135,119,104, + 131,116,112,7,115,152,135,54,48,7,120,104,131,118,8,7,122,64,7,128,30,228,161,30,202,1,32,220,225,29,218,192,29,194,193,29,230,161,13,204,1,30,218,160,29,194,129,30,208,1,160,7,121, + 168,135,114,0,8,119,120,135,54,152,135,116,56,7,119,40,7,114,104,3,125,40,7,121,120,135,121,104,3,115,128,135,54,104,135,112,160,7,116,0,232,65,30,234,161,28,0,194,29,222,161,13,232, + 65,30,194,1,30,224,33,29,220,225,28,218,160,29,194,129,30,208,1,160,7,121,168,135,114,0,136,121,160,135,112,24,135,117,104,3,120,144,135,119,160,135,114,24,7,122,120,7,121,104,3,113, + 168,7,115,48,135,114,144,135,54,152,135,116,208,135,114,0,240,0,32,234,193,29,230,33,28,204,161,28,218,192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,96,131,33,12,192, + 2,84,27,140,129,0,22,160,218,0,17,255,255,255,255,63,0,109,0,172,1,96,10,128,31,0,18,80,1,125,176,193,40,2,96,1,170,13,134,33,0,11,80,109,96,142,255,255,255,255,31,128,54,0,214,0,144, + 128,10,232,3,0,73,24,0,0,4,0,0,0,19,134,64,24,38,12,68,97,76,24,142,194,0,0,0,0,19,176,112,72,7,121,176,3,58,104,131,112,128,7,120,96,135,114,104,131,118,8,135,113,120,135,121,192, + 135,56,160,3,55,128,3,55,128,131,13,183,81,14,109,0,15,122,96,7,116,160,7,118,64,7,122,96,7,116,208,6,233,16,7,122,128,7,122,128,7,109,144,14,120,160,7,120,160,7,120,208,6,233,16,7, + 118,160,7,113,96,7,122,16,7,118,208,6,233,48,7,114,160,7,115,32,7,122,48,7,114,208,6,233,96,7,116,160,7,118,64,7,122,96,7,116,208,6,230,48,7,114,160,7,115,32,7,122,48,7,114,208,6,230, + 96,7,116,160,7,118,64,7,122,96,7,116,208,6,246,16,7,118,160,7,113,96,7,122,16,7,118,208,6,246,32,7,116,160,7,115,32,7,122,48,7,114,208,6,246,48,7,114,160,7,115,32,7,122,48,7,114,208, + 6,246,64,7,120,160,7,118,64,7,122,96,7,116,208,6,246,96,7,116,160,7,118,64,7,122,96,7,116,208,6,246,144,7,118,160,7,113,32,7,120,160,7,113,32,7,120,208,6,246,16,7,114,128,7,122,16, + 7,114,128,7,122,16,7,114,128,7,109,96,15,113,144,7,114,160,7,114,80,7,118,160,7,114,80,7,118,208,6,246,32,7,117,96,7,122,32,7,117,96,7,122,32,7,117,96,7,109,96,15,117,16,7,114,160, + 7,117,16,7,114,160,7,117,16,7,114,208,6,246,16,7,112,32,7,116,160,7,113,0,7,114,64,7,122,16,7,112,32,7,116,208,6,238,128,7,122,16,7,118,160,7,115,32,7,26,33,12,89,48,0,210,208,67,42, + 160,64,0,0,8,0,0,0,4,0,0,0,0,0,10,96,72,85,108,15,16,0,2,0,0,128,0,0,0,0,0,64,1,72,108,16,40,234,50,0,0,144,5,2,0,0,0,10,0,0,0,50,30,152,16,25,17,76,144,140,9,38,71,198,4,67,106,69, + 80,2,133,80,14,229,83,128,2,5,81,32,197,48,2,80,6,36,199,18,158,0,0,177,24,0,0,165,0,0,0,51,8,128,28,196,225,28,102,20,1,61,136,67,56,132,195,140,66,128,7,121,120,7,115,152,113,12, + 230,0,15,237,16,14,244,128,14,51,12,66,30,194,193,29,206,161,28,102,48,5,61,136,67,56,132,131,27,204,3,61,200,67,61,140,3,61,204,120,140,116,112,7,123,8,7,121,72,135,112,112,7,122, + 112,3,118,120,135,112,32,135,25,204,17,14,236,144,14,225,48,15,110,48,15,227,240,14,240,80,14,51,16,196,29,222,33,28,216,33,29,194,97,30,102,48,137,59,188,131,59,208,67,57,180,3,60, + 188,131,60,132,3,59,204,240,20,118,96,7,123,104,7,55,104,135,114,104,7,55,128,135,112,144,135,112,96,7,118,40,7,118,248,5,118,120,135,119,128,135,95,8,135,113,24,135,114,152,135,121, + 152,129,44,238,240,14,238,224,14,245,192,14,236,48,3,98,200,161,28,228,161,28,204,161,28,228,161,28,220,97,28,202,33,28,196,129,29,202,97,6,214,144,67,57,200,67,57,152,67,57,200,67, + 57,184,195,56,148,67,56,136,3,59,148,195,47,188,131,60,252,130,59,212,3,59,176,195,12,199,105,135,112,88,135,114,112,131,116,104,7,120,96,135,116,24,135,116,160,135,25,206,83,15,238, + 0,15,242,80,14,228,144,14,227,64,15,225,32,14,236,80,14,51,32,40,29,220,193,30,194,65,30,210,33,28,220,129,30,220,224,28,228,225,29,234,1,30,102,24,81,56,176,67,58,156,131,59,204,80, + 36,118,96,7,123,104,7,55,96,135,119,120,7,120,152,81,76,244,144,15,240,80,14,51,30,106,30,202,97,28,232,33,29,222,193,29,126,1,30,228,161,28,204,33,29,240,97,6,84,133,131,56,204,195, + 59,176,67,61,208,67,57,252,194,60,228,67,59,136,195,59,176,195,140,197,10,135,121,152,135,119,24,135,116,8,7,122,40,7,114,152,129,92,227,16,14,236,192,14,229,80,14,243,48,35,193,210, + 65,30,228,225,23,216,225,29,222,1,30,102,72,25,59,176,131,61,180,131,27,132,195,56,140,67,57,204,195,60,184,193,57,200,195,59,212,3,60,204,72,180,113,8,7,118,96,7,113,8,135,113,88, + 135,25,219,198,14,236,96,15,237,224,6,240,32,15,229,48,15,229,32,15,246,80,14,110,16,14,227,48,14,229,48,15,243,224,6,233,224,14,228,80,14,248,48,35,226,236,97,28,194,129,29,216,225, + 23,236,33,29,230,33,29,196,33,29,216,33,29,232,33,31,102,32,157,59,188,67,61,184,3,57,148,131,57,204,88,188,112,112,7,119,120,7,122,8,7,122,72,135,119,112,135,25,206,135,14,229,16, + 14,240,16,14,236,192,14,239,48,14,243,144,14,244,80,14,51,40,48,8,135,116,144,7,55,48,135,122,112,135,113,160,135,116,120,7,119,248,133,115,144,135,119,168,7,120,152,7,0,0,0,0,121, + 32,0,0,252,0,0,0,114,30,72,32,67,136,12,25,9,114,50,72,32,35,129,140,145,145,209,68,160,16,40,100,60,49,50,66,142,144,33,163,56,6,220,41,1,0,0,0,139,210,88,216,6,109,80,28,20,27,71, + 6,81,100,48,134,180,40,15,178,24,197,34,41,24,178,28,13,83,68,75,32,86,101,114,115,105,111,110,119,99,104,97,114,95,115,105,122,101,102,114,97,109,101,45,112,111,105,110,116,101,114, + 97,105,114,46,109,97,120,95,100,101,118,105,99,101,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,99,111,110,115,116,97,110,116,95,98,117,102,102,101,114,115,97,105,114, + 46,109,97,120,95,116,104,114,101,97,100,103,114,111,117,112,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,114, + 101,97,100,95,119,114,105,116,101,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,115,97,109,112,108,101,114,115,65,112,112,108,101,32,109,101,116,97,108,32,118,101, + 114,115,105,111,110,32,51,50,48,50,51,46,51,54,56,32,40,109,101,116,97,108,102,101,45,51,50,48,50,51,46,51,54,56,41,77,101,116,97,108,97,105,114,46,99,111,109,112,105,108,101,46,100, + 101,110,111,114,109,115,95,100,105,115,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,97,115,116,95,109,97,116,104,95,101,110,97,98,108,101,97,105,114,46,99,111,109, + 112,105,108,101,46,102,114,97,109,101,98,117,102,102,101,114,95,102,101,116,99,104,95,101,110,97,98,108,101,97,105,114,46,114,101,110,100,101,114,95,116,97,114,103,101,116,97,105,114, + 46,97,114,103,95,116,121,112,101,95,110,97,109,101,102,108,111,97,116,52,97,105,114,46,97,114,103,95,110,97,109,101,102,67,111,108,111,114,97,105,114,46,102,114,97,103,109,101,110, + 116,95,105,110,112,117,116,117,115,101,114,40,108,111,99,110,48,41,97,105,114,46,99,101,110,116,101,114,97,105,114,46,112,101,114,115,112,101,99,116,105,118,101,73,110,95,67,111,108, + 111,114,117,115,101,114,40,108,111,99,110,49,41,102,108,111,97,116,50,73,110,95,85,86,97,105,114,46,116,101,120,116,117,114,101,97,105,114,46,108,111,99,97,116,105,111,110,95,105,110, + 100,101,120,97,105,114,46,115,97,109,112,108,101,116,101,120,116,117,114,101,50,100,60,102,108,111,97,116,44,32,115,97,109,112,108,101,62,115,84,101,120,116,117,114,101,97,105,114, + 46,115,97,109,112,108,101,114,115,97,109,112,108,101,114,115,84,101,120,116,117,114,101,83,109,112,108,114,0,198,96,0,0,0,0,0,0,48,130,208,8,35,8,82,51,130,208,12,35,8,13,49,130,208, + 20,35,8,141,49,130,208,28,35,8,13,50,130,208,36,35,8,141,50,130,208,44,35,8,13,51,130,144,0,51,12,100,16,148,193,12,131,25,8,103,48,195,128,6,3,25,204,48,160,1,145,6,51,12,104,80,164, + 193,12,3,26,24,105,48,195,128,6,135,26,204,48,160,1,178,6,51,12,104,144,176,193,12,129,50,195,64,6,109,224,6,51,16,203,27,152,129,27,204,16,48,51,4,205,12,129,51,195,241,184,129,27, + 64,145,52,205,16,128,194,12,137,27,80,149,117,65,145,132,205,144,152,1,149,89,23,164,73,219,12,10,25,112,157,27,152,129,7,125,18,24,204,144,188,65,24,116,110,96,6,144,24,72,99,48,3, + 33,10,163,64,10,165,48,195,0,7,161,96,10,71,6,0,199,113,28,199,113,28,199,113,28,231,6,110,224,6,110,224,6,110,224,6,110,224,6,22,29,232,129,101,89,166,192,177,2,43,144,131,58,128, + 130,140,4,38,40,35,54,54,187,54,151,182,55,178,58,182,50,23,51,182,176,179,185,81,18,56,136,3,57,152,3,58,168,3,59,184,3,60,72,133,141,205,174,205,37,141,172,204,141,110,148,32,15, + 114,9,75,147,115,177,43,147,155,75,123,115,27,37,208,131,164,194,210,228,92,216,194,220,206,234,194,206,202,190,236,202,228,230,210,222,220,70,9,246,32,167,176,52,57,151,177,183,54, + 184,52,182,178,175,55,56,186,180,55,183,185,81,6,62,232,3,63,72,38,44,77,206,197,76,46,236,172,173,204,141,110,148,192,20,0,0,0,0,169,24,0,0,37,0,0,0,11,10,114,40,135,119,128,7,122, + 88,112,152,67,61,184,195,56,176,67,57,208,195,130,230,28,198,161,13,232,65,30,194,193,29,230,33,29,232,33,29,222,193,29,22,52,227,96,14,231,80,15,225,32,15,228,64,15,225,32,15,231, + 80,14,244,176,128,129,7,121,40,135,112,96,7,118,120,135,113,8,7,122,40,7,114,88,112,156,195,56,180,1,59,164,131,61,148,195,2,107,28,216,33,28,220,225,28,220,32,28,228,97,28,220,32, + 28,232,129,30,194,97,28,208,161,28,200,97,28,194,129,29,216,97,193,1,15,244,32,15,225,80,15,244,128,14,0,0,0,0,209,16,0,0,6,0,0,0,7,204,60,164,131,59,156,3,59,148,3,61,160,131,60,148, + 67,56,144,195,1,0,0,0,97,32,0,0,49,0,0,0,19,4,65,44,16,0,0,0,4,0,0,0,196,106,96,4,128,220,8,0,129,17,0,18,51,0,0,0,241,48,0,0,28,0,0,0,34,71,200,144,81,14,196,42,0,0,0,0,23,134,1,0, + 97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,115,40,109,97,105,110,48,41,97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,45,115,97,109,112,108,101,114,115,97,105,114, + 45,97,108,105,97,115,45,115,99,111,112,101,45,116,101,120,116,117,114,101,115,0,43,132,85,64,133,21,3,43,172,66,42,172,24,90,97,21,84,97,131,208,10,172,0,0,35,6,205,16,130,96,240,88, + 135,129,20,3,33,8,204,104,66,0,96,176,136,255,108,3,17,0,27,4,196,0,0,0,2,0,0,0,91,6,224,104,5,0,0,0,0,0,0,0,113,32,0,0,3,0,0,0,50,14,16,34,132,0,251,5,0,0,0,0,0,0,0,0,101,12,0,0,37, + 0,0,0,18,3,148,40,1,0,0,0,3,0,0,0,32,0,0,0,9,0,0,0,76,0,0,0,1,0,0,0,88,0,0,0,0,0,0,0,88,0,0,0,2,0,0,0,136,0,0,0,0,0,0,0,41,0,0,0,24,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,136,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,255,255,255,255,0,36,0,0,5,0,0,0,27,0,0,0,5,0,0,0,27,0,0,0,255,255,255,255,8,36,0,0,0,0,0,0,93,12,0,0,20,0,0,0,18,3, + 148,161,0,0,0,0,109,97,105,110,48,97,105,114,46,115,97,109,112,108,101,95,116,101,120,116,117,114,101,95,50,100,46,118,52,102,51,50,51,50,48,50,51,46,51,54,56,97,105,114,54,52,45,97, + 112,112,108,101,45,109,97,99,111,115,120,49,52,46,48,46,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; +#elif TARGET_OS_IPHONE +const uint8_t metallib_vertex[3876] = { + 77,84,76,66,1,0,2,0,7,0,0,130,18,0,1,0,36,15,0,0,0,0,0,0,88,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,49,0,0,0,0,0,0,0,12,1,0,0,0,0,0,0,8,0,0,0,0,0,0,0,20,1,0,0,0,0,0,0,16, + 14,0,0,0,0,0,0,1,0,0,0,123,0,0,0,78,65,77,69,6,0,109,97,105,110,48,0,84,89,80,69,1,0,0,72,65,83,72,32,0,240,54,230,217,232,66,102,78,35,5,77,235,101,252,229,192,148,96,126,162,111, + 77,253,247,211,52,17,198,182,137,68,244,77,68,83,90,8,0,16,14,0,0,0,0,0,0,79,70,70,84,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,86,69,82,83,8,0,2,0,7,0,3,0,2,0,69,78,68, + 84,69,78,68,84,45,0,0,0,86,65,84,84,24,0,3,0,97,80,111,115,0,0,128,97,85,86,0,1,128,97,67,111,108,111,114,0,2,128,86,65,84,89,5,0,3,0,4,4,6,69,78,68,84,4,0,0,0,69,78,68,84,222,192, + 23,11,0,0,0,0,20,0,0,0,252,13,0,0,255,255,255,255,66,67,192,222,53,20,0,0,3,0,0,0,98,12,48,36,128,16,5,200,20,0,0,0,33,12,0,0,72,3,0,0,11,2,33,0,2,0,0,0,22,0,0,0,7,129,35,145,65,200, + 4,73,6,16,50,57,146,1,132,12,37,5,8,25,30,4,139,98,128,16,69,2,66,146,11,66,132,16,50,20,56,8,24,75,10,50,66,136,72,112,196,33,35,68,18,135,140,16,65,146,2,100,200,8,177,20,32,67,70, + 136,32,201,1,50,66,132,24,42,40,42,144,49,124,176,92,145,32,196,200,0,0,0,137,32,0,0,24,0,0,0,50,34,8,9,32,98,70,0,33,43,36,152,16,33,37,36,152,16,25,39,12,133,164,144,96,66,100,92, + 32,36,100,130,224,153,1,24,70,32,128,97,4,1,184,67,72,32,37,77,17,37,76,62,149,82,210,193,57,141,52,1,205,148,4,145,65,4,66,48,197,136,68,145,13,4,204,17,128,129,10,228,28,1,40,12, + 34,8,194,48,2,145,140,0,0,0,0,0,81,24,0,0,100,0,0,0,27,246,35,248,255,255,255,255,1,48,5,192,15,0,56,0,254,0,144,0,10,232,3,34,28,224,1,30,228,225,29,240,161,13,204,161,30,220,97,28, + 218,192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,128,48,7,121,8,135,118,40,135,54,128,135,119,72,7,119,160,135,114,144,7,32,28,216,129,29,0,162,29,210,193,29,218,128, + 29,202,225,28,194,129,29,218,192,30,202,97,28,232,225,29,228,161,13,238,33,29,200,129,30,208,1,136,3,57,192,3,96,112,135,119,104,3,113,168,135,116,96,7,122,72,7,119,152,7,128,112,135, + 119,104,131,116,112,7,115,152,135,54,48,7,120,104,131,118,8,7,122,64,7,128,30,228,161,30,202,1,32,220,225,29,218,192,29,194,193,29,230,161,13,204,1,30,218,160,29,194,129,30,208,1,160, + 7,121,168,135,114,0,8,119,120,135,54,152,135,116,56,7,119,40,7,114,104,3,125,40,7,121,120,135,121,104,3,115,128,135,54,104,135,112,160,7,116,0,232,65,30,234,161,28,0,194,29,222,161, + 13,232,65,30,194,1,30,224,33,29,220,225,28,218,160,29,194,129,30,208,1,160,7,121,168,135,114,0,136,121,160,135,112,24,135,117,104,3,120,144,135,119,160,135,114,24,7,122,120,7,121,104, + 3,113,168,7,115,48,135,114,144,135,54,152,135,116,208,135,114,0,240,0,32,234,193,29,230,33,28,204,161,28,218,192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,96,195,24,8, + 4,176,0,164,0,84,65,128,4,105,0,13,225,144,14,242,208,6,226,80,15,230,96,14,229,32,15,109,224,14,239,208,6,225,192,14,233,16,14,243,0,0,0,73,24,0,0,1,0,0,0,19,132,64,0,19,170,112,72, + 7,121,176,3,58,104,131,112,128,7,120,96,135,114,104,131,116,120,135,121,136,3,60,112,131,56,112,3,56,216,112,27,229,208,6,240,160,7,118,64,7,122,96,7,116,160,7,118,64,7,109,144,14, + 113,160,7,120,160,7,120,208,6,233,128,7,122,128,7,122,128,7,109,144,14,113,96,7,122,16,7,118,160,7,113,96,7,109,144,14,115,32,7,122,48,7,114,160,7,115,32,7,109,144,14,118,64,7,122, + 96,7,116,160,7,118,64,7,109,96,14,115,32,7,122,48,7,114,160,7,115,32,7,109,96,14,118,64,7,122,96,7,116,160,7,118,64,7,109,96,15,113,96,7,122,16,7,118,160,7,113,96,7,109,96,15,114,64, + 7,122,48,7,114,160,7,115,32,7,109,96,15,115,32,7,122,48,7,114,160,7,115,32,7,109,96,15,116,128,7,122,96,7,116,160,7,118,64,7,109,96,15,118,64,7,122,96,7,116,160,7,118,64,7,109,96,15, + 121,96,7,122,16,7,114,128,7,122,16,7,114,128,7,109,96,15,113,32,7,120,160,7,113,32,7,120,160,7,113,32,7,120,208,6,246,16,7,121,32,7,122,32,7,117,96,7,122,32,7,117,96,7,109,96,15,114, + 80,7,118,160,7,114,80,7,118,160,7,114,80,7,118,208,6,246,80,7,113,32,7,122,80,7,113,32,7,122,80,7,113,32,7,109,96,15,113,0,7,114,64,7,122,16,7,112,32,7,116,160,7,113,0,7,114,64,7,109, + 224,14,120,160,7,113,96,7,122,48,7,114,160,17,194,144,5,3,32,13,61,164,2,10,3,0,128,0,0,0,64,0,0,0,0,0,160,0,36,54,8,20,85,26,0,0,200,2,1,0,11,0,0,0,50,30,152,16,25,17,76,144,140,9, + 38,71,198,4,67,202,34,40,129,66,40,135,242,41,64,129,130,40,144,17,128,50,160,29,1,32,29,75,144,2,0,0,0,0,177,24,0,0,165,0,0,0,51,8,128,28,196,225,28,102,20,1,61,136,67,56,132,195, + 140,66,128,7,121,120,7,115,152,113,12,230,0,15,237,16,14,244,128,14,51,12,66,30,194,193,29,206,161,28,102,48,5,61,136,67,56,132,131,27,204,3,61,200,67,61,140,3,61,204,120,140,116,112, + 7,123,8,7,121,72,135,112,112,7,122,112,3,118,120,135,112,32,135,25,204,17,14,236,144,14,225,48,15,110,48,15,227,240,14,240,80,14,51,16,196,29,222,33,28,216,33,29,194,97,30,102,48,137, + 59,188,131,59,208,67,57,180,3,60,188,131,60,132,3,59,204,240,20,118,96,7,123,104,7,55,104,135,114,104,7,55,128,135,112,144,135,112,96,7,118,40,7,118,248,5,118,120,135,119,128,135,95, + 8,135,113,24,135,114,152,135,121,152,129,44,238,240,14,238,224,14,245,192,14,236,48,3,98,200,161,28,228,161,28,204,161,28,228,161,28,220,97,28,202,33,28,196,129,29,202,97,6,214,144, + 67,57,200,67,57,152,67,57,200,67,57,184,195,56,148,67,56,136,3,59,148,195,47,188,131,60,252,130,59,212,3,59,176,195,12,199,105,135,112,88,135,114,112,131,116,104,7,120,96,135,116,24, + 135,116,160,135,25,206,83,15,238,0,15,242,80,14,228,144,14,227,64,15,225,32,14,236,80,14,51,32,40,29,220,193,30,194,65,30,210,33,28,220,129,30,220,224,28,228,225,29,234,1,30,102,24, + 81,56,176,67,58,156,131,59,204,80,36,118,96,7,123,104,7,55,96,135,119,120,7,120,152,81,76,244,144,15,240,80,14,51,30,106,30,202,97,28,232,33,29,222,193,29,126,1,30,228,161,28,204,33, + 29,240,97,6,84,133,131,56,204,195,59,176,67,61,208,67,57,252,194,60,228,67,59,136,195,59,176,195,140,197,10,135,121,152,135,119,24,135,116,8,7,122,40,7,114,152,129,92,227,16,14,236, + 192,14,229,80,14,243,48,35,193,210,65,30,228,225,23,216,225,29,222,1,30,102,72,25,59,176,131,61,180,131,27,132,195,56,140,67,57,204,195,60,184,193,57,200,195,59,212,3,60,204,72,180, + 113,8,7,118,96,7,113,8,135,113,88,135,25,219,198,14,236,96,15,237,224,6,240,32,15,229,48,15,229,32,15,246,80,14,110,16,14,227,48,14,229,48,15,243,224,6,233,224,14,228,80,14,248,48, + 35,226,236,97,28,194,129,29,216,225,23,236,33,29,230,33,29,196,33,29,216,33,29,232,33,31,102,32,157,59,188,67,61,184,3,57,148,131,57,204,88,188,112,112,7,119,120,7,122,8,7,122,72,135, + 119,112,135,25,206,135,14,229,16,14,240,16,14,236,192,14,239,48,14,243,144,14,244,80,14,51,40,48,8,135,116,144,7,55,48,135,122,112,135,113,160,135,116,120,7,119,248,133,115,144,135, + 119,168,7,120,152,7,0,0,0,0,121,32,0,0,25,1,0,0,114,30,72,32,67,136,12,25,9,114,50,72,32,35,129,140,145,145,209,68,160,16,40,100,60,49,50,66,142,144,33,163,152,6,100,208,82,0,0,0,139, + 210,88,216,6,109,80,28,20,27,71,6,209,18,25,76,178,24,6,179,64,18,49,24,202,131,68,148,161,68,87,35,0,0,0,0,83,68,75,32,86,101,114,115,105,111,110,119,99,104,97,114,95,115,105,122, + 101,102,114,97,109,101,45,112,111,105,110,116,101,114,97,105,114,46,109,97,120,95,100,101,118,105,99,101,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,99,111,110,115,116, + 97,110,116,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,104,114,101,97,100,103,114,111,117,112,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,101,120, + 116,117,114,101,115,97,105,114,46,109,97,120,95,114,101,97,100,95,119,114,105,116,101,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,115,97,109,112,108,101,114,115, + 65,112,112,108,101,32,109,101,116,97,108,32,118,101,114,115,105,111,110,32,51,50,48,50,51,46,51,54,56,32,40,109,101,116,97,108,102,101,45,51,50,48,50,51,46,51,54,56,41,77,101,116,97, + 108,97,105,114,46,99,111,109,112,105,108,101,46,100,101,110,111,114,109,115,95,100,105,115,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,97,115,116,95,109,97,116,104, + 95,101,110,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,114,97,109,101,98,117,102,102,101,114,95,102,101,116,99,104,95,101,110,97,98,108,101,97,105,114,46,118,101, + 114,116,101,120,95,111,117,116,112,117,116,117,115,101,114,40,108,111,99,110,48,41,97,105,114,46,97,114,103,95,116,121,112,101,95,110,97,109,101,102,108,111,97,116,52,97,105,114,46, + 97,114,103,95,110,97,109,101,79,117,116,95,67,111,108,111,114,117,115,101,114,40,108,111,99,110,49,41,102,108,111,97,116,50,79,117,116,95,85,86,97,105,114,46,112,111,115,105,116,105, + 111,110,103,108,95,80,111,115,105,116,105,111,110,97,105,114,46,118,101,114,116,101,120,95,105,110,112,117,116,97,105,114,46,108,111,99,97,116,105,111,110,95,105,110,100,101,120,97, + 80,111,115,97,85,86,97,67,111,108,111,114,97,105,114,46,98,117,102,102,101,114,97,105,114,46,98,117,102,102,101,114,95,115,105,122,101,97,105,114,46,114,101,97,100,97,105,114,46,97, + 100,100,114,101,115,115,95,115,112,97,99,101,97,105,114,46,115,116,114,117,99,116,95,116,121,112,101,95,105,110,102,111,117,83,99,97,108,101,117,84,114,97,110,115,108,97,116,101,97, + 105,114,46,97,114,103,95,116,121,112,101,95,115,105,122,101,97,105,114,46,97,114,103,95,116,121,112,101,95,97,108,105,103,110,95,115,105,122,101,117,80,117,115,104,67,111,110,115,116, + 97,110,116,112,99,0,0,0,230,117,0,0,0,0,0,0,48,130,144,4,35,8,10,51,130,144,8,35,8,201,48,130,144,16,35,8,73,49,130,144,24,35,8,201,49,130,144,32,35,8,73,50,130,144,40,35,8,7,48,195, + 160,6,193,26,204,48,176,129,208,6,51,12,110,48,168,193,12,131,27,16,111,48,195,224,6,197,27,204,48,184,129,241,6,51,12,110,112,192,193,12,131,27,32,113,48,195,224,6,137,28,204,16,40, + 51,12,106,224,6,115,48,3,177,208,129,26,204,193,12,1,51,67,208,204,16,56,51,24,15,20,73,19,53,131,241,84,145,53,93,51,20,88,36,77,217,12,67,41,152,194,41,204,144,204,129,182,205,1, + 27,68,214,196,205,144,176,129,182,177,1,27,68,214,212,205,144,168,129,182,169,1,27,68,210,228,205,160,204,65,28,204,129,69,6,113,16,7,115,96,149,193,12,20,29,124,96,32,7,219,28,176, + 65,24,136,129,26,140,1,43,152,129,28,156,65,28,68,104,48,165,193,12,68,42,168,194,42,180,194,12,67,29,160,130,43,156,25,0,28,199,113,28,199,113,28,199,113,110,224,6,110,224,6,110,224, + 6,110,224,6,110,96,209,129,30,88,150,69,7,116,224,6,116,128,11,184,128,11,252,128,30,160,32,35,129,9,202,136,141,205,174,205,165,237,141,172,142,173,204,197,140,45,236,108,110,148, + 164,14,236,224,14,240,32,15,244,96,15,248,160,15,82,97,99,179,107,115,73,35,43,115,163,27,37,240,131,92,194,210,228,92,236,202,228,230,210,222,220,70,9,254,32,169,176,52,57,23,182, + 48,183,179,186,176,179,178,47,187,50,185,185,180,55,183,81,2,80,200,41,44,77,206,101,236,173,13,46,141,173,236,235,13,142,46,237,205,109,110,148,33,20,68,97,20,82,9,75,147,115,177, + 43,147,163,43,195,27,37,112,5,0,0,0,169,24,0,0,37,0,0,0,11,10,114,40,135,119,128,7,122,88,112,152,67,61,184,195,56,176,67,57,208,195,130,230,28,198,161,13,232,65,30,194,193,29,230, + 33,29,232,33,29,222,193,29,22,52,227,96,14,231,80,15,225,32,15,228,64,15,225,32,15,231,80,14,244,176,128,129,7,121,40,135,112,96,7,118,120,135,113,8,7,122,40,7,114,88,112,156,195,56, + 180,1,59,164,131,61,148,195,2,107,28,216,33,28,220,225,28,220,32,28,228,97,28,220,32,28,232,129,30,194,97,28,208,161,28,200,97,28,194,129,29,216,97,193,1,15,244,32,15,225,80,15,244, + 128,14,0,0,0,0,209,16,0,0,6,0,0,0,7,204,60,164,131,59,156,3,59,148,3,61,160,131,60,148,67,56,144,195,1,0,0,0,97,32,0,0,68,0,0,0,19,4,65,44,16,0,0,0,11,0,0,0,148,51,0,197,64,91,2,212, + 115,16,73,20,69,115,16,73,36,17,4,163,1,35,0,99,4,32,8,130,248,71,49,7,97,89,23,70,50,26,64,51,3,0,0,0,241,48,0,0,32,0,0,0,34,71,200,144,81,18,196,43,0,0,0,0,207,115,89,0,111,109,110, + 105,112,111,116,101,110,116,32,99,104,97,114,83,105,109,112,108,101,32,67,43,43,32,84,66,65,65,97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,115,40,109,97,105,110,48,41,97, + 105,114,45,97,108,105,97,115,45,115,99,111,112,101,45,97,114,103,40,51,41,0,19,132,101,89,33,212,130,44,172,24,108,161,22,102,97,67,16,11,27,6,88,184,5,90,216,48,224,2,46,208,194,134, + 192,22,0,0,157,6,38,154,40,16,130,65,36,254,157,134,135,234,40,16,130,67,0,254,131,12,1,226,12,50,4,138,51,134,48,68,22,128,255,28,195,16,76,179,13,12,6,204,54,4,90,48,219,16,12,194, + 6,1,49,0,4,0,0,0,91,138,32,192,133,35,23,182,20,68,128,11,71,46,0,0,0,0,0,0,113,32,0,0,3,0,0,0,50,14,16,34,132,0,132,6,0,0,0,0,0,0,0,0,101,12,0,0,31,0,0,0,18,3,148,240,0,0,0,0,3,0, + 0,0,5,0,0,0,9,0,0,0,76,0,0,0,1,0,0,0,88,0,0,0,0,0,0,0,88,0,0,0,1,0,0,0,112,0,0,0,0,0,0,0,14,0,0,0,21,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,112,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, + 0,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,255,255,255,255,0,36,0,0,0,0,0,0,93,12,0,0,12,0,0,0,18,3,148,99,0,0,0,0,109,97,105,110,48,51,50,48,50,51,46,51,54,56,97,105,114,54,52,45,97,112,112, + 108,101,45,105,111,115,49,56,46,49,46,48,0,0,0,0,0, +}; +const uint8_t metallib_fragment[3771] = { + 77,84,76,66,1,0,2,0,7,0,0,130,18,0,1,0,187,14,0,0,0,0,0,0,88,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,227,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,235,0,0,0,0,0,0,0,208, + 13,0,0,0,0,0,0,1,0,0,0,123,0,0,0,78,65,77,69,6,0,109,97,105,110,48,0,84,89,80,69,1,0,1,72,65,83,72,32,0,167,26,51,31,140,153,203,226,66,149,243,47,185,58,96,202,28,176,71,121,86,159, + 244,234,235,69,155,58,121,67,241,212,77,68,83,90,8,0,208,13,0,0,0,0,0,0,79,70,70,84,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,86,69,82,83,8,0,2,0,7,0,3,0,2,0,69,78,68,84, + 69,78,68,84,4,0,0,0,69,78,68,84,4,0,0,0,69,78,68,84,222,192,23,11,0,0,0,0,20,0,0,0,180,13,0,0,255,255,255,255,66,67,192,222,53,20,0,0,3,0,0,0,98,12,48,36,128,16,5,200,20,0,0,0,33,12, + 0,0,41,3,0,0,11,2,33,0,2,0,0,0,22,0,0,0,7,129,35,145,65,200,4,73,6,16,50,57,146,1,132,12,37,5,8,25,30,4,139,98,128,20,69,2,66,146,11,66,164,16,50,20,56,8,24,75,10,50,82,136,72,112, + 196,33,35,68,18,135,140,16,65,146,2,100,200,8,177,20,32,67,70,136,32,201,1,50,82,132,24,42,40,42,144,49,124,176,92,145,32,197,200,0,0,0,137,32,0,0,31,0,0,0,50,34,72,9,32,98,70,0,33, + 43,36,152,20,33,37,36,152,20,25,39,12,133,164,144,96,82,100,92,32,36,101,130,128,154,1,24,70,32,128,27,132,97,4,1,64,74,154,34,74,152,252,127,34,174,137,138,136,223,30,254,105,140, + 0,24,68,32,2,140,164,41,162,132,201,255,37,128,121,22,34,250,167,49,2,96,16,193,16,76,33,194,40,135,208,28,1,114,132,160,230,8,130,57,2,48,24,70,16,26,163,172,114,6,115,12,128,70,111, + 32,64,5,218,8,0,0,81,24,0,0,105,0,0,0,27,246,35,248,255,255,255,255,1,104,3,96,13,0,83,0,252,0,144,128,10,232,3,34,28,224,1,30,228,225,29,240,161,13,204,161,30,220,97,28,218,192,28, + 224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,128,48,7,121,8,135,118,40,135,54,128,135,119,72,7,119,160,135,114,144,7,32,28,216,129,29,0,162,29,210,193,29,218,128,29,202,225, + 28,194,129,29,218,192,30,202,97,28,232,225,29,228,161,13,238,33,29,200,129,30,208,1,136,3,57,192,3,96,112,135,119,104,3,113,168,135,116,96,7,122,72,7,119,152,7,128,112,135,119,104, + 131,116,112,7,115,152,135,54,48,7,120,104,131,118,8,7,122,64,7,128,30,228,161,30,202,1,32,220,225,29,218,192,29,194,193,29,230,161,13,204,1,30,218,160,29,194,129,30,208,1,160,7,121, + 168,135,114,0,8,119,120,135,54,152,135,116,56,7,119,40,7,114,104,3,125,40,7,121,120,135,121,104,3,115,128,135,54,104,135,112,160,7,116,0,232,65,30,234,161,28,0,194,29,222,161,13,232, + 65,30,194,1,30,224,33,29,220,225,28,218,160,29,194,129,30,208,1,160,7,121,168,135,114,0,136,121,160,135,112,24,135,117,104,3,120,144,135,119,160,135,114,24,7,122,120,7,121,104,3,113, + 168,7,115,48,135,114,144,135,54,152,135,116,208,135,114,0,240,0,32,234,193,29,230,33,28,204,161,28,218,192,28,224,161,13,218,33,28,232,1,29,0,122,144,135,122,40,7,96,131,33,12,192, + 2,84,27,140,129,0,22,160,218,0,17,255,255,255,255,63,0,109,0,172,1,96,10,128,31,0,18,80,1,125,176,193,40,2,96,1,170,13,134,33,0,11,80,109,96,142,255,255,255,255,31,128,54,0,214,0,144, + 128,10,232,3,0,73,24,0,0,4,0,0,0,19,134,64,24,38,12,68,97,76,24,142,194,0,0,0,0,19,170,112,72,7,121,176,3,58,104,131,112,128,7,120,96,135,114,104,131,116,120,135,121,136,3,60,112,131, + 56,112,3,56,216,112,27,229,208,6,240,160,7,118,64,7,122,96,7,116,160,7,118,64,7,109,144,14,113,160,7,120,160,7,120,208,6,233,128,7,122,128,7,122,128,7,109,144,14,113,96,7,122,16,7, + 118,160,7,113,96,7,109,144,14,115,32,7,122,48,7,114,160,7,115,32,7,109,144,14,118,64,7,122,96,7,116,160,7,118,64,7,109,96,14,115,32,7,122,48,7,114,160,7,115,32,7,109,96,14,118,64,7, + 122,96,7,116,160,7,118,64,7,109,96,15,113,96,7,122,16,7,118,160,7,113,96,7,109,96,15,114,64,7,122,48,7,114,160,7,115,32,7,109,96,15,115,32,7,122,48,7,114,160,7,115,32,7,109,96,15,116, + 128,7,122,96,7,116,160,7,118,64,7,109,96,15,118,64,7,122,96,7,116,160,7,118,64,7,109,96,15,121,96,7,122,16,7,114,128,7,122,16,7,114,128,7,109,96,15,113,32,7,120,160,7,113,32,7,120, + 160,7,113,32,7,120,208,6,246,16,7,121,32,7,122,32,7,117,96,7,122,32,7,117,96,7,109,96,15,114,80,7,118,160,7,114,80,7,118,160,7,114,80,7,118,208,6,246,80,7,113,32,7,122,80,7,113,32, + 7,122,80,7,113,32,7,109,96,15,113,0,7,114,64,7,122,16,7,112,32,7,116,160,7,113,0,7,114,64,7,109,224,14,120,160,7,113,96,7,122,48,7,114,160,17,194,144,5,3,32,13,61,164,2,10,4,0,128, + 0,0,0,64,0,0,0,0,0,160,0,134,84,197,246,0,1,32,0,0,0,8,0,0,0,0,0,20,128,196,6,129,162,43,3,0,0,89,32,10,0,0,0,50,30,152,16,25,17,76,144,140,9,38,71,198,4,67,106,69,80,2,133,80,14,229, + 83,128,2,5,81,32,35,0,101,64,114,44,65,10,0,0,0,177,24,0,0,165,0,0,0,51,8,128,28,196,225,28,102,20,1,61,136,67,56,132,195,140,66,128,7,121,120,7,115,152,113,12,230,0,15,237,16,14,244, + 128,14,51,12,66,30,194,193,29,206,161,28,102,48,5,61,136,67,56,132,131,27,204,3,61,200,67,61,140,3,61,204,120,140,116,112,7,123,8,7,121,72,135,112,112,7,122,112,3,118,120,135,112,32, + 135,25,204,17,14,236,144,14,225,48,15,110,48,15,227,240,14,240,80,14,51,16,196,29,222,33,28,216,33,29,194,97,30,102,48,137,59,188,131,59,208,67,57,180,3,60,188,131,60,132,3,59,204, + 240,20,118,96,7,123,104,7,55,104,135,114,104,7,55,128,135,112,144,135,112,96,7,118,40,7,118,248,5,118,120,135,119,128,135,95,8,135,113,24,135,114,152,135,121,152,129,44,238,240,14, + 238,224,14,245,192,14,236,48,3,98,200,161,28,228,161,28,204,161,28,228,161,28,220,97,28,202,33,28,196,129,29,202,97,6,214,144,67,57,200,67,57,152,67,57,200,67,57,184,195,56,148,67, + 56,136,3,59,148,195,47,188,131,60,252,130,59,212,3,59,176,195,12,199,105,135,112,88,135,114,112,131,116,104,7,120,96,135,116,24,135,116,160,135,25,206,83,15,238,0,15,242,80,14,228, + 144,14,227,64,15,225,32,14,236,80,14,51,32,40,29,220,193,30,194,65,30,210,33,28,220,129,30,220,224,28,228,225,29,234,1,30,102,24,81,56,176,67,58,156,131,59,204,80,36,118,96,7,123,104, + 7,55,96,135,119,120,7,120,152,81,76,244,144,15,240,80,14,51,30,106,30,202,97,28,232,33,29,222,193,29,126,1,30,228,161,28,204,33,29,240,97,6,84,133,131,56,204,195,59,176,67,61,208,67, + 57,252,194,60,228,67,59,136,195,59,176,195,140,197,10,135,121,152,135,119,24,135,116,8,7,122,40,7,114,152,129,92,227,16,14,236,192,14,229,80,14,243,48,35,193,210,65,30,228,225,23,216, + 225,29,222,1,30,102,72,25,59,176,131,61,180,131,27,132,195,56,140,67,57,204,195,60,184,193,57,200,195,59,212,3,60,204,72,180,113,8,7,118,96,7,113,8,135,113,88,135,25,219,198,14,236, + 96,15,237,224,6,240,32,15,229,48,15,229,32,15,246,80,14,110,16,14,227,48,14,229,48,15,243,224,6,233,224,14,228,80,14,248,48,35,226,236,97,28,194,129,29,216,225,23,236,33,29,230,33, + 29,196,33,29,216,33,29,232,33,31,102,32,157,59,188,67,61,184,3,57,148,131,57,204,88,188,112,112,7,119,120,7,122,8,7,122,72,135,119,112,135,25,206,135,14,229,16,14,240,16,14,236,192, + 14,239,48,14,243,144,14,244,80,14,51,40,48,8,135,116,144,7,55,48,135,122,112,135,113,160,135,116,120,7,119,248,133,115,144,135,119,168,7,120,152,7,0,0,0,0,121,32,0,0,251,0,0,0,114, + 30,72,32,67,136,12,25,9,114,50,72,32,35,129,140,145,145,209,68,160,16,40,100,60,49,50,66,142,144,33,163,56,6,220,41,1,0,0,0,139,210,88,216,6,109,80,28,20,27,71,6,81,100,48,134,180, + 40,15,178,24,197,34,41,24,178,28,13,83,68,75,32,86,101,114,115,105,111,110,119,99,104,97,114,95,115,105,122,101,102,114,97,109,101,45,112,111,105,110,116,101,114,97,105,114,46,109, + 97,120,95,100,101,118,105,99,101,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,99,111,110,115,116,97,110,116,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116, + 104,114,101,97,100,103,114,111,117,112,95,98,117,102,102,101,114,115,97,105,114,46,109,97,120,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,114,101,97,100,95,119,114, + 105,116,101,95,116,101,120,116,117,114,101,115,97,105,114,46,109,97,120,95,115,97,109,112,108,101,114,115,65,112,112,108,101,32,109,101,116,97,108,32,118,101,114,115,105,111,110,32, + 51,50,48,50,51,46,51,54,56,32,40,109,101,116,97,108,102,101,45,51,50,48,50,51,46,51,54,56,41,77,101,116,97,108,97,105,114,46,99,111,109,112,105,108,101,46,100,101,110,111,114,109,115, + 95,100,105,115,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,97,115,116,95,109,97,116,104,95,101,110,97,98,108,101,97,105,114,46,99,111,109,112,105,108,101,46,102,114, + 97,109,101,98,117,102,102,101,114,95,102,101,116,99,104,95,101,110,97,98,108,101,97,105,114,46,114,101,110,100,101,114,95,116,97,114,103,101,116,97,105,114,46,97,114,103,95,116,121, + 112,101,95,110,97,109,101,102,108,111,97,116,52,97,105,114,46,97,114,103,95,110,97,109,101,102,67,111,108,111,114,97,105,114,46,102,114,97,103,109,101,110,116,95,105,110,112,117,116, + 117,115,101,114,40,108,111,99,110,48,41,97,105,114,46,99,101,110,116,101,114,97,105,114,46,112,101,114,115,112,101,99,116,105,118,101,73,110,95,67,111,108,111,114,117,115,101,114,40, + 108,111,99,110,49,41,102,108,111,97,116,50,73,110,95,85,86,97,105,114,46,116,101,120,116,117,114,101,97,105,114,46,108,111,99,97,116,105,111,110,95,105,110,100,101,120,97,105,114,46, + 115,97,109,112,108,101,116,101,120,116,117,114,101,50,100,60,102,108,111,97,116,44,32,115,97,109,112,108,101,62,115,84,101,120,116,117,114,101,97,105,114,46,115,97,109,112,108,101, + 114,115,97,109,112,108,101,114,115,84,101,120,116,117,114,101,83,109,112,108,114,0,6,95,0,0,0,0,0,0,48,130,208,8,35,8,18,51,130,208,12,35,8,13,49,130,208,20,35,8,141,49,130,208,28, + 35,8,13,50,130,208,36,35,8,141,50,130,208,44,35,8,9,48,195,64,6,65,25,204,48,152,129,112,6,51,12,104,48,144,193,12,3,26,16,105,48,195,128,6,69,26,204,48,160,129,145,6,51,12,104,112, + 168,193,12,3,26,32,107,48,195,128,6,9,27,204,16,40,51,12,100,128,6,109,48,3,177,184,1,25,180,193,12,1,51,67,208,204,16,56,51,28,79,27,180,1,20,73,211,12,193,31,204,144,180,1,85,89, + 23,20,73,216,12,137,25,80,153,117,65,154,180,205,160,144,1,215,181,129,25,120,208,39,129,193,12,137,27,132,65,215,6,102,0,137,129,52,6,51,16,161,32,10,163,64,10,51,12,111,0,10,165, + 112,99,0,112,28,199,113,28,199,113,28,199,185,129,27,184,129,27,184,129,27,184,129,27,184,129,69,7,122,96,89,150,41,112,172,192,10,228,160,14,160,32,35,129,9,202,136,141,205,174,205, + 165,237,141,172,142,173,204,197,140,45,236,108,110,148,228,13,224,32,14,228,96,14,232,160,14,236,224,14,82,97,99,179,107,115,73,35,43,115,163,27,37,192,131,92,194,210,228,92,236,202, + 228,230,210,222,220,70,9,242,32,169,176,52,57,23,182,48,183,179,186,176,179,178,47,187,50,185,185,180,55,183,81,2,61,200,41,44,77,206,101,236,173,13,46,141,173,236,235,13,142,46,237, + 205,109,110,148,97,15,248,160,15,146,9,75,147,115,49,147,11,59,107,43,115,163,27,37,40,5,0,0,0,0,169,24,0,0,37,0,0,0,11,10,114,40,135,119,128,7,122,88,112,152,67,61,184,195,56,176, + 67,57,208,195,130,230,28,198,161,13,232,65,30,194,193,29,230,33,29,232,33,29,222,193,29,22,52,227,96,14,231,80,15,225,32,15,228,64,15,225,32,15,231,80,14,244,176,128,129,7,121,40,135, + 112,96,7,118,120,135,113,8,7,122,40,7,114,88,112,156,195,56,180,1,59,164,131,61,148,195,2,107,28,216,33,28,220,225,28,220,32,28,228,97,28,220,32,28,232,129,30,194,97,28,208,161,28, + 200,97,28,194,129,29,216,97,193,1,15,244,32,15,225,80,15,244,128,14,0,0,0,0,209,16,0,0,6,0,0,0,7,204,60,164,131,59,156,3,59,148,3,61,160,131,60,148,67,56,144,195,1,0,0,0,97,32,0,0, + 49,0,0,0,19,4,65,44,16,0,0,0,4,0,0,0,196,106,96,4,128,220,8,0,129,17,0,18,51,0,0,0,241,48,0,0,28,0,0,0,34,71,200,144,81,14,196,42,0,0,0,0,23,134,1,0,97,105,114,45,97,108,105,97,115, + 45,115,99,111,112,101,115,40,109,97,105,110,48,41,97,105,114,45,97,108,105,97,115,45,115,99,111,112,101,45,115,97,109,112,108,101,114,115,97,105,114,45,97,108,105,97,115,45,115,99, + 111,112,101,45,116,101,120,116,117,114,101,115,0,43,4,85,56,133,21,195,42,168,2,42,172,24,88,65,21,82,97,131,192,10,171,0,0,35,6,205,16,130,96,240,84,135,129,20,3,33,8,204,104,66,0, + 96,176,136,255,108,3,17,0,27,4,196,0,0,0,2,0,0,0,91,6,224,96,5,0,0,0,0,0,0,0,113,32,0,0,3,0,0,0,50,14,16,34,132,0,248,5,0,0,0,0,0,0,0,0,101,12,0,0,37,0,0,0,18,3,148,40,1,0,0,0,3,0, + 0,0,32,0,0,0,9,0,0,0,76,0,0,0,1,0,0,0,88,0,0,0,0,0,0,0,88,0,0,0,2,0,0,0,136,0,0,0,0,0,0,0,41,0,0,0,21,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,136,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0, + 0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,255,255,255,255,0,36,0,0,5,0,0,0,27,0,0,0,5,0,0,0,27,0,0,0,255,255,255,255,8,36,0,0,0,0,0,0,93,12,0,0,19,0,0,0,18,3,148,126,0,0,0,0,109,97,105,110, + 48,97,105,114,46,115,97,109,112,108,101,95,116,101,120,116,117,114,101,95,50,100,46,118,52,102,51,50,51,50,48,50,51,46,51,54,56,97,105,114,54,52,45,97,112,112,108,101,45,105,111,115, + 49,56,46,49,46,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; +#elif TARGET_IPHONE_SIMULATOR +#error "SDL_GPU does not support the iphone simulator" +#endif +#endif + +#endif // #ifndef IMGUI_DISABLE diff --git a/backends/sdlgpu3/build_instructions.txt b/backends/sdlgpu3/build_instructions.txt new file mode 100644 index 000000000000..751dc97a4e0b --- /dev/null +++ b/backends/sdlgpu3/build_instructions.txt @@ -0,0 +1,36 @@ +1) Compile the raw shader files to SPIRV: + + glslc -o vertex.spv -c shader.vert + glslc -o fragment.spv -c shader.frag + + +2) Build SDL_shadercross (https://github.com/libsdl-org/SDL_shadercross) + + +3-A) Compiling for the Vulkan Driver: + + Nothing to do, you just need the previous vertex.spv/fragment.spv, proceed to step 4 + + +3-B) Compiling for the DirectX 12 Driver: + + ./shadercross vertex.spv -s SPIRV -d DXBC -t vertex -e main -o vertex.dxbc + ./shadercross fragment.spv -s SPIRV -d DXBC -t fragment -e main -o fragment.dxbc + + Proceed to step 4 + + +3-C) Compiling for Metal (On windows you'll need the Metal Developer Tools for Windows, on linux you might use wine, but I never tested it): + + ./shadercross vertex.spv -s SPIRV -d MSL -t vertex -e main -o vertex.metal + ./shadercross fragment.spv -s SPIRV -d MSL -t fragment -e main -o fragment.metal + + xcrun -sdk macosx metal -o vertex.ir -c vertex.metal + xcrun -sdk macosx metal -o fragment.ir -c fragment.metal + xcrun -sdk macosx metallib -o vertex.metallib -c vertex.ir + xcrun -sdk macosx metallib -o fragment.metallib -c fragment.ir + + Proceed to step 4 + + +4) Either find a way to load the shader bytecode from file, or use a tool like https://notisrac.github.io/FileToCArray/ to convert the file to a uint8_t array \ No newline at end of file diff --git a/backends/sdlgpu3/shader.frag b/backends/sdlgpu3/shader.frag new file mode 100644 index 000000000000..2de1f76a3b23 --- /dev/null +++ b/backends/sdlgpu3/shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0) out vec4 fColor; + +layout(set=2, binding=0) uniform sampler2D sTexture; + +layout(location = 0) in struct { + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} \ No newline at end of file diff --git a/backends/sdlgpu3/shader.vert b/backends/sdlgpu3/shader.vert new file mode 100644 index 000000000000..3363da8b2a7b --- /dev/null +++ b/backends/sdlgpu3/shader.vert @@ -0,0 +1,22 @@ +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; + +layout(set=1,binding=0) uniform UBO { + vec2 uScale; + vec2 uTranslate; +} ubo; + +layout(location = 0) out struct { + vec4 Color; + vec2 UV; +} Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos * ubo.uScale + ubo.uTranslate, 0, 1); + gl_Position.y *= -1.0f; +} \ No newline at end of file diff --git a/examples/example_sdl3_sdlgpu3/Makefile b/examples/example_sdl3_sdlgpu3/Makefile new file mode 100644 index 000000000000..f6239e0fa845 --- /dev/null +++ b/examples/example_sdl3_sdlgpu3/Makefile @@ -0,0 +1,73 @@ +# +# Cross Platform Makefile +# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X +# +# You will need SDL3 (http://www.libsdl.org) which is still unreleased/unpackaged. + +#CXX = g++ +#CXX = clang++ + +EXE = example_sdl3_sdlgpu3 +IMGUI_DIR = ../.. +SOURCES = main.cpp +SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp +SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_sdlgpu3.cpp +OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) +UNAME_S := $(shell uname -s) + +CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends +CXXFLAGS += -g -Wall -Wformat +LIBS = + + +##--------------------------------------------------------------------- +## BUILD FLAGS PER PLATFORM +##--------------------------------------------------------------------- + +ifeq ($(UNAME_S), Linux) #LINUX + ECHO_MESSAGE = "Linux" + LIBS += -ldl `pkg-config sdl3 --libs` + + CXXFLAGS += `pkg-config sdl3 --cflags` + CFLAGS = $(CXXFLAGS) +endif + +ifeq ($(UNAME_S), Darwin) #APPLE + ECHO_MESSAGE = "Mac OS X" + LIBS += -framework Cocoa -framework IOKit -framework CoreVideo `pkg-config --libs sdl3` + LIBS += -L/usr/local/lib -L/opt/local/lib + + CXXFLAGS += `pkg-config sdl3 --cflags` + CXXFLAGS += -I/usr/local/include -I/opt/local/include + CFLAGS = $(CXXFLAGS) +endif + +ifeq ($(OS), Windows_NT) + ECHO_MESSAGE = "MinGW" + LIBS += -lgdi32 -limm32 `pkg-config --static --libs sdl3` + + CXXFLAGS += `pkg-config --cflags sdl3` + CFLAGS = $(CXXFLAGS) +endif + +##--------------------------------------------------------------------- +## BUILD RULES +##--------------------------------------------------------------------- + +%.o:%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:$(IMGUI_DIR)/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:$(IMGUI_DIR)/backends/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +all: $(EXE) + @echo Build complete for $(ECHO_MESSAGE) + +$(EXE): $(OBJS) + $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) + +clean: + rm -f $(EXE) $(OBJS) diff --git a/examples/example_sdl3_sdlgpu3/build_win64.bat b/examples/example_sdl3_sdlgpu3/build_win64.bat new file mode 100644 index 000000000000..ad7a2d603ae7 --- /dev/null +++ b/examples/example_sdl3_sdlgpu3/build_win64.bat @@ -0,0 +1,14 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars64.bat or vcvarsall.bat to setup command-line compiler. + +@set OUT_EXE=example_sdl3_sdlgpu3 +@set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include +@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_sdlgpu3.cpp ..\..\imgui*.cpp +@set LIBS=/LIBPATH:%SDL3_DIR%\lib\x64 SDL3.lib shell32.lib + +@set OUT_DIR=Debug +mkdir %OUT_DIR% +cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console + +@set OUT_DIR=Release +@REM mkdir %OUT_DIR% +@REM cl /nologo /Zi /MD /utf-8 /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console diff --git a/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj b/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj new file mode 100644 index 000000000000..3d034f52c0a5 --- /dev/null +++ b/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj @@ -0,0 +1,189 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {c22cb6f8-39a5-4dda-90ed-4aca4e81e1e5} + example_sdl3_sdlgpu3 + 8.1 + + + + Application + true + MultiByte + v140 + + + Application + true + MultiByte + v140 + + + Application + false + true + MultiByte + v140 + + + Application + false + true + MultiByte + v140 + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + + Level4 + Disabled + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories) + _MBCS;%(PreprocessorDefinitions) + /utf-8 %(AdditionalOptions) + + + true + %SDL3_DIR%\lib\x86;%(AdditionalLibraryDirectories) + SDL3.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + Disabled + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories) + _MBCS;%(PreprocessorDefinitions) + /utf-8 %(AdditionalOptions) + + + true + %SDL3_DIR%\lib\x64;%(AdditionalLibraryDirectories) + SDL3.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + MaxSpeed + true + true + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories) + false + _MBCS;%(PreprocessorDefinitions) + /utf-8 %(AdditionalOptions) + + + true + true + true + %SDL3_DIR%\lib\x86;%(AdditionalLibraryDirectories) + SDL3.lib;%(AdditionalDependencies) + Console + + + + + + + Level4 + MaxSpeed + true + true + ..\..;..\..\backends;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories) + false + _MBCS;%(PreprocessorDefinitions) + /utf-8 %(AdditionalOptions) + + + true + true + true + %SDL3_DIR%\lib\x64;%(AdditionalLibraryDirectories) + SDL3.lib;%(AdditionalDependencies) + Console + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj.filters b/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj.filters new file mode 100644 index 000000000000..4710b550cc0f --- /dev/null +++ b/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj.filters @@ -0,0 +1,60 @@ + + + + + sources + + + sources + + + sources + + + imgui + + + imgui + + + imgui + + + imgui + + + imgui + + + + + sources + + + sources + + + sources + + + imgui + + + imgui + + + imgui + + + + + + + + {9044ef92-2afa-42f2-92df-ac473c7c32b3} + + + {ef84458b-039a-4902-8455-4e33df5a8578} + + + \ No newline at end of file diff --git a/examples/example_sdl3_sdlgpu3/main.cpp b/examples/example_sdl3_sdlgpu3/main.cpp new file mode 100644 index 000000000000..6c29962dd0b8 --- /dev/null +++ b/examples/example_sdl3_sdlgpu3/main.cpp @@ -0,0 +1,210 @@ +// Dear ImGui: standalone example application for SDL_Gpu + +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). +// - Introduction, links and more at the top of imgui.cpp + +// Important note to the reader who wish to integrate imgui_impl_sdlgpu3.cpp/.h in their own engine/app. +// - Unline other backends, the user must call the function Imgui_ImplSDLGPU_PrepareDrawData BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData. +// Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info. + +#include "imgui.h" +#include "imgui_impl_sdl3.h" +#include "imgui_impl_sdlgpu3.h" +#include // printf, fprintf +#include // abort +#include + + +// This example doesn't compile with Emscripten yet! Awaiting SDL3 support. +#ifdef __EMSCRIPTEN__ +#include "../libs/emscripten/emscripten_mainloop_stub.h" +#endif + +// Main code +int main(int, char**) +{ + // Setup SDL + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD) != 0) + { + printf("Error: SDL_Init(): %s\n", SDL_GetError()); + return -1; + } + + // Create SDL window graphics context + SDL_Window* window = SDL_CreateWindow("Dear ImGui SDLGpu example", 1280, 720, SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return -1; + } + + // Create SDL Gpu Device + SDL_GPUDevice* gpuDevice = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_METALLIB,true,nullptr); + if (gpuDevice == nullptr) + { + printf("Error: SDL_CreateGPUDevice(): %s\n", SDL_GetError()); + return -1; + } + + // Claim window for GPU Device + if (!SDL_ClaimWindowForGPUDevice(gpuDevice, window)) + { + printf("Error: SDL_ClaimWindowForGPUDevice(): %s\n", SDL_GetError()); + return -1; + } + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + // Setup Platform/Renderer backends + ImGui_ImplSDL3_InitForOther(window); + ImGui_ImplSDLGPU_InitInfo init_info = {}; + init_info.GpuDevice = gpuDevice; + init_info.ColorTargetFormat = SDL_GetGPUSwapchainTextureFormat(gpuDevice, window); + init_info.MSAASamples = SDL_GPU_SAMPLECOUNT_1; + ImGui_ImplSDLGPU_Init(&init_info); + + // Load Fonts + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering. + // - Read 'docs/FONTS.md' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != nullptr); + + // Our state + bool show_demo_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + // Main loop + bool done = false; + while (!done) + { + // Poll and handle events (inputs, window resize, etc.) + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - 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. + SDL_Event event; + while (SDL_PollEvent(&event)) + { + ImGui_ImplSDL3_ProcessEvent(&event); + if (event.type == SDL_EVENT_QUIT) + done = true; + 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_ImplSDLGPU_NewFrame(); + ImGui_ImplSDL3_NewFrame(); + ImGui::NewFrame(); + + // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). + if (show_demo_window) + ImGui::ShowDemoWindow(&show_demo_window); + + // 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window. + { + static float f = 0.0f; + static int counter = 0; + + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::End(); + } + + // 3. Show another simple window. + if (show_another_window) + { + ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked) + ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; + ImGui::End(); + } + + // Rendering + ImGui::Render(); + ImDrawData* draw_data = ImGui::GetDrawData(); + const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f); + + // Acquire a GPU command buffer + SDL_GPUCommandBuffer* command_buffer = SDL_AcquireGPUCommandBuffer(gpuDevice); + + //Acquire a swapchain texture + SDL_GPUTexture* swapchain_texture; + SDL_AcquireGPUSwapchainTexture(command_buffer, window, &swapchain_texture, nullptr, nullptr); + + if (swapchain_texture != nullptr && !is_minimized) + { + // !!! THIS IS MANDATORY !!! + // Call Imgui_ImplSDLGPU_PrepareDrawData to upload the vertex/index buffer + Imgui_ImplSDLGPU_PrepareDrawData(draw_data, command_buffer); + + // Setup and start a render pass + SDL_GPUColorTargetInfo target_info = {}; + target_info.texture = swapchain_texture; + target_info.clear_color = SDL_FColor{ clear_color.x,clear_color.y,clear_color.z,clear_color.w }; + target_info.load_op = SDL_GPU_LOADOP_CLEAR; + target_info.store_op = SDL_GPU_STOREOP_STORE; + target_info.mip_level = 0; + target_info.layer_or_depth_plane = 0; + target_info.cycle = false; + SDL_GPURenderPass* render_pass = SDL_BeginGPURenderPass(command_buffer, &target_info, 1, nullptr); + /// Render ImGui + ImGui_ImplSDLGPU_RenderDrawData(draw_data, command_buffer, render_pass); + SDL_EndGPURenderPass(render_pass); + } + // Submit the command buffer + SDL_SubmitGPUCommandBuffer(command_buffer); + } + // Cleanup + SDL_WaitForGPUIdle(gpuDevice); + ImGui_ImplSDL3_Shutdown(); + ImGui_ImplSDLGPU_Shutdown(); + ImGui::DestroyContext(); + SDL_ReleaseWindowFromGPUDevice(gpuDevice, window); + SDL_DestroyGPUDevice(gpuDevice); + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; +} diff --git a/examples/imgui_examples.sln b/examples/imgui_examples.sln index 85f7451d4f61..cf1c5ad50f63 100644 --- a/examples/imgui_examples.sln +++ b/examples/imgui_examples.sln @@ -37,6 +37,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_vulkan", "exam EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_vulkan", "example_win32_vulkan\example_win32_vulkan.vcxproj", "{0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_sdlgpu3", "example_sdl3_sdlgpu3\example_sdl3_sdlgpu3.vcxproj", "{C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -181,6 +183,14 @@ Global {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Release|Win32.Build.0 = Release|Win32 {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Release|x64.ActiveCfg = Release|x64 {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}.Release|x64.Build.0 = Release|x64 + {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Debug|Win32.ActiveCfg = Debug|Win32 + {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Debug|Win32.Build.0 = Debug|Win32 + {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Debug|x64.ActiveCfg = Debug|x64 + {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Debug|x64.Build.0 = Debug|x64 + {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Release|Win32.ActiveCfg = Release|Win32 + {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Release|Win32.Build.0 = Release|Win32 + {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Release|x64.ActiveCfg = Release|x64 + {C22CB6F8-39A5-4DDA-90ED-4ACA4E81E1E5}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From e79984927266f9b44302b2b43e70cf674513cffd Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 9 Jan 2025 16:08:14 +0100 Subject: [PATCH 358/548] Backends: SDLGPU3: Added sdl_gpu backend (amends). (#8163, #7998, #7988) --- backends/imgui_impl_sdlgpu3.cpp | 301 ++++++++++++------------ backends/imgui_impl_sdlgpu3.h | 18 +- backends/sdlgpu3/build_instructions.txt | 6 +- backends/sdlgpu3/shader.frag | 5 +- backends/sdlgpu3/shader.vert | 8 +- backends/vulkan/build_instructions.txt | 4 + docs/CHANGELOG.txt | 1 + docs/EXAMPLES.md | 24 +- docs/README.md | 2 +- examples/example_sdl3_sdlgpu3/main.cpp | 53 +++-- 10 files changed, 221 insertions(+), 201 deletions(-) create mode 100644 backends/vulkan/build_instructions.txt diff --git a/backends/imgui_impl_sdlgpu3.cpp b/backends/imgui_impl_sdlgpu3.cpp index 31e899b77d92..e681efdc39ab 100644 --- a/backends/imgui_impl_sdlgpu3.cpp +++ b/backends/imgui_impl_sdlgpu3.cpp @@ -1,4 +1,4 @@ -// dear imgui: Renderer Backend for SDL_Gpu +// dear imgui: Renderer Backend for SDL_GPU // This needs to be used along with the SDL3 Platform Backend // Implemented features: @@ -17,19 +17,19 @@ // - Introduction, links and more at the top of imgui.cpp // Important note to the reader who wish to integrate imgui_impl_sdlgpu3.cpp/.h in their own engine/app. -// - Unline other backends, the user must call the function Imgui_ImplSDLGPU_PrepareDrawData BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData. +// - Unlike other backends, the user must call the function Imgui_ImplSDLGPU3_PrepareDrawData() BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU3_RenderDrawData. // Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info. // CHANGELOG -// 2024-11-18: SDL_Gpu: Added the SDL_Gpu backend. +// 2025-01-09: SDL_Gpu: Added the SDL_GPU3 backend. #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_impl_sdlgpu3.h" #include "imgui_impl_sdlgpu3_shaders.h" -// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplSDLGPU_RenderDrawData() -struct ImGui_ImplSDLGPU_FrameData +// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplSDLGPU3_RenderDrawData() +struct ImGui_ImplSDLGPU3_FrameData { SDL_GPUBuffer* VertexBuffer = nullptr; SDL_GPUBuffer* IndexBuffer = nullptr; @@ -37,10 +37,10 @@ struct ImGui_ImplSDLGPU_FrameData uint32_t IndexBufferSize = 0; }; -// SDL_Gpu Data -struct ImGui_ImplSDLGPU_Data +// SDL_GPU Data +struct ImGui_ImplSDLGPU3_Data { - ImGui_ImplSDLGPU_InitInfo GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo GPUInitInfo; // Graphics pipeline & shaders SDL_GPUShader* VertexShader = nullptr; @@ -50,16 +50,16 @@ struct ImGui_ImplSDLGPU_Data // Font data SDL_GPUSampler* FontSampler = nullptr; SDL_GPUTexture* FontTexture = nullptr; - SDL_GPUTextureSamplerBinding FontBinding = {nullptr,nullptr}; + SDL_GPUTextureSamplerBinding FontBinding = { nullptr, nullptr }; // Frame data for main window - ImGui_ImplSDLGPU_FrameData MainWindowFrameData; + ImGui_ImplSDLGPU3_FrameData MainWindowFrameData; }; // Forward Declarations -static bool ImGui_ImplSDLGPU_CreateDeviceObjects(); -static void ImGui_ImplSDLGPU_DestroyDeviceObjects(); -static void ImGui_ImplSDLGPU_DestroyFrameData(); +static bool ImGui_ImplSDLGPU3_CreateDeviceObjects(); +static void ImGui_ImplSDLGPU3_DestroyDeviceObjects(); +static void ImGui_ImplSDLGPU3_DestroyFrameData(); //----------------------------------------------------------------------------- // FUNCTIONS @@ -68,38 +68,19 @@ static void ImGui_ImplSDLGPU_DestroyFrameData(); // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. // FIXME: multi-context support has never been tested. -static ImGui_ImplSDLGPU_Data* ImGui_ImplSDLGPU_GetBackendData() +static ImGui_ImplSDLGPU3_Data* ImGui_ImplSDLGPU3_GetBackendData() { - return ImGui::GetCurrentContext() ? (ImGui_ImplSDLGPU_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; + return ImGui::GetCurrentContext() ? (ImGui_ImplSDLGPU3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; } -static void CreateOrResizeBuffer(SDL_GPUBuffer** buffer,uint32_t* old_size, uint32_t new_size,SDL_GPUBufferUsageFlags usage) +static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass * render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height) { - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + //ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - SDL_WaitForGPUIdle(v->GpuDevice); - SDL_ReleaseGPUBuffer(v->GpuDevice, *buffer); - - SDL_GPUBufferCreateInfo buffer_info = {}; - buffer_info.usage = usage; - buffer_info.size = new_size; - buffer_info.props = 0; - *buffer = SDL_CreateGPUBuffer(v->GpuDevice,&buffer_info); - *old_size = new_size; - IM_ASSERT(*buffer != nullptr && "Failed to create GPU Buffer, call SDL_GetError() for more information"); -} - -static void ImGui_ImplSDLGPU_SetupRenderState(ImDrawData* draw_data,SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer,SDL_GPURenderPass * render_pass, ImGui_ImplSDLGPU_FrameData* fd, uint32_t fb_width, uint32_t fb_height) -{ - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - - // Bind graphics pipeline: - { - SDL_BindGPUGraphicsPipeline(render_pass,pipeline); - } + // Bind graphics pipeline + SDL_BindGPUGraphicsPipeline(render_pass,pipeline); - // Bind Vertex And Index Buffers: + // Bind Vertex And Index Buffers if (draw_data->TotalVtxCount > 0) { SDL_GPUBufferBinding vertex_buffer_binding = {}; @@ -112,56 +93,66 @@ static void ImGui_ImplSDLGPU_SetupRenderState(ImDrawData* draw_data,SDL_GPUGraph SDL_BindGPUIndexBuffer(render_pass,&index_buffer_binding,sizeof(ImDrawIdx) == 2 ? SDL_GPU_INDEXELEMENTSIZE_16BIT : SDL_GPU_INDEXELEMENTSIZE_32BIT); } - // Setup viewport: - { - SDL_GPUViewport viewport = {}; - viewport.x = 0; - viewport.y = 0; - viewport.w = fb_width; - viewport.h = fb_height; - viewport.min_depth = 0.0f; - viewport.min_depth = 1.0f; - SDL_SetGPUViewport(render_pass,&viewport); - } - - // Setup scale and translation: + // Setup viewport + SDL_GPUViewport viewport = {}; + viewport.x = 0; + viewport.y = 0; + viewport.w = (float)fb_width; + viewport.h = (float)fb_height; + viewport.min_depth = 0.0f; + viewport.min_depth = 1.0f; + SDL_SetGPUViewport(render_pass,&viewport); + + // Setup scale and translation // Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. - { - struct UBO{ - float scale[2]; - float translation[2]; - } ubo; - ubo.scale[0] = 2.0f / draw_data->DisplaySize.x; - ubo.scale[1] = 2.0f / draw_data->DisplaySize.y; - ubo.translation[0] = -1.0f - draw_data->DisplayPos.x * ubo.scale[0]; - ubo.translation[1] = -1.0f - draw_data->DisplayPos.y * ubo.scale[1]; - SDL_PushGPUVertexUniformData(command_buffer,0,&ubo,sizeof(UBO)); - } + struct UBO { float scale[2]; float translation[2]; } ubo; + ubo.scale[0] = 2.0f / draw_data->DisplaySize.x; + ubo.scale[1] = 2.0f / draw_data->DisplaySize.y; + ubo.translation[0] = -1.0f - draw_data->DisplayPos.x * ubo.scale[0]; + ubo.translation[1] = -1.0f - draw_data->DisplayPos.y * ubo.scale[1]; + SDL_PushGPUVertexUniformData(command_buffer, 0, &ubo, sizeof(UBO)); } -// SDL_GPU doesn't allow copy passes to occur while a render or compute pass is bound +static void CreateOrResizeBuffer(SDL_GPUBuffer** buffer, uint32_t* old_size, uint32_t new_size, SDL_GPUBufferUsageFlags usage) +{ + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + + SDL_WaitForGPUIdle(v->GpuDevice); + SDL_ReleaseGPUBuffer(v->GpuDevice, *buffer); + + SDL_GPUBufferCreateInfo buffer_info = {}; + buffer_info.usage = usage; + buffer_info.size = new_size; + buffer_info.props = 0; + *buffer = SDL_CreateGPUBuffer(v->GpuDevice, &buffer_info); + *old_size = new_size; + IM_ASSERT(*buffer != nullptr && "Failed to create GPU Buffer, call SDL_GetError() for more information"); +} + +// SDL_GPU doesn't allow copy passes to occur while a render or compute pass is bound! // The only way to allow a user to supply their own RenderPass (to render to a texture instead of the window for example), -// is to split the upload part of ImGui_ImplSDLGPU_RenderDrawData to another function that needs to be called by the user before rendering -void Imgui_ImplSDLGPU_PrepareDrawData(ImDrawData* draw_data,SDL_GPUCommandBuffer* command_buffer) +// is to split the upload part of ImGui_ImplSDLGPU3_RenderDrawData() to another function that needs to be called by the user before rendering. +void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); - if(fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount <= 0) + if (fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount <= 0) return; - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; - ImGui_ImplSDLGPU_FrameData* fd = &bd->MainWindowFrameData; + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_FrameData* fd = &bd->MainWindowFrameData; uint32_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); uint32_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); - - if(fd->VertexBuffer == nullptr || fd->VertexBufferSize < vertex_size) - CreateOrResizeBuffer(&fd->VertexBuffer,&fd->VertexBufferSize,vertex_size, SDL_GPU_BUFFERUSAGE_VERTEX); + if (fd->VertexBuffer == nullptr || fd->VertexBufferSize < vertex_size) + CreateOrResizeBuffer(&fd->VertexBuffer, &fd->VertexBufferSize, vertex_size, SDL_GPU_BUFFERUSAGE_VERTEX); if (fd->IndexBuffer == nullptr || fd->IndexBufferSize < index_size) - CreateOrResizeBuffer(&fd->IndexBuffer,&fd->IndexBufferSize,index_size, SDL_GPU_BUFFERUSAGE_INDEX); + CreateOrResizeBuffer(&fd->IndexBuffer, &fd->IndexBufferSize, index_size, SDL_GPU_BUFFERUSAGE_INDEX); + // FIXME: It feels like more code could be shared there. SDL_GPUTransferBufferCreateInfo vertex_transferbuffer_info = {}; vertex_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; vertex_transferbuffer_info.size = vertex_size; @@ -169,22 +160,23 @@ void Imgui_ImplSDLGPU_PrepareDrawData(ImDrawData* draw_data,SDL_GPUCommandBuffer index_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; index_transferbuffer_info.size = index_size; - SDL_GPUTransferBuffer* vertex_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice,&vertex_transferbuffer_info); + SDL_GPUTransferBuffer* vertex_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice, &vertex_transferbuffer_info); IM_ASSERT(vertex_transferbuffer != nullptr && "Failed to create the vertex transfer buffer, call SDL_GetError() for more information"); - SDL_GPUTransferBuffer* index_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice,&index_transferbuffer_info); + SDL_GPUTransferBuffer* index_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice, &index_transferbuffer_info); IM_ASSERT(index_transferbuffer != nullptr && "Failed to create the index transfer buffer, call SDL_GetError() for more information"); - ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer(v->GpuDevice,vertex_transferbuffer,true); - ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer(v->GpuDevice,index_transferbuffer,true); - for(int n = 0; n < draw_data->CmdListsCount; n++){ + ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer(v->GpuDevice, vertex_transferbuffer, true); + ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer(v->GpuDevice, index_transferbuffer, true); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { const ImDrawList* draw_list = draw_data->CmdLists[n]; memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert)); memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx)); vtx_dst += draw_list->VtxBuffer.Size; idx_dst += draw_list->IdxBuffer.Size; } - SDL_UnmapGPUTransferBuffer(v->GpuDevice,vertex_transferbuffer); - SDL_UnmapGPUTransferBuffer(v->GpuDevice,index_transferbuffer); + SDL_UnmapGPUTransferBuffer(v->GpuDevice, vertex_transferbuffer); + SDL_UnmapGPUTransferBuffer(v->GpuDevice, index_transferbuffer); SDL_GPUTransferBufferLocation vertex_buffer_location = {}; vertex_buffer_location.offset = 0; @@ -197,34 +189,35 @@ void Imgui_ImplSDLGPU_PrepareDrawData(ImDrawData* draw_data,SDL_GPUCommandBuffer vertex_buffer_region.buffer = fd->VertexBuffer; vertex_buffer_region.offset = 0; vertex_buffer_region.size = vertex_size; + SDL_GPUBufferRegion index_buffer_region = {}; index_buffer_region.buffer = fd->IndexBuffer; index_buffer_region.offset = 0; index_buffer_region.size = index_size; SDL_GPUCopyPass* copy_pass = SDL_BeginGPUCopyPass(command_buffer); - SDL_UploadToGPUBuffer(copy_pass,&vertex_buffer_location,&vertex_buffer_region,true); - SDL_UploadToGPUBuffer(copy_pass,&index_buffer_location,&index_buffer_region,true); + SDL_UploadToGPUBuffer(copy_pass, &vertex_buffer_location, &vertex_buffer_region,true); + SDL_UploadToGPUBuffer(copy_pass, &index_buffer_location, &index_buffer_region,true); SDL_EndGPUCopyPass(copy_pass); SDL_ReleaseGPUTransferBuffer(v->GpuDevice, index_transferbuffer); SDL_ReleaseGPUTransferBuffer(v->GpuDevice, vertex_transferbuffer); } -void ImGui_ImplSDLGPU_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline) +void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); - if(fb_width <= 0 || fb_height <= 0) + if (fb_width <= 0 || fb_height <= 0) return; - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - ImGui_ImplSDLGPU_FrameData* fd = &bd->MainWindowFrameData; + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + ImGui_ImplSDLGPU3_FrameData* fd = &bd->MainWindowFrameData; if (pipeline == nullptr) pipeline = bd->Pipeline; - ImGui_ImplSDLGPU_SetupRenderState(draw_data,pipeline,command_buffer,render_pass,fd,fb_width,fb_height); + ImGui_ImplSDLGPU3_SetupRenderState(draw_data, pipeline, command_buffer, render_pass, fd, fb_width, fb_height); // Will project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports @@ -267,10 +260,10 @@ void ImGui_ImplSDLGPU_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer SDL_SetGPUScissor(render_pass,&scissor_rect); // Bind DescriptorSet with font or user texture - SDL_BindGPUFragmentSamplers(render_pass,0,(SDL_GPUTextureSamplerBinding*)pcmd->GetTexID(),1); + SDL_BindGPUFragmentSamplers(render_pass, 0, (SDL_GPUTextureSamplerBinding*)pcmd->GetTexID(), 1); // Draw - SDL_DrawGPUIndexedPrimitives(render_pass,pcmd->ElemCount,1,pcmd->IdxOffset + global_idx_offset,pcmd->VtxOffset + global_vtx_offset,0); + SDL_DrawGPUIndexedPrimitives(render_pass, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0); } } global_idx_offset += draw_list->IdxBuffer.Size; @@ -281,21 +274,21 @@ void ImGui_ImplSDLGPU_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer // Our last values will leak into user/application rendering if you forgot to call SDL_SetGPUViewport() and SDL_SetGPUScissor() yourself to explicitly set that state // In theory we should aim to backup/restore those values but I am not sure this is possible. // We perform a call to SDL_SetGPUScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644) - SDL_Rect scissor_rect {0,0,fb_width,fb_height}; - SDL_SetGPUScissor(render_pass,&scissor_rect); + SDL_Rect scissor_rect { 0, 0, fb_width, fb_height }; + SDL_SetGPUScissor(render_pass, &scissor_rect); } -bool ImGui_ImplSDLGPU_CreateFontsTexture() +bool ImGui_ImplSDLGPU3_CreateFontsTexture() { ImGuiIO& io = ImGui::GetIO(); - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; // Destroy existing texture (if any) if (bd->FontTexture) { SDL_WaitForGPUIdle(v->GpuDevice); - ImGui_ImplSDLGPU_DestroyFontsTexture(); + ImGui_ImplSDLGPU3_DestroyFontsTexture(); } unsigned char* pixels; @@ -315,7 +308,7 @@ bool ImGui_ImplSDLGPU_CreateFontsTexture() texture_info.num_levels = 1; texture_info.sample_count = SDL_GPU_SAMPLECOUNT_1; - bd->FontTexture = SDL_CreateGPUTexture(v->GpuDevice,&texture_info); + bd->FontTexture = SDL_CreateGPUTexture(v->GpuDevice, &texture_info); IM_ASSERT(bd->FontTexture && "Failed to create font texture, call SDL_GetError() for more info"); } @@ -328,12 +321,12 @@ bool ImGui_ImplSDLGPU_CreateFontsTexture() font_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; font_transferbuffer_info.size = upload_size; - SDL_GPUTransferBuffer* font_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice,&font_transferbuffer_info); + SDL_GPUTransferBuffer* font_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice, &font_transferbuffer_info); IM_ASSERT(font_transferbuffer != nullptr && "Failed to create font transfer buffer, call SDL_GetError() for more information"); - void* texture_ptr = SDL_MapGPUTransferBuffer(v->GpuDevice,font_transferbuffer,false); - memcpy(texture_ptr,pixels,upload_size); - SDL_UnmapGPUTransferBuffer(v->GpuDevice,font_transferbuffer); + void* texture_ptr = SDL_MapGPUTransferBuffer(v->GpuDevice, font_transferbuffer, false); + memcpy(texture_ptr, pixels, upload_size); + SDL_UnmapGPUTransferBuffer(v->GpuDevice, font_transferbuffer); SDL_GPUTextureTransferInfo font_transfer_info = {}; font_transfer_info.offset = 0; @@ -347,7 +340,7 @@ bool ImGui_ImplSDLGPU_CreateFontsTexture() SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(v->GpuDevice); SDL_GPUCopyPass* copy_pass = SDL_BeginGPUCopyPass(cmd); - SDL_UploadToGPUTexture(copy_pass,&font_transfer_info,&font_texture_region,false); + SDL_UploadToGPUTexture(copy_pass, &font_transfer_info, &font_texture_region, false); SDL_EndGPUCopyPass(copy_pass); SDL_SubmitGPUCommandBuffer(cmd); SDL_ReleaseGPUTransferBuffer(v->GpuDevice, font_transferbuffer); @@ -359,28 +352,26 @@ bool ImGui_ImplSDLGPU_CreateFontsTexture() return true; } -// You probably never need to call this, as it is called by ImGui_ImplSDLGPU_CreateFontsTexture() and ImGui_ImplSDLGPU_Shutdown(). -void ImGui_ImplSDLGPU_DestroyFontsTexture() +// You probably never need to call this, as it is called by ImGui_ImplSDLGPU3_CreateFontsTexture() and ImGui_ImplSDLGPU3_Shutdown(). +void ImGui_ImplSDLGPU3_DestroyFontsTexture() { ImGuiIO& io = ImGui::GetIO(); - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; - - if(bd->FontTexture) + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + if (bd->FontTexture) { - SDL_ReleaseGPUTexture(v->GpuDevice,bd->FontTexture); + SDL_ReleaseGPUTexture(v->GpuDevice, bd->FontTexture); bd->FontBinding.texture = nullptr; bd->FontTexture = nullptr; } - io.Fonts->SetTexID(0); } -static void Imgui_ImplSDLGPU_CreateShaders() +static void Imgui_ImplSDLGPU3_CreateShaders() { // Create the shader modules - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; const char* driver = SDL_GetGPUDeviceDriver(v->GpuDevice); @@ -400,22 +391,20 @@ static void Imgui_ImplSDLGPU_CreateShaders() fragment_shader_info.num_storage_textures = 0; fragment_shader_info.num_uniform_buffers = 0; - if(strcmp(driver,"vulkan") == 0) + if (strcmp(driver, "vulkan") == 0) { vertex_shader_info.format = SDL_GPU_SHADERFORMAT_SPIRV; vertex_shader_info.code = spirv_vertex; vertex_shader_info.code_size = sizeof(spirv_vertex); - fragment_shader_info.format = SDL_GPU_SHADERFORMAT_SPIRV; fragment_shader_info.code = spirv_fragment; fragment_shader_info.code_size = sizeof(spirv_fragment); } - else if (strcmp(driver,"direct3d12") == 0) + else if (strcmp(driver, "direct3d12") == 0) { vertex_shader_info.format = SDL_GPU_SHADERFORMAT_DXBC; vertex_shader_info.code = dxbc_vertex; vertex_shader_info.code_size = sizeof(dxbc_vertex); - fragment_shader_info.format = SDL_GPU_SHADERFORMAT_DXBC; fragment_shader_info.code = dxbc_fragment; fragment_shader_info.code_size = sizeof(dxbc_fragment); @@ -427,25 +416,23 @@ static void Imgui_ImplSDLGPU_CreateShaders() vertex_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB; vertex_shader_info.code = metallib_vertex; vertex_shader_info.code_size = sizeof(metallib_vertex); - fragment_shader_info.entrypoint = "main0"; fragment_shader_info.format = SDL_GPU_SHADERFORMAT_METALLIB; fragment_shader_info.code = metallib_fragment; fragment_shader_info.code_size = sizeof(metallib_fragment); } #endif - bd->VertexShader = SDL_CreateGPUShader(v->GpuDevice,&vertex_shader_info); - bd->FragmentShader = SDL_CreateGPUShader(v->GpuDevice,&fragment_shader_info); - + bd->VertexShader = SDL_CreateGPUShader(v->GpuDevice, &vertex_shader_info); + bd->FragmentShader = SDL_CreateGPUShader(v->GpuDevice, &fragment_shader_info); IM_ASSERT(bd->VertexShader != nullptr && "Failed to create vertex shader, call SDL_GetError() for more information"); IM_ASSERT(bd->FragmentShader != nullptr && "Failed to create fragment shader, call SDL_GetError() for more information"); } -static void ImGui_ImplSDLGPU_CreateGraphicsPipeline() +static void ImGui_ImplSDLGPU3_CreateGraphicsPipeline() { - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; - Imgui_ImplSDLGPU_CreateShaders(); + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + Imgui_ImplSDLGPU3_CreateShaders(); SDL_GPUVertexBufferDescription vertex_buffer_desc[1]; vertex_buffer_desc[0].slot = 0; @@ -520,14 +507,14 @@ static void ImGui_ImplSDLGPU_CreateGraphicsPipeline() pipeline_info.depth_stencil_state = depth_stencil_state; pipeline_info.target_info = target_info; - bd->Pipeline = SDL_CreateGPUGraphicsPipeline(v->GpuDevice,&pipeline_info); + bd->Pipeline = SDL_CreateGPUGraphicsPipeline(v->GpuDevice, &pipeline_info); IM_ASSERT(bd->Pipeline != nullptr && "Failed to create graphics pipeline, call SDL_GetError() for more information"); } -bool ImGui_ImplSDLGPU_CreateDeviceObjects() +bool ImGui_ImplSDLGPU3_CreateDeviceObjects() { - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; if (!bd->FontSampler) { @@ -546,53 +533,53 @@ bool ImGui_ImplSDLGPU_CreateDeviceObjects() sampler_info.max_anisotropy = 1.0f; sampler_info.enable_compare = false; - bd->FontSampler = SDL_CreateGPUSampler(v->GpuDevice,&sampler_info); + bd->FontSampler = SDL_CreateGPUSampler(v->GpuDevice, &sampler_info); bd->FontBinding.sampler = bd->FontSampler; IM_ASSERT(bd->FontSampler != nullptr && "Failed to create font sampler, call SDL_GetError() for more information"); } - ImGui_ImplSDLGPU_CreateGraphicsPipeline(); + ImGui_ImplSDLGPU3_CreateGraphicsPipeline(); return true; } -void ImGui_ImplSDLGPU_DestroyFrameData() +void ImGui_ImplSDLGPU3_DestroyFrameData() { - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; - SDL_ReleaseGPUBuffer(v->GpuDevice,bd->MainWindowFrameData.VertexBuffer); - SDL_ReleaseGPUBuffer(v->GpuDevice,bd->MainWindowFrameData.IndexBuffer); + SDL_ReleaseGPUBuffer(v->GpuDevice, bd->MainWindowFrameData.VertexBuffer); + SDL_ReleaseGPUBuffer(v->GpuDevice, bd->MainWindowFrameData.IndexBuffer); bd->MainWindowFrameData.VertexBuffer = nullptr; bd->MainWindowFrameData.IndexBuffer = nullptr; bd->MainWindowFrameData.VertexBufferSize = 0; bd->MainWindowFrameData.IndexBufferSize = 0; } -void ImGui_ImplSDLGPU_DestroyDeviceObjects() +void ImGui_ImplSDLGPU3_DestroyDeviceObjects() { - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - ImGui_ImplSDLGPU_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; - ImGui_ImplSDLGPU_DestroyFrameData(); - ImGui_ImplSDLGPU_DestroyFontsTexture(); + ImGui_ImplSDLGPU3_DestroyFrameData(); + ImGui_ImplSDLGPU3_DestroyFontsTexture(); - if(bd->VertexShader) { SDL_ReleaseGPUShader(v->GpuDevice,bd->VertexShader); bd->VertexShader = nullptr;} - if(bd->FragmentShader) { SDL_ReleaseGPUShader(v->GpuDevice,bd->FragmentShader); bd->FragmentShader = nullptr;} - if(bd->FontSampler) { SDL_ReleaseGPUSampler(v->GpuDevice, bd->FontSampler); bd->FontSampler = nullptr;} - if(bd->Pipeline) { SDL_ReleaseGPUGraphicsPipeline(v->GpuDevice,bd->Pipeline); bd->Pipeline = nullptr;} + if (bd->VertexShader) { SDL_ReleaseGPUShader(v->GpuDevice, bd->VertexShader); bd->VertexShader = nullptr;} + if (bd->FragmentShader) { SDL_ReleaseGPUShader(v->GpuDevice, bd->FragmentShader); bd->FragmentShader = nullptr;} + if (bd->FontSampler) { SDL_ReleaseGPUSampler(v->GpuDevice, bd->FontSampler); bd->FontSampler = nullptr;} + if (bd->Pipeline) { SDL_ReleaseGPUGraphicsPipeline(v->GpuDevice, bd->Pipeline); bd->Pipeline = nullptr;} } -bool ImGui_ImplSDLGPU_Init(ImGui_ImplSDLGPU_InitInfo* info) +bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info) { ImGuiIO& io = ImGui::GetIO(); IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Setup backend capabilities flags - ImGui_ImplSDLGPU_Data* bd = IM_NEW(ImGui_ImplSDLGPU_Data)(); + ImGui_ImplSDLGPU3_Data* bd = IM_NEW(ImGui_ImplSDLGPU3_Data)(); io.BackendRendererUserData = (void*)bd; - io.BackendRendererName = "imgui_impl_sdlgpu"; + io.BackendRendererName = "imgui_impl_sdlgpu3"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. IM_ASSERT(info->GpuDevice != nullptr); @@ -600,31 +587,31 @@ bool ImGui_ImplSDLGPU_Init(ImGui_ImplSDLGPU_InitInfo* info) bd->GPUInitInfo = *info; - ImGui_ImplSDLGPU_CreateDeviceObjects(); + ImGui_ImplSDLGPU3_CreateDeviceObjects(); return true; } -void ImGui_ImplSDLGPU_Shutdown() +void ImGui_ImplSDLGPU3_Shutdown() { - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); - ImGui_ImplSDLGPU_DestroyDeviceObjects(); + ImGui_ImplSDLGPU3_DestroyDeviceObjects(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset; IM_DELETE(bd); } -void ImGui_ImplSDLGPU_NewFrame() +void ImGui_ImplSDLGPU3_NewFrame() { - ImGui_ImplSDLGPU_Data* bd = ImGui_ImplSDLGPU_GetBackendData(); - IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplVulkan_Init()?"); + ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); + IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLGPU3_Init()?"); - if(!bd->FontTexture) - ImGui_ImplSDLGPU_CreateFontsTexture(); + if (!bd->FontTexture) + ImGui_ImplSDLGPU3_CreateFontsTexture(); } #endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_sdlgpu3.h b/backends/imgui_impl_sdlgpu3.h index 18d3001e400c..ff9c751c8660 100644 --- a/backends/imgui_impl_sdlgpu3.h +++ b/backends/imgui_impl_sdlgpu3.h @@ -1,4 +1,4 @@ -// dear imgui: Renderer Backend for SDL_Gpu +// dear imgui: Renderer Backend for SDL_GPU // This needs to be used along with the SDL3 Platform Backend // Implemented features: @@ -27,7 +27,7 @@ // Initialization data, for ImGui_ImplSDLGPU_Init() // - Remember to set ColorTargetFormat to the correct format. If you're rendering to the swapchain, call SDL_GetGPUSwapchainTextureFormat to query the right value -struct ImGui_ImplSDLGPU_InitInfo +struct ImGui_ImplSDLGPU3_InitInfo { SDL_GPUDevice* GpuDevice = nullptr; SDL_GPUTextureFormat ColorTargetFormat = SDL_GPU_TEXTUREFORMAT_INVALID; @@ -35,12 +35,12 @@ struct ImGui_ImplSDLGPU_InitInfo }; // Follow "Getting Started" link and check examples/ folder to learn about using backends! -IMGUI_IMPL_API bool ImGui_ImplSDLGPU_Init(ImGui_ImplSDLGPU_InitInfo* info); -IMGUI_IMPL_API void ImGui_ImplSDLGPU_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplSDLGPU_NewFrame(); -IMGUI_IMPL_API void Imgui_ImplSDLGPU_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer); -IMGUI_IMPL_API void ImGui_ImplSDLGPU_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline = nullptr); -IMGUI_IMPL_API bool ImGui_ImplSDLGPU_CreateFontsTexture(); -IMGUI_IMPL_API void ImGui_ImplSDLGPU_DestroyFontsTexture(); +IMGUI_IMPL_API bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info); +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_NewFrame(); +IMGUI_IMPL_API void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer); +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline = nullptr); +IMGUI_IMPL_API bool ImGui_ImplSDLGPU3_CreateFontsTexture(); +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_DestroyFontsTexture(); #endif // #ifndef IMGUI_DISABLE diff --git a/backends/sdlgpu3/build_instructions.txt b/backends/sdlgpu3/build_instructions.txt index 751dc97a4e0b..25f4a5d28318 100644 --- a/backends/sdlgpu3/build_instructions.txt +++ b/backends/sdlgpu3/build_instructions.txt @@ -1,3 +1,7 @@ + +Instructions to rebuild imgui_impl_sdlgpu3_shaders.h +(You don't need to copy this folder if you are using the backend as-is) + 1) Compile the raw shader files to SPIRV: glslc -o vertex.spv -c shader.vert @@ -33,4 +37,4 @@ Proceed to step 4 -4) Either find a way to load the shader bytecode from file, or use a tool like https://notisrac.github.io/FileToCArray/ to convert the file to a uint8_t array \ No newline at end of file +4) Use a tool like https://notisrac.github.io/FileToCArray/ or misc/fonts/binary_to_compressed_c.cpp in imgui repository to convert the file to a uint8_t array. diff --git a/backends/sdlgpu3/shader.frag b/backends/sdlgpu3/shader.frag index 2de1f76a3b23..ab9ce184e0fa 100644 --- a/backends/sdlgpu3/shader.frag +++ b/backends/sdlgpu3/shader.frag @@ -3,7 +3,8 @@ layout(location = 0) out vec4 fColor; layout(set=2, binding=0) uniform sampler2D sTexture; -layout(location = 0) in struct { +layout(location = 0) in struct +{ vec4 Color; vec2 UV; } In; @@ -11,4 +12,4 @@ layout(location = 0) in struct { void main() { fColor = In.Color * texture(sTexture, In.UV.st); -} \ No newline at end of file +} diff --git a/backends/sdlgpu3/shader.vert b/backends/sdlgpu3/shader.vert index 3363da8b2a7b..3a85a9038192 100644 --- a/backends/sdlgpu3/shader.vert +++ b/backends/sdlgpu3/shader.vert @@ -3,12 +3,14 @@ layout(location = 0) in vec2 aPos; layout(location = 1) in vec2 aUV; layout(location = 2) in vec4 aColor; -layout(set=1,binding=0) uniform UBO { +layout(set=1,binding=0) uniform UBO +{ vec2 uScale; vec2 uTranslate; } ubo; -layout(location = 0) out struct { +layout(location = 0) out struct +{ vec4 Color; vec2 UV; } Out; @@ -19,4 +21,4 @@ void main() Out.UV = aUV; gl_Position = vec4(aPos * ubo.uScale + ubo.uTranslate, 0, 1); gl_Position.y *= -1.0f; -} \ No newline at end of file +} diff --git a/backends/vulkan/build_instructions.txt b/backends/vulkan/build_instructions.txt new file mode 100644 index 000000000000..1f028d96f53e --- /dev/null +++ b/backends/vulkan/build_instructions.txt @@ -0,0 +1,4 @@ + +Script to rebuild shaders stored inside imgui_impl_vulkan.h +(You don't need to copy this folder if you are using the backend as-is) + diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 00df8a746418..80b95681037c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,6 +68,7 @@ Other changes: - Demo: Added label edition to Property Editor demo + fix an ID issue. (#8266) [@moritz-h] - Misc: Fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] - Misc: Fixed MinGW builds uses UTF-8 friendly _wfopen(). (#8300) +- Backends: SDL_GPU for SDL3: Added backend for SDL_GPU! (#8163, #7998, #7988) [@DeltaW0x]. - Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). [@Helodity] - Backends: Metal: Fixed leaks when using metal-cpp. (#8276, #8166) [@selimsandal] diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index 224beb1c16a0..0df73059bda2 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -139,8 +139,8 @@ This support building with Emscripten and targeting WebGL.
Prefer using that if you are using modern GL or WebGL in your application. [example_sdl2_sdlrenderer2/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_sdlrenderer2/)
-SDL2 (Win32, Mac, Linux, etc.) + SDL_Renderer for SDL2 (most graphics backends are supported underneath)
-= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_sdlrenderer.cpp
+SDL2 (Win32, Mac, Linux, etc.) + SDL_Renderer for SDL2 example.
+= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_sdlrenderer2.cpp
This requires SDL 2.0.18+ (released November 2021)
[example_sdl2_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_vulkan/)
@@ -149,6 +149,26 @@ SDL2 (Win32, Mac, Linux, etc.) + Vulkan example.
This is quite long and tedious, because: Vulkan.
For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp. +[example_sdl3_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_opengl3/)
+SDL3 (Win32, Mac, Linux, etc.) + OpenGL3+/ES2/ES3 example.
+= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_opengl3.cpp
+This uses more modern GL calls and custom shaders.
+This support building with Emscripten and targeting WebGL.
+ +[example_sdl3_sdlgpu3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_sdlgpu3/)
+SDL3 (Win32, Mac, Linux, etc.) + SDL_GPU for SDL3 example.
+= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_sdlrenderer3.cpp
+ +[example_sdl3_sdlrenderer3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_sdlrenderer3/)
+SDL3 (Win32, Mac, Linux, etc.) + SDL_Renderer for SDL3 example.
+= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_sdlrenderer3.cpp
+ +[example_sdl3_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_vulkan/)
+SDL3 (Win32, Mac, Linux, etc.) + Vulkan example.
+= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_vulkan.cpp
+This is quite long and tedious, because: Vulkan.
+For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp. + [example_win32_directx9/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx9/)
DirectX9 example, Windows only.
= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx9.cpp diff --git a/docs/README.md b/docs/README.md index 388d8eac63af..9b437311af12 100644 --- a/docs/README.md +++ b/docs/README.md @@ -123,7 +123,7 @@ On most platforms and when using C++, **you should be able to use a combination Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading a texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles, which is essentially what Backends are doing. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that: setting up a window and using backends. If you follow the [Getting Started](https://github.com/ocornut/imgui/wiki/Getting-Started) guide it should in theory takes you less than an hour to integrate Dear ImGui. **Make sure to spend time reading the [FAQ](https://www.dearimgui.com/faq), comments, and the examples applications!** Officially maintained backends/bindings (in repository): -- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_Renderer, Vulkan, WebGPU. +- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_GPU, SDL_Renderer2/3, Vulkan, WebGPU. - Platforms: GLFW, SDL2/SDL3, Win32, Glut, OSX, Android. - Frameworks: Allegro5, Emscripten. diff --git a/examples/example_sdl3_sdlgpu3/main.cpp b/examples/example_sdl3_sdlgpu3/main.cpp index 6c29962dd0b8..353c10857809 100644 --- a/examples/example_sdl3_sdlgpu3/main.cpp +++ b/examples/example_sdl3_sdlgpu3/main.cpp @@ -1,4 +1,4 @@ -// Dear ImGui: standalone example application for SDL_Gpu +// Dear ImGui: standalone example application for SDL3 + SDL_GPU // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq @@ -17,7 +17,6 @@ #include // abort #include - // This example doesn't compile with Emscripten yet! Awaiting SDL3 support. #ifdef __EMSCRIPTEN__ #include "../libs/emscripten/emscripten_mainloop_stub.h" @@ -34,23 +33,23 @@ int main(int, char**) } // Create SDL window graphics context - SDL_Window* window = SDL_CreateWindow("Dear ImGui SDLGpu example", 1280, 720, SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); + SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+SDL_GPU example", 1280, 720, SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY); if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); return -1; } - // Create SDL Gpu Device - SDL_GPUDevice* gpuDevice = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_METALLIB,true,nullptr); - if (gpuDevice == nullptr) + // Create GPU Device + SDL_GPUDevice* gpu_device = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_METALLIB,true,nullptr); + if (gpu_device == nullptr) { printf("Error: SDL_CreateGPUDevice(): %s\n", SDL_GetError()); return -1; } // Claim window for GPU Device - if (!SDL_ClaimWindowForGPUDevice(gpuDevice, window)) + if (!SDL_ClaimWindowForGPUDevice(gpu_device, window)) { printf("Error: SDL_ClaimWindowForGPUDevice(): %s\n", SDL_GetError()); return -1; @@ -69,11 +68,11 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplSDL3_InitForOther(window); - ImGui_ImplSDLGPU_InitInfo init_info = {}; - init_info.GpuDevice = gpuDevice; - init_info.ColorTargetFormat = SDL_GetGPUSwapchainTextureFormat(gpuDevice, window); + ImGui_ImplSDLGPU3_InitInfo init_info = {}; + init_info.GpuDevice = gpu_device; + init_info.ColorTargetFormat = SDL_GetGPUSwapchainTextureFormat(gpu_device, window); init_info.MSAASamples = SDL_GPU_SAMPLECOUNT_1; - ImGui_ImplSDLGPU_Init(&init_info); + ImGui_ImplSDLGPU3_Init(&init_info); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -119,9 +118,9 @@ int main(int, char**) SDL_Delay(10); continue; } - + // Start the Dear ImGui frame - ImGui_ImplSDLGPU_NewFrame(); + ImGui_ImplSDLGPU3_NewFrame(); ImGui_ImplSDL3_NewFrame(); ImGui::NewFrame(); @@ -167,18 +166,15 @@ int main(int, char**) ImDrawData* draw_data = ImGui::GetDrawData(); const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f); - // Acquire a GPU command buffer - SDL_GPUCommandBuffer* command_buffer = SDL_AcquireGPUCommandBuffer(gpuDevice); + SDL_GPUCommandBuffer* command_buffer = SDL_AcquireGPUCommandBuffer(gpu_device); // Acquire a GPU command buffer - //Acquire a swapchain texture SDL_GPUTexture* swapchain_texture; - SDL_AcquireGPUSwapchainTexture(command_buffer, window, &swapchain_texture, nullptr, nullptr); + SDL_AcquireGPUSwapchainTexture(command_buffer, window, &swapchain_texture, nullptr, nullptr); // Acquire a swapchain texture if (swapchain_texture != nullptr && !is_minimized) { - // !!! THIS IS MANDATORY !!! - // Call Imgui_ImplSDLGPU_PrepareDrawData to upload the vertex/index buffer - Imgui_ImplSDLGPU_PrepareDrawData(draw_data, command_buffer); + // This is mandatory: call Imgui_ImplSDLGPU3_PrepareDrawData() to upload the vertex/index buffer! + Imgui_ImplSDLGPU3_PrepareDrawData(draw_data, command_buffer); // Setup and start a render pass SDL_GPUColorTargetInfo target_info = {}; @@ -190,21 +186,26 @@ int main(int, char**) target_info.layer_or_depth_plane = 0; target_info.cycle = false; SDL_GPURenderPass* render_pass = SDL_BeginGPURenderPass(command_buffer, &target_info, 1, nullptr); - /// Render ImGui - ImGui_ImplSDLGPU_RenderDrawData(draw_data, command_buffer, render_pass); + + // Render ImGui + ImGui_ImplSDLGPU3_RenderDrawData(draw_data, command_buffer, render_pass); + SDL_EndGPURenderPass(render_pass); } + // Submit the command buffer SDL_SubmitGPUCommandBuffer(command_buffer); } // Cleanup - SDL_WaitForGPUIdle(gpuDevice); + SDL_WaitForGPUIdle(gpu_device); ImGui_ImplSDL3_Shutdown(); - ImGui_ImplSDLGPU_Shutdown(); + ImGui_ImplSDLGPU3_Shutdown(); ImGui::DestroyContext(); - SDL_ReleaseWindowFromGPUDevice(gpuDevice, window); - SDL_DestroyGPUDevice(gpuDevice); + + SDL_ReleaseWindowFromGPUDevice(gpu_device, window); + SDL_DestroyGPUDevice(gpu_device); SDL_DestroyWindow(window); SDL_Quit(); + return 0; } From 596e09770d351fad21adbfa7b4f88383c6da1440 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 9 Jan 2025 17:07:53 +0100 Subject: [PATCH 359/548] Backends: SDL3: Added ImGui_ImplSDL3_InitForSDLGPU() for consistency. (#8163, #7998, #7988) --- backends/imgui_impl_sdl3.cpp | 5 +++++ backends/imgui_impl_sdl3.h | 1 + docs/CHANGELOG.txt | 2 ++ examples/example_sdl3_sdlgpu3/main.cpp | 2 +- 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index a167c74cd617..c3935b2abd56 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -531,6 +531,11 @@ bool ImGui_ImplSDL3_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* rendere return ImGui_ImplSDL3_Init(window, renderer, nullptr); } +bool ImGui_ImplSDL3_InitForSDLGPU(SDL_Window* window) +{ + return ImGui_ImplSDL3_Init(window, nullptr, nullptr); +} + bool ImGui_ImplSDL3_InitForOther(SDL_Window* window) { return ImGui_ImplSDL3_Init(window, nullptr, nullptr); diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h index 0d906a65cd32..ff0e2aed3dd5 100644 --- a/backends/imgui_impl_sdl3.h +++ b/backends/imgui_impl_sdl3.h @@ -35,6 +35,7 @@ IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForVulkan(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForD3D(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForMetal(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer); +IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForSDLGPU(SDL_Window* window); IMGUI_IMPL_API bool ImGui_ImplSDL3_InitForOther(SDL_Window* window); IMGUI_IMPL_API void ImGui_ImplSDL3_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDL3_NewFrame(); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 80b95681037c..56ad9b8d00f7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -69,6 +69,8 @@ Other changes: - Misc: Fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] - Misc: Fixed MinGW builds uses UTF-8 friendly _wfopen(). (#8300) - Backends: SDL_GPU for SDL3: Added backend for SDL_GPU! (#8163, #7998, #7988) [@DeltaW0x]. +- Backends: SDL3: Added ImGui_ImplSDL3_InitForSDLGPU() for consistency, even + though it is currently not doing anything particular. (#8163, #7998, #7988) - Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). [@Helodity] - Backends: Metal: Fixed leaks when using metal-cpp. (#8276, #8166) [@selimsandal] diff --git a/examples/example_sdl3_sdlgpu3/main.cpp b/examples/example_sdl3_sdlgpu3/main.cpp index 353c10857809..f025c537dea0 100644 --- a/examples/example_sdl3_sdlgpu3/main.cpp +++ b/examples/example_sdl3_sdlgpu3/main.cpp @@ -67,7 +67,7 @@ int main(int, char**) //ImGui::StyleColorsLight(); // Setup Platform/Renderer backends - ImGui_ImplSDL3_InitForOther(window); + ImGui_ImplSDL3_InitForSDLGPU(window); ImGui_ImplSDLGPU3_InitInfo init_info = {}; init_info.GpuDevice = gpu_device; init_info.ColorTargetFormat = SDL_GetGPUSwapchainTextureFormat(gpu_device, window); From e7fb97208a876a2c57143e9cda0372d878c6abe9 Mon Sep 17 00:00:00 2001 From: Daniel Walz Date: Thu, 9 Jan 2025 23:12:07 +0100 Subject: [PATCH 360/548] Backends: Metal: Added missing IM_UNUSED (#8302) --- backends/imgui_impl_metal.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 3ff905a60cef..1e0c47f52b51 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -143,6 +143,7 @@ bool ImGui_ImplMetal_Init(id device) void ImGui_ImplMetal_Shutdown() { ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData(); + IM_UNUSED(bd); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGui_ImplMetal_DestroyDeviceObjects(); ImGui_ImplMetal_DestroyBackendData(); From 0b8ff4b2382d4bbd5c168b1a5373f86ea3145957 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 9 Jan 2025 23:15:59 +0100 Subject: [PATCH 361/548] Backends, Examples: Vulkan: add IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE. use in descriptor pools sizes. (#6642) --- backends/imgui_impl_vulkan.cpp | 4 +++- backends/imgui_impl_vulkan.h | 6 ++++-- docs/CHANGELOG.txt | 4 ++++ examples/example_glfw_vulkan/main.cpp | 9 +++++---- examples/example_sdl2_vulkan/main.cpp | 9 +++++---- examples/example_sdl3_vulkan/main.cpp | 9 +++++---- examples/example_win32_vulkan/main.cpp | 9 +++++---- 7 files changed, 31 insertions(+), 19 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 4345f2b11554..940ea2d79b15 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -26,6 +26,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-01-09: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in descriptor pool. (#6642) // 2025-01-06: Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples. // 2024-12-11: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) // 2024-11-27: Vulkan: Make user-provided descriptor pool optional. As a convenience, when setting init_info->DescriptorPoolSize the backend will create one itself. (#8172, #4867) @@ -1022,8 +1023,9 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() check_vk_result(err); } - if (v->DescriptorPoolSize) + if (v->DescriptorPoolSize != 0) { + IM_ASSERT(v->DescriptorPoolSize > IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE); VkDescriptorPoolSize pool_size = { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, v->DescriptorPoolSize }; VkDescriptorPoolCreateInfo pool_info = {}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 5621acbddb64..3bd9948647c3 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -61,14 +61,16 @@ #define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING #endif +// Current version of the backend use 1 descriptor for the font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture(). +// It is expected that as early as Q1 2025 the backend will use a few more descriptors. Use this value + number of desired calls to ImGui_ImplVulkan_AddTexture(). +#define IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE (1) // Minimum per atlas + // Initialization data, for ImGui_ImplVulkan_Init() // [Please zero-clear before use!] // - About descriptor pool: // - A VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // and must contain a pool size large enough to hold a small number of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptors. // - As an convenience, by setting DescriptorPoolSize > 0 the backend will create one for you. -// - Current version of the backend use 1 descriptor for the font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture(). -// - It is expected that as early as Q1 2025 the backend will use a few more descriptors, so aim at 10 + number of desierd calls to ImGui_ImplVulkan_AddTexture(). // - About dynamic rendering: // - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure. struct ImGui_ImplVulkan_InitInfo diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 56ad9b8d00f7..1b713e17f151 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -79,6 +79,10 @@ Other changes: platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) [@Zer0xFF] - Backends: Vulkan: Added a few more ImGui_ImplVulkanH_XXX helper functions primarily for the purpose of making our examples simpler. +- Backends: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify + how many image sampler descriptors are expected to be available in the provided + descriptor pool. Current backend needs 1 but it is expected that by end of Q1 2025 + this number will grow (will staying a very small number). (#6642) - Backends: DX11: Expose vertex constant buffer in ImGui_ImplDX11_RenderState. Reset projection matrix in ImDrawCallback_ResetRenderState handlers. (#6969, #5834, #7468, #3590) - Backends: DX10: Expose ImGui_ImplDX10_RenderState for completeness. (#6969, #5834, #7468, #3590) diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 9f8dced2f18d..b61dcaae0088 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -189,17 +189,18 @@ static void SetupVulkan(ImVector instance_extensions) } // Create Descriptor Pool - // The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that) - // If you wish to load e.g. additional textures you may need to alter pools sizes. + // If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets. { VkDescriptorPoolSize pool_sizes[] = { - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE }, }; VkDescriptorPoolCreateInfo pool_info = {}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - pool_info.maxSets = 1; + pool_info.maxSets = 0; + for (VkDescriptorPoolSize& pool_size : pool_sizes) + pool_info.maxSets += pool_size.descriptorCount; pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); pool_info.pPoolSizes = pool_sizes; err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index fafa8ea42a76..b82ed0b7ace8 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -177,17 +177,18 @@ static void SetupVulkan(ImVector instance_extensions) } // Create Descriptor Pool - // The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that) - // If you wish to load e.g. additional textures you may need to alter pools sizes. + // If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets. { VkDescriptorPoolSize pool_sizes[] = { - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE }, }; VkDescriptorPoolCreateInfo pool_info = {}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - pool_info.maxSets = 1; + pool_info.maxSets = 0; + for (VkDescriptorPoolSize& pool_size : pool_sizes) + pool_info.maxSets += pool_size.descriptorCount; pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); pool_info.pPoolSizes = pool_sizes; err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index 569eaeffb871..e36f87194ead 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -182,17 +182,18 @@ static void SetupVulkan(ImVector instance_extensions) } // Create Descriptor Pool - // The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that) - // If you wish to load e.g. additional textures you may need to alter pools sizes. + // If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets. { VkDescriptorPoolSize pool_sizes[] = { - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE }, }; VkDescriptorPoolCreateInfo pool_info = {}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - pool_info.maxSets = 1; + pool_info.maxSets = 0; + for (VkDescriptorPoolSize& pool_size : pool_sizes) + pool_info.maxSets += pool_size.descriptorCount; pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); pool_info.pPoolSizes = pool_sizes; err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp index 3fabf7a2dec5..c6c138695a13 100644 --- a/examples/example_win32_vulkan/main.cpp +++ b/examples/example_win32_vulkan/main.cpp @@ -178,17 +178,18 @@ static void SetupVulkan(ImVector instance_extensions) } // Create Descriptor Pool - // The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that) - // If you wish to load e.g. additional textures you may need to alter pools sizes. + // If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets. { VkDescriptorPoolSize pool_sizes[] = { - { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE }, }; VkDescriptorPoolCreateInfo pool_info = {}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; - pool_info.maxSets = 1; + pool_info.maxSets = 0; + for (VkDescriptorPoolSize& pool_size : pool_sizes) + pool_info.maxSets += pool_size.descriptorCount; pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); pool_info.pPoolSizes = pool_sizes; err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool); From 1d962820d8b972d93a4627afc3cb4c09837c298c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 12 Jan 2025 15:11:30 +0100 Subject: [PATCH 362/548] Error Handling: Turned common EndTable() and other TableXXX functions fail cases into recoverable errors. (#1651, #8314) --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 45 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1b713e17f151..bf9f209c4647 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,8 @@ Other changes: - Error Handling: Fixed bugs recovering from within a table that created a child window, and from nested child windows. (#1651) +- Error Handling: Turned common EndTable() and other TableXXX functions + fail cases into a recoverable error. (#1651, #8314) - InputText: Fixed a bug where character replacements performed from a callback were not applied when pasting from clipbard. (#8229) - InputText: Fixed issue when activating a ReadOnly field when the underlying diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 1ab9c703ec5d..ec25bf906022 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1337,7 +1337,11 @@ void ImGui::EndTable() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Only call EndTable() if BeginTable() returns true!"); + if (table == NULL) + { + IM_ASSERT_USER_ERROR(table != NULL, "EndTable() call should only be done while in BeginTable() scope!"); + return; + } // This assert would be very useful to catch a common error... unfortunately it would probably trigger in some // cases, and for consistency user may sometimes output empty tables (and still benefit from e.g. outer border) @@ -1560,8 +1564,12 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); - IM_ASSERT(table->IsLayoutLocked == false && "Need to call call TableSetupColumn() before first row!"); + if (table == NULL) + { + IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!"); + return; + } + IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!"); IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()"); if (table->DeclColumnsCount >= table->ColumnsCount) { @@ -1634,7 +1642,11 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); + if (table == NULL) + { + IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!"); + return; + } IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!"); IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS); IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit @@ -1711,9 +1723,11 @@ void ImGui::TableSetColumnEnabled(int column_n, bool enabled) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL); - if (!table) + if (table == NULL) + { + IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!"); return; + } IM_ASSERT(table->Flags & ImGuiTableFlags_Hideable); // See comments above if (column_n < 0) column_n = table->CurrentColumn; @@ -3034,7 +3048,11 @@ void ImGui::TableHeadersRow() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); + if (table == NULL) + { + IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!"); + return; + } // Call layout if not already done. This is automatically done by TableNextRow: we do it here _only_ to make // it easier to debug-step in TableUpdateLayout(). Your own version of this function doesn't need this. @@ -3079,7 +3097,12 @@ void ImGui::TableHeader(const char* label) return; ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Need to call TableHeader() after BeginTable()!"); + if (table == NULL) + { + IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!"); + return; + } + IM_ASSERT(table->CurrentColumn != -1); const int column_n = table->CurrentColumn; ImGuiTableColumn* column = &table->Columns[column_n]; @@ -3254,7 +3277,11 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label ImGuiTable* table = g.CurrentTable; ImGuiWindow* window = g.CurrentWindow; ImDrawList* draw_list = window->DrawList; - IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); + if (table == NULL) + { + IM_ASSERT_USER_ERROR(table != NULL, "Call should only be done while in BeginTable() scope!"); + return; + } IM_ASSERT(table->CurrentRow == -1 && "Must be first row"); if (max_label_width == 0.0f) From a28ffa81c4a8e244e2682587285a63e3d0f2c67e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Jan 2025 13:26:15 +0100 Subject: [PATCH 363/548] Docs: added more references to IsKeyDown(), InFlags. (#8317) --- docs/CHANGELOG.txt | 4 +++- imgui.cpp | 2 +- imgui_internal.h | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bf9f209c4647..9c1b280b3da4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -153,11 +153,12 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v Breaking changes: - Commented out pre-1.87 IO system (equivalent to using IMGUI_DISABLE_OBSOLETE_KEYIO or IMGUI_DISABLE_OBSOLETE_FUNCTIONS before). - - io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022). + - io.KeyMap[] and io.KeysDown[] are removed (obsoleted February 2022). Use IsKeyDown() instead. - io.NavInputs[] and ImGuiNavInput are removed (obsoleted July 2022). - Pre-1.87 backends are not supported: - backends need to call io.AddKeyEvent(), io.AddMouseEvent() instead of writing to io.KeysDown[], io.MouseDown[] fields. - backends need to call io.AddKeyAnalogEvent() for gamepad values instead of writing to io.NavInputs[] fields. + - you can use IsKeyDown() instead of reading from io.KeysDown[]. - For more references: - read 1.87 and 1.88 part of API BREAKING CHANGES in imgui.cpp or read Changelog for 1.87 and 1.88. - read https://github.com/ocornut/imgui/issues/4921 @@ -2390,6 +2391,7 @@ Breaking Changes: - For all calls to IO new functions, the Dear ImGui context should be bound/current. - Reworked IO keyboard input API: (#4921, #2625, #3724) [@thedmd, @ocornut] - Added io.AddKeyEvent() function, obsoleting writing directly to io.KeyMap[], io.KeysDown[] arrays. + - You can use IsKeyDown() instead of reading from io.KeysDown[]. - For keyboard modifiers, you can call io.AddKeyEvent() with ImGuiKey_ModXXX values, obsoleting writing directly to io.KeyCtrl, io.KeyShift etc. - Added io.SetKeyEventNativeData() function (optional) to pass native and old legacy indices. diff --git a/imgui.cpp b/imgui.cpp index bad766f030eb..c676172effd3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -647,7 +647,7 @@ CODE - Backend writing to io.MouseHoveredViewport -> backend should call io.AddMouseViewportEvent() [Docking branch w/ multi-viewports only] note: for all calls to IO new functions, the Dear ImGui context should be bound/current. read https://github.com/ocornut/imgui/issues/4921 for details. - - 2022/01/10 (1.87) - inputs: reworked keyboard IO. Removed io.KeyMap[], io.KeysDown[] in favor of calling io.AddKeyEvent(). Removed GetKeyIndex(), now unnecessary. All IsKeyXXX() functions now take ImGuiKey values. All features are still functional until IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Read Changelog and Release Notes for details. + - 2022/01/10 (1.87) - inputs: reworked keyboard IO. Removed io.KeyMap[], io.KeysDown[] in favor of calling io.AddKeyEvent(), ImGui::IsKeyDown(). Removed GetKeyIndex(), now unnecessary. All IsKeyXXX() functions now take ImGuiKey values. All features are still functional until IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Read Changelog and Release Notes for details. - IsKeyPressed(MY_NATIVE_KEY_XXX) -> use IsKeyPressed(ImGuiKey_XXX) - IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX) - Backend writing to io.KeyMap[],io.KeysDown[] -> backend should call io.AddKeyEvent() (+ call io.SetKeyEventNativeData() if you want legacy user code to stil function with legacy key codes). diff --git a/imgui_internal.h b/imgui_internal.h index 850136b0db2a..9ff2b6d3e0fd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1247,11 +1247,11 @@ struct ImGuiNextItemData struct ImGuiLastItemData { ImGuiID ID; - ImGuiItemFlags ItemFlags; // See ImGuiItemFlags_ + ImGuiItemFlags ItemFlags; // See ImGuiItemFlags_ (called 'InFlags' before v1.91.4). ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_ ImRect Rect; // Full rectangle ImRect NavRect; // Navigation scoring rectangle (not displayed) - // Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags ar set. + // Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags are set. ImRect DisplayRect; // Display rectangle. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) is set. ImRect ClipRect; // Clip rectangle at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasClipRect) is set.. ImGuiKeyChord Shortcut; // Shortcut at the time of submitting item. ONLY VALID IF (StatusFlags & ImGuiItemStatusFlags_HasShortcut) is set.. From a604d4f717bb99a704fcb17d29a6f0dbac78c060 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 10 Jan 2025 17:08:09 +0100 Subject: [PATCH 364/548] Fixed IsItemDeactivated(), IsItemDeactivatedAfterEdit() to work when interrupted before/after the active id is submitted. (#5184, #5904, #6766, #8303, #8004) --- docs/CHANGELOG.txt | 9 +++++++++ imgui.cpp | 40 ++++++++++++++++++++++++---------------- imgui.h | 2 +- imgui_internal.h | 16 ++++++++++++---- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9c1b280b3da4..1f1eb05a96fd 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,15 @@ Breaking changes: Other changes: +- Fixed issues with IsItemDeactivated() and IsItemDeactivatedAfterEdit() not + emitting a reliable signal when an item is deactivated externally: e.g. + via an explicit clear of focus, clear of active id, opening of modal etc. + (#5184, #5904, #6766, #8303, #8004) + - It used to work when the interruption happened in the frame before the + active item as submitted, but not after. It should work in both cases now. + - While this is not specific to a certain widgets, typically it would + mostly be noticeable on InputText() because it keeps ActiveId for a + longer time while allowing other interaction to happen. - Error Handling: Fixed bugs recovering from within a table that created a child window, and from nested child windows. (#1651) - Error Handling: Turned common EndTable() and other TableXXX functions diff --git a/imgui.cpp b/imgui.cpp index c676172effd3..6b9f47164400 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3930,9 +3930,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas) ActiveIdSource = ImGuiInputSource_None; ActiveIdMouseButton = -1; ActiveIdPreviousFrame = 0; - ActiveIdPreviousFrameIsAlive = false; - ActiveIdPreviousFrameHasBeenEditedBefore = false; - ActiveIdPreviousFrameWindow = NULL; + memset(&DeactivatedItemData, 0, sizeof(DeactivatedItemData)); memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation)); LastActiveId = 0; LastActiveIdTimer = 0.0f; @@ -4175,7 +4173,7 @@ void ImGui::Shutdown() g.WindowsById.Clear(); g.NavWindow = NULL; g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL; - g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL; + g.ActiveIdWindow = NULL; g.MovingWindow = NULL; g.KeysRoutingTable.Clear(); @@ -4359,6 +4357,13 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) g.MovingWindow = NULL; } + // Store deactivate data + ImGuiDeactivatedItemData* deactivated_data = &g.DeactivatedItemData; + deactivated_data->ID = g.ActiveId; + deactivated_data->ElapseFrame = (g.LastItemData.ID == g.ActiveId) ? g.FrameCount : g.FrameCount + 1; // FIXME: OK to use LastItemData? + deactivated_data->HasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore; + deactivated_data->IsAlive = (g.ActiveIdIsAlive == g.ActiveId); + // This could be written in a more general way (e.g associate a hook to ActiveId), // but since this is currently quite an exception we'll leave it as is. // One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveID() @@ -5189,11 +5194,8 @@ void ImGui::NewFrame() g.ActiveIdTimer += g.IO.DeltaTime; g.LastActiveIdTimer += g.IO.DeltaTime; g.ActiveIdPreviousFrame = g.ActiveId; - g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow; - g.ActiveIdPreviousFrameHasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore; g.ActiveIdIsAlive = 0; g.ActiveIdHasBeenEditedThisFrame = false; - g.ActiveIdPreviousFrameIsAlive = false; g.ActiveIdIsJustActivated = false; if (g.TempInputId != 0 && g.ActiveId != g.TempInputId) g.TempInputId = 0; @@ -5202,6 +5204,9 @@ void ImGui::NewFrame() g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingAllKeyboardKeys = false; } + if (g.DeactivatedItemData.ElapseFrame < g.FrameCount) + g.DeactivatedItemData.ID = 0; + g.DeactivatedItemData.IsAlive = false; // Record when we have been stationary as this state is preserved while over same item. // FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values. @@ -5833,13 +5838,13 @@ bool ImGui::IsItemDeactivated() ImGuiContext& g = *GImGui; if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated) return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0; - return (g.ActiveIdPreviousFrame == g.LastItemData.ID && g.ActiveIdPreviousFrame != 0 && g.ActiveId != g.LastItemData.ID); + return (g.DeactivatedItemData.ID == g.LastItemData.ID && g.LastItemData.ID != 0 && g.DeactivatedItemData.ElapseFrame >= g.FrameCount); } bool ImGui::IsItemDeactivatedAfterEdit() { ImGuiContext& g = *GImGui; - return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEditedBefore || (g.ActiveId == 0 && g.ActiveIdHasBeenEditedBefore)); + return IsItemDeactivated() && g.DeactivatedItemData.HasBeenEditedBefore; } // == (GetItemID() == GetFocusID() && GetFocusID() != 0) @@ -10443,8 +10448,8 @@ void ImGui::KeepAliveID(ImGuiID id) ImGuiContext& g = *GImGui; if (g.ActiveId == id) g.ActiveIdIsAlive = id; - if (g.ActiveIdPreviousFrame == id) - g.ActiveIdPreviousFrameIsAlive = true; + if (g.DeactivatedItemData.ID == id) + g.DeactivatedItemData.IsAlive = true; } // Declare item bounding box for clipping and interaction. @@ -10529,6 +10534,9 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu // window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG] #endif + if (id != 0 && g.DeactivatedItemData.ID == id) + g.DeactivatedItemData.ElapseFrame = g.FrameCount; + // 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) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible; @@ -10888,7 +10896,7 @@ void ImGui::BeginGroup() group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive; group_data.BackupHoveredIdIsAlive = g.HoveredId != 0; group_data.BackupIsSameLine = window->DC.IsSameLine; - group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive; + group_data.BackupDeactivatedIdIsAlive = g.DeactivatedItemData.IsAlive; group_data.EmitItem = true; window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x; @@ -10939,11 +10947,11 @@ void ImGui::EndGroup() // Also if you grep for LastItemId you'll notice it is only used in that context. // (The two tests not the same because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.) const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId; - const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true); + const bool group_contains_deactivated_id = (group_data.BackupDeactivatedIdIsAlive == false) && (g.DeactivatedItemData.IsAlive == true); if (group_contains_curr_active_id) g.LastItemData.ID = g.ActiveId; - else if (group_contains_prev_active_id) - g.LastItemData.ID = g.ActiveIdPreviousFrame; + else if (group_contains_deactivated_id) + g.LastItemData.ID = g.DeactivatedItemData.ID; g.LastItemData.Rect = group_bb; // Forward Hovered flag @@ -10957,7 +10965,7 @@ void ImGui::EndGroup() // Forward Deactivated flag g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated; - if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame) + if (group_contains_deactivated_id) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated; g.GroupStack.pop_back(); diff --git a/imgui.h b/imgui.h index 0f7a99862432..5a3a7af6569e 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.7 WIP" -#define IMGUI_VERSION_NUM 19164 +#define IMGUI_VERSION_NUM 19165 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 9ff2b6d3e0fd..bb5a5677460e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -140,6 +140,7 @@ struct ImGuiContext; // Main Dear ImGui context struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum) struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum +struct ImGuiDeactivatedItemData; // Data for IsItemDeactivated()/IsItemDeactivatedAfterEdit() function. struct ImGuiErrorRecoveryState; // Storage of stack sizes for error handling and recovery struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup() struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box @@ -1070,7 +1071,7 @@ struct IMGUI_API ImGuiGroupData ImVec2 BackupCurrLineSize; float BackupCurrLineTextBaseOffset; ImGuiID BackupActiveIdIsAlive; - bool BackupActiveIdPreviousFrameIsAlive; + bool BackupDeactivatedIdIsAlive; bool BackupHoveredIdIsAlive; bool BackupIsSameLine; bool EmitItem; @@ -1314,6 +1315,15 @@ struct ImGuiPtrOrIndex ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } }; +// Data used by IsItemDeactivated()/IsItemDeactivatedAfterEdit() functions +struct ImGuiDeactivatedItemData +{ + ImGuiID ID; + int ElapseFrame; + bool HasBeenEditedBefore; + bool IsAlive; +}; + //----------------------------------------------------------------------------- // [SECTION] Popup support //----------------------------------------------------------------------------- @@ -2106,9 +2116,7 @@ struct ImGuiContext ImGuiWindow* ActiveIdWindow; ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad ImGuiID ActiveIdPreviousFrame; - bool ActiveIdPreviousFrameIsAlive; - bool ActiveIdPreviousFrameHasBeenEditedBefore; - ImGuiWindow* ActiveIdPreviousFrameWindow; + ImGuiDeactivatedItemData DeactivatedItemData; ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX. ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. From 00f12b9a09d2a39831eb8dfc4f75f11460768a6e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Jan 2025 15:22:45 +0100 Subject: [PATCH 365/548] InputText: Fixed not calling CallbackEdit on revert/clear with Escape key. (#8273) + rework comments. Seems like there is no reason to not run that path. Amend ancient 9501cd99, f3ab5e625 --- docs/CHANGELOG.txt | 2 ++ imgui.h | 4 ++-- imgui_widgets.cpp | 14 ++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1f1eb05a96fd..5753d10dba16 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -62,6 +62,8 @@ Other changes: value is being modified. (#8242) - InputText: Added sanity check to detect some cases of passing a non zero-terminated input buffer. +- InputText: Fixed not calling CallbackEdit on revert/clear with Escape key, + although IsItemEdited() was behaving correctly. (#8273) - Tables: Fixed TableAngledHeadersRow() creating an infinite horizontal scrolling region when the table is hosted in a viewport with negative coordinates. diff --git a/imgui.h b/imgui.h index 5a3a7af6569e..a89a6c621a23 100644 --- a/imgui.h +++ b/imgui.h @@ -1182,7 +1182,7 @@ enum ImGuiInputTextFlags_ ImGuiInputTextFlags_CallbackAlways = 1 << 20, // Callback on each iteration. User code may query cursor position, modify text buffer. ImGuiInputTextFlags_CallbackCharFilter = 1 << 21, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. ImGuiInputTextFlags_CallbackResize = 1 << 22, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this) - ImGuiInputTextFlags_CallbackEdit = 1 << 23, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) + ImGuiInputTextFlags_CallbackEdit = 1 << 23, // Callback on any edit. Note that InputText() already returns true on edit + you can always use IsItemEdited(). The callback is useful to manipulate the underlying buffer while focus is active. // Obsolete names //ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior @@ -2442,7 +2442,7 @@ struct ImGuiIO // Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used. // The callback function should return 0 by default. // Callbacks (follow a flag name and see comments in ImGuiInputTextFlags_ declarations for more details) -// - ImGuiInputTextFlags_CallbackEdit: Callback on buffer edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) +// - ImGuiInputTextFlags_CallbackEdit: Callback on buffer edit. Note that InputText() already returns true on edit + you can always use IsItemEdited(). The callback is useful to manipulate the underlying buffer while focus is active. // - ImGuiInputTextFlags_CallbackAlways: Callback on each iteration // - ImGuiInputTextFlags_CallbackCompletion: Callback on pressing TAB // - ImGuiInputTextFlags_CallbackHistory: Callback on pressing Up/Down arrows diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 854f09634bd0..725f6de2aca7 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4977,19 +4977,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } } - // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer - // before clearing ActiveId, even though strictly speaking it wasn't modified on this frame. - // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. - // This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage + // FIXME-OPT: We always reapply the live buffer back to the input buffer before clearing ActiveId, + // even though strictly speaking it wasn't modified on this frame. Should mark dirty state from the stb_textedit callbacks. + // If we do that, need to ensure that as special case, 'validated == true' also writes back. + // This also allows the user to use InputText() without maintaining any user-side storage. // (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object // unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize). - const bool apply_edit_back_to_user_buffer = !revert_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); + const bool apply_edit_back_to_user_buffer = true;// !revert_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); if (apply_edit_back_to_user_buffer) { - // Apply new value immediately - copy modified buffer back + // Apply current edited text immediately. // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer - // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect. - // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks. // User callback if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0) From 32cea853317c6ee1dbfb4f08925b410956366ed7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Jan 2025 15:51:39 +0100 Subject: [PATCH 366/548] Debug Tools: Item Picker: Always available in menu. Tweak Demo Debug Options. (#2673, #1651) --- docs/CHANGELOG.txt | 3 +++ imgui_demo.cpp | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5753d10dba16..8d3ced68e2df 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,7 @@ Other changes: a child window, and from nested child windows. (#1651) - Error Handling: Turned common EndTable() and other TableXXX functions fail cases into a recoverable error. (#1651, #8314) +- Error Handling: Exposed some options in Demo->Tools->Debug Options. (#1651) - InputText: Fixed a bug where character replacements performed from a callback were not applied when pasting from clipbard. (#8229) - InputText: Fixed issue when activating a ReadOnly field when the underlying @@ -76,6 +77,8 @@ Other changes: windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231) - Debug Tools: Debug Log: hovering 0xXXXXXXXX values in log is allowed even if a popup is blocking mouse access to the debug log window. (#5855) +- Debug Tools: Item Picker: Always available regardless of value of + io.ConfigDebugIsDebuggerPresent. (#2673) - Fonts: Fixed miscalculation of Ellipsis ("...") character width when automatically created from a single comma character, affecting some fonts/settings (not all). - Demo: Added label edition to Property Editor demo + fix an ID issue. (#8266) [@moritz-h] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c9a21759d456..7bb15d737bee 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -743,19 +743,27 @@ static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data) #else const bool has_debug_tools = false; #endif + if (ImGui::BeginMenu("Debug Options")) + { + ImGui::BeginDisabled(!has_debug_tools); + ImGui::Checkbox("Highlight ID Conflicts", &io.ConfigDebugHighlightIdConflicts); + ImGui::EndDisabled(); + ImGui::Checkbox("Assert on error recovery", &io.ConfigErrorRecoveryEnableAssert); + ImGui::TextDisabled("(see Demo->Configuration for details & more)"); + ImGui::EndMenu(); + } + ImGui::MenuItem("Metrics/Debugger", NULL, &demo_data->ShowMetrics, has_debug_tools); ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools); ImGui::MenuItem("ID Stack Tool", NULL, &demo_data->ShowIDStackTool, has_debug_tools); bool is_debugger_present = io.ConfigDebugIsDebuggerPresent; - if (ImGui::MenuItem("Item Picker", NULL, false, has_debug_tools && is_debugger_present)) + if (ImGui::MenuItem("Item Picker", NULL, false, has_debug_tools))// && is_debugger_present)) ImGui::DebugStartItemPicker(); if (!is_debugger_present) - ImGui::SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable the menu option to avoid casual users crashing the application.\n\nYou can however always access the Item Picker in Metrics->Tools."); + ImGui::SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable some extra features to avoid casual users crashing the application."); ImGui::MenuItem("Style Editor", NULL, &demo_data->ShowStyleEditor); ImGui::MenuItem("About Dear ImGui", NULL, &demo_data->ShowAbout); - ImGui::SeparatorText("Debug Options"); - ImGui::MenuItem("Highlight ID Conflicts", NULL, &io.ConfigDebugHighlightIdConflicts, has_debug_tools); ImGui::EndMenu(); } ImGui::EndMenuBar(); From 6fb7d442559a4540d3bbbe70d9dfc4a04d60109b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Jan 2025 16:46:29 +0100 Subject: [PATCH 367/548] Backends: SDL2/SDL3: Comments. (#7672, #7670) --- backends/imgui_impl_sdl2.cpp | 2 ++ backends/imgui_impl_sdl3.cpp | 3 ++- imgui_demo.cpp | 3 +-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index e937b5496654..0aaf9830a9c5 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -399,6 +399,8 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) if (ImGui_ImplSDL2_GetViewportForWindowID(event->key.windowID) == nullptr) return false; ImGui_ImplSDL2_UpdateKeyModifiers((SDL_Keymod)event->key.keysym.mod); + //IMGUI_DEBUG_LOG("SDL_KEY_%s : key=%d ('%s'), scancode=%d ('%s'), mod=%X\n", + // (event->type == SDL_KEYDOWN) ? "DOWN" : "UP ", event->key.keysym.sym, SDL_GetKeyName(event->key.keysym.sym), event->key.keysym.scancode, SDL_GetScancodeName(event->key.keysym.scancode), event->key.keysym.mod); ImGuiKey key = ImGui_ImplSDL2_KeyEventToImGuiKey(event->key.keysym.sym, event->key.keysym.scancode); io.AddKeyEvent(key, (event->type == SDL_KEYDOWN)); io.SetKeyEventNativeData(key, event->key.keysym.sym, event->key.keysym.scancode, event->key.keysym.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions. diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index c3935b2abd56..b8e4dec5ea84 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -375,8 +375,9 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event) { if (ImGui_ImplSDL3_GetViewportForWindowID(event->key.windowID) == nullptr) return false; - //IMGUI_DEBUG_LOG("SDL_EVENT_KEY_%d: key=%d, scancode=%d, mod=%X\n", (event->type == SDL_EVENT_KEY_DOWN) ? "DOWN" : "UP", event->key.key, event->key.scancode, event->key.mod); ImGui_ImplSDL3_UpdateKeyModifiers((SDL_Keymod)event->key.mod); + //IMGUI_DEBUG_LOG("SDL_EVENT_KEY_%s : key=%d ('%s'), scancode=%d ('%s'), mod=%X\n", + // (event->type == SDL_EVENT_KEY_DOWN) ? "DOWN" : "UP ", event->key.key, SDL_GetKeyName(event->key.key), event->key.scancode, SDL_GetScancodeName(event->key.scancode), event->key.mod); ImGuiKey key = ImGui_ImplSDL3_KeyEventToImGuiKey(event->key.key, event->key.scancode); io.AddKeyEvent(key, (event->type == SDL_EVENT_KEY_DOWN)); io.SetKeyEventNativeData(key, event->key.key, event->key.scancode, event->key.scancode); // To support legacy indexing (<1.87 user code). Legacy backend uses SDLK_*** as indices to IsKeyXXX() functions. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7bb15d737bee..4bc70fe425e0 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -743,6 +743,7 @@ static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data) #else const bool has_debug_tools = false; #endif + ImGui::MenuItem("Metrics/Debugger", NULL, &demo_data->ShowMetrics, has_debug_tools); if (ImGui::BeginMenu("Debug Options")) { ImGui::BeginDisabled(!has_debug_tools); @@ -752,8 +753,6 @@ static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data) ImGui::TextDisabled("(see Demo->Configuration for details & more)"); ImGui::EndMenu(); } - - ImGui::MenuItem("Metrics/Debugger", NULL, &demo_data->ShowMetrics, has_debug_tools); ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools); ImGui::MenuItem("ID Stack Tool", NULL, &demo_data->ShowIDStackTool, has_debug_tools); bool is_debugger_present = io.ConfigDebugIsDebuggerPresent; From 290e402a0206e9c0fb6868f60a007e4f93273d13 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Jan 2025 18:55:09 +0100 Subject: [PATCH 368/548] TreeNode, Tables: added ImGuiTreeNodeFlags_LabelSpanAllColumns. (#8318, #3565) --- docs/CHANGELOG.txt | 4 ++++ imgui.h | 7 ++++--- imgui_demo.cpp | 2 ++ imgui_widgets.cpp | 10 +++++++--- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8d3ced68e2df..8e2a9419a06c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -70,6 +70,10 @@ Other changes: coordinates. - Tables, MultiSelect: Fixed an issue where column width may be mismeasured when calling BeginMultiSelect() while inside a table. (#8250) +- TreeNode, Tables: Added ImGuiTreeNodeFlags_LabelSpanAllColumns to make + the label (not only the frame) also spans all columns. This can be useful + for table rows where you know nothing else is submitted. (#8318, #3565) + Obviously best used with ImGuiTableFlags_NoBordersInBodyUntilResize. - Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to disable keyboard modifiers altering the tweak speed. Useful if you want to alter tweak speed yourself based on your own logic. (#8223) diff --git a/imgui.h b/imgui.h index a89a6c621a23..8e2821643162 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.7 WIP" -#define IMGUI_VERSION_NUM 19165 +#define IMGUI_VERSION_NUM 19166 #define IMGUI_HAS_TABLE /* @@ -1206,9 +1206,10 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode. ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (cover the indent area). ImGuiTreeNodeFlags_SpanTextWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text. - ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (text will still fit in current column) - ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 15, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) + ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (label will still fit in current column) + ImGuiTreeNodeFlags_LabelSpanAllColumns = 1 << 15, // Label will span all columns of its container table //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 16, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible + ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 17, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog, #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4bc70fe425e0..548ce1b05d56 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6363,6 +6363,8 @@ static void ShowDemoWindowTables() ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanFullWidth); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanTextWidth); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags, ImGuiTreeNodeFlags_SpanAllColumns); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_LabelSpanAllColumns", &tree_node_flags, ImGuiTreeNodeFlags_LabelSpanAllColumns); + ImGui::SameLine(); HelpMarker("Useful if you know that you aren't displaying contents in other columns"); HelpMarker("See \"Columns flags\" section to configure how indentation is applied to individual columns."); if (ImGui::BeginTable("3ways", 3, flags)) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 725f6de2aca7..44fe25f1aa5c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6532,6 +6532,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // We vertically grow up to current line height up the typical widget height. const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2); const bool span_all_columns = (flags & ImGuiTreeNodeFlags_SpanAllColumns) != 0 && (g.CurrentTable != NULL); + const bool span_all_columns_label = (flags & ImGuiTreeNodeFlags_LabelSpanAllColumns) != 0 && (g.CurrentTable != NULL); ImRect frame_bb; frame_bb.Min.x = span_all_columns ? window->ParentWorkRect.Min.x : (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x; frame_bb.Min.y = window->DC.CursorPos.y; @@ -6557,7 +6558,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l bool is_open = TreeNodeUpdateNextOpen(storage_id, flags); bool is_visible; - if (span_all_columns) + if (span_all_columns || span_all_columns_label) { // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. const float backup_clip_rect_min_x = window->ClipRect.Min.x; @@ -6598,7 +6599,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l return is_open; } - if (span_all_columns) + if (span_all_columns || span_all_columns_label) { TablePushBackgroundChannel(); g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasClipRect; @@ -6751,7 +6752,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l LogSetNextTextDecoration(">", NULL); } - if (span_all_columns) + if (span_all_columns && !span_all_columns_label) TablePopBackgroundChannel(); // Label @@ -6759,6 +6760,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); else RenderText(text_pos, label, label_end, false); + + if (span_all_columns_label) + TablePopBackgroundChannel(); } if (store_tree_node_stack_data && is_open) From c5f60942bdd9f1fb0ae61f3d82510b0c05c16191 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Jan 2025 19:18:05 +0100 Subject: [PATCH 369/548] Demo: tweak demo for ImGuiTreeNodeFlags_LabelSpanAllColumns. (#8318, #3565) --- imgui_demo.cpp | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 548ce1b05d56..cc8afe388813 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6357,17 +6357,17 @@ static void ShowDemoWindowTables() IMGUI_DEMO_MARKER("Tables/Tree view"); if (ImGui::TreeNode("Tree view")) { - static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody; + static ImGuiTableFlags table_flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody; - static ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAllColumns; - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanFullWidth); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &tree_node_flags, ImGuiTreeNodeFlags_SpanTextWidth); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags, ImGuiTreeNodeFlags_SpanAllColumns); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_LabelSpanAllColumns", &tree_node_flags, ImGuiTreeNodeFlags_LabelSpanAllColumns); + static ImGuiTreeNodeFlags tree_node_flags_base = ImGuiTreeNodeFlags_SpanAllColumns; + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanFullWidth); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanTextWidth); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanAllColumns); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_LabelSpanAllColumns", &tree_node_flags_base, ImGuiTreeNodeFlags_LabelSpanAllColumns); ImGui::SameLine(); HelpMarker("Useful if you know that you aren't displaying contents in other columns"); HelpMarker("See \"Columns flags\" section to configure how indentation is applied to individual columns."); - if (ImGui::BeginTable("3ways", 3, flags)) + if (ImGui::BeginTable("3ways", 3, table_flags)) { // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide); @@ -6388,13 +6388,21 @@ static void ShowDemoWindowTables() ImGui::TableNextRow(); ImGui::TableNextColumn(); const bool is_folder = (node->ChildCount > 0); + + ImGuiTreeNodeFlags node_flags = tree_node_flags_base; + if (node != &all_nodes[0]) + node_flags &= ~ImGuiTreeNodeFlags_LabelSpanAllColumns; // Only demonstrate this on the root node. + if (is_folder) { - bool open = ImGui::TreeNodeEx(node->Name, tree_node_flags); - ImGui::TableNextColumn(); - ImGui::TextDisabled("--"); - ImGui::TableNextColumn(); - ImGui::TextUnformatted(node->Type); + bool open = ImGui::TreeNodeEx(node->Name, node_flags); + if ((node_flags & ImGuiTreeNodeFlags_LabelSpanAllColumns) == 0) + { + ImGui::TableNextColumn(); + ImGui::TextDisabled("--"); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(node->Type); + } if (open) { for (int child_n = 0; child_n < node->ChildCount; child_n++) @@ -6404,7 +6412,7 @@ static void ShowDemoWindowTables() } else { - ImGui::TreeNodeEx(node->Name, tree_node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen); + ImGui::TreeNodeEx(node->Name, node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen); ImGui::TableNextColumn(); ImGui::Text("%d", node->Size); ImGui::TableNextColumn(); @@ -6414,7 +6422,7 @@ static void ShowDemoWindowTables() }; static const MyTreeNode nodes[] = { - { "Root", "Folder", -1, 1, 3 }, // 0 + { "Root with Long Name", "Folder", -1, 1, 3 }, // 0 { "Music", "Folder", -1, 4, 2 }, // 1 { "Textures", "Folder", -1, 6, 3 }, // 2 { "desktop.ini", "System file", 1024, -1,-1 }, // 3 From c38c18c1a072d2f31a15722c81393f0585cef9e7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Jan 2025 19:39:57 +0100 Subject: [PATCH 370/548] Avoid using 1<<31 for ImGuiWindowFlags_NavFlattened as it seems to confuse some binding generators. --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 8e2821643162..c71e7521f635 100644 --- a/imgui.h +++ b/imgui.h @@ -1099,8 +1099,8 @@ enum ImGuiWindowFlags_ // Obsolete names #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + ImGuiWindowFlags_NavFlattened = 1 << 29, // Obsoleted in 1.90.9: Use ImGuiChildFlags_NavFlattened in BeginChild() call. ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90.0: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call. - ImGuiWindowFlags_NavFlattened = 1 << 31, // Obsoleted in 1.90.9: Use ImGuiChildFlags_NavFlattened in BeginChild() call. #endif }; From 21902e2f53602ff85e4f23fe4d974864997f4648 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Jan 2025 19:51:15 +0100 Subject: [PATCH 371/548] Backends: SDL_GPU: fixed SDL_GPUViewport initialisation. (#8163, #7998, #7988) Probably harmless. Amend 8bbccf7 --- backends/imgui_impl_sdlgpu3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/imgui_impl_sdlgpu3.cpp b/backends/imgui_impl_sdlgpu3.cpp index e681efdc39ab..7eb5eeb08fc0 100644 --- a/backends/imgui_impl_sdlgpu3.cpp +++ b/backends/imgui_impl_sdlgpu3.cpp @@ -100,7 +100,7 @@ static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGra viewport.w = (float)fb_width; viewport.h = (float)fb_height; viewport.min_depth = 0.0f; - viewport.min_depth = 1.0f; + viewport.max_depth = 1.0f; SDL_SetGPUViewport(render_pass,&viewport); // Setup scale and translation From 9f8481a842e45c6490a36818841cc8e34ca003c4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Jan 2025 13:14:50 +0100 Subject: [PATCH 372/548] (Breaking) TreeNode: renamed ImGuiTreeNodeFlags_SpanTextWidth to ImGuiTreeNodeFlags_SpanLabelWidth. (#6937) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 1 + imgui.h | 5 +++-- imgui_demo.cpp | 8 ++++---- imgui_widgets.cpp | 4 ++-- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8e2a9419a06c..5e581d0bdc8b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,9 @@ HOW TO UPDATE? Breaking changes: +- TreeNode: renamed ImGuiTreeNodeFlags_SpanTextWidth to ImGuiTreeNodeFlags_SpanLabelWidth + for consistency with other names. Kept redirection enum (will obsolete). (#6937) + Other changes: - Fixed issues with IsItemDeactivated() and IsItemDeactivatedAfterEdit() not diff --git a/imgui.cpp b/imgui.cpp index 6b9f47164400..c0540d697982 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -430,6 +430,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. + - 2025/01/14 (1.91.7) - renamed ImGuiTreeNodeFlags_SpanTextWidth to ImGuiTreeNodeFlags_SpanLabelWidth for consistency with other names. Kept redirection enum (will obsolete). (#6937) - 2024/11/27 (1.91.6) - changed CRC32 table from CRC32-adler to CRC32c polynomial in order to be compatible with the result of SSE 4.2 instructions. As a result, old .ini data may be partially lost (docking and tables information particularly). Because some users have crafted and storing .ini data as a way to workaround limitations of the docking API, we are providing a '#define IMGUI_USE_LEGACY_CRC32_ADLER' compile-time option to keep using old CRC32 tables if you cannot afford invalidating old .ini data. diff --git a/imgui.h b/imgui.h index c71e7521f635..44c1027ec031 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.7 WIP" -#define IMGUI_VERSION_NUM 19166 +#define IMGUI_VERSION_NUM 19167 #define IMGUI_HAS_TABLE /* @@ -1205,7 +1205,7 @@ enum ImGuiTreeNodeFlags_ 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. ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode. ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (cover the indent area). - ImGuiTreeNodeFlags_SpanTextWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text. + ImGuiTreeNodeFlags_SpanLabelWidth = 1 << 13, // Narrow hit box + narrow hovering highlight, will only cover the label text. ImGuiTreeNodeFlags_SpanAllColumns = 1 << 14, // Frame will span all columns of its container table (label will still fit in current column) ImGuiTreeNodeFlags_LabelSpanAllColumns = 1 << 15, // Label will span all columns of its container table //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 16, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible @@ -1214,6 +1214,7 @@ enum ImGuiTreeNodeFlags_ #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7 + ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth,// Renamed in 1.90.7 #endif }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index cc8afe388813..0cb45a508b23 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1122,7 +1122,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node."); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &base_flags, ImGuiTreeNodeFlags_SpanTextWidth); ImGui::SameLine(); HelpMarker("Reduce hit area to the text label and a bit of margin."); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanLabelWidth", &base_flags, ImGuiTreeNodeFlags_SpanLabelWidth); ImGui::SameLine(); HelpMarker("Reduce hit area to the text label and a bit of margin."); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only."); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap", &base_flags, ImGuiTreeNodeFlags_AllowOverlap); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed", &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)"); @@ -1159,9 +1159,9 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::Text("This is a drag and drop source"); ImGui::EndDragDropSource(); } - if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanTextWidth)) + if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanLabelWidth)) { - // Item 2 has an additional inline button to help demonstrate SpanTextWidth. + // Item 2 has an additional inline button to help demonstrate SpanLabelWidth. ImGui::SameLine(); if (ImGui::SmallButton("button")) {} } @@ -6361,7 +6361,7 @@ static void ShowDemoWindowTables() static ImGuiTreeNodeFlags tree_node_flags_base = ImGuiTreeNodeFlags_SpanAllColumns; ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanFullWidth); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanTextWidth); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanLabelWidth", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanLabelWidth); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags_base, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::CheckboxFlags("ImGuiTreeNodeFlags_LabelSpanAllColumns", &tree_node_flags_base, ImGuiTreeNodeFlags_LabelSpanAllColumns); ImGui::SameLine(); HelpMarker("Useful if you know that you aren't displaying contents in other columns"); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 44fe25f1aa5c..7fc082df3f9e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6536,7 +6536,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l ImRect frame_bb; frame_bb.Min.x = span_all_columns ? window->ParentWorkRect.Min.x : (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x; frame_bb.Min.y = window->DC.CursorPos.y; - frame_bb.Max.x = span_all_columns ? window->ParentWorkRect.Max.x : (flags & ImGuiTreeNodeFlags_SpanTextWidth) ? window->DC.CursorPos.x + text_width + padding.x : window->WorkRect.Max.x; + frame_bb.Max.x = span_all_columns ? window->ParentWorkRect.Max.x : (flags & ImGuiTreeNodeFlags_SpanLabelWidth) ? window->DC.CursorPos.x + text_width + padding.x : window->WorkRect.Max.x; frame_bb.Max.y = window->DC.CursorPos.y + frame_height; if (display_frame) { @@ -6550,7 +6550,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing ImRect interact_bb = frame_bb; - if ((flags & (ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanTextWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0) + if ((flags & (ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanLabelWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0) interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f); // Compute open and multi-select states before ItemAdd() as it clear NextItem data. From 5c1d2d1e4c562a2ed3efbc64476e703a655b45fd Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Jan 2025 13:16:43 +0100 Subject: [PATCH 373/548] Version 1.91.7 --- docs/CHANGELOG.txt | 22 ++++++++++++---------- 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, 21 insertions(+), 19 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5e581d0bdc8b..462de35fb3df 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,9 +36,11 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.91.7 WIP (In Progress) + VERSION 1.91.7 (Released 2025-01-14) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.7 + Breaking changes: - TreeNode: renamed ImGuiTreeNodeFlags_SpanTextWidth to ImGuiTreeNodeFlags_SpanLabelWidth @@ -59,9 +61,9 @@ Other changes: a child window, and from nested child windows. (#1651) - Error Handling: Turned common EndTable() and other TableXXX functions fail cases into a recoverable error. (#1651, #8314) -- Error Handling: Exposed some options in Demo->Tools->Debug Options. (#1651) +- Error Handling: Basic error handling options in Demo->Tools->Debug Options. (#1651) - InputText: Fixed a bug where character replacements performed from a callback - were not applied when pasting from clipbard. (#8229) + were not applied when pasting from clipboard. (#8229) - InputText: Fixed issue when activating a ReadOnly field when the underlying value is being modified. (#8242) - InputText: Added sanity check to detect some cases of passing a non @@ -70,12 +72,12 @@ Other changes: although IsItemEdited() was behaving correctly. (#8273) - Tables: Fixed TableAngledHeadersRow() creating an infinite horizontal scrolling region when the table is hosted in a viewport with negative - coordinates. + coordinates (left of primary monitor, with multi-viewports enabled). - Tables, MultiSelect: Fixed an issue where column width may be mismeasured when calling BeginMultiSelect() while inside a table. (#8250) - TreeNode, Tables: Added ImGuiTreeNodeFlags_LabelSpanAllColumns to make - the label (not only the frame) also spans all columns. This can be useful - for table rows where you know nothing else is submitted. (#8318, #3565) + the label (not only the highlight/frame) also spans all columns. This is + useful for table rows where you know nothing else is submitted. (#8318, #3565) Obviously best used with ImGuiTableFlags_NoBordersInBodyUntilResize. - Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to disable keyboard modifiers altering the tweak speed. Useful if you want to alter tweak speed @@ -84,13 +86,13 @@ Other changes: windows with the ImGuiWindowFlags_NoNavInputs flag. (#8231) - Debug Tools: Debug Log: hovering 0xXXXXXXXX values in log is allowed even if a popup is blocking mouse access to the debug log window. (#5855) -- Debug Tools: Item Picker: Always available regardless of value of - io.ConfigDebugIsDebuggerPresent. (#2673) +- Debug Tools: Item Picker: Always available in Tools menu regardless of value + of io.ConfigDebugIsDebuggerPresent. (#2673) - Fonts: Fixed miscalculation of Ellipsis ("...") character width when automatically created from a single comma character, affecting some fonts/settings (not all). - Demo: Added label edition to Property Editor demo + fix an ID issue. (#8266) [@moritz-h] - Misc: Fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] -- Misc: Fixed MinGW builds uses UTF-8 friendly _wfopen(). (#8300) +- Misc: Fixed MinGW builds not using UTF-8 friendly _wfopen(). (#8300) - Backends: SDL_GPU for SDL3: Added backend for SDL_GPU! (#8163, #7998, #7988) [@DeltaW0x]. - Backends: SDL3: Added ImGui_ImplSDL3_InitForSDLGPU() for consistency, even though it is currently not doing anything particular. (#8163, #7998, #7988) @@ -105,7 +107,7 @@ Other changes: - Backends: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in the provided descriptor pool. Current backend needs 1 but it is expected that by end of Q1 2025 - this number will grow (will staying a very small number). (#6642) + this number will grow (will stay a small number). (#6642) - Backends: DX11: Expose vertex constant buffer in ImGui_ImplDX11_RenderState. Reset projection matrix in ImDrawCallback_ResetRenderState handlers. (#6969, #5834, #7468, #3590) - Backends: DX10: Expose ImGui_ImplDX10_RenderState for completeness. (#6969, #5834, #7468, #3590) diff --git a/imgui.cpp b/imgui.cpp index c0540d697982..63dbd1fe8ae4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 WIP +// dear imgui, v1.91.7 // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 44c1027ec031..0f7bdbbc6bfb 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 WIP +// dear imgui, v1.91.7 // (headers) // Help: @@ -28,8 +28,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.7 WIP" -#define IMGUI_VERSION_NUM 19167 +#define IMGUI_VERSION "1.91.7" +#define IMGUI_VERSION_NUM 19170 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0cb45a508b23..d0e41f370cf2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 WIP +// dear imgui, v1.91.7 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 8baaf8b11767..344eae9e8a40 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 WIP +// dear imgui, v1.91.7 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index bb5a5677460e..f3f915d7ead2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 WIP +// dear imgui, v1.91.7 // (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 ec25bf906022..efef5ff74347 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 WIP +// dear imgui, v1.91.7 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7fc082df3f9e..dd27400cd156 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 WIP +// dear imgui, v1.91.7 // (widgets code) /* From c59a2267d0977d7261a78c884ccf7735345c4060 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 15 Jan 2025 11:58:47 +0100 Subject: [PATCH 374/548] Version 1.91.8 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 462de35fb3df..373dcd1082b2 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.8 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking changes: + +Other changes: + + ----------------------------------------------------------------------- VERSION 1.91.7 (Released 2025-01-14) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 63dbd1fe8ae4..678ff2e522f0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 +// dear imgui, v1.91.8 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 0f7bdbbc6bfb..cd7c925930ae 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 +// dear imgui, v1.91.8 WIP // (headers) // Help: @@ -28,8 +28,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.7" -#define IMGUI_VERSION_NUM 19170 +#define IMGUI_VERSION "1.91.8 WIP" +#define IMGUI_VERSION_NUM 19171 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d0e41f370cf2..26c246db68a9 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 +// dear imgui, v1.91.8 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 344eae9e8a40..e8c445dd30b3 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 +// dear imgui, v1.91.8 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index f3f915d7ead2..9db5fde5e2f8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 +// dear imgui, v1.91.8 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 efef5ff74347..e0df575c440c 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 +// dear imgui, v1.91.8 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index dd27400cd156..71a5c5b9a00e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.7 +// dear imgui, v1.91.8 WIP // (widgets code) /* From 100075f2be6a16d6569f6c591c2a908394f414eb Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 15 Jan 2025 12:05:33 +0100 Subject: [PATCH 375/548] Backends: DirectX12: Texture upload use the command queue provided in ImGui_ImplDX12_InitInfo instead of creating its own. + minor tweaks to faciliate branch merging. --- backends/imgui_impl_dx12.cpp | 53 ++++++++++++++++-------------------- docs/CHANGELOG.txt | 3 ++ imgui.cpp | 1 + 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 24fdb7aa0025..6f17f587aff9 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-01-15: DirectX12: Texture upload use the command queue provided in ImGui_ImplDX12_InitInfo instead of creating its own. // 2024-12-09: DirectX12: Let user specifies the DepthStencilView format by setting ImGui_ImplDX12_InitInfo::DSVFormat. // 2024-11-15: DirectX12: *BREAKING CHANGE* Changed ImGui_ImplDX12_Init() signature to take a ImGui_ImplDX12_InitInfo struct. Legacy ImGui_ImplDX12_Init() signature is still supported (will obsolete). // 2024-11-15: DirectX12: *BREAKING CHANGE* User is now required to pass function pointers to allocate/free SRV Descriptors. We provide convenience legacy fields to pass a single descriptor, matching the old API, but upcoming features will want multiple. @@ -64,6 +65,8 @@ struct ImGui_ImplDX12_Texture ID3D12Resource* pTextureResource; D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle; D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle; + + ImGui_ImplDX12_Texture() { memset((void*)this, 0, sizeof(*this)); } }; struct ImGui_ImplDX12_Data @@ -180,8 +183,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) return; - // FIXME: I'm assuming that this only gets called once per frame! - // If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator. + // FIXME: We are assuming that this only gets called once per frame! ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); bd->frameIndex = bd->frameIndex + 1; ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[bd->frameIndex % bd->numFramesInFlight]; @@ -352,11 +354,11 @@ static void ImGui_ImplDX12_CreateFontsTexture() bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&pTexture)); - UINT uploadPitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u); - UINT uploadSize = height * uploadPitch; + UINT upload_pitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u); + UINT upload_size = height * upload_pitch; desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; desc.Alignment = 0; - desc.Width = uploadSize; + desc.Width = upload_size; desc.Height = 1; desc.DepthOrArraySize = 1; desc.MipLevels = 1; @@ -376,26 +378,28 @@ static void ImGui_ImplDX12_CreateFontsTexture() IM_ASSERT(SUCCEEDED(hr)); void* mapped = nullptr; - D3D12_RANGE range = { 0, uploadSize }; + D3D12_RANGE range = { 0, upload_size }; hr = uploadBuffer->Map(0, &range, &mapped); IM_ASSERT(SUCCEEDED(hr)); for (int y = 0; y < height; y++) - memcpy((void*) ((uintptr_t) mapped + y * uploadPitch), pixels + y * width * 4, width * 4); + memcpy((void*) ((uintptr_t) mapped + y * upload_pitch), pixels + y * width * 4, width * 4); uploadBuffer->Unmap(0, &range); D3D12_TEXTURE_COPY_LOCATION srcLocation = {}; - srcLocation.pResource = uploadBuffer; - srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srcLocation.PlacedFootprint.Footprint.Width = width; - srcLocation.PlacedFootprint.Footprint.Height = height; - srcLocation.PlacedFootprint.Footprint.Depth = 1; - srcLocation.PlacedFootprint.Footprint.RowPitch = uploadPitch; - D3D12_TEXTURE_COPY_LOCATION dstLocation = {}; - dstLocation.pResource = pTexture; - dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - dstLocation.SubresourceIndex = 0; + { + srcLocation.pResource = uploadBuffer; + srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srcLocation.PlacedFootprint.Footprint.Width = width; + srcLocation.PlacedFootprint.Footprint.Height = height; + srcLocation.PlacedFootprint.Footprint.Depth = 1; + srcLocation.PlacedFootprint.Footprint.RowPitch = upload_pitch; + + dstLocation.pResource = pTexture; + dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dstLocation.SubresourceIndex = 0; + } D3D12_RESOURCE_BARRIER barrier = {}; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; @@ -412,15 +416,6 @@ static void ImGui_ImplDX12_CreateFontsTexture() HANDLE event = ::CreateEvent(0, 0, 0, 0); IM_ASSERT(event != nullptr); - D3D12_COMMAND_QUEUE_DESC queueDesc = {}; - queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; - queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; - queueDesc.NodeMask = 1; - - ID3D12CommandQueue* cmdQueue = nullptr; - hr = bd->pd3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue)); - IM_ASSERT(SUCCEEDED(hr)); - ID3D12CommandAllocator* cmdAlloc = nullptr; hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc)); IM_ASSERT(SUCCEEDED(hr)); @@ -435,6 +430,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() hr = cmdList->Close(); IM_ASSERT(SUCCEEDED(hr)); + ID3D12CommandQueue* cmdQueue = bd->InitInfo.CommandQueue; cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList); hr = cmdQueue->Signal(fence, 1); IM_ASSERT(SUCCEEDED(hr)); @@ -444,7 +440,6 @@ static void ImGui_ImplDX12_CreateFontsTexture() cmdList->Release(); cmdAlloc->Release(); - cmdQueue->Release(); ::CloseHandle(event); fence->Release(); uploadBuffer->Release(); @@ -707,11 +702,11 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() if (!bd || !bd->pd3dDevice) return; - ImGuiIO& io = ImGui::GetIO(); SafeRelease(bd->pRootSignature); SafeRelease(bd->pPipelineState); // Free SRV descriptor used by texture + ImGuiIO& io = ImGui::GetIO(); ImGui_ImplDX12_Texture* font_tex = &bd->FontTexture; bd->InitInfo.SrvDescriptorFreeFn(&bd->InitInfo, font_tex->hFontSrvCpuDescHandle, font_tex->hFontSrvGpuDescHandle); SafeRelease(font_tex->pTextureResource); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 373dcd1082b2..7b0f545ee9a8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,9 @@ Breaking changes: Other changes: +- Backends: DirectX12: Texture upload use the command queue provided in + ImGui_ImplDX12_InitInfo instead of creating its own. + ----------------------------------------------------------------------- VERSION 1.91.7 (Released 2025-01-14) diff --git a/imgui.cpp b/imgui.cpp index 678ff2e522f0..009a9abf1f16 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5086,6 +5086,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() } // Called once a frame. Followed by SetCurrentFont() which sets up the remaining data. +// FIXME-VIEWPORT: the concept of a single ClipRectFullscreen is not ideal! static void SetupDrawListSharedData() { ImGuiContext& g = *GImGui; From 8a9de84cd0130110ce6d1411558a8d59d7169ae3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 15 Jan 2025 13:47:52 +0100 Subject: [PATCH 376/548] FontAtlas: reduced baked IM_DRAWLIST_TEX_LINES_WIDTH_MAX from 63 to 32. (#3245) --- docs/CHANGELOG.txt | 1 + imgui.h | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7b0f545ee9a8..0ca9af5a249a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,7 @@ Breaking changes: Other changes: +- ImDrawList: texture baked storage for thick line reduced from ~64x64 to ~32x32. (#3245) - Backends: DirectX12: Texture upload use the command queue provided in ImGui_ImplDX12_InitInfo instead of creating its own. diff --git a/imgui.h b/imgui.h index cd7c925930ae..d4c8edb365fd 100644 --- a/imgui.h +++ b/imgui.h @@ -2923,7 +2923,7 @@ struct ImGuiSelectionExternalStorage // The maximum line width to bake anti-aliased textures for. Build atlas with ImFontAtlasFlags_NoBakedLines to disable baking. #ifndef IM_DRAWLIST_TEX_LINES_WIDTH_MAX -#define IM_DRAWLIST_TEX_LINES_WIDTH_MAX (63) +#define IM_DRAWLIST_TEX_LINES_WIDTH_MAX (32) #endif // ImDrawCallback: Draw callbacks for advanced uses [configurable type: override in imconfig.h] @@ -2997,7 +2997,6 @@ struct ImDrawChannel ImVector _IdxBuffer; }; - // Split/Merge functions are used to split the draw list into different layers which can be drawn into out of order. // This is used by the Columns/Tables API, so items of each column can be batched together in a same draw call. struct ImDrawListSplitter From 0e21bde77b0647b872cc4e571b3c05f54d2e556e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 15 Jan 2025 13:58:38 +0100 Subject: [PATCH 377/548] Misc shallow merge to reduce diff in other branches. --- backends/imgui_impl_dx10.cpp | 2 +- backends/imgui_impl_opengl2.cpp | 12 +++++++++++- imgui.h | 8 +++++--- imgui_internal.h | 8 ++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 89499af0cbaa..5471eef5311c 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -47,7 +47,7 @@ #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. #endif -// DirectX data +// DirectX10 data struct ImGui_ImplDX10_Data { ID3D10Device* pd3dDevice; diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index 767731fb39ea..2a255be4c7f7 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -69,6 +69,16 @@ #include #endif +// [Debugging] +//#define IMGUI_IMPL_OPENGL_DEBUG +#ifdef IMGUI_IMPL_OPENGL_DEBUG +#include +#define GL_CALL(_CALL) do { _CALL; GLenum gl_err = glGetError(); if (gl_err != 0) fprintf(stderr, "GL error 0x%x returned from '%s'.\n", gl_err, #_CALL); } while (0) // Call with error check +#else +#define GL_CALL(_CALL) _CALL // Call without error check +#endif + +// OpenGL data struct ImGui_ImplOpenGL2_Data { GLuint FontTexture; @@ -155,7 +165,7 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid // Setup viewport, orthographic projection matrix // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. - glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); + GL_CALL(glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height)); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); diff --git a/imgui.h b/imgui.h index d4c8edb365fd..b9a4fe1581b0 100644 --- a/imgui.h +++ b/imgui.h @@ -158,7 +158,7 @@ typedef unsigned int ImU32; // 32-bit unsigned integer (often used to st typedef signed long long ImS64; // 64-bit signed integer typedef unsigned long long ImU64; // 64-bit unsigned integer -// Forward declarations +// Forward declarations: ImDrawList, ImFontAtlas layer struct ImDrawChannel; // Temporary storage to output draw commands out of order, used by ImDrawListSplitter and ImDrawList::ChannelsSplit() struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call, unless it is a callback) struct ImDrawData; // All draw command lists required to render the frame + pos/size coordinates to use for the projection matrix. @@ -173,6 +173,8 @@ struct ImFontConfig; // Configuration data when adding a font or struct ImFontGlyph; // A single font glyph (code point + coordinates within in ImFontAtlas + offset) struct ImFontGlyphRangesBuilder; // Helper to build glyph ranges from text/string data struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*OBSOLETE* please avoid using) + +// Forward declarations: ImGui layer struct ImGuiContext; // Dear ImGui context (opaque structure, unless including imgui_internal.h) struct ImGuiIO; // Main configuration and I/O between your application and ImGui (also see: ImGuiPlatformIO) struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use) @@ -3374,7 +3376,7 @@ struct ImFontAtlas IMGUI_API const ImWchar* GetGlyphRangesVietnamese(); // Default + Vietnamese characters //------------------------------------------- - // [BETA] Custom Rectangles/Glyphs API + // [ALPHA] Custom Rectangles/Glyphs API //------------------------------------------- // You can request arbitrary rectangles to be packed into the atlas, for your own purposes. @@ -3400,11 +3402,11 @@ struct ImFontAtlas ImTextureID TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure. int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. int TexGlyphPadding; // FIXME: Should be called "TexPackPadding". Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0 (will also need to set AntiAliasedLinesUseTex = false). - bool Locked; // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert. void* UserData; // Store your own atlas related user-data (if e.g. you have multiple font atlas). // [Internal] // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you. + bool Locked; // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert. bool TexReady; // Set when texture was built matching current font input bool TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format. unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight diff --git a/imgui_internal.h b/imgui_internal.h index 9db5fde5e2f8..12d8f7a51b7a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -130,10 +130,17 @@ Index of this file: // [SECTION] Forward declarations //----------------------------------------------------------------------------- +// Utilities +// (other types which are not forwarded declared are: ImBitArray<>, ImSpan<>, ImSpanAllocator<>, ImPool<>, ImChunkStream<>) struct ImBitVector; // Store 1-bit per value struct ImRect; // An axis-aligned rectangle (2 points) +struct ImGuiTextIndex; // Maintain a line index for a text buffer. + +// ImDrawList/ImFontAtlas struct ImDrawDataBuilder; // Helper to build a ImDrawData instance struct ImDrawListSharedData; // Data shared between all ImDrawList instances + +// ImGui struct ImGuiBoxSelectState; // Box-selection state (currently used by multi-selection, could potentially be used by others) struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it struct ImGuiContext; // Main Dear ImGui context @@ -736,6 +743,7 @@ struct ImGuiTextIndex // Helper: ImGuiStorage IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_end, ImGuiID key); + //----------------------------------------------------------------------------- // [SECTION] ImDrawList support //----------------------------------------------------------------------------- From 6684984c49bf2975b2f1e257daf0cd216d55f1e8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 15 Jan 2025 15:13:05 +0100 Subject: [PATCH 378/548] Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in provided example, to reduce latency. --- docs/CHANGELOG.txt | 2 ++ examples/example_win32_directx12/main.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0ca9af5a249a..27e447ec30e4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -44,6 +44,8 @@ Breaking changes: Other changes: - ImDrawList: texture baked storage for thick line reduced from ~64x64 to ~32x32. (#3245) +- Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in + provided example, to reduce latency. - Backends: DirectX12: Texture upload use the command queue provided in ImGui_ImplDX12_InitInfo instead of creating its own. diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index 392ba18aab14..5b1a7af370bf 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -23,8 +23,8 @@ #endif // Config for example app -static const int APP_NUM_FRAMES_IN_FLIGHT = 3; -static const int APP_NUM_BACK_BUFFERS = 3; +static const int APP_NUM_FRAMES_IN_FLIGHT = 2; +static const int APP_NUM_BACK_BUFFERS = 2; static const int APP_SRV_HEAP_SIZE = 64; struct FrameContext From 8ebf22d3c11ee89840d43f415cb48c947908a927 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 15 Jan 2025 16:10:47 +0100 Subject: [PATCH 379/548] Backends: Vulkan: use ImVector<> for simplicity. --- backends/imgui_impl_vulkan.cpp | 32 +++++++++++++------------------- backends/imgui_impl_vulkan.h | 4 ++-- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 940ea2d79b15..f4bd50694d22 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -216,7 +216,7 @@ struct ImGui_ImplVulkan_WindowRenderBuffers { uint32_t Index; uint32_t Count; - ImGui_ImplVulkan_FrameRenderBuffers* FrameRenderBuffers; + ImVector FrameRenderBuffers; }; struct ImGui_ImplVulkan_Texture @@ -501,12 +501,12 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm // Allocate array to store enough vertex/index buffers ImGui_ImplVulkan_WindowRenderBuffers* wrb = &bd->MainWindowRenderBuffers; - if (wrb->FrameRenderBuffers == nullptr) + if (wrb->FrameRenderBuffers.Size == 0) { wrb->Index = 0; wrb->Count = v->ImageCount; - wrb->FrameRenderBuffers = (ImGui_ImplVulkan_FrameRenderBuffers*)IM_ALLOC(sizeof(ImGui_ImplVulkan_FrameRenderBuffers) * wrb->Count); - memset((void*)wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkan_FrameRenderBuffers) * wrb->Count); + wrb->FrameRenderBuffers.resize(wrb->Count); + memset((void*)wrb->FrameRenderBuffers.Data, 0, wrb->FrameRenderBuffers.size_in_bytes()); } IM_ASSERT(wrb->Count == v->ImageCount); wrb->Index = (wrb->Index + 1) % wrb->Count; @@ -1250,8 +1250,7 @@ void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulk { for (uint32_t n = 0; n < buffers->Count; n++) ImGui_ImplVulkan_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator); - IM_FREE(buffers->FrameRenderBuffers); - buffers->FrameRenderBuffers = nullptr; + buffers->FrameRenderBuffers.clear(); buffers->Index = 0; buffers->Count = 0; } @@ -1460,10 +1459,8 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator); for (uint32_t i = 0; i < wd->SemaphoreCount; i++) ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator); - IM_FREE(wd->Frames); - IM_FREE(wd->FrameSemaphores); - wd->Frames = nullptr; - wd->FrameSemaphores = nullptr; + wd->Frames.clear(); + wd->FrameSemaphores.clear(); wd->ImageCount = 0; if (wd->RenderPass) vkDestroyRenderPass(device, wd->RenderPass, allocator); @@ -1518,12 +1515,11 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers); check_vk_result(err); - IM_ASSERT(wd->Frames == nullptr && wd->FrameSemaphores == nullptr); wd->SemaphoreCount = wd->ImageCount + 1; - wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount); - wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->SemaphoreCount); - memset((void*)wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount); - memset((void*)wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->SemaphoreCount); + wd->Frames.resize(wd->ImageCount); + wd->FrameSemaphores.resize(wd->SemaphoreCount); + memset(wd->Frames.Data, 0, wd->Frames.size_in_bytes()); + memset(wd->FrameSemaphores.Data, 0, wd->FrameSemaphores.size_in_bytes()); for (uint32_t i = 0; i < wd->ImageCount; i++) wd->Frames[i].Backbuffer = backbuffers[i]; } @@ -1633,10 +1629,8 @@ void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator); for (uint32_t i = 0; i < wd->SemaphoreCount; i++) ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator); - IM_FREE(wd->Frames); - IM_FREE(wd->FrameSemaphores); - wd->Frames = nullptr; - wd->FrameSemaphores = nullptr; + wd->Frames.clear(); + wd->FrameSemaphores.clear(); vkDestroyPipeline(device, wd->Pipeline, allocator); vkDestroyRenderPass(device, wd->RenderPass, allocator); vkDestroySwapchainKHR(device, wd->Swapchain, allocator); diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 3bd9948647c3..6f4839c1301b 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -207,8 +207,8 @@ struct ImGui_ImplVulkanH_Window uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count) uint32_t SemaphoreCount; // Number of simultaneous in-flight frames + 1, to be able to use it in vkAcquireNextImageKHR uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data) - ImGui_ImplVulkanH_Frame* Frames; - ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores; + ImVector Frames; + ImVector FrameSemaphores; ImGui_ImplVulkanH_Window() { From 0f33d7185fefb5351858e288eb28da698867d461 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 15 Jan 2025 17:25:44 +0100 Subject: [PATCH 380/548] Examples: Vulkan: vkAcquireNextImageKHR() and vkQueuePresentKHR() returning VK_SUBOPTIMAL_KHR keeps moving forward. (#7825, #7831) --- docs/CHANGELOG.txt | 2 ++ examples/example_glfw_vulkan/main.cpp | 18 ++++++++---------- examples/example_sdl2_vulkan/main.cpp | 18 ++++++++---------- examples/example_sdl3_vulkan/main.cpp | 18 ++++++++---------- examples/example_win32_vulkan/main.cpp | 18 ++++++++---------- 5 files changed, 34 insertions(+), 40 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 27e447ec30e4..429785637549 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -46,6 +46,8 @@ Other changes: - ImDrawList: texture baked storage for thick line reduced from ~64x64 to ~32x32. (#3245) - Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in provided example, to reduce latency. +- Examples: Vulkan: better handle VK_SUBOPTIMAL_KHR being returned by + vkAcquireNextImageKHR() or vkQueuePresentKHR(). (#7825, #7831) [@NostraMagister] - Backends: DirectX12: Texture upload use the command queue provided in ImGui_ImplDX12_InitInfo instead of creating its own. diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index b61dcaae0088..31da972dfcf0 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -61,7 +61,7 @@ static void glfw_error_callback(int error, const char* description) } static void check_vk_result(VkResult err) { - if (err == 0) + if (err == VK_SUCCESS) return; fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err); if (err < 0) @@ -263,17 +263,15 @@ static void CleanupVulkanWindow() static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data) { - VkResult err; - VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; - err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); + VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) - { g_SwapChainRebuild = true; + if (err == VK_ERROR_OUT_OF_DATE_KHR) return; - } - check_vk_result(err); + if (err != VK_SUBOPTIMAL_KHR) + check_vk_result(err); ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; { @@ -342,11 +340,11 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) info.pImageIndices = &wd->FrameIndex; VkResult err = vkQueuePresentKHR(g_Queue, &info); if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) - { g_SwapChainRebuild = true; + if (err == VK_ERROR_OUT_OF_DATE_KHR) return; - } - check_vk_result(err); + if (err != VK_SUBOPTIMAL_KHR) + check_vk_result(err); wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores } diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index b82ed0b7ace8..0d7a4586e0c8 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -49,7 +49,7 @@ static bool g_SwapChainRebuild = false; static void check_vk_result(VkResult err) { - if (err == 0) + if (err == VK_SUCCESS) return; fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err); if (err < 0) @@ -251,17 +251,15 @@ static void CleanupVulkanWindow() static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data) { - VkResult err; - VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; - err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); + VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) - { g_SwapChainRebuild = true; + if (err == VK_ERROR_OUT_OF_DATE_KHR) return; - } - check_vk_result(err); + if (err != VK_SUBOPTIMAL_KHR) + check_vk_result(err); ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; { @@ -330,11 +328,11 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) info.pImageIndices = &wd->FrameIndex; VkResult err = vkQueuePresentKHR(g_Queue, &info); if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) - { g_SwapChainRebuild = true; + if (err == VK_ERROR_OUT_OF_DATE_KHR) return; - } - check_vk_result(err); + if (err != VK_SUBOPTIMAL_KHR) + check_vk_result(err); wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores } diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index e36f87194ead..81f0581e97a9 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -54,7 +54,7 @@ static bool g_SwapChainRebuild = false; static void check_vk_result(VkResult err) { - if (err == 0) + if (err == VK_SUCCESS) return; fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err); if (err < 0) @@ -256,17 +256,15 @@ static void CleanupVulkanWindow() static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data) { - VkResult err; - VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; - err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); + VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) - { g_SwapChainRebuild = true; + if (err == VK_ERROR_OUT_OF_DATE_KHR) return; - } - check_vk_result(err); + if (err != VK_SUBOPTIMAL_KHR) + check_vk_result(err); ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; { @@ -335,11 +333,11 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) info.pImageIndices = &wd->FrameIndex; VkResult err = vkQueuePresentKHR(g_Queue, &info); if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) - { g_SwapChainRebuild = true; + if (err == VK_ERROR_OUT_OF_DATE_KHR) return; - } - check_vk_result(err); + if (err != VK_SUBOPTIMAL_KHR) + check_vk_result(err); wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores } diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp index c6c138695a13..f337d8e7de5a 100644 --- a/examples/example_win32_vulkan/main.cpp +++ b/examples/example_win32_vulkan/main.cpp @@ -50,7 +50,7 @@ static bool g_SwapChainRebuild = false; static void check_vk_result(VkResult err) { - if (err == 0) + if (err == VK_SUCCESS) return; fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err); if (err < 0) @@ -252,17 +252,15 @@ static void CleanupVulkanWindow() static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data) { - VkResult err; - VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore; VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; - err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); + VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex); if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) - { g_SwapChainRebuild = true; + if (err == VK_ERROR_OUT_OF_DATE_KHR) return; - } - check_vk_result(err); + if (err != VK_SUBOPTIMAL_KHR) + check_vk_result(err); ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex]; { @@ -331,11 +329,11 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) info.pImageIndices = &wd->FrameIndex; VkResult err = vkQueuePresentKHR(g_Queue, &info); if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR) - { g_SwapChainRebuild = true; + if (err == VK_ERROR_OUT_OF_DATE_KHR) return; - } - check_vk_result(err); + if (err != VK_SUBOPTIMAL_KHR) + check_vk_result(err); wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores } From b4a5d1dc531254d7079c3bebdc564fa5817c3be7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 16 Jan 2025 12:42:54 +0100 Subject: [PATCH 381/548] Backends: SDLGPU3: Rename GpuDevice->Device. Expose ImGui_ImplSDLGPU3_CreateDeviceObjects(), ImGui_ImplSDLGPU3_DestroyDeviceObjects(). Misc renaming. (#8163, #7998, #7988) --- backends/imgui_impl_sdlgpu3.cpp | 127 ++++++++++++------------- backends/imgui_impl_sdlgpu3.h | 19 ++-- docs/CHANGELOG.txt | 7 +- examples/example_sdl3_sdlgpu3/main.cpp | 2 +- 4 files changed, 80 insertions(+), 75 deletions(-) diff --git a/backends/imgui_impl_sdlgpu3.cpp b/backends/imgui_impl_sdlgpu3.cpp index 7eb5eeb08fc0..b508e091aa31 100644 --- a/backends/imgui_impl_sdlgpu3.cpp +++ b/backends/imgui_impl_sdlgpu3.cpp @@ -21,13 +21,16 @@ // Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info. // CHANGELOG -// 2025-01-09: SDL_Gpu: Added the SDL_GPU3 backend. +// 2025-01-16: Renamed ImGui_ImplSDLGPU3_InitInfo::GpuDevice to Device. +// 2025-01-09: SDL_GPU: Added the SDL_GPU3 backend. #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_impl_sdlgpu3.h" #include "imgui_impl_sdlgpu3_shaders.h" +// SDL_GPU Data + // Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplSDLGPU3_RenderDrawData() struct ImGui_ImplSDLGPU3_FrameData { @@ -37,10 +40,9 @@ struct ImGui_ImplSDLGPU3_FrameData uint32_t IndexBufferSize = 0; }; -// SDL_GPU Data struct ImGui_ImplSDLGPU3_Data { - ImGui_ImplSDLGPU3_InitInfo GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo InitInfo; // Graphics pipeline & shaders SDL_GPUShader* VertexShader = nullptr; @@ -57,8 +59,6 @@ struct ImGui_ImplSDLGPU3_Data }; // Forward Declarations -static bool ImGui_ImplSDLGPU3_CreateDeviceObjects(); -static void ImGui_ImplSDLGPU3_DestroyDeviceObjects(); static void ImGui_ImplSDLGPU3_DestroyFrameData(); //----------------------------------------------------------------------------- @@ -116,16 +116,16 @@ static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGra static void CreateOrResizeBuffer(SDL_GPUBuffer** buffer, uint32_t* old_size, uint32_t new_size, SDL_GPUBufferUsageFlags usage) { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo; - SDL_WaitForGPUIdle(v->GpuDevice); - SDL_ReleaseGPUBuffer(v->GpuDevice, *buffer); + SDL_WaitForGPUIdle(v->Device); + SDL_ReleaseGPUBuffer(v->Device, *buffer); SDL_GPUBufferCreateInfo buffer_info = {}; buffer_info.usage = usage; buffer_info.size = new_size; buffer_info.props = 0; - *buffer = SDL_CreateGPUBuffer(v->GpuDevice, &buffer_info); + *buffer = SDL_CreateGPUBuffer(v->Device, &buffer_info); *old_size = new_size; IM_ASSERT(*buffer != nullptr && "Failed to create GPU Buffer, call SDL_GetError() for more information"); } @@ -142,7 +142,7 @@ void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff return; ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo; ImGui_ImplSDLGPU3_FrameData* fd = &bd->MainWindowFrameData; uint32_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); @@ -160,13 +160,13 @@ void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff index_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; index_transferbuffer_info.size = index_size; - SDL_GPUTransferBuffer* vertex_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice, &vertex_transferbuffer_info); + SDL_GPUTransferBuffer* vertex_transferbuffer = SDL_CreateGPUTransferBuffer(v->Device, &vertex_transferbuffer_info); IM_ASSERT(vertex_transferbuffer != nullptr && "Failed to create the vertex transfer buffer, call SDL_GetError() for more information"); - SDL_GPUTransferBuffer* index_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice, &index_transferbuffer_info); + SDL_GPUTransferBuffer* index_transferbuffer = SDL_CreateGPUTransferBuffer(v->Device, &index_transferbuffer_info); IM_ASSERT(index_transferbuffer != nullptr && "Failed to create the index transfer buffer, call SDL_GetError() for more information"); - ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer(v->GpuDevice, vertex_transferbuffer, true); - ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer(v->GpuDevice, index_transferbuffer, true); + ImDrawVert* vtx_dst = (ImDrawVert*)SDL_MapGPUTransferBuffer(v->Device, vertex_transferbuffer, true); + ImDrawIdx* idx_dst = (ImDrawIdx*)SDL_MapGPUTransferBuffer(v->Device, index_transferbuffer, true); for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* draw_list = draw_data->CmdLists[n]; @@ -175,8 +175,8 @@ void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff vtx_dst += draw_list->VtxBuffer.Size; idx_dst += draw_list->IdxBuffer.Size; } - SDL_UnmapGPUTransferBuffer(v->GpuDevice, vertex_transferbuffer); - SDL_UnmapGPUTransferBuffer(v->GpuDevice, index_transferbuffer); + SDL_UnmapGPUTransferBuffer(v->Device, vertex_transferbuffer); + SDL_UnmapGPUTransferBuffer(v->Device, index_transferbuffer); SDL_GPUTransferBufferLocation vertex_buffer_location = {}; vertex_buffer_location.offset = 0; @@ -199,8 +199,8 @@ void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff SDL_UploadToGPUBuffer(copy_pass, &vertex_buffer_location, &vertex_buffer_region,true); SDL_UploadToGPUBuffer(copy_pass, &index_buffer_location, &index_buffer_region,true); SDL_EndGPUCopyPass(copy_pass); - SDL_ReleaseGPUTransferBuffer(v->GpuDevice, index_transferbuffer); - SDL_ReleaseGPUTransferBuffer(v->GpuDevice, vertex_transferbuffer); + SDL_ReleaseGPUTransferBuffer(v->Device, index_transferbuffer); + SDL_ReleaseGPUTransferBuffer(v->Device, vertex_transferbuffer); } void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline) @@ -278,16 +278,16 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe SDL_SetGPUScissor(render_pass, &scissor_rect); } -bool ImGui_ImplSDLGPU3_CreateFontsTexture() +void ImGui_ImplSDLGPU3_CreateFontsTexture() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo; // Destroy existing texture (if any) if (bd->FontTexture) { - SDL_WaitForGPUIdle(v->GpuDevice); + SDL_WaitForGPUIdle(v->Device); ImGui_ImplSDLGPU3_DestroyFontsTexture(); } @@ -308,7 +308,7 @@ bool ImGui_ImplSDLGPU3_CreateFontsTexture() texture_info.num_levels = 1; texture_info.sample_count = SDL_GPU_SAMPLECOUNT_1; - bd->FontTexture = SDL_CreateGPUTexture(v->GpuDevice, &texture_info); + bd->FontTexture = SDL_CreateGPUTexture(v->Device, &texture_info); IM_ASSERT(bd->FontTexture && "Failed to create font texture, call SDL_GetError() for more info"); } @@ -317,39 +317,37 @@ bool ImGui_ImplSDLGPU3_CreateFontsTexture() // Create all the upload structures and upload: { - SDL_GPUTransferBufferCreateInfo font_transferbuffer_info = {}; - font_transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; - font_transferbuffer_info.size = upload_size; + SDL_GPUTransferBufferCreateInfo transferbuffer_info = {}; + transferbuffer_info.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD; + transferbuffer_info.size = upload_size; - SDL_GPUTransferBuffer* font_transferbuffer = SDL_CreateGPUTransferBuffer(v->GpuDevice, &font_transferbuffer_info); - IM_ASSERT(font_transferbuffer != nullptr && "Failed to create font transfer buffer, call SDL_GetError() for more information"); + SDL_GPUTransferBuffer* transferbuffer = SDL_CreateGPUTransferBuffer(v->Device, &transferbuffer_info); + IM_ASSERT(transferbuffer != nullptr && "Failed to create font transfer buffer, call SDL_GetError() for more information"); - void* texture_ptr = SDL_MapGPUTransferBuffer(v->GpuDevice, font_transferbuffer, false); + void* texture_ptr = SDL_MapGPUTransferBuffer(v->Device, transferbuffer, false); memcpy(texture_ptr, pixels, upload_size); - SDL_UnmapGPUTransferBuffer(v->GpuDevice, font_transferbuffer); + SDL_UnmapGPUTransferBuffer(v->Device, transferbuffer); - SDL_GPUTextureTransferInfo font_transfer_info = {}; - font_transfer_info.offset = 0; - font_transfer_info.transfer_buffer = font_transferbuffer; + SDL_GPUTextureTransferInfo transfer_info = {}; + transfer_info.offset = 0; + transfer_info.transfer_buffer = transferbuffer; - SDL_GPUTextureRegion font_texture_region = {}; - font_texture_region.texture = bd->FontTexture; - font_texture_region.w = width; - font_texture_region.h = height; - font_texture_region.d = 1; + SDL_GPUTextureRegion texture_region = {}; + texture_region.texture = bd->FontTexture; + texture_region.w = width; + texture_region.h = height; + texture_region.d = 1; - SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(v->GpuDevice); + SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(v->Device); SDL_GPUCopyPass* copy_pass = SDL_BeginGPUCopyPass(cmd); - SDL_UploadToGPUTexture(copy_pass, &font_transfer_info, &font_texture_region, false); + SDL_UploadToGPUTexture(copy_pass, &transfer_info, &texture_region, false); SDL_EndGPUCopyPass(copy_pass); SDL_SubmitGPUCommandBuffer(cmd); - SDL_ReleaseGPUTransferBuffer(v->GpuDevice, font_transferbuffer); + SDL_ReleaseGPUTransferBuffer(v->Device, transferbuffer); } // Store our identifier io.Fonts->SetTexID((ImTextureID)&bd->FontBinding); - - return true; } // You probably never need to call this, as it is called by ImGui_ImplSDLGPU3_CreateFontsTexture() and ImGui_ImplSDLGPU3_Shutdown(). @@ -357,10 +355,10 @@ void ImGui_ImplSDLGPU3_DestroyFontsTexture() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo; if (bd->FontTexture) { - SDL_ReleaseGPUTexture(v->GpuDevice, bd->FontTexture); + SDL_ReleaseGPUTexture(v->Device, bd->FontTexture); bd->FontBinding.texture = nullptr; bd->FontTexture = nullptr; } @@ -371,9 +369,9 @@ static void Imgui_ImplSDLGPU3_CreateShaders() { // Create the shader modules ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo; - const char* driver = SDL_GetGPUDeviceDriver(v->GpuDevice); + const char* driver = SDL_GetGPUDeviceDriver(v->Device); SDL_GPUShaderCreateInfo vertex_shader_info = {}; vertex_shader_info.entrypoint = "main"; @@ -422,8 +420,8 @@ static void Imgui_ImplSDLGPU3_CreateShaders() fragment_shader_info.code_size = sizeof(metallib_fragment); } #endif - bd->VertexShader = SDL_CreateGPUShader(v->GpuDevice, &vertex_shader_info); - bd->FragmentShader = SDL_CreateGPUShader(v->GpuDevice, &fragment_shader_info); + bd->VertexShader = SDL_CreateGPUShader(v->Device, &vertex_shader_info); + bd->FragmentShader = SDL_CreateGPUShader(v->Device, &fragment_shader_info); IM_ASSERT(bd->VertexShader != nullptr && "Failed to create vertex shader, call SDL_GetError() for more information"); IM_ASSERT(bd->FragmentShader != nullptr && "Failed to create fragment shader, call SDL_GetError() for more information"); } @@ -431,7 +429,7 @@ static void Imgui_ImplSDLGPU3_CreateShaders() static void ImGui_ImplSDLGPU3_CreateGraphicsPipeline() { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo; Imgui_ImplSDLGPU3_CreateShaders(); SDL_GPUVertexBufferDescription vertex_buffer_desc[1]; @@ -507,14 +505,14 @@ static void ImGui_ImplSDLGPU3_CreateGraphicsPipeline() pipeline_info.depth_stencil_state = depth_stencil_state; pipeline_info.target_info = target_info; - bd->Pipeline = SDL_CreateGPUGraphicsPipeline(v->GpuDevice, &pipeline_info); + bd->Pipeline = SDL_CreateGPUGraphicsPipeline(v->Device, &pipeline_info); IM_ASSERT(bd->Pipeline != nullptr && "Failed to create graphics pipeline, call SDL_GetError() for more information"); } -bool ImGui_ImplSDLGPU3_CreateDeviceObjects() +void ImGui_ImplSDLGPU3_CreateDeviceObjects() { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo; if (!bd->FontSampler) { @@ -533,23 +531,22 @@ bool ImGui_ImplSDLGPU3_CreateDeviceObjects() sampler_info.max_anisotropy = 1.0f; sampler_info.enable_compare = false; - bd->FontSampler = SDL_CreateGPUSampler(v->GpuDevice, &sampler_info); + bd->FontSampler = SDL_CreateGPUSampler(v->Device, &sampler_info); bd->FontBinding.sampler = bd->FontSampler; IM_ASSERT(bd->FontSampler != nullptr && "Failed to create font sampler, call SDL_GetError() for more information"); } ImGui_ImplSDLGPU3_CreateGraphicsPipeline(); - - return true; + ImGui_ImplSDLGPU3_CreateFontsTexture(); } void ImGui_ImplSDLGPU3_DestroyFrameData() { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo; - SDL_ReleaseGPUBuffer(v->GpuDevice, bd->MainWindowFrameData.VertexBuffer); - SDL_ReleaseGPUBuffer(v->GpuDevice, bd->MainWindowFrameData.IndexBuffer); + SDL_ReleaseGPUBuffer(v->Device, bd->MainWindowFrameData.VertexBuffer); + SDL_ReleaseGPUBuffer(v->Device, bd->MainWindowFrameData.IndexBuffer); bd->MainWindowFrameData.VertexBuffer = nullptr; bd->MainWindowFrameData.IndexBuffer = nullptr; bd->MainWindowFrameData.VertexBufferSize = 0; @@ -559,15 +556,15 @@ void ImGui_ImplSDLGPU3_DestroyFrameData() void ImGui_ImplSDLGPU3_DestroyDeviceObjects() { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); - ImGui_ImplSDLGPU3_InitInfo* v = &bd->GPUInitInfo; + ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo; ImGui_ImplSDLGPU3_DestroyFrameData(); ImGui_ImplSDLGPU3_DestroyFontsTexture(); - if (bd->VertexShader) { SDL_ReleaseGPUShader(v->GpuDevice, bd->VertexShader); bd->VertexShader = nullptr;} - if (bd->FragmentShader) { SDL_ReleaseGPUShader(v->GpuDevice, bd->FragmentShader); bd->FragmentShader = nullptr;} - if (bd->FontSampler) { SDL_ReleaseGPUSampler(v->GpuDevice, bd->FontSampler); bd->FontSampler = nullptr;} - if (bd->Pipeline) { SDL_ReleaseGPUGraphicsPipeline(v->GpuDevice, bd->Pipeline); bd->Pipeline = nullptr;} + if (bd->VertexShader) { SDL_ReleaseGPUShader(v->Device, bd->VertexShader); bd->VertexShader = nullptr;} + if (bd->FragmentShader) { SDL_ReleaseGPUShader(v->Device, bd->FragmentShader); bd->FragmentShader = nullptr;} + if (bd->FontSampler) { SDL_ReleaseGPUSampler(v->Device, bd->FontSampler); bd->FontSampler = nullptr;} + if (bd->Pipeline) { SDL_ReleaseGPUGraphicsPipeline(v->Device, bd->Pipeline); bd->Pipeline = nullptr;} } bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info) @@ -582,10 +579,10 @@ bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info) io.BackendRendererName = "imgui_impl_sdlgpu3"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. - IM_ASSERT(info->GpuDevice != nullptr); + IM_ASSERT(info->Device != nullptr); IM_ASSERT(info->ColorTargetFormat != SDL_GPU_TEXTUREFORMAT_INVALID); - bd->GPUInitInfo = *info; + bd->InitInfo = *info; ImGui_ImplSDLGPU3_CreateDeviceObjects(); diff --git a/backends/imgui_impl_sdlgpu3.h b/backends/imgui_impl_sdlgpu3.h index ff9c751c8660..865139e26a0f 100644 --- a/backends/imgui_impl_sdlgpu3.h +++ b/backends/imgui_impl_sdlgpu3.h @@ -29,18 +29,21 @@ // - Remember to set ColorTargetFormat to the correct format. If you're rendering to the swapchain, call SDL_GetGPUSwapchainTextureFormat to query the right value struct ImGui_ImplSDLGPU3_InitInfo { - SDL_GPUDevice* GpuDevice = nullptr; + SDL_GPUDevice* Device = nullptr; SDL_GPUTextureFormat ColorTargetFormat = SDL_GPU_TEXTUREFORMAT_INVALID; SDL_GPUSampleCount MSAASamples = SDL_GPU_SAMPLECOUNT_1; }; // Follow "Getting Started" link and check examples/ folder to learn about using backends! -IMGUI_IMPL_API bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info); -IMGUI_IMPL_API void ImGui_ImplSDLGPU3_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplSDLGPU3_NewFrame(); -IMGUI_IMPL_API void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer); -IMGUI_IMPL_API void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline = nullptr); -IMGUI_IMPL_API bool ImGui_ImplSDLGPU3_CreateFontsTexture(); -IMGUI_IMPL_API void ImGui_ImplSDLGPU3_DestroyFontsTexture(); +IMGUI_IMPL_API bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info); +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_NewFrame(); +IMGUI_IMPL_API void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer); +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline = nullptr); + +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_DestroyDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_CreateFontsTexture(); +IMGUI_IMPL_API void ImGui_ImplSDLGPU3_DestroyFontsTexture(); #endif // #ifndef IMGUI_DISABLE diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 429785637549..f04436ac0687 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,9 @@ HOW TO UPDATE? Breaking changes: +- Backends: SDLGPU3: Renamed ImGui_ImplSDLGPU3_InitInfo::GpuDevice to Device + for consistency. (#8163, #7998, #7988) + Other changes: - ImDrawList: texture baked storage for thick line reduced from ~64x64 to ~32x32. (#3245) @@ -48,6 +51,8 @@ Other changes: provided example, to reduce latency. - Examples: Vulkan: better handle VK_SUBOPTIMAL_KHR being returned by vkAcquireNextImageKHR() or vkQueuePresentKHR(). (#7825, #7831) [@NostraMagister] +- Backends: SDLGPU3: Exposed ImGui_ImplSDLGPU3_CreateDeviceObjects()/_DestroyDeviceObjects(). + Removed return value from ImGui_ImplSDLGPU3_CreateFontsTexture(). (#8163, #7998, #7988) - Backends: DirectX12: Texture upload use the command queue provided in ImGui_ImplDX12_InitInfo instead of creating its own. @@ -110,7 +115,7 @@ Other changes: - Demo: Added label edition to Property Editor demo + fix an ID issue. (#8266) [@moritz-h] - Misc: Fixed misc/cpp/imgui_stdlib.h/.cpp not supporting IMGUI_DISABLE. (#8294) [@juur] - Misc: Fixed MinGW builds not using UTF-8 friendly _wfopen(). (#8300) -- Backends: SDL_GPU for SDL3: Added backend for SDL_GPU! (#8163, #7998, #7988) [@DeltaW0x]. +- Backends: SDLGPU3 for SDL3: Added backend for SDL_GPU! (#8163, #7998, #7988) [@DeltaW0x]. - Backends: SDL3: Added ImGui_ImplSDL3_InitForSDLGPU() for consistency, even though it is currently not doing anything particular. (#8163, #7998, #7988) - Backends: Allegro5: Avoid calling al_set_mouse_cursor() repeatedly since it appears diff --git a/examples/example_sdl3_sdlgpu3/main.cpp b/examples/example_sdl3_sdlgpu3/main.cpp index f025c537dea0..1077639e7fea 100644 --- a/examples/example_sdl3_sdlgpu3/main.cpp +++ b/examples/example_sdl3_sdlgpu3/main.cpp @@ -69,7 +69,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplSDL3_InitForSDLGPU(window); ImGui_ImplSDLGPU3_InitInfo init_info = {}; - init_info.GpuDevice = gpu_device; + init_info.Device = gpu_device; init_info.ColorTargetFormat = SDL_GetGPUSwapchainTextureFormat(gpu_device, window); init_info.MSAASamples = SDL_GPU_SAMPLECOUNT_1; ImGui_ImplSDLGPU3_Init(&init_info); From 007735737a4f1895fc9e578ce5420874d6875bd9 Mon Sep 17 00:00:00 2001 From: Diego Mateos Date: Thu, 16 Jan 2025 17:10:26 +0100 Subject: [PATCH 382/548] Ignore vscode artifacts (#8324) --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f632636e0fdd..15a908273eae 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,9 @@ examples/example_sdl2_opengl3/web/* .idea cmake-build-* +## VS code artifacts +.vscode + ## Unix executables from our example Makefiles examples/example_glfw_metal/example_glfw_metal examples/example_glfw_opengl2/example_glfw_opengl2 From 4c64ba16c54823e77a719d6b599e824f066f5f92 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 16 Jan 2025 17:42:00 +0100 Subject: [PATCH 383/548] imgui_freetype: fixed issue where glyph advances would incorrectly be snapped to pixels. --- docs/CHANGELOG.txt | 4 ++++ misc/freetype/imgui_freetype.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f04436ac0687..f543799f0c8d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,10 @@ Breaking changes: Other changes: - ImDrawList: texture baked storage for thick line reduced from ~64x64 to ~32x32. (#3245) +- imgui_freetype: fixed issue where glyph advances would incorrectly be + snapped to pixels. Effectively it would only be noticeable when hinting + is disabled with ImGuiFreeTypeBuilderFlags_NoHinting, as hinting itself + snaps glyph advances. - Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in provided example, to reduce latency. - Examples: Vulkan: better handle VK_SUBOPTIMAL_KHR being returned by diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 997bc4340bd5..421fdba63436 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -104,6 +104,9 @@ static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_ // Code //------------------------------------------------------------------------- +#define FT_CEIL(X) (((X + 63) & -64) / 64) // From SDL_ttf: Handy routines for converting from fixed point +#define FT_SCALEFACTOR 64.0f + namespace { // Glyph metrics: @@ -182,9 +185,6 @@ namespace float InvRasterizationDensity; }; - // From SDL_ttf: Handy routines for converting from fixed point - #define FT_CEIL(X) (((X + 63) & -64) / 64) - bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_font_builder_flags) { FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &Face); @@ -316,7 +316,7 @@ namespace out_glyph_info->Height = (int)ft_bitmap->rows; out_glyph_info->OffsetX = Face->glyph->bitmap_left; out_glyph_info->OffsetY = -Face->glyph->bitmap_top; - out_glyph_info->AdvanceX = (float)FT_CEIL(slot->advance.x); + out_glyph_info->AdvanceX = (float)slot->advance.x / FT_SCALEFACTOR; out_glyph_info->IsColored = (ft_bitmap->pixel_mode == FT_PIXEL_MODE_BGRA); return ft_bitmap; From b7c27c5333bca2d9b7958b3a12a1438ab18d20d7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 16 Jan 2025 19:07:09 +0100 Subject: [PATCH 384/548] Windows: legacy SetWindowFontScale() is properly inherited by nested child windows. (#2701, #8138, #1018) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 5 ++++- imgui.h | 2 +- imgui_internal.h | 3 ++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f543799f0c8d..c69c017d9961 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,9 @@ Other changes: snapped to pixels. Effectively it would only be noticeable when hinting is disabled with ImGuiFreeTypeBuilderFlags_NoHinting, as hinting itself snaps glyph advances. +- Windows: legacy SetWindowFontScale() is properly inherited by nested child + windows. Note that an upcoming major release should make this obsolete, + but in the meanwhile it works better now. (#2701, #8138, #1018) - Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in provided example, to reduce latency. - Examples: Vulkan: better handle VK_SUBOPTIMAL_KHR being returned by diff --git a/imgui.cpp b/imgui.cpp index 009a9abf1f16..613bef69a528 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4276,7 +4276,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NUL SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); LastFrameActive = -1; LastTimeActive = -1.0f; - FontWindowScale = 1.0f; + FontWindowScale = FontWindowScaleParents = 1.0f; SettingsOffset = -1; DrawList = &DrawListInst; DrawList->_OwnerName = Name; @@ -7037,6 +7037,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // There's little point to expose a flag to set this: because the interesting cases won't be using parent_window_in_stack, // e.g. linking a tool window in a standalone viewport to a document window, regardless of their Begin() stack parenting. (#6798) window->ParentWindowForFocusRoute = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window_in_stack : NULL; + + // Inherent SetWindowFontScale() from parent until we fix this system... + window->FontWindowScaleParents = parent_window ? parent_window->FontWindowScaleParents * parent_window->FontWindowScale : 1.0f; } // Add to focus scope stack diff --git a/imgui.h b/imgui.h index b9a4fe1581b0..b111407e2fae 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.8 WIP" -#define IMGUI_VERSION_NUM 19171 +#define IMGUI_VERSION_NUM 19172 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 12d8f7a51b7a..b98aafca8668 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2551,6 +2551,7 @@ struct IMGUI_API ImGuiWindow ImGuiStorage StateStorage; ImVector ColumnsStorage; float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale() + float FontWindowScaleParents; int SettingsOffset; // Offset into SettingsWindows[] (offsets are always valid as we only grow the array from the back) ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer) @@ -2585,7 +2586,7 @@ struct IMGUI_API ImGuiWindow // We don't use g.FontSize because the window may be != g.CurrentWindow. ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } - float CalcFontSize() const { ImGuiContext& g = *Ctx; float scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; } + float CalcFontSize() const { ImGuiContext& g = *Ctx; return g.FontBaseSize * FontWindowScale * FontWindowScaleParents; } ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight)); } ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight; return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight); } }; From f2262eb81aa2a86f8acc9d9ef5996f6a14429d4d Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 16 Jan 2025 19:46:54 +0100 Subject: [PATCH 385/548] Windows: latch FontRefSize at time of Begin(), consistent with e.g. TitleBarHeight, and to avoid calling CalcFontSize() on non-current window. --- imgui.cpp | 14 ++++++++------ imgui_internal.h | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 613bef69a528..7c08e6e87d4b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4276,6 +4276,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NUL SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); LastFrameActive = -1; LastTimeActive = -1.0f; + FontRefSize = 0.0f; FontWindowScale = FontWindowScaleParents = 1.0f; SettingsOffset = -1; DrawList = &DrawListInst; @@ -7201,6 +7202,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y; window->TitleBarHeight = (flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : g.FontSize + g.Style.FramePadding.y * 2.0f; window->MenuBarHeight = (flags & ImGuiWindowFlags_MenuBar) ? window->DC.MenuBarOffset.y + g.FontSize + g.Style.FramePadding.y * 2.0f : 0.0f; + window->FontRefSize = g.FontSize; // Lock this to discourage calling window->CalcFontSize() outside of current window. // Depending on condition we use previous or current window size to compare against contents size to decide if a scrollbar should be visible. // Those flags will be altered further down in the function depending on more conditions. @@ -9649,7 +9651,7 @@ void ImGui::UpdateMouseWheel() { LockWheelingWindow(window, wheel.x); float max_step = window->InnerRect.GetWidth() * 0.67f; - float scroll_step = ImTrunc(ImMin(2 * window->CalcFontSize(), max_step)); + float scroll_step = ImTrunc(ImMin(2 * window->FontRefSize, max_step)); SetScrollX(window, window->Scroll.x - wheel.x * scroll_step); g.WheelingWindowScrolledFrame = g.FrameCount; } @@ -9657,7 +9659,7 @@ void ImGui::UpdateMouseWheel() { LockWheelingWindow(window, wheel.y); float max_step = window->InnerRect.GetHeight() * 0.67f; - float scroll_step = ImTrunc(ImMin(5 * window->CalcFontSize(), max_step)); + float scroll_step = ImTrunc(ImMin(5 * window->FontRefSize, max_step)); SetScrollY(window, window->Scroll.y - wheel.y * scroll_step); g.WheelingWindowScrolledFrame = g.FrameCount; } @@ -12987,7 +12989,7 @@ static void ImGui::NavUpdate() { // *Fallback* manual-scroll with Nav directional keys when window has no navigable item ImGuiWindow* window = g.NavWindow; - const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. + const float scroll_speed = IM_ROUND(window->FontRefSize * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. const ImGuiDir move_dir = g.NavMoveDir; if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY && move_dir != ImGuiDir_None) { @@ -13177,8 +13179,8 @@ void ImGui::NavUpdateCreateMoveRequest() if ((clamp_x || clamp_y) && !inner_rect_rel.Contains(window->NavRectRel[g.NavLayer])) { IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel for gamepad move\n"); - float pad_x = ImMin(inner_rect_rel.GetWidth(), window->CalcFontSize() * 0.5f); - float pad_y = ImMin(inner_rect_rel.GetHeight(), window->CalcFontSize() * 0.5f); // Terrible approximation for the intent of starting navigation from first fully visible item + float pad_x = ImMin(inner_rect_rel.GetWidth(), window->FontRefSize * 0.5f); + float pad_y = ImMin(inner_rect_rel.GetHeight(), window->FontRefSize * 0.5f); // Terrible approximation for the intent of starting navigation from first fully visible item inner_rect_rel.Min.x = clamp_x ? (inner_rect_rel.Min.x + pad_x) : -FLT_MAX; inner_rect_rel.Max.x = clamp_x ? (inner_rect_rel.Max.x - pad_x) : +FLT_MAX; inner_rect_rel.Min.y = clamp_y ? (inner_rect_rel.Min.y + pad_y) : -FLT_MAX; @@ -13436,7 +13438,7 @@ static float ImGui::NavUpdatePageUpPageDown() else { ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; - const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); + const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->FontRefSize * 1.0f + nav_rect_rel.GetHeight()); float nav_scoring_rect_offset_y = 0.0f; if (IsKeyPressed(ImGuiKey_PageUp, true)) { diff --git a/imgui_internal.h b/imgui_internal.h index b98aafca8668..736031d32e4d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2552,6 +2552,7 @@ struct IMGUI_API ImGuiWindow ImVector ColumnsStorage; float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale() float FontWindowScaleParents; + float FontRefSize; // This is a copy of window->CalcFontSize() at the time of Begin(), trying to phase out CalcFontSize() especially as it may be called on non-current window. int SettingsOffset; // Offset into SettingsWindows[] (offsets are always valid as we only grow the array from the back) ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer) From 487d7f9a296cec2af496b64f6eb9d939fc8fae33 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 16 Jan 2025 22:30:43 +0100 Subject: [PATCH 386/548] Font: Internals: make used page maps smaller. Since it's extremely rarely used and for iterations only. ~34->16 bytes with ImWchar32. --- imgui.cpp | 4 ++-- imgui.h | 2 +- imgui_draw.cpp | 20 ++++++++++---------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7c08e6e87d4b..b326c444dc24 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16177,9 +16177,9 @@ void ImGui::DebugNodeFont(ImFont* font) // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k) // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT // is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here) - if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095)) + if (!(base & 8191) && font->IsGlyphRangeUnused(base, base + 8191)) { - base += 4096 - 256; + base += 8192 - 256; continue; } diff --git a/imgui.h b/imgui.h index b111407e2fae..bcf0ac403e3d 100644 --- a/imgui.h +++ b/imgui.h @@ -3461,7 +3461,7 @@ struct ImFont float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] (unscaled) int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) - ImU8 Used4kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/4096/8]; // 2 bytes if ImWchar=ImWchar16, 34 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints. + ImU8 Used8kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/8192/8]; // 1 bytes if ImWchar=ImWchar16, 16 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints. // Methods IMGUI_API ImFont(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e8c445dd30b3..67a993de54c6 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3689,7 +3689,7 @@ ImFont::ImFont() Scale = 1.0f; Ascent = Descent = 0.0f; MetricsTotalSurface = 0; - memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap)); + memset(Used8kPagesMap, 0, sizeof(Used8kPagesMap)); } ImFont::~ImFont() @@ -3709,7 +3709,7 @@ void ImFont::ClearOutputData() DirtyLookupTables = true; Ascent = Descent = 0.0f; MetricsTotalSurface = 0; - memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap)); + memset(Used8kPagesMap, 0, sizeof(Used8kPagesMap)); } static ImWchar FindFirstExistingGlyph(ImFont* font, const ImWchar* candidate_chars, int candidate_chars_count) @@ -3732,7 +3732,7 @@ void ImFont::BuildLookupTable() IndexAdvanceX.clear(); IndexLookup.clear(); DirtyLookupTables = false; - memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap)); + memset(Used8kPagesMap, 0, sizeof(Used8kPagesMap)); GrowIndex(max_codepoint + 1); for (int i = 0; i < Glyphs.Size; i++) { @@ -3741,8 +3741,8 @@ void ImFont::BuildLookupTable() IndexLookup[codepoint] = (ImWchar)i; // Mark 4K page as used - const int page_n = codepoint / 4096; - Used4kPagesMap[page_n >> 3] |= 1 << (page_n & 7); + const int page_n = codepoint / 8192; + Used8kPagesMap[page_n >> 3] |= 1 << (page_n & 7); } // Create a glyph to handle TAB @@ -3804,15 +3804,15 @@ void ImFont::BuildLookupTable() } } -// API is designed this way to avoid exposing the 4K page size +// API is designed this way to avoid exposing the 8K page size // e.g. use with IsGlyphRangeUnused(0, 255) bool ImFont::IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last) { - unsigned int page_begin = (c_begin / 4096); - unsigned int page_last = (c_last / 4096); + unsigned int page_begin = (c_begin / 8192); + unsigned int page_last = (c_last / 8192); for (unsigned int page_n = page_begin; page_n <= page_last; page_n++) - if ((page_n >> 3) < sizeof(Used4kPagesMap)) - if (Used4kPagesMap[page_n >> 3] & (1 << (page_n & 7))) + if ((page_n >> 3) < sizeof(Used8kPagesMap)) + if (Used8kPagesMap[page_n >> 3] & (1 << (page_n & 7))) return false; return true; } From dd89a3741b1d05ab0997d80bfe0377070251d300 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 17 Jan 2025 17:11:22 +0100 Subject: [PATCH 387/548] Backends: Vulkan: sharing duplicate code. (#5446, #8326) --- backends/imgui_impl_vulkan.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index f4bd50694d22..2bd40f624aed 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1079,6 +1079,15 @@ void ImGui_ImplVulkan_DestroyDeviceObjects() if (bd->DescriptorPool) { vkDestroyDescriptorPool(v->Device, bd->DescriptorPool, v->Allocator); bd->DescriptorPool = VK_NULL_HANDLE; } } +#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING +static void ImGui_ImplVulkan_LoadDynamicRenderingFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data) +{ + // Manually load those two (see #5446) + ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast(loader_func("vkCmdBeginRenderingKHR", user_data)); + ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast(loader_func("vkCmdEndRenderingKHR", user_data)); +} +#endif + bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data) { // Load function pointers @@ -1094,9 +1103,7 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch #undef IMGUI_VULKAN_FUNC_LOAD #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - // Manually load those two (see #5446) - ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast(loader_func("vkCmdBeginRenderingKHR", user_data)); - ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast(loader_func("vkCmdEndRenderingKHR", user_data)); + ImGui_ImplVulkan_LoadDynamicRenderingFunctions(loader_func, user_data); #endif #else IM_UNUSED(loader_func); @@ -1115,8 +1122,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) { #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING #ifndef IMGUI_IMPL_VULKAN_USE_LOADER - ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast(vkGetInstanceProcAddr(info->Instance, "vkCmdBeginRenderingKHR")); - ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast(vkGetInstanceProcAddr(info->Instance, "vkCmdEndRenderingKHR")); + ImGui_ImplVulkan_LoadDynamicRenderingFunctions([](const char* function_name, void* user_data) { return vkGetInstanceProcAddr((VkInstance)user_data, function_name); }, (void*)info->Instance); #endif IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR != nullptr); IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR != nullptr); From d7454de80a2d51cee6601d275c441987e7aebb5e Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 17 Jan 2025 18:09:28 +0100 Subject: [PATCH 388/548] Font: minor tweak to struct alignment. --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index bcf0ac403e3d..b42fa06371a0 100644 --- a/imgui.h +++ b/imgui.h @@ -3457,10 +3457,10 @@ struct ImFont ImWchar FallbackChar; // 2-4 // out // = FFFD/'?' // Character used if a glyph isn't found. float EllipsisWidth; // 4 // out // Width float EllipsisCharStep; // 4 // out // Step between characters when EllipsisCount > 0 - bool DirtyLookupTables; // 1 // out // float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] (unscaled) int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) + bool DirtyLookupTables; // 1 // out // ImU8 Used8kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/8192/8]; // 1 bytes if ImWchar=ImWchar16, 16 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints. // Methods From 80c9cd1f6e4ec84034f918de21aba3953dfa9893 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 18 Jan 2025 16:43:17 +0100 Subject: [PATCH 389/548] Font: reduce unnecessary padding in ImFontConfig struct too. --- imgui.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.h b/imgui.h index b42fa06371a0..82903424a886 100644 --- a/imgui.h +++ b/imgui.h @@ -3233,26 +3233,27 @@ struct ImDrawData // [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontAtlasFlags, ImFontAtlas, ImFontGlyphRangesBuilder, ImFont) //----------------------------------------------------------------------------- +// A font input/source (we may rename this to ImFontSource in the future) struct ImFontConfig { void* FontData; // // TTF/OTF data int FontDataSize; // // TTF/OTF data size bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). + bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. + bool PixelSnapH; // false // Align every glyph AdvanceX to pixel boundaries. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. int FontNo; // 0 // Index of font within TTF/OTF file - float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height). int OversampleH; // 2 // Rasterize at higher quality for sub-pixel positioning. Note the difference between 2 and 3 is minimal. You can reduce this to 1 for large glyphs save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details. int OversampleV; // 1 // Rasterize at higher quality for sub-pixel positioning. This is not really useful as we don't use sub-pixel positions on the Y axis. - bool PixelSnapH; // false // Align every glyph AdvanceX to pixel boundaries. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. + float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height). ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs when rendered: essentially add to glyph->AdvanceX. Only X axis is supported for now. ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. const ImWchar* GlyphRanges; // NULL // THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs - bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure. float RasterizerMultiply; // 1.0f // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future. float RasterizerDensity; // 1.0f // DPI scale for rasterization, not altering other font metrics: make it easy to swap between e.g. a 100% and a 400% fonts for a zooming display. IMPORTANT: If you increase this it is expected that you increase font scale accordingly, otherwise quality may look lowered. - ImWchar EllipsisChar; // 0 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. + ImWchar EllipsisChar; // 0 // Explicitly specify Unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. // [Internal] char Name[40]; // Name (strictly to ease debugging) From aa23f3801b7414989093abf7388144bc4dfd221c Mon Sep 17 00:00:00 2001 From: "Daniel K. O. (dkosmari)" Date: Fri, 17 Jan 2025 19:18:05 -0300 Subject: [PATCH 390/548] Backends: SDL_Renderer2/3: Use endian-dependent RGBA32 texture format, to match SDL_Color. (#8327) --- backends/imgui_impl_sdlrenderer2.cpp | 3 ++- backends/imgui_impl_sdlrenderer3.cpp | 3 ++- docs/CHANGELOG.txt | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp index 6d0ee564f1b3..fcc6d5dd3e39 100644 --- a/backends/imgui_impl_sdlrenderer2.cpp +++ b/backends/imgui_impl_sdlrenderer2.cpp @@ -21,6 +21,7 @@ // - Introduction, links and more at the top of imgui.cpp // CHANGELOG +// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color. // 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer2_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 2024-05-14: *BREAKING CHANGE* ImGui_ImplSDLRenderer3_RenderDrawData() requires SDL_Renderer* passed as parameter. // 2023-05-30: Renamed imgui_impl_sdlrenderer.h/.cpp to imgui_impl_sdlrenderer2.h/.cpp to accommodate for upcoming SDL3. @@ -228,7 +229,7 @@ bool ImGui_ImplSDLRenderer2_CreateFontsTexture() // Upload texture to graphics system // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) - bd->FontTexture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height); + bd->FontTexture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, width, height); if (bd->FontTexture == nullptr) { SDL_Log("error creating texture"); diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp index 1bcf7a228b0a..0cede09be733 100644 --- a/backends/imgui_impl_sdlrenderer3.cpp +++ b/backends/imgui_impl_sdlrenderer3.cpp @@ -23,6 +23,7 @@ // - Introduction, links and more at the top of imgui.cpp // CHANGELOG +// 2025-01-18: Use endian-dependent RGBA32 texture format, to match SDL_Color. // 2024-10-09: Expose selected render state in ImGui_ImplSDLRenderer3_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 2024-07-01: Update for SDL3 api changes: SDL_RenderGeometryRaw() uint32 version was removed (SDL#9009). // 2024-05-14: *BREAKING CHANGE* ImGui_ImplSDLRenderer3_RenderDrawData() requires SDL_Renderer* passed as parameter. @@ -247,7 +248,7 @@ bool ImGui_ImplSDLRenderer3_CreateFontsTexture() // Upload texture to graphics system // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) - bd->FontTexture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STATIC, width, height); + bd->FontTexture = SDL_CreateTexture(bd->Renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, width, height); if (bd->FontTexture == nullptr) { SDL_Log("error creating texture"); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c69c017d9961..f2812a66197b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,8 @@ Other changes: vkAcquireNextImageKHR() or vkQueuePresentKHR(). (#7825, #7831) [@NostraMagister] - Backends: SDLGPU3: Exposed ImGui_ImplSDLGPU3_CreateDeviceObjects()/_DestroyDeviceObjects(). Removed return value from ImGui_ImplSDLGPU3_CreateFontsTexture(). (#8163, #7998, #7988) +- Backends: SDL_Renderer2/3: Use endian-dependent RGBA32 texture format, to match + SDL_Color. (#8327) [@dkosmari] - Backends: DirectX12: Texture upload use the command queue provided in ImGui_ImplDX12_InitInfo instead of creating its own. From aa1b4ea861173109a64eef644243f632f388d567 Mon Sep 17 00:00:00 2001 From: Julian Rachele Date: Sun, 19 Jan 2025 16:30:15 -0500 Subject: [PATCH 391/548] Backends: OSX: Remove notification observer when shutting down. (#8331) --- backends/imgui_impl_osx.mm | 2 ++ docs/CHANGELOG.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index c2a5f6378a45..92c26418f8f6 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -29,6 +29,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-01-20: Removed notification observer when shutting down. (#8331) // 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: // - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn // - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn @@ -497,6 +498,7 @@ void ImGui_ImplOSX_Shutdown() ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); + [[NSNotificationCenter defaultCenter] removeObserver:bd->Observer]; bd->Observer = nullptr; if (bd->Monitor != nullptr) { diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f2812a66197b..c81fc8df0a7c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,7 @@ Other changes: SDL_Color. (#8327) [@dkosmari] - Backends: DirectX12: Texture upload use the command queue provided in ImGui_ImplDX12_InitInfo instead of creating its own. +- Backends: OSX: Removed notification observer when shutting down. (#8331) [@jrachele] ----------------------------------------------------------------------- From 8b0af7fddcba41d2c091b6752451ed9082af777e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 20 Jan 2025 14:30:40 +0100 Subject: [PATCH 392/548] Backends: SDL: update comments regarding API stability, regarding SDL_GPU and SDL_Renderer. --- backends/imgui_impl_sdl3.cpp | 6 ++---- backends/imgui_impl_sdl3.h | 6 ++---- backends/imgui_impl_sdlrenderer2.cpp | 12 +++++++----- backends/imgui_impl_sdlrenderer2.h | 12 +++++++----- backends/imgui_impl_sdlrenderer3.cpp | 18 +++++++++--------- backends/imgui_impl_sdlrenderer3.h | 18 +++++++++--------- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index b8e4dec5ea84..eb0eef89f5a5 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -1,9 +1,7 @@ -// dear imgui: Platform Backend for SDL3 (*EXPERIMENTAL*) -// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) +// dear imgui: Platform Backend for SDL3 +// This needs to be used along with a Renderer (e.g. SDL_GPU, DirectX11, OpenGL3, Vulkan..) // (Info: SDL3 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) -// (**IMPORTANT: SDL 3.0.0 is NOT YET RELEASED AND CURRENTLY HAS A FAST CHANGING API. THIS CODE BREAKS OFTEN AS SDL3 CHANGES.**) - // Implemented features: // [X] Platform: Clipboard support. // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen. diff --git a/backends/imgui_impl_sdl3.h b/backends/imgui_impl_sdl3.h index ff0e2aed3dd5..5b8973738201 100644 --- a/backends/imgui_impl_sdl3.h +++ b/backends/imgui_impl_sdl3.h @@ -1,9 +1,7 @@ -// dear imgui: Platform Backend for SDL3 (*EXPERIMENTAL*) -// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) +// dear imgui: Platform Backend for SDL3 +// This needs to be used along with a Renderer (e.g. SDL_GPU, DirectX11, OpenGL3, Vulkan..) // (Info: SDL3 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.) -// (**IMPORTANT: SDL 3.0.0 is NOT YET RELEASED AND CURRENTLY HAS A FAST CHANGING API. THIS CODE BREAKS OFTEN AS SDL3 CHANGES.**) - // Implemented features: // [X] Platform: Clipboard support. // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen. diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp index fcc6d5dd3e39..8245854c262c 100644 --- a/backends/imgui_impl_sdlrenderer2.cpp +++ b/backends/imgui_impl_sdlrenderer2.cpp @@ -1,11 +1,13 @@ // dear imgui: Renderer Backend for SDL_Renderer for SDL2 // (Requires: SDL 2.0.17+) -// Note how SDL_Renderer is an _optional_ component of SDL2. -// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX. -// If your application will want to render any non trivial amount of graphics other than UI, -// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user and -// it might be difficult to step out of those boundaries. +// Note that SDL_Renderer is an _optional_ component of SDL2, which IMHO is now largely obsolete. +// For a multi-platform app consider using other technologies: +// - SDL3+SDL_GPU: SDL_GPU is SDL3 new graphics abstraction API. You will need to update to SDL3. +// - SDL2+DirectX, SDL2+OpenGL, SDL2+Vulkan: combine SDL with dedicated renderers. +// If your application wants to render any non trivial amount of graphics other than UI, +// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user +// and it might be difficult to step out of those boundaries. // Implemented features: // [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID! diff --git a/backends/imgui_impl_sdlrenderer2.h b/backends/imgui_impl_sdlrenderer2.h index 7aed18d21809..a0337d314753 100644 --- a/backends/imgui_impl_sdlrenderer2.h +++ b/backends/imgui_impl_sdlrenderer2.h @@ -1,11 +1,13 @@ // dear imgui: Renderer Backend for SDL_Renderer for SDL2 // (Requires: SDL 2.0.17+) -// Note how SDL_Renderer is an _optional_ component of SDL2. -// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX. -// If your application will want to render any non trivial amount of graphics other than UI, -// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user and -// it might be difficult to step out of those boundaries. +// Note that SDL_Renderer is an _optional_ component of SDL2, which IMHO is now largely obsolete. +// For a multi-platform app consider using other technologies: +// - SDL3+SDL_GPU: SDL_GPU is SDL3 new graphics abstraction API. You will need to update to SDL3. +// - SDL2+DirectX, SDL2+OpenGL, SDL2+Vulkan: combine SDL with dedicated renderers. +// If your application wants to render any non trivial amount of graphics other than UI, +// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user +// and it might be difficult to step out of those boundaries. // Implemented features: // [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID! diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp index 0cede09be733..99253d9643fd 100644 --- a/backends/imgui_impl_sdlrenderer3.cpp +++ b/backends/imgui_impl_sdlrenderer3.cpp @@ -1,13 +1,13 @@ // dear imgui: Renderer Backend for SDL_Renderer for SDL3 -// (Requires: SDL 3.0.0+) - -// (**IMPORTANT: SDL 3.0.0 is NOT YET RELEASED AND CURRENTLY HAS A FAST CHANGING API. THIS CODE BREAKS OFTEN AS SDL3 CHANGES.**) - -// Note how SDL_Renderer is an _optional_ component of SDL3. -// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX. -// If your application will want to render any non trivial amount of graphics other than UI, -// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user and -// it might be difficult to step out of those boundaries. +// (Requires: SDL 3.1.8+) + +// Note that SDL_Renderer is an _optional_ component of SDL3, which IMHO is now largely obsolete. +// For a multi-platform app consider using other technologies: +// - SDL3+SDL_GPU: SDL_GPU is SDL3 new graphics abstraction API. +// - SDL3+DirectX, SDL3+OpenGL, SDL3+Vulkan: combine SDL with dedicated renderers. +// If your application wants to render any non trivial amount of graphics other than UI, +// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user +// and it might be difficult to step out of those boundaries. // Implemented features: // [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID! diff --git a/backends/imgui_impl_sdlrenderer3.h b/backends/imgui_impl_sdlrenderer3.h index 3a7a51ee545e..3473bcc77e00 100644 --- a/backends/imgui_impl_sdlrenderer3.h +++ b/backends/imgui_impl_sdlrenderer3.h @@ -1,13 +1,13 @@ // dear imgui: Renderer Backend for SDL_Renderer for SDL3 -// (Requires: SDL 3.0.0+) - -// (**IMPORTANT: SDL 3.0.0 is NOT YET RELEASED AND CURRENTLY HAS A FAST CHANGING API. THIS CODE BREAKS OFTEN AS SDL3 CHANGES.**) - -// Note how SDL_Renderer is an _optional_ component of SDL3. -// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX. -// If your application will want to render any non trivial amount of graphics other than UI, -// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user and -// it might be difficult to step out of those boundaries. +// (Requires: SDL 3.1.8+) + +// Note that SDL_Renderer is an _optional_ component of SDL3, which IMHO is now largely obsolete. +// For a multi-platform app consider using other technologies: +// - SDL3+SDL_GPU: SDL_GPU is SDL3 new graphics abstraction API. +// - SDL3+DirectX, SDL3+OpenGL, SDL3+Vulkan: combine SDL with dedicated renderers. +// If your application wants to render any non trivial amount of graphics other than UI, +// please be aware that SDL_Renderer currently offers a limited graphic API to the end-user +// and it might be difficult to step out of those boundaries. // Implemented features: // [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID! From 4c2e7bb03557dd28f0a6b6809c3466485cc4c3df Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 20 Jan 2025 15:24:46 +0100 Subject: [PATCH 393/548] Backends: SDL2,SDL3: removed assert preventing using ImGui_ImplSDL2_SetGamepadMode()/ImGui_ImplSDL3_SetGamepadMode() with ImGui_ImplSDL2_GamepadMode_Manual/ImGui_ImplSDL3_GamepadMode_Manual and an empty array. (#8329) --- backends/imgui_impl_sdl2.cpp | 3 ++- backends/imgui_impl_sdl3.cpp | 3 ++- docs/CHANGELOG.txt | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 0aaf9830a9c5..a27962a316bb 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-01-20: Made ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode_Manual) accept an empty array. // 2024-10-24: Emscripten: from SDL 2.30.9, SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f. // 2024-09-09: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) // 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: @@ -665,7 +666,7 @@ void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_ ImGui_ImplSDL2_CloseGamepads(); if (mode == ImGui_ImplSDL2_GamepadMode_Manual) { - IM_ASSERT(manual_gamepads_array != nullptr && manual_gamepads_count > 0); + IM_ASSERT(manual_gamepads_array != nullptr || manual_gamepads_count <= 0); for (int n = 0; n < manual_gamepads_count; n++) bd->Gamepads.push_back(manual_gamepads_array[n]); } diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index eb0eef89f5a5..d5de5443e244 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-01-20: Made ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode_Manual) accept an empty array. // 2024-10-24: Emscripten: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f on Emscripten. // 2024-09-03: Update for SDL3 api changes: SDL_GetGamepads() memory ownership revert. (#7918, #7898, #7807) // 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: @@ -635,7 +636,7 @@ void ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode mode, SDL_Gamepad* ImGui_ImplSDL3_CloseGamepads(); if (mode == ImGui_ImplSDL3_GamepadMode_Manual) { - IM_ASSERT(manual_gamepads_array != nullptr && manual_gamepads_count > 0); + IM_ASSERT(manual_gamepads_array != nullptr || manual_gamepads_count <= 0); for (int n = 0; n < manual_gamepads_count; n++) bd->Gamepads.push_back(manual_gamepads_array[n]); } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c81fc8df0a7c..17f62c386f66 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -58,6 +58,10 @@ Other changes: provided example, to reduce latency. - Examples: Vulkan: better handle VK_SUBOPTIMAL_KHR being returned by vkAcquireNextImageKHR() or vkQueuePresentKHR(). (#7825, #7831) [@NostraMagister] +- Backends: SDL2: removed assert preventing using ImGui_ImplSDL2_SetGamepadMode() + with ImGui_ImplSDL2_GamepadMode_Manual and an empty array. (#8329) +- Backends: SDL3: removed assert preventing using ImGui_ImplSDL3_SetGamepadMode() + with ImGui_ImplSDL3_GamepadMode_Manual and an empty array. (#8329) - Backends: SDLGPU3: Exposed ImGui_ImplSDLGPU3_CreateDeviceObjects()/_DestroyDeviceObjects(). Removed return value from ImGui_ImplSDLGPU3_CreateFontsTexture(). (#8163, #7998, #7988) - Backends: SDL_Renderer2/3: Use endian-dependent RGBA32 texture format, to match From e8779a67b1498ba345dc139a2b2303b17408e14b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 20 Jan 2025 17:55:09 +0100 Subject: [PATCH 394/548] Font: direct AddText()/RenderText() calls don't need to call strlen() if below clipping region. Unlikely to meaningful affect anyone but still.. --- imgui_draw.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 67a993de54c6..97342b35b7e2 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1669,8 +1669,7 @@ void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 // Accept null ranges if (text_begin == text_end || text_begin[0] == 0) return; - if (text_end == NULL) - text_end = text_begin + strlen(text_begin); + // No need to strlen() here: font->RenderText() will do it and may early out. // Pull default font/size from the shared ImDrawListSharedData instance if (font == NULL) @@ -1693,7 +1692,7 @@ void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) { - AddText(NULL, 0.0f, pos, col, text_begin, text_end); + AddText(_Data->Font, _Data->FontSize, pos, col, text_begin, text_end); } void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col) @@ -4125,15 +4124,15 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) { - if (!text_end) - text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. - // Align to be pixel perfect float x = IM_TRUNC(pos.x); float y = IM_TRUNC(pos.y); if (y > clip_rect.w) return; + if (!text_end) + text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. + const float scale = size / FontSize; const float line_height = FontSize * scale; const float origin_x = x; From 7ae7c9079038050a3c19d6e768d183301d8a303c Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 21 Jan 2025 13:55:44 +0100 Subject: [PATCH 395/548] Tabs, Style: reworked selected overline rendering to better accommodate for rounded tabs. (#8334) --- docs/CHANGELOG.txt | 4 ++++ imgui.cpp | 4 ++-- imgui_demo.cpp | 2 +- imgui_widgets.cpp | 20 +++++++++++++++----- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 17f62c386f66..ccb4882da23a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,10 @@ Other changes: - Windows: legacy SetWindowFontScale() is properly inherited by nested child windows. Note that an upcoming major release should make this obsolete, but in the meanwhile it works better now. (#2701, #8138, #1018) +- Tabs, Style: reworked selected overline rendering to better accommodate + for rounded tabs. Reduced default thickness (style.TabBarOverlineSize), + increased default rounding (style.TabRounding). (#8334) [@Kian738, @ocornut] + styles as the current look is not right (but ImGuiCol_TabSelectedOverline stays the same). - Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in provided example, to reduce latency. - Examples: Vulkan: better handle VK_SUBOPTIMAL_KHR being returned by diff --git a/imgui.cpp b/imgui.cpp index b326c444dc24..f448ab90d21e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1334,11 +1334,11 @@ ImGuiStyle::ImGuiStyle() GrabMinSize = 12.0f; // Minimum width/height of a grab box for slider/scrollbar GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. - TabRounding = 4.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. + TabRounding = 5.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. TabBorderSize = 0.0f; // Thickness of border around tabs. TabMinWidthForCloseButton = 0.0f; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. TabBarBorderSize = 1.0f; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. - TabBarOverlineSize = 2.0f; // Thickness of tab-bar overline, which highlights the selected tab-bar. + TabBarOverlineSize = 1.0f; // Thickness of tab-bar overline, which highlights the selected tab-bar. TableAngledHeadersAngle = 35.0f * (IM_PI / 180.0f); // Angle of angled headers (supported values range from -50 degrees to +50 degrees). TableAngledHeadersTextAlign = ImVec2(0.5f,0.0f);// Alignment of angled headers within the cell ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 26c246db68a9..e41c0ac5c500 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7966,7 +7966,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("TabBarBorderSize", &style.TabBarBorderSize, 0.0f, 2.0f, "%.0f"); - ImGui::SliderFloat("TabBarOverlineSize", &style.TabBarOverlineSize, 0.0f, 2.0f, "%.0f"); + ImGui::SliderFloat("TabBarOverlineSize", &style.TabBarOverlineSize, 0.0f, 3.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Overline is only drawn over the selected tab when ImGuiTabBarFlags_DrawSelectedOverline is set."); ImGui::SeparatorText("Rounding"); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 71a5c5b9a00e..4f58c4cd2332 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -10150,11 +10150,21 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, TabItemBackground(display_draw_list, bb, flags, tab_col); if (tab_contents_visible && (tab_bar->Flags & ImGuiTabBarFlags_DrawSelectedOverline) && style.TabBarOverlineSize > 0.0f) { - float x_offset = IM_TRUNC(0.4f * style.TabRounding); - if (x_offset < 2.0f * g.CurrentDpiScale) - x_offset = 0.0f; - float y_offset = 1.0f * g.CurrentDpiScale; - display_draw_list->AddLine(bb.GetTL() + ImVec2(x_offset, y_offset), bb.GetTR() + ImVec2(-x_offset, y_offset), GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline), style.TabBarOverlineSize); + // Might be moved to TabItemBackground() ? + ImVec2 tl = bb.GetTL() + ImVec2(0, 1.0f * g.CurrentDpiScale); + ImVec2 tr = bb.GetTR() + ImVec2(0, 1.0f * g.CurrentDpiScale); + ImU32 overline_col = GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline); + if (style.TabRounding > 0.0f) + { + float rounding = style.TabRounding; + display_draw_list->PathArcToFast(tl + ImVec2(+rounding, +rounding), rounding, 7, 9); + display_draw_list->PathArcToFast(tr + ImVec2(-rounding, +rounding), rounding, 9, 11); + display_draw_list->PathStroke(overline_col, 0, style.TabBarOverlineSize); + } + else + { + display_draw_list->AddLine(tl - ImVec2(0.5f, 0.5f), tr - ImVec2(0.5f, 0.5f), overline_col, style.TabBarOverlineSize); + } } RenderNavCursor(bb, id); From 2af26b75d13e6f2be97c53d2d3ebf17b1b18a150 Mon Sep 17 00:00:00 2001 From: David Maas Date: Tue, 21 Jan 2025 14:25:39 +0100 Subject: [PATCH 396/548] ColorEdit, ColorPicker: Fixed alpha preview broken in 1.91.7. (#8336, #8241). [@PathogenDavid] ImAlphaBlendColors() was broken by ImLerp() change. (cd6c83c) --- docs/CHANGELOG.txt | 1 + imgui_internal.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ccb4882da23a..c7f26c3b7617 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,7 @@ Other changes: - Windows: legacy SetWindowFontScale() is properly inherited by nested child windows. Note that an upcoming major release should make this obsolete, but in the meanwhile it works better now. (#2701, #8138, #1018) +- ColorEdit, ColorPicker: Fixed alpha preview broken in 1.91.7. (#8336, #8241). [@PathogenDavid] - Tabs, Style: reworked selected overline rendering to better accommodate for rounded tabs. Reduced default thickness (style.TabBarOverlineSize), increased default rounding (style.TabRounding). (#8334) [@Kian738, @ocornut] diff --git a/imgui_internal.h b/imgui_internal.h index 736031d32e4d..33a6ec8b0bc5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -469,7 +469,7 @@ static inline double ImRsqrt(double x) { return 1.0 / sqrt(x); } template static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; } template static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; } template static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } -template static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * (T)t); } +template static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); } template static inline void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; } template static inline T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; } template static inline T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; } From bf13442c7cf4a082466dae31d50981ec103a7af7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 21 Jan 2025 14:59:29 +0100 Subject: [PATCH 397/548] Moved ImGuiColorEditFlags_AlphaPreview/ImGuiColorEditFlags_AlphaPreviewHalf flags. Demo: reorganized some of color edit/picker demo section. --- imgui.h | 4 ++-- imgui_demo.cpp | 65 +++++++++++++++++++++++++------------------------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/imgui.h b/imgui.h index 82903424a886..2306667cf9dc 100644 --- a/imgui.h +++ b/imgui.h @@ -1752,11 +1752,11 @@ enum ImGuiColorEditFlags_ ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small color square preview instead. ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source. ImGuiColorEditFlags_NoBorder = 1 << 10, // // ColorButton: disable border (which is enforced by default) + ImGuiColorEditFlags_AlphaPreview = 1 << 11, // // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque. + ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 12, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque. // User Options (right-click on widget to change some of them). ImGuiColorEditFlags_AlphaBar = 1 << 16, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. - ImGuiColorEditFlags_AlphaPreview = 1 << 17, // // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque. - ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 18, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque. ImGuiColorEditFlags_HDR = 1 << 19, // // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well). ImGuiColorEditFlags_DisplayRGB = 1 << 20, // [Display] // ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex. ImGuiColorEditFlags_DisplayHSV = 1 << 21, // [Display] // " diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e41c0ac5c500..5100356b38a9 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2117,19 +2117,15 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) if (ImGui::TreeNode("Color/Picker Widgets")) { static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f); + static ImGuiColorEditFlags base_flags = ImGuiColorEditFlags_AlphaPreview; - static bool alpha_preview = true; - static bool alpha_half_preview = false; - static bool drag_and_drop = true; - static bool options_menu = true; - static bool hdr = false; ImGui::SeparatorText("Options"); - ImGui::Checkbox("With Alpha Preview", &alpha_preview); - ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview); - ImGui::Checkbox("With Drag and Drop", &drag_and_drop); - ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options."); - ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets."); - ImGuiColorEditFlags misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions); + ImGui::CheckboxFlags("ImGuiColorEditFlags_NoAlpha", &base_flags, ImGuiColorEditFlags_NoAlpha); + ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaPreview", &base_flags, ImGuiColorEditFlags_AlphaPreview); + ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaPreviewHalf", &base_flags, ImGuiColorEditFlags_AlphaPreviewHalf); + ImGui::CheckboxFlags("ImGuiColorEditFlags_NoDragDrop", &base_flags, ImGuiColorEditFlags_NoDragDrop); + ImGui::CheckboxFlags("ImGuiColorEditFlags_NoOptions", &base_flags, ImGuiColorEditFlags_NoOptions); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options."); + ImGui::CheckboxFlags("ImGuiColorEditFlags_HDR", &base_flags, ImGuiColorEditFlags_HDR); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets."); IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit"); ImGui::SeparatorText("Inline color editor"); @@ -2137,15 +2133,15 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::SameLine(); HelpMarker( "Click on the color square to open a color picker.\n" "CTRL+click on individual component to input value.\n"); - ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags); + ImGui::ColorEdit3("MyColor##1", (float*)&color, base_flags); IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (HSV, with Alpha)"); ImGui::Text("Color widget HSV with Alpha:"); - ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | misc_flags); + ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | base_flags); IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (float display)"); ImGui::Text("Color widget with Float Display:"); - ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags); + ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | base_flags); IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with Picker)"); ImGui::Text("Color button with Picker:"); @@ -2153,7 +2149,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n" "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only " "be used for the tooltip and picker popup."); - ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags); + ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | base_flags); IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with custom Picker popup)"); ImGui::Text("Color button with Custom Picker Popup:"); @@ -2173,7 +2169,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) } static ImVec4 backup_color; - bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags); + bool open_popup = ImGui::ColorButton("MyColor##3b", color, base_flags); ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); open_popup |= ImGui::Button("Palette"); if (open_popup) @@ -2185,7 +2181,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) { ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!"); ImGui::Separator(); - ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview); + ImGui::ColorPicker4("##picker", (float*)&color, base_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview); ImGui::SameLine(); ImGui::BeginGroup(); // Lock X position @@ -2227,40 +2223,42 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::Text("Color button only:"); static bool no_border = false; ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border); - ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80)); + ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, base_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80)); IMGUI_DEMO_MARKER("Widgets/Color/ColorPicker"); ImGui::SeparatorText("Color picker"); - static bool alpha = true; - static bool alpha_bar = true; - static bool side_preview = true; + static bool ref_color = false; static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f); - static int display_mode = 0; static int picker_mode = 0; - ImGui::Checkbox("With Alpha", &alpha); - ImGui::Checkbox("With Alpha Bar", &alpha_bar); - ImGui::Checkbox("With Side Preview", &side_preview); - if (side_preview) + static int display_mode = 0; + static ImGuiColorEditFlags color_picker_flags = ImGuiColorEditFlags_AlphaBar; + + ImGui::PushID("Color picker"); + ImGui::CheckboxFlags("ImGuiColorEditFlags_NoAlpha", &color_picker_flags, ImGuiColorEditFlags_NoAlpha); + ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaBar", &color_picker_flags, ImGuiColorEditFlags_AlphaBar); + ImGui::CheckboxFlags("ImGuiColorEditFlags_NoSidePreview", &color_picker_flags, ImGuiColorEditFlags_NoSidePreview); + if (color_picker_flags & ImGuiColorEditFlags_NoSidePreview) { ImGui::SameLine(); ImGui::Checkbox("With Ref Color", &ref_color); if (ref_color) { ImGui::SameLine(); - ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags); + ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | base_flags); } } - ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0"); + + ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0ImGuiColorEditFlags_PickerHueBar\0ImGuiColorEditFlags_PickerHueWheel\0"); + ImGui::SameLine(); HelpMarker("When not specified explicitly, user can right-click the picker to change mode."); + + ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0ImGuiColorEditFlags_NoInputs\0ImGuiColorEditFlags_DisplayRGB\0ImGuiColorEditFlags_DisplayHSV\0ImGuiColorEditFlags_DisplayHex\0"); ImGui::SameLine(); HelpMarker( "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, " "but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex " "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions()."); - ImGui::SameLine(); HelpMarker("When not specified explicitly (Auto/Current mode), user can right-click the picker to change mode."); - ImGuiColorEditFlags flags = misc_flags; - if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4() - if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar; - if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview; + + ImGuiColorEditFlags flags = base_flags | color_picker_flags; if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar; if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel; if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs; // Disable all RGB/HSV/Hex displays @@ -2289,6 +2287,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::SameLine(); ImGui::SetNextItemWidth(w); ImGui::ColorPicker3("##MyColor##6", (float*)&color, ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha); + ImGui::PopID(); // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0) static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV! From 3e6bdc2242ca2e29346b380f76212e64e480a146 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Jan 2025 10:22:31 +0100 Subject: [PATCH 398/548] Examples: SDL3+SDL_GPU: use SDL_GPU_PRESENTMODE_MAILBOX swapchain parameters. --- examples/example_sdl3_sdlgpu3/main.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/example_sdl3_sdlgpu3/main.cpp b/examples/example_sdl3_sdlgpu3/main.cpp index 1077639e7fea..dbc7759ba5d5 100644 --- a/examples/example_sdl3_sdlgpu3/main.cpp +++ b/examples/example_sdl3_sdlgpu3/main.cpp @@ -7,7 +7,7 @@ // - Introduction, links and more at the top of imgui.cpp // Important note to the reader who wish to integrate imgui_impl_sdlgpu3.cpp/.h in their own engine/app. -// - Unline other backends, the user must call the function Imgui_ImplSDLGPU_PrepareDrawData BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData. +// - Unlike other backends, the user must call the function Imgui_ImplSDLGPU_PrepareDrawData() BEFORE issuing a SDL_GPURenderPass containing ImGui_ImplSDLGPU_RenderDrawData. // Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info. #include "imgui.h" @@ -54,6 +54,7 @@ int main(int, char**) printf("Error: SDL_ClaimWindowForGPUDevice(): %s\n", SDL_GetError()); return -1; } + SDL_SetGPUSwapchainParameters(gpu_device, window, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_MAILBOX); // Setup Dear ImGui context IMGUI_CHECKVERSION(); @@ -140,7 +141,7 @@ int main(int, char**) ImGui::Checkbox("Another Window", &show_another_window); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + ImGui::ColorEdit4("clear color", (float*)&clear_color); // Edit 3 floats representing a color if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated) counter++; @@ -179,7 +180,7 @@ int main(int, char**) // Setup and start a render pass SDL_GPUColorTargetInfo target_info = {}; target_info.texture = swapchain_texture; - target_info.clear_color = SDL_FColor{ clear_color.x,clear_color.y,clear_color.z,clear_color.w }; + target_info.clear_color = SDL_FColor { clear_color.x, clear_color.y, clear_color.z, clear_color.w }; target_info.load_op = SDL_GPU_LOADOP_CLEAR; target_info.store_op = SDL_GPU_STOREOP_STORE; target_info.mip_level = 0; @@ -196,6 +197,7 @@ int main(int, char**) // Submit the command buffer SDL_SubmitGPUCommandBuffer(command_buffer); } + // Cleanup SDL_WaitForGPUIdle(gpu_device); ImGui_ImplSDL3_Shutdown(); From d17e9fc107ef561743e335aaa62641fcd8ce1952 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Jan 2025 10:32:09 +0100 Subject: [PATCH 399/548] Backends: SDL_GPU: shallow tweaks + disable anisotropy in sampler. Examples: SDL+Vulkan: Fixed incorrect defines. --- backends/imgui_impl_sdlgpu3.cpp | 13 +++++++------ examples/example_sdl2_vulkan/main.cpp | 2 +- examples/example_sdl3_vulkan/main.cpp | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/backends/imgui_impl_sdlgpu3.cpp b/backends/imgui_impl_sdlgpu3.cpp index b508e091aa31..74b966227ddd 100644 --- a/backends/imgui_impl_sdlgpu3.cpp +++ b/backends/imgui_impl_sdlgpu3.cpp @@ -89,8 +89,8 @@ static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGra SDL_GPUBufferBinding index_buffer_binding = {}; index_buffer_binding.buffer = fd->IndexBuffer; index_buffer_binding.offset = 0; - SDL_BindGPUVertexBuffers(render_pass,0,&vertex_buffer_binding,1); - SDL_BindGPUIndexBuffer(render_pass,&index_buffer_binding,sizeof(ImDrawIdx) == 2 ? SDL_GPU_INDEXELEMENTSIZE_16BIT : SDL_GPU_INDEXELEMENTSIZE_32BIT); + SDL_BindGPUVertexBuffers(render_pass,0, &vertex_buffer_binding, 1); + SDL_BindGPUIndexBuffer(render_pass, &index_buffer_binding, sizeof(ImDrawIdx) == 2 ? SDL_GPU_INDEXELEMENTSIZE_16BIT : SDL_GPU_INDEXELEMENTSIZE_32BIT); } // Setup viewport @@ -101,7 +101,7 @@ static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, SDL_GPUGra viewport.h = (float)fb_height; viewport.min_depth = 0.0f; viewport.max_depth = 1.0f; - SDL_SetGPUViewport(render_pass,&viewport); + SDL_SetGPUViewport(render_pass, &viewport); // Setup scale and translation // Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. @@ -118,6 +118,7 @@ static void CreateOrResizeBuffer(SDL_GPUBuffer** buffer, uint32_t* old_size, uin ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); ImGui_ImplSDLGPU3_InitInfo* v = &bd->InitInfo; + // Even though this is fairly rarely called. SDL_WaitForGPUIdle(v->Device); SDL_ReleaseGPUBuffer(v->Device, *buffer); @@ -196,8 +197,8 @@ void Imgui_ImplSDLGPU3_PrepareDrawData(ImDrawData* draw_data, SDL_GPUCommandBuff index_buffer_region.size = index_size; SDL_GPUCopyPass* copy_pass = SDL_BeginGPUCopyPass(command_buffer); - SDL_UploadToGPUBuffer(copy_pass, &vertex_buffer_location, &vertex_buffer_region,true); - SDL_UploadToGPUBuffer(copy_pass, &index_buffer_location, &index_buffer_region,true); + SDL_UploadToGPUBuffer(copy_pass, &vertex_buffer_location, &vertex_buffer_region, true); + SDL_UploadToGPUBuffer(copy_pass, &index_buffer_location, &index_buffer_region, true); SDL_EndGPUCopyPass(copy_pass); SDL_ReleaseGPUTransferBuffer(v->Device, index_transferbuffer); SDL_ReleaseGPUTransferBuffer(v->Device, vertex_transferbuffer); @@ -527,7 +528,7 @@ void ImGui_ImplSDLGPU3_CreateDeviceObjects() sampler_info.mip_lod_bias = 0.0f; sampler_info.min_lod = -1000.0f; sampler_info.max_lod = 1000.0f; - sampler_info.enable_anisotropy = true; + sampler_info.enable_anisotropy = false; sampler_info.max_anisotropy = 1.0f; sampler_info.enable_compare = false; diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 0d7a4586e0c8..c0282f9328f7 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -217,7 +217,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); // Select Present Mode -#ifdef APP_UNLIMITED_FRAME_RATE +#ifdef APP_USE_UNLIMITED_FRAME_RATE VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR }; #else VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index 81f0581e97a9..52544c34229a 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -222,7 +222,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); // Select Present Mode -#ifdef APP_UNLIMITED_FRAME_RATE +#ifdef APP_USE_UNLIMITED_FRAME_RATE VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR }; #else VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR }; From fdca6c08adbd71f711261e28f4d75124c14d1cc5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Jan 2025 11:28:47 +0100 Subject: [PATCH 400/548] Inputs: added IsMouseReleasedWithDelay() helper. (#8337, #8320) --- docs/CHANGELOG.txt | 6 ++++++ imgui.cpp | 13 +++++++++++++ imgui.h | 2 ++ imgui_demo.cpp | 2 ++ 4 files changed, 23 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c7f26c3b7617..3cce5f1c3efa 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,12 @@ Other changes: snapped to pixels. Effectively it would only be noticeable when hinting is disabled with ImGuiFreeTypeBuilderFlags_NoHinting, as hinting itself snaps glyph advances. +- Inputs: added IsMouseReleasedWithDelay() helper. (#8337, #8320) + Use if you absolutely need to distinguish single-click from double-clicks + by introducing a delay. This is a very rarely used UI idiom, but some apps + use this: e.g. MS Explorer single-click on an icon triggers a rename. + Generally use with 'delay >= io.MouseDoubleClickTime' + combine with a + 'io.MouseClickedLastCount == 1' check. - Windows: legacy SetWindowFontScale() is properly inherited by nested child windows. Note that an upcoming major release should make this obsolete, but in the meanwhile it works better now. (#2701, #8138, #1018) diff --git a/imgui.cpp b/imgui.cpp index f448ab90d21e..90639578e652 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9210,6 +9210,17 @@ bool ImGui::IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id) return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), owner_id); // Should be same as IsKeyReleased(MouseButtonToKey(button), owner_id) } +// Use if you absolutely need to distinguish single-click from double-click by introducing a delay. +// Generally use with 'delay >= io.MouseDoubleClickTime' + combined with a 'io.MouseClickedLastCount == 1' test. +// This is a very rarely used UI idiom, but some apps use this: e.g. MS Explorer single click on an icon to rename. +bool ImGui::IsMouseReleasedWithDelay(ImGuiMouseButton button, float delay) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); + const float time_since_release = (float)(g.Time - g.IO.MouseReleasedTime[button]); + return !IsMouseDown(button) && (time_since_release - g.IO.DeltaTime < delay) && (time_since_release >= delay); +} + bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button) { ImGuiContext& g = *GImGui; @@ -9483,6 +9494,8 @@ static void ImGui::UpdateMouseInputs() io.MouseClicked[i] = io.MouseDown[i] && io.MouseDownDuration[i] < 0.0f; io.MouseClickedCount[i] = 0; // Will be filled below io.MouseReleased[i] = !io.MouseDown[i] && io.MouseDownDuration[i] >= 0.0f; + if (io.MouseReleased[i]) + io.MouseReleasedTime[i] = g.Time; io.MouseDownDurationPrev[i] = io.MouseDownDuration[i]; io.MouseDownDuration[i] = io.MouseDown[i] ? (io.MouseDownDuration[i] < 0.0f ? 0.0f : io.MouseDownDuration[i] + io.DeltaTime) : -1.0f; if (io.MouseClicked[i]) diff --git a/imgui.h b/imgui.h index 2306667cf9dc..e27c3a3d1056 100644 --- a/imgui.h +++ b/imgui.h @@ -1011,6 +1011,7 @@ namespace ImGui IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down). Same as GetMouseClickedCount() == 1. IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down) IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? Same as GetMouseClickedCount() == 2. (note that a double-click will also report IsMouseClicked() == true) + IMGUI_API bool IsMouseReleasedWithDelay(ImGuiMouseButton button, float delay); // delayed mouse release (use very sparingly!). Generally used with 'delay >= io.MouseDoubleClickTime' + combined with a 'io.MouseClickedLastCount==1' test. This is a very rarely used UI idiom, but some apps use this: e.g. MS Explorer single click on an icon to rename. IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0). IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block. IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available @@ -2405,6 +2406,7 @@ struct ImGuiIO ImU16 MouseClickedCount[5]; // == 0 (not clicked), == 1 (same as MouseClicked[]), == 2 (double-clicked), == 3 (triple-clicked) etc. when going from !Down to Down ImU16 MouseClickedLastCount[5]; // Count successive number of clicks. Stays valid after mouse release. Reset after another click is done. bool MouseReleased[5]; // Mouse button went from Down to !Down + double MouseReleasedTime[5]; // Time of last released (rarely used! but useful to handle delayed single-click when trying to disambiguate them from double-click). bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds. bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window. bool MouseWheelRequestAxisSwap; // On a non-Mac system, holding SHIFT requests WheelY to perform the equivalent of a WheelX event. On a Mac system this is already enforced by the system. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5100356b38a9..9f6264a5d279 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7407,6 +7407,8 @@ static void ShowDemoWindowInputs() ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDown(i)) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } ImGui::Text("Mouse wheel: %.1f", io.MouseWheel); + ImGui::Text("Mouse clicked count:"); + for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseClickedCount[i] > 0) { ImGui::SameLine(); ImGui::Text("b%d: %d", i, io.MouseClickedCount[i]); } // We iterate both legacy native range and named ImGuiKey ranges. This is a little unusual/odd but this allows // displaying the data for old/new backends. From 6906ac979e51ca9b2b60f3d820dd43f8f689884c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Jan 2025 12:12:07 +0100 Subject: [PATCH 401/548] ColorEdit, ColorPicker: (Breaking) redesigned how alpha is displayed in the preview square. (#8335, #1578, #346) Added ImGuiColorEditFlags_AlphaOpaque, ImGuiColorEditFlags_AlphaNoBg. Removed ImGuiColorEditFlags_AlphaPreview. --- docs/CHANGELOG.txt | 8 ++++++++ imgui.cpp | 3 +++ imgui.h | 16 +++++++++++++--- imgui_demo.cpp | 11 ++++++----- imgui_widgets.cpp | 22 +++++++++++++--------- 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3cce5f1c3efa..f0aeebbb34cf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,14 @@ HOW TO UPDATE? Breaking changes: +- ColorEdit, ColorPicker: redesigned how alpha is displayed in the preview square. (#8335, #1578, #346) + - Removed ImGuiColorEditFlags_AlphaPreview (made value 0): it is now the default behavior. + - Prior to 1.91.8: alpha was made opaque in the preview by default _unless_ using ImGuiColorEditFlags_AlphaPreview. + - We now display the preview as transparent by default. You can use ImGuiColorEditFlags_AlphaOpaque to use old behavior. + - The new flags may be combined better and allow finer controls: + - ImGuiColorEditFlags_AlphaOpaque: disable alpha in the preview, but alpha value still editable. + - ImGuiColorEditFlags_AlphaNoBg: disable rendering a checkerboard background behind transparent color. + - ImGuiColorEditFlags_AlphaPreviewHalf: display half opaque / half transparent preview. - Backends: SDLGPU3: Renamed ImGui_ImplSDLGPU3_InitInfo::GpuDevice to Device for consistency. (#8163, #7998, #7988) diff --git a/imgui.cpp b/imgui.cpp index 90639578e652..0b988f2b47ec 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -430,6 +430,9 @@ 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. + - 2025/01/22 (1.91.8) - removed ImGuiColorEditFlags_AlphaPreview (made value 0): it is now the default behavior. + prior to 1.91.8: alpha was made opaque in the preview by default _unless_ using ImGuiColorEditFlags_AlphaPreview. We now display the preview as transparent by default. You can use ImGuiColorEditFlags_AlphaOpaque to use old behavior. + the new flags (ImGuiColorEditFlags_AlphaOpaque, ImGuiColorEditFlags_AlphaNoBg + existing ImGuiColorEditFlags_AlphaPreviewHalf) may be combined better and allow finer controls: - 2025/01/14 (1.91.7) - renamed ImGuiTreeNodeFlags_SpanTextWidth to ImGuiTreeNodeFlags_SpanLabelWidth for consistency with other names. Kept redirection enum (will obsolete). (#6937) - 2024/11/27 (1.91.6) - changed CRC32 table from CRC32-adler to CRC32c polynomial in order to be compatible with the result of SSE 4.2 instructions. As a result, old .ini data may be partially lost (docking and tables information particularly). diff --git a/imgui.h b/imgui.h index e27c3a3d1056..d42a932c296f 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.8 WIP" -#define IMGUI_VERSION_NUM 19172 +#define IMGUI_VERSION_NUM 19173 #define IMGUI_HAS_TABLE /* @@ -1753,8 +1753,14 @@ enum ImGuiColorEditFlags_ ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small color square preview instead. ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source. ImGuiColorEditFlags_NoBorder = 1 << 10, // // ColorButton: disable border (which is enforced by default) - ImGuiColorEditFlags_AlphaPreview = 1 << 11, // // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque. - ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 12, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque. + + // Alpha preview + // - Prior to 1.91.8 (2025/01/21): alpha was made opaque in the preview by default using old name ImGuiColorEditFlags_AlphaPreview. + // - We now display the preview as transparent by default. You can use ImGuiColorEditFlags_AlphaOpaque to use old behavior. + // - The new flags may be combined better and allow finer controls. + ImGuiColorEditFlags_AlphaOpaque = 1 << 11, // // ColorEdit, ColorPicker, ColorButton: disable alpha in the preview,. Contrary to _NoAlpha it may still be edited when calling ColorEdit4()/ColorPicker4(). For ColorButton() this does the same as _NoAlpha. + ImGuiColorEditFlags_AlphaNoBg = 1 << 12, // // ColorEdit, ColorPicker, ColorButton: disable rendering a checkerboard background behind transparent color. + ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 13, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half transparent preview. // User Options (right-click on widget to change some of them). ImGuiColorEditFlags_AlphaBar = 1 << 16, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. @@ -1774,12 +1780,16 @@ enum ImGuiColorEditFlags_ ImGuiColorEditFlags_DefaultOptions_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar, // [Internal] Masks + ImGuiColorEditFlags_AlphaMask_ = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaOpaque | ImGuiColorEditFlags_AlphaNoBg | ImGuiColorEditFlags_AlphaPreviewHalf, ImGuiColorEditFlags_DisplayMask_ = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex, ImGuiColorEditFlags_DataTypeMask_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float, ImGuiColorEditFlags_PickerMask_ = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar, ImGuiColorEditFlags_InputMask_ = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV, // Obsolete names +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + ImGuiColorEditFlags_AlphaPreview = 0, // [Removed in 1.91.8] This is the default now. Will display a checkerboard unless ImGuiColorEditFlags_AlphaNoBg is set. +#endif //ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex // [renamed in 1.69] }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9f6264a5d279..43344f3fc543 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2117,11 +2117,12 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) if (ImGui::TreeNode("Color/Picker Widgets")) { static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f); - static ImGuiColorEditFlags base_flags = ImGuiColorEditFlags_AlphaPreview; + static ImGuiColorEditFlags base_flags = ImGuiColorEditFlags_None; ImGui::SeparatorText("Options"); ImGui::CheckboxFlags("ImGuiColorEditFlags_NoAlpha", &base_flags, ImGuiColorEditFlags_NoAlpha); - ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaPreview", &base_flags, ImGuiColorEditFlags_AlphaPreview); + ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaOpaque", &base_flags, ImGuiColorEditFlags_AlphaOpaque); + ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaNoBg", &base_flags, ImGuiColorEditFlags_AlphaNoBg); ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaPreviewHalf", &base_flags, ImGuiColorEditFlags_AlphaPreviewHalf); ImGui::CheckboxFlags("ImGuiColorEditFlags_NoDragDrop", &base_flags, ImGuiColorEditFlags_NoDragDrop); ImGui::CheckboxFlags("ImGuiColorEditFlags_NoOptions", &base_flags, ImGuiColorEditFlags_NoOptions); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options."); @@ -8047,9 +8048,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) filter.Draw("Filter colors", ImGui::GetFontSize() * 16); static ImGuiColorEditFlags alpha_flags = 0; - if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None)) { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine(); - if (ImGui::RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_AlphaPreview)) { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine(); - if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine(); + if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_AlphaOpaque)) { alpha_flags = ImGuiColorEditFlags_AlphaOpaque; } ImGui::SameLine(); + if (ImGui::RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_None)) { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine(); + if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine(); HelpMarker( "In the color list:\n" "Left-click on color square to open color picker,\n" diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 4f58c4cd2332..e0fec9122b4d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5902,7 +5902,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl if ((flags & ImGuiColorEditFlags_NoLabel)) Text("Current"); - ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_NoTooltip; + ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaMask_ | ImGuiColorEditFlags_NoTooltip; ColorButton("##current", col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2)); if (ref_col != NULL) { @@ -5942,7 +5942,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl if ((flags & ImGuiColorEditFlags_NoInputs) == 0) { PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x); - ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf; + ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaMask_ | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSmallPreview; ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker; if (flags & ImGuiColorEditFlags_DisplayRGB || (flags & ImGuiColorEditFlags_DisplayMask_) == 0) if (ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_DisplayRGB)) @@ -6118,8 +6118,8 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); - if (flags & ImGuiColorEditFlags_NoAlpha) - flags &= ~(ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf); + if (flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaOpaque)) + flags &= ~(ImGuiColorEditFlags_AlphaNoBg | ImGuiColorEditFlags_AlphaPreviewHalf); ImVec4 col_rgb = col; if (flags & ImGuiColorEditFlags_InputHSV) @@ -6138,14 +6138,17 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f) { float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f); - RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawFlags_RoundCornersRight); + if ((flags & ImGuiColorEditFlags_AlphaNoBg) == 0) + RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawFlags_RoundCornersRight); + else + window->DrawList->AddRectFilled(ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), rounding, ImDrawFlags_RoundCornersRight); window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawFlags_RoundCornersLeft); } else { // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha - ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col_rgb : col_rgb_without_alpha; - if (col_source.w < 1.0f) + ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaOpaque) ? col_rgb_without_alpha : col_rgb; + if (col_source.w < 1.0f && (flags & ImGuiColorEditFlags_AlphaNoBg) == 0) RenderColorRectWithAlphaCheckerboard(window->DrawList, bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding); else window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding); @@ -6175,7 +6178,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl // Tooltip if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered && IsItemHovered(ImGuiHoveredFlags_ForTooltip)) - ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); + ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_AlphaMask_)); return pressed; } @@ -6216,7 +6219,8 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2); ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); - ColorButton("##preview", cf, (flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz); + ImGuiColorEditFlags flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_AlphaMask_; + ColorButton("##preview", cf, (flags & flags_to_forward) | ImGuiColorEditFlags_NoTooltip, sz); SameLine(); if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags_InputMask_)) { From 71da34c48cf70f1f553a7a8b4edfbb0babdcfbef Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Jan 2025 16:56:18 +0100 Subject: [PATCH 402/548] Debug Tools: Tweaked font preview + indent "Glyphs" block. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 99 +++++++++++++++++++++++++--------------------- 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f0aeebbb34cf..ab01011c7616 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -73,6 +73,7 @@ Other changes: for rounded tabs. Reduced default thickness (style.TabBarOverlineSize), increased default rounding (style.TabRounding). (#8334) [@Kian738, @ocornut] styles as the current look is not right (but ImGuiCol_TabSelectedOverline stays the same). +- Debug Tools: Tweaked font preview. - Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in provided example, to reduce latency. - Examples: Vulkan: better handle VK_SUBOPTIMAL_KHR being returned by diff --git a/imgui.cpp b/imgui.cpp index 0b988f2b47ec..0fe7c820935c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16147,18 +16147,24 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co // [DEBUG] Display details for a single font, called by ShowStyleEditor(). void ImGui::DebugNodeFont(ImFont* font) { - bool opened = TreeNode(font, "Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)", + bool opened = TreeNode(font, "Font: \"%s\": %.2f px, %d glyphs, %d sources(s)", font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount); - SameLine(); - if (SmallButton("Set as default")) - GetIO().FontDefault = font; - if (!opened) - return; // Display preview text + if (!opened) + Indent(); + Indent(); PushFont(font); Text("The quick brown fox jumps over the lazy dog"); PopFont(); + if (!opened) + { + Unindent(); + Unindent(); + return; + } + if (SmallButton("Set as default")) + GetIO().FontDefault = font; // Display details SetNextItemWidth(GetFontSize() * 8); @@ -16182,57 +16188,60 @@ void ImGui::DebugNodeFont(ImFont* font) config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y); // Display all glyphs of the fonts in separate pages of 256 characters - if (TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) { - ImDrawList* draw_list = GetWindowDrawList(); - const ImU32 glyph_col = GetColorU32(ImGuiCol_Text); - const float cell_size = font->FontSize * 1; - const float cell_spacing = GetStyle().ItemSpacing.y; - for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256) + if (TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) { - // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k) - // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT - // is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here) - if (!(base & 8191) && font->IsGlyphRangeUnused(base, base + 8191)) + ImDrawList* draw_list = GetWindowDrawList(); + const ImU32 glyph_col = GetColorU32(ImGuiCol_Text); + const float cell_size = font->FontSize * 1; + const float cell_spacing = GetStyle().ItemSpacing.y; + for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256) { - base += 8192 - 256; - continue; - } - - int count = 0; - for (unsigned int n = 0; n < 256; n++) - if (font->FindGlyphNoFallback((ImWchar)(base + n))) - count++; - if (count <= 0) - continue; - if (!TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph")) - continue; + // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k) + // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT + // is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here) + if (!(base & 8191) && font->IsGlyphRangeUnused(base, base + 8191)) + { + base += 8192 - 256; + continue; + } - // Draw a 16x16 grid of glyphs - ImVec2 base_pos = GetCursorScreenPos(); - for (unsigned int n = 0; n < 256; n++) - { - // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions - // available here and thus cannot easily generate a zero-terminated UTF-8 encoded string. - ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing)); - ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size); - const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n)); - draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50)); - if (!glyph) + int count = 0; + for (unsigned int n = 0; n < 256; n++) + if (font->FindGlyphNoFallback((ImWchar)(base + n))) + count++; + if (count <= 0) + continue; + if (!TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph")) continue; - font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n)); - if (IsMouseHoveringRect(cell_p1, cell_p2) && BeginTooltip()) + + // Draw a 16x16 grid of glyphs + ImVec2 base_pos = GetCursorScreenPos(); + for (unsigned int n = 0; n < 256; n++) { - DebugNodeFontGlyph(font, glyph); - EndTooltip(); + // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions + // available here and thus cannot easily generate a zero-terminated UTF-8 encoded string. + ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing)); + ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size); + const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n)); + draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50)); + if (!glyph) + continue; + font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n)); + if (IsMouseHoveringRect(cell_p1, cell_p2) && BeginTooltip()) + { + DebugNodeFontGlyph(font, glyph); + EndTooltip(); + } } + Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16)); + TreePop(); } - Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16)); TreePop(); } - TreePop(); } TreePop(); + Unindent(); } void ImGui::DebugNodeFontGlyph(ImFont*, const ImFontGlyph* glyph) From 10199341b1d5c193a9f2748fdeeeac2e57ce354e Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 Jan 2025 11:31:32 +0100 Subject: [PATCH 403/548] ImFontAtlas: made calling ClearFonts() call ClearInputData(). (#8174, #6556, #6336, #4723) --- docs/CHANGELOG.txt | 4 +++- imgui.h | 2 +- imgui_draw.cpp | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ab01011c7616..f0021b2ab49c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,7 +54,6 @@ Breaking changes: Other changes: -- ImDrawList: texture baked storage for thick line reduced from ~64x64 to ~32x32. (#3245) - imgui_freetype: fixed issue where glyph advances would incorrectly be snapped to pixels. Effectively it would only be noticeable when hinting is disabled with ImGuiFreeTypeBuilderFlags_NoHinting, as hinting itself @@ -74,6 +73,9 @@ Other changes: increased default rounding (style.TabRounding). (#8334) [@Kian738, @ocornut] styles as the current look is not right (but ImGuiCol_TabSelectedOverline stays the same). - Debug Tools: Tweaked font preview. +- ImDrawList: texture baked storage for thick line reduced from ~64x64 to ~32x32. (#3245) +- ImFontAtlas: made calling ClearFonts() call ClearInputData(), as calling + one without the other is never correct. (#8174, #6556, #6336, #4723) - Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in provided example, to reduce latency. - Examples: Vulkan: better handle VK_SUBOPTIMAL_KHR being returned by diff --git a/imgui.h b/imgui.h index d42a932c296f..48910ea753e0 100644 --- a/imgui.h +++ b/imgui.h @@ -3355,8 +3355,8 @@ struct ImFontAtlas IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_data_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. IMGUI_API void ClearInputData(); // Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts. + IMGUI_API void ClearFonts(); // Clear input+output font data (same as ClearInputData() + glyphs storage, UV coordinates). IMGUI_API void ClearTexData(); // Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory. - IMGUI_API void ClearFonts(); // Clear output font data (glyphs storage, UV coordinates). IMGUI_API void Clear(); // Clear all input and output. // Build atlas, retrieve pixel data. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 97342b35b7e2..eb5cfd51b539 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2520,6 +2520,7 @@ void ImFontAtlas::ClearTexData() void ImFontAtlas::ClearFonts() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); + ClearInputData(); Fonts.clear_delete(); TexReady = false; } From 9bc5b0406d36508a3167b0a069f3f18987f838e6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 Jan 2025 14:39:07 +0100 Subject: [PATCH 404/548] Windows, Style: Fixed small rendering issues with menu bar, resize grip and scrollbar when using thick border sizes. (#8267, #7887) Amend e.g. 742b5f4c. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 14 ++++++++------ imgui_widgets.cpp | 10 ++++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f0021b2ab49c..c6e9d26f3577 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -67,6 +67,8 @@ Other changes: - Windows: legacy SetWindowFontScale() is properly inherited by nested child windows. Note that an upcoming major release should make this obsolete, but in the meanwhile it works better now. (#2701, #8138, #1018) +- Windows, Style: Fixed small rendering issues with menu bar, resize grip and + scrollbar when using thick border sizes. (#8267, #7887) - ColorEdit, ColorPicker: Fixed alpha preview broken in 1.91.7. (#8336, #8241). [@PathogenDavid] - Tabs, Style: reworked selected overline rendering to better accommodate for rounded tabs. Reduced default thickness (style.TabBarOverlineSize), diff --git a/imgui.cpp b/imgui.cpp index 0fe7c820935c..ac91f490baef 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6712,7 +6712,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window) if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) { float y = window->Pos.y + window->TitleBarHeight - 1; - window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), border_col, g.Style.FrameBorderSize); + window->DrawList->AddLine(ImVec2(window->Pos.x + border_size * 0.5f, y), ImVec2(window->Pos.x + window->Size.x - border_size * 0.5f, y), border_col, g.Style.FrameBorderSize); } } @@ -6772,9 +6772,10 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar { ImRect menu_bar_rect = window->MenuBarRect(); menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them. - window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop); + window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop); + float window_border_size = window->WindowBorderSize; if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y) - window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); + window->DrawList->AddLine(menu_bar_rect.GetBL() + ImVec2(window_border_size * 0.5f, 0.0f), menu_bar_rect.GetBR() - ImVec2(window_border_size * 0.5f, 0.0f), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); } // Scrollbars @@ -6793,9 +6794,10 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar continue; const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN); - window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size))); - window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size))); - window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12); + const float border_inner = IM_ROUND(window_border_size * 0.5f); + window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(border_inner, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, border_inner))); + window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, border_inner) : ImVec2(border_inner, resize_grip_draw_size))); + window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + border_inner), corner.y + grip.InnerDir.y * (window_rounding + border_inner)), window_rounding, grip.AngleMin12, grip.AngleMax12); window->DrawList->PathFillConvex(col); } } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e0fec9122b4d..9ce939fd39e3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -911,13 +911,14 @@ ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis) { const ImRect outer_rect = window->Rect(); const ImRect inner_rect = window->InnerRect; - const float border_size = window->WindowBorderSize; const float scrollbar_size = window->ScrollbarSizes[axis ^ 1]; // (ScrollbarSizes.x = width of Y scrollbar; ScrollbarSizes.y = height of X scrollbar) IM_ASSERT(scrollbar_size > 0.0f); + const float border_size = IM_ROUND(window->WindowBorderSize * 0.5f); + const float border_top = (window->Flags & ImGuiWindowFlags_MenuBar) ? IM_ROUND(GImGui->Style.FrameBorderSize * 0.5f) : 0.0f; if (axis == ImGuiAxis_X) - return ImRect(inner_rect.Min.x, ImMax(outer_rect.Min.y, outer_rect.Max.y - border_size - scrollbar_size), inner_rect.Max.x - border_size, outer_rect.Max.y - border_size); + return ImRect(inner_rect.Min.x + border_size, ImMax(outer_rect.Min.y + border_size, outer_rect.Max.y - border_size - scrollbar_size), inner_rect.Max.x - border_size, outer_rect.Max.y - border_size); else - return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y, outer_rect.Max.x - border_size, inner_rect.Max.y - border_size); + return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y + border_top, outer_rect.Max.x - border_size, inner_rect.Max.y - border_size); } void ImGui::Scrollbar(ImGuiAxis axis) @@ -8630,8 +8631,9 @@ bool ImGui::BeginMenuBar() // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect. // We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy. + const float border_top = ImMax(window->WindowBorderSize * 0.5f - window->TitleBarHeight, 0.0f); ImRect bar_rect = window->MenuBarRect(); - ImRect clip_rect(IM_ROUND(bar_rect.Min.x + window->WindowBorderSize), IM_ROUND(bar_rect.Min.y + window->WindowBorderSize), IM_ROUND(ImMax(bar_rect.Min.x, bar_rect.Max.x - ImMax(window->WindowRounding, window->WindowBorderSize))), IM_ROUND(bar_rect.Max.y)); + ImRect clip_rect(IM_ROUND(bar_rect.Min.x + window->WindowBorderSize * 0.5f), IM_ROUND(bar_rect.Min.y + border_top), IM_ROUND(ImMax(bar_rect.Min.x, bar_rect.Max.x - ImMax(window->WindowRounding, window->WindowBorderSize * 0.5f))), IM_ROUND(bar_rect.Max.y)); clip_rect.ClipWith(window->OuterRectClipped); PushClipRect(clip_rect.Min, clip_rect.Max, false); From bbf957875bbca8fb8b459997fba571eba964f4d2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 Jan 2025 14:43:16 +0100 Subject: [PATCH 405/548] Amend 9bc5b04 to avoid using GImGui mid-function. --- imgui_widgets.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 9ce939fd39e3..1bd19fe7cff2 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -909,12 +909,13 @@ ImGuiID ImGui::GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis) // Return scrollbar rectangle, must only be called for corresponding axis if window->ScrollbarX/Y is set. ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis) { + ImGuiContext& g = *GImGui; const ImRect outer_rect = window->Rect(); const ImRect inner_rect = window->InnerRect; const float scrollbar_size = window->ScrollbarSizes[axis ^ 1]; // (ScrollbarSizes.x = width of Y scrollbar; ScrollbarSizes.y = height of X scrollbar) IM_ASSERT(scrollbar_size > 0.0f); const float border_size = IM_ROUND(window->WindowBorderSize * 0.5f); - const float border_top = (window->Flags & ImGuiWindowFlags_MenuBar) ? IM_ROUND(GImGui->Style.FrameBorderSize * 0.5f) : 0.0f; + const float border_top = (window->Flags & ImGuiWindowFlags_MenuBar) ? IM_ROUND(g.Style.FrameBorderSize * 0.5f) : 0.0f; if (axis == ImGuiAxis_X) return ImRect(inner_rect.Min.x + border_size, ImMax(outer_rect.Min.y + border_size, outer_rect.Max.y - border_size - scrollbar_size), inner_rect.Max.x - border_size, outer_rect.Max.y - border_size); else From ed7551c1d4443b92513337fd6653f0fac8268da9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 Jan 2025 14:59:37 +0100 Subject: [PATCH 406/548] Selectable: Fixed horizontal label alignment when combined with using ImGuiSelectableFlags_SpanAllColumns. (#8338) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 9 +++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c6e9d26f3577..eac83b090236 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -139,6 +139,8 @@ Other changes: the label (not only the highlight/frame) also spans all columns. This is useful for table rows where you know nothing else is submitted. (#8318, #3565) Obviously best used with ImGuiTableFlags_NoBordersInBodyUntilResize. +- Selectable: Fixed horizontal label alignment when combined with using + ImGuiSelectableFlags_SpanAllColumns. (#8338) - Drags: Added ImGuiSliderFlags_NoSpeedTweaks flag to disable keyboard modifiers altering the tweak speed. Useful if you want to alter tweak speed yourself based on your own logic. (#8223) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1bd19fe7cff2..ad4820827630 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6943,13 +6943,9 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth)) size.x = ImMax(label_size.x, max_x - min_x); - // Text stays at the submission position, but bounding box may be extended on both sides - const ImVec2 text_min = pos; - const ImVec2 text_max(min_x + size.x, pos.y + size.y); - // Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable. // FIXME: Not part of layout so not included in clipper calculation, but ItemSize currently doesn't allow offsetting CursorPos. - ImRect bb(min_x, pos.y, text_max.x, text_max.y); + ImRect bb(min_x, pos.y, min_x + size.x, pos.y + size.y); if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0) { const float spacing_x = span_all_columns ? 0.0f : style.ItemSpacing.x; @@ -7085,8 +7081,9 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl PopColumnsBackground(); } + // Text stays at the submission position. Alignment/clipping extents ignore SpanAllColumns. if (is_visible) - RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb); + RenderTextClipped(pos, ImVec2(window->WorkRect.Max.x, pos.y + size.y), label, NULL, &label_size, style.SelectableTextAlign, &bb); // Automatically close popups if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.ItemFlags & ImGuiItemFlags_AutoClosePopups)) From 53244aaac72f3986dd29d79c2aecb2cc2cdf58f5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 Jan 2025 15:00:21 +0100 Subject: [PATCH 407/548] Amend 9bc5b04 with a shadowed variable warning fix. --- imgui.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index ac91f490baef..5468951d7549 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6773,7 +6773,6 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar ImRect menu_bar_rect = window->MenuBarRect(); menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them. window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop); - float window_border_size = window->WindowBorderSize; if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y) window->DrawList->AddLine(menu_bar_rect.GetBL() + ImVec2(window_border_size * 0.5f, 0.0f), menu_bar_rect.GetBR() - ImVec2(window_border_size * 0.5f, 0.0f), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); } From 9eafb7bbfb7b281029056f042514a76a9b17bc5a Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 Jan 2025 16:54:59 +0100 Subject: [PATCH 408/548] ImFont: IndexLookup[] table hold 16-bit values even in ImWchar32 mode. --- docs/CHANGELOG.txt | 3 +++ imgui.h | 2 +- imgui_draw.cpp | 19 ++++++++++--------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index eac83b090236..d9a95e3c103a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -78,6 +78,9 @@ Other changes: - ImDrawList: texture baked storage for thick line reduced from ~64x64 to ~32x32. (#3245) - ImFontAtlas: made calling ClearFonts() call ClearInputData(), as calling one without the other is never correct. (#8174, #6556, #6336, #4723) +- ImFont: IndexLookup[] table hold 16-bit values even in ImWchar32 mode, + as it accounts for number of glyphs in same font. This is favorable to + CalcTextSize() calls touching less memory. - Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in provided example, to reduce latency. - Examples: Vulkan: better handle VK_SUBOPTIMAL_KHR being returned by diff --git a/imgui.h b/imgui.h index 48910ea753e0..8c6082d9ea06 100644 --- a/imgui.h +++ b/imgui.h @@ -3456,7 +3456,7 @@ struct ImFont float FontSize; // 4 // in // // Height of characters/line, set during loading (don't change after loading) // [Internal] Members: Hot ~28/40 bytes (for RenderText loop) - ImVector IndexLookup; // 12-16 // out // // Sparse. Index glyphs by Unicode code-point. + ImVector IndexLookup; // 12-16 // out // // Sparse. Index glyphs by Unicode code-point. ImVector Glyphs; // 12-16 // out // // All glyphs. const ImFontGlyph* FallbackGlyph; // 4-8 // out // = FindGlyph(FontFallbackChar) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index eb5cfd51b539..1a30b9a9b256 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3738,7 +3738,7 @@ void ImFont::BuildLookupTable() { int codepoint = (int)Glyphs[i].Codepoint; IndexAdvanceX[codepoint] = Glyphs[i].AdvanceX; - IndexLookup[codepoint] = (ImWchar)i; + IndexLookup[codepoint] = (ImU16)i; // Mark 4K page as used const int page_n = codepoint / 8192; @@ -3756,7 +3756,7 @@ void ImFont::BuildLookupTable() tab_glyph.Codepoint = '\t'; tab_glyph.AdvanceX *= IM_TABSIZE; IndexAdvanceX[(int)tab_glyph.Codepoint] = (float)tab_glyph.AdvanceX; - IndexLookup[(int)tab_glyph.Codepoint] = (ImWchar)(Glyphs.Size - 1); + IndexLookup[(int)tab_glyph.Codepoint] = (ImU16)(Glyphs.Size - 1); } // Mark special glyphs as not visible (note that AddGlyph already mark as non-visible glyphs with zero-size polygons) @@ -3829,7 +3829,7 @@ void ImFont::GrowIndex(int new_size) if (new_size <= IndexLookup.Size) return; IndexAdvanceX.resize(new_size, -1.0f); - IndexLookup.resize(new_size, (ImWchar)-1); + IndexLookup.resize(new_size, (ImU16)-1); } // x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero. @@ -3872,6 +3872,7 @@ void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, floa glyph.U1 = u1; glyph.V1 = v1; glyph.AdvanceX = advance_x; + IM_ASSERT(Glyphs.Size < 0xFFFF); // IndexLookup[] hold 16-bit values and -1 is reserved. // Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round) // We use (U1-U0)*TexWidth instead of X1-X0 to account for oversampling. @@ -3885,13 +3886,13 @@ void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst) IM_ASSERT(IndexLookup.Size > 0); // Currently this can only be called AFTER the font has been built, aka after calling ImFontAtlas::GetTexDataAs*() function. unsigned int index_size = (unsigned int)IndexLookup.Size; - if (dst < index_size && IndexLookup.Data[dst] == (ImWchar)-1 && !overwrite_dst) // 'dst' already exists + if (dst < index_size && IndexLookup.Data[dst] == (ImU16)-1 && !overwrite_dst) // 'dst' already exists return; if (src >= index_size && dst >= index_size) // both 'dst' and 'src' don't exist -> no-op return; GrowIndex(dst + 1); - IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (ImWchar)-1; + IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (ImU16)-1; IndexAdvanceX[dst] = (src < index_size) ? IndexAdvanceX.Data[src] : 1.0f; } @@ -3900,8 +3901,8 @@ const ImFontGlyph* ImFont::FindGlyph(ImWchar c) { if (c >= (size_t)IndexLookup.Size) return FallbackGlyph; - const ImWchar i = IndexLookup.Data[c]; - if (i == (ImWchar)-1) + const ImU16 i = IndexLookup.Data[c]; + if (i == (ImU16)-1) return FallbackGlyph; return &Glyphs.Data[i]; } @@ -3910,8 +3911,8 @@ const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) { if (c >= (size_t)IndexLookup.Size) return NULL; - const ImWchar i = IndexLookup.Data[c]; - if (i == (ImWchar)-1) + const ImU16 i = IndexLookup.Data[c]; + if (i == (ImU16)-1) return NULL; return &Glyphs.Data[i]; } From 4211fdc70bac319543d4fedac1d6d42c9f1a94a5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 22 Jan 2025 15:44:51 +0100 Subject: [PATCH 409/548] ImFont: compact comments in header section. --- imgui.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/imgui.h b/imgui.h index 8c6082d9ea06..ba763da86cd7 100644 --- a/imgui.h +++ b/imgui.h @@ -3451,28 +3451,28 @@ struct ImFontAtlas struct ImFont { // [Internal] Members: Hot ~20/24 bytes (for CalcTextSize) - ImVector IndexAdvanceX; // 12-16 // out // // Sparse. Glyphs->AdvanceX in a directly indexable way (cache-friendly for CalcTextSize functions which only this info, and are often bottleneck in large UI). + ImVector IndexAdvanceX; // 12-16 // out // Sparse. Glyphs->AdvanceX in a directly indexable way (cache-friendly for CalcTextSize functions which only this info, and are often bottleneck in large UI). float FallbackAdvanceX; // 4 // out // = FallbackGlyph->AdvanceX - float FontSize; // 4 // in // // Height of characters/line, set during loading (don't change after loading) + float FontSize; // 4 // in // Height of characters/line, set during loading (don't change after loading) // [Internal] Members: Hot ~28/40 bytes (for RenderText loop) - ImVector IndexLookup; // 12-16 // out // // Sparse. Index glyphs by Unicode code-point. - ImVector Glyphs; // 12-16 // out // // All glyphs. + ImVector IndexLookup; // 12-16 // out // Sparse. Index glyphs by Unicode code-point. + ImVector Glyphs; // 12-16 // out // All glyphs. const ImFontGlyph* FallbackGlyph; // 4-8 // out // = FindGlyph(FontFallbackChar) // [Internal] Members: Cold ~32/40 bytes // Conceptually ConfigData[] is the list of font sources merged to create this font. - ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into - const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData to ConfigDataCount instances - short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. + ImFontAtlas* ContainerAtlas; // 4-8 // out // What we has been loaded into + const ImFontConfig* ConfigData; // 4-8 // in // Pointer within ContainerAtlas->ConfigData to ConfigDataCount instances + short ConfigDataCount; // 2 // in // Number of ImFontConfig involved in creating this font. Usually 1, or >1 when merging multiple font sources into one ImFont. short EllipsisCharCount; // 1 // out // 1 or 3 - ImWchar EllipsisChar; // 2-4 // out // = '...'/'.'// Character used for ellipsis rendering. - ImWchar FallbackChar; // 2-4 // out // = FFFD/'?' // Character used if a glyph isn't found. - float EllipsisWidth; // 4 // out // Width - float EllipsisCharStep; // 4 // out // Step between characters when EllipsisCount > 0 - float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() - float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] (unscaled) - int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) + ImWchar EllipsisChar; // 2-4 // out // Character used for ellipsis rendering ('...'). + ImWchar FallbackChar; // 2-4 // out // Character used if a glyph isn't found (U+FFFD, '?') + float EllipsisWidth; // 4 // out // Total ellipsis Width + float EllipsisCharStep; // 4 // out // Step between characters when EllipsisCount > 0 + float Scale; // 4 // in // Base font scale (1.0f), multiplied by the per-window font scale which you can adjust with SetWindowFontScale() + float Ascent, Descent; // 4+4 // out // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] (unscaled) + int MetricsTotalSurface;// 4 // out // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) bool DirtyLookupTables; // 1 // out // ImU8 Used8kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/8192/8]; // 1 bytes if ImWchar=ImWchar16, 16 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints. @@ -3481,9 +3481,9 @@ struct ImFont IMGUI_API ~ImFont(); IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c); IMGUI_API const ImFontGlyph*FindGlyphNoFallback(ImWchar c); - float GetCharAdvance(ImWchar c) { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } - bool IsLoaded() const { return ContainerAtlas != NULL; } - const char* GetDebugName() const { return ConfigData ? ConfigData->Name : ""; } + float GetCharAdvance(ImWchar c) { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } + bool IsLoaded() const { return ContainerAtlas != NULL; } + const char* GetDebugName() const { return ConfigData ? ConfigData->Name : ""; } // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. From 8a1613a382f81d321355efe47698a34520fe2c8a Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 Jan 2025 19:27:50 +0100 Subject: [PATCH 410/548] Fonts: OversampleH/OversampleV value defaults to 0 for automatic selection. --- docs/CHANGELOG.txt | 10 +++++++--- docs/FONTS.md | 2 -- imgui.cpp | 10 +++++++--- imgui.h | 4 ++-- imgui_draw.cpp | 30 ++++++++++++++++++++---------- imgui_internal.h | 1 + misc/freetype/imgui_freetype.cpp | 2 +- 7 files changed, 38 insertions(+), 21 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d9a95e3c103a..3e0080ac3d47 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -76,11 +76,15 @@ Other changes: styles as the current look is not right (but ImGuiCol_TabSelectedOverline stays the same). - Debug Tools: Tweaked font preview. - ImDrawList: texture baked storage for thick line reduced from ~64x64 to ~32x32. (#3245) -- ImFontAtlas: made calling ClearFonts() call ClearInputData(), as calling - one without the other is never correct. (#8174, #6556, #6336, #4723) -- ImFont: IndexLookup[] table hold 16-bit values even in ImWchar32 mode, +- Fonts: IndexLookup[] table hold 16-bit values even in ImWchar32 mode, as it accounts for number of glyphs in same font. This is favorable to CalcTextSize() calls touching less memory. +- Fonts: OversampleH/OversampleV defaults to 0 for automatic selection. + - OversampleH == 0 --> use 1 or 2 depending on font size and use of PixelSnapH. + - OversampleV == 0 --> always use 1. + This also +- ImFontAtlas: made calling ClearFonts() call ClearInputData(), as calling + one without the other is never correct. (#8174, #6556, #6336, #4723) - Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in provided example, to reduce latency. - Examples: Vulkan: better handle VK_SUBOPTIMAL_KHR being returned by diff --git a/docs/FONTS.md b/docs/FONTS.md index c451af61c0ba..e36afdf817d0 100644 --- a/docs/FONTS.md +++ b/docs/FONTS.md @@ -110,8 +110,6 @@ ImGui::PopFont(); **For advanced options create a ImFontConfig structure and pass it to the AddFont() function (it will be copied internally):** ```cpp ImFontConfig config; -config.OversampleH = 2; -config.OversampleV = 1; config.GlyphExtraSpacing.x = 1.0f; ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config); ``` diff --git a/imgui.cpp b/imgui.cpp index 5468951d7549..3764b5663c03 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16184,9 +16184,13 @@ void ImGui::DebugNodeFont(ImFont* font) Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) if (font->ConfigData) - if (const ImFontConfig* cfg = &font->ConfigData[config_i]) - BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)", - config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y); + { + const ImFontConfig* cfg = &font->ConfigData[config_i]; + int oversample_h, oversample_v; + ImFontAtlasBuildGetOversampleFactors(cfg, &oversample_h, &oversample_v); + BulletText("Input %d: \'%s\', Oversample: (%d=>%d,%d=>%d), PixelSnapH: %d, Offset: (%.1f,%.1f)", + config_i, cfg->Name, cfg->OversampleH, oversample_h, cfg->OversampleV, oversample_v, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y); + } // Display all glyphs of the fonts in separate pages of 256 characters { diff --git a/imgui.h b/imgui.h index ba763da86cd7..8e240b390ead 100644 --- a/imgui.h +++ b/imgui.h @@ -3254,8 +3254,8 @@ struct ImFontConfig bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. bool PixelSnapH; // false // Align every glyph AdvanceX to pixel boundaries. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. int FontNo; // 0 // Index of font within TTF/OTF file - int OversampleH; // 2 // Rasterize at higher quality for sub-pixel positioning. Note the difference between 2 and 3 is minimal. You can reduce this to 1 for large glyphs save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details. - int OversampleV; // 1 // Rasterize at higher quality for sub-pixel positioning. This is not really useful as we don't use sub-pixel positions on the Y axis. + int OversampleH; // 0 (2) // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1 or 2 depending on size. Note the difference between 2 and 3 is minimal. You can reduce this to 1 for large glyphs save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details. + int OversampleV; // 0 (1) // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1. This is not really useful as we don't use sub-pixel positions on the Y axis. float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height). ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs when rendered: essentially add to glyph->AdvanceX. Only X axis is supported for now. ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 1a30b9a9b256..c7f8044c64f9 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2374,8 +2374,8 @@ ImFontConfig::ImFontConfig() { memset(this, 0, sizeof(*this)); FontDataOwnedByAtlas = true; - OversampleH = 2; - OversampleV = 1; + OversampleH = 0; // Auto == 1 or 2 depending on size + OversampleV = 0; // Auto == 1 GlyphMaxAdvanceX = FLT_MAX; RasterizerMultiply = 1.0f; RasterizerDensity = 1.0f; @@ -2573,8 +2573,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0); IM_ASSERT(font_cfg->SizePixels > 0.0f && "Is ImFontConfig struct correctly initialized?"); - IM_ASSERT(font_cfg->OversampleH > 0 && font_cfg->OversampleV > 0 && "Is ImFontConfig struct correctly initialized?"); - IM_ASSERT(font_cfg->RasterizerDensity > 0.0f); + IM_ASSERT(font_cfg->RasterizerDensity > 0.0f && "Is ImFontConfig struct correctly initialized?"); // Create new font if (!font_cfg->MergeMode) @@ -2858,6 +2857,13 @@ static void UnpackBitVectorToFlatIndexList(const ImBitVector* in, ImVector* out->push_back((int)(((it - it_begin) << 5) + bit_n)); } +void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* cfg, int* out_oversample_h, int* out_oversample_v) +{ + // Automatically disable horizontal oversampling over size 32 + *out_oversample_h = (cfg->OversampleH != 0) ? cfg->OversampleH : (cfg->SizePixels * cfg->RasterizerDensity > 32.0f || cfg->PixelSnapH) ? 1 : 2; + *out_oversample_v = (cfg->OversampleV != 0) ? cfg->OversampleV : 1; +} + static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { IM_ASSERT(atlas->ConfigData.Size > 0); @@ -2985,15 +2991,19 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) buf_rects_out_n += src_tmp.GlyphsCount; buf_packedchars_out_n += src_tmp.GlyphsCount; - // Convert our ranges in the format stb_truetype wants + // Automatic selection of oversampling parameters ImFontConfig& cfg = atlas->ConfigData[src_i]; + int oversample_h, oversample_v; + ImFontAtlasBuildGetOversampleFactors(&cfg, &oversample_h, &oversample_v); + + // Convert our ranges in the format stb_truetype wants src_tmp.PackRange.font_size = cfg.SizePixels * cfg.RasterizerDensity; src_tmp.PackRange.first_unicode_codepoint_in_range = 0; src_tmp.PackRange.array_of_unicode_codepoints = src_tmp.GlyphsList.Data; src_tmp.PackRange.num_chars = src_tmp.GlyphsList.Size; src_tmp.PackRange.chardata_for_range = src_tmp.PackedChars; - src_tmp.PackRange.h_oversample = (unsigned char)cfg.OversampleH; - src_tmp.PackRange.v_oversample = (unsigned char)cfg.OversampleV; + src_tmp.PackRange.h_oversample = (unsigned char)oversample_h; + src_tmp.PackRange.v_oversample = (unsigned char)oversample_v; // Gather the sizes of all rectangles we will need to pack (this loop is based on stbtt_PackFontRangesGatherRects) const float scale = (cfg.SizePixels > 0.0f) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels * cfg.RasterizerDensity) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -cfg.SizePixels * cfg.RasterizerDensity); @@ -3002,9 +3012,9 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) int x0, y0, x1, y1; const int glyph_index_in_font = stbtt_FindGlyphIndex(&src_tmp.FontInfo, src_tmp.GlyphsList[glyph_i]); IM_ASSERT(glyph_index_in_font != 0); - stbtt_GetGlyphBitmapBoxSubpixel(&src_tmp.FontInfo, glyph_index_in_font, scale * cfg.OversampleH, scale * cfg.OversampleV, 0, 0, &x0, &y0, &x1, &y1); - src_tmp.Rects[glyph_i].w = (stbrp_coord)(x1 - x0 + pack_padding + cfg.OversampleH - 1); - src_tmp.Rects[glyph_i].h = (stbrp_coord)(y1 - y0 + pack_padding + cfg.OversampleV - 1); + stbtt_GetGlyphBitmapBoxSubpixel(&src_tmp.FontInfo, glyph_index_in_font, scale * oversample_h, scale * oversample_v, 0, 0, &x0, &y0, &x1, &y1); + src_tmp.Rects[glyph_i].w = (stbrp_coord)(x1 - x0 + pack_padding + oversample_h - 1); + src_tmp.Rects[glyph_i].h = (stbrp_coord)(y1 - y0 + pack_padding + oversample_v - 1); total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h; } } diff --git a/imgui_internal.h b/imgui_internal.h index 33a6ec8b0bc5..e78659adc369 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3571,6 +3571,7 @@ IMGUI_API void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, IMGUI_API void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value); IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor); IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride); +IMGUI_API void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* cfg, int* out_oversample_h, int* out_oversample_v); //----------------------------------------------------------------------------- // [SECTION] Test Engine specific hooks (imgui_test_engine) diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 421fdba63436..029991bbdec3 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -33,7 +33,7 @@ // - For correct results you need to be using sRGB and convert to linear space in the pixel shader output. // - The default dear imgui styles will be impacted by this change (alpha values will need tweaking). -// FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer). +// FIXME: cfg.OversampleH, OversampleV are not supported, but generally not necessary with this rasterizer because Hinting makes everything look better. #include "imgui.h" #ifndef IMGUI_DISABLE From afb6e9a879cbac8346601a5b4984e3991c30cc8f Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 Jan 2025 20:03:04 +0100 Subject: [PATCH 411/548] Fonts: OversampleH auto-selection uses 36 as heuristic for now. --- imgui_draw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index c7f8044c64f9..f00a68361935 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2859,8 +2859,8 @@ static void UnpackBitVectorToFlatIndexList(const ImBitVector* in, ImVector* void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* cfg, int* out_oversample_h, int* out_oversample_v) { - // Automatically disable horizontal oversampling over size 32 - *out_oversample_h = (cfg->OversampleH != 0) ? cfg->OversampleH : (cfg->SizePixels * cfg->RasterizerDensity > 32.0f || cfg->PixelSnapH) ? 1 : 2; + // Automatically disable horizontal oversampling over size 36 + *out_oversample_h = (cfg->OversampleH != 0) ? cfg->OversampleH : (cfg->SizePixels * cfg->RasterizerDensity > 36.0f || cfg->PixelSnapH) ? 1 : 2; *out_oversample_v = (cfg->OversampleV != 0) ? cfg->OversampleV : 1; } From 96e3b147f0ad8a0b70e818d6d845aa7956e8e7b2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 25 Jan 2025 01:14:46 +0100 Subject: [PATCH 412/548] Fixed build with IMGUI_ENABLE_FREETYPE (#8346) --- imgui_draw.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index f00a68361935..4b59d6775867 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2819,6 +2819,13 @@ void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsig *data = table[*data]; } +void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* cfg, int* out_oversample_h, int* out_oversample_v) +{ + // Automatically disable horizontal oversampling over size 36 + *out_oversample_h = (cfg->OversampleH != 0) ? cfg->OversampleH : (cfg->SizePixels * cfg->RasterizerDensity > 36.0f || cfg->PixelSnapH) ? 1 : 2; + *out_oversample_v = (cfg->OversampleV != 0) ? cfg->OversampleV : 1; +} + #ifdef IMGUI_ENABLE_STB_TRUETYPE // Temporary data for one source font (multiple source fonts can be merged into one destination ImFont) // (C++03 doesn't allow instancing ImVector<> with function-local types so we declare the type here.) @@ -2857,13 +2864,6 @@ static void UnpackBitVectorToFlatIndexList(const ImBitVector* in, ImVector* out->push_back((int)(((it - it_begin) << 5) + bit_n)); } -void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* cfg, int* out_oversample_h, int* out_oversample_v) -{ - // Automatically disable horizontal oversampling over size 36 - *out_oversample_h = (cfg->OversampleH != 0) ? cfg->OversampleH : (cfg->SizePixels * cfg->RasterizerDensity > 36.0f || cfg->PixelSnapH) ? 1 : 2; - *out_oversample_v = (cfg->OversampleV != 0) ? cfg->OversampleV : 1; -} - static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { IM_ASSERT(atlas->ConfigData.Size > 0); From 5a28f188ff0f502e63336f2993235308ea775267 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 27 Jan 2025 12:27:10 +0100 Subject: [PATCH 413/548] Fixed parameter names to SetLastItemData() to align with current names. --- imgui.cpp | 6 +++--- imgui_internal.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3764b5663c03..9416757c8b2f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4695,12 +4695,12 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id) // This is also inlined in ItemAdd() // Note: if ImGuiItemStatusFlags_HasDisplayRect is set, user needs to set g.LastItemData.DisplayRect. -void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags item_flags, const ImRect& item_rect) +void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags item_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect) { ImGuiContext& g = *GImGui; g.LastItemData.ID = item_id; - g.LastItemData.ItemFlags = in_flags; - g.LastItemData.StatusFlags = item_flags; + g.LastItemData.ItemFlags = item_flags; + g.LastItemData.StatusFlags = status_flags; g.LastItemData.Rect = g.LastItemData.NavRect = item_rect; } diff --git a/imgui_internal.h b/imgui_internal.h index e78659adc369..a8cd3719e31b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3095,7 +3095,7 @@ namespace ImGui IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flags); IMGUI_API bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags = 0); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id); - IMGUI_API void SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect); + IMGUI_API void SetLastItemData(ImGuiID item_id, ImGuiItemFlags item_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API void PushMultiItemsWidths(int components, float width_full); From 134fbe12451c4538c17a7730c1fa30663372e06e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 27 Jan 2025 12:39:44 +0100 Subject: [PATCH 414/548] Windows: Fixed IsItemXXXX() functions not working on append-version of EndChild(). (#8350) Also made some of the fields accessible after BeginChild() to match Begin() logic. --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 28 ++++++++++++++++++++++------ imgui_internal.h | 1 + 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3e0080ac3d47..e9952a080948 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -69,6 +69,8 @@ Other changes: but in the meanwhile it works better now. (#2701, #8138, #1018) - Windows, Style: Fixed small rendering issues with menu bar, resize grip and scrollbar when using thick border sizes. (#8267, #7887) +- Windows: Fixed IsItemXXXX() functions not working on append-version of EndChild(). (#8350) + Also made some of the fields accessible after BeginChild() to match Begin() logic. - ColorEdit, ColorPicker: Fixed alpha preview broken in 1.91.7. (#8336, #8241). [@PathogenDavid] - Tabs, Style: reworked selected overline rendering to better accommodate for rounded tabs. Reduced default thickness (style.TabBarOverlineSize), diff --git a/imgui.cpp b/imgui.cpp index 9416757c8b2f..7afea92bcb2a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1256,6 +1256,7 @@ static void RenderWindowTitleBarContents(ImGuiWindow* window, const static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col); static void RenderDimmedBackgrounds(); static void SetLastItemDataForWindow(ImGuiWindow* window, const ImRect& rect); +static void SetLastItemDataForChildWindowItem(ImGuiWindow* window, const ImRect& rect); // Viewports const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHashStr("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. @@ -4704,6 +4705,18 @@ void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags item_flags, ImGuiIte g.LastItemData.Rect = g.LastItemData.NavRect = item_rect; } +static void ImGui::SetLastItemDataForWindow(ImGuiWindow* window, const ImRect& rect) +{ + ImGuiContext& g = *GImGui; + SetLastItemData(window->MoveId, g.CurrentItemFlags, window->DC.WindowItemStatusFlags, rect); +} + +static void ImGui::SetLastItemDataForChildWindowItem(ImGuiWindow* window, const ImRect& rect) +{ + ImGuiContext& g = *GImGui; + SetLastItemData(window->ChildId, g.CurrentItemFlags, window->DC.WindowItemStatusFlags, rect); +} + float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) { if (wrap_pos_x < 0.0f) @@ -6157,7 +6170,14 @@ void ImGui::EndChild() } if (g.HoveredWindow == child_window) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; + child_window->DC.WindowItemStatusFlags = g.LastItemData.StatusFlags; + //SetLastItemDataForChildWindowItem(child_window, child_window->Rect()); // Not needed, effectively done by ItemAdd() } + else + { + SetLastItemDataForChildWindowItem(child_window, child_window->Rect()); + } + g.WithinEndChildID = backup_within_end_child_id; g.LogLinePosY = -FLT_MAX; // To enforce a carriage return } @@ -7612,6 +7632,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin(). // This is useful to allow creating context menus on title bar only, etc. + window->DC.WindowItemStatusFlags = ImGuiItemStatusFlags_None; + window->DC.WindowItemStatusFlags |= IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0; SetLastItemDataForWindow(window, title_bar_rect); // [DEBUG] @@ -7717,12 +7739,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) return !window->SkipItems; } -static void ImGui::SetLastItemDataForWindow(ImGuiWindow* window, const ImRect& rect) -{ - ImGuiContext& g = *GImGui; - SetLastItemData(window->MoveId, g.CurrentItemFlags, IsMouseHoveringRect(rect.Min, rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0, rect); -} - void ImGui::End() { ImGuiContext& g = *GImGui; diff --git a/imgui_internal.h b/imgui_internal.h index a8cd3719e31b..b7b81c2e2676 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2456,6 +2456,7 @@ struct IMGUI_API ImGuiWindowTempData ImGuiLayoutType LayoutType; ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() ImU32 ModalDimBgColor; + ImGuiItemStatusFlags WindowItemStatusFlags; // Local parameters stacks // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. From a05d547ae88c228a392153bbee6a1fa88abc926e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 27 Jan 2025 14:39:26 +0100 Subject: [PATCH 415/548] Windows: separating WindowItemStatusFlags from ChildItemStatusFlag, because IsItemXXX _after_ BeginChild()>Begin() shouldn't return last status emitted by e.g. EndChild() As IsItemXXX() after is specced as returning title bar data we don't want to lock ourselves up from adding them to child window (e.g. MDI idea using windows to host child windows). --- imgui.cpp | 4 ++-- imgui_internal.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7afea92bcb2a..e4c2f2a2edc2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4714,7 +4714,7 @@ static void ImGui::SetLastItemDataForWindow(ImGuiWindow* window, const ImRect& r static void ImGui::SetLastItemDataForChildWindowItem(ImGuiWindow* window, const ImRect& rect) { ImGuiContext& g = *GImGui; - SetLastItemData(window->ChildId, g.CurrentItemFlags, window->DC.WindowItemStatusFlags, rect); + SetLastItemData(window->ChildId, g.CurrentItemFlags, window->DC.ChildItemStatusFlags, rect); } float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) @@ -6170,7 +6170,7 @@ void ImGui::EndChild() } if (g.HoveredWindow == child_window) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; - child_window->DC.WindowItemStatusFlags = g.LastItemData.StatusFlags; + child_window->DC.ChildItemStatusFlags = g.LastItemData.StatusFlags; //SetLastItemDataForChildWindowItem(child_window, child_window->Rect()); // Not needed, effectively done by ItemAdd() } else diff --git a/imgui_internal.h b/imgui_internal.h index b7b81c2e2676..2922993b3784 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2457,6 +2457,7 @@ struct IMGUI_API ImGuiWindowTempData ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() ImU32 ModalDimBgColor; ImGuiItemStatusFlags WindowItemStatusFlags; + ImGuiItemStatusFlags ChildItemStatusFlags; // Local parameters stacks // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. From 9c4948a4d1a24237a63546de2e79e331bb5722b4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 27 Jan 2025 15:41:24 +0100 Subject: [PATCH 416/548] TabBar: Internals: added TabItemSpacing(). (#8349, #3291) --- imgui_internal.h | 3 ++ imgui_widgets.cpp | 118 ++++++++++++++++++++++++++++------------------ 2 files changed, 74 insertions(+), 47 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 2922993b3784..0b19c63e3085 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2612,6 +2612,8 @@ enum ImGuiTabItemFlagsPrivate_ ImGuiTabItemFlags_SectionMask_ = ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing, ImGuiTabItemFlags_NoCloseButton = 1 << 20, // Track whether p_open was set or not (we'll need this info on the next frame to recompute ContentWidth during layout) ImGuiTabItemFlags_Button = 1 << 21, // Used by TabItemButton, change the tab item behavior to mimic a button + ImGuiTabItemFlags_Invisible = 1 << 22, // To reserve space e.g. with ImGuiTabItemFlags_Leading + //ImGuiTabItemFlags_Unsorted = 1 << 23, // [Docking] Trailing tabs with the _Unsorted flag will be sorted based on the DockOrder of their Window. }; // Storage for one active tab item (sizeof() 40 bytes) @@ -3378,6 +3380,7 @@ namespace ImGui IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, ImVec2 mouse_pos); IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar); IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window); + IMGUI_API void TabItemSpacing(const char* str_id, ImGuiTabItemFlags flags, float width); IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button_or_unsaved_marker); IMGUI_API ImVec2 TabItemCalcSize(ImGuiWindow* window); IMGUI_API void TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ad4820827630..22f73866063c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -9925,7 +9925,7 @@ bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags f IM_ASSERT_USER_ERROR(tab_bar, "Needs to be called between BeginTabBar() and EndTabBar()!"); return false; } - IM_ASSERT(!(flags & ImGuiTabItemFlags_Button)); // BeginTabItem() Can't be used with button flags, use TabItemButton() instead! + IM_ASSERT((flags & ImGuiTabItemFlags_Button) == 0); // BeginTabItem() Can't be used with button flags, use TabItemButton() instead! bool ret = TabItemEx(tab_bar, label, p_open, flags, NULL); if (ret && !(flags & ImGuiTabItemFlags_NoPushId)) @@ -9971,6 +9971,23 @@ bool ImGui::TabItemButton(const char* label, ImGuiTabItemFlags flags) return TabItemEx(tab_bar, label, NULL, flags | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder, NULL); } +void ImGui::TabItemSpacing(const char* str_id, ImGuiTabItemFlags flags, float width) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (window->SkipItems) + return; + + ImGuiTabBar* tab_bar = g.CurrentTabBar; + if (tab_bar == NULL) + { + IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!"); + return; + } + SetNextItemWidth(width); + TabItemEx(tab_bar, str_id, NULL, flags | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder | ImGuiTabItemFlags_Invisible, NULL); +} + bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window) { // Layout whole tab bar if not already done @@ -10116,8 +10133,11 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiButtonFlags button_flags = ((is_tab_button ? ImGuiButtonFlags_PressedOnClickRelease : ImGuiButtonFlags_PressedOnClick) | ImGuiButtonFlags_AllowOverlap); if (g.DragDropActive) button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); + bool hovered, held, pressed; + if (flags & ImGuiTabItemFlags_Invisible) + hovered = held = pressed = false; + else + pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); if (pressed && !is_tab_button) TabBarQueueFocus(tab_bar, tab); @@ -10149,46 +10169,59 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, #endif // Render tab shape - ImDrawList* display_draw_list = window->DrawList; - const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabSelected : ImGuiCol_TabDimmedSelected) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabDimmed)); - TabItemBackground(display_draw_list, bb, flags, tab_col); - if (tab_contents_visible && (tab_bar->Flags & ImGuiTabBarFlags_DrawSelectedOverline) && style.TabBarOverlineSize > 0.0f) - { - // Might be moved to TabItemBackground() ? - ImVec2 tl = bb.GetTL() + ImVec2(0, 1.0f * g.CurrentDpiScale); - ImVec2 tr = bb.GetTR() + ImVec2(0, 1.0f * g.CurrentDpiScale); - ImU32 overline_col = GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline); - if (style.TabRounding > 0.0f) - { - float rounding = style.TabRounding; - display_draw_list->PathArcToFast(tl + ImVec2(+rounding, +rounding), rounding, 7, 9); - display_draw_list->PathArcToFast(tr + ImVec2(-rounding, +rounding), rounding, 9, 11); - display_draw_list->PathStroke(overline_col, 0, style.TabBarOverlineSize); - } - else + const bool is_visible = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) && !(flags & ImGuiTabItemFlags_Invisible); + if (is_visible) + { + ImDrawList* display_draw_list = window->DrawList; + const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabSelected : ImGuiCol_TabDimmedSelected) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabDimmed)); + TabItemBackground(display_draw_list, bb, flags, tab_col); + if (tab_contents_visible && (tab_bar->Flags & ImGuiTabBarFlags_DrawSelectedOverline) && style.TabBarOverlineSize > 0.0f) { - display_draw_list->AddLine(tl - ImVec2(0.5f, 0.5f), tr - ImVec2(0.5f, 0.5f), overline_col, style.TabBarOverlineSize); + // Might be moved to TabItemBackground() ? + ImVec2 tl = bb.GetTL() + ImVec2(0, 1.0f * g.CurrentDpiScale); + ImVec2 tr = bb.GetTR() + ImVec2(0, 1.0f * g.CurrentDpiScale); + ImU32 overline_col = GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline); + if (style.TabRounding > 0.0f) + { + float rounding = style.TabRounding; + display_draw_list->PathArcToFast(tl + ImVec2(+rounding, +rounding), rounding, 7, 9); + display_draw_list->PathArcToFast(tr + ImVec2(-rounding, +rounding), rounding, 9, 11); + display_draw_list->PathStroke(overline_col, 0, style.TabBarOverlineSize); + } + else + { + display_draw_list->AddLine(tl - ImVec2(0.5f, 0.5f), tr - ImVec2(0.5f, 0.5f), overline_col, style.TabBarOverlineSize); + } } - } - RenderNavCursor(bb, id); + RenderNavCursor(bb, id); - // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget. - const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup); - if (tab_bar->SelectedTabId != tab->ID && hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button) - TabBarQueueFocus(tab_bar, tab); + // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget. + const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup); + if (tab_bar->SelectedTabId != tab->ID && hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button) + TabBarQueueFocus(tab_bar, tab); - if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton) - flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton; + if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton) + flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton; - // Render tab label, process close button - const ImGuiID close_button_id = p_open ? GetIDWithSeed("#CLOSE", NULL, id) : 0; - bool just_closed; - bool text_clipped; - TabItemLabelAndCloseButton(display_draw_list, bb, tab_just_unsaved ? (flags & ~ImGuiTabItemFlags_UnsavedDocument) : flags, tab_bar->FramePadding, label, id, close_button_id, tab_contents_visible, &just_closed, &text_clipped); - if (just_closed && p_open != NULL) - { - *p_open = false; - TabBarCloseTab(tab_bar, tab); + // Render tab label, process close button + const ImGuiID close_button_id = p_open ? GetIDWithSeed("#CLOSE", NULL, id) : 0; + bool just_closed; + bool text_clipped; + TabItemLabelAndCloseButton(display_draw_list, bb, tab_just_unsaved ? (flags & ~ImGuiTabItemFlags_UnsavedDocument) : flags, tab_bar->FramePadding, label, id, close_button_id, tab_contents_visible, &just_closed, &text_clipped); + if (just_closed && p_open != NULL) + { + *p_open = false; + TabBarCloseTab(tab_bar, tab); + } + + // Tooltip + // (Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer-> seems ok) + // (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores) + // FIXME: This is a mess. + // FIXME: We may want disabled tab to still display the tooltip? + if (text_clipped && g.HoveredId == id && !held) + if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip)) + SetItemTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label); } // Restore main window position so user can draw there @@ -10196,15 +10229,6 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, PopClipRect(); window->DC.CursorPos = backup_main_cursor_pos; - // Tooltip - // (Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer-> seems ok) - // (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores) - // FIXME: This is a mess. - // FIXME: We may want disabled tab to still display the tooltip? - if (text_clipped && g.HoveredId == id && !held) - if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip)) - SetItemTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label); - IM_ASSERT(!is_tab_button || !(tab_bar->SelectedTabId == tab->ID && is_tab_button)); // TabItemButton should not be selected if (is_tab_button) return pressed; From ea0da0bf4736692cff7dd28eeba6ae3c95daf1aa Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 27 Jan 2025 18:04:44 +0100 Subject: [PATCH 417/548] Extracted PushPasswordFont() out of InputText code. --- imgui_internal.h | 1 + imgui_widgets.cpp | 31 ++++++++++++++++++------------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 0b19c63e3085..667c4ea1fab6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3018,6 +3018,7 @@ namespace ImGui // Fonts, drawing IMGUI_API void SetCurrentFont(ImFont* font); inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } + IMGUI_API void PushPasswordFont(); inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); return GetForegroundDrawList(); } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches. IMGUI_API ImDrawList* GetBackgroundDrawList(ImGuiViewport* viewport); // get background draw list for the given viewport. this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents. IMGUI_API ImDrawList* GetForegroundDrawList(ImGuiViewport* viewport); // get foreground draw list for the given viewport. this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 22f73866063c..e37a2fb45b76 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4246,6 +4246,23 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons BufTextLen += new_text_len; } +void ImGui::PushPasswordFont() +{ + ImGuiContext& g = *GImGui; + ImFont* in_font = g.Font; + ImFont* out_font = &g.InputTextPasswordFont; + const ImFontGlyph* glyph = in_font->FindGlyph('*'); + out_font->FontSize = in_font->FontSize; + out_font->Scale = in_font->Scale; + out_font->Ascent = in_font->Ascent; + out_font->Descent = in_font->Descent; + out_font->ContainerAtlas = in_font->ContainerAtlas; + out_font->FallbackGlyph = glyph; + out_font->FallbackAdvanceX = glyph->AdvanceX; + IM_ASSERT(out_font->Glyphs.Size == 0 && out_font->IndexAdvanceX.Size == 0 && out_font->IndexLookup.Size == 0); + PushFont(out_font); +} + // Return false to discard a character. static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, bool input_source_is_clipboard) { @@ -4656,19 +4673,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Password pushes a temporary font with only a fallback glyph if (is_password && !is_displaying_hint) - { - const ImFontGlyph* glyph = g.Font->FindGlyph('*'); - ImFont* password_font = &g.InputTextPasswordFont; - password_font->FontSize = g.Font->FontSize; - password_font->Scale = g.Font->Scale; - password_font->Ascent = g.Font->Ascent; - password_font->Descent = g.Font->Descent; - password_font->ContainerAtlas = g.Font->ContainerAtlas; - password_font->FallbackGlyph = glyph; - password_font->FallbackAdvanceX = glyph->AdvanceX; - IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty()); - PushFont(password_font); - } + PushPasswordFont(); // Process mouse inputs and character inputs if (g.ActiveId == id) From 4230e98720357c5e770e3a078a9e4d09f0923279 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 28 Jan 2025 14:39:00 +0100 Subject: [PATCH 418/548] Error Handling, Debug Log: IMGUI_DEBUG_LOG_ERROR() doesn't need the extra variable. Amend 236006152 --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index 667c4ea1fab6..ea6479ec317c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -229,7 +229,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer #endif // Debug Logging for ShowDebugLogWindow(). This is designed for relatively rare events so please don't spam. -#define IMGUI_DEBUG_LOG_ERROR(...) do { ImGuiContext& g2 = *GImGui; if (g2.DebugLogFlags & ImGuiDebugLogFlags_EventError) IMGUI_DEBUG_LOG(__VA_ARGS__); else g2.DebugLogSkippedErrors++; } while (0) +#define IMGUI_DEBUG_LOG_ERROR(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventError) IMGUI_DEBUG_LOG(__VA_ARGS__); else g.DebugLogSkippedErrors++; } while (0) #define IMGUI_DEBUG_LOG_ACTIVEID(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) From dfd1bc3c5b35ed9d4203b39e1bdf43d60a061b74 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 29 Jan 2025 19:05:18 +0100 Subject: [PATCH 419/548] Tables, Menus: Fixed using BeginTable() in menu layer (any menu bar). (#8355) --- docs/CHANGELOG.txt | 3 +++ imgui_internal.h | 1 + imgui_tables.cpp | 8 +++++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e9952a080948..be448d16f355 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -71,6 +71,9 @@ Other changes: scrollbar when using thick border sizes. (#8267, #7887) - Windows: Fixed IsItemXXXX() functions not working on append-version of EndChild(). (#8350) Also made some of the fields accessible after BeginChild() to match Begin() logic. +- Tables, Menus: Fixed using BeginTable() in menu layer (any menu bar). (#8355) + It previously overrode the current layer back to main layer, which caused an issue + with MainMenuBar attempted to release focus when leaving the menu layer. - ColorEdit, ColorPicker: Fixed alpha preview broken in 1.91.7. (#8336, #8241). [@PathogenDavid] - Tabs, Style: reworked selected overline rendering to better accommodate for rounded tabs. Reduced default thickness (style.TabBarOverlineSize), diff --git a/imgui_internal.h b/imgui_internal.h index ea6479ec317c..d4154dabaae2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2877,6 +2877,7 @@ struct IMGUI_API ImGuiTable ImGuiTableDrawChannelIdx DummyDrawChannel; // Redirect non-visible columns here. ImGuiTableDrawChannelIdx Bg2DrawChannelCurrent; // For Selectable() and other widgets drawing across columns after the freezing line. Index within DrawSplitter.Channels[] ImGuiTableDrawChannelIdx Bg2DrawChannelUnfrozen; + ImS8 NavLayer; // ImGuiNavLayer at the time of BeginTable(). bool IsLayoutLocked; // Set by TableUpdateLayout() which is called when beginning the first row. bool IsInsideRow; // Set when inside TableBeginRow()/TableEndRow(). bool IsInitializing; diff --git a/imgui_tables.cpp b/imgui_tables.cpp index e0df575c440c..d5e952d8f9a1 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -374,6 +374,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG table->ColumnsCount = columns_count; table->IsLayoutLocked = false; table->InnerWidth = inner_width; + table->NavLayer = (ImS8)outer_window->DC.NavLayerCurrent; temp_data->UserOuterSize = outer_size; // Instance data (for instance 0, TableID == TableInstanceID) @@ -1050,7 +1051,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) const int column_n = table->DisplayOrderToIndex[order_n]; ImGuiTableColumn* column = &table->Columns[column_n]; - column->NavLayerCurrent = (ImS8)(table->FreezeRowsCount > 0 ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main); // Use Count NOT request so Header line changes layer when frozen + // Initial nav layer: using FreezeRowsCount, NOT FreezeRowsRequest, so Header line changes layer when frozen + column->NavLayerCurrent = (ImS8)(table->FreezeRowsCount > 0 ? ImGuiNavLayer_Menu : table->NavLayer); if (offset_x_frozen && table->FreezeColumnsCount == visible_n) { @@ -1493,7 +1495,7 @@ void ImGui::EndTable() if (inner_window != outer_window) { short backup_nav_layers_active_mask = inner_window->DC.NavLayersActiveMask; - inner_window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main; // So empty table don't appear to navigate differently. + inner_window->DC.NavLayersActiveMask |= 1 << table->NavLayer; // So empty table don't appear to navigate differently. g.CurrentTable = NULL; // To avoid error recovery recursing EndChild(); g.CurrentTable = table; @@ -2032,7 +2034,7 @@ void ImGui::TableEndRow(ImGuiTable* table) if (unfreeze_rows_request) { for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - table->Columns[column_n].NavLayerCurrent = ImGuiNavLayer_Main; + table->Columns[column_n].NavLayerCurrent = table->NavLayer; const float y0 = ImMax(table->RowPosY2 + 1, table->InnerClipRect.Min.y); table_instance->LastFrozenHeight = y0 - table->OuterRect.Min.y; From a71191515ac29725ee2aa94b6f5d59cc9ffa108c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 29 Jan 2025 19:07:28 +0100 Subject: [PATCH 420/548] EndMainMenuBar doesn't attempt to restore focus when there's an active id. (#8355) I don't have a specific issue in mind but it seems sane to add that test. --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e37a2fb45b76..f772f309c84d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8769,7 +8769,7 @@ void ImGui::EndMainMenuBar() // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window // FIXME: With this strategy we won't be able to restore a NULL focus. ImGuiContext& g = *GImGui; - if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest) + if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest && g.ActiveId == 0) FocusTopMostWindowUnderOne(g.NavWindow, NULL, NULL, ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild); End(); From dabc99018915a534d11d22abc65a6f4d6898d2d4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 29 Jan 2025 19:59:41 +0100 Subject: [PATCH 421/548] Rename internal id for standardizing naming convention. "##menubar" -> "##MenuBar", "###NavWindowingList" -> "###NavWindowingOverlay" "###NavUpdateWindowing" one should have zero side effect on anyone. --- imgui.cpp | 6 +++--- imgui.h | 2 +- imgui_widgets.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e4c2f2a2edc2..5223ed76c892 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -13649,7 +13649,7 @@ static void ImGui::NavUpdateWindowing() // Start CTRL+Tab or Square+L/R window selection // (g.ConfigNavWindowingKeyNext/g.ConfigNavWindowingKeyPrev defaults are ImGuiMod_Ctrl|ImGuiKey_Tab and ImGuiMod_Ctrl|ImGuiMod_Shift|ImGuiKey_Tab) - const ImGuiID owner_id = ImHashStr("###NavUpdateWindowing"); + const ImGuiID owner_id = ImHashStr("##NavUpdateWindowing"); const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; const bool keyboard_next_window = allow_windowing && g.ConfigNavWindowingKeyNext && Shortcut(g.ConfigNavWindowingKeyNext, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways, owner_id); @@ -13849,12 +13849,12 @@ void ImGui::NavUpdateWindowingOverlay() return; if (g.NavWindowingListWindow == NULL) - g.NavWindowingListWindow = FindWindowByName("###NavWindowingList"); + g.NavWindowingListWindow = FindWindowByName("##NavWindowingOverlay"); const ImGuiViewport* viewport = GetMainViewport(); SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX)); SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f)); PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f); - Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings); + Begin("##NavWindowingOverlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings); if (g.ContextName[0] != 0) SeparatorText(g.ContextName); for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--) diff --git a/imgui.h b/imgui.h index 8e240b390ead..7d2f333349a4 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.8 WIP" -#define IMGUI_VERSION_NUM 19173 +#define IMGUI_VERSION_NUM 19174 #define IMGUI_HAS_TABLE /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f772f309c84d..dccb7a5356da 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8630,7 +8630,7 @@ bool ImGui::BeginMenuBar() IM_ASSERT(!window->DC.MenuBarAppending); BeginGroup(); // Backup position on layer 0 // FIXME: Misleading to use a group for that backup/restore - PushID("##menubar"); + PushID("##MenuBar"); // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect. // We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy. From c0308da665dd1553955ba340a82e0b969631c1ad Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 29 Jan 2025 20:13:22 +0100 Subject: [PATCH 422/548] Fixed zealous GCC warning. (#8355) Amend dfd1bc3 --- imgui_tables.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index d5e952d8f9a1..5411e8a1b818 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1052,7 +1052,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) ImGuiTableColumn* column = &table->Columns[column_n]; // Initial nav layer: using FreezeRowsCount, NOT FreezeRowsRequest, so Header line changes layer when frozen - column->NavLayerCurrent = (ImS8)(table->FreezeRowsCount > 0 ? ImGuiNavLayer_Menu : table->NavLayer); + column->NavLayerCurrent = (ImS8)(table->FreezeRowsCount > 0 ? ImGuiNavLayer_Menu : (ImGuiNavLayer)table->NavLayer); if (offset_x_frozen && table->FreezeColumnsCount == visible_n) { From fa178f42350598f853f2ec36b5aeb231e0e08c75 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 30 Jan 2025 14:30:14 +0100 Subject: [PATCH 423/548] Error Handling: Recovery from missing EndMenuBar() call. (#1651) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 5 +++++ imgui_widgets.cpp | 9 +++++---- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index be448d16f355..99333efdabe3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -71,6 +71,7 @@ Other changes: scrollbar when using thick border sizes. (#8267, #7887) - Windows: Fixed IsItemXXXX() functions not working on append-version of EndChild(). (#8350) Also made some of the fields accessible after BeginChild() to match Begin() logic. +- Error Handling: Recovery from missing EndMenuBar() call. (#1651) - Tables, Menus: Fixed using BeginTable() in menu layer (any menu bar). (#8355) It previously overrode the current layer back to main layer, which caused an issue with MainMenuBar attempted to release focus when leaving the menu layer. diff --git a/imgui.cpp b/imgui.cpp index 5223ed76c892..dffd37b45f08 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10301,6 +10301,11 @@ void ImGui::ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryStat IM_ASSERT_USER_ERROR(0, "Missing EndMultiSelect()"); EndMultiSelect(); } + if (window->DC.MenuBarAppending) //-V1044 + { + IM_ASSERT_USER_ERROR(0, "Missing EndMenuBar()"); + EndMenuBar(); + } while (window->DC.TreeDepth > state_in->SizeOfTreeStack) //-V1044 { IM_ASSERT_USER_ERROR(0, "Missing TreePop()"); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index dccb7a5356da..9335da9fd0d3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8657,6 +8657,10 @@ void ImGui::EndMenuBar() return; ImGuiContext& g = *GImGui; + IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'" + IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); + IM_ASSERT(window->DC.MenuBarAppending); + // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings. if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) { @@ -8683,9 +8687,6 @@ void ImGui::EndMenuBar() } } - IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'" - IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); - IM_ASSERT(window->DC.MenuBarAppending); PopClipRect(); PopID(); window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->Pos.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos. @@ -8764,11 +8765,11 @@ bool ImGui::BeginMainMenuBar() void ImGui::EndMainMenuBar() { + ImGuiContext& g = *GImGui; EndMenuBar(); // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window // FIXME: With this strategy we won't be able to restore a NULL focus. - ImGuiContext& g = *GImGui; if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest && g.ActiveId == 0) FocusTopMostWindowUnderOne(g.NavWindow, NULL, NULL, ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild); From ae6cfd32a0372f5ac4bec3ae304e78746d7fca23 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 30 Jan 2025 14:34:05 +0100 Subject: [PATCH 424/548] Tables, Menus: Fixed tables or child windows submitted inside BeginMainMenuBar() being unable to save their settings. (#8356) Amend error handling (fa178f4) to avoid us setting ImGuiWindowFlags_NoSavedSettings on the wrong window. --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 99333efdabe3..c07fcf766af7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -75,6 +75,8 @@ Other changes: - Tables, Menus: Fixed using BeginTable() in menu layer (any menu bar). (#8355) It previously overrode the current layer back to main layer, which caused an issue with MainMenuBar attempted to release focus when leaving the menu layer. +- Tables, Menus: Fixed tables or child windows submitted inside BeginMainMenuBar() + being unable to save their settings, as the main menu bar uses _NoSavedSettings. (#8356) - ColorEdit, ColorPicker: Fixed alpha preview broken in 1.91.7. (#8336, #8241). [@PathogenDavid] - Tabs, Style: reworked selected overline rendering to better accommodate for rounded tabs. Reduced default thickness (style.TabBarOverlineSize), diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 9335da9fd0d3..0981b447e033 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8755,18 +8755,29 @@ bool ImGui::BeginMainMenuBar() float height = GetFrameHeight(); bool is_open = BeginViewportSideBar("##MainMenuBar", viewport, ImGuiDir_Up, height, window_flags); g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f); - - if (is_open) - BeginMenuBar(); - else + if (!is_open) + { End(); + return false; + } + + // Temporarily disable _NoSavedSettings, in the off-chance that tables or child windows submitted within the menu-bar may want to use settings. (#8356) + g.CurrentWindow->Flags &= ~ImGuiWindowFlags_NoSavedSettings; + BeginMenuBar(); return is_open; } void ImGui::EndMainMenuBar() { ImGuiContext& g = *GImGui; + if (!g.CurrentWindow->DC.MenuBarAppending) + { + IM_ASSERT_USER_ERROR(0, "Calling EndMainMenuBar() not from a menu-bar!"); // Not technically testing that it is the main menu bar + return; + } + EndMenuBar(); + g.CurrentWindow->Flags |= ImGuiWindowFlags_NoSavedSettings; // Restore _NoSavedSettings (#8356) // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window // FIXME: With this strategy we won't be able to restore a NULL focus. From e6c5296f30a5111fa1dc926d2c15abd0f809fbb1 Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Fri, 31 Jan 2025 16:11:33 +0300 Subject: [PATCH 425/548] Examples: SDL3: Fix for Emscripten platform (#8363) --- examples/example_sdl3_opengl3/main.cpp | 1 - examples/example_sdl3_sdlrenderer3/main.cpp | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp index 5520a7da9293..8cd54bd4ef68 100644 --- a/examples/example_sdl3_opengl3/main.cpp +++ b/examples/example_sdl3_opengl3/main.cpp @@ -18,7 +18,6 @@ #include #endif -// This example doesn't compile with Emscripten yet! Awaiting SDL3 support. #ifdef __EMSCRIPTEN__ #include "../libs/emscripten/emscripten_mainloop_stub.h" #endif diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 4b9b86e9bd5a..483350fcb47a 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -21,6 +21,10 @@ #include #endif +#ifdef __EMSCRIPTEN__ +#include "../libs/emscripten/emscripten_mainloop_stub.h" +#endif + // Main code int main(int, char**) { From dbb5eeaadffb6a3ba6a60de1290312e5802dba5a Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 31 Jan 2025 15:57:48 +0100 Subject: [PATCH 426/548] Version 1.91.8 --- docs/CHANGELOG.txt | 11 ++++++----- 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, 15 insertions(+), 14 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c07fcf766af7..eaedb9c1be0c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,12 +36,15 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.91.8 WIP (In Progress) + VERSION 1.91.8 (Released 2025-01-31) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.8 + Breaking changes: -- ColorEdit, ColorPicker: redesigned how alpha is displayed in the preview square. (#8335, #1578, #346) +- ColorEdit, ColorPicker: redesigned how alpha is displayed in the preview + square. (#8335, #1578, #346) - Removed ImGuiColorEditFlags_AlphaPreview (made value 0): it is now the default behavior. - Prior to 1.91.8: alpha was made opaque in the preview by default _unless_ using ImGuiColorEditFlags_AlphaPreview. - We now display the preview as transparent by default. You can use ImGuiColorEditFlags_AlphaOpaque to use old behavior. @@ -63,7 +66,7 @@ Other changes: by introducing a delay. This is a very rarely used UI idiom, but some apps use this: e.g. MS Explorer single-click on an icon triggers a rename. Generally use with 'delay >= io.MouseDoubleClickTime' + combine with a - 'io.MouseClickedLastCount == 1' check. + 'GetMouseClickedCount() == 1' check. - Windows: legacy SetWindowFontScale() is properly inherited by nested child windows. Note that an upcoming major release should make this obsolete, but in the meanwhile it works better now. (#2701, #8138, #1018) @@ -81,7 +84,6 @@ Other changes: - Tabs, Style: reworked selected overline rendering to better accommodate for rounded tabs. Reduced default thickness (style.TabBarOverlineSize), increased default rounding (style.TabRounding). (#8334) [@Kian738, @ocornut] - styles as the current look is not right (but ImGuiCol_TabSelectedOverline stays the same). - Debug Tools: Tweaked font preview. - ImDrawList: texture baked storage for thick line reduced from ~64x64 to ~32x32. (#3245) - Fonts: IndexLookup[] table hold 16-bit values even in ImWchar32 mode, @@ -90,7 +92,6 @@ Other changes: - Fonts: OversampleH/OversampleV defaults to 0 for automatic selection. - OversampleH == 0 --> use 1 or 2 depending on font size and use of PixelSnapH. - OversampleV == 0 --> always use 1. - This also - ImFontAtlas: made calling ClearFonts() call ClearInputData(), as calling one without the other is never correct. (#8174, #6556, #6336, #4723) - Examples: DirectX12: Reduced number of frame in flight from 3 to 2 in diff --git a/imgui.cpp b/imgui.cpp index dffd37b45f08..5ca57dfc65b3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 WIP +// dear imgui, v1.91.8 // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 7d2f333349a4..7b037a584027 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 WIP +// dear imgui, v1.91.8 // (headers) // Help: @@ -28,8 +28,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.8 WIP" -#define IMGUI_VERSION_NUM 19174 +#define IMGUI_VERSION "1.91.8" +#define IMGUI_VERSION_NUM 19180 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 43344f3fc543..03ce4710adc8 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 WIP +// dear imgui, v1.91.8 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 4b59d6775867..e426f0e5dc67 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 WIP +// dear imgui, v1.91.8 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index d4154dabaae2..af52d0feae3c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 WIP +// dear imgui, v1.91.8 // (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 5411e8a1b818..e7a3b8e8d191 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 WIP +// dear imgui, v1.91.8 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 0981b447e033..1e4297fcbd67 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 WIP +// dear imgui, v1.91.8 // (widgets code) /* From e2a99b57605982c50f2df4fefaf0767aadde9cd8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 31 Jan 2025 18:26:52 +0100 Subject: [PATCH 427/548] Internals: renamed GetIOEx() to GetIO(). Added GetPlatformIO() explicit context variant. --- imgui.cpp | 9 ++++++++- imgui_internal.h | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5ca57dfc65b3..7d4da45501d0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4814,7 +4814,7 @@ ImGuiIO& ImGui::GetIO() } // This variant exists to facilitate backends experimenting with multi-threaded parallel context. (#8069, #6293, #5856) -ImGuiIO& ImGui::GetIOEx(ImGuiContext* ctx) +ImGuiIO& ImGui::GetIO(ImGuiContext* ctx) { IM_ASSERT(ctx != NULL); return ctx->IO; @@ -4826,6 +4826,13 @@ ImGuiPlatformIO& ImGui::GetPlatformIO() return GImGui->PlatformIO; } +// This variant exists to facilitate backends experimenting with multi-threaded parallel context. (#8069, #6293, #5856) +ImGuiPlatformIO& ImGui::GetPlatformIO(ImGuiContext* ctx) +{ + IM_ASSERT(ctx != NULL; + return ctx->PlatformIO; +} + // Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame() ImDrawData* ImGui::GetDrawData() { diff --git a/imgui_internal.h b/imgui_internal.h index af52d0feae3c..2d2ea02df323 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2980,7 +2980,8 @@ namespace ImGui // If this ever crashes because g.CurrentWindow is NULL, it means that either: // - ImGui::NewFrame() has never been called, which is illegal. // - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. - IMGUI_API ImGuiIO& GetIOEx(ImGuiContext* ctx); + IMGUI_API ImGuiIO& GetIO(ImGuiContext* ctx); + IMGUI_API ImGuiPlatformIO& GetPlatformIO(ImGuiContext* ctx); inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; } IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id); From e4db4e423d78bce7e6c050f1f0710b3b635a9871 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 31 Jan 2025 19:50:18 +0100 Subject: [PATCH 428/548] Internals: renamed GetIOEx() to GetIO(). Added GetPlatformIO() explicit context variant. - OOPS --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 7d4da45501d0..88f5088515af 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4829,7 +4829,7 @@ ImGuiPlatformIO& ImGui::GetPlatformIO() // This variant exists to facilitate backends experimenting with multi-threaded parallel context. (#8069, #6293, #5856) ImGuiPlatformIO& ImGui::GetPlatformIO(ImGuiContext* ctx) { - IM_ASSERT(ctx != NULL; + IM_ASSERT(ctx != NULL); return ctx->PlatformIO; } From f820bf7cd4bd92cfbe5bbd3bab51e7cb81442e53 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Feb 2025 12:33:40 +0100 Subject: [PATCH 429/548] Version 1.91.9 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 eaedb9c1be0c..296c4202d393 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.9 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking changes: + +Other changes: + + ----------------------------------------------------------------------- VERSION 1.91.8 (Released 2025-01-31) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 88f5088515af..09c5175a3967 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 +// dear imgui, v1.91.9 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 7b037a584027..9b1a8323dfc7 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 +// dear imgui, v1.91.9 WIP // (headers) // Help: @@ -28,8 +28,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.8" -#define IMGUI_VERSION_NUM 19180 +#define IMGUI_VERSION "1.91.9 WIP" +#define IMGUI_VERSION_NUM 19181 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 03ce4710adc8..530ed6cc41bc 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 +// dear imgui, v1.91.9 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e426f0e5dc67..3fa5adae1701 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 +// dear imgui, v1.91.9 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 2d2ea02df323..d59c19c601a3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 +// dear imgui, v1.91.9 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 e7a3b8e8d191..71d1e7d8be3b 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 +// dear imgui, v1.91.9 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1e4297fcbd67..1ddaf71be402 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.8 +// dear imgui, v1.91.9 WIP // (widgets code) /* From 626533999502662a9f507b34d9ae0d8579d55a95 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Feb 2025 14:01:48 +0100 Subject: [PATCH 430/548] Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), RadioButton(), Selectable(). (#8370) Item is already made inactive at the time of calling MarkItemEdited(). Fix a604d4f71 --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 296c4202d393..10dc36bb884b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,9 @@ Breaking changes: Other changes: +- Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), Selectable(). (#8370) + Regression from 2025/01/13. + ----------------------------------------------------------------------- VERSION 1.91.8 (Released 2025-01-31) diff --git a/imgui.cpp b/imgui.cpp index 09c5175a3967..5f0ca9d81242 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4440,8 +4440,11 @@ void ImGui::MarkItemEdited(ImGuiID id) return; if (g.ActiveId == id || g.ActiveId == 0) { + // FIXME: Can't we fully rely on LastItemData yet? g.ActiveIdHasBeenEditedThisFrame = true; g.ActiveIdHasBeenEditedBefore = true; + if (g.DeactivatedItemData.ID == id) + g.DeactivatedItemData.HasBeenEditedBefore = true; } // We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343) From 204cebc8fc5678c446037f232945bde58003fa76 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Feb 2025 14:21:53 +0100 Subject: [PATCH 431/548] Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] --- backends/imgui_impl_metal.mm | 4 ++-- docs/CHANGELOG.txt | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 1e0c47f52b51..5df9176a095e 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -311,11 +311,11 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData, id c indexBufferOffset += (size_t)draw_list->IdxBuffer.Size * sizeof(ImDrawIdx); } - __block MetalContext* sharedMetalContext = bd->SharedMetalContext; + MetalContext* sharedMetalContext = bd->SharedMetalContext; [commandBuffer addCompletedHandler:^(id) { dispatch_async(dispatch_get_main_queue(), ^{ - @synchronized(bd->SharedMetalContext.bufferCache) + @synchronized(sharedMetalContext.bufferCache) { [sharedMetalContext.bufferCache addObject:vertexBuffer]; [sharedMetalContext.bufferCache addObject:indexBuffer]; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 10dc36bb884b..935d453ab604 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,9 +43,9 @@ Breaking changes: Other changes: -- Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), Selectable(). (#8370) - Regression from 2025/01/13. - +- Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), + RadioButton(), Selectable(). Regression from 2025/01/13. (#8370) +- Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] ----------------------------------------------------------------------- VERSION 1.91.8 (Released 2025-01-31) From 5dd84082ab333453e50f08ba4dc9ebf0d8860254 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Feb 2025 15:11:03 +0100 Subject: [PATCH 432/548] InputTextWithHint(): Fixed buffer overflow when user callback modifies the buffer contents in a way that alters hint visibility. (#8368) --- backends/imgui_impl_metal.mm | 1 + docs/CHANGELOG.txt | 3 +++ imgui.cpp | 1 + imgui_widgets.cpp | 14 +++++++++++++- 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 5df9176a095e..1cd2308d144d 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -15,6 +15,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-03: Metal: Crash fix. (#8367) // 2024-01-08: Metal: Fixed memory leaks when using metal-cpp (#8276, #8166) or when using multiple contexts (#7419). // 2022-08-23: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'. // 2022-07-05: Metal: Add dispatch synchronization. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 935d453ab604..e472ffcf2f94 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,6 +45,9 @@ Other changes: - Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), RadioButton(), Selectable(). Regression from 2025/01/13. (#8370) +- InputTextWithHint(): Fixed buffer-overflow (luckily often with no visible effect) + when a user callback modified the buffer contents in a way that altered the + visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut] - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 5f0ca9d81242..8f99608b24dd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2012,6 +2012,7 @@ const char* ImStreolRange(const char* str, const char* str_end) const char* ImStrbol(const char* buf_mid_line, const char* buf_begin) // find beginning-of-line { + IM_ASSERT_PARANOID(buf_mid_line >= buf_begin && buf_mid_line <= buf_begin + strlen(buf_begin)); while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n') buf_mid_line--; return buf_mid_line; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1ddaf71be402..be015a6f44ff 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4669,7 +4669,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Select the buffer to render. const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state; - const bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0); + bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0); // Password pushes a temporary font with only a fallback glyph if (is_password && !is_displaying_hint) @@ -5151,6 +5151,18 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const int buf_display_max_length = 2 * 1024 * 1024; const char* buf_display = buf_display_from_state ? state->TextA.Data : buf; //-V595 const char* buf_display_end = NULL; // We have specialized paths below for setting the length + + // Display hint when contents is empty + // At this point we need to handle the possibility that a callback could have modified the underlying buffer (#8368) + const bool new_is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0); + if (new_is_displaying_hint != is_displaying_hint) + { + if (is_password && !is_displaying_hint) + PopFont(); + is_displaying_hint = new_is_displaying_hint; + if (is_password && !is_displaying_hint) + PushPasswordFont(); + } if (is_displaying_hint) { buf_display = hint; From da0ba9e2fef6a60bae033580499a74e2764ce635 Mon Sep 17 00:00:00 2001 From: PhantomCloak Date: Sun, 2 Feb 2025 19:25:09 +0300 Subject: [PATCH 433/548] Backends: WebGPU: add type alias for dawn WGPUProgrammableStageDescriptor -> WGPUComputeState. (#8369) --- backends/imgui_impl_wgpu.cpp | 6 ++++++ docs/CHANGELOG.txt | 2 ++ 2 files changed, 8 insertions(+) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 2f34c0e0b345..84de56df2057 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -58,6 +58,12 @@ #include #include +#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +// Dawn renamed WGPUProgrammableStageDescriptor to WGPUComputeState (see: https://github.com/webgpu-native/webgpu-headers/pull/413) +// Using type alias until WGPU adopts the same naming convention (#8369) +using WGPUProgrammableStageDescriptor = WGPUComputeState; +#endif + // Dear ImGui prototypes from imgui_internal.h extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed = 0); #define MEMALIGN(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align (copied from IM_ALIGN() macro). diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e472ffcf2f94..bf40370200f4 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,6 +49,8 @@ Other changes: when a user callback modified the buffer contents in a way that altered the visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut] - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] +- Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. + [@PhantomCloak] (#8369) ----------------------------------------------------------------------- VERSION 1.91.8 (Released 2025-01-31) From de962e83d0095a0676a42da184cad8e4066669a9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Feb 2025 17:50:12 +0100 Subject: [PATCH 434/548] ImFont: remove SetGlyphVisible() Which was never marked public. Added by d284a6cff. (#2149, #515) Making room by removing stuff that are inconvenient to implement in our scaling system. If you were using this function please post an issue to report it. --- imgui.h | 1 - imgui_draw.cpp | 12 ++++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/imgui.h b/imgui.h index 9b1a8323dfc7..f80e9d255f28 100644 --- a/imgui.h +++ b/imgui.h @@ -3498,7 +3498,6 @@ struct ImFont IMGUI_API void GrowIndex(int new_size); IMGUI_API void AddGlyph(const ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. - IMGUI_API void SetGlyphVisible(ImWchar c, bool visible); IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last); }; diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3fa5adae1701..c66f52cd4103 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3770,8 +3770,10 @@ void ImFont::BuildLookupTable() } // Mark special glyphs as not visible (note that AddGlyph already mark as non-visible glyphs with zero-size polygons) - SetGlyphVisible((ImWchar)' ', false); - SetGlyphVisible((ImWchar)'\t', false); + if (ImFontGlyph* glyph = (ImFontGlyph*)(void*)FindGlyph((ImWchar)' ')) + glyph->Visible = false; + if (ImFontGlyph* glyph = (ImFontGlyph*)(void*)FindGlyph((ImWchar)'\t')) + glyph->Visible = false; // Setup Fallback character const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' }; @@ -3827,12 +3829,6 @@ bool ImFont::IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last) return true; } -void ImFont::SetGlyphVisible(ImWchar c, bool visible) -{ - if (ImFontGlyph* glyph = (ImFontGlyph*)(void*)FindGlyph((ImWchar)c)) - glyph->Visible = visible ? 1 : 0; -} - void ImFont::GrowIndex(int new_size) { IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size); From 1a31e31ae92db10431a35bc5fbb5465848659e9a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Feb 2025 17:55:35 +0100 Subject: [PATCH 435/548] (Breaking) Fonts: removed ImFontConfig::GlyphExtraSpacing option which seems largely obsolete and unused. (#242) --- docs/CHANGELOG.txt | 3 +++ docs/FONTS.md | 2 +- imgui.cpp | 1 + imgui.h | 6 +++--- imgui_draw.cpp | 5 +---- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bf40370200f4..72f0ed126f44 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,9 @@ HOW TO UPDATE? Breaking changes: +- Removed ImFontConfig::GlyphExtraSpacing option which seems largely obsolete and + unused. If you were using this please report it! (#242). + Other changes: - Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), diff --git a/docs/FONTS.md b/docs/FONTS.md index e36afdf817d0..e9fbcbe42712 100644 --- a/docs/FONTS.md +++ b/docs/FONTS.md @@ -110,7 +110,7 @@ ImGui::PopFont(); **For advanced options create a ImFontConfig structure and pass it to the AddFont() function (it will be copied internally):** ```cpp ImFontConfig config; -config.GlyphExtraSpacing.x = 1.0f; +config.RasterizerDensity = 2.0f; ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config); ``` diff --git a/imgui.cpp b/imgui.cpp index 8f99608b24dd..3a7e600058ec 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -430,6 +430,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. + - 2025/02/03 (1.91.9) - removed ImFontConfig::GlyphExtraSpacing option which seems largely obsolete and unused. If you were using this please report it! - 2025/01/22 (1.91.8) - removed ImGuiColorEditFlags_AlphaPreview (made value 0): it is now the default behavior. prior to 1.91.8: alpha was made opaque in the preview by default _unless_ using ImGuiColorEditFlags_AlphaPreview. We now display the preview as transparent by default. You can use ImGuiColorEditFlags_AlphaOpaque to use old behavior. the new flags (ImGuiColorEditFlags_AlphaOpaque, ImGuiColorEditFlags_AlphaNoBg + existing ImGuiColorEditFlags_AlphaPreviewHalf) may be combined better and allow finer controls: diff --git a/imgui.h b/imgui.h index f80e9d255f28..f6bfa4e5d0d6 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.9 WIP" -#define IMGUI_VERSION_NUM 19181 +#define IMGUI_VERSION_NUM 19182 #define IMGUI_HAS_TABLE /* @@ -3257,7 +3257,7 @@ struct ImFontConfig int OversampleH; // 0 (2) // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1 or 2 depending on size. Note the difference between 2 and 3 is minimal. You can reduce this to 1 for large glyphs save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details. int OversampleV; // 0 (1) // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1. This is not really useful as we don't use sub-pixel positions on the Y axis. float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height). - ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs when rendered: essentially add to glyph->AdvanceX. Only X axis is supported for now. + //ImVec2 GlyphExtraSpacing; // 0, 0 // (REMOVED AT IT SEEMS LARGELY OBSOLETE. PLEASE REPORT IF YOU WERE USING THIS). Extra spacing (in pixels) between glyphs when rendered: essentially add to glyph->AdvanceX. Only X axis is supported for now. ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. const ImWchar* GlyphRanges; // NULL // THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font @@ -3281,7 +3281,7 @@ struct ImFontGlyph unsigned int Colored : 1; // Flag to indicate glyph is colored and should generally ignore tinting (make it usable with no shift on little-endian as this is used in loops) unsigned int Visible : 1; // Flag to indicate glyph has no visible pixels (e.g. space). Allow early out when rendering. unsigned int Codepoint : 30; // 0x0000..0x10FFFF - float AdvanceX; // Distance to next character (= data from font + ImFontConfig::GlyphExtraSpacing.x baked in) + float AdvanceX; // Horizontal distance to advance layout with float X0, Y0, X1, Y1; // Glyph corners float U0, V0, U1, V1; // Texture coordinates }; diff --git a/imgui_draw.cpp b/imgui_draw.cpp index c66f52cd4103..78fa4c1eac79 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3349,7 +3349,7 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas) if (r->Font == NULL || r->GlyphID == 0) continue; - // Will ignore ImFontConfig settings: GlyphMinAdvanceX, GlyphMinAdvanceY, GlyphExtraSpacing, PixelSnapH + // Will ignore ImFontConfig settings: GlyphMinAdvanceX, GlyphMinAdvanceY, PixelSnapH IM_ASSERT(r->Font->ContainerAtlas == atlas); ImVec2 uv0, uv1; atlas->CalcCustomRectUV(r, &uv0, &uv1); @@ -3858,9 +3858,6 @@ void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, floa // Snap to pixel if (cfg->PixelSnapH) advance_x = IM_ROUND(advance_x); - - // Bake spacing - advance_x += cfg->GlyphExtraSpacing.x; } int glyph_idx = Glyphs.Size; From 2d20e13746c05bfe36d4a57ac465e7a9fe9005d9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 4 Feb 2025 20:19:57 +0100 Subject: [PATCH 436/548] Backends: GLFW: Added comment about io.AddMouseSourceEvent() not being properly called. (#8374) --- backends/imgui_impl_glfw.cpp | 2 ++ backends/imgui_impl_glfw.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 01a6a5566397..66183561f08a 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -9,6 +9,8 @@ // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5] // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// Missing features or Issues: +// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index 53a22415d87c..bba6d09ea8c1 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -8,6 +8,8 @@ // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values are obsolete since 1.87 and not supported since 1.91.5] // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. +// Missing features or Issues: +// [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. From cfed18afc79c1bdea142cccd74639734edbfbaf6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 6 Feb 2025 12:34:37 +0100 Subject: [PATCH 437/548] Add ImFontConfig::GlyphExtraAdvanceX as a replacement for GlyphExtraSpacing.x (#242) Partly restore 1a31e31. --- docs/CHANGELOG.txt | 3 +-- imgui.cpp | 2 +- imgui.h | 5 +++-- imgui_draw.cpp | 3 +++ 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 72f0ed126f44..a81ef2038f2b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,8 +41,7 @@ HOW TO UPDATE? Breaking changes: -- Removed ImFontConfig::GlyphExtraSpacing option which seems largely obsolete and - unused. If you were using this please report it! (#242). +- Renamed ImFontConfig::GlyphExtraSpacing.x option to GlyphExtraAdvanceX. (#242) Other changes: diff --git a/imgui.cpp b/imgui.cpp index 3a7e600058ec..4de75457ddc9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -430,7 +430,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. - - 2025/02/03 (1.91.9) - removed ImFontConfig::GlyphExtraSpacing option which seems largely obsolete and unused. If you were using this please report it! + - 2025/02/06 (1.91.9) - renamed ImFontConfig::GlyphExtraSpacing.x to ImFontConfig::GlyphExtraAdvanceX. - 2025/01/22 (1.91.8) - removed ImGuiColorEditFlags_AlphaPreview (made value 0): it is now the default behavior. prior to 1.91.8: alpha was made opaque in the preview by default _unless_ using ImGuiColorEditFlags_AlphaPreview. We now display the preview as transparent by default. You can use ImGuiColorEditFlags_AlphaOpaque to use old behavior. the new flags (ImGuiColorEditFlags_AlphaOpaque, ImGuiColorEditFlags_AlphaNoBg + existing ImGuiColorEditFlags_AlphaPreviewHalf) may be combined better and allow finer controls: diff --git a/imgui.h b/imgui.h index f6bfa4e5d0d6..a3f660366ad2 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.9 WIP" -#define IMGUI_VERSION_NUM 19182 +#define IMGUI_VERSION_NUM 19183 #define IMGUI_HAS_TABLE /* @@ -3257,11 +3257,12 @@ struct ImFontConfig int OversampleH; // 0 (2) // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1 or 2 depending on size. Note the difference between 2 and 3 is minimal. You can reduce this to 1 for large glyphs save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details. int OversampleV; // 0 (1) // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1. This is not really useful as we don't use sub-pixel positions on the Y axis. float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height). - //ImVec2 GlyphExtraSpacing; // 0, 0 // (REMOVED AT IT SEEMS LARGELY OBSOLETE. PLEASE REPORT IF YOU WERE USING THIS). Extra spacing (in pixels) between glyphs when rendered: essentially add to glyph->AdvanceX. Only X axis is supported for now. + //ImVec2 GlyphExtraSpacing; // 0, 0 // (REMOVED IN 1.91.9: use GlyphExtraAdvanceX) ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. const ImWchar* GlyphRanges; // NULL // THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs + float GlyphExtraAdvanceX; // 0 // Extra spacing (in pixels) between glyphs. Please contact us if you are using this. unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure. float RasterizerMultiply; // 1.0f // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future. float RasterizerDensity; // 1.0f // DPI scale for rasterization, not altering other font metrics: make it easy to swap between e.g. a 100% and a 400% fonts for a zooming display. IMPORTANT: If you increase this it is expected that you increase font scale accordingly, otherwise quality may look lowered. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 78fa4c1eac79..ed5164bb77a7 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3858,6 +3858,9 @@ void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, floa // Snap to pixel if (cfg->PixelSnapH) advance_x = IM_ROUND(advance_x); + + // Bake extra spacing + advance_x += cfg->GlyphExtraAdvanceX; } int glyph_idx = Glyphs.Size; From 0625b37760215f2b890e8605e7070bb8c9521a22 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 6 Feb 2025 18:37:32 +0100 Subject: [PATCH 438/548] Scrollbar: Rework logic that fades-out scrollbar when it becomes too small. Amend 0236bc246f --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a81ef2038f2b..7977ef681a77 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,8 @@ Other changes: - InputTextWithHint(): Fixed buffer-overflow (luckily often with no visible effect) when a user callback modified the buffer contents in a way that altered the visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut] +- Scrollbar: Rework logic that fades-out scrollbar when it becomes too small, + which amusingly made it disappear when using very big font/frame size. - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index be015a6f44ff..612ff62a639f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -971,8 +971,8 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 // When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the window resize grab) float alpha = 1.0f; - if ((axis == ImGuiAxis_Y) && bb_frame_height < g.FontSize + g.Style.FramePadding.y * 2.0f) - alpha = ImSaturate((bb_frame_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f)); + if ((axis == ImGuiAxis_Y) && bb_frame_height < bb_frame_width) + alpha = ImSaturate(bb_frame_height / ImMax(bb_frame_width * 2.0f, 1.0f)); if (alpha <= 0.0f) return false; @@ -989,7 +989,8 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 // But we maintain a minimum size in pixel to allow for the user to still aim inside. IM_ASSERT(ImMax(size_contents_v, size_visible_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers. const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_visible_v), (ImS64)1); - const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_visible_v / (float)win_size_v), style.GrabMinSize, scrollbar_size_v); + const float grab_h_minsize = ImMin(bb.GetSize()[axis], style.GrabMinSize); + const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_visible_v / (float)win_size_v), grab_h_minsize, scrollbar_size_v); const float grab_h_norm = grab_h_pixels / scrollbar_size_v; // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). From 4f1d3809c32b0dd8745273bf7e22b4aa37494ce8 Mon Sep 17 00:00:00 2001 From: fdsa <14tanks999@gmail.com> Date: Wed, 5 Feb 2025 18:41:03 -0800 Subject: [PATCH 439/548] Fixed tabs and spaces (#8377) --- .github/ISSUE_TEMPLATE/issue_template.yml | 2 +- backends/imgui_impl_glfw.cpp | 2 +- backends/imgui_impl_glut.cpp | 2 +- backends/imgui_impl_sdlrenderer2.cpp | 34 +++++++++---------- backends/imgui_impl_sdlrenderer3.cpp | 34 +++++++++---------- backends/imgui_impl_wgpu.cpp | 8 ++--- backends/imgui_impl_win32.cpp | 30 ++++++++-------- docs/CONTRIBUTING.md | 10 +++--- docs/FAQ.md | 2 +- docs/TODO.txt | 2 +- examples/example_allegro5/README.md | 6 ++-- .../project.pbxproj | 12 +++---- examples/example_apple_metal/main.mm | 4 +-- examples/example_sdl3_opengl3/Makefile | 8 ++--- examples/example_sdl3_sdlgpu3/Makefile | 8 ++--- examples/example_sdl3_sdlrenderer3/Makefile | 8 ++--- .../example_win32_opengl3/build_mingw.bat | 2 +- imgui.h | 2 +- imgui_demo.cpp | 18 +++++----- misc/freetype/README.md | 2 +- misc/freetype/imgui_freetype.cpp | 10 +++--- 21 files changed, 103 insertions(+), 103 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/issue_template.yml b/.github/ISSUE_TEMPLATE/issue_template.yml index c1b57de4b739..46ed826d520a 100644 --- a/.github/ISSUE_TEMPLATE/issue_template.yml +++ b/.github/ISSUE_TEMPLATE/issue_template.yml @@ -8,7 +8,7 @@ body: For anything else: **we are happy to use 'GitHub Issues' for many types of open-ended questions**. We are encouraging 'Issues' becoming a large, centralized, tagged, cross-referenced database of Dear ImGui contents. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users. - + **If you are using Dear ImGui as part of a job that you are being well-paid for** and your company is not a sponsor. Please be mindful that this is a Free Software and you might be about to ask volunteers to help you doing your job. Please put extra effort describing your issue or question properly. If your company is wealthy, please read [Funding](https://github.com/ocornut/imgui/wiki/Funding) and consider getting in touch. - type: markdown attributes: diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 66183561f08a..454a36d368ce 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -469,7 +469,7 @@ void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int) { - // Unused in 'master' branch but 'docking' branch will use this, so we declare it ahead of it so if you have to install callbacks you can install this one too. + // Unused in 'master' branch but 'docking' branch will use this, so we declare it ahead of it so if you have to install callbacks you can install this one too. } #ifdef EMSCRIPTEN_USE_EMBEDDED_GLFW3 diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp index ef7f17922ec5..a68f9dbc8ed7 100644 --- a/backends/imgui_impl_glut.cpp +++ b/backends/imgui_impl_glut.cpp @@ -50,7 +50,7 @@ static int g_Time = 0; // Current time, in milliseconds -// Glut has 1 function for characters and one for "special keys". We map the characters in the 0..255 range and the keys above. +// Glut has one function for characters and one for "special keys". We map the characters in the 0..255 range and the keys above. static ImGuiKey ImGui_ImplGLUT_KeyToImGuiKey(int key) { switch (key) diff --git a/backends/imgui_impl_sdlrenderer2.cpp b/backends/imgui_impl_sdlrenderer2.cpp index 8245854c262c..bfaeb9138161 100644 --- a/backends/imgui_impl_sdlrenderer2.cpp +++ b/backends/imgui_impl_sdlrenderer2.cpp @@ -100,10 +100,10 @@ void ImGui_ImplSDLRenderer2_Shutdown() static void ImGui_ImplSDLRenderer2_SetupRenderState(SDL_Renderer* renderer) { - // Clear out any viewports and cliprect set by the user + // Clear out any viewports and cliprect set by the user // FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process. - SDL_RenderSetViewport(renderer, nullptr); - SDL_RenderSetClipRect(renderer, nullptr); + SDL_RenderSetViewport(renderer, nullptr); + SDL_RenderSetClipRect(renderer, nullptr); } void ImGui_ImplSDLRenderer2_NewFrame() @@ -117,21 +117,21 @@ void ImGui_ImplSDLRenderer2_NewFrame() void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* renderer) { - // If there's a scale factor set by the user, use that instead + // If there's a scale factor set by the user, use that instead // If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass // to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here. float rsx = 1.0f; - float rsy = 1.0f; - SDL_RenderGetScale(renderer, &rsx, &rsy); + float rsy = 1.0f; + SDL_RenderGetScale(renderer, &rsx, &rsy); ImVec2 render_scale; - render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f; - render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f; + render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f; + render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f; - // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) - int fb_width = (int)(draw_data->DisplaySize.x * render_scale.x); - int fb_height = (int)(draw_data->DisplaySize.y * render_scale.y); - if (fb_width == 0 || fb_height == 0) - return; + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + int fb_width = (int)(draw_data->DisplaySize.x * render_scale.x); + int fb_height = (int)(draw_data->DisplaySize.y * render_scale.y); + if (fb_width == 0 || fb_height == 0) + return; // Backup SDL_Renderer state that will be modified to restore it afterwards struct BackupSDLRendererState @@ -154,9 +154,9 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* render_state.Renderer = renderer; platform_io.Renderer_RenderState = &render_state; - // Will project scissor/clipping rectangles into framebuffer space - ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports - ImVec2 clip_scale = render_scale; + // Will project scissor/clipping rectangles into framebuffer space + ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports + ImVec2 clip_scale = render_scale; // Render command lists for (int n = 0; n < draw_data->CmdListsCount; n++) @@ -201,7 +201,7 @@ void ImGui_ImplSDLRenderer2_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* #endif // Bind texture, Draw - SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID(); + SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID(); SDL_RenderGeometryRaw(renderer, tex, xy, (int)sizeof(ImDrawVert), color, (int)sizeof(ImDrawVert), diff --git a/backends/imgui_impl_sdlrenderer3.cpp b/backends/imgui_impl_sdlrenderer3.cpp index 99253d9643fd..42fefa0cd8f3 100644 --- a/backends/imgui_impl_sdlrenderer3.cpp +++ b/backends/imgui_impl_sdlrenderer3.cpp @@ -99,10 +99,10 @@ void ImGui_ImplSDLRenderer3_Shutdown() static void ImGui_ImplSDLRenderer3_SetupRenderState(SDL_Renderer* renderer) { - // Clear out any viewports and cliprect set by the user + // Clear out any viewports and cliprect set by the user // FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process. - SDL_SetRenderViewport(renderer, nullptr); - SDL_SetRenderClipRect(renderer, nullptr); + SDL_SetRenderViewport(renderer, nullptr); + SDL_SetRenderClipRect(renderer, nullptr); } void ImGui_ImplSDLRenderer3_NewFrame() @@ -136,21 +136,21 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* { ImGui_ImplSDLRenderer3_Data* bd = ImGui_ImplSDLRenderer3_GetBackendData(); - // If there's a scale factor set by the user, use that instead + // If there's a scale factor set by the user, use that instead // If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass // to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here. float rsx = 1.0f; - float rsy = 1.0f; - SDL_GetRenderScale(renderer, &rsx, &rsy); + float rsy = 1.0f; + SDL_GetRenderScale(renderer, &rsx, &rsy); ImVec2 render_scale; - render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f; - render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f; + render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f; + render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f; - // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) - int fb_width = (int)(draw_data->DisplaySize.x * render_scale.x); - int fb_height = (int)(draw_data->DisplaySize.y * render_scale.y); - if (fb_width == 0 || fb_height == 0) - return; + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) + int fb_width = (int)(draw_data->DisplaySize.x * render_scale.x); + int fb_height = (int)(draw_data->DisplaySize.y * render_scale.y); + if (fb_width == 0 || fb_height == 0) + return; // Backup SDL_Renderer state that will be modified to restore it afterwards struct BackupSDLRendererState @@ -175,9 +175,9 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* render_state.Renderer = renderer; platform_io.Renderer_RenderState = &render_state; - // Will project scissor/clipping rectangles into framebuffer space - ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports - ImVec2 clip_scale = render_scale; + // Will project scissor/clipping rectangles into framebuffer space + ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports + ImVec2 clip_scale = render_scale; // Render command lists for (int n = 0; n < draw_data->CmdListsCount; n++) @@ -218,7 +218,7 @@ void ImGui_ImplSDLRenderer3_RenderDrawData(ImDrawData* draw_data, SDL_Renderer* const SDL_Color* color = (const SDL_Color*)(const void*)((const char*)(vtx_buffer + pcmd->VtxOffset) + offsetof(ImDrawVert, col)); // SDL 2.0.19+ // Bind texture, Draw - SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID(); + SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID(); SDL_RenderGeometryRaw8BitColor(renderer, bd->ColorBuffer, tex, xy, (int)sizeof(ImDrawVert), color, (int)sizeof(ImDrawVert), diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 84de56df2057..a81662d8429d 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -268,13 +268,13 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); #ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN - WGPUShaderSourceWGSL wgsl_desc = {}; + WGPUShaderSourceWGSL wgsl_desc = {}; wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL; - wgsl_desc.code = { wgsl_source, WGPU_STRLEN }; + wgsl_desc.code = { wgsl_source, WGPU_STRLEN }; #else - WGPUShaderModuleWGSLDescriptor wgsl_desc = {}; + WGPUShaderModuleWGSLDescriptor wgsl_desc = {}; wgsl_desc.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor; - wgsl_desc.code = wgsl_source; + wgsl_desc.code = wgsl_source; #endif WGPUShaderModuleDescriptor desc = {}; diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index f1cf6eccc52b..03ab53523d37 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -790,9 +790,9 @@ static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD) { typedef LONG(WINAPI* PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*, ULONG, ULONGLONG); static PFN_RtlVerifyVersionInfo RtlVerifyVersionInfoFn = nullptr; - if (RtlVerifyVersionInfoFn == nullptr) - if (HMODULE ntdllModule = ::GetModuleHandleA("ntdll.dll")) - RtlVerifyVersionInfoFn = (PFN_RtlVerifyVersionInfo)GetProcAddress(ntdllModule, "RtlVerifyVersionInfo"); + if (RtlVerifyVersionInfoFn == nullptr) + if (HMODULE ntdllModule = ::GetModuleHandleA("ntdll.dll")) + RtlVerifyVersionInfoFn = (PFN_RtlVerifyVersionInfo)GetProcAddress(ntdllModule, "RtlVerifyVersionInfo"); if (RtlVerifyVersionInfoFn == nullptr) return FALSE; @@ -800,10 +800,10 @@ static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD) ULONGLONG conditionMask = 0; versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); versionInfo.dwMajorVersion = major; - versionInfo.dwMinorVersion = minor; - VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); - VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); - return (RtlVerifyVersionInfoFn(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask) == 0) ? TRUE : FALSE; + versionInfo.dwMinorVersion = minor; + VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + return (RtlVerifyVersionInfoFn(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask) == 0) ? TRUE : FALSE; } #define _IsWindowsVistaOrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA @@ -861,16 +861,16 @@ float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor) UINT xdpi = 96, ydpi = 96; if (_IsWindows8Point1OrGreater()) { - static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process - static PFN_GetDpiForMonitor GetDpiForMonitorFn = nullptr; - if (GetDpiForMonitorFn == nullptr && shcore_dll != nullptr) + static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process + static PFN_GetDpiForMonitor GetDpiForMonitorFn = nullptr; + if (GetDpiForMonitorFn == nullptr && shcore_dll != nullptr) GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor"); - if (GetDpiForMonitorFn != nullptr) - { - GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); + if (GetDpiForMonitorFn != nullptr) + { + GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert! - return xdpi / 96.0f; - } + return xdpi / 96.0f; + } } #ifndef NOGDI const HDC dc = ::GetDC(nullptr); diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 5cc9cdb53f40..f70cf0e23448 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -34,7 +34,7 @@ Only if you: Then please [use the Discussions forums](https://github.com/ocornut/imgui/discussions) instead of opening an issue. -If Dear ImGui is successfully showing in your app and you have used Dear ImGui before, you can open an Issue. Any form of discussions is welcome as a new issue. +If Dear ImGui is successfully showing in your app and you have used Dear ImGui before, you can open an Issue. Any form of discussions is welcome as a new issue. ## How to open an issue @@ -52,7 +52,7 @@ Steps: - **Please INCLUDE CODE. Provide a Minimal, Complete, and Verifiable Example ([MCVE](https://stackoverflow.com/help/mcve)) to demonstrate your problem**. An ideal submission includes a small piece of code that anyone can paste into one of the examples applications (examples/../main.cpp) or demo (imgui_demo.cpp) to understand and reproduce it. **Narrowing your problem to its shortest and purest form is the easiest way to understand it, explain it and fix it**. Please test your shortened code to ensure it exhibits the problem. **Often while creating the MCVE you will solve the problem!** Many questions that are missing a standalone verifiable example are missing the actual cause of their issue in the description, which ends up wasting everyone's time. - **Attach screenshots (or GIF/video) to clarify the context**. They often convey useful information that is omitted by the description. You can drag pictures/files in the message edit box. Avoid using 3rd party image hosting services, prefer the long-term longevity of GitHub attachments (you can drag pictures into your post). On Windows, you can use [ScreenToGif](https://www.screentogif.com/) to easily capture .gif files. - **If you are discussing an assert or a crash, please provide a debugger callstack**. Never state "it crashes" without additional information. If you don't know how to use a debugger and retrieve a callstack, learning about it will be useful. -- **Please make sure that your project has asserts enabled.** Calls to IM_ASSERT() are scattered in the code to help catch common issues. When an assert is triggered read the comments around it. By default IM_ASSERT() calls the standard assert() function. To verify that your asserts are enabled, add the line `IM_ASSERT(false);` in your main() function. Your application should display an error message and abort. If your application doesn't report an error, your asserts are disabled. +- **Please make sure that your project has asserts enabled.** Calls to IM_ASSERT() are scattered in the code to help catch common issues. When an assert is triggered read the comments around it. By default IM_ASSERT() calls the standard assert() function. To verify that your asserts are enabled, add the line `IM_ASSERT(false);` in your main() function. Your application should display an error message and abort. If your application doesn't report an error, your asserts are disabled. - Please state if you have made substantial modifications to your copy of Dear ImGui or the back-end. - If you are not calling Dear ImGui directly from C++, please provide information about your Language and the wrapper/binding you are using. - Be mindful that messages are being sent to the mailbox of "Watching" users. Try to proofread your messages before sending them. Edits are not seen by those users unless they browse the site. @@ -65,12 +65,12 @@ If you have been using Dear ImGui for a while or have been using C/C++ for sever ## How to open a Pull Request -- **Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance.** PR should be crafted both in the interest of the end-users and also to ease the maintainer into understanding and accepting it. +- **Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance.** PR should be crafted both in the interest of the end-users and also to ease the maintainer into understanding and accepting it. - Many PRs are useful to demonstrate a need and a possible solution but aren't adequate for merging (causing other issues, not seeing other aspects of the big picture, etc.). In doubt, don't hesitate to push a PR because that is always the first step toward pointing toward a problem, and finding the mergeable solution! Even if a PR stays unmerged for a long time, its presence can be useful for other users and helps toward finding a general solution. -- **When adding a feature,** please describe the usage context (how you intend to use it, why you need it, etc.). Be mindful of [The XY Problem](http://xyproblem.info/). +- **When adding a feature,** please describe the usage context (how you intend to use it, why you need it, etc.). Be mindful of [The XY Problem](http://xyproblem.info/). - **When fixing a warning or compilation problem,** please post the compiler log and specify the compiler version and platform you are using. - **Attach screenshots (or GIF/video) to clarify the context and demonstrate the feature at a glance.** You can drag pictures/files in the message edit box. Prefer the long-term longevity of GitHub attachments over 3rd party hosting (you can drag pictures into your post). -- **Make sure your code follows the coding style already used in the codebase:** 4 spaces indentations (no tabs), `local_variable`, `FunctionName()`, `MemberName`, `// Text Comment`, `//CodeComment();`, C-style casts, etc.. We don't use modern C++ idioms and tend to use only a minimum of C++11 features. The applications under examples/ are generally less consistent because they sometimes try to mimic the coding style often adopted by a certain ecosystem (e.g. DirectX-related code tend to use the style of their sample). +- **Make sure your code follows the coding style already used in the codebase:** 4 spaces indentations (no tabs), `local_variable`, `FunctionName()`, `MemberName`, `// Text Comment`, `//CodeComment();`, C-style casts, etc.. We don't use modern C++ idioms and tend to use only a minimum of C++11 features. The applications under examples/ are generally less consistent because they sometimes try to mimic the coding style often adopted by a certain ecosystem (e.g. DirectX-related code tend to use the style of their sample). - **Make sure you create a branch dedicated to the pull request**. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR (we can still cherry-pick individual commits). ## Copyright / Contributor License Agreement diff --git a/docs/FAQ.md b/docs/FAQ.md index 8dde1967b469..6e8d6c26f7dd 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -233,7 +233,7 @@ for (int n = 0; n < 3; n++) ImGui::End();
A primer on labels and the ID Stack... diff --git a/docs/TODO.txt b/docs/TODO.txt index 2a42874cd3fe..31238ff83536 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -9,7 +9,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - doc: add a proper documentation system (maybe relying on automation? #435) - doc: checklist app to verify backends/integration of imgui (test inputs, rendering, callback, etc.). - doc/tips: tips of the day: website? applet in imgui_club? - + - window: preserve/restore relative focus ordering (persistent or not), and e.g. of multiple reappearing windows (#2304) -> also see docking reference to same #. - window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis). (#690) - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass. diff --git a/examples/example_allegro5/README.md b/examples/example_allegro5/README.md index 4af31f6f3a2e..940b47fdb22d 100644 --- a/examples/example_allegro5/README.md +++ b/examples/example_allegro5/README.md @@ -24,9 +24,9 @@ You may install Allegro using vcpkg: git clone https://github.com/Microsoft/vcpkg cd vcpkg bootstrap-vcpkg.bat -vcpkg install allegro5 --triplet=x86-windows ; for win32 -vcpkg install allegro5 --triplet=x64-windows ; for win64 -vcpkg integrate install ; register include / libs in Visual Studio +vcpkg install allegro5 --triplet=x86-windows ; for win32 +vcpkg install allegro5 --triplet=x64-windows ; for win64 +vcpkg integrate install ; register include / libs in Visual Studio ``` Build: diff --git a/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj b/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj index 4bb4fc288791..5f657eab9495 100644 --- a/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj +++ b/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj @@ -268,9 +268,9 @@ 8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal.mm in Sources */, 83BBEA0920EB54E700295997 /* imgui.cpp in Sources */, 83BBEA0720EB54E700295997 /* imgui_demo.cpp in Sources */, - 83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */, + 83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */, 5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */, - 07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */, + 07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */, 8309BDA5253CCC070045E2A1 /* main.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -281,10 +281,10 @@ files = ( 8309BDBE253CCCB60045E2A1 /* imgui_impl_metal.mm in Sources */, 8309BDBF253CCCB60045E2A1 /* imgui_impl_osx.mm in Sources */, - 83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */, - 83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */, - 83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */, - 5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */, + 83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */, + 83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */, + 83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */, + 5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */, 07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */, 8309BDA8253CCC080045E2A1 /* main.mm in Sources */, ); diff --git a/examples/example_apple_metal/main.mm b/examples/example_apple_metal/main.mm index 109ef6153c3e..830f1aed33b6 100644 --- a/examples/example_apple_metal/main.mm +++ b/examples/example_apple_metal/main.mm @@ -129,7 +129,7 @@ -(void)drawInMTKView:(MTKView*)view if (renderPassDescriptor == nil) { [commandBuffer commit]; - return; + return; } // Start the Dear ImGui frame @@ -192,7 +192,7 @@ -(void)drawInMTKView:(MTKView*)view [renderEncoder popDebugGroup]; [renderEncoder endEncoding]; - // Present + // Present [commandBuffer presentDrawable:view.currentDrawable]; [commandBuffer commit]; } diff --git a/examples/example_sdl3_opengl3/Makefile b/examples/example_sdl3_opengl3/Makefile index 741e97d0c270..c2ef3ba556c3 100644 --- a/examples/example_sdl3_opengl3/Makefile +++ b/examples/example_sdl3_opengl3/Makefile @@ -54,11 +54,11 @@ ifeq ($(UNAME_S), Darwin) #APPLE endif ifeq ($(OS), Windows_NT) - ECHO_MESSAGE = "MinGW" - LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl3` + ECHO_MESSAGE = "MinGW" + LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl3` - CXXFLAGS += `pkg-config --cflags sdl3` - CFLAGS = $(CXXFLAGS) + CXXFLAGS += `pkg-config --cflags sdl3` + CFLAGS = $(CXXFLAGS) endif ##--------------------------------------------------------------------- diff --git a/examples/example_sdl3_sdlgpu3/Makefile b/examples/example_sdl3_sdlgpu3/Makefile index f6239e0fa845..c3159d88804e 100644 --- a/examples/example_sdl3_sdlgpu3/Makefile +++ b/examples/example_sdl3_sdlgpu3/Makefile @@ -43,11 +43,11 @@ ifeq ($(UNAME_S), Darwin) #APPLE endif ifeq ($(OS), Windows_NT) - ECHO_MESSAGE = "MinGW" - LIBS += -lgdi32 -limm32 `pkg-config --static --libs sdl3` + ECHO_MESSAGE = "MinGW" + LIBS += -lgdi32 -limm32 `pkg-config --static --libs sdl3` - CXXFLAGS += `pkg-config --cflags sdl3` - CFLAGS = $(CXXFLAGS) + CXXFLAGS += `pkg-config --cflags sdl3` + CFLAGS = $(CXXFLAGS) endif ##--------------------------------------------------------------------- diff --git a/examples/example_sdl3_sdlrenderer3/Makefile b/examples/example_sdl3_sdlrenderer3/Makefile index 238576c7c341..2ca98654574b 100644 --- a/examples/example_sdl3_sdlrenderer3/Makefile +++ b/examples/example_sdl3_sdlrenderer3/Makefile @@ -43,11 +43,11 @@ ifeq ($(UNAME_S), Darwin) #APPLE endif ifeq ($(OS), Windows_NT) - ECHO_MESSAGE = "MinGW" - LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl3` + ECHO_MESSAGE = "MinGW" + LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl3` - CXXFLAGS += `pkg-config --cflags sdl3` - CFLAGS = $(CXXFLAGS) + CXXFLAGS += `pkg-config --cflags sdl3` + CFLAGS = $(CXXFLAGS) endif ##--------------------------------------------------------------------- diff --git a/examples/example_win32_opengl3/build_mingw.bat b/examples/example_win32_opengl3/build_mingw.bat index 7672185858d2..e9f804f5d00a 100644 --- a/examples/example_win32_opengl3/build_mingw.bat +++ b/examples/example_win32_opengl3/build_mingw.bat @@ -1,4 +1,4 @@ -@REM Build for MINGW64 or 32 from MSYS2. +@REM Build for MINGW64 or 32 from MSYS2. @set OUT_DIR=Debug @set OUT_EXE=example_win32_opengl3 @set INCLUDES=-I../.. -I../../backends diff --git a/imgui.h b/imgui.h index a3f660366ad2..acec7bf999ac 100644 --- a/imgui.h +++ b/imgui.h @@ -1177,7 +1177,7 @@ enum ImGuiInputTextFlags_ ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID(). // Elide display / Alignment - ImGuiInputTextFlags_ElideLeft = 1 << 17, // When text doesn't fit, elide left side to ensure right side stays visible. Useful for path/filenames. Single-line only! + ImGuiInputTextFlags_ElideLeft = 1 << 17, // When text doesn't fit, elide left side to ensure right side stays visible. Useful for path/filenames. Single-line only! // Callback features ImGuiInputTextFlags_CallbackCompletion = 1 << 18, // Callback on pressing TAB (for completion handling) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 530ed6cc41bc..dd6ebb93e8d2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -584,7 +584,7 @@ void ImGui::ShowDemoWindow(bool* p_open) "- Error recovery is not perfect nor guaranteed! It is a feature to ease development.\n" "- You not are not supposed to rely on it in the course of a normal application run.\n" "- Possible usage: facilitate recovery from errors triggered from a scripting language or after specific exceptions handlers.\n" - "- Always ensure that on programmers seat you have at minimum Asserts or Tooltips enabled when making direct imgui API call!" + "- Always ensure that on programmers seat you have at minimum Asserts or Tooltips enabled when making direct imgui API call! " "Otherwise it would severely hinder your ability to catch and correct mistakes!"); ImGui::Checkbox("io.ConfigErrorRecoveryEnableAssert", &io.ConfigErrorRecoveryEnableAssert); ImGui::Checkbox("io.ConfigErrorRecoveryEnableDebugLog", &io.ConfigErrorRecoveryEnableDebugLog); @@ -1035,8 +1035,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::SeparatorText("Custom"); HelpMarker( - "Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() is the preferred way to standardize" - "tooltip activation details across your application. You may however decide to use custom" + "Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() is the preferred way to standardize " + "tooltip activation details across your application. You may however decide to use custom " "flags for a specific tooltip instance."); // The following examples are passed for documentation purpose but may not be useful to most users. @@ -2271,8 +2271,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::Text("Set defaults in code:"); ImGui::SameLine(); HelpMarker( "SetColorEditOptions() is designed to allow you to set boot-time default.\n" - "We don't have Push/Pop functions because you can force options on a per-widget basis if needed," - "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid" + "We don't have Push/Pop functions because you can force options on a per-widget basis if needed, " + "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid " "encouraging you to persistently save values that aren't forward-compatible."); if (ImGui::Button("Default: Uint8 + HSV + Hue Bar")) ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar); @@ -2295,8 +2295,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::Spacing(); ImGui::Text("HSV encoded colors"); ImGui::SameLine(); HelpMarker( - "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV" - "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the" + "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV " + "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the " "added benefit that you can manipulate hue values with the picker even when saturation or value are zero."); ImGui::Text("Color widget with InputHSV:"); ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float); @@ -3558,7 +3558,7 @@ static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data) if (ImGui::TreeNode("Multi-Select (trees)")) { HelpMarker( - "This is rather advanced and experimental. If you are getting started with multi-select," + "This is rather advanced and experimental. If you are getting started with multi-select, " "please don't start by looking at how to use it for a tree!\n\n" "Future versions will try to simplify and formalize some of this."); @@ -9493,7 +9493,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) float th = (n == 0) ? 1.0f : thickness; draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle - draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), ImVec2(sz*0.5f, sz*0.3f), col, -0.3f, circle_segments, th); x += sz + spacing; // Ellipse + draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), ImVec2(sz*0.5f, sz*0.3f), col, -0.3f, circle_segments, th); x += sz + spacing; // Ellipse draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th); x += sz + spacing; // Square draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th); x += sz + spacing; // Square with all rounded corners draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners diff --git a/misc/freetype/README.md b/misc/freetype/README.md index 3955b080e2fc..6e2e8671e9e2 100644 --- a/misc/freetype/README.md +++ b/misc/freetype/README.md @@ -38,7 +38,7 @@ You can use the `ImGuiFreeTypeBuilderFlags_LoadColor` flag to load certain color ### Using OpenType SVG fonts (SVGinOT) - *SVG in Open Type* is a standard by Adobe and Mozilla for color OpenType and Open Font Format fonts. It allows font creators to embed complete SVG files within a font enabling full color and even animations. -- Popular fonts such as [twemoji](https://github.com/13rac1/twemoji-color-font) and fonts made with [scfbuild](https://github.com/13rac1/scfbuild) is SVGinOT +- Popular fonts such as [twemoji](https://github.com/13rac1/twemoji-color-font) and fonts made with [scfbuild](https://github.com/13rac1/scfbuild) is SVGinOT. - Two alternatives are possible to render SVG fonts: use "lunasvg" or "plutosvg". plutosvg will support some more fonts (e.g. NotoColorEmoji-Regular) and may load them faster. #### Using lunasvg diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 029991bbdec3..875060d7f394 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -269,11 +269,11 @@ namespace if (glyph_index == 0) return nullptr; - // If this crash for you: FreeType 2.11.0 has a crash bug on some bitmap/colored fonts. - // - https://gitlab.freedesktop.org/freetype/freetype/-/issues/1076 - // - https://github.com/ocornut/imgui/issues/4567 - // - https://github.com/ocornut/imgui/issues/4566 - // You can use FreeType 2.10, or the patched version of 2.11.0 in VcPkg, or probably any upcoming FreeType version. + // If this crash for you: FreeType 2.11.0 has a crash bug on some bitmap/colored fonts. + // - https://gitlab.freedesktop.org/freetype/freetype/-/issues/1076 + // - https://github.com/ocornut/imgui/issues/4567 + // - https://github.com/ocornut/imgui/issues/4566 + // You can use FreeType 2.10, or the patched version of 2.11.0 in VcPkg, or probably any upcoming FreeType version. FT_Error error = FT_Load_Glyph(Face, glyph_index, LoadFlags); if (error) return nullptr; From 914fbcf2e52d43db71d13f12f1a9971719f1c560 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 7 Feb 2025 16:23:00 +0100 Subject: [PATCH 440/548] Fonts: removed unnecessary const qualifier from ImFont::FindGlyph() Amend 0bde57c --- imgui.h | 16 +++++++++------- imgui_draw.cpp | 4 ++-- imgui_widgets.cpp | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/imgui.h b/imgui.h index acec7bf999ac..24f8fc2b0e2c 100644 --- a/imgui.h +++ b/imgui.h @@ -3412,6 +3412,7 @@ struct ImFontAtlas // Members //------------------------------------------- + // Input ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_) ImTextureID TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure. int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. @@ -3443,8 +3444,8 @@ struct ImFontAtlas int PackIdLines; // Custom texture rectangle ID for baked anti-aliased lines // [Obsolete] - //typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+ - //typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+ + //typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+ + //typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+ }; // Font runtime data and rendering @@ -3459,7 +3460,7 @@ struct ImFont // [Internal] Members: Hot ~28/40 bytes (for RenderText loop) ImVector IndexLookup; // 12-16 // out // Sparse. Index glyphs by Unicode code-point. ImVector Glyphs; // 12-16 // out // All glyphs. - const ImFontGlyph* FallbackGlyph; // 4-8 // out // = FindGlyph(FontFallbackChar) + ImFontGlyph* FallbackGlyph; // 4-8 // out // = FindGlyph(FontFallbackChar) // [Internal] Members: Cold ~32/40 bytes // Conceptually ConfigData[] is the list of font sources merged to create this font. @@ -3480,12 +3481,13 @@ struct ImFont // Methods IMGUI_API ImFont(); IMGUI_API ~ImFont(); - IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c); - IMGUI_API const ImFontGlyph*FindGlyphNoFallback(ImWchar c); + IMGUI_API ImFontGlyph* FindGlyph(ImWchar c); + IMGUI_API ImFontGlyph* FindGlyphNoFallback(ImWchar c); float GetCharAdvance(ImWchar c) { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } bool IsLoaded() const { return ContainerAtlas != NULL; } const char* GetDebugName() const { return ConfigData ? ConfigData->Name : ""; } + // [Internal] Don't use! // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL); // utf8 @@ -3552,7 +3554,7 @@ struct ImGuiPlatformIO IMGUI_API ImGuiPlatformIO(); //------------------------------------------------------------------ - // Interface with OS and Platform backend + // Input - Interface with OS and Platform backend (most common stuff) //------------------------------------------------------------------ // Optional: Access OS clipboard @@ -3577,7 +3579,7 @@ struct ImGuiPlatformIO ImWchar Platform_LocaleDecimalPoint; // '.' //------------------------------------------------------------------ - // Interface with Renderer Backend + // Input - Interface with Renderer Backend //------------------------------------------------------------------ // Written by some backends during ImGui_ImplXXXX_RenderDrawData() call to point backend_specific ImGui_ImplXXXX_RenderState* structure. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ed5164bb77a7..5bf0f0b1802a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3903,7 +3903,7 @@ void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst) } // Find glyph, return fallback if missing -const ImFontGlyph* ImFont::FindGlyph(ImWchar c) +ImFontGlyph* ImFont::FindGlyph(ImWchar c) { if (c >= (size_t)IndexLookup.Size) return FallbackGlyph; @@ -3913,7 +3913,7 @@ const ImFontGlyph* ImFont::FindGlyph(ImWchar c) return &Glyphs.Data[i]; } -const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) +ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) { if (c >= (size_t)IndexLookup.Size) return NULL; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 612ff62a639f..d246147bdebc 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4252,7 +4252,7 @@ void ImGui::PushPasswordFont() ImGuiContext& g = *GImGui; ImFont* in_font = g.Font; ImFont* out_font = &g.InputTextPasswordFont; - const ImFontGlyph* glyph = in_font->FindGlyph('*'); + ImFontGlyph* glyph = in_font->FindGlyph('*'); out_font->FontSize = in_font->FontSize; out_font->Scale = in_font->Scale; out_font->Ascent = in_font->Ascent; From 4982602f6feb0df9fe67e20a197aa074bfde3780 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 7 Feb 2025 18:16:04 +0100 Subject: [PATCH 441/548] Windows, Style: Added style.WindowBorderHoverPadding setting to configure inner/outer padding applied to hit-testing of windows borders. Amend 3c7177c6, 59f3c4fc2, ae7f833c6. Could be latched inside windows to be multi-dpi friendly, but likely won't matter soon. --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 21 ++++++++++----------- imgui.h | 1 + imgui_demo.cpp | 5 ++++- imgui_internal.h | 2 +- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7977ef681a77..b9888b134ffd 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,9 @@ Other changes: - Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), RadioButton(), Selectable(). Regression from 2025/01/13. (#8370) +- Windows, Style: Added style.WindowBorderHoverPadding setting to configure + inner/outer padding applied to hit-testing of windows borders and detection + of hovered window. - InputTextWithHint(): Fixed buffer-overflow (luckily often with no visible effect) when a user callback modified the buffer contents in a way that altered the visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut] diff --git a/imgui.cpp b/imgui.cpp index 4de75457ddc9..29fe4a220d8b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1167,11 +1167,7 @@ CODE // When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch. static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear - static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f; // Time to highlight an item activated by a shortcut. - -// Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by backend) -static const float WINDOWS_HOVER_PADDING = 4.0f; // Extend outside window for hovering/resizing (maxxed with TouchPadding) and inside windows for borders. Affect FindHoveredWindow(). static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time. static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.70f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved. @@ -1318,6 +1314,7 @@ ImGuiStyle::ImGuiStyle() WindowPadding = ImVec2(8,8); // Padding within a window WindowRounding = 0.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested. + WindowBorderHoverPadding = 4.0f; // Hit-testing extent outside/inside resizing border. Also extend determination of hovered window. Generally meaningfully larger than WindowBorderSize to make it easy to reach borders. WindowMinSize = ImVec2(32,32); // Minimum window size WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text WindowMenuButtonPosition = ImGuiDir_Left; // Position of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left. @@ -1379,6 +1376,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor) WindowPadding = ImTrunc(WindowPadding * scale_factor); WindowRounding = ImTrunc(WindowRounding * scale_factor); WindowMinSize = ImTrunc(WindowMinSize * scale_factor); + WindowBorderHoverPadding = ImTrunc(WindowBorderHoverPadding * scale_factor); ChildRounding = ImTrunc(ChildRounding * scale_factor); PopupRounding = ImTrunc(PopupRounding * scale_factor); FramePadding = ImTrunc(FramePadding * scale_factor); @@ -5037,7 +5035,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() // FIXME-DPI: This storage was added on 2021/03/31 for test engine, but if we want to multiply WINDOWS_HOVER_PADDING // by DpiScale, we need to make this window-agnostic anyhow, maybe need storing inside ImGuiWindow. - g.WindowsHoverPadding = ImMax(g.Style.TouchExtraPadding, ImVec2(WINDOWS_HOVER_PADDING, WINDOWS_HOVER_PADDING)); + g.WindowsBorderHoverPadding = ImMax(ImMax(g.Style.TouchExtraPadding.x, g.Style.TouchExtraPadding.y), g.Style.WindowBorderHoverPadding); // Find the window hovered by mouse: // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. @@ -5800,7 +5798,7 @@ void ImGui::FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_vi hovered_window = g.MovingWindow; ImVec2 padding_regular = g.Style.TouchExtraPadding; - ImVec2 padding_for_resize = g.IO.ConfigWindowsResizeFromEdges ? g.WindowsHoverPadding : padding_regular; + ImVec2 padding_for_resize = ImMax(g.Style.TouchExtraPadding, ImVec2(g.Style.WindowBorderHoverPadding, g.Style.WindowBorderHoverPadding)); for (int i = g.Windows.Size - 1; i >= 0; i--) { ImGuiWindow* window = g.Windows[i]; @@ -6502,7 +6500,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si int ret_auto_fit_mask = 0x00; const float grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); const float grip_hover_inner_size = (resize_grip_count > 0) ? IM_TRUNC(grip_draw_size * 0.75f) : 0.0f; - const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_HOVER_PADDING : 0.0f; + const float grip_hover_outer_size = g.WindowsBorderHoverPadding; ImRect clamp_rect = visibility_rect; const bool window_move_from_title_bar = g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar); @@ -6570,7 +6568,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si const ImGuiAxis axis = (border_n == ImGuiDir_Left || border_n == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y; bool hovered, held; - ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_HOVER_PADDING); + ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, g.WindowsBorderHoverPadding); ImGuiID border_id = window->GetID(border_n + 4); // == GetWindowResizeBorderID() ItemAdd(border_rect, border_id, NULL, ImGuiItemFlags_NoNav); ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus); @@ -6608,7 +6606,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si const ImVec2 border_curr = (window->Pos + ImMin(def.SegmentN1, def.SegmentN2) * window->Size); const float border_target_rel_mode_for_axis = border_curr[axis] + g.IO.MouseDelta[axis]; - const float border_target_abs_mode_for_axis = g.IO.MousePos[axis] - g.ActiveIdClickOffset[axis] + WINDOWS_HOVER_PADDING; // Match ButtonBehavior() padding above. + const float border_target_abs_mode_for_axis = g.IO.MousePos[axis] - g.ActiveIdClickOffset[axis] + g.WindowsBorderHoverPadding; // Match ButtonBehavior() padding above. // Use absolute mode position ImVec2 border_target = window->Pos; @@ -6697,7 +6695,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si // Recalculate next expected border expected coordinates if (*border_held != -1) - g.WindowResizeBorderExpectedRect = GetResizeBorderRect(window, *border_held, grip_hover_inner_size, WINDOWS_HOVER_PADDING); + g.WindowResizeBorderExpectedRect = GetResizeBorderRect(window, *border_held, grip_hover_inner_size, g.WindowsBorderHoverPadding); return ret_auto_fit_mask; } @@ -10184,7 +10182,8 @@ static void ImGui::ErrorCheckNewFrameSanityChecks() IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations - IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); + IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting!"); + IM_ASSERT(g.Style.WindowBorderHoverPadding > 0.0f && "Invalid style setting!"); // Required otherwise cannot resize from borders. IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); IM_ASSERT(g.Style.ColorButtonPosition == ImGuiDir_Left || g.Style.ColorButtonPosition == ImGuiDir_Right); diff --git a/imgui.h b/imgui.h index 24f8fc2b0e2c..d58473801aea 100644 --- a/imgui.h +++ b/imgui.h @@ -2146,6 +2146,7 @@ struct ImGuiStyle ImVec2 WindowPadding; // Padding within a window. float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). + float WindowBorderHoverPadding; // Hit-testing extent outside/inside resizing border. Also extend determination of hovered window. Generally meaningfully larger than WindowBorderSize to make it easy to reach borders. ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constrain individual windows, use SetNextWindowSizeConstraints(). ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. ImGuiDir WindowMenuButtonPosition; // Side of the collapsing/docking button in the title bar (None/Left/Right). Defaults to ImGuiDir_Left. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index dd6ebb93e8d2..3c40de2e7dd9 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7985,11 +7985,14 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderAngle("TableAngledHeadersAngle", &style.TableAngledHeadersAngle, -50.0f, +50.0f); ImGui::SliderFloat2("TableAngledHeadersTextAlign", (float*)&style.TableAngledHeadersTextAlign, 0.0f, 1.0f, "%.2f"); - ImGui::SeparatorText("Widgets"); + ImGui::SeparatorText("Windows"); ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f"); + ImGui::SliderFloat("WindowBorderHoverPadding", &style.WindowBorderHoverPadding, 1.0f, 20.0f, "%.0f"); int window_menu_button_position = style.WindowMenuButtonPosition + 1; if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0")) style.WindowMenuButtonPosition = (ImGuiDir)(window_menu_button_position - 1); + + ImGui::SeparatorText("Widgets"); ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0"); ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content."); diff --git a/imgui_internal.h b/imgui_internal.h index d59c19c601a3..0aa894d56fca 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2083,7 +2083,7 @@ struct ImGuiContext ImVector CurrentWindowStack; ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow* int WindowsActiveCount; // Number of unique windows submitted by frame - ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING). + float WindowsBorderHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, style.WindowBorderHoverPadding). This isn't so multi-dpi friendly. ImGuiID DebugBreakInWindow; // Set to break in Begin() call. ImGuiWindow* CurrentWindow; // Window being drawn into ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs. From e5668b8c738bd76d372a46e6a3d10812193be12f Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 7 Feb 2025 22:48:31 +0100 Subject: [PATCH 442/548] Internals: rename ImGuiNextWindowData::Flags to HasFlags for consistency and to reduce mistakes. --- imgui.cpp | 52 +++++++++++++++++++++++------------------------ imgui_internal.h | 9 +++++--- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 12 +++++------ 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 29fe4a220d8b..4ba2051d5532 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6068,7 +6068,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I // A SetNextWindowSize() call always has priority (#8020) // (since the code in Begin() never supported SizeVal==0.0f aka auto-resize via SetNextWindowSize() call, we don't support it here for now) // FIXME: We only support ImGuiCond_Always in this path. Supporting other paths would requires to obtain window pointer. - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) != 0 && (g.NextWindowData.SizeCond & ImGuiCond_Always) != 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) != 0 && (g.NextWindowData.SizeCond & ImGuiCond_Always) != 0) { if (g.NextWindowData.SizeVal.x > 0.0f) { @@ -6084,11 +6084,11 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I SetNextWindowSize(size); // Forward child flags (we allow prior settings to merge but it'll only work for adding flags) - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasChildFlags) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) g.NextWindowData.ChildFlags |= child_flags; else g.NextWindowData.ChildFlags = child_flags; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags; // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value. // FIXME: 2023/11/14: commented out shorted version. We had an issue with multiple ### in child window path names, which the trailing hash helped workaround. @@ -6302,7 +6302,7 @@ static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, const ImVec2& s { ImGuiContext& g = *GImGui; ImVec2 new_size = size_desired; - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSizeConstraint) { // See comments in SetNextWindowSizeConstraints() for details about setting size_min an size_max. ImRect cr = g.NextWindowData.SizeConstraintRect; @@ -6780,7 +6780,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar ImU32 bg_col = GetColorU32(GetWindowBgColorIdx(window)); bool override_alpha = false; float alpha = 1.0f; - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasBgAlpha) { alpha = g.NextWindowData.BgAlphaVal; override_alpha = true; @@ -6950,7 +6950,7 @@ void ImGui::UpdateWindowSkipRefresh(ImGuiWindow* window) { ImGuiContext& g = *GImGui; window->SkipRefresh = false; - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasRefreshPolicy) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasRefreshPolicy) == 0) return; if (g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_TryToAvoidRefresh) { @@ -7031,7 +7031,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { UpdateWindowInFocusOrderList(window, window_just_created, flags); window->Flags = (ImGuiWindowFlags)flags; - window->ChildFlags = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : 0; + window->ChildFlags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : 0; window->LastFrameActive = current_frame; window->LastTimeActive = (float)g.Time; window->BeginOrderWithinParent = 0; @@ -7095,7 +7095,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // (FIXME: Consider splitting the HasXXX flags into X/Y components bool window_pos_set_by_api = false; bool window_size_x_set_by_api = false, window_size_y_set_by_api = false; - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos) { window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0; if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f) @@ -7111,7 +7111,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond); } } - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) { window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f); window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f); @@ -7121,7 +7121,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) g.NextWindowData.SizeVal.y = window->SizeFull.y; SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond); } - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasScroll) { if (g.NextWindowData.ScrollVal.x >= 0.0f) { @@ -7134,13 +7134,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->ScrollTargetCenterRatio.y = 0.0f; } } - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasContentSize) window->ContentSizeExplicit = g.NextWindowData.ContentSizeVal; else if (first_begin_of_the_frame) window->ContentSizeExplicit = ImVec2(0.0f, 0.0f); - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasCollapsed) SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond); - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasFocus) FocusWindow(window); if (window->Appearing) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); @@ -8223,7 +8223,7 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pi { ImGuiContext& g = *GImGui; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasPos; g.NextWindowData.PosVal = pos; g.NextWindowData.PosPivotVal = pivot; g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always; @@ -8233,7 +8233,7 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) { ImGuiContext& g = *GImGui; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasSize; g.NextWindowData.SizeVal = size; g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always; } @@ -8245,7 +8245,7 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data) { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasSizeConstraint; g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max); g.NextWindowData.SizeCallback = custom_callback; g.NextWindowData.SizeCallbackUserData = custom_callback_user_data; @@ -8256,14 +8256,14 @@ void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& s void ImGui::SetNextWindowContentSize(const ImVec2& size) { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasContentSize; g.NextWindowData.ContentSizeVal = ImTrunc(size); } void ImGui::SetNextWindowScroll(const ImVec2& scroll) { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasScroll; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasScroll; g.NextWindowData.ScrollVal = scroll; } @@ -8271,7 +8271,7 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) { ImGuiContext& g = *GImGui; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasCollapsed; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasCollapsed; g.NextWindowData.CollapsedVal = collapsed; g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always; } @@ -8279,7 +8279,7 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) void ImGui::SetNextWindowBgAlpha(float alpha) { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasBgAlpha; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasBgAlpha; g.NextWindowData.BgAlphaVal = alpha; } @@ -8287,7 +8287,7 @@ void ImGui::SetNextWindowBgAlpha(float alpha) void ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags) { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasRefreshPolicy; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasRefreshPolicy; g.NextWindowData.RefreshFlagsVal = flags; } @@ -11301,7 +11301,7 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext // See FindBestWindowPosForPopup() for positionning logic of other tooltips (not drag and drop ones). //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding; const bool is_touchscreen = (g.IO.MouseSource == ImGuiMouseSource_TouchScreen); - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos) == 0) { ImVec2 tooltip_pos = is_touchscreen ? (g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_TOUCH * g.Style.MouseCursorScale) : (g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_MOUSE * g.Style.MouseCursorScale); ImVec2 tooltip_pivot = is_touchscreen ? TOOLTIP_DEFAULT_PIVOT_TOUCH : ImVec2(0.0f, 0.0f); @@ -11724,7 +11724,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla // Center modal windows by default for increased visibility // (this won't really last as settings will kick in, and is mostly for backward compatibility. user may do the same themselves) // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window. - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos) == 0) { const ImGuiViewport* viewport = GetMainViewport(); SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f)); @@ -12017,7 +12017,7 @@ void ImGui::SetWindowFocus(const char* name) void ImGui::SetNextWindowFocus() { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasFocus; } // Similar to IsWindowHovered() @@ -16548,7 +16548,7 @@ static void ShowDebugLogFlag(const char* name, ImGuiDebugLogFlags flags) void ImGui::ShowDebugLogWindow(bool* p_open) { ImGuiContext& g = *GImGui; - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) == 0) SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 12.0f), ImGuiCond_FirstUseEver); if (!Begin("Dear ImGui Debug Log", p_open) || GetCurrentWindow()->BeginCount > 1) { @@ -16868,7 +16868,7 @@ static int StackToolFormatLevelInfo(ImGuiIDStackTool* tool, int n, bool format_f void ImGui::ShowIDStackToolWindow(bool* p_open) { ImGuiContext& g = *GImGui; - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) == 0) SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver); if (!Begin("Dear ImGui ID Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1) { diff --git a/imgui_internal.h b/imgui_internal.h index 0aa894d56fca..ad9dc91e8b1b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1201,7 +1201,9 @@ enum ImGuiNextWindowDataFlags_ // Storage for SetNexWindow** functions struct ImGuiNextWindowData { - ImGuiNextWindowDataFlags Flags; + ImGuiNextWindowDataFlags HasFlags; + + // Members below are NOT cleared. Always rely on HasFlags. ImGuiCond PosCond; ImGuiCond SizeCond; ImGuiCond CollapsedCond; @@ -1220,7 +1222,7 @@ struct ImGuiNextWindowData ImGuiWindowRefreshFlags RefreshFlagsVal; ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } - inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } + inline void ClearFlags() { HasFlags = ImGuiNextWindowDataFlags_None; } }; enum ImGuiNextItemDataFlags_ @@ -1237,7 +1239,8 @@ struct ImGuiNextItemData { ImGuiNextItemDataFlags HasFlags; // Called HasFlags instead of Flags to avoid mistaking this ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData. - // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem() + + // Members below are NOT cleared by ItemAdd() meaning they are still valid during e.g. NavProcessItem(). Always rely on HasFlags. ImGuiID FocusScopeId; // Set by SetNextItemSelectionUserData() ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values) float Width; // Set by SetNextItemWidth() diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 71d1e7d8be3b..3bd9502d09dd 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -415,7 +415,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG // Reset scroll if we are reactivating it if ((previous_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0) - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasScroll) == 0) SetNextWindowScroll(ImVec2(0.0f, 0.0f)); // Create scrolling region (without border and zero window padding) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d246147bdebc..2b95c0dd58f3 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1829,7 +1829,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.Flags; + ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.HasFlags; g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values if (window->SkipItems) return false; @@ -1898,7 +1898,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF if (!popup_open) return false; - g.NextWindowData.Flags = backup_next_window_data_flags; + g.NextWindowData.HasFlags = backup_next_window_data_flags; return BeginComboPopup(popup_id, bb, flags); } @@ -1913,7 +1913,7 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags // Set popup size float w = bb.GetWidth(); - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSizeConstraint) { g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w); } @@ -1927,9 +1927,9 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4; else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20; ImVec2 constraint_min(0.0f, 0.0f), constraint_max(FLT_MAX, FLT_MAX); - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.x <= 0.0f) // Don't apply constraints if user specified a size + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.x <= 0.0f) // Don't apply constraints if user specified a size constraint_min.x = w; - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.y <= 0.0f) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.y <= 0.0f) constraint_max.y = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items); SetNextWindowSizeConstraints(constraint_min, constraint_max); } @@ -2061,7 +2061,7 @@ bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(vo preview_value = getter(user_data, *current_item); // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here. - if (popup_max_height_in_items != -1 && !(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)) + if (popup_max_height_in_items != -1 && !(g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSizeConstraint)) SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); if (!BeginCombo(label, preview_value, ImGuiComboFlags_None)) From e368015d79a9deffc45894fcd33586092f968395 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 7 Feb 2025 22:56:02 +0100 Subject: [PATCH 443/548] Tables: a clipped scrolling table correctly clears SetNextWindowXXX flags. (#8196) Amend 43c51eb12 --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b9888b134ffd..8fa53fc2589d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Other changes: visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut] - Scrollbar: Rework logic that fades-out scrollbar when it becomes too small, which amusingly made it disappear when using very big font/frame size. +- Tables: fixed calling SetNextWindowScroll() on clipped scrolling table + to not leak the value into a subsequent window. (#8196) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 3bd9502d09dd..2c1a0d3629c0 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -340,6 +340,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG { ItemSize(outer_rect); ItemAdd(outer_rect, id); + g.NextWindowData.ClearFlags(); return false; } From 50dbb086f23594c1b3b8db8ecaf255b6cbace832 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 7 Feb 2025 22:57:15 +0100 Subject: [PATCH 444/548] Tables: sneakily honor ImGuiNextWindowDataFlags_HasChildFlags/ImGuiNextWindowDataFlags_HasWindowFlags as a way to facilitate various hacks/workarounds. --- imgui_internal.h | 6 ++++-- imgui_tables.cpp | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index ad9dc91e8b1b..f2aaeaa83d72 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1194,8 +1194,9 @@ enum ImGuiNextWindowDataFlags_ ImGuiNextWindowDataFlags_HasFocus = 1 << 5, ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6, ImGuiNextWindowDataFlags_HasScroll = 1 << 7, - ImGuiNextWindowDataFlags_HasChildFlags = 1 << 8, - ImGuiNextWindowDataFlags_HasRefreshPolicy = 1 << 9, + ImGuiNextWindowDataFlags_HasWindowFlags = 1 << 8, + ImGuiNextWindowDataFlags_HasChildFlags = 1 << 9, + ImGuiNextWindowDataFlags_HasRefreshPolicy = 1 << 10, }; // Storage for SetNexWindow** functions @@ -1212,6 +1213,7 @@ struct ImGuiNextWindowData ImVec2 SizeVal; ImVec2 ContentSizeVal; ImVec2 ScrollVal; + ImGuiWindowFlags WindowFlags; // Only honored by BeginTable() ImGuiChildFlags ChildFlags; bool CollapsedVal; ImRect SizeConstraintRect; diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 2c1a0d3629c0..c2e0127768a4 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -420,8 +420,11 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG SetNextWindowScroll(ImVec2(0.0f, 0.0f)); // Create scrolling region (without border and zero window padding) - ImGuiWindowFlags child_window_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None; - BeginChildEx(name, instance_id, outer_rect.GetSize(), ImGuiChildFlags_None, child_window_flags); + ImGuiChildFlags child_child_flags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : ImGuiChildFlags_None; + ImGuiWindowFlags child_window_flags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasWindowFlags) ? g.NextWindowData.WindowFlags : ImGuiWindowFlags_None; + if (flags & ImGuiTableFlags_ScrollX) + child_window_flags |= ImGuiWindowFlags_HorizontalScrollbar; + BeginChildEx(name, instance_id, outer_rect.GetSize(), child_child_flags, child_window_flags); table->InnerWindow = g.CurrentWindow; table->WorkRect = table->InnerWindow->WorkRect; table->OuterRect = table->InnerWindow->Rect(); From e8ad60cc4f7ade30db505f739772befd3eb62b26 Mon Sep 17 00:00:00 2001 From: edenware <52419657+edenoftheware@users.noreply.github.com> Date: Fri, 7 Feb 2025 21:01:46 -0600 Subject: [PATCH 445/548] Fix typo (#8382) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index d58473801aea..6f9f11ebc5c3 100644 --- a/imgui.h +++ b/imgui.h @@ -3132,7 +3132,7 @@ struct ImDrawList // General polygon // - Only simple polygons are supported by filling functions (no self-intersections, no holes). - // - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience fo user but not used by main library. + // - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience for the user but not used by the main library. IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness); IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col); From 2206e31e5449217b7298d7d704ef5da1763a128f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 11:37:55 +0100 Subject: [PATCH 446/548] Demo: Combos: demonstrate a very simple way to add a filter to a combo. (#718) --- docs/CHANGELOG.txt | 2 ++ imgui_demo.cpp | 32 +++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8fa53fc2589d..c30f81817609 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,8 @@ Other changes: which amusingly made it disappear when using very big font/frame size. - Tables: fixed calling SetNextWindowScroll() on clipped scrolling table to not leak the value into a subsequent window. (#8196) +- Demo: Combos: demonstrate a very simple way to add a filter to a combo, + by showing the filter inside the combo contents. (#718) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3c40de2e7dd9..0898ef251610 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1435,7 +1435,6 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) // Pass in the preview value visible before opening the combo (it could technically be different contents or not pulled from items[]) const char* combo_preview_value = items[item_selected_idx]; - if (ImGui::BeginCombo("combo 1", combo_preview_value, flags)) { for (int n = 0; n < IM_ARRAYSIZE(items); n++) @@ -1451,23 +1450,46 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::EndCombo(); } + // Show case embedding a filter using a simple trick: displaying the filter inside combo contents. + // See https://github.com/ocornut/imgui/issues/718 for advanced/esoteric alternatives. + if (ImGui::BeginCombo("combo 2 (w/ filter)", combo_preview_value, flags)) + { + static ImGuiTextFilter filter; + if (ImGui::IsWindowAppearing()) + { + ImGui::SetKeyboardFocusHere(); + filter.Clear(); + } + ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F); + filter.Draw("##Filter", -FLT_MIN); + + for (int n = 0; n < IM_ARRAYSIZE(items); n++) + { + const bool is_selected = (item_selected_idx == n); + if (filter.PassFilter(items[n])) + if (ImGui::Selectable(items[n], is_selected)) + item_selected_idx = n; + } + ImGui::EndCombo(); + } + ImGui::Spacing(); ImGui::SeparatorText("One-liner variants"); - HelpMarker("Flags above don't apply to this section."); + HelpMarker("The Combo() function is not greatly useful apart from cases were you want to embed all options in a single strings.\nFlags above don't apply to this section."); // Simplified one-liner Combo() API, using values packed in a single constant string // This is a convenience for when the selection set is small and known at compile-time. static int item_current_2 = 0; - ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); + ImGui::Combo("combo 3 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); // Simplified one-liner Combo() using an array of const char* // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control. static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview - ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); + ImGui::Combo("combo 4 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); // Simplified one-liner Combo() using an accessor function static int item_current_4 = 0; - ImGui::Combo("combo 4 (function)", &item_current_4, [](void* data, int n) { return ((const char**)data)[n]; }, items, IM_ARRAYSIZE(items)); + ImGui::Combo("combo 5 (function)", &item_current_4, [](void* data, int n) { return ((const char**)data)[n]; }, items, IM_ARRAYSIZE(items)); ImGui::TreePop(); } From a18622c3695c8fb178acefad2da26f3ba2e50ffc Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 12:02:01 +0100 Subject: [PATCH 447/548] TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 6 +++++- imgui.h | 2 +- imgui_demo.cpp | 3 +++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c30f81817609..ab4345fb3601 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,8 @@ Other changes: which amusingly made it disappear when using very big font/frame size. - Tables: fixed calling SetNextWindowScroll() on clipped scrolling table to not leak the value into a subsequent window. (#8196) +- TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to + handle UTF-8 regardless of system regional settings. (#7660) [@achabense] - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] diff --git a/imgui.cpp b/imgui.cpp index 4ba2051d5532..2402bf109ae3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15090,7 +15090,11 @@ static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const cha #endif static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) { - return (INT_PTR)::ShellExecuteA(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT) > 32; + const int path_wsize = ::MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); + ImVector path_wbuf; + path_wbuf.resize(path_wsize); + ::MultiByteToWideChar(CP_UTF8, 0, path, -1, path_wbuf.Data, path_wsize); + return (INT_PTR)::ShellExecuteW(NULL, L"open", path_wbuf.Data, NULL, NULL, SW_SHOWDEFAULT) > 32; } #else #include diff --git a/imgui.h b/imgui.h index 6f9f11ebc5c3..29daaae7e179 100644 --- a/imgui.h +++ b/imgui.h @@ -3565,7 +3565,7 @@ struct ImGuiPlatformIO void* Platform_ClipboardUserData; // Optional: Open link/folder/file in OS Shell - // (default to use ShellExecuteA() on Windows, system() on Linux/Mac) + // (default to use ShellExecuteW() on Windows, system() on Linux/Mac) bool (*Platform_OpenInShellFn)(ImGuiContext* ctx, const char* path); void* Platform_OpenInShellUserData; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0898ef251610..2774fbc96c9c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7771,6 +7771,9 @@ void ImGui::ShowAboutWindow(bool* p_open) #ifdef IMGUI_DISABLE_WIN32_FUNCTIONS ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS"); #endif +#ifdef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS + ImGui::Text("define: IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS"); +#endif #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS"); #endif From a431e1277e8f4907ff874b466b71b98696cdc227 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 12:09:44 +0100 Subject: [PATCH 448/548] Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. (#7660) --- backends/imgui_impl_sdl2.cpp | 3 +++ backends/imgui_impl_sdl3.cpp | 2 ++ docs/CHANGELOG.txt | 2 ++ 3 files changed, 7 insertions(+) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index a27962a316bb..abe0e4342d6f 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode_Manual) accept an empty array. // 2024-10-24: Emscripten: from SDL 2.30.9, SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f. // 2024-09-09: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) @@ -480,6 +481,8 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void platform_io.Platform_SetImeDataFn = ImGui_ImplSDL2_PlatformSetImeData; #ifdef __EMSCRIPTEN__ platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplSDL2_EmscriptenOpenURL(url); return true; }; +#else + platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; }; #endif // Gamepad handling diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index d5de5443e244..16ab5706bdb5 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode_Manual) accept an empty array. // 2024-10-24: Emscripten: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f on Emscripten. // 2024-09-03: Update for SDL3 api changes: SDL_GetGamepads() memory ownership revert. (#7918, #7898, #7807) @@ -464,6 +465,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText; platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText; platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData; + platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; }; // Gamepad handling bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ab4345fb3601..74416e373bd0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,8 @@ Other changes: handle UTF-8 regardless of system regional settings. (#7660) [@achabense] - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) +- Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn + handler. (#7660) [@achabense] - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) From 88cda0cab6f369c2629f6a32b0eaae4436d77c1c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 12:39:54 +0100 Subject: [PATCH 449/548] Fixed minor warning. Added comment. --- backends/imgui_impl_opengl3.cpp | 1 + imgui.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index efc1a3c49283..9465388a66ef 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -303,6 +303,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) // GLES 2 bd->GlVersion = 200; bd->GlProfileIsES2 = true; + IM_UNUSED(gl_version_str); #else // Desktop or GLES 3 GLint major = 0; diff --git a/imgui.cpp b/imgui.cpp index 2402bf109ae3..b909e0c306ed 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2399,7 +2399,7 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* int e = 0; e = (*out_char < mins[len]) << 6; // non-canonical encoding e |= ((*out_char >> 11) == 0x1b) << 7; // surrogate half? - e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8; // out of range? + e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8; // out of range we can store in ImWchar (FIXME: May evolve) e |= (s[1] & 0xc0) >> 2; e |= (s[2] & 0xc0) >> 4; e |= (s[3] ) >> 6; From 4dc9df6aae8ff1f09701c13c053ed9fd55efaff4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 19:29:18 +0100 Subject: [PATCH 450/548] Tables: fixed an issue where Columns Visible/Hidden state wouldn't be correctly overridden when hot-reloading .ini state. (#7934) --- docs/CHANGELOG.txt | 3 +++ imgui_internal.h | 4 ++-- imgui_tables.cpp | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 74416e373bd0..b76f7455b95e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,8 @@ Other changes: which amusingly made it disappear when using very big font/frame size. - Tables: fixed calling SetNextWindowScroll() on clipped scrolling table to not leak the value into a subsequent window. (#8196) +- Tables: fixed an issue where Columns Visible/Hidden state wouldn't be correctly + overridden when hot-reloading .ini state. (#7934) - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] - Demo: Combos: demonstrate a very simple way to add a filter to a combo, @@ -67,6 +69,7 @@ Other changes: - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) + ----------------------------------------------------------------------- VERSION 1.91.8 (Released 2025-01-31) ----------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index f2aaeaa83d72..b904909d741b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2944,7 +2944,7 @@ struct ImGuiTableColumnSettings ImGuiTableColumnIdx DisplayOrder; ImGuiTableColumnIdx SortOrder; ImU8 SortDirection : 2; - ImU8 IsEnabled : 1; // "Visible" in ini file + ImS8 IsEnabled : 2; // "Visible" in ini file ImU8 IsStretch : 1; ImGuiTableColumnSettings() @@ -2954,7 +2954,7 @@ struct ImGuiTableColumnSettings Index = -1; DisplayOrder = SortOrder = -1; SortDirection = ImGuiSortDirection_None; - IsEnabled = 1; + IsEnabled = -1; IsStretch = 0; } }; diff --git a/imgui_tables.cpp b/imgui_tables.cpp index c2e0127768a4..3a023d426a16 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3741,7 +3741,7 @@ void ImGui::TableLoadSettings(ImGuiTable* table) else column->DisplayOrder = (ImGuiTableColumnIdx)column_n; display_order_mask |= (ImU64)1 << column->DisplayOrder; - column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled; + column->IsUserEnabled = column->IsUserEnabledNextFrame = (column_settings->IsEnabled != -1 ? column_settings->IsEnabled == 1 : (column->Flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1); column->SortOrder = column_settings->SortOrder; column->SortDirection = column_settings->SortDirection; } From 3b2f2602b4d6ecb0d7c09865dccbf8036afc002a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 21:33:49 +0100 Subject: [PATCH 451/548] Windows: Fixed an issue where BeginChild() inside a collapsed Begin() wouldn't inherit the SkipItems flag. Amend/fix a89f05a10 (old!) Discovered while looking at glyph being processed in WIP branch. --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 2 +- imgui.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b76f7455b95e..1253dc41d71a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,9 @@ Other changes: - Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), RadioButton(), Selectable(). Regression from 2025/01/13. (#8370) +- Windows: Fixed an issue where BeginChild() inside a collapsed Begin() + wouldn't inherit the SkipItems flag, resulting in missing coarse clipping + opportunity for code not checking the BeginChild() return value. - Windows, Style: Added style.WindowBorderHoverPadding setting to configure inner/outer padding applied to hit-testing of windows borders and detection of hovered window. diff --git a/imgui.cpp b/imgui.cpp index b909e0c306ed..1945dd6c47cf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7702,7 +7702,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Hide along with parent or if parent is collapsed if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0)) window->HiddenFramesCanSkipItems = 1; - if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCannotSkipItems > 0)) + if (parent_window && parent_window->HiddenFramesCannotSkipItems > 0) window->HiddenFramesCannotSkipItems = 1; } diff --git a/imgui.h b/imgui.h index 29daaae7e179..86137e5e12aa 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.9 WIP" -#define IMGUI_VERSION_NUM 19183 +#define IMGUI_VERSION_NUM 19184 #define IMGUI_HAS_TABLE /* From 6916f935eb221b351178349deb33282cbc24f7a9 Mon Sep 17 00:00:00 2001 From: fdsa <14tanks999@gmail.com> Date: Tue, 11 Feb 2025 13:12:55 -0800 Subject: [PATCH 452/548] InputText: Allow CTRL+Shift+Z to redo even outside of OSX. (#8389) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 3 ++- imgui_demo.cpp | 8 ++++---- imgui_widgets.cpp | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1253dc41d71a..cdb5e3845e1d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,7 @@ Other changes: - Windows, Style: Added style.WindowBorderHoverPadding setting to configure inner/outer padding applied to hit-testing of windows borders and detection of hovered window. +- InputText: Allow CTRL+Shift+Z to redo even outside of OSX. (#8389) [@tanksdude] - InputTextWithHint(): Fixed buffer-overflow (luckily often with no visible effect) when a user callback modified the buffer contents in a way that altered the visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut] diff --git a/imgui.cpp b/imgui.cpp index 1945dd6c47cf..af4aa2068507 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -142,7 +142,8 @@ CODE - CTRL+Shift+Left/Right: Select words. - CTRL+A or Double-Click: Select All. - CTRL+X, CTRL+C, CTRL+V: Use OS clipboard. - - CTRL+Z, CTRL+Y: Undo, Redo. + - CTRL+Z Undo. + - CTRL+Y or CTRL+Shift+Z: Redo. - ESCAPE: Revert text to its original value. - On OSX, controls are automatically adjusted to match standard OSX text editing 2ts and behaviors. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2774fbc96c9c..db9a6de1a71e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -861,8 +861,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) "Hold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or Double-Click to select all.\n" - "CTRL+X,CTRL+C,CTRL+V clipboard.\n" - "CTRL+Z,CTRL+Y undo/redo.\n" + "CTRL+X,CTRL+C,CTRL+V for clipboard.\n" + "CTRL+Z to undo, CTRL+Y/CTRL+SHIFT+Z to redo.\n" "ESCAPE to revert.\n\n" "PROGRAMMER:\n" "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() " @@ -8237,7 +8237,7 @@ void ImGui::ShowUserGuide() ImGui::BulletText("CTRL+Left/Right to word jump."); ImGui::BulletText("CTRL+A or double-click to select all."); ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste."); - ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo."); + ImGui::BulletText("CTRL+Z to undo, CTRL+Y/CTRL+SHIFT+Z to redo."); ImGui::BulletText("ESCAPE to revert."); ImGui::Unindent(); ImGui::BulletText("With keyboard navigation enabled:"); @@ -8273,7 +8273,7 @@ static void ShowExampleAppMainMenuBar() if (ImGui::BeginMenu("Edit")) { if (ImGui::MenuItem("Undo", "CTRL+Z")) {} - if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item + if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item ImGui::Separator(); if (ImGui::MenuItem("Cut", "CTRL+X")) {} if (ImGui::MenuItem("Copy", "CTRL+C")) {} diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2b95c0dd58f3..6676a96d5452 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4804,14 +4804,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl const bool is_startend_key_down = is_osx && io.KeyCtrl && !io.KeySuper && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End - // Using Shortcut() with ImGuiInputFlags_RouteFocused (default policy) to allow routing operations for other code (e.g. calling window trying to use CTRL+A and CTRL+B: formet would be handled by InputText) + // Using Shortcut() with ImGuiInputFlags_RouteFocused (default policy) to allow routing operations for other code (e.g. calling window trying to use CTRL+A and CTRL+B: former would be handled by InputText) // Otherwise we could simply assume that we own the keys as we are active. const ImGuiInputFlags f_repeat = ImGuiInputFlags_Repeat; const bool is_cut = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_X, f_repeat, id) || Shortcut(ImGuiMod_Shift | ImGuiKey_Delete, f_repeat, id)) && !is_readonly && !is_password && (!is_multiline || state->HasSelection()); const bool is_copy = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, 0, id) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_Insert, 0, id)) && !is_password && (!is_multiline || state->HasSelection()); const bool is_paste = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_V, f_repeat, id) || Shortcut(ImGuiMod_Shift | ImGuiKey_Insert, f_repeat, id)) && !is_readonly; const bool is_undo = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_Z, f_repeat, id)) && !is_readonly && is_undoable; - const bool is_redo = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_Y, f_repeat, id) || (is_osx && Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Z, f_repeat, id))) && !is_readonly && is_undoable; + const bool is_redo = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_Y, f_repeat, id) || Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Z, f_repeat, id)) && !is_readonly && is_undoable; const bool is_select_all = Shortcut(ImGuiMod_Ctrl | ImGuiKey_A, 0, id); // We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful. From 3d900edba7c47bf957a7c7bfcf9773ecf923fa53 Mon Sep 17 00:00:00 2001 From: PuPuHX <654524200@qq.com> Date: Tue, 11 Feb 2025 10:57:47 +0800 Subject: [PATCH 453/548] Examples: Win32+DirectX12: Fixed ExampleDescriptorHeapAllocator overflow free index. Amend 40b2286d1. --- examples/example_win32_directx12/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index 5b1a7af370bf..e83ce7dcbbc9 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -54,7 +54,7 @@ struct ExampleDescriptorHeapAllocator HeapHandleIncrement = device->GetDescriptorHandleIncrementSize(HeapType); FreeIndices.reserve((int)desc.NumDescriptors); for (int n = desc.NumDescriptors; n > 0; n--) - FreeIndices.push_back(n); + FreeIndices.push_back(n - 1); } void Destroy() { From ef7ffaff7425ceabb2145ff4cf1df3cdadd252c9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Feb 2025 15:46:17 +0100 Subject: [PATCH 454/548] Styles, Tabs: (Breaking) Renamed TabMinWidthForCloseButton to TabCloseButtonMinWidthUnselected. Added TabCloseButtonMinWidthSelected. (#8387) --- docs/CHANGELOG.txt | 8 ++++++++ imgui.cpp | 6 ++++-- imgui.h | 8 +++++++- imgui_demo.cpp | 12 ++++++++---- imgui_widgets.cpp | 10 +++++++--- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cdb5e3845e1d..7036ba64df0f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,6 +42,7 @@ HOW TO UPDATE? Breaking changes: - Renamed ImFontConfig::GlyphExtraSpacing.x option to GlyphExtraAdvanceX. (#242) +- Renamed style.TabMinWidthForCloseButton to style.TabCloseButtonMinWidthUnselected. Other changes: @@ -63,6 +64,13 @@ Other changes: to not leak the value into a subsequent window. (#8196) - Tables: fixed an issue where Columns Visible/Hidden state wouldn't be correctly overridden when hot-reloading .ini state. (#7934) +- Styles, Tabs: made the Close Button of selected tabs always visible by default, + without requiring to hover the tab. (#8387) + - Added style.TabCloseButtonMinWidthSelected/TabCloseButtonMinWidthUnselected settings + to configure visibility of the Close Button for selected and unselected tabs. + (-1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width) + - Default for selected tabs: TabCloseButtonMinWidthSelected = -1.0f (always visible) + - Default for unselected tabs: TabCloseButtonMinWidthUnselected = 0.0f (visible when hovered) - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] - Demo: Combos: demonstrate a very simple way to add a filter to a combo, diff --git a/imgui.cpp b/imgui.cpp index af4aa2068507..d6b763631eda 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1339,7 +1339,8 @@ ImGuiStyle::ImGuiStyle() LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. TabRounding = 5.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. TabBorderSize = 0.0f; // Thickness of border around tabs. - TabMinWidthForCloseButton = 0.0f; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. + TabCloseButtonMinWidthSelected = -1.0f; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. + TabCloseButtonMinWidthUnselected = 0.0f; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never show close button when unselected. TabBarBorderSize = 1.0f; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. TabBarOverlineSize = 1.0f; // Thickness of tab-bar overline, which highlights the selected tab-bar. TableAngledHeadersAngle = 35.0f * (IM_PI / 180.0f); // Angle of angled headers (supported values range from -50 degrees to +50 degrees). @@ -1394,7 +1395,8 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor) GrabRounding = ImTrunc(GrabRounding * scale_factor); LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor); TabRounding = ImTrunc(TabRounding * scale_factor); - TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImTrunc(TabMinWidthForCloseButton * scale_factor) : FLT_MAX; + TabCloseButtonMinWidthSelected = (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor) : FLT_MAX; + TabCloseButtonMinWidthUnselected = (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor) : FLT_MAX; TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor); SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor); DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor); diff --git a/imgui.h b/imgui.h index 86137e5e12aa..6174b8a89f6d 100644 --- a/imgui.h +++ b/imgui.h @@ -2170,7 +2170,8 @@ struct ImGuiStyle float LogSliderDeadzone; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. float TabBorderSize; // Thickness of border around tabs. - float TabMinWidthForCloseButton; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. + float TabCloseButtonMinWidthSelected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. + float TabCloseButtonMinWidthUnselected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never show close button when unselected. float TabBarBorderSize; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. float TabBarOverlineSize; // Thickness of tab-bar overline, which highlights the selected tab-bar. float TableAngledHeadersAngle; // Angle of angled headers (supported values range from -50.0f degrees to +50.0f degrees). @@ -2201,6 +2202,11 @@ struct ImGuiStyle IMGUI_API ImGuiStyle(); IMGUI_API void ScaleAllSizes(float scale_factor); + + // Obsolete names +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + // TabMinWidthForCloseButton = TabCloseButtonMinWidthUnselected // Renamed in 1.91.9. +#endif }; //----------------------------------------------------------------------------- diff --git a/imgui_demo.cpp b/imgui_demo.cpp index db9a6de1a71e..7671b7764ba3 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7991,10 +7991,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f"); - ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f"); - ImGui::SliderFloat("TabBarBorderSize", &style.TabBarBorderSize, 0.0f, 2.0f, "%.0f"); - ImGui::SliderFloat("TabBarOverlineSize", &style.TabBarOverlineSize, 0.0f, 3.0f, "%.0f"); - ImGui::SameLine(); HelpMarker("Overline is only drawn over the selected tab when ImGuiTabBarFlags_DrawSelectedOverline is set."); ImGui::SeparatorText("Rounding"); ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f"); @@ -8003,6 +7999,14 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f"); + + ImGui::SeparatorText("Tabs"); + ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f"); + ImGui::SliderFloat("TabBarBorderSize", &style.TabBarBorderSize, 0.0f, 2.0f, "%.0f"); + ImGui::SliderFloat("TabBarOverlineSize", &style.TabBarOverlineSize, 0.0f, 3.0f, "%.0f"); + ImGui::SameLine(); HelpMarker("Overline is only drawn over the selected tab when ImGuiTabBarFlags_DrawSelectedOverline is set."); + ImGui::DragFloat("TabCloseButtonMinWidthSelected", &style.TabCloseButtonMinWidthSelected, 0.1f, -1.0f, 100.0f, (style.TabCloseButtonMinWidthSelected < 0.0f) ? "%.0f (Always)" : "%.0f"); + ImGui::DragFloat("TabCloseButtonMinWidthUnselected", &style.TabCloseButtonMinWidthUnselected, 0.1f, -1.0f, 100.0f, (style.TabCloseButtonMinWidthUnselected < 0.0f) ? "%.0f (Always)" : "%.0f"); ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f"); ImGui::SeparatorText("Tables"); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6676a96d5452..1b56d5944b97 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -10369,9 +10369,13 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, bool close_button_pressed = false; bool close_button_visible = false; if (close_button_id != 0) - if (is_contents_visible || bb.GetWidth() >= ImMax(button_sz, g.Style.TabMinWidthForCloseButton)) - if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id) - close_button_visible = true; + { + bool is_hovered = g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id; // Any interaction account for this too. + if (is_contents_visible) + close_button_visible = (g.Style.TabCloseButtonMinWidthSelected < 0.0f) ? true : (is_hovered && bb.GetWidth() >= ImMax(button_sz, g.Style.TabCloseButtonMinWidthSelected)); + else + close_button_visible = (g.Style.TabCloseButtonMinWidthUnselected < 0.0f) ? true : (is_hovered && bb.GetWidth() >= ImMax(button_sz, g.Style.TabCloseButtonMinWidthUnselected)); + } bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x); if (close_button_visible) From 7221f5e739c78e8367ac368f120248b2fed93b19 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Feb 2025 19:01:02 +0100 Subject: [PATCH 455/548] Styles, Tabs: Fixed ef7ffaf. (#8387) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d6b763631eda..a69ae6c036e5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1395,8 +1395,8 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor) GrabRounding = ImTrunc(GrabRounding * scale_factor); LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor); TabRounding = ImTrunc(TabRounding * scale_factor); - TabCloseButtonMinWidthSelected = (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor) : FLT_MAX; - TabCloseButtonMinWidthUnselected = (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor) : FLT_MAX; + TabCloseButtonMinWidthSelected = (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor) : TabCloseButtonMinWidthSelected; + TabCloseButtonMinWidthUnselected = (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor) : TabCloseButtonMinWidthUnselected; TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor); SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor); DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor); From 7cd31c3557caadcf095fcf6da513b1a763ac77dc Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Feb 2025 19:08:52 +0100 Subject: [PATCH 456/548] Tables: tamed some .ini settings optimizations to more accurately allow overwriting/hot-reloading settings. (#7934) --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 23 +++++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7036ba64df0f..d897ace83126 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,8 @@ Other changes: to not leak the value into a subsequent window. (#8196) - Tables: fixed an issue where Columns Visible/Hidden state wouldn't be correctly overridden when hot-reloading .ini state. (#7934) +- Tables: tamed some .ini settings optimizations to more accurately allow + overwriting/hot-reloading settings in more situations. (#7934) - Styles, Tabs: made the Close Button of selected tabs always visible by default, without requiring to hover the tab. (#8387) - Added style.TabCloseButtonMinWidthSelected/TabCloseButtonMinWidthUnselected settings diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 3a023d426a16..b7726e90820f 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -577,6 +577,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG // Initialize table->SettingsOffset = -1; table->IsSortSpecsDirty = true; + table->IsSettingsDirty = true; // Records itself into .ini file even when in default state (#7934) table->InstanceInteracted = -1; table->ContextPopupColumn = -1; table->ReorderColumn = table->ResizedColumn = table->LastResizedColumn = -1; @@ -3718,6 +3719,19 @@ void ImGui::TableLoadSettings(ImGuiTable* table) table->SettingsLoadedFlags = settings->SaveFlags; table->RefScale = settings->RefScale; + // Initialize default columns settings + for (int column_n = 0; column_n < table->ColumnsCount; column_n++) + { + ImGuiTableColumn* column = &table->Columns[column_n]; + column->StretchWeight = -1.0f; + column->WidthRequest = -1.0f; + column->AutoFitQueue = 0x00; + column->DisplayOrder = (ImGuiTableColumnIdx)column_n; + column->IsUserEnabled = column->IsUserEnabledNextFrame = (column->Flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1; + column->SortOrder = (column->Flags & ImGuiTableColumnFlags_DefaultSort) ? 0 : -1; + column->SortDirection = (column->Flags & ImGuiTableColumnFlags_DefaultSort) ? (ImS8)ImGuiSortDirection_None : (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending); + } + // Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings(); ImU64 display_order_mask = 0; @@ -3734,14 +3748,12 @@ void ImGui::TableLoadSettings(ImGuiTable* table) column->StretchWeight = column_settings->WidthOrWeight; else column->WidthRequest = column_settings->WidthOrWeight; - column->AutoFitQueue = 0x00; } if (settings->SaveFlags & ImGuiTableFlags_Reorderable) column->DisplayOrder = column_settings->DisplayOrder; - else - column->DisplayOrder = (ImGuiTableColumnIdx)column_n; display_order_mask |= (ImU64)1 << column->DisplayOrder; - column->IsUserEnabled = column->IsUserEnabledNextFrame = (column_settings->IsEnabled != -1 ? column_settings->IsEnabled == 1 : (column->Flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1); + if ((settings->SaveFlags & ImGuiTableFlags_Hideable) && column_settings->IsEnabled != -1) + column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled == 1; column->SortOrder = column_settings->SortOrder; column->SortDirection = column_settings->SortDirection; } @@ -3837,8 +3849,7 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle const bool save_visible = (settings->SaveFlags & ImGuiTableFlags_Hideable) != 0; const bool save_order = (settings->SaveFlags & ImGuiTableFlags_Reorderable) != 0; const bool save_sort = (settings->SaveFlags & ImGuiTableFlags_Sortable) != 0; - if (!save_size && !save_visible && !save_order && !save_sort) - continue; + // We need to save the [Table] entry even if all the bools are false, since this records a table with "default settings". buf->reserve(buf->size() + 30 + settings->ColumnsCount * 50); // ballpark reserve buf->appendf("[%s][0x%08X,%d]\n", handler->TypeName, settings->ID, settings->ColumnsCount); From a931fb7f51269edda025180710fbd7a286e09688 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Feb 2025 19:15:00 +0100 Subject: [PATCH 457/548] Fixed static analyzer warning. (was harmless as initialized in NewFrame) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index a69ae6c036e5..251e46819b3a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3906,6 +3906,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas) InputEventsNextEventId = 1; WindowsActiveCount = 0; + WindowsBorderHoverPadding = 0.0f; CurrentWindow = NULL; HoveredWindow = NULL; HoveredWindowUnderMovingWindow = NULL; From b78cc37891608c582cd71b2bdc299f6ff8392432 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Feb 2025 19:27:43 +0100 Subject: [PATCH 458/548] Backends: SDL2: Fixed build for versions older than 2.0.14. (#7660) --- backends/imgui_impl_sdl2.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index abe0e4342d6f..24585a9d337d 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -116,6 +116,7 @@ #define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0 #endif #define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) +#define SDL_HAS_OPEN_URL SDL_VERSION_ATLEAST(2,0,14) #if SDL_HAS_VULKAN #include #endif @@ -481,7 +482,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void platform_io.Platform_SetImeDataFn = ImGui_ImplSDL2_PlatformSetImeData; #ifdef __EMSCRIPTEN__ platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplSDL2_EmscriptenOpenURL(url); return true; }; -#else +#elif SDL_HAS_OPEN_URL platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; }; #endif From f94a5f0e8c4b22476891cc18372ff5caaebe8492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Tassoux?= Date: Thu, 13 Feb 2025 14:30:49 +0100 Subject: [PATCH 459/548] Docs: Update doc about plutosvg (#8395) --- imconfig.h | 3 +-- misc/freetype/README.md | 16 ++++------------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/imconfig.h b/imconfig.h index 8f8bc3b9a9bb..a1e29e849bc8 100644 --- a/imconfig.h +++ b/imconfig.h @@ -88,8 +88,7 @@ //---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT) // Only works in combination with IMGUI_ENABLE_FREETYPE. -// - lunasvg is currently easier to acquire/install, as e.g. it is part of vcpkg. -// - plutosvg will support more fonts and may load them faster. It currently requires to be built manually but it is fairly easy. See misc/freetype/README for instructions. +// - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions. // - Both require headers to be available in the include path + program to be linked with the library code (not provided). // - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement) //#define IMGUI_ENABLE_FREETYPE_PLUTOSVG diff --git a/misc/freetype/README.md b/misc/freetype/README.md index 6e2e8671e9e2..e1bd0198bb11 100644 --- a/misc/freetype/README.md +++ b/misc/freetype/README.md @@ -48,15 +48,7 @@ Requires: [lunasvg](https://github.com/sammycage/lunasvg) v2.3.2 and above #### Using plutosvg (and plutovg) - Add `#define IMGUI_ENABLE_FREETYPE_PLUTOSVG` in your `imconfig.h`. -- Compile and link with plutosvg *and* plutovg (which is required by plutosvg) - -_Compilation hints for plutovg_ -- Compile all source files in `plutovg/source/*.c` -- Add include directory: `plutovg/include` + `plutovg/stb` - -_Compilation hints for plutosvg_ -- Compile `plutosvg/source/plutosvg.c` -- Add include directory: `plutosvg/source` -- Add define: `PLUTOSVG_HAS_FREETYPE` -- Link with: plutovg, freetype - +- Get latest plutosvg binaries or build yourself. Under Windows you may use vcpkg with: `vcpkg install plutosvg --triplet=x64-windows`. Alternatively, if you build imgui from vcpkg, you just need to enable the plutosvg feature: `vcpkg install imgui[plutosvg] --triplet=x64-windows` +- If you prefer to build plutosvg manually: + - Compilation hints for plutovg: Compile all source files in `plutovg/source/*.c` + Add include directory: `plutovg/include` + `plutovg/stb` + - Compilation hints for plutosvg: Compile `plutosvg/source/plutosvg.c` + Add include directory: `plutosvg/source` + Add define: `PLUTOSVG_HAS_FREETYPE` + Link with: plutovg, freetype From 890ead6a718c95c730012d7c2c3e5844a4a93bb9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 13 Feb 2025 15:40:49 +0100 Subject: [PATCH 460/548] Backends: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" without -KHR on API 1.3. (#8326, #8365) --- backends/imgui_impl_vulkan.cpp | 11 ++++++++--- backends/imgui_impl_vulkan.h | 13 +++++++------ docs/CHANGELOG.txt | 4 ++++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 2bd40f624aed..7be2ed1d1b30 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -26,6 +26,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-13: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326) // 2025-01-09: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in descriptor pool. (#6642) // 2025-01-06: Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples. // 2024-12-11: Vulkan: Fixed setting VkSwapchainCreateInfoKHR::preTransform for platforms not supporting VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR. (#8222) @@ -1082,9 +1083,11 @@ void ImGui_ImplVulkan_DestroyDeviceObjects() #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING static void ImGui_ImplVulkan_LoadDynamicRenderingFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data) { - // Manually load those two (see #5446) - ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast(loader_func("vkCmdBeginRenderingKHR", user_data)); - ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast(loader_func("vkCmdEndRenderingKHR", user_data)); + // Manually load those two (see #5446, #8326, #8365) + ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); + ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; + ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast(loader_func(v->ApiVersion < VK_API_VERSION_1_3 ? "vkCmdBeginRenderingKHR" : "vkCmdBeginRendering", user_data)); + ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast(loader_func(v->ApiVersion < VK_API_VERSION_1_3 ? "vkCmdEndRenderingKHR" : "vkCmdEndRendering", user_data)); } #endif @@ -1155,6 +1158,8 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) IM_ASSERT(info->RenderPass != VK_NULL_HANDLE); bd->VulkanInitInfo = *info; + if (bd->VulkanInitInfo.ApiVersion == 0) + bd->VulkanInitInfo.ApiVersion = VK_HEADER_VERSION_COMPLETE; ImGui_ImplVulkan_CreateDeviceObjects(); diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 6f4839c1301b..9b79d3250873 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -75,16 +75,17 @@ // - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure. struct ImGui_ImplVulkan_InitInfo { + uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3, which might be lower than header version (VK_HEADER_VERSION_COMPLETE) VkInstance Instance; VkPhysicalDevice PhysicalDevice; VkDevice Device; uint32_t QueueFamily; VkQueue Queue; - VkDescriptorPool DescriptorPool; // See requirements in note above; ignored if using DescriptorPoolSize > 0 - VkRenderPass RenderPass; // Ignored if using dynamic rendering - uint32_t MinImageCount; // >= 2 - uint32_t ImageCount; // >= MinImageCount - VkSampleCountFlagBits MSAASamples; // 0 defaults to VK_SAMPLE_COUNT_1_BIT + VkDescriptorPool DescriptorPool; // See requirements in note above; ignored if using DescriptorPoolSize > 0 + VkRenderPass RenderPass; // Ignored if using dynamic rendering + uint32_t MinImageCount; // >= 2 + uint32_t ImageCount; // >= MinImageCount + VkSampleCountFlagBits MSAASamples; // 0 defaults to VK_SAMPLE_COUNT_1_BIT // (Optional) VkPipelineCache PipelineCache; @@ -103,7 +104,7 @@ struct ImGui_ImplVulkan_InitInfo // (Optional) Allocation, Debugging const VkAllocationCallbacks* Allocator; void (*CheckVkResultFn)(VkResult err); - VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory. + VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory. }; // Follow "Getting Started" link and check examples/ folder to learn about using backends! diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d897ace83126..ec2180fac618 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -80,6 +80,10 @@ Other changes: - Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. (#7660) [@achabense] - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] +- Backends: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. + Default to header version if unspecified. (#8326, #8365) [@mklefrancois] +- Backends: Vulkan: Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" + (without -KHR suffix) on API 1.3. (#8326, #8365) [@mklefrancois] - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) From 12963f52314d126817da333675fe2f6bcde44ffe Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 13 Feb 2025 15:49:47 +0100 Subject: [PATCH 461/548] Examples: Vulkan: make ApiVersion a little more visible in examples. (#8326, #8365) --- backends/imgui_impl_vulkan.h | 2 +- examples/example_glfw_vulkan/main.cpp | 1 + examples/example_sdl2_vulkan/main.cpp | 1 + examples/example_sdl3_vulkan/main.cpp | 1 + examples/example_win32_vulkan/main.cpp | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 9b79d3250873..c8afc92ac5c6 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -75,7 +75,7 @@ // - When using dynamic rendering, set UseDynamicRendering=true and fill PipelineRenderingCreateInfo structure. struct ImGui_ImplVulkan_InitInfo { - uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3, which might be lower than header version (VK_HEADER_VERSION_COMPLETE) + uint32_t ApiVersion; // Fill with API version of Instance, e.g. VK_API_VERSION_1_3 or your value of VkApplicationInfo::apiVersion. May be lower than header version (VK_HEADER_VERSION_COMPLETE) VkInstance Instance; VkPhysicalDevice PhysicalDevice; VkDevice Device; diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 31da972dfcf0..ce7fcde5e127 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -396,6 +396,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplGlfw_InitForVulkan(window, true); ImGui_ImplVulkan_InitInfo init_info = {}; + //init_info.ApiVersion = VK_API_VERSION_1_3; // Pass in your value of VkApplicationInfo::apiVersion, otherwise will default to header version. init_info.Instance = g_Instance; init_info.PhysicalDevice = g_PhysicalDevice; init_info.Device = g_Device; diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index c0282f9328f7..0c29154bcabb 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -396,6 +396,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplSDL2_InitForVulkan(window); ImGui_ImplVulkan_InitInfo init_info = {}; + //init_info.ApiVersion = VK_API_VERSION_1_3; // Pass in your value of VkApplicationInfo::apiVersion, otherwise will default to header version. init_info.Instance = g_Instance; init_info.PhysicalDevice = g_PhysicalDevice; init_info.Device = g_Device; diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index 52544c34229a..99e441d7ef4b 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -400,6 +400,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplSDL3_InitForVulkan(window); ImGui_ImplVulkan_InitInfo init_info = {}; + //init_info.ApiVersion = VK_API_VERSION_1_3; // Pass in your value of VkApplicationInfo::apiVersion, otherwise will default to header version. init_info.Instance = g_Instance; init_info.PhysicalDevice = g_PhysicalDevice; init_info.Device = g_Device; diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp index f337d8e7de5a..427a2494a43b 100644 --- a/examples/example_win32_vulkan/main.cpp +++ b/examples/example_win32_vulkan/main.cpp @@ -387,6 +387,7 @@ int main(int, char**) // Setup Platform/Renderer backends ImGui_ImplWin32_Init(hwnd); ImGui_ImplVulkan_InitInfo init_info = {}; + //init_info.ApiVersion = VK_API_VERSION_1_3; // Pass in your value of VkApplicationInfo::apiVersion, otherwise will default to header version. init_info.Instance = g_Instance; init_info.PhysicalDevice = g_PhysicalDevice; init_info.Device = g_Device; From e1ae7db4cccf1cb6a516a43dd8f63899f504ca52 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 13 Feb 2025 16:03:40 +0100 Subject: [PATCH 462/548] Backends: Vulkan: Fixed building with older headers not supporting VK_HEADER_VERSION_COMPLETE. (#8326, #8365) --- backends/imgui_impl_vulkan.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 7be2ed1d1b30..af084cc0ef26 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1159,7 +1159,14 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) bd->VulkanInitInfo = *info; if (bd->VulkanInitInfo.ApiVersion == 0) + { + // We don't care about other versions for now, so don't need to make this exhaustive (with #ifdef VK_VERSION_1_X checks) +#ifdef VK_HEADER_VERSION_COMPLETE bd->VulkanInitInfo.ApiVersion = VK_HEADER_VERSION_COMPLETE; +#else + bd->VulkanInitInfo.ApiVersion = VK_API_VERSION_1_0; +#endif + } ImGui_ImplVulkan_CreateDeviceObjects(); From 98c2f6b0c450b2401a2db97a6c96c042b2bfd404 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 13 Feb 2025 16:19:41 +0100 Subject: [PATCH 463/548] Tables, Error Handling: Recovery from invalid index in TableSetColumnIndex(). (#1651) --- docs/CHANGELOG.txt | 1 + imgui_tables.cpp | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ec2180fac618..283d485dfd4d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -66,6 +66,7 @@ Other changes: overridden when hot-reloading .ini state. (#7934) - Tables: tamed some .ini settings optimizations to more accurately allow overwriting/hot-reloading settings in more situations. (#7934) +- Tables, Error Handling: Recovery from invalid index in TableSetColumnIndex(). (#1651) - Styles, Tabs: made the Close Button of selected tabs always visible by default, without requiring to hover the tab. (#8387) - Added style.TabCloseButtonMinWidthSelected/TabCloseButtonMinWidthUnselected settings diff --git a/imgui_tables.cpp b/imgui_tables.cpp index b7726e90820f..6486dccd60b4 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -2106,7 +2106,11 @@ bool ImGui::TableSetColumnIndex(int column_n) { if (table->CurrentColumn != -1) TableEndCell(table); - IM_ASSERT(column_n >= 0 && table->ColumnsCount); + if ((column_n >= 0 && column_n < table->ColumnsCount) == false) + { + IM_ASSERT_USER_ERROR(column_n >= 0 && column_n < table->ColumnsCount, "TableSetColumnIndex() invalid column index!"); + return false; + } TableBeginCell(table, column_n); } From ec4cd2cb8cf144ea16935806d11d5639a84f73dd Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 14 Feb 2025 12:19:24 +0100 Subject: [PATCH 464/548] Backends: Vulkan: Fixed crash with using no prototypes + *BREAKING* Added ApiVersion to ImGui_ImplVulkan_LoadFunctions(). (#8326, #8365, #8400) --- backends/imgui_impl_vulkan.cpp | 43 ++++++++++++++++++++-------------- backends/imgui_impl_vulkan.h | 2 +- docs/CHANGELOG.txt | 4 ++++ 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index af084cc0ef26..7379e000b741 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -26,6 +26,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions(). // 2025-02-13: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326) // 2025-01-09: Vulkan: Added IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE to clarify how many image sampler descriptors are expected to be available in descriptor pool. (#6642) // 2025-01-06: Vulkan: Added more ImGui_ImplVulkanH_XXXX helper functions to simplify our examples. @@ -1081,22 +1082,34 @@ void ImGui_ImplVulkan_DestroyDeviceObjects() } #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING -static void ImGui_ImplVulkan_LoadDynamicRenderingFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data) +static void ImGui_ImplVulkan_LoadDynamicRenderingFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data) { // Manually load those two (see #5446, #8326, #8365) - ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); - ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; - ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast(loader_func(v->ApiVersion < VK_API_VERSION_1_3 ? "vkCmdBeginRenderingKHR" : "vkCmdBeginRendering", user_data)); - ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast(loader_func(v->ApiVersion < VK_API_VERSION_1_3 ? "vkCmdEndRenderingKHR" : "vkCmdEndRendering", user_data)); + ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast(loader_func(api_version < VK_API_VERSION_1_3 ? "vkCmdBeginRenderingKHR" : "vkCmdBeginRendering", user_data)); + ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast(loader_func(api_version < VK_API_VERSION_1_3 ? "vkCmdEndRenderingKHR" : "vkCmdEndRendering", user_data)); } #endif -bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data) +// If unspecified by user, assume that ApiVersion == HeaderVersion + // We don't care about other versions than 1.3 for our checks, so don't need to make this exhaustive (e.g. with all #ifdef VK_VERSION_1_X checks) +static uint32_t ImGui_ImplVulkan_GetDefaultApiVersion() +{ +#ifdef VK_HEADER_VERSION_COMPLETE + return VK_HEADER_VERSION_COMPLETE; +#else + return VK_API_VERSION_1_0; +#endif +} + +bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data) { // Load function pointers // You can use the default Vulkan loader using: - // ImGui_ImplVulkan_LoadFunctions([](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); }); + // ImGui_ImplVulkan_LoadFunctions(VK_API_VERSION_1_3, [](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); }); // But this would be roughly equivalent to not setting VK_NO_PROTOTYPES. + if (api_version == 0) + api_version = ImGui_ImplVulkan_GetDefaultApiVersion(); + #ifdef IMGUI_IMPL_VULKAN_USE_LOADER #define IMGUI_VULKAN_FUNC_LOAD(func) \ func = reinterpret_cast(loader_func(#func, user_data)); \ @@ -1106,7 +1119,7 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch #undef IMGUI_VULKAN_FUNC_LOAD #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - ImGui_ImplVulkan_LoadDynamicRenderingFunctions(loader_func, user_data); + ImGui_ImplVulkan_LoadDynamicRenderingFunctions(api_version, loader_func, user_data); #endif #else IM_UNUSED(loader_func); @@ -1121,11 +1134,14 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) { IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!"); + if (info->ApiVersion == 0) + info->ApiVersion = ImGui_ImplVulkan_GetDefaultApiVersion(); + if (info->UseDynamicRendering) { #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING #ifndef IMGUI_IMPL_VULKAN_USE_LOADER - ImGui_ImplVulkan_LoadDynamicRenderingFunctions([](const char* function_name, void* user_data) { return vkGetInstanceProcAddr((VkInstance)user_data, function_name); }, (void*)info->Instance); + ImGui_ImplVulkan_LoadDynamicRenderingFunctions(info->ApiVersion, [](const char* function_name, void* user_data) { return vkGetInstanceProcAddr((VkInstance)user_data, function_name); }, (void*)info->Instance); #endif IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR != nullptr); IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR != nullptr); @@ -1158,15 +1174,6 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) IM_ASSERT(info->RenderPass != VK_NULL_HANDLE); bd->VulkanInitInfo = *info; - if (bd->VulkanInitInfo.ApiVersion == 0) - { - // We don't care about other versions for now, so don't need to make this exhaustive (with #ifdef VK_VERSION_1_X checks) -#ifdef VK_HEADER_VERSION_COMPLETE - bd->VulkanInitInfo.ApiVersion = VK_HEADER_VERSION_COMPLETE; -#else - bd->VulkanInitInfo.ApiVersion = VK_API_VERSION_1_0; -#endif - } ImGui_ImplVulkan_CreateDeviceObjects(); diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index c8afc92ac5c6..c3f40e138ae9 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -124,7 +124,7 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet d // Optional: load Vulkan functions with a custom function loader // This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES -IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr); +IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr); // [BETA] Selected render state data shared with callbacks. // This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplVulkan_RenderDrawData() call. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 283d485dfd4d..9ca3a0c81d35 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,10 @@ Breaking changes: - Renamed ImFontConfig::GlyphExtraSpacing.x option to GlyphExtraAdvanceX. (#242) - Renamed style.TabMinWidthForCloseButton to style.TabCloseButtonMinWidthUnselected. +- Backends: Vulkan: Added 'uint32_t api_version' argument to ImGui_ImplVulkan_LoadFunctions(). + Note that it was also added to ImGui_ImplVulkan_InitInfo but for the later it is optional. + (#8326, #8365, #8400) + Other changes: From 474305c476a777c94db750c961af5a94c6df4237 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 14 Feb 2025 16:15:09 +0100 Subject: [PATCH 465/548] ImFont: simpler constructor. --- imgui_draw.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 5bf0f0b1802a..ca66b6d7947d 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3685,21 +3685,8 @@ void ImFontGlyphRangesBuilder::BuildRanges(ImVector* out_ranges) ImFont::ImFont() { - FontSize = 0.0f; - FallbackAdvanceX = 0.0f; - FallbackChar = 0; - EllipsisChar = 0; - EllipsisWidth = EllipsisCharStep = 0.0f; - EllipsisCharCount = 0; - FallbackGlyph = NULL; - ContainerAtlas = NULL; - ConfigData = NULL; - ConfigDataCount = 0; - DirtyLookupTables = false; + memset(this, 0, sizeof(*this)); Scale = 1.0f; - Ascent = Descent = 0.0f; - MetricsTotalSurface = 0; - memset(Used8kPagesMap, 0, sizeof(Used8kPagesMap)); } ImFont::~ImFont() From 2860d7ba05667be5e2e51cf27d658352884800b8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 14 Feb 2025 19:44:35 +0100 Subject: [PATCH 466/548] Selectable: Fixed horizontal label alignment with SelectableTextAlign.x > 0 and specifying a selectable size. (#8338) Regression from ed7551c1d --- docs/CHANGELOG.txt | 3 ++- imgui_widgets.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9ca3a0c81d35..938b83aaf28f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,7 +47,6 @@ Breaking changes: Note that it was also added to ImGui_ImplVulkan_InitInfo but for the later it is optional. (#8326, #8365, #8400) - Other changes: - Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), @@ -71,6 +70,8 @@ Other changes: - Tables: tamed some .ini settings optimizations to more accurately allow overwriting/hot-reloading settings in more situations. (#7934) - Tables, Error Handling: Recovery from invalid index in TableSetColumnIndex(). (#1651) +- Selectable: Fixed horizontal label alignment with SelectableTextAlign.x > 0 and + specifying a selectable size. (#8338) - Styles, Tabs: made the Close Button of selected tabs always visible by default, without requiring to hover the tab. (#8387) - Added style.TabCloseButtonMinWidthSelected/TabCloseButtonMinWidthUnselected settings diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 1b56d5944b97..eb2b26bd086f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7101,7 +7101,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // Text stays at the submission position. Alignment/clipping extents ignore SpanAllColumns. if (is_visible) - RenderTextClipped(pos, ImVec2(window->WorkRect.Max.x, pos.y + size.y), label, NULL, &label_size, style.SelectableTextAlign, &bb); + RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label, NULL, &label_size, style.SelectableTextAlign, &bb); // Automatically close popups if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.ItemFlags & ImGuiItemFlags_AutoClosePopups)) From 78ec1272e962ec9ca5515222cde87ee9f0b1c105 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 14 Feb 2025 21:39:45 +0100 Subject: [PATCH 467/548] ImDrawList: added InitialFringeScale in ImDrawListSharedData. Default to 1.0f. This is to allow some DPI mods with less changes. Only the initial value in SetupDrawListSharedData() will need change. --- imgui.cpp | 1 + imgui_draw.cpp | 3 ++- imgui_internal.h | 3 ++- imgui_widgets.cpp | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 251e46819b3a..c27095fd452f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5136,6 +5136,7 @@ static void SetupDrawListSharedData() g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill; if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; + g.DrawListSharedData.InitialFringeScale = 1.0f; // FIXME-DPI: Change this for some DPI scaling experiments. } void ImGui::NewFrame() diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ca66b6d7947d..3953212a1e9f 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -374,6 +374,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) ImDrawListSharedData::ImDrawListSharedData() { memset(this, 0, sizeof(*this)); + InitialFringeScale = 1.0f; for (int i = 0; i < IM_ARRAYSIZE(ArcFastVtx); i++) { const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(ArcFastVtx); @@ -433,7 +434,7 @@ void ImDrawList::_ResetForNewFrame() _Path.resize(0); _Splitter.Clear(); CmdBuffer.push_back(ImDrawCmd()); - _FringeScale = 1.0f; + _FringeScale = _Data->InitialFringeScale; } void ImDrawList::_ClearFreeMemory() diff --git a/imgui_internal.h b/imgui_internal.h index b904909d741b..e272d5479124 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -786,8 +786,9 @@ struct IMGUI_API ImDrawListSharedData float FontScale; // Current/default font scale (== FontSize / Font->FontSize) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc - ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() + float InitialFringeScale; // Initial scale to apply to AA fringe ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards) + ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() ImVector TempBuffer; // Temporary write buffer // Lookup tables diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index eb2b26bd086f..2d45c5d51843 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -913,7 +913,7 @@ ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis) const ImRect outer_rect = window->Rect(); const ImRect inner_rect = window->InnerRect; const float scrollbar_size = window->ScrollbarSizes[axis ^ 1]; // (ScrollbarSizes.x = width of Y scrollbar; ScrollbarSizes.y = height of X scrollbar) - IM_ASSERT(scrollbar_size > 0.0f); + IM_ASSERT(scrollbar_size >= 0.0f); const float border_size = IM_ROUND(window->WindowBorderSize * 0.5f); const float border_top = (window->Flags & ImGuiWindowFlags_MenuBar) ? IM_ROUND(g.Style.FrameBorderSize * 0.5f) : 0.0f; if (axis == ImGuiAxis_X) From c4a32a129d55eb66158408b61f51d40907a5aace Mon Sep 17 00:00:00 2001 From: Nico van Bentum Date: Thu, 13 Feb 2025 21:50:12 +0100 Subject: [PATCH 468/548] Tabs: fixed middle-button to close not checking hovering, only close button visibility. (#8399, #8387) Main bug has been here since 54a60aaa4, but it's only ef7ffaff7 which made it very visible. --- docs/CHANGELOG.txt | 4 +++- imgui_widgets.cpp | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 938b83aaf28f..19b334ba64a8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -72,13 +72,15 @@ Other changes: - Tables, Error Handling: Recovery from invalid index in TableSetColumnIndex(). (#1651) - Selectable: Fixed horizontal label alignment with SelectableTextAlign.x > 0 and specifying a selectable size. (#8338) -- Styles, Tabs: made the Close Button of selected tabs always visible by default, +- Tabs, Style: made the Close Button of selected tabs always visible by default, without requiring to hover the tab. (#8387) - Added style.TabCloseButtonMinWidthSelected/TabCloseButtonMinWidthUnselected settings to configure visibility of the Close Button for selected and unselected tabs. (-1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width) - Default for selected tabs: TabCloseButtonMinWidthSelected = -1.0f (always visible) - Default for unselected tabs: TabCloseButtonMinWidthUnselected = 0.0f (visible when hovered) +- Tabs: fixed middle-mouse-button to close tab not checking that close button + is hovered, merely it's visibility. (#8399, #8387) [@nicovanbentum] - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] - Demo: Combos: demonstrate a very simple way to add a filter to a combo, diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2d45c5d51843..6e08cec22e5a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -10368,9 +10368,10 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, // 'g.ActiveId==close_button_id' will be true when we are holding on the close button, in which case both hovered booleans are false bool close_button_pressed = false; bool close_button_visible = false; + bool is_hovered = g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id; // Any interaction account for this too. + if (close_button_id != 0) { - bool is_hovered = g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id; // Any interaction account for this too. if (is_contents_visible) close_button_visible = (g.Style.TabCloseButtonMinWidthSelected < 0.0f) ? true : (is_hovered && bb.GetWidth() >= ImMax(button_sz, g.Style.TabCloseButtonMinWidthSelected)); else @@ -10386,7 +10387,7 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, g.LastItemData = last_item_backup; // Close with middle mouse button - if (!(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2)) + if (is_hovered && !(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2)) close_button_pressed = true; } else if (unsaved_marker_visible) From 8f0411ff037790ec65bfb3118473dde532c47785 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 18 Feb 2025 18:19:10 +0100 Subject: [PATCH 469/548] Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) --- backends/imgui_impl_opengl3.cpp | 30 +++++++++++++++++++++++------- docs/CHANGELOG.txt | 2 ++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 9465388a66ef..14ae90a7e122 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -22,6 +22,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-18: OpenGL: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) // 2024-10-07: OpenGL: Changed default texture sampler to Clamp instead of Repeat/Wrap. // 2024-06-28: OpenGL: ImGui_ImplOpenGL3_NewFrame() recreates font texture if it has been destroyed by ImGui_ImplOpenGL3_DestroyFontsTexture(). (#7748) // 2024-05-07: OpenGL: Update loader for Linux to support EGL/GLVND. (#7562) @@ -169,6 +170,7 @@ // - You can temporarily use an unstripped version. See https://github.com/dearimgui/gl3w_stripped/releases // Changes to this backend using new APIs should be accompanied by a regenerated stripped loader version. #define IMGL3W_IMPL +#define IMGUI_IMPL_OPENGL_LOADER_IMGL3W #include "imgui_impl_opengl3_loader.h" #endif @@ -276,6 +278,21 @@ struct ImGui_ImplOpenGL3_VtxAttribState }; #endif +// Not static to allow third-party code to use that if they want to (but undocumented) +bool ImGui_ImplOpenGL3_InitLoader(); +bool ImGui_ImplOpenGL3_InitLoader() +{ + // Initialize our loader +#ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W + if (glGetIntegerv == NULL && imgl3wInit() != 0) + { + fprintf(stderr, "Failed to initialize OpenGL loader!\n"); + return false; + } +#endif + return true; +} + // Functions bool ImGui_ImplOpenGL3_Init(const char* glsl_version) { @@ -283,14 +300,9 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) IMGUI_CHECKVERSION(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); - // Initialize our loader -#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) - if (imgl3wInit() != 0) - { - fprintf(stderr, "Failed to initialize OpenGL loader!\n"); + // Initialize loader + if (!ImGui_ImplOpenGL3_InitLoader()) return false; - } -#endif // Setup backend capabilities flags ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)(); @@ -406,6 +418,8 @@ void ImGui_ImplOpenGL3_NewFrame() ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplOpenGL3_Init()?"); + ImGui_ImplOpenGL3_InitLoader(); // Lazily init loader if not already done for e.g. DLL boundaries. + if (!bd->ShaderHandle) ImGui_ImplOpenGL3_CreateDeviceObjects(); if (!bd->FontTexture) @@ -497,6 +511,8 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) if (fb_width <= 0 || fb_height <= 0) return; + ImGui_ImplOpenGL3_InitLoader(); // Lazily init loader if not already done for e.g. DLL boundaries. + ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); // Backup GL state diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 19b334ba64a8..a50bab51eff7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -87,6 +87,8 @@ Other changes: by showing the filter inside the combo contents. (#718) - Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. (#7660) [@achabense] +- Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend + from e.g. other DLL boundaries. (#8406) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] - Backends: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. (#8326, #8365) [@mklefrancois] From 8a35386ba750fa4c6a77dcbf57211d481528fe43 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 18 Feb 2025 18:40:47 +0100 Subject: [PATCH 470/548] Added ImGuiMouseCursor_Wait mouse cursor (busy/wait/hourglass shape) + support in SDL2,SDL3,Win32,Allegro5 backends. --- backends/imgui_impl_allegro5.cpp | 2 ++ backends/imgui_impl_glfw.cpp | 1 + backends/imgui_impl_glfw.h | 1 + backends/imgui_impl_osx.h | 2 ++ backends/imgui_impl_osx.mm | 6 ++++-- backends/imgui_impl_sdl2.cpp | 2 ++ backends/imgui_impl_sdl3.cpp | 2 ++ backends/imgui_impl_win32.cpp | 2 ++ docs/CHANGELOG.txt | 2 ++ imgui.h | 1 + imgui_demo.cpp | 2 +- 11 files changed, 20 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 3718b64eace4..7307affde40a 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-18: Added ImGuiMouseCursor_Wait mouse cursor support. // 2025-01-06: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). // 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: // - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn @@ -594,6 +595,7 @@ static void ImGui_ImplAllegro5_UpdateMouseCursor() case ImGuiMouseCursor_ResizeEW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_E; break; case ImGuiMouseCursor_ResizeNESW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NE; break; case ImGuiMouseCursor_ResizeNWSE: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NW; break; + case ImGuiMouseCursor_Wait: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_BUSY; break; case ImGuiMouseCursor_NotAllowed: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_UNAVAILABLE; break; } al_set_system_mouse_cursor(bd->Display, cursor_id); diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 454a36d368ce..8bb61d14e2d3 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -11,6 +11,7 @@ // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // Missing features or Issues: // [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. +// [ ] Missing ImGuiMouseCursor_Wait cursor. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index bba6d09ea8c1..260a06b146f4 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -10,6 +10,7 @@ // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // Missing features or Issues: // [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. +// [ ] Missing ImGuiMouseCursor_Wait cursor. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index 2e7eabb2b415..e4cda54ae25d 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -10,6 +10,8 @@ // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: IME support. +// Missing features or Issues: +// [ ] Missing ImGuiMouseCursor_Wait cursor. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 92c26418f8f6..53bdace566c7 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -10,6 +10,8 @@ // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: IME support. +// Missing features or Issues: +// [ ] Missing ImGuiMouseCursor_Wait cursor. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -422,12 +424,12 @@ bool ImGui_ImplOSX_Init(NSView* view) bd->MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor]; bd->MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor]; bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor]; - bd->MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor]; - bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedCursor]; bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@selector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor] : [NSCursor resizeUpDownCursor]; bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@selector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor]; bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor]; bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor]; + bd->MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor]; + bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedCursor]; // Note that imgui.cpp also include default OSX clipboard handlers which can be enabled // by adding '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h and adding '-framework ApplicationServices' to your linker command-line. diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 24585a9d337d..d8fd43ae48ff 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-18: Added ImGuiMouseCursor_Wait mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode_Manual) accept an empty array. // 2024-10-24: Emscripten: from SDL 2.30.9, SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f. @@ -499,6 +500,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); + bd->MouseCursors[ImGuiMouseCursor_Wait] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT); bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); // Set platform dependent data in viewport diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 16ab5706bdb5..246a91213e07 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-18: Added ImGuiMouseCursor_Wait mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode_Manual) accept an empty array. // 2024-10-24: Emscripten: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f on Emscripten. @@ -480,6 +481,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NESW_RESIZE); bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NWSE_RESIZE); bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_POINTER); + bd->MouseCursors[ImGuiMouseCursor_Wait] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT); bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NOT_ALLOWED); // Set platform dependent data in viewport diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 03ab53523d37..cd1cc7ad554e 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-18: Added ImGuiMouseCursor_Wait mouse cursor support. // 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768) // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. // 2023-09-25: Inputs: Synthesize key-down event on key-up for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit it (same behavior as GLFW/SDL). @@ -256,6 +257,7 @@ static bool ImGui_ImplWin32_UpdateMouseCursor(ImGuiIO& io, ImGuiMouseCursor imgu case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; + case ImGuiMouseCursor_Wait: win32_cursor = IDC_WAIT; break; case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break; } ::SetCursor(::LoadCursor(nullptr, win32_cursor)); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a50bab51eff7..a72107d127ec 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -83,10 +83,12 @@ Other changes: is hovered, merely it's visibility. (#8399, #8387) [@nicovanbentum] - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] +- Misc: Added ImGuiMouseCursor_Wait mouse cursor (busy/wait/hourglass shape). - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) - Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. (#7660) [@achabense] +- Backends: SDL2, SDL3, Win32, Allegro5: Added support for ImGuiMouseCursor_Wait. - Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] diff --git a/imgui.h b/imgui.h index 6174b8a89f6d..5a9b1250c991 100644 --- a/imgui.h +++ b/imgui.h @@ -1833,6 +1833,7 @@ enum ImGuiMouseCursor_ ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window ImGuiMouseCursor_Hand, // (Unused by Dear ImGui functions. Use for e.g. hyperlinks) + ImGuiMouseCursor_Wait, // When waiting for something to process/load. ImGuiMouseCursor_NotAllowed, // When hovering something with disallowed interaction. Usually a crossed circle. ImGuiMouseCursor_COUNT }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7671b7764ba3..a2b3de5f9ab1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7593,7 +7593,7 @@ static void ShowDemoWindowInputs() IMGUI_DEMO_MARKER("Inputs & Focus/Mouse Cursors"); if (ImGui::TreeNode("Mouse Cursors")) { - const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "NotAllowed" }; + const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "Wait", "NotAllowed" }; IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT); ImGuiMouseCursor current = ImGui::GetMouseCursor(); From eec097fe35c0bb2bba60c0a5ce0664cc3507f3bf Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 18 Feb 2025 18:52:08 +0100 Subject: [PATCH 471/548] Added ImGuiMouseCursor_Progress mouse cursor 8a35386+ support in SDL2,SDL3,Win32,Allegro5 backends. Amend 8a35386 --- backends/imgui_impl_allegro5.cpp | 3 ++- backends/imgui_impl_glfw.cpp | 2 +- backends/imgui_impl_glfw.h | 2 +- backends/imgui_impl_osx.h | 2 +- backends/imgui_impl_osx.mm | 2 +- backends/imgui_impl_sdl2.cpp | 3 ++- backends/imgui_impl_sdl3.cpp | 3 ++- backends/imgui_impl_win32.cpp | 3 ++- docs/CHANGELOG.txt | 6 ++++-- imgui.h | 1 + imgui_demo.cpp | 2 +- 11 files changed, 18 insertions(+), 11 deletions(-) diff --git a/backends/imgui_impl_allegro5.cpp b/backends/imgui_impl_allegro5.cpp index 7307affde40a..9db3e51981b4 100644 --- a/backends/imgui_impl_allegro5.cpp +++ b/backends/imgui_impl_allegro5.cpp @@ -20,7 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2025-02-18: Added ImGuiMouseCursor_Wait mouse cursor support. +// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-01-06: Avoid calling al_set_mouse_cursor() repeatedly since it appears to leak on on X11 (#8256). // 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: // - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn @@ -596,6 +596,7 @@ static void ImGui_ImplAllegro5_UpdateMouseCursor() case ImGuiMouseCursor_ResizeNESW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NE; break; case ImGuiMouseCursor_ResizeNWSE: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NW; break; case ImGuiMouseCursor_Wait: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_BUSY; break; + case ImGuiMouseCursor_Progress: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_PROGRESS; break; case ImGuiMouseCursor_NotAllowed: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_UNAVAILABLE; break; } al_set_system_mouse_cursor(bd->Display, cursor_id); diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 8bb61d14e2d3..69cde6c08910 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -11,7 +11,7 @@ // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // Missing features or Issues: // [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. -// [ ] Missing ImGuiMouseCursor_Wait cursor. +// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_glfw.h b/backends/imgui_impl_glfw.h index 260a06b146f4..e203b556fe95 100644 --- a/backends/imgui_impl_glfw.h +++ b/backends/imgui_impl_glfw.h @@ -10,7 +10,7 @@ // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Resizing cursors requires GLFW 3.4+! Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // Missing features or Issues: // [ ] Touch events are only correctly identified as Touch on Windows. This create issues with some interactions. GLFW doesn't provide a way to identify touch inputs from mouse inputs, we cannot call io.AddMouseSourceEvent() to identify the source. We provide a Windows-specific workaround. -// [ ] Missing ImGuiMouseCursor_Wait cursor. +// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index e4cda54ae25d..9d0aec07a0fc 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -11,7 +11,7 @@ // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: IME support. // Missing features or Issues: -// [ ] Missing ImGuiMouseCursor_Wait cursor. +// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 53bdace566c7..4726462cbec5 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -11,7 +11,7 @@ // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. // [X] Platform: IME support. // Missing features or Issues: -// [ ] Missing ImGuiMouseCursor_Wait cursor. +// [ ] Missing ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index d8fd43ae48ff..fbfa2fba8d9a 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,7 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2025-02-18: Added ImGuiMouseCursor_Wait mouse cursor support. +// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode_Manual) accept an empty array. // 2024-10-24: Emscripten: from SDL 2.30.9, SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f. @@ -501,6 +501,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); bd->MouseCursors[ImGuiMouseCursor_Wait] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT); + bd->MouseCursors[ImGuiMouseCursor_Progress] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAITARROW); bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); // Set platform dependent data in viewport diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 246a91213e07..006316afbb8b 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,7 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2025-02-18: Added ImGuiMouseCursor_Wait mouse cursor support. +// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode_Manual) accept an empty array. // 2024-10-24: Emscripten: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f on Emscripten. @@ -482,6 +482,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NWSE_RESIZE); bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_POINTER); bd->MouseCursors[ImGuiMouseCursor_Wait] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT); + bd->MouseCursors[ImGuiMouseCursor_Progress] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_PROGRESS); bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NOT_ALLOWED); // Set platform dependent data in viewport diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index cd1cc7ad554e..49948c529441 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -21,7 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2025-02-18: Added ImGuiMouseCursor_Wait mouse cursor support. +// 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768) // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. // 2023-09-25: Inputs: Synthesize key-down event on key-up for VK_SNAPSHOT / ImGuiKey_PrintScreen as Windows doesn't emit it (same behavior as GLFW/SDL). @@ -258,6 +258,7 @@ static bool ImGui_ImplWin32_UpdateMouseCursor(ImGuiIO& io, ImGuiMouseCursor imgu case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break; case ImGuiMouseCursor_Wait: win32_cursor = IDC_WAIT; break; + case ImGuiMouseCursor_Progress: win32_cursor = IDC_APPSTARTING; break; case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break; } ::SetCursor(::LoadCursor(nullptr, win32_cursor)); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a72107d127ec..7f2b4554ad6d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -83,12 +83,14 @@ Other changes: is hovered, merely it's visibility. (#8399, #8387) [@nicovanbentum] - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] -- Misc: Added ImGuiMouseCursor_Wait mouse cursor (busy/wait/hourglass shape). +- Misc: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursors + (busy/wait/hourglass shape, with or without an arrow cursor). - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) - Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. (#7660) [@achabense] -- Backends: SDL2, SDL3, Win32, Allegro5: Added support for ImGuiMouseCursor_Wait. +- Backends: SDL2, SDL3, Win32, Allegro5: Added support for ImGuiMouseCursor_Wait + and ImGuiMouseCursor_Progress cursors. - Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] diff --git a/imgui.h b/imgui.h index 5a9b1250c991..16c0b2c22e35 100644 --- a/imgui.h +++ b/imgui.h @@ -1834,6 +1834,7 @@ enum ImGuiMouseCursor_ ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window ImGuiMouseCursor_Hand, // (Unused by Dear ImGui functions. Use for e.g. hyperlinks) ImGuiMouseCursor_Wait, // When waiting for something to process/load. + ImGuiMouseCursor_Progress, // When waiting for something to process/load, but application is still interactive. ImGuiMouseCursor_NotAllowed, // When hovering something with disallowed interaction. Usually a crossed circle. ImGuiMouseCursor_COUNT }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a2b3de5f9ab1..3be8647248d0 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7593,7 +7593,7 @@ static void ShowDemoWindowInputs() IMGUI_DEMO_MARKER("Inputs & Focus/Mouse Cursors"); if (ImGui::TreeNode("Mouse Cursors")) { - const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "Wait", "NotAllowed" }; + const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "Wait", "Progress", "NotAllowed" }; IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT); ImGuiMouseCursor current = ImGui::GetMouseCursor(); From 8b7b3ce03eef61933727a0823741469e4f6d9b33 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 19 Feb 2025 10:14:38 +0100 Subject: [PATCH 472/548] Tables: fixed an issue where Columns Width state wouldn't be correctly restored when hot-reloading .ini state. (#7934) Amend 7cd31c355 column->SortDirection initialized setting was wrong in first block but without side-effect, since sorting always stored explicitly in .ini data. --- docs/CHANGELOG.txt | 4 ++-- imgui_tables.cpp | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7f2b4554ad6d..044be4360761 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -65,8 +65,8 @@ Other changes: which amusingly made it disappear when using very big font/frame size. - Tables: fixed calling SetNextWindowScroll() on clipped scrolling table to not leak the value into a subsequent window. (#8196) -- Tables: fixed an issue where Columns Visible/Hidden state wouldn't be correctly - overridden when hot-reloading .ini state. (#7934) +- Tables: fixed an issue where Columns Visible/Width state wouldn't be correctly + restored when hot-reloading .ini state. (#7934) - Tables: tamed some .ini settings optimizations to more accurately allow overwriting/hot-reloading settings in more situations. (#7934) - Tables, Error Handling: Recovery from invalid index in TableSetColumnIndex(). (#1651) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 6486dccd60b4..3a24ec4c476b 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1608,6 +1608,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo flags = column->Flags; // Initialize defaults + // FIXME: Similar to code in TableLoadSettings(), best to see how if we can merge. column->InitStretchWeightOrWidth = init_width_or_weight; if (table->IsInitializing) { @@ -1627,7 +1628,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo // Init default visibility/sort state if ((flags & ImGuiTableColumnFlags_DefaultHide) && (table->SettingsLoadedFlags & ImGuiTableFlags_Hideable) == 0) column->IsUserEnabled = column->IsUserEnabledNextFrame = false; - if (flags & ImGuiTableColumnFlags_DefaultSort && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0) + if ((flags & ImGuiTableColumnFlags_DefaultSort) && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0) { column->SortOrder = 0; // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs. column->SortDirection = (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending); @@ -3724,16 +3725,17 @@ void ImGui::TableLoadSettings(ImGuiTable* table) table->RefScale = settings->RefScale; // Initialize default columns settings + // FIXME: Similar to code in TableSetupColumn(), best to see how if we can merge. for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; - column->StretchWeight = -1.0f; - column->WidthRequest = -1.0f; + column->StretchWeight = (column->Flags & ImGuiTableColumnFlags_WidthStretch) && (column->InitStretchWeightOrWidth > 0.0f) ? column->InitStretchWeightOrWidth : -1.0f; + column->WidthRequest = (column->Flags & ImGuiTableColumnFlags_WidthFixed) && (column->InitStretchWeightOrWidth > 0.0f) ? column->InitStretchWeightOrWidth : -1.0f; column->AutoFitQueue = 0x00; column->DisplayOrder = (ImGuiTableColumnIdx)column_n; column->IsUserEnabled = column->IsUserEnabledNextFrame = (column->Flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1; column->SortOrder = (column->Flags & ImGuiTableColumnFlags_DefaultSort) ? 0 : -1; - column->SortDirection = (column->Flags & ImGuiTableColumnFlags_DefaultSort) ? (ImS8)ImGuiSortDirection_None : (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending); + column->SortDirection = (column->Flags & ImGuiTableColumnFlags_DefaultSort) ? ((column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending)) : (ImS8)ImGuiSortDirection_None; } // Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn From 05742f9b6ff06d7ce47669bd5b30fd74390ba11f Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 19 Feb 2025 10:55:44 +0100 Subject: [PATCH 473/548] Tables: share code between TableSetupColumn() and TableLoadSettings(). (#7934) --- imgui_tables.cpp | 61 ++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 3a24ec4c476b..f6aff8c026fb 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1565,6 +1565,31 @@ void ImGui::EndTable() NavUpdateCurrentWindowIsScrollPushableX(); } +// Called in TableSetupColumn() when initializing and in TableLoadSettings() for defaults before applying stored settings. +// 'init_mask' specify which fields to initialize. +static void TableInitColumnDefaults(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags init_mask) +{ + ImGuiTableColumnFlags flags = column->Flags; + if (init_mask & ImGuiTableFlags_Resizable) + { + float init_width_or_weight = column->InitStretchWeightOrWidth; + column->WidthRequest = ((flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f) ? init_width_or_weight : -1.0f; + column->StretchWeight = (init_width_or_weight > 0.0f && (flags & ImGuiTableColumnFlags_WidthStretch)) ? init_width_or_weight : -1.0f; + if (init_width_or_weight > 0.0f) // Disable auto-fit if an explicit width/weight has been specified + column->AutoFitQueue = 0x00; + } + if (init_mask & ImGuiTableFlags_Reorderable) + column->DisplayOrder = (ImGuiTableColumnIdx)table->Columns.index_from_ptr(column); + if (init_mask & ImGuiTableFlags_Hideable) + column->IsUserEnabled = column->IsUserEnabledNextFrame = (flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1; + if (init_mask & ImGuiTableFlags_Sortable) + { + // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs. + column->SortOrder = (flags & ImGuiTableColumnFlags_DefaultSort) ? 0 : -1; + column->SortDirection = (flags & ImGuiTableColumnFlags_DefaultSort) ? ((flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending)) : (ImS8)ImGuiSortDirection_None; + } +} + // See "COLUMNS SIZING POLICIES" comments at the top of this file // If (init_width_or_weight <= 0.0f) it is ignored void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id) @@ -1593,7 +1618,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo IM_ASSERT(init_width_or_weight <= 0.0f && "Can only specify width/weight if sizing policy is set explicitly in either Table or Column."); // When passing a width automatically enforce WidthFixed policy - // (whereas TableSetupColumnFlags would default to WidthAuto if table is not Resizable) + // (whereas TableSetupColumnFlags would default to WidthAuto if table is not resizable) if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0 && init_width_or_weight > 0.0f) if ((table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedFit || (table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame) flags |= ImGuiTableColumnFlags_WidthFixed; @@ -1608,31 +1633,13 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo flags = column->Flags; // Initialize defaults - // FIXME: Similar to code in TableLoadSettings(), best to see how if we can merge. column->InitStretchWeightOrWidth = init_width_or_weight; if (table->IsInitializing) { - // Init width or weight - if (column->WidthRequest < 0.0f && column->StretchWeight < 0.0f) - { - if ((flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f) - column->WidthRequest = init_width_or_weight; - if (flags & ImGuiTableColumnFlags_WidthStretch) - column->StretchWeight = (init_width_or_weight > 0.0f) ? init_width_or_weight : -1.0f; - - // Disable auto-fit if an explicit width/weight has been specified - if (init_width_or_weight > 0.0f) - column->AutoFitQueue = 0x00; - } - - // Init default visibility/sort state - if ((flags & ImGuiTableColumnFlags_DefaultHide) && (table->SettingsLoadedFlags & ImGuiTableFlags_Hideable) == 0) - column->IsUserEnabled = column->IsUserEnabledNextFrame = false; - if ((flags & ImGuiTableColumnFlags_DefaultSort) && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0) - { - column->SortOrder = 0; // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs. - column->SortDirection = (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending); - } + ImGuiTableFlags init_flags = ~0; + if (column->WidthRequest >= 0.0f && column->StretchWeight >= 0.0f) + init_flags &= ~ImGuiTableFlags_Resizable; + TableInitColumnDefaults(table, column, init_flags); } // Store name (append with zero-terminator in contiguous buffer) @@ -3725,17 +3732,11 @@ void ImGui::TableLoadSettings(ImGuiTable* table) table->RefScale = settings->RefScale; // Initialize default columns settings - // FIXME: Similar to code in TableSetupColumn(), best to see how if we can merge. for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; - column->StretchWeight = (column->Flags & ImGuiTableColumnFlags_WidthStretch) && (column->InitStretchWeightOrWidth > 0.0f) ? column->InitStretchWeightOrWidth : -1.0f; - column->WidthRequest = (column->Flags & ImGuiTableColumnFlags_WidthFixed) && (column->InitStretchWeightOrWidth > 0.0f) ? column->InitStretchWeightOrWidth : -1.0f; + TableInitColumnDefaults(table, column, ~0); column->AutoFitQueue = 0x00; - column->DisplayOrder = (ImGuiTableColumnIdx)column_n; - column->IsUserEnabled = column->IsUserEnabledNextFrame = (column->Flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1; - column->SortOrder = (column->Flags & ImGuiTableColumnFlags_DefaultSort) ? 0 : -1; - column->SortDirection = (column->Flags & ImGuiTableColumnFlags_DefaultSort) ? ((column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending)) : (ImS8)ImGuiSortDirection_None; } // Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn From 85c488ee121b5f2a3c51141a571dc20f9fd16710 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 20 Feb 2025 11:46:56 +0100 Subject: [PATCH 474/548] Hot-fix for broken MouseDrawCursor support for ImGuiMouseCursor_Wait/ImGuiMouseCursor_Progress/ImGuiMouseCursor_NotAllowed. Amend 8a35386, eec097f. --- imgui_draw.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3953212a1e9f..6ff583db637a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2466,6 +2466,8 @@ static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3 { ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW { ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE { ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand + { ImVec2(0,3), ImVec2(12,19), ImVec2(0, 0) }, // ImGuiMouseCursor_Wait + { ImVec2(0,3), ImVec2(12,19), ImVec2(0, 0) }, // ImGuiMouseCursor_Progress { ImVec2(109,0),ImVec2(13,15), ImVec2( 6, 7) }, // ImGuiMouseCursor_NotAllowed }; From 6dc376f676b3a09375ad53dce652cebac3cb3dc9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 20 Feb 2025 11:54:32 +0100 Subject: [PATCH 475/548] ImFontAtlas: added software/drawlist version of ImGuiMouseCursor_Wait/ImGuiMouseCursor_Progress + moved GetMouseCursorTexData() to internals. --- imgui.cpp | 9 ++++++++- imgui.h | 1 - imgui_draw.cpp | 22 +++++++++++----------- imgui_internal.h | 2 ++ 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c27095fd452f..e24079487d41 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3793,7 +3793,7 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso { // We scale cursor with current viewport/monitor, however Windows 10 for its own hardware cursor seems to be using a different scale factor. ImVec2 offset, size, uv[4]; - if (!font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2])) + if (!ImFontAtlasGetMouseCursorTexData(font_atlas, mouse_cursor, &offset, &size, &uv[0], &uv[2])) continue; const ImVec2 pos = base_pos - offset; const float scale = base_scale; @@ -3806,6 +3806,13 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow); draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border); draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill); + if (mouse_cursor == ImGuiMouseCursor_Wait || mouse_cursor == ImGuiMouseCursor_Progress) + { + float a_min = ImFmod((float)g.Time * 5.0f, 2.0f * IM_PI); + float a_max = a_min + IM_PI * 1.65f; + draw_list->PathArcTo(pos + ImVec2(14, -1) * scale, 6.0f * scale, a_min, a_max); + draw_list->PathStroke(col_fill, ImDrawFlags_None, 3.0f * scale); + } draw_list->PopTextureID(); } } diff --git a/imgui.h b/imgui.h index 16c0b2c22e35..a607a669e98e 100644 --- a/imgui.h +++ b/imgui.h @@ -3415,7 +3415,6 @@ struct ImFontAtlas // [Internal] IMGUI_API void CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const; - IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); //------------------------------------------- // Members diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 6ff583db637a..3fd71cf3c4e8 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2402,7 +2402,7 @@ ImFontConfig::ImFontConfig() // - ImFontAtlas::AddCustomRectRegular() // - ImFontAtlas::AddCustomRectFontGlyph() // - ImFontAtlas::CalcCustomRectUV() -// - ImFontAtlas::GetMouseCursorTexData() +// - ImFontAtlasGetMouseCursorTexData() // - ImFontAtlas::Build() // - ImFontAtlasBuildMultiplyCalcLookupTable() // - ImFontAtlasBuildMultiplyRectAlpha8() @@ -2466,8 +2466,8 @@ static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3 { ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW { ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE { ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand - { ImVec2(0,3), ImVec2(12,19), ImVec2(0, 0) }, // ImGuiMouseCursor_Wait - { ImVec2(0,3), ImVec2(12,19), ImVec2(0, 0) }, // ImGuiMouseCursor_Progress + { ImVec2(0,3), ImVec2(12,19), ImVec2(0, 0) }, // ImGuiMouseCursor_Wait // Arrow + custom code in ImGui::RenderMouseCursor() + { ImVec2(0,3), ImVec2(12,19), ImVec2(0, 0) }, // ImGuiMouseCursor_Progress // Arrow + custom code in ImGui::RenderMouseCursor() { ImVec2(109,0),ImVec2(13,15), ImVec2( 6, 7) }, // ImGuiMouseCursor_NotAllowed }; @@ -2754,24 +2754,24 @@ void ImFontAtlas::CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* ou *out_uv_max = ImVec2((float)(rect->X + rect->Width) * TexUvScale.x, (float)(rect->Y + rect->Height) * TexUvScale.y); } -bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]) +bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]) { if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_COUNT) return false; - if (Flags & ImFontAtlasFlags_NoMouseCursors) + if (atlas->Flags & ImFontAtlasFlags_NoMouseCursors) return false; - IM_ASSERT(PackIdMouseCursors != -1); - ImFontAtlasCustomRect* r = GetCustomRectByIndex(PackIdMouseCursors); + IM_ASSERT(atlas->PackIdMouseCursors != -1); + ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdMouseCursors); ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r->X, (float)r->Y); ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1]; *out_size = size; *out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2]; - out_uv_border[0] = (pos) * TexUvScale; - out_uv_border[1] = (pos + size) * TexUvScale; + out_uv_border[0] = (pos) * atlas->TexUvScale; + out_uv_border[1] = (pos + size) * atlas->TexUvScale; pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W + 1; - out_uv_fill[0] = (pos) * TexUvScale; - out_uv_fill[1] = (pos + size) * TexUvScale; + out_uv_fill[0] = (pos) * atlas->TexUvScale; + out_uv_fill[1] = (pos + size) * atlas->TexUvScale; return true; } diff --git a/imgui_internal.h b/imgui_internal.h index e272d5479124..f0cf1c1068f3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3587,6 +3587,8 @@ IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_ta IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride); IMGUI_API void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* cfg, int* out_oversample_h, int* out_oversample_v); +IMGUI_API bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); + //----------------------------------------------------------------------------- // [SECTION] Test Engine specific hooks (imgui_test_engine) //----------------------------------------------------------------------------- From a6bcbb173b36c1c0a12dfa75f996f440d16c1daa Mon Sep 17 00:00:00 2001 From: Tygyh <32486062+tygyh@users.noreply.github.com> Date: Thu, 20 Feb 2025 18:07:25 +0100 Subject: [PATCH 476/548] Examples: Android: Update kotlin version (#8409) --- examples/example_android_opengl3/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_android_opengl3/android/app/build.gradle b/examples/example_android_opengl3/android/app/build.gradle index 53181baa2157..3a68c83718df 100644 --- a/examples/example_android_opengl3/android/app/build.gradle +++ b/examples/example_android_opengl3/android/app/build.gradle @@ -42,5 +42,5 @@ repositories { mavenCentral() } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" } From 1e18a6cf6018e8de4cb38ebd87d2b9213f09823b Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 21 Feb 2025 16:55:35 +0100 Subject: [PATCH 477/548] Examples: GLFW+Vulkan: make GLFW_DIR overridable in cmake bit. (#8419) --- examples/example_glfw_vulkan/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/example_glfw_vulkan/CMakeLists.txt b/examples/example_glfw_vulkan/CMakeLists.txt index 443a144eae65..75475dbae873 100644 --- a/examples/example_glfw_vulkan/CMakeLists.txt +++ b/examples/example_glfw_vulkan/CMakeLists.txt @@ -15,7 +15,9 @@ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") # GLFW -set(GLFW_DIR ../../../glfw) # Set this to point to an up-to-date GLFW repo +if(NOT GLFW_DIR) + set(GLFW_DIR ../../../glfw) # Set this to point to an up-to-date GLFW repo +endif() option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) From 434b7710f3f291cad628b88d4ffb45e0fa3d249e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 19 Feb 2025 16:49:35 +0100 Subject: [PATCH 478/548] Internals: packing ImGuiDataVarInfo + misc renaming + value of ImGuiDataType_Pointer doesn't need to be Count+1 --- imgui.cpp | 18 +++++++++--------- imgui_internal.h | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e24079487d41..501a19c6675d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3367,7 +3367,7 @@ void ImGui::PopStyleColor(int count) } } -static const ImGuiDataVarInfo GStyleVarInfo[] = +static const ImGuiDataVarInfo GStyleVarsInfo[] = { { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, DisabledAlpha) }, // ImGuiStyleVar_DisabledAlpha @@ -3407,15 +3407,15 @@ static const ImGuiDataVarInfo GStyleVarInfo[] = const ImGuiDataVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx) { IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT); - IM_STATIC_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT); - return &GStyleVarInfo[idx]; + IM_STATIC_ASSERT(IM_ARRAYSIZE(GStyleVarsInfo) == ImGuiStyleVar_COUNT); + return &GStyleVarsInfo[idx]; } void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) { ImGuiContext& g = *GImGui; const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type != ImGuiDataType_Float || var_info->Count != 1) + if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 1) { IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); return; @@ -3429,7 +3429,7 @@ void ImGui::PushStyleVarX(ImGuiStyleVar idx, float val_x) { ImGuiContext& g = *GImGui; const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type != ImGuiDataType_Float || var_info->Count != 2) + if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2) { IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); return; @@ -3443,7 +3443,7 @@ void ImGui::PushStyleVarY(ImGuiStyleVar idx, float val_y) { ImGuiContext& g = *GImGui; const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type != ImGuiDataType_Float || var_info->Count != 2) + if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2) { IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); return; @@ -3457,7 +3457,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) { ImGuiContext& g = *GImGui; const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type != ImGuiDataType_Float || var_info->Count != 2) + if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2) { IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); return; @@ -3481,8 +3481,8 @@ void ImGui::PopStyleVar(int count) ImGuiStyleMod& backup = g.StyleVarStack.back(); const ImGuiDataVarInfo* info = GetStyleVarInfo(backup.VarIdx); void* data = info->GetVarPtr(&g.Style); - if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; } - else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; } + if (info->DataType == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; } + else if (info->DataType == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; } g.StyleVarStack.pop_back(); count--; } diff --git a/imgui_internal.h b/imgui_internal.h index f0cf1c1068f3..22d0354231bd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -814,9 +814,9 @@ struct ImDrawDataBuilder struct ImGuiDataVarInfo { - ImGuiDataType Type; - ImU32 Count; // 1+ - ImU32 Offset; // Offset in parent structure + ImGuiDataType DataType : 8; + ImU32 Count : 8; // 1+ + ImU32 Offset : 16; // Offset in parent structure void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); } }; @@ -837,7 +837,7 @@ struct ImGuiDataTypeInfo // Extend ImGuiDataType_ enum ImGuiDataTypePrivate_ { - ImGuiDataType_Pointer = ImGuiDataType_COUNT + 1, + ImGuiDataType_Pointer = ImGuiDataType_COUNT, ImGuiDataType_ID, }; From edc66d79c7df44899cb1e9be4f839ef4371be91b Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 21 Feb 2025 23:09:54 +0100 Subject: [PATCH 479/548] Nav: extract code into a NavUpdateWindowingApplyFocus() so it may be reused elsewhere. --- imgui.cpp | 50 +++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 501a19c6675d..9e2a5e2002e1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1212,6 +1212,7 @@ static void UpdateWindowInFocusOrderList(ImGuiWindow* window, bool j // Navigation static void NavUpdate(); static void NavUpdateWindowing(); +static void NavUpdateWindowingApplyFocus(ImGuiWindow* window); static void NavUpdateWindowingOverlay(); static void NavUpdateCancelRequest(); static void NavUpdateCreateMoveRequest(); @@ -13651,6 +13652,33 @@ static void NavUpdateWindowingTarget(int focus_change_dir) g.NavWindowingToggleLayer = false; } +// Apply focus and close overlay +static void ImGui::NavUpdateWindowingApplyFocus(ImGuiWindow* apply_focus_window) +{ + ImGuiContext& g = *GImGui; + if (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow) + { + ClearActiveID(); + SetNavCursorVisibleAfterMove(); + ClosePopupsOverWindow(apply_focus_window, false); + FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild); + apply_focus_window = g.NavWindow; + if (apply_focus_window->NavLastIds[0] == 0) + NavInitWindow(apply_focus_window, false); + + // If the window has ONLY a menu layer (no main layer), select it directly + // Use NavLayersActiveMaskNext since windows didn't have a chance to be Begin()-ed on this frame, + // so CTRL+Tab where the keys are only held for 1 frame will be able to use correct layers mask since + // the target window as already been previewed once. + // FIXME-NAV: This should be done in NavInit.. or in FocusWindow... However in both of those cases, + // we won't have a guarantee that windows has been visible before and therefore NavLayersActiveMask* + // won't be valid. + if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu)) + g.NavLayer = ImGuiNavLayer_Menu; + } + g.NavWindowingTarget = NULL; +} + // Windowing management mode // Keyboard: CTRL+Tab (change focus/move/resize), Alt (toggle menu layer) // Gamepad: Hold Menu/Square (change focus/move/resize), Tap Menu/Square (toggle menu layer) @@ -13802,28 +13830,8 @@ static void ImGui::NavUpdateWindowing() } // Apply final focus - if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow)) - { - ClearActiveID(); - SetNavCursorVisibleAfterMove(); - ClosePopupsOverWindow(apply_focus_window, false); - FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild); - apply_focus_window = g.NavWindow; - if (apply_focus_window->NavLastIds[0] == 0) - NavInitWindow(apply_focus_window, false); - - // If the window has ONLY a menu layer (no main layer), select it directly - // Use NavLayersActiveMaskNext since windows didn't have a chance to be Begin()-ed on this frame, - // so CTRL+Tab where the keys are only held for 1 frame will be able to use correct layers mask since - // the target window as already been previewed once. - // FIXME-NAV: This should be done in NavInit.. or in FocusWindow... However in both of those cases, - // we won't have a guarantee that windows has been visible before and therefore NavLayersActiveMask* - // won't be valid. - if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu)) - g.NavLayer = ImGuiNavLayer_Menu; - } if (apply_focus_window) - g.NavWindowingTarget = NULL; + NavUpdateWindowingApplyFocus(apply_focus_window); // Apply menu/layer toggle if (apply_toggle_layer && g.NavWindow) From 74afea04d6432e3cbcadd43f8eaf771aed48a1c8 Mon Sep 17 00:00:00 2001 From: Tygyh <32486062+tygyh@users.noreply.github.com> Date: Sat, 22 Feb 2025 23:36:40 +0100 Subject: [PATCH 480/548] Fix typos in docs (#8427) --- docs/CHANGELOG.txt | 4 ++-- docs/CONTRIBUTING.md | 2 +- docs/TODO.txt | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 044be4360761..0d1bbd0523af 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -346,7 +346,7 @@ Other changes: initial mouse down event. - Note that it may reveal incorrect usage if you were using InputInt/InputFloat without persistent storage by relying solely on e.g. IsItemDeactivatedAfterEdit(): - this was never supported and didn't work consistantly (see #8149). + this was never supported and didn't work consistently (see #8149). - InputText: fixed a bug (regression in 1.91.2) where modifying text buffer within a callback would sometimes prevents further appending to the buffer. - Tabs, Style: made ImGuiCol_TabDimmedSelectedOverline alpha 0 (not visible) in default @@ -450,7 +450,7 @@ Other changes: supported by InputFloat, InputInt, InputScalar etc. widgets. It actually never was. (#8065, #3946) - imgui_freetype: Added support for plutosvg (as an alternative to lunasvg) to render OpenType SVG fonts. Requires defining IMGUI_ENABLE_FREETYPE_PLUTOSVG along with IMGUI_ENABLE_FREETYPE. - Providing headers/librairies for plutosvg + plutovg is up to you (see #7927 for help). + Providing headers/libraries for plutosvg + plutovg is up to you (see #7927 for help). (#7927, #7187, #6591, #6607) [@pthom] - Backends: DX11, DX12, SDLRenderer2/3. Vulkan, WGPU: expose selected state in ImGui_ImplXXXX_RenderState structures during render loop user draw callbacks. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index f70cf0e23448..fb946c4b3db4 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -77,5 +77,5 @@ If you have been using Dear ImGui for a while or have been using C/C++ for sever Any code you submit will become part of the repository and be distributed under the [Dear ImGui license](https://github.com/ocornut/imgui/blob/master/LICENSE.txt). By submitting code to the project you agree that the code is your work and that you can give it to the project. -You also agree by submitting your code that you grant all transferrable rights to the code to the project maintainer, including for example re-licensing the code, modifying the code, and distributing it in source or binary forms. Specifically, this includes a requirement that you assign copyright to the project maintainer. For this reason, do not modify any copyright statements in files in any PRs. +You also agree by submitting your code that you grant all transferable rights to the code to the project maintainer, including for example re-licensing the code, modifying the code, and distributing it in source or binary forms. Specifically, this includes a requirement that you assign copyright to the project maintainer. For this reason, do not modify any copyright statements in files in any PRs. diff --git a/docs/TODO.txt b/docs/TODO.txt index 31238ff83536..14a152a4bec0 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -22,7 +22,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - window: using SetWindowPos() inside Begin() and moving the window with the mouse reacts a very ugly glitch. We should just defer the SetWindowPos() call. - window: GetWindowSize() returns (0,0) when not calculated? (#1045) - window: investigate better auto-positioning for new windows. - - window: top most window flag? more z-order contrl? (#2574) + - window: top most window flag? more z-order control? (#2574) - window/size: manually triggered auto-fit (double-click on grip) shouldn't resize window down to viewport size? - window/size: how to allow to e.g. auto-size vertically to fit contents, but be horizontally resizable? Assuming SetNextWindowSize() is modified to treat -1.0f on each axis as "keep as-is" (would be good but might break erroneous code): Problem is UpdateWindowManualResize() and lots of code treat (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) together. - window/opt: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. -> this may require enforcing that it is illegal to submit contents if Begin returns false. @@ -57,7 +57,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - widgets: start exposing PushItemFlag() and ImGuiItemFlags - widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260 - widgets: activate by identifier (trigger button, focus given id) - - widgets: custom glyph/shapes replacements for stock sapes. (also #6090 #2431 #2235 #6517) + - widgets: custom glyph/shapes replacements for stock shapes. (also #6090 #2431 #2235 #6517) - widgets: coloredit: keep reporting as active when picker is on? - widgets: group/scalarn functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow. - selectable: using (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported. @@ -137,7 +137,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - image/image button: misalignment on padded/bordered button? - image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that? - slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt() - - slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate. + - slider: add dragging-based widgets to edit values with mouse (on 2 axes), saving screen real-estate. - slider: tint background based on value (e.g. v_min -> v_max, or use 0.0f either side of the sign) - slider: relative dragging? + precision dragging - slider: step option (#1183) @@ -213,7 +213,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs. - log: obsolete LogButtons().... (was: LogButtons() options for specifying depth and/or hiding depth slider) - - filters: set a current filter that certains items (e.g. tree node) can automatically query to hide themselves + - filters: set a current filter that certain items (e.g. tree node) can automatically query to hide themselves - filters: handle wild-cards (with implicit leading/trailing *), reg-exprs - filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb) From 5dce79e9410bfe0fd1709980b637ce38a2313ed0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 24 Feb 2025 10:52:15 +0100 Subject: [PATCH 481/548] Backends: DirectX12: Fixed an issue where pre-1.91.5 legacy ImGui_ImplDX12_Init() signature started breaking in 1.91.8 due to missing command queue. (#8429) --- backends/imgui_impl_dx12.cpp | 25 ++++++++++++++++++++++--- backends/imgui_impl_dx12.h | 5 +++-- docs/CHANGELOG.txt | 2 ++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 6f17f587aff9..8449832c5b09 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-24: DirectX12: Fixed an issue where ImGui_ImplDX12_Init() signature change from 2024-11-15 combined with change from 2025-01-15 made legacy ImGui_ImplDX12_Init() crash. (#8429) // 2025-01-15: DirectX12: Texture upload use the command queue provided in ImGui_ImplDX12_InitInfo instead of creating its own. // 2024-12-09: DirectX12: Let user specifies the DepthStencilView format by setting ImGui_ImplDX12_InitInfo::DSVFormat. // 2024-11-15: DirectX12: *BREAKING CHANGE* Changed ImGui_ImplDX12_Init() signature to take a ImGui_ImplDX12_InitInfo struct. Legacy ImGui_ImplDX12_Init() signature is still supported (will obsolete). @@ -75,6 +76,8 @@ struct ImGui_ImplDX12_Data ID3D12Device* pd3dDevice; ID3D12RootSignature* pRootSignature; ID3D12PipelineState* pPipelineState; + ID3D12CommandQueue* pCommandQueue; + bool commandQueueOwned; DXGI_FORMAT RTVFormat; DXGI_FORMAT DSVFormat; ID3D12DescriptorHeap* pd3dSrvDescHeap; @@ -430,7 +433,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() hr = cmdList->Close(); IM_ASSERT(SUCCEEDED(hr)); - ID3D12CommandQueue* cmdQueue = bd->InitInfo.CommandQueue; + ID3D12CommandQueue* cmdQueue = bd->pCommandQueue; cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList); hr = cmdQueue->Signal(fence, 1); IM_ASSERT(SUCCEEDED(hr)); @@ -702,6 +705,9 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() if (!bd || !bd->pd3dDevice) return; + if (bd->commandQueueOwned) + SafeRelease(bd->pCommandQueue); + bd->commandQueueOwned = false; SafeRelease(bd->pRootSignature); SafeRelease(bd->pPipelineState); @@ -732,6 +738,8 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info) init_info = &bd->InitInfo; bd->pd3dDevice = init_info->Device; + IM_ASSERT(init_info->CommandQueue != NULL); + bd->pCommandQueue = init_info->CommandQueue; bd->RTVFormat = init_info->RTVFormat; bd->DSVFormat = init_info->DSVFormat; bd->numFramesInFlight = init_info->NumFramesInFlight; @@ -793,8 +801,19 @@ bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FO init_info.RTVFormat = rtv_format; init_info.SrvDescriptorHeap = srv_descriptor_heap; init_info.LegacySingleSrvCpuDescriptor = font_srv_cpu_desc_handle; - init_info.LegacySingleSrvGpuDescriptor = font_srv_gpu_desc_handle;; - return ImGui_ImplDX12_Init(&init_info); + init_info.LegacySingleSrvGpuDescriptor = font_srv_gpu_desc_handle; + + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.NodeMask = 1; + HRESULT hr = device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&init_info.CommandQueue)); + IM_ASSERT(SUCCEEDED(hr)); + + bool ret = ImGui_ImplDX12_Init(&init_info); + ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); + bd->commandQueueOwned = true; + return ret; } #endif diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h index a57c1694d36e..736e9f5c2e3e 100644 --- a/backends/imgui_impl_dx12.h +++ b/backends/imgui_impl_dx12.h @@ -27,7 +27,7 @@ struct ImGui_ImplDX12_InitInfo { ID3D12Device* Device; - ID3D12CommandQueue* CommandQueue; + ID3D12CommandQueue* CommandQueue; // Command queue used for queuing texture uploads. int NumFramesInFlight; DXGI_FORMAT RTVFormat; // RenderTarget format. DXGI_FORMAT DSVFormat; // DepthStencilView format. @@ -54,7 +54,8 @@ IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // Legacy initialization API Obsoleted in 1.91.5 -// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap' +// - font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture, they must be in 'srv_descriptor_heap' +// - When we introduced the ImGui_ImplDX12_InitInfo struct we also added a 'ID3D12CommandQueue* CommandQueue' field. IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* srv_descriptor_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle); #endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0d1bbd0523af..ae09637033fc 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -93,6 +93,8 @@ Other changes: and ImGuiMouseCursor_Progress cursors. - Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) +- Backends: DirectX12: Fixed an issue where pre-1.91.5 legacy ImGui_ImplDX12_Init() + signature started breaking in 1.91.8 due to missing command queue. (#8429) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] - Backends: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. (#8326, #8365) [@mklefrancois] From ef969a53f5fe8b956dc252718f14997393e3344f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 24 Feb 2025 11:44:48 +0100 Subject: [PATCH 482/548] Tabs: fixed Unsaved Marker not being visible when Close Button is. (#8430, #8387) --- imgui_widgets.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6e08cec22e5a..f011805f98d1 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -10377,9 +10377,15 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, else close_button_visible = (g.Style.TabCloseButtonMinWidthUnselected < 0.0f) ? true : (is_hovered && bb.GetWidth() >= ImMax(button_sz, g.Style.TabCloseButtonMinWidthUnselected)); } - bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x); - if (close_button_visible) + // When tabs/document is unsaved, the unsaved marker takes priority over the close button. + const bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x) && (!close_button_visible || !is_hovered); + if (unsaved_marker_visible) + { + const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz)); + RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text)); + } + else if (close_button_visible) { ImGuiLastItemData last_item_backup = g.LastItemData; if (CloseButton(close_button_id, button_pos)) @@ -10390,11 +10396,6 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, if (is_hovered && !(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2)) close_button_pressed = true; } - else if (unsaved_marker_visible) - { - const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz)); - RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text)); - } // This is all rather complicated // (the main idea is that because the close button only appears on hover, we don't want it to alter the ellipsis position) From dac40d04872e32399f81b1bf8d0befe87c4cd647 Mon Sep 17 00:00:00 2001 From: TheMode Date: Sat, 22 Feb 2025 11:36:41 +0100 Subject: [PATCH 483/548] Backends: SDL2, SDL3: don't call SDL_GetGlobalMouseState() when mouse position is in relative mode. (#8425, #8407) --- backends/imgui_impl_sdl2.cpp | 5 ++++- backends/imgui_impl_sdl3.cpp | 4 +++- docs/CHANGELOG.txt | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index fbfa2fba8d9a..361fc3b57e3f 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode_Manual) accept an empty array. @@ -622,8 +623,10 @@ static void ImGui_ImplSDL2_UpdateMouseData() SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y); // (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured) - if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0) + const bool is_relative_mouse_mode = SDL_GetRelativeMouseMode() != 0; + if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) { + // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) int window_x, window_y, mouse_x_global, mouse_y_global; SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); SDL_GetWindowPosition(bd->Window, &window_x, &window_y); diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 006316afbb8b..d2433793e609 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode_Manual) accept an empty array. @@ -588,7 +589,8 @@ static void ImGui_ImplSDL3_UpdateMouseData() SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y); // (Optional) Fallback to provide mouse position when focused (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured) - if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0) + const bool is_relative_mouse_mode = SDL_GetWindowRelativeMouseMode(bd->Window); + if (bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) { // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window) float mouse_x_global, mouse_y_global; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ae09637033fc..d0acdcb9210d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -87,10 +87,12 @@ Other changes: (busy/wait/hourglass shape, with or without an arrow cursor). - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) -- Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn +- Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. (#7660) [@achabense] - Backends: SDL2, SDL3, Win32, Allegro5: Added support for ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress cursors. +- Backends: SDL2, SDL3: Avoid calling SDL_GetGlobalMouseState() when mouse is in + relative mode. (#8425, #8407) [@TheMode] - Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) - Backends: DirectX12: Fixed an issue where pre-1.91.5 legacy ImGui_ImplDX12_Init() From 030746faff4a0181ec3149b8457f7bd0a5770819 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 24 Feb 2025 17:45:16 +0100 Subject: [PATCH 484/548] Debug Tools: Added io.ConfigDebugHighlightIdConflictsShowItemPicker. (#7961, #7669) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 24 +++++++++++++++++------- imgui.h | 3 ++- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d0acdcb9210d..d5c4ded328f0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -83,6 +83,8 @@ Other changes: is hovered, merely it's visibility. (#8399, #8387) [@nicovanbentum] - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] +- Debug Tools: Added io.ConfigDebugHighlightIdConflictsShowItemPicker (defaults to true) + to allow disabled Item Picker suggestion in user facing builds. (#7961, #7669) - Misc: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursors (busy/wait/hourglass shape, with or without an arrow cursor). - Demo: Combos: demonstrate a very simple way to add a filter to a combo, diff --git a/imgui.cpp b/imgui.cpp index 9e2a5e2002e1..a5d52d415d7c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1454,6 +1454,7 @@ ImGuiIO::ImGuiIO() ConfigMemoryCompactTimer = 60.0f; ConfigDebugIsDebuggerPresent = false; ConfigDebugHighlightIdConflicts = true; + ConfigDebugHighlightIdConflictsShowItemPicker = true; ConfigDebugBeginReturnValueOnce = false; ConfigDebugBeginReturnValueLoop = false; @@ -10445,15 +10446,24 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip() //BulletText("Code intending to use duplicate ID may use e.g. PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); ... PopItemFlag()"); // Not making this too visible for fear of it being abused. BulletText("Set io.ConfigDebugHighlightIdConflicts=false to disable this warning in non-programmers builds."); Separator(); - Text("(Hold CTRL to: use"); - SameLine(); - if (SmallButton("Item Picker")) - DebugStartItemPicker(); - SameLine(); - Text("to break in item call-stack, or"); - SameLine(); + if (g.IO.ConfigDebugHighlightIdConflictsShowItemPicker) + { + Text("(Hold CTRL to: use "); + SameLine(0.0f, 0.0f); + if (SmallButton("Item Picker")) + DebugStartItemPicker(); + SameLine(0.0f, 0.0f); + Text(" to break in item call-stack, or "); + } + else + { + Text("(Hold CTRL to "); + } + SameLine(0.0f, 0.0f); if (SmallButton("Open FAQ->About ID Stack System") && g.PlatformIO.Platform_OpenInShellFn != NULL) g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage"); + SameLine(0.0f, 0.0f); + Text(")"); EndErrorTooltip(); } diff --git a/imgui.h b/imgui.h index a607a669e98e..5cba09f1c414 100644 --- a/imgui.h +++ b/imgui.h @@ -2319,7 +2319,8 @@ struct ImGuiIO // - Code should use PushID()/PopID() in loops, or append "##xx" to same-label identifiers. // - Empty label e.g. Button("") == same ID as parent widget/node. Use Button("##xx") instead! // - See FAQ https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-about-the-id-stack-system - bool ConfigDebugHighlightIdConflicts;// = true // Highlight and show an error message when multiple items have conflicting identifiers. + bool ConfigDebugHighlightIdConflicts;// = true // Highlight and show an error message popup when multiple items have conflicting identifiers. + bool ConfigDebugHighlightIdConflictsShowItemPicker;//=true // Show "Item Picker" button in aforementioned popup. // Tools to test correct Begin/End and BeginChild/EndChild behaviors. // - Presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX() From 6e29450f76db356ebee19a9ac4ee8f4fc129e961 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 25 Feb 2025 16:02:10 +0100 Subject: [PATCH 485/548] Internals: added IsItemActiveAsInputText() helper. --- imgui_internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui_internal.h b/imgui_internal.h index 22d0354231bd..c4ec9cc93a25 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3481,6 +3481,7 @@ namespace ImGui inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); } inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active IMGUI_API void SetNextItemRefVal(ImGuiDataType data_type, void* p_data); + inline bool IsItemActiveAsInputText() { ImGuiContext& g = *GImGui; return g.ActiveId != 0 && g.ActiveId == g.LastItemData.ID && g.InputTextState.ID == g.LastItemData.ID; } // This may be useful to apply workaround that a based on distinguish whenever an item is active as a text input field. // Color IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); From 4c0604ec2ee9a9121ea4ecb55543ff507ca81bcc Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 18 Jan 2025 16:03:46 +0100 Subject: [PATCH 486/548] Font: shallow refactor, rename ConfigData[] fields to Sources[], ConfigDataCount to SourcesCount. In theory this is all internal stuff. --- imgui.cpp | 12 ++-- imgui.h | 10 +-- imgui_draw.cpp | 114 +++++++++++++++---------------- imgui_internal.h | 6 +- misc/freetype/imgui_freetype.cpp | 54 +++++++-------- 5 files changed, 98 insertions(+), 98 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a5d52d415d7c..64514028ff86 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16215,7 +16215,7 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co void ImGui::DebugNodeFont(ImFont* font) { bool opened = TreeNode(font, "Font: \"%s\": %.2f px, %d glyphs, %d sources(s)", - font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount); + font->Sources ? font->Sources[0].Name : "", font->FontSize, font->Glyphs.Size, font->SourcesCount); // Display preview text if (!opened) @@ -16248,14 +16248,14 @@ void ImGui::DebugNodeFont(ImFont* font) Text("Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar); const int surface_sqrt = (int)ImSqrt((float)font->MetricsTotalSurface); Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt); - for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) - if (font->ConfigData) + for (int config_i = 0; config_i < font->SourcesCount; config_i++) + if (font->Sources) { - const ImFontConfig* cfg = &font->ConfigData[config_i]; + const ImFontConfig* src = &font->Sources[config_i]; int oversample_h, oversample_v; - ImFontAtlasBuildGetOversampleFactors(cfg, &oversample_h, &oversample_v); + ImFontAtlasBuildGetOversampleFactors(src, &oversample_h, &oversample_v); BulletText("Input %d: \'%s\', Oversample: (%d=>%d,%d=>%d), PixelSnapH: %d, Offset: (%.1f,%.1f)", - config_i, cfg->Name, cfg->OversampleH, oversample_h, cfg->OversampleV, oversample_v, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y); + config_i, src->Name, src->OversampleH, oversample_h, src->OversampleV, oversample_v, src->PixelSnapH, src->GlyphOffset.x, src->GlyphOffset.y); } // Display all glyphs of the fonts in separate pages of 256 characters diff --git a/imgui.h b/imgui.h index 5cba09f1c414..1bdc2cb10b13 100644 --- a/imgui.h +++ b/imgui.h @@ -3441,7 +3441,7 @@ struct ImFontAtlas ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. ImVector CustomRects; // Rectangles for packing custom texture data into the atlas. - ImVector ConfigData; // Configuration data + ImVector Sources; // Source/configuration data ImVec4 TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1]; // UVs for baked anti-aliased lines // [Internal] Font builder @@ -3472,10 +3472,10 @@ struct ImFont ImFontGlyph* FallbackGlyph; // 4-8 // out // = FindGlyph(FontFallbackChar) // [Internal] Members: Cold ~32/40 bytes - // Conceptually ConfigData[] is the list of font sources merged to create this font. + // Conceptually Sources[] is the list of font sources merged to create this font. ImFontAtlas* ContainerAtlas; // 4-8 // out // What we has been loaded into - const ImFontConfig* ConfigData; // 4-8 // in // Pointer within ContainerAtlas->ConfigData to ConfigDataCount instances - short ConfigDataCount; // 2 // in // Number of ImFontConfig involved in creating this font. Usually 1, or >1 when merging multiple font sources into one ImFont. + ImFontConfig* Sources; // 4-8 // in // Pointer within ContainerAtlas->Sources[], to SourcesCount instances + short SourcesCount; // 2 // in // Number of ImFontConfig involved in creating this font. Usually 1, or >1 when merging multiple font sources into one ImFont. short EllipsisCharCount; // 1 // out // 1 or 3 ImWchar EllipsisChar; // 2-4 // out // Character used for ellipsis rendering ('...'). ImWchar FallbackChar; // 2-4 // out // Character used if a glyph isn't found (U+FFFD, '?') @@ -3494,7 +3494,7 @@ struct ImFont IMGUI_API ImFontGlyph* FindGlyphNoFallback(ImWchar c); float GetCharAdvance(ImWchar c) { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } bool IsLoaded() const { return ContainerAtlas != NULL; } - const char* GetDebugName() const { return ConfigData ? ConfigData->Name : ""; } + const char* GetDebugName() const { return Sources ? Sources->Name : ""; } // [Internal] Don't use! // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3fd71cf3c4e8..206c29ce5a06 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2408,7 +2408,7 @@ ImFontConfig::ImFontConfig() // - ImFontAtlasBuildMultiplyRectAlpha8() // - ImFontAtlasBuildWithStbTruetype() // - ImFontAtlasGetBuilderForStbTruetype() -// - ImFontAtlasUpdateConfigDataPointers() +// - ImFontAtlasUpdateSourcesPointers() // - ImFontAtlasBuildSetupFont() // - ImFontAtlasBuildPackCustomRects() // - ImFontAtlasBuildRender8bppRectFromString() @@ -2487,7 +2487,7 @@ ImFontAtlas::~ImFontAtlas() void ImFontAtlas::ClearInputData() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); - for (ImFontConfig& font_cfg : ConfigData) + for (ImFontConfig& font_cfg : Sources) if (font_cfg.FontData && font_cfg.FontDataOwnedByAtlas) { IM_FREE(font_cfg.FontData); @@ -2496,12 +2496,12 @@ void ImFontAtlas::ClearInputData() // When clearing this we lose access to the font name and other information used to build the font. for (ImFont* font : Fonts) - if (font->ConfigData >= ConfigData.Data && font->ConfigData < ConfigData.Data + ConfigData.Size) + if (font->Sources >= Sources.Data && font->Sources < Sources.Data + Sources.Size) { - font->ConfigData = NULL; - font->ConfigDataCount = 0; + font->Sources = NULL; + font->SourcesCount = 0; } - ConfigData.clear(); + Sources.clear(); CustomRects.clear(); PackIdMouseCursors = PackIdLines = -1; // Important: we leave TexReady untouched @@ -2584,8 +2584,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) else IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font. - ConfigData.push_back(*font_cfg); - ImFontConfig& new_font_cfg = ConfigData.back(); + Sources.push_back(*font_cfg); + ImFontConfig& new_font_cfg = Sources.back(); if (new_font_cfg.DstFont == NULL) new_font_cfg.DstFont = Fonts.back(); if (!new_font_cfg.FontDataOwnedByAtlas) @@ -2601,8 +2601,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) // - We may support it better later and remove this rounding. new_font_cfg.SizePixels = ImTrunc(new_font_cfg.SizePixels); - // Pointers to ConfigData and BuilderData are otherwise dangling - ImFontAtlasUpdateConfigDataPointers(this); + // Pointers to Sources data are otherwise dangling + ImFontAtlasUpdateSourcesPointers(this); // Invalidate texture TexReady = false; @@ -2780,7 +2780,7 @@ bool ImFontAtlas::Build() IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); // Default font is none are specified - if (ConfigData.Size == 0) + if (Sources.Size == 0) AddFontDefault(); // Select builder @@ -2822,11 +2822,11 @@ void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsig *data = table[*data]; } -void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* cfg, int* out_oversample_h, int* out_oversample_v) +void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* src, int* out_oversample_h, int* out_oversample_v) { // Automatically disable horizontal oversampling over size 36 - *out_oversample_h = (cfg->OversampleH != 0) ? cfg->OversampleH : (cfg->SizePixels * cfg->RasterizerDensity > 36.0f || cfg->PixelSnapH) ? 1 : 2; - *out_oversample_v = (cfg->OversampleV != 0) ? cfg->OversampleV : 1; + *out_oversample_h = (src->OversampleH != 0) ? src->OversampleH : (src->SizePixels * src->RasterizerDensity > 36.0f || src->PixelSnapH) ? 1 : 2; + *out_oversample_v = (src->OversampleV != 0) ? src->OversampleV : 1; } #ifdef IMGUI_ENABLE_STB_TRUETYPE @@ -2869,7 +2869,7 @@ static void UnpackBitVectorToFlatIndexList(const ImBitVector* in, ImVector* static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { - IM_ASSERT(atlas->ConfigData.Size > 0); + IM_ASSERT(atlas->Sources.Size > 0); ImFontAtlasBuildInit(atlas); @@ -2883,32 +2883,32 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) // Temporary storage for building ImVector src_tmp_array; ImVector dst_tmp_array; - src_tmp_array.resize(atlas->ConfigData.Size); + src_tmp_array.resize(atlas->Sources.Size); dst_tmp_array.resize(atlas->Fonts.Size); memset(src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes()); memset(dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes()); // 1. Initialize font loading structure, check font data validity - for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++) + for (int src_i = 0; src_i < atlas->Sources.Size; src_i++) { ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; - IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); + ImFontConfig& src = atlas->Sources[src_i]; + IM_ASSERT(src.DstFont && (!src.DstFont->IsLoaded() || src.DstFont->ContainerAtlas == atlas)); - // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) + // Find index from src.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) src_tmp.DstIndex = -1; for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) - if (cfg.DstFont == atlas->Fonts[output_i]) + if (src.DstFont == atlas->Fonts[output_i]) src_tmp.DstIndex = output_i; if (src_tmp.DstIndex == -1) { - IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array? + IM_ASSERT(src_tmp.DstIndex != -1); // src.DstFont not pointing within atlas->Fonts[] array? return false; } // Initialize helper structure for font loading and verify that the TTF/OTF data is correct - const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); + const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)src.FontData, src.FontNo); IM_ASSERT(font_offset >= 0 && "FontData is incorrect, or FontNo cannot be found."); - if (!stbtt_InitFont(&src_tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) + if (!stbtt_InitFont(&src_tmp.FontInfo, (unsigned char*)src.FontData, font_offset)) { IM_ASSERT(0 && "stbtt_InitFont(): failed to parse FontData. It is correct and complete? Check FontDataSize."); return false; @@ -2916,7 +2916,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) // Measure highest codepoints ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault(); + src_tmp.SrcRanges = src.GlyphRanges ? src.GlyphRanges : atlas->GetGlyphRangesDefault(); for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) { // Check for valid range. This may also help detect *some* dangling pointers, because a common @@ -2995,12 +2995,12 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) buf_packedchars_out_n += src_tmp.GlyphsCount; // Automatic selection of oversampling parameters - ImFontConfig& cfg = atlas->ConfigData[src_i]; + ImFontConfig& src = atlas->Sources[src_i]; int oversample_h, oversample_v; - ImFontAtlasBuildGetOversampleFactors(&cfg, &oversample_h, &oversample_v); + ImFontAtlasBuildGetOversampleFactors(&src, &oversample_h, &oversample_v); // Convert our ranges in the format stb_truetype wants - src_tmp.PackRange.font_size = cfg.SizePixels * cfg.RasterizerDensity; + src_tmp.PackRange.font_size = src.SizePixels * src.RasterizerDensity; src_tmp.PackRange.first_unicode_codepoint_in_range = 0; src_tmp.PackRange.array_of_unicode_codepoints = src_tmp.GlyphsList.Data; src_tmp.PackRange.num_chars = src_tmp.GlyphsList.Size; @@ -3009,7 +3009,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) src_tmp.PackRange.v_oversample = (unsigned char)oversample_v; // Gather the sizes of all rectangles we will need to pack (this loop is based on stbtt_PackFontRangesGatherRects) - const float scale = (cfg.SizePixels > 0.0f) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels * cfg.RasterizerDensity) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -cfg.SizePixels * cfg.RasterizerDensity); + const float scale = (src.SizePixels > 0.0f) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, src.SizePixels * src.RasterizerDensity) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -src.SizePixels * src.RasterizerDensity); for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++) { int x0, y0, x1, y1; @@ -3069,7 +3069,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) // 8. Render/rasterize font characters into the texture for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) { - ImFontConfig& cfg = atlas->ConfigData[src_i]; + ImFontConfig& src = atlas->Sources[src_i]; ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; if (src_tmp.GlyphsCount == 0) continue; @@ -3077,10 +3077,10 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) stbtt_PackFontRangesRenderIntoRects(&spc, &src_tmp.FontInfo, &src_tmp.PackRange, 1, src_tmp.Rects); // Apply multiply operator - if (cfg.RasterizerMultiply != 1.0f) + if (src.RasterizerMultiply != 1.0f) { unsigned char multiply_table[256]; - ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); + ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, src.RasterizerMultiply); stbrp_rect* r = &src_tmp.Rects[0]; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++, r++) if (r->was_packed) @@ -3098,22 +3098,22 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { // When merging fonts with MergeMode=true: // - We can have multiple input fonts writing into a same destination font. - // - dst_font->ConfigData is != from cfg which is our source configuration. + // - dst_font->Sources is != from src which is our source configuration. ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; - ImFont* dst_font = cfg.DstFont; + ImFontConfig& src = atlas->Sources[src_i]; + ImFont* dst_font = src.DstFont; - const float font_scale = stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels); + const float font_scale = stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, src.SizePixels); int unscaled_ascent, unscaled_descent, unscaled_line_gap; stbtt_GetFontVMetrics(&src_tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap); const float ascent = ImCeil(unscaled_ascent * font_scale); const float descent = ImFloor(unscaled_descent * font_scale); - ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); - const float font_off_x = cfg.GlyphOffset.x; - const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); + ImFontAtlasBuildSetupFont(atlas, dst_font, &src, ascent, descent); + const float font_off_x = src.GlyphOffset.x; + const float font_off_y = src.GlyphOffset.y + IM_ROUND(dst_font->Ascent); - const float inv_rasterization_scale = 1.0f / cfg.RasterizerDensity; + const float inv_rasterization_scale = 1.0f / src.RasterizerDensity; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) { @@ -3127,7 +3127,7 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) float y0 = q.y0 * inv_rasterization_scale + font_off_y; float x1 = q.x1 * inv_rasterization_scale + font_off_x; float y1 = q.y1 * inv_rasterization_scale + font_off_y; - dst_font->AddGlyph(&cfg, (ImWchar)codepoint, x0, y0, x1, y1, q.s0, q.t0, q.s1, q.t1, pc.xadvance * inv_rasterization_scale); + dst_font->AddGlyph(&src, (ImWchar)codepoint, x0, y0, x1, y1, q.s0, q.t0, q.s1, q.t1, pc.xadvance * inv_rasterization_scale); } } @@ -3147,17 +3147,17 @@ const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype() #endif // IMGUI_ENABLE_STB_TRUETYPE -void ImFontAtlasUpdateConfigDataPointers(ImFontAtlas* atlas) +void ImFontAtlasUpdateSourcesPointers(ImFontAtlas* atlas) { - for (ImFontConfig& font_cfg : atlas->ConfigData) + for (ImFontConfig& src : atlas->Sources) { - ImFont* font = font_cfg.DstFont; - if (!font_cfg.MergeMode) + ImFont* font = src.DstFont; + if (!src.MergeMode) { - font->ConfigData = &font_cfg; - font->ConfigDataCount = 0; + font->Sources = &src; + font->SourcesCount = 0; } - font->ConfigDataCount++; + font->SourcesCount++; } } @@ -3167,7 +3167,7 @@ void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* f { font->ClearOutputData(); font->FontSize = font_config->SizePixels; - IM_ASSERT(font->ConfigData == font_config); + IM_ASSERT(font->Sources == font_config); font->ContainerAtlas = atlas; font->Ascent = ascent; font->Descent = descent; @@ -3786,7 +3786,7 @@ void ImFont::BuildLookupTable() // Setup Ellipsis character. It is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. // FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots. - const ImWchar ellipsis_chars[] = { ConfigData->EllipsisChar, (ImWchar)0x2026, (ImWchar)0x0085 }; + const ImWchar ellipsis_chars[] = { Sources->EllipsisChar, (ImWchar)0x2026, (ImWchar)0x0085 }; const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E }; if (EllipsisChar == 0) EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars)); @@ -3830,27 +3830,27 @@ void ImFont::GrowIndex(int new_size) // x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero. // Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis). -// 'cfg' is not necessarily == 'this->ConfigData' because multiple source fonts+configs can be used to build one target font. -void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) +// 'src' is not necessarily == 'this->Sources' because multiple source fonts+configs can be used to build one target font. +void ImFont::AddGlyph(const ImFontConfig* src, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) { - if (cfg != NULL) + if (src != NULL) { // Clamp & recenter if needed const float advance_x_original = advance_x; - advance_x = ImClamp(advance_x, cfg->GlyphMinAdvanceX, cfg->GlyphMaxAdvanceX); + advance_x = ImClamp(advance_x, src->GlyphMinAdvanceX, src->GlyphMaxAdvanceX); if (advance_x != advance_x_original) { - float char_off_x = cfg->PixelSnapH ? ImTrunc((advance_x - advance_x_original) * 0.5f) : (advance_x - advance_x_original) * 0.5f; + float char_off_x = src->PixelSnapH ? ImTrunc((advance_x - advance_x_original) * 0.5f) : (advance_x - advance_x_original) * 0.5f; x0 += char_off_x; x1 += char_off_x; } // Snap to pixel - if (cfg->PixelSnapH) + if (src->PixelSnapH) advance_x = IM_ROUND(advance_x); // Bake extra spacing - advance_x += cfg->GlyphExtraAdvanceX; + advance_x += src->GlyphExtraAdvanceX; } int glyph_idx = Glyphs.Size; diff --git a/imgui_internal.h b/imgui_internal.h index c4ec9cc93a25..c70bb999c595 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3577,16 +3577,16 @@ struct ImFontBuilderIO #ifdef IMGUI_ENABLE_STB_TRUETYPE IMGUI_API const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype(); #endif -IMGUI_API void ImFontAtlasUpdateConfigDataPointers(ImFontAtlas* atlas); +IMGUI_API void ImFontAtlasUpdateSourcesPointers(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas); -IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); +IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src, float ascent, float descent); IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque); IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned char in_marker_pixel_value); IMGUI_API void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value); IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor); IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride); -IMGUI_API void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* cfg, int* out_oversample_h, int* out_oversample_v); +IMGUI_API void ImFontAtlasBuildGetOversampleFactors(const ImFontConfig* src, int* out_oversample_h, int* out_oversample_v); IMGUI_API bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 875060d7f394..73b9862bcfb9 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -166,7 +166,7 @@ namespace // NB: No ctor/dtor, explicitly call Init()/Shutdown() struct FreeTypeFont { - bool InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime. + bool InitFont(FT_Library ft_library, const ImFontConfig& src, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime. void CloseFont(); void SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint); @@ -185,9 +185,9 @@ namespace float InvRasterizationDensity; }; - bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_font_builder_flags) + bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& src, unsigned int extra_font_builder_flags) { - FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &Face); + FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)src.FontData, (uint32_t)src.FontDataSize, (uint32_t)src.FontNo, &Face); if (error != 0) return false; error = FT_Select_Charmap(Face, FT_ENCODING_UNICODE); @@ -195,7 +195,7 @@ namespace return false; // Convert to FreeType flags (NB: Bold and Oblique are processed separately) - UserFlags = cfg.FontBuilderFlags | extra_font_builder_flags; + UserFlags = src.FontBuilderFlags | extra_font_builder_flags; LoadFlags = 0; if ((UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) == 0) @@ -222,11 +222,11 @@ namespace if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor) LoadFlags |= FT_LOAD_COLOR; - RasterizationDensity = cfg.RasterizerDensity; + RasterizationDensity = src.RasterizerDensity; InvRasterizationDensity = 1.0f / RasterizationDensity; memset(&Info, 0, sizeof(Info)); - SetPixelHeight((uint32_t)cfg.SizePixels); + SetPixelHeight((uint32_t)src.SizePixels); return true; } @@ -443,7 +443,7 @@ struct ImFontBuildDstDataFT bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, unsigned int extra_flags) { - IM_ASSERT(atlas->ConfigData.Size > 0); + IM_ASSERT(atlas->Sources.Size > 0); ImFontAtlasBuildInit(atlas); @@ -458,36 +458,36 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u bool src_load_color = false; ImVector src_tmp_array; ImVector dst_tmp_array; - src_tmp_array.resize(atlas->ConfigData.Size); + src_tmp_array.resize(atlas->Sources.Size); dst_tmp_array.resize(atlas->Fonts.Size); memset((void*)src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes()); memset((void*)dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes()); // 1. Initialize font loading structure, check font data validity - for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++) + for (int src_i = 0; src_i < atlas->Sources.Size; src_i++) { ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; + ImFontConfig& src = atlas->Sources[src_i]; FreeTypeFont& font_face = src_tmp.Font; - IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); + IM_ASSERT(src.DstFont && (!src.DstFont->IsLoaded() || src.DstFont->ContainerAtlas == atlas)); - // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) + // Find index from src.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) src_tmp.DstIndex = -1; for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) - if (cfg.DstFont == atlas->Fonts[output_i]) + if (src.DstFont == atlas->Fonts[output_i]) src_tmp.DstIndex = output_i; - IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array? + IM_ASSERT(src_tmp.DstIndex != -1); // src.DstFont not pointing within atlas->Fonts[] array? if (src_tmp.DstIndex == -1) return false; // Load font - if (!font_face.InitFont(ft_library, cfg, extra_flags)) + if (!font_face.InitFont(ft_library, src, extra_flags)) return false; // Measure highest codepoints - src_load_color |= (cfg.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0; + src_load_color |= (src.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0; ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault(); + src_tmp.SrcRanges = src.GlyphRanges ? src.GlyphRanges : atlas->GetGlyphRangesDefault(); for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) { // Check for valid range. This may also help detect *some* dangling pointers, because a common @@ -577,7 +577,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) { ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - ImFontConfig& cfg = atlas->ConfigData[src_i]; + ImFontConfig& src = atlas->Sources[src_i]; if (src_tmp.GlyphsCount == 0) continue; @@ -585,10 +585,10 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u buf_rects_out_n += src_tmp.GlyphsCount; // Compute multiply table if requested - const bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f); + const bool multiply_enabled = (src.RasterizerMultiply != 1.0f); unsigned char multiply_table[256]; if (multiply_enabled) - ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); + ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, src.RasterizerMultiply); // Gather the sizes of all rectangles we will need to pack for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++) @@ -687,18 +687,18 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u // When merging fonts with MergeMode=true: // - We can have multiple input fonts writing into a same destination font. - // - dst_font->ConfigData is != from cfg which is our source configuration. - ImFontConfig& cfg = atlas->ConfigData[src_i]; - ImFont* dst_font = cfg.DstFont; + // - dst_font->Sources is != from src which is our source configuration. + ImFontConfig& src = atlas->Sources[src_i]; + ImFont* dst_font = src.DstFont; const float ascent = src_tmp.Font.Info.Ascender; const float descent = src_tmp.Font.Info.Descender; - ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); + ImFontAtlasBuildSetupFont(atlas, dst_font, &src, ascent, descent); if (src_tmp.GlyphsCount == 0) continue; - const float font_off_x = cfg.GlyphOffset.x; - const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); + const float font_off_x = src.GlyphOffset.x; + const float font_off_y = src.GlyphOffset.y + IM_ROUND(dst_font->Ascent); const int padding = atlas->TexGlyphPadding; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) @@ -724,7 +724,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u float v0 = (ty) / (float)atlas->TexHeight; float u1 = (tx + info.Width) / (float)atlas->TexWidth; float v1 = (ty + info.Height) / (float)atlas->TexHeight; - dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX * src_tmp.Font.InvRasterizationDensity); + dst_font->AddGlyph(&src, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX * src_tmp.Font.InvRasterizationDensity); ImFontGlyph* dst_glyph = &dst_font->Glyphs.back(); IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint); From a86fcbd9474bb4121f25cbf9196674d79f90f1f1 Mon Sep 17 00:00:00 2001 From: Russ Gibson Date: Wed, 26 Feb 2025 05:38:08 -0800 Subject: [PATCH 487/548] Examples: SDL3+SDL_Renderer: removed reference to OpenGL to remove confusion. (#8434) --- examples/example_sdl3_sdlrenderer3/Makefile | 2 +- examples/example_sdl3_sdlrenderer3/main.cpp | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/examples/example_sdl3_sdlrenderer3/Makefile b/examples/example_sdl3_sdlrenderer3/Makefile index 2ca98654574b..c7ee64fc7712 100644 --- a/examples/example_sdl3_sdlrenderer3/Makefile +++ b/examples/example_sdl3_sdlrenderer3/Makefile @@ -44,7 +44,7 @@ endif ifeq ($(OS), Windows_NT) ECHO_MESSAGE = "MinGW" - LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl3` + LIBS += -lgdi32 -limm32 `pkg-config --static --libs sdl3` CXXFLAGS += `pkg-config --cflags sdl3` CFLAGS = $(CXXFLAGS) diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 483350fcb47a..68078eebdebd 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -15,11 +15,6 @@ #include "imgui_impl_sdlrenderer3.h" #include #include -#if defined(IMGUI_IMPL_OPENGL_ES2) -#include -#else -#include -#endif #ifdef __EMSCRIPTEN__ #include "../libs/emscripten/emscripten_mainloop_stub.h" @@ -36,7 +31,7 @@ int main(int, char**) } // Create window with SDL_Renderer graphics context - Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; + Uint32 window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+SDL_Renderer example", 1280, 720, window_flags); if (window == nullptr) { From 242d856ede78544a6ed2debea3afecad884630c6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 26 Feb 2025 14:40:41 +0100 Subject: [PATCH 488/548] Examples: SDL3+SDL_Renderer: removed reference to OpenGL to remove confusion. (#8434) Amend --- examples/example_sdl3_sdlrenderer3/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_sdl3_sdlrenderer3/Makefile b/examples/example_sdl3_sdlrenderer3/Makefile index c7ee64fc7712..1976fa924c0f 100644 --- a/examples/example_sdl3_sdlrenderer3/Makefile +++ b/examples/example_sdl3_sdlrenderer3/Makefile @@ -34,7 +34,7 @@ endif ifeq ($(UNAME_S), Darwin) #APPLE ECHO_MESSAGE = "Mac OS X" - LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl3-config --libs` + LIBS += -framework Cocoa -framework IOKit -framework CoreVideo `sdl3-config --libs` LIBS += -L/usr/local/lib -L/opt/local/lib CXXFLAGS += `pkg-config sdl3 --cflags` From 4f4fb1d220d31ca8b04163ed80bed7108e6429bc Mon Sep 17 00:00:00 2001 From: "Jose L. Hidalgo (PpluX)" Date: Sat, 22 Feb 2025 12:47:30 +0100 Subject: [PATCH 489/548] Backends: WebGPU: update code for latest webgpu-native changes. (#8426) --- backends/imgui_impl_wgpu.cpp | 22 ++++++++++++---------- docs/CHANGELOG.txt | 3 ++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index a81662d8429d..36d053e2b91b 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -17,6 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-26: Update for latest webgpu-native changes. // 2024-10-14: Update Dawn support for change of string usages. (#8082, #8083) // 2024-10-07: Expose selected render state in ImGui_ImplWGPU_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 2024-10-07: Changed default texture sampler to Clamp instead of Repeat/Wrap. @@ -65,7 +66,7 @@ using WGPUProgrammableStageDescriptor = WGPUComputeState; #endif // Dear ImGui prototypes from imgui_internal.h -extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed = 0); +extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed); #define MEMALIGN(_SIZE,_ALIGN) (((_SIZE) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align (copied from IM_ALIGN() macro). // WebGPU data @@ -267,7 +268,7 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c { ImGui_ImplWGPU_Data* bd = ImGui_ImplWGPU_GetBackendData(); -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPUShaderSourceWGSL wgsl_desc = {}; wgsl_desc.chain.sType = WGPUSType_ShaderSourceWGSL; wgsl_desc.code = { wgsl_source, WGPU_STRLEN }; @@ -282,7 +283,8 @@ static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(const c WGPUProgrammableStageDescriptor stage_desc = {}; stage_desc.module = wgpuDeviceCreateShaderModule(bd->wgpuDevice, &desc); -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN + +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) stage_desc.entryPoint = { "main", WGPU_STRLEN }; #else stage_desc.entryPoint = "main"; @@ -399,7 +401,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder { nullptr, "Dear ImGui Vertex buffer", -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPU_STRLEN, #endif WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex, @@ -426,7 +428,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder { nullptr, "Dear ImGui Index buffer", -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPU_STRLEN, #endif WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index, @@ -539,7 +541,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture() // Upload texture to graphics system { WGPUTextureDescriptor tex_desc = {}; -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) tex_desc.label = { "Dear ImGui Font Texture", WGPU_STRLEN }; #else tex_desc.label = "Dear ImGui Font Texture"; @@ -567,12 +569,12 @@ static void ImGui_ImplWGPU_CreateFontsTexture() // Upload texture data { - WGPUImageCopyTexture dst_view = {}; + WGPUTexelCopyTextureInfo dst_view = {}; dst_view.texture = bd->renderResources.FontTexture; dst_view.mipLevel = 0; dst_view.origin = { 0, 0, 0 }; dst_view.aspect = WGPUTextureAspect_All; - WGPUTextureDataLayout layout = {}; + WGPUTexelCopyBufferLayout layout = {}; layout.offset = 0; layout.bytesPerRow = width * size_pp; layout.rowsPerImage = height; @@ -606,7 +608,7 @@ static void ImGui_ImplWGPU_CreateUniformBuffer() { nullptr, "Dear ImGui Uniform buffer", -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPU_STRLEN, #endif WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform, @@ -714,7 +716,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() // Create depth-stencil State WGPUDepthStencilState depth_stencil_state = {}; depth_stencil_state.format = bd->depthStencilFormat; -#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) depth_stencil_state.depthWriteEnabled = WGPUOptionalBool_False; #else depth_stencil_state.depthWriteEnabled = false; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d5c4ded328f0..b3af5d94c2bf 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -104,8 +104,9 @@ Other changes: Default to header version if unspecified. (#8326, #8365) [@mklefrancois] - Backends: Vulkan: Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326, #8365) [@mklefrancois] -- Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. +- Backends: WebGPU: Fix for DAWN API change WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) +- Backends: WebGPU: Fix for webgpu-native API changes. (#8426) [@pplux] ----------------------------------------------------------------------- From 6aa0810de5dad4add4e73ff6352df63429f921ee Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 26 Feb 2025 15:10:28 +0100 Subject: [PATCH 490/548] Backends: WebGPU: update code for latest webgpu-native changes. Amend. (#8426) --- backends/imgui_impl_wgpu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 36d053e2b91b..45eaeba6457c 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -493,7 +493,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder { // Bind custom texture ImTextureID tex_id = pcmd->GetTexID(); - ImGuiID tex_id_hash = ImHashData(&tex_id, sizeof(tex_id)); + ImGuiID tex_id_hash = ImHashData(&tex_id, sizeof(tex_id), 0); auto bind_group = bd->renderResources.ImageBindGroups.GetVoidPtr(tex_id_hash); if (bind_group) { @@ -755,7 +755,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bg_layouts[1], bd->renderResources.FontTextureView); bd->renderResources.ImageBindGroup = image_bind_group; bd->renderResources.ImageBindGroupLayout = bg_layouts[1]; - bd->renderResources.ImageBindGroups.SetVoidPtr(ImHashData(&bd->renderResources.FontTextureView, sizeof(ImTextureID)), image_bind_group); + bd->renderResources.ImageBindGroups.SetVoidPtr(ImHashData(&bd->renderResources.FontTextureView, sizeof(ImTextureID), 0), image_bind_group); SafeRelease(vertex_shader_desc.module); SafeRelease(pixel_shader_desc.module); From 9996a2d51b47e8679936f58de31f6df382a83689 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 26 Feb 2025 15:16:38 +0100 Subject: [PATCH 491/548] Backends: WebGPU: update code for latest webgpu-native changes. Fix for Emscripten. (#8426) --- backends/imgui_impl_wgpu.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 45eaeba6457c..4fffa23a5b0c 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -569,12 +569,20 @@ static void ImGui_ImplWGPU_CreateFontsTexture() // Upload texture data { +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPUTexelCopyTextureInfo dst_view = {}; +#else + WGPUImageCopyTexture dst_view = {}; +#endif dst_view.texture = bd->renderResources.FontTexture; dst_view.mipLevel = 0; dst_view.origin = { 0, 0, 0 }; dst_view.aspect = WGPUTextureAspect_All; +#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) || defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU) WGPUTexelCopyBufferLayout layout = {}; +#else + WGPUTextureDataLayout layout = {}; +#endif layout.offset = 0; layout.bytesPerRow = width * size_pp; layout.rowsPerImage = height; From aaacb01b8d4441453928116240b5041625d43fbf Mon Sep 17 00:00:00 2001 From: "Jose L. Hidalgo (PpluX)" Date: Wed, 26 Feb 2025 15:19:56 +0100 Subject: [PATCH 492/548] Backends: WebGPU: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) --- backends/imgui_impl_wgpu.cpp | 33 ++++++++++++++++----------------- docs/CHANGELOG.txt | 2 ++ 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 4fffa23a5b0c..b04ac3bb7d63 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -17,7 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2025-02-26: Update for latest webgpu-native changes. +// 2025-02-26: Recreate image bind groups during render. (#8426, #8046, #7765, #8027) + Update for latest webgpu-native changes. // 2024-10-14: Update Dawn support for change of string usages. (#8082, #8083) // 2024-10-07: Expose selected render state in ImGui_ImplWGPU_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 2024-10-07: Changed default texture sampler to Clamp instead of Repeat/Wrap. @@ -78,7 +78,6 @@ struct RenderResources WGPUBuffer Uniforms = nullptr; // Shader uniforms WGPUBindGroup CommonBindGroup = nullptr; // Resources bind-group to bind the common resources to pipeline ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map) - WGPUBindGroup ImageBindGroup = nullptr; // Default font-resource of Dear ImGui WGPUBindGroupLayout ImageBindGroupLayout = nullptr; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM }; @@ -252,7 +251,6 @@ static void SafeRelease(RenderResources& res) SafeRelease(res.Sampler); SafeRelease(res.Uniforms); SafeRelease(res.CommonBindGroup); - SafeRelease(res.ImageBindGroup); SafeRelease(res.ImageBindGroupLayout); }; @@ -494,17 +492,13 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder // Bind custom texture ImTextureID tex_id = pcmd->GetTexID(); ImGuiID tex_id_hash = ImHashData(&tex_id, sizeof(tex_id), 0); - auto bind_group = bd->renderResources.ImageBindGroups.GetVoidPtr(tex_id_hash); - if (bind_group) + WGPUBindGroup bind_group = (WGPUBindGroup)bd->renderResources.ImageBindGroups.GetVoidPtr(tex_id_hash); + if (!bind_group) { - wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, nullptr); - } - else - { - WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bd->renderResources.ImageBindGroupLayout, (WGPUTextureView)tex_id); - bd->renderResources.ImageBindGroups.SetVoidPtr(tex_id_hash, image_bind_group); - wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, image_bind_group, 0, nullptr); + bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bd->renderResources.ImageBindGroupLayout, (WGPUTextureView)tex_id); + bd->renderResources.ImageBindGroups.SetVoidPtr(tex_id_hash, bind_group); } + wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, nullptr); // Project scissor/clipping rectangles into framebuffer space ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); @@ -526,6 +520,16 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder global_idx_offset += draw_list->IdxBuffer.Size; global_vtx_offset += draw_list->VtxBuffer.Size; } + + // Remove all ImageBindGroups + ImGuiStorage& image_bind_groups = bd->renderResources.ImageBindGroups; + for (int i = 0; i < image_bind_groups.Data.Size; i++) + { + WGPUBindGroup bind_group = (WGPUBindGroup)image_bind_groups.Data[i].val_p; + SafeRelease(bind_group); + } + image_bind_groups.Data.resize(0); + platform_io.Renderer_RenderState = nullptr; } @@ -759,11 +763,7 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() common_bg_descriptor.entryCount = sizeof(common_bg_entries) / sizeof(WGPUBindGroupEntry); common_bg_descriptor.entries = common_bg_entries; bd->renderResources.CommonBindGroup = wgpuDeviceCreateBindGroup(bd->wgpuDevice, &common_bg_descriptor); - - WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bg_layouts[1], bd->renderResources.FontTextureView); - bd->renderResources.ImageBindGroup = image_bind_group; bd->renderResources.ImageBindGroupLayout = bg_layouts[1]; - bd->renderResources.ImageBindGroups.SetVoidPtr(ImHashData(&bd->renderResources.FontTextureView, sizeof(ImTextureID), 0), image_bind_group); SafeRelease(vertex_shader_desc.module); SafeRelease(pixel_shader_desc.module); @@ -823,7 +823,6 @@ bool ImGui_ImplWGPU_Init(ImGui_ImplWGPU_InitInfo* init_info) bd->renderResources.Uniforms = nullptr; bd->renderResources.CommonBindGroup = nullptr; bd->renderResources.ImageBindGroups.Data.reserve(100); - bd->renderResources.ImageBindGroup = nullptr; bd->renderResources.ImageBindGroupLayout = nullptr; // Create buffers with a default size (they will later be grown as needed) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b3af5d94c2bf..ff249c140cd8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -104,6 +104,8 @@ Other changes: Default to header version if unspecified. (#8326, #8365) [@mklefrancois] - Backends: Vulkan: Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326, #8365) [@mklefrancois] +- Backends: WebGPU: Recreate image bind groups during render to allow reuse of + WGPUTextureView pointers. (#8426, #8046, #7765, #8027) [@pplux, @Jairard] - Backends: WebGPU: Fix for DAWN API change WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) - Backends: WebGPU: Fix for webgpu-native API changes. (#8426) [@pplux] From aa83d5d455dcab4b65cca71efd6291f943feea67 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 26 Feb 2025 15:34:31 +0100 Subject: [PATCH 493/548] Backends: SDL2, SDL3: Only start SDL_CaptureMouse() when mouse is being dragged. (#6410, #3650) To mitigate issues with e.g. Linux debuggers not claiming capture back. --- backends/imgui_impl_sdl2.cpp | 11 +++++++++-- backends/imgui_impl_sdl3.cpp | 11 +++++++++-- docs/CHANGELOG.txt | 2 ++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 361fc3b57e3f..6256b4dddec4 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650) // 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. @@ -609,8 +610,14 @@ static void ImGui_ImplSDL2_UpdateMouseData() // We forward mouse input when hovered or captured (via SDL_MOUSEMOTION) or when focused (below) #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE - // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside - SDL_CaptureMouse((bd->MouseButtonsDown != 0) ? SDL_TRUE : SDL_FALSE); + // - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside. + // - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to migitate the issue we wait until mouse has moved to begin capture. + bool want_capture = false; + for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++) + if (ImGui::IsMouseDragging(button_n, 1.0f)) + want_capture = true; + SDL_CaptureMouse(want_capture ? SDL_TRUE : SDL_FALSE); + SDL_Window* focused_window = SDL_GetKeyboardFocus(); const bool is_app_focused = (bd->Window == focused_window); #else diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index d2433793e609..2d8027184b60 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650) // 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. @@ -574,8 +575,14 @@ static void ImGui_ImplSDL3_UpdateMouseData() // We forward mouse input when hovered or captured (via SDL_EVENT_MOUSE_MOTION) or when focused (below) #if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE - // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside - SDL_CaptureMouse(bd->MouseButtonsDown != 0); + // - SDL_CaptureMouse() let the OS know e.g. that our drags can extend outside of parent boundaries (we want updated position) and shouldn't trigger other operations outside. + // - Debuggers under Linux tends to leave captured mouse on break, which may be very inconvenient, so to migitate the issue we wait until mouse has moved to begin capture. + bool want_capture = false; + for (int button_n = 0; button_n < ImGuiMouseButton_COUNT && !want_capture; button_n++) + if (ImGui::IsMouseDragging(button_n, 1.0f)) + want_capture = true; + SDL_CaptureMouse(want_capture); + SDL_Window* focused_window = SDL_GetKeyboardFocus(); const bool is_app_focused = (bd->Window == focused_window); #else diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ff249c140cd8..5a1b63ad2895 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -95,6 +95,8 @@ Other changes: and ImGuiMouseCursor_Progress cursors. - Backends: SDL2, SDL3: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. (#8425, #8407) [@TheMode] +- Backends: SDL2, SDL3: Only start SDL_CaptureMouse() when mouse is being dragged, + to mitigate issues with e.g. Linux debuggers not claiming capture back. (#6410, #3650) - Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) - Backends: DirectX12: Fixed an issue where pre-1.91.5 legacy ImGui_ImplDX12_Init() From 8bd3e20c86b1541f1da2c1f1d2444220432193fa Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 26 Feb 2025 18:06:31 -0500 Subject: [PATCH 494/548] Backends: WebGPU: include imgui.h before backend check (#8437) --- backends/imgui_impl_wgpu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index b04ac3bb7d63..4bf03e8f1b0c 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -41,6 +41,8 @@ // 2021-02-18: Change blending equation to preserve alpha in output buffer. // 2021-01-28: Initial version. +#include "imgui.h" + // When targeting native platforms (i.e. NOT emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN // or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details. #ifndef __EMSCRIPTEN__ @@ -53,7 +55,6 @@ #endif #endif -#include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_impl_wgpu.h" #include From cdafefd4be389ef4c6747b102086278b2cc355c3 Mon Sep 17 00:00:00 2001 From: Alan Date: Thu, 27 Feb 2025 07:47:33 -0500 Subject: [PATCH 495/548] Backends: WebGPU: Add nextInChain field for VertexAttributes under Dawn (#8438) --- backends/imgui_impl_wgpu.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 4bf03e8f1b0c..3187be29a39f 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -687,9 +687,15 @@ bool ImGui_ImplWGPU_CreateDeviceObjects() // Vertex input configuration WGPUVertexAttribute attribute_desc[] = { +#ifdef IMGUI_IMPL_WEBGPU_BACKEND_DAWN + { nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 }, + { nullptr, WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 }, + { nullptr, WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 }, +#else { WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, pos), 0 }, { WGPUVertexFormat_Float32x2, (uint64_t)offsetof(ImDrawVert, uv), 1 }, { WGPUVertexFormat_Unorm8x4, (uint64_t)offsetof(ImDrawVert, col), 2 }, +#endif }; WGPUVertexBufferLayout buffer_layouts[1]; From 494ea57b65325f00165da10e6b57b4f295a65bca Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 27 Feb 2025 19:28:01 +0100 Subject: [PATCH 496/548] Image: removed 'tint_col', 'border_col' parameters from Image(). Added ImageWithBg(). Added style.ImageBorderSize, ImGuiStyleVar_ImageBorderSize. (#8131, #8238) Displaying a black background behind Font Atlas texture. --- docs/CHANGELOG.txt | 18 ++++++++++++++++++ imgui.cpp | 23 ++++++++++++++++++----- imgui.h | 11 ++++++++--- imgui_demo.cpp | 11 +++++------ imgui_internal.h | 1 - imgui_widgets.cpp | 30 +++++++++++++++++++++++++----- 6 files changed, 74 insertions(+), 20 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5a1b63ad2895..9e797e3ec22d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,22 @@ HOW TO UPDATE? Breaking changes: +- Image: removed 'tint_col' and 'border_col' parameter from Image() function. (#8131, #8238) + - Old function signature: + void Image (ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1), ImVec4 tint_col = (1,1,1,1), ImVec4 border_col = (0,0,0,0)); + - New function signatures: + void Image (ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1)); + void ImageWithBg(ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1), ImVec4 bg_col = (0,0,0,0), ImVec4 tint_col = (1,1,1,1)); + - TL;DR: 'border_col' had misleading side-effect on layout, 'bg_col' was missing, parameter order couldn't be consistent with ImageButton(). + - New behavior always use ImGuiCol_Border color + style.ImageBorderSize / ImGuiStyleVar_ImageBorderSize. + - Old behavior altered border size (and therefore layout) based on border color's + alpha, which caused variety of problems. + - Old behavior used a fixed value of 1.0f for border size which was not tweakable. + - Kept legacy signature (will obsolete), which mimics the old behavior, + but uses Max(1.0f, style.ImageBorderSize) when border_col is specified. + - Added ImageWithBg() function which has both 'bg_col' (which was missing) and 'tint_col'. + It was impossible to add 'bg_col' to Image() with a parameter order consistent with + other functions, so we decided to remove 'tint_col' and introduce ImageWithBg(). - Renamed ImFontConfig::GlyphExtraSpacing.x option to GlyphExtraAdvanceX. (#242) - Renamed style.TabMinWidthForCloseButton to style.TabCloseButtonMinWidthUnselected. - Backends: Vulkan: Added 'uint32_t api_version' argument to ImGui_ImplVulkan_LoadFunctions(). @@ -70,6 +86,8 @@ Other changes: - Tables: tamed some .ini settings optimizations to more accurately allow overwriting/hot-reloading settings in more situations. (#7934) - Tables, Error Handling: Recovery from invalid index in TableSetColumnIndex(). (#1651) +- Image: Added ImageWithBg() variant with bg color and tint color. (#8131, #8238) +- Image, Style: Added style.ImageBorderSize, ImGuiStyleVar_ImageBorderSize. (#8131, #8238) - Selectable: Fixed horizontal label alignment with SelectableTextAlign.x > 0 and specifying a selectable size. (#8338) - Tabs, Style: made the Close Button of selected tabs always visible by default, diff --git a/imgui.cpp b/imgui.cpp index 64514028ff86..6e038fad8730 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -431,6 +431,15 @@ 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. + - 2025/02/27 (1.91.9) - Image(): removed 'tint_col' and 'border_col' parameter from Image() function. Added ImageWithBg() replacement. (#8131, #8238) + - old: void Image (ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1), ImVec4 tint_col = (1,1,1,1), ImVec4 border_col = (0,0,0,0)); + - new: void Image (ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1)); + - new: void ImageWithBg(ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1), ImVec4 bg_col = (0,0,0,0), ImVec4 tint_col = (1,1,1,1)); + - TL;DR: 'border_col' had misleading side-effect on layout, 'bg_col' was missing, parameter order couldn't be consistent with ImageButton(). + - new behavior always use ImGuiCol_Border color + style.ImageBorderSize / ImGuiStyleVar_ImageBorderSize. + - old behavior altered border size (and therefore layout) based on border color's alpha, which caused variety of problems + old behavior a fixed 1.0f for border size which was not tweakable. + - kept legacy signature (will obsolete), which mimics the old behavior, but uses Max(1.0f, style.ImageBorderSize) when border_col is specified. + - added ImageWithBg() function which has both 'bg_col' (which was missing) and 'tint_col'. It was impossible to add 'bg_col' to Image() with a parameter order consistent with other functions, so we decided to remove 'tint_col' and introduce ImageWithBg(). - 2025/02/06 (1.91.9) - renamed ImFontConfig::GlyphExtraSpacing.x to ImFontConfig::GlyphExtraAdvanceX. - 2025/01/22 (1.91.8) - removed ImGuiColorEditFlags_AlphaPreview (made value 0): it is now the default behavior. prior to 1.91.8: alpha was made opaque in the preview by default _unless_ using ImGuiColorEditFlags_AlphaPreview. We now display the preview as transparent by default. You can use ImGuiColorEditFlags_AlphaOpaque to use old behavior. @@ -1338,6 +1347,7 @@ ImGuiStyle::ImGuiStyle() GrabMinSize = 12.0f; // Minimum width/height of a grab box for slider/scrollbar GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. + ImageBorderSize = 0.0f; // Thickness of border around tabs. TabRounding = 5.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. TabBorderSize = 0.0f; // Thickness of border around tabs. TabCloseButtonMinWidthSelected = -1.0f; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. @@ -1395,6 +1405,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor) GrabMinSize = ImTrunc(GrabMinSize * scale_factor); GrabRounding = ImTrunc(GrabRounding * scale_factor); LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor); + ImageBorderSize = ImTrunc(ImageBorderSize * scale_factor); TabRounding = ImTrunc(TabRounding * scale_factor); TabCloseButtonMinWidthSelected = (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor) : TabCloseButtonMinWidthSelected; TabCloseButtonMinWidthUnselected = (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor) : TabCloseButtonMinWidthUnselected; @@ -3393,6 +3404,7 @@ static const ImGuiDataVarInfo GStyleVarsInfo[] = { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding + { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ImageBorderSize) }, // ImGuiStyleVar_ImageBorderSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBorderSize) }, // ImGuiStyleVar_TabBorderSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarBorderSize) }, // ImGuiStyleVar_TabBarBorderSize @@ -15422,11 +15434,12 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas) if (TreeNode("Font Atlas", "Font Atlas (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight)) { ImGuiContext& g = *GImGui; - ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig; - Checkbox("Tint with Text Color", &cfg->ShowAtlasTintedWithTextColor); // Using text color ensure visibility of core atlas data, but will alter custom colored icons - ImVec4 tint_col = cfg->ShowAtlasTintedWithTextColor ? GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); - ImVec4 border_col = GetStyleColorVec4(ImGuiCol_Border); - Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col); + PushStyleVar(ImGuiStyleVar_ImageBorderSize, ImMax(1.0f, g.Style.ImageBorderSize)); + ImVec2 image_pos = GetCursorScreenPos(); + ImVec2 image_size((float)atlas->TexWidth, (float)atlas->TexHeight); + GetWindowDrawList()->AddRectFilled(image_pos, image_pos + image_size + ImVec2(g.Style.ImageBorderSize, g.Style.ImageBorderSize), IM_COL32(0, 0, 0, 255)); + Image(atlas->TexID, image_size); + PopStyleVar(); TreePop(); } } diff --git a/imgui.h b/imgui.h index 1bdc2cb10b13..ee9697ea8b84 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.9 WIP" -#define IMGUI_VERSION_NUM 19184 +#define IMGUI_VERSION_NUM 19185 #define IMGUI_HAS_TABLE /* @@ -566,9 +566,10 @@ namespace ImGui // Widgets: Images // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples // - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above. - // - Note that Image() may add +2.0f to provided size if a border is visible, ImageButton() adds style.FramePadding*2.0f to provided size. + // - Image() pads adds style.ImageBorderSize on each side, ImageButton() adds style.FramePadding on each side. // - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. - IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0)); + IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1)); + IMGUI_API void ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Widgets: Combo Box (Dropdown) @@ -1714,6 +1715,7 @@ enum ImGuiStyleVar_ ImGuiStyleVar_ScrollbarRounding, // float ScrollbarRounding ImGuiStyleVar_GrabMinSize, // float GrabMinSize ImGuiStyleVar_GrabRounding, // float GrabRounding + ImGuiStyleVar_ImageBorderSize, // float ImageBorderSize ImGuiStyleVar_TabRounding, // float TabRounding ImGuiStyleVar_TabBorderSize, // float TabBorderSize ImGuiStyleVar_TabBarBorderSize, // float TabBarBorderSize @@ -2170,6 +2172,7 @@ struct ImGuiStyle float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar. float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. float LogSliderDeadzone; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. + float ImageBorderSize; // Thickness of border around Image() calls. float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. float TabBorderSize; // Thickness of border around tabs. float TabCloseButtonMinWidthSelected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. @@ -3614,6 +3617,8 @@ struct ImGuiPlatformImeData #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + // OBSOLETED in 1.91.9 (from February 2025) + IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col); // <-- border_col was removed in favor of ImGuiCol_ImageBorder. // OBSOLETED in 1.91.0 (from July 2024) static inline void PushButtonRepeat(bool repeat) { PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); } static inline void PopButtonRepeat() { PopItemFlag(); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3be8647248d0..4372dfb4555c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1348,15 +1348,12 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) float my_tex_w = (float)io.Fonts->TexWidth; float my_tex_h = (float)io.Fonts->TexHeight; { - static bool use_text_color_for_tint = false; - ImGui::Checkbox("Use Text Color for Tint", &use_text_color_for_tint); ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h); ImVec2 pos = ImGui::GetCursorScreenPos(); ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right - ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint - ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border); - ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col); + ImGui::PushStyleVar(ImGuiStyleVar_ImageBorderSize, IM_MAX(1.0f, ImGui::GetStyle().ImageBorderSize)); + ImGui::ImageWithBg(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); if (ImGui::BeginItemTooltip()) { float region_sz = 32.0f; @@ -1371,9 +1368,10 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz); ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h); ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h); - ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, tint_col, border_col); + ImGui::ImageWithBg(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); ImGui::EndTooltip(); } + ImGui::PopStyleVar(); } IMGUI_DEMO_MARKER("Widgets/Images/Textured buttons"); @@ -8031,6 +8029,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat2("SeparatorTextAlign", (float*)&style.SeparatorTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SliderFloat2("SeparatorTextPadding", (float*)&style.SeparatorTextPadding, 0.0f, 40.0f, "%.0f"); ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f"); + ImGui::SliderFloat("ImageBorderSize", &style.ImageBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SeparatorText("Tooltips"); for (int n = 0; n < 2; n++) diff --git a/imgui_internal.h b/imgui_internal.h index c70bb999c595..985f8b1890c5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1998,7 +1998,6 @@ struct ImGuiMetricsConfig bool ShowDrawCmdMesh = true; bool ShowDrawCmdBoundingBoxes = true; bool ShowTextEncodingViewer = false; - bool ShowAtlasTintedWithTextColor = false; int ShowWindowsRectsType = -1; int ShowTablesRectsType = -1; int HighlightMonitorIdx = -1; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f011805f98d1..8d5aa9581d76 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1062,25 +1062,45 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples // - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above. -void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) +void ImGui::ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col) { + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; - const float border_size = (border_col.w > 0.0f) ? 1.0f : 0.0f; - const ImVec2 padding(border_size, border_size); + const ImVec2 padding(g.Style.ImageBorderSize, g.Style.ImageBorderSize); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + image_size + padding * 2.0f); ItemSize(bb); if (!ItemAdd(bb, 0)) return; // Render - if (border_size > 0.0f) - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f, ImDrawFlags_None, border_size); + if (g.Style.ImageBorderSize > 0.0f) + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), 0.0f, ImDrawFlags_None, g.Style.ImageBorderSize); + if (bg_col.w > 0.0f) + window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col)); window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col)); } +void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1) +{ + ImageWithBg(user_texture_id, image_size, uv0, uv1); +} + +// 1.91.9 (February 2025) removed 'tint_col' and 'border_col' parameters, made border size not depend on color value. (#8131, #8238) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS +void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) +{ + ImGuiContext& g = *GImGui; + PushStyleVar(ImGuiStyleVar_ImageBorderSize, (border_col.w > 0.0f) ? ImMax(1.0f, g.Style.ImageBorderSize) : 0.0f); // Preserve legacy behavior where border is always visible when border_col's Alpha is >0.0f + PushStyleColor(ImGuiCol_Border, border_col); + ImageWithBg(user_texture_id, image_size, uv0, uv1, ImVec4(0, 0, 0, 0), tint_col); + PopStyleColor(); + PopStyleVar(); +} +#endif + bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags) { ImGuiContext& g = *GImGui; From 482a1f50b61ee71b515a5a4a1c5f6a998214780a Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 27 Feb 2025 16:08:51 +0100 Subject: [PATCH 497/548] Internals: rename ImGuiDataVarInfo to ImGuiStyleVarInfo. Move ImGuiStyleMod, ImGuiColorMod to own section. # Conflicts: # imgui.cpp --- imgui.cpp | 90 ++++++++++++++++++++++++------------------------ imgui.h | 2 ++ imgui_internal.h | 49 ++++++++++++++------------ 3 files changed, 74 insertions(+), 67 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6e038fad8730..30477001f6e4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3380,45 +3380,45 @@ void ImGui::PopStyleColor(int count) } } -static const ImGuiDataVarInfo GStyleVarsInfo[] = -{ - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, DisabledAlpha) }, // ImGuiStyleVar_DisabledAlpha - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, CellPadding) }, // ImGuiStyleVar_CellPadding - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ImageBorderSize) }, // ImGuiStyleVar_ImageBorderSize - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBorderSize) }, // ImGuiStyleVar_TabBorderSize - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarBorderSize) }, // ImGuiStyleVar_TabBarBorderSize - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarOverlineSize) }, // ImGuiStyleVar_TabBarOverlineSize - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersAngle)}, // ImGuiStyleVar_TableAngledHeadersAngle - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign - { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)}, // ImGuiStyleVar_SeparatorTextBorderSize - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) }, // ImGuiStyleVar_SeparatorTextAlign - { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) }, // ImGuiStyleVar_SeparatorTextPadding +static const ImGuiStyleVarInfo GStyleVarsInfo[] = +{ + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, DisabledAlpha) }, // ImGuiStyleVar_DisabledAlpha + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, CellPadding) }, // ImGuiStyleVar_CellPadding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ImageBorderSize) }, // ImGuiStyleVar_ImageBorderSize + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TabBorderSize) }, // ImGuiStyleVar_TabBorderSize + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TabBarBorderSize) }, // ImGuiStyleVar_TabBarBorderSize + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TabBarOverlineSize) }, // ImGuiStyleVar_TabBarOverlineSize + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersAngle)}, // ImGuiStyleVar_TableAngledHeadersAngle + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign + { 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)}, // ImGuiStyleVar_SeparatorTextBorderSize + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) }, // ImGuiStyleVar_SeparatorTextAlign + { 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) }, // ImGuiStyleVar_SeparatorTextPadding }; -const ImGuiDataVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx) +const ImGuiStyleVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx) { IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT); IM_STATIC_ASSERT(IM_ARRAYSIZE(GStyleVarsInfo) == ImGuiStyleVar_COUNT); @@ -3428,7 +3428,7 @@ const ImGuiDataVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx) void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) { ImGuiContext& g = *GImGui; - const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); + const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 1) { IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); @@ -3442,7 +3442,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) void ImGui::PushStyleVarX(ImGuiStyleVar idx, float val_x) { ImGuiContext& g = *GImGui; - const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); + const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2) { IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); @@ -3456,7 +3456,7 @@ void ImGui::PushStyleVarX(ImGuiStyleVar idx, float val_x) void ImGui::PushStyleVarY(ImGuiStyleVar idx, float val_y) { ImGuiContext& g = *GImGui; - const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); + const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2) { IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); @@ -3470,7 +3470,7 @@ void ImGui::PushStyleVarY(ImGuiStyleVar idx, float val_y) void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) { ImGuiContext& g = *GImGui; - const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); + const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); if (var_info->DataType != ImGuiDataType_Float || var_info->Count != 2) { IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); @@ -3493,10 +3493,10 @@ void ImGui::PopStyleVar(int count) { // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it. ImGuiStyleMod& backup = g.StyleVarStack.back(); - const ImGuiDataVarInfo* info = GetStyleVarInfo(backup.VarIdx); - void* data = info->GetVarPtr(&g.Style); - if (info->DataType == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; } - else if (info->DataType == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; } + const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(backup.VarIdx); + void* data = var_info->GetVarPtr(&g.Style); + if (var_info->DataType == ImGuiDataType_Float && var_info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; } + else if (var_info->DataType == ImGuiDataType_Float && var_info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; } g.StyleVarStack.pop_back(); count--; } diff --git a/imgui.h b/imgui.h index ee9697ea8b84..caf8088b2938 100644 --- a/imgui.h +++ b/imgui.h @@ -2195,6 +2195,8 @@ struct ImGuiStyle bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. float CircleTessellationMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. + + // Colors ImVec4 Colors[ImGuiCol_COUNT]; // Behaviors diff --git a/imgui_internal.h b/imgui_internal.h index 985f8b1890c5..f896171cd0d7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -14,6 +14,7 @@ Index of this file: // [SECTION] Macros // [SECTION] Generic helpers // [SECTION] ImDrawList support +// [SECTION] Style support // [SECTION] Data types support // [SECTION] Widgets support: flags, enums, data structures // [SECTION] Popup support @@ -145,7 +146,6 @@ struct ImGuiBoxSelectState; // Box-selection state (currently used by mu struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it struct ImGuiContext; // Main Dear ImGui context struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine -struct ImGuiDataVarInfo; // Variable information (e.g. to access style variables from an enum) struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum struct ImGuiDeactivatedItemData; // Data for IsItemDeactivated()/IsItemDeactivatedAfterEdit() function. struct ImGuiErrorRecoveryState; // Storage of stack sizes for error handling and recovery @@ -166,6 +166,7 @@ struct ImGuiOldColumns; // Storage data for a columns set for legacy struct ImGuiPopupData; // Storage for current popup stack struct ImGuiSettingsHandler; // Storage for one type registered in the .ini file struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it +struct ImGuiStyleVarInfo; // Style variable information (e.g. to access style variables from an enum) struct ImGuiTabBar; // Storage for a tab bar struct ImGuiTabItem; // Storage for a tab item (within a tab bar) struct ImGuiTable; // Storage for a table @@ -809,17 +810,38 @@ struct ImDrawDataBuilder }; //----------------------------------------------------------------------------- -// [SECTION] Data types support +// [SECTION] Style support //----------------------------------------------------------------------------- -struct ImGuiDataVarInfo +struct ImGuiStyleVarInfo { - ImGuiDataType DataType : 8; ImU32 Count : 8; // 1+ + ImGuiDataType DataType : 8; ImU32 Offset : 16; // Offset in parent structure void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); } }; +// Stacked color modifier, backup of modified data so we can restore it +struct ImGuiColorMod +{ + ImGuiCol Col; + ImVec4 BackupValue; +}; + +// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. +struct ImGuiStyleMod +{ + ImGuiStyleVar VarIdx; + union { int BackupInt[2]; float BackupFloat[2]; }; + ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; } + ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; } + ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; } +}; + +//----------------------------------------------------------------------------- +// [SECTION] Data types support +//----------------------------------------------------------------------------- + struct ImGuiDataTypeStorage { ImU8 Data[8]; // Opaque storage to fit any data up to ImGuiDataType_COUNT @@ -1038,23 +1060,6 @@ enum ImGuiPlotType ImGuiPlotType_Histogram, }; -// Stacked color modifier, backup of modified data so we can restore it -struct ImGuiColorMod -{ - ImGuiCol Col; - ImVec4 BackupValue; -}; - -// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. -struct ImGuiStyleMod -{ - ImGuiStyleVar VarIdx; - union { int BackupInt[2]; float BackupFloat[2]; }; - ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; } - ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; } - ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; } -}; - // Storage data for BeginComboPreview()/EndComboPreview() struct IMGUI_API ImGuiComboPreviewData { @@ -3114,7 +3119,7 @@ namespace ImGui IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); // Parameter stacks (shared) - IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx); + IMGUI_API const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx); IMGUI_API void BeginDisabledOverrideReenable(); IMGUI_API void EndDisabledOverrideReenable(); From 1aab00da8589d06ed861a0b40e9dfaeff791084f Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 27 Feb 2025 21:55:17 +0100 Subject: [PATCH 498/548] Misc shallow tweaks/tidying up. (#8446) --- backends/imgui_impl_dx10.cpp | 11 ++++------- backends/imgui_impl_dx11.cpp | 11 ++++------- backends/imgui_impl_dx12.cpp | 27 +++++++++------------------ backends/imgui_impl_metal.h | 1 + backends/imgui_impl_opengl3.cpp | 2 +- backends/imgui_impl_osx.h | 1 + 6 files changed, 20 insertions(+), 33 deletions(-) diff --git a/backends/imgui_impl_dx10.cpp b/backends/imgui_impl_dx10.cpp index 5471eef5311c..801983211aba 100644 --- a/backends/imgui_impl_dx10.cpp +++ b/backends/imgui_impl_dx10.cpp @@ -87,8 +87,7 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData(); // Setup viewport - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + D3D10_VIEWPORT vp = {}; vp.Width = (UINT)draw_data->DisplaySize.x; vp.Height = (UINT)draw_data->DisplaySize.y; vp.MinDepth = 0.0f; @@ -152,8 +151,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) { if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; - D3D10_BUFFER_DESC desc; - memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + D3D10_BUFFER_DESC desc = {}; desc.Usage = D3D10_USAGE_DYNAMIC; desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert); desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; @@ -167,8 +165,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) { if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC desc; - memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + D3D10_BUFFER_DESC desc = {}; desc.Usage = D3D10_USAGE_DYNAMIC; desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx); desc.BindFlags = D3D10_BIND_INDEX_BUFFER; @@ -431,7 +428,7 @@ bool ImGui_ImplDX10_CreateDeviceObjects() // Create the constant buffer { - D3D10_BUFFER_DESC desc; + D3D10_BUFFER_DESC desc = {}; desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX10); desc.Usage = D3D10_USAGE_DYNAMIC; desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index b38fece264b5..9f39588810eb 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -90,8 +90,7 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); // Setup viewport - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + D3D11_VIEWPORT vp = {}; vp.Width = draw_data->DisplaySize.x; vp.Height = draw_data->DisplaySize.y; vp.MinDepth = 0.0f; @@ -158,8 +157,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) { if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; - D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + D3D11_BUFFER_DESC desc = {}; desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert); desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; @@ -172,8 +170,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) { if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + D3D11_BUFFER_DESC desc = {}; desc.Usage = D3D11_USAGE_DYNAMIC; desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx); desc.BindFlags = D3D11_BIND_INDEX_BUFFER; @@ -447,7 +444,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects() // Create the constant buffer { - D3D11_BUFFER_DESC desc; + D3D11_BUFFER_DESC desc = {}; desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX11); desc.Usage = D3D11_USAGE_DYNAMIC; desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 8449832c5b09..e9a2c119c4b6 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -137,8 +137,7 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic } // Setup viewport - D3D12_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D12_VIEWPORT)); + D3D12_VIEWPORT vp = {}; vp.Width = draw_data->DisplaySize.x; vp.Height = draw_data->DisplaySize.y; vp.MinDepth = 0.0f; @@ -149,14 +148,12 @@ static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12Graphic // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - D3D12_VERTEX_BUFFER_VIEW vbv; - memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW)); + D3D12_VERTEX_BUFFER_VIEW vbv = {}; vbv.BufferLocation = fr->VertexBuffer->GetGPUVirtualAddress() + offset; vbv.SizeInBytes = fr->VertexBufferSize * stride; vbv.StrideInBytes = stride; command_list->IASetVertexBuffers(0, 1, &vbv); - D3D12_INDEX_BUFFER_VIEW ibv; - memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW)); + D3D12_INDEX_BUFFER_VIEW ibv = {}; ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress(); ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx); ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; @@ -196,13 +193,11 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL { SafeRelease(fr->VertexBuffer); fr->VertexBufferSize = draw_data->TotalVtxCount + 5000; - D3D12_HEAP_PROPERTIES props; - memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES)); + D3D12_HEAP_PROPERTIES props = {}; props.Type = D3D12_HEAP_TYPE_UPLOAD; props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; - D3D12_RESOURCE_DESC desc; - memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC)); + D3D12_RESOURCE_DESC desc = {}; desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; desc.Width = fr->VertexBufferSize * sizeof(ImDrawVert); desc.Height = 1; @@ -219,13 +214,11 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL { SafeRelease(fr->IndexBuffer); fr->IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D12_HEAP_PROPERTIES props; - memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES)); + D3D12_HEAP_PROPERTIES props = {}; props.Type = D3D12_HEAP_TYPE_UPLOAD; props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; - D3D12_RESOURCE_DESC desc; - memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC)); + D3D12_RESOURCE_DESC desc = {}; desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; desc.Width = fr->IndexBufferSize * sizeof(ImDrawIdx); desc.Height = 1; @@ -333,8 +326,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() // Upload texture to graphics system ImGui_ImplDX12_Texture* font_tex = &bd->FontTexture; { - D3D12_HEAP_PROPERTIES props; - memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES)); + D3D12_HEAP_PROPERTIES props = {}; props.Type = D3D12_HEAP_TYPE_DEFAULT; props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; @@ -561,8 +553,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects() // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. // See https://github.com/ocornut/imgui/pull/638 for sources and details. - D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc; - memset(&psoDesc, 0, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC)); + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; psoDesc.NodeMask = 1; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.pRootSignature = bd->pRootSignature; diff --git a/backends/imgui_impl_metal.h b/backends/imgui_impl_metal.h index 351c2eff735c..d46998269cea 100644 --- a/backends/imgui_impl_metal.h +++ b/backends/imgui_impl_metal.h @@ -13,6 +13,7 @@ // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). // - Introduction, links and more at the top of imgui.cpp +#pragma once #include "imgui.h" // IMGUI_IMPL_API #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 14ae90a7e122..1311d1bc9f0e 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -284,7 +284,7 @@ bool ImGui_ImplOpenGL3_InitLoader() { // Initialize our loader #ifdef IMGUI_IMPL_OPENGL_LOADER_IMGL3W - if (glGetIntegerv == NULL && imgl3wInit() != 0) + if (glGetIntegerv == nullptr && imgl3wInit() != 0) { fprintf(stderr, "Failed to initialize OpenGL loader!\n"); return false; diff --git a/backends/imgui_impl_osx.h b/backends/imgui_impl_osx.h index 9d0aec07a0fc..5d4dd8d41b7f 100644 --- a/backends/imgui_impl_osx.h +++ b/backends/imgui_impl_osx.h @@ -21,6 +21,7 @@ // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). // - Introduction, links and more at the top of imgui.cpp +#pragma once #include "imgui.h" // IMGUI_IMPL_API #ifndef IMGUI_DISABLE From 9c2876b9f8f3859951390f27186527393001fe20 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 27 Feb 2025 22:04:56 +0100 Subject: [PATCH 499/548] ShowFontAtlas() uses ImageWithBg(). (#8131, #8238) Amend 494ea57 --- imgui.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 30477001f6e4..64d447be306d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15435,10 +15435,7 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas) { ImGuiContext& g = *GImGui; PushStyleVar(ImGuiStyleVar_ImageBorderSize, ImMax(1.0f, g.Style.ImageBorderSize)); - ImVec2 image_pos = GetCursorScreenPos(); - ImVec2 image_size((float)atlas->TexWidth, (float)atlas->TexHeight); - GetWindowDrawList()->AddRectFilled(image_pos, image_pos + image_size + ImVec2(g.Style.ImageBorderSize, g.Style.ImageBorderSize), IM_COL32(0, 0, 0, 255)); - Image(atlas->TexID, image_size); + ImageWithBg(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); PopStyleVar(); TreePop(); } From c5ade6591e39216ec950136a6d8e3e3274f2bddf Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 2 Mar 2025 13:39:29 +0100 Subject: [PATCH 500/548] TextLink(), TextLinkOpenURL(): fixed honoring text baseline alignment. (#8451, #7660) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9e797e3ec22d..f7241d7de398 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -99,6 +99,8 @@ Other changes: - Default for unselected tabs: TabCloseButtonMinWidthUnselected = 0.0f (visible when hovered) - Tabs: fixed middle-mouse-button to close tab not checking that close button is hovered, merely it's visibility. (#8399, #8387) [@nicovanbentum] +- TextLink(), TextLinkOpenURL(): fixed honoring text baseline alignment. + (#8451, #7660) [@achabense] - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] - Debug Tools: Added io.ConfigDebugHighlightIdConflictsShowItemPicker (defaults to true) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 8d5aa9581d76..76dabb8f9c55 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1444,7 +1444,7 @@ bool ImGui::TextLink(const char* label) const ImGuiID id = window->GetID(label); const char* label_end = FindRenderedTextEnd(label); - ImVec2 pos = window->DC.CursorPos; + ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); ImVec2 size = CalcTextSize(label, label_end, true); ImRect bb(pos, pos + size); ItemSize(size, 0.0f); From 4819eae8674209f7ddf70cd9a8b2e10528405fff Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 2 Mar 2025 14:15:11 +0100 Subject: [PATCH 501/548] Clipper: Fixed an issue where passing an out of bound index to IncludeItemByIndex() could incorrectly offset the final cursor. One case where it would manifest was calling Combo() with an out of range index. (#8450) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f7241d7de398..0fd46d378274 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -103,6 +103,9 @@ Other changes: (#8451, #7660) [@achabense] - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] +- Clipper: Fixed an issue where passing an out of bound index to IncludeItemByIndex() + could incorrectly offset the final cursor, even if that index was not iterated through. + One case where it would manifest was calling Combo() with an out of range index. (#8450) - Debug Tools: Added io.ConfigDebugHighlightIdConflictsShowItemPicker (defaults to true) to allow disabled Item Picker suggestion in user facing builds. (#7961, #7669) - Misc: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursors diff --git a/imgui.cpp b/imgui.cpp index 64d447be306d..77e3c1d36422 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3258,11 +3258,11 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) { clipper->DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted); clipper->DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, clipper->ItemsCount); - if (clipper->DisplayStart > already_submitted) //-V1051 - clipper->SeekCursorForItem(clipper->DisplayStart); data->StepNo++; - if (clipper->DisplayStart == clipper->DisplayEnd && data->StepNo < data->Ranges.Size) + if (clipper->DisplayStart >= clipper->DisplayEnd) continue; + if (clipper->DisplayStart > already_submitted) + clipper->SeekCursorForItem(clipper->DisplayStart); return true; } @@ -3279,7 +3279,7 @@ bool ImGuiListClipper::Step() ImGuiContext& g = *Ctx; bool need_items_height = (ItemsHeight <= 0.0f); bool ret = ImGuiListClipper_StepInternal(this); - if (ret && (DisplayStart == DisplayEnd)) + if (ret && (DisplayStart >= DisplayEnd)) ret = false; if (g.CurrentTable && g.CurrentTable->IsUnfrozenRows == false) IMGUI_DEBUG_LOG_CLIPPER("Clipper: Step(): inside frozen table row.\n"); From ce13f6b73e30307fa150b1e88f6014a454da466c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 13:10:58 +0100 Subject: [PATCH 502/548] Backends: GLFW: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. (#8452) Amend 8e4010479 --- backends/imgui_impl_glfw.cpp | 9 ++++++++- docs/CHANGELOG.txt | 2 ++ imgui.h | 2 +- imgui_internal.h | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 69cde6c08910..874a0a440997 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -28,7 +28,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: +// 2025-03-03: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. +// 2024-08-22: Moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: // - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn // - io.SetClipboardTextFn -> platform_io.Platform_SetClipboardTextFn // - io.PlatformOpenInShellFn -> platform_io.Platform_OpenInShellFn @@ -598,8 +599,14 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw bd->Time = 0.0; ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); +#if GLFW_VERSION_COMBINED < 3300 + platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(ImGui_ImplGlfw_GetBackendData()->Window, text); }; + platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) { return glfwGetClipboardString(ImGui_ImplGlfw_GetBackendData()->Window); }; +#else platform_io.Platform_SetClipboardTextFn = [](ImGuiContext*, const char* text) { glfwSetClipboardString(nullptr, text); }; platform_io.Platform_GetClipboardTextFn = [](ImGuiContext*) { return glfwGetClipboardString(nullptr); }; +#endif + #ifdef __EMSCRIPTEN__ platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplGlfw_EmscriptenOpenURL(url); return true; }; #endif diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0fd46d378274..bc0f8f17f4a0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -112,6 +112,8 @@ Other changes: (busy/wait/hourglass shape, with or without an arrow cursor). - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) +- Backends: GLFW: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled + with asserts enabled. (#8452) - Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. (#7660) [@achabense] - Backends: SDL2, SDL3, Win32, Allegro5: Added support for ImGuiMouseCursor_Wait diff --git a/imgui.h b/imgui.h index caf8088b2938..641b1ab92123 100644 --- a/imgui.h +++ b/imgui.h @@ -907,7 +907,7 @@ namespace ImGui IMGUI_API void PopClipRect(); // Focus, Activation - IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of of a newly appearing window. + IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a newly appearing window. IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. // Keyboard/Gamepad Navigation diff --git a/imgui_internal.h b/imgui_internal.h index f896171cd0d7..4bdc6e94791c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2940,7 +2940,7 @@ struct IMGUI_API ImGuiTableTempData ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; } }; -// sizeof() ~ 12 +// sizeof() ~ 16 struct ImGuiTableColumnSettings { float WidthOrWeight; From eefd2da0f68ebec8e93484088f5257612e37281f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 17:38:09 +0100 Subject: [PATCH 503/548] Demo: (Refactor) Added new empty sections.. Renamed existing helper functions. --- docs/CHANGELOG.txt | 1 + imgui_demo.cpp | 191 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 154 insertions(+), 38 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bc0f8f17f4a0..390681161e0a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -110,6 +110,7 @@ Other changes: to allow disabled Item Picker suggestion in user facing builds. (#7961, #7669) - Misc: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursors (busy/wait/hourglass shape, with or without an arrow cursor). +- Demo: Reorganized "Widgets" section to be alphabetically ordered and split in more functions. - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) - Backends: GLFW: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4372dfb4555c..81d6cfca82da 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -72,13 +72,36 @@ Index of this file: // [SECTION] Helpers // [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos) // [SECTION] Demo Window / ShowDemoWindow() -// [SECTION] ShowDemoWindowMenuBar() -// [SECTION] ShowDemoWindowWidgets() -// [SECTION] ShowDemoWindowMultiSelect() -// [SECTION] ShowDemoWindowLayout() -// [SECTION] ShowDemoWindowPopups() -// [SECTION] ShowDemoWindowTables() -// [SECTION] ShowDemoWindowInputs() +// [SECTION] DemoWindowMenuBar() +// [SECTION] DemoWindowWidgets() +// [SECTION] DemoWindowWidgetsBasic() +// [SECTION] DemoWindowWidgetsBullets() +// [SECTION] DemoWindowWidgetsCollapsingHeaders() +// [SECTION] DemoWindowWidgetsComboBoxes() +// [SECTION] DemoWindowWidgetsColorAndPickers() +// [SECTION] DemoWindowWidgetsDataTypes() +// [SECTION] DemoWindowWidgetsDisableBlocks() +// [SECTION] DemoWindowWidgetsDragAndDrop() +// [SECTION] DemoWindowWidgetsDragsAndSliders() +// [SECTION] DemoWindowWidgetsImages() +// [SECTION] DemoWindowWidgetsListBoxes() +// [SECTION] DemoWindowWidgetsMultiComponents() +// [SECTION] DemoWindowWidgetsPlotting() +// [SECTION] DemoWindowWidgetsProgressBars() +// [SECTION] DemoWindowWidgetsQueryingStatuses() +// [SECTION] DemoWindowWidgetsSelectables() +// [SECTION] DemoWindowWidgetsSelectionAndMultiSelect() +// [SECTION] DemoWindowWidgetsTabs() +// [SECTION] DemoWindowWidgetsText() +// [SECTION] DemoWindowWidgetsTextFilter() +// [SECTION] DemoWindowWidgetsTextInput() +// [SECTION] DemoWindowWidgetsTooltips() +// [SECTION] DemoWindowWidgetsTreeNodes() +// [SECTION] DemoWindowWidgetsVerticalSliders() +// [SECTION] DemoWindowLayout() +// [SECTION] DemoWindowPopups() +// [SECTION] DemoWindowTables() +// [SECTION] DemoWindowInputs() // [SECTION] About Window / ShowAboutWindow() // [SECTION] Style Editor / ShowStyleEditor() // [SECTION] User Guide / ShowUserGuide() @@ -225,14 +248,14 @@ static void ShowExampleMenuFile(); // We split the contents of the big ShowDemoWindow() function into smaller functions // (because the link time of very large functions tends to grow non-linearly) -static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data); -static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data); -static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data); -static void ShowDemoWindowLayout(); -static void ShowDemoWindowPopups(); -static void ShowDemoWindowTables(); -static void ShowDemoWindowColumns(); -static void ShowDemoWindowInputs(); +static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data); +static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data); +static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data); +static void DemoWindowLayout(); +static void DemoWindowPopups(); +static void DemoWindowTables(); +static void DemoWindowColumns(); +static void DemoWindowInputs(); //----------------------------------------------------------------------------- // [SECTION] Helpers @@ -475,7 +498,7 @@ void ImGui::ShowDemoWindow(bool* p_open) //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f); // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align) // Menu Bar - ShowDemoWindowMenuBar(&demo_data); + DemoWindowMenuBar(&demo_data); ImGui::Text("dear imgui says hello! (%s) (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM); ImGui::Spacing(); @@ -683,11 +706,11 @@ void ImGui::ShowDemoWindow(bool* p_open) } // All demo contents - ShowDemoWindowWidgets(&demo_data); - ShowDemoWindowLayout(); - ShowDemoWindowPopups(); - ShowDemoWindowTables(); - ShowDemoWindowInputs(); + DemoWindowWidgets(&demo_data); + DemoWindowLayout(); + DemoWindowPopups(); + DemoWindowTables(); + DemoWindowInputs(); // End of ShowDemoWindow() ImGui::PopItemWidth(); @@ -695,10 +718,10 @@ void ImGui::ShowDemoWindow(bool* p_open) } //----------------------------------------------------------------------------- -// [SECTION] ShowDemoWindowMenuBar() +// [SECTION] DemoWindowMenuBar() //----------------------------------------------------------------------------- -static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data) +static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data) { IMGUI_DEMO_MARKER("Menu"); if (ImGui::BeginMenuBar()) @@ -770,10 +793,10 @@ static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data) } //----------------------------------------------------------------------------- -// [SECTION] ShowDemoWindowWidgets() +// [SECTION] DemoWindowWidgets() //----------------------------------------------------------------------------- -static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) +static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) { IMGUI_DEMO_MARKER("Widgets"); //ImGui::SetNextItemOpen(true, ImGuiCond_Once); @@ -1680,7 +1703,7 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::TreePop(); } - ShowDemoWindowMultiSelect(demo_data); + DemoWindowWidgetsSelectionAndMultiSelect(demo_data); // To wire InputText() with std::string or any other custom string type, // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. @@ -2986,6 +3009,70 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) } } +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsBasic() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsBullets() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsCollapsingHeaders() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsColorAndPickers() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsComboBoxes() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsDataTypes() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsDisableBlocks() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsDragAndDrop() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsDragsAndSliders() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsImages() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsListBoxes() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsMultiComponents() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsPlotting() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsProgressBars() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsQueryingStatuses() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsSelectables() +//----------------------------------------------------------------------------- + static const char* ExampleNames[] = { "Artichoke", "Arugula", "Asparagus", "Avocado", "Bamboo Shoots", "Bean Sprouts", "Beans", "Beet", "Belgian Endive", "Bell Pepper", @@ -3212,13 +3299,13 @@ struct ExampleDualListBox }; //----------------------------------------------------------------------------- -// [SECTION] ShowDemoWindowMultiSelect() +// [SECTION] DemoWindowWidgetsSelectionAndMultiSelect() //----------------------------------------------------------------------------- // Multi-selection demos // Also read: https://github.com/ocornut/imgui/wiki/Multi-Select //----------------------------------------------------------------------------- -static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data) +static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data) { IMGUI_DEMO_MARKER("Widgets/Selection State & Multi-Select"); if (ImGui::TreeNode("Selection State & Multi-Select")) @@ -3954,10 +4041,38 @@ static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data) } //----------------------------------------------------------------------------- -// [SECTION] ShowDemoWindowLayout() +// [SECTION] DemoWindowWidgetsTabs() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsText() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsTextFilter() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsTextInput() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsTooltips() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsTreeNodes() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsVerticalSliders() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowLayout() //----------------------------------------------------------------------------- -static void ShowDemoWindowLayout() +static void DemoWindowLayout() { IMGUI_DEMO_MARKER("Layout"); if (!ImGui::CollapsingHeader("Layout & Scrolling")) @@ -4820,10 +4935,10 @@ static void ShowDemoWindowLayout() } //----------------------------------------------------------------------------- -// [SECTION] ShowDemoWindowPopups() +// [SECTION] DemoWindowPopups() //----------------------------------------------------------------------------- -static void ShowDemoWindowPopups() +static void DemoWindowPopups() { IMGUI_DEMO_MARKER("Popups"); if (!ImGui::CollapsingHeader("Popups & Modal windows")) @@ -5284,10 +5399,10 @@ static void ShowTableColumnsStatusFlags(ImGuiTableColumnFlags flags) } //----------------------------------------------------------------------------- -// [SECTION] ShowDemoWindowTables() +// [SECTION] DemoWindowTables() //----------------------------------------------------------------------------- -static void ShowDemoWindowTables() +static void DemoWindowTables() { //ImGui::SetNextItemOpen(true, ImGuiCond_Once); IMGUI_DEMO_MARKER("Tables"); @@ -7184,7 +7299,7 @@ static void ShowDemoWindowTables() ImGui::PopID(); - ShowDemoWindowColumns(); + DemoWindowColumns(); if (disable_indent) ImGui::PopStyleVar(); @@ -7192,7 +7307,7 @@ static void ShowDemoWindowTables() // Demonstrate old/legacy Columns API! // [2020: Columns are under-featured and not maintained. Prefer using the more flexible and powerful BeginTable() API!] -static void ShowDemoWindowColumns() +static void DemoWindowColumns() { IMGUI_DEMO_MARKER("Columns (legacy API)"); bool open = ImGui::TreeNode("Legacy Columns API"); @@ -7399,10 +7514,10 @@ static void ShowDemoWindowColumns() } //----------------------------------------------------------------------------- -// [SECTION] ShowDemoWindowInputs() +// [SECTION] DemoWindowInputs() //----------------------------------------------------------------------------- -static void ShowDemoWindowInputs() +static void DemoWindowInputs() { IMGUI_DEMO_MARKER("Inputs & Focus"); if (ImGui::CollapsingHeader("Inputs & Focus")) From b2c55c9db56bc7ceb0618c9e247deeff3cb43f47 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 17:50:48 +0100 Subject: [PATCH 504/548] Demo: (Refactor) Moved code into DemoWindowWidgetsBasic() section. --- imgui_demo.cpp | 411 +++++++++++++++++++++++++------------------------ 1 file changed, 209 insertions(+), 202 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 81d6cfca82da..1e43ea3c4f9e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -250,6 +250,7 @@ static void ShowExampleMenuFile(); // (because the link time of very large functions tends to grow non-linearly) static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data); +static void DemoWindowWidgetsBasic(); static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data); static void DemoWindowLayout(); static void DemoWindowPopups(); @@ -807,203 +808,8 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) if (disable_all) ImGui::BeginDisabled(); - IMGUI_DEMO_MARKER("Widgets/Basic"); - if (ImGui::TreeNode("Basic")) - { - ImGui::SeparatorText("General"); - - IMGUI_DEMO_MARKER("Widgets/Basic/Button"); - static int clicked = 0; - if (ImGui::Button("Button")) - clicked++; - if (clicked & 1) - { - ImGui::SameLine(); - ImGui::Text("Thanks for clicking me!"); - } - - IMGUI_DEMO_MARKER("Widgets/Basic/Checkbox"); - static bool check = true; - ImGui::Checkbox("checkbox", &check); - - IMGUI_DEMO_MARKER("Widgets/Basic/RadioButton"); - static int e = 0; - ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine(); - ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine(); - ImGui::RadioButton("radio c", &e, 2); - - // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style. - IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Colored)"); - for (int i = 0; i < 7; i++) - { - if (i > 0) - ImGui::SameLine(); - ImGui::PushID(i); - ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f)); - ImGui::Button("Click"); - ImGui::PopStyleColor(3); - ImGui::PopID(); - } - - // Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements - // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!) - // See 'Demo->Layout->Text Baseline Alignment' for details. - ImGui::AlignTextToFramePadding(); - ImGui::Text("Hold to repeat:"); - ImGui::SameLine(); - - // Arrow buttons with Repeater - IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Repeating)"); - static int counter = 0; - float spacing = ImGui::GetStyle().ItemInnerSpacing.x; - ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); - if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; } - ImGui::SameLine(0.0f, spacing); - if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; } - ImGui::PopItemFlag(); - ImGui::SameLine(); - ImGui::Text("%d", counter); - - ImGui::Button("Tooltip"); - ImGui::SetItemTooltip("I am a tooltip"); - - ImGui::LabelText("label", "Value"); - - ImGui::SeparatorText("Inputs"); - - { - // To wire InputText() with std::string or any other custom string type, - // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. - IMGUI_DEMO_MARKER("Widgets/Basic/InputText"); - static char str0[128] = "Hello, world!"; - ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); - ImGui::SameLine(); HelpMarker( - "USER:\n" - "Hold SHIFT or use mouse to select text.\n" - "CTRL+Left/Right to word jump.\n" - "CTRL+A or Double-Click to select all.\n" - "CTRL+X,CTRL+C,CTRL+V for clipboard.\n" - "CTRL+Z to undo, CTRL+Y/CTRL+SHIFT+Z to redo.\n" - "ESCAPE to revert.\n\n" - "PROGRAMMER:\n" - "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() " - "to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated " - "in imgui_demo.cpp)."); + DemoWindowWidgetsBasic(); - static char str1[128] = ""; - ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1)); - - IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat"); - static int i0 = 123; - ImGui::InputInt("input int", &i0); - - static float f0 = 0.001f; - ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f"); - - static double d0 = 999999.00000001; - ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f"); - - static float f1 = 1.e10f; - ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e"); - ImGui::SameLine(); HelpMarker( - "You can input value using the scientific notation,\n" - " e.g. \"1e+8\" becomes \"100000000\"."); - - static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; - ImGui::InputFloat3("input float3", vec4a); - } - - ImGui::SeparatorText("Drags"); - - { - IMGUI_DEMO_MARKER("Widgets/Basic/DragInt, DragFloat"); - static int i1 = 50, i2 = 42, i3 = 128; - ImGui::DragInt("drag int", &i1, 1); - ImGui::SameLine(); HelpMarker( - "Click and drag to edit value.\n" - "Hold SHIFT/ALT for faster/slower edit.\n" - "Double-click or CTRL+click to input value."); - ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp); - ImGui::DragInt("drag int wrap 100..200", &i3, 1, 100, 200, "%d", ImGuiSliderFlags_WrapAround); - - static float f1 = 1.00f, f2 = 0.0067f; - ImGui::DragFloat("drag float", &f1, 0.005f); - ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns"); - //ImGui::DragFloat("drag wrap -1..1", &f3, 0.005f, -1.0f, 1.0f, NULL, ImGuiSliderFlags_WrapAround); - } - - ImGui::SeparatorText("Sliders"); - - { - IMGUI_DEMO_MARKER("Widgets/Basic/SliderInt, SliderFloat"); - static int i1 = 0; - ImGui::SliderInt("slider int", &i1, -1, 3); - ImGui::SameLine(); HelpMarker("CTRL+click to input value."); - - static float f1 = 0.123f, f2 = 0.0f; - ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f"); - ImGui::SliderFloat("slider float (log)", &f2, -10.0f, 10.0f, "%.4f", ImGuiSliderFlags_Logarithmic); - - IMGUI_DEMO_MARKER("Widgets/Basic/SliderAngle"); - static float angle = 0.0f; - ImGui::SliderAngle("slider angle", &angle); - - // Using the format string to display a name instead of an integer. - // Here we completely omit '%d' from the format string, so it'll only display a name. - // This technique can also be used with DragInt(). - IMGUI_DEMO_MARKER("Widgets/Basic/Slider (enum)"); - enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT }; - static int elem = Element_Fire; - const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" }; - const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown"; - ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); // Use ImGuiSliderFlags_NoInput flag to disable CTRL+Click here. - ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer."); - } - - ImGui::SeparatorText("Selectors/Pickers"); - - { - IMGUI_DEMO_MARKER("Widgets/Basic/ColorEdit3, ColorEdit4"); - static float col1[3] = { 1.0f, 0.0f, 0.2f }; - static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; - ImGui::ColorEdit3("color 1", col1); - ImGui::SameLine(); HelpMarker( - "Click on the color square to open a color picker.\n" - "Click and hold to use drag and drop.\n" - "Right-click on the color square to show options.\n" - "CTRL+click on individual component to input value.\n"); - - ImGui::ColorEdit4("color 2", col2); - } - - { - // Using the _simplified_ one-liner Combo() api here - // See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api. - IMGUI_DEMO_MARKER("Widgets/Basic/Combo"); - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" }; - static int item_current = 0; - ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items)); - ImGui::SameLine(); HelpMarker( - "Using the simplified one-liner Combo API here.\n" - "Refer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API."); - } - - { - // Using the _simplified_ one-liner ListBox() api here - // See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api. - IMGUI_DEMO_MARKER("Widgets/Basic/ListBox"); - const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; - static int item_current = 1; - ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4); - ImGui::SameLine(); HelpMarker( - "Using the simplified one-liner ListBox API here.\n" - "Refer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API."); - } - - ImGui::TreePop(); - } IMGUI_DEMO_MARKER("Widgets/Tooltips"); if (ImGui::TreeNode("Tooltips")) @@ -1097,12 +903,6 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::TreePop(); } - // Testing ImGuiOnceUponAFrame helper. - //static ImGuiOnceUponAFrame once; - //for (int i = 0; i < 5; i++) - // if (once) - // ImGui::Text("This will be displayed only once."); - IMGUI_DEMO_MARKER("Widgets/Tree Nodes"); if (ImGui::TreeNode("Tree Nodes")) { @@ -3013,6 +2813,213 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) // [SECTION] DemoWindowWidgetsBasic() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsBasic() +{ + IMGUI_DEMO_MARKER("Widgets/Basic"); + if (ImGui::TreeNode("Basic")) + { + ImGui::SeparatorText("General"); + + IMGUI_DEMO_MARKER("Widgets/Basic/Button"); + static int clicked = 0; + if (ImGui::Button("Button")) + clicked++; + if (clicked & 1) + { + ImGui::SameLine(); + ImGui::Text("Thanks for clicking me!"); + } + + IMGUI_DEMO_MARKER("Widgets/Basic/Checkbox"); + static bool check = true; + ImGui::Checkbox("checkbox", &check); + + IMGUI_DEMO_MARKER("Widgets/Basic/RadioButton"); + static int e = 0; + ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine(); + ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine(); + ImGui::RadioButton("radio c", &e, 2); + + // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style. + IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Colored)"); + for (int i = 0; i < 7; i++) + { + if (i > 0) + ImGui::SameLine(); + ImGui::PushID(i); + ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f)); + ImGui::Button("Click"); + ImGui::PopStyleColor(3); + ImGui::PopID(); + } + + // Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements + // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!) + // See 'Demo->Layout->Text Baseline Alignment' for details. + ImGui::AlignTextToFramePadding(); + ImGui::Text("Hold to repeat:"); + ImGui::SameLine(); + + // Arrow buttons with Repeater + IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Repeating)"); + static int counter = 0; + float spacing = ImGui::GetStyle().ItemInnerSpacing.x; + ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); + if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; } + ImGui::SameLine(0.0f, spacing); + if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; } + ImGui::PopItemFlag(); + ImGui::SameLine(); + ImGui::Text("%d", counter); + + ImGui::Button("Tooltip"); + ImGui::SetItemTooltip("I am a tooltip"); + + ImGui::LabelText("label", "Value"); + + ImGui::SeparatorText("Inputs"); + + { + // To wire InputText() with std::string or any other custom string type, + // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. + IMGUI_DEMO_MARKER("Widgets/Basic/InputText"); + static char str0[128] = "Hello, world!"; + ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); + ImGui::SameLine(); HelpMarker( + "USER:\n" + "Hold SHIFT or use mouse to select text.\n" + "CTRL+Left/Right to word jump.\n" + "CTRL+A or Double-Click to select all.\n" + "CTRL+X,CTRL+C,CTRL+V for clipboard.\n" + "CTRL+Z to undo, CTRL+Y/CTRL+SHIFT+Z to redo.\n" + "ESCAPE to revert.\n\n" + "PROGRAMMER:\n" + "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() " + "to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated " + "in imgui_demo.cpp)."); + + static char str1[128] = ""; + ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1)); + + IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat"); + static int i0 = 123; + ImGui::InputInt("input int", &i0); + + static float f0 = 0.001f; + ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f"); + + static double d0 = 999999.00000001; + ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f"); + + static float f1 = 1.e10f; + ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e"); + ImGui::SameLine(); HelpMarker( + "You can input value using the scientific notation,\n" + " e.g. \"1e+8\" becomes \"100000000\"."); + + static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; + ImGui::InputFloat3("input float3", vec4a); + } + + ImGui::SeparatorText("Drags"); + + { + IMGUI_DEMO_MARKER("Widgets/Basic/DragInt, DragFloat"); + static int i1 = 50, i2 = 42, i3 = 128; + ImGui::DragInt("drag int", &i1, 1); + ImGui::SameLine(); HelpMarker( + "Click and drag to edit value.\n" + "Hold SHIFT/ALT for faster/slower edit.\n" + "Double-click or CTRL+click to input value."); + ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp); + ImGui::DragInt("drag int wrap 100..200", &i3, 1, 100, 200, "%d", ImGuiSliderFlags_WrapAround); + + static float f1 = 1.00f, f2 = 0.0067f; + ImGui::DragFloat("drag float", &f1, 0.005f); + ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns"); + //ImGui::DragFloat("drag wrap -1..1", &f3, 0.005f, -1.0f, 1.0f, NULL, ImGuiSliderFlags_WrapAround); + } + + ImGui::SeparatorText("Sliders"); + + { + IMGUI_DEMO_MARKER("Widgets/Basic/SliderInt, SliderFloat"); + static int i1 = 0; + ImGui::SliderInt("slider int", &i1, -1, 3); + ImGui::SameLine(); HelpMarker("CTRL+click to input value."); + + static float f1 = 0.123f, f2 = 0.0f; + ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f"); + ImGui::SliderFloat("slider float (log)", &f2, -10.0f, 10.0f, "%.4f", ImGuiSliderFlags_Logarithmic); + + IMGUI_DEMO_MARKER("Widgets/Basic/SliderAngle"); + static float angle = 0.0f; + ImGui::SliderAngle("slider angle", &angle); + + // Using the format string to display a name instead of an integer. + // Here we completely omit '%d' from the format string, so it'll only display a name. + // This technique can also be used with DragInt(). + IMGUI_DEMO_MARKER("Widgets/Basic/Slider (enum)"); + enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT }; + static int elem = Element_Fire; + const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" }; + const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown"; + ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); // Use ImGuiSliderFlags_NoInput flag to disable CTRL+Click here. + ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer."); + } + + ImGui::SeparatorText("Selectors/Pickers"); + + { + IMGUI_DEMO_MARKER("Widgets/Basic/ColorEdit3, ColorEdit4"); + static float col1[3] = { 1.0f, 0.0f, 0.2f }; + static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; + ImGui::ColorEdit3("color 1", col1); + ImGui::SameLine(); HelpMarker( + "Click on the color square to open a color picker.\n" + "Click and hold to use drag and drop.\n" + "Right-click on the color square to show options.\n" + "CTRL+click on individual component to input value.\n"); + + ImGui::ColorEdit4("color 2", col2); + } + + { + // Using the _simplified_ one-liner Combo() api here + // See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api. + IMGUI_DEMO_MARKER("Widgets/Basic/Combo"); + const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" }; + static int item_current = 0; + ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items)); + ImGui::SameLine(); HelpMarker( + "Using the simplified one-liner Combo API here.\n" + "Refer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API."); + } + + { + // Using the _simplified_ one-liner ListBox() api here + // See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api. + IMGUI_DEMO_MARKER("Widgets/Basic/ListBox"); + const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; + static int item_current = 1; + ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4); + ImGui::SameLine(); HelpMarker( + "Using the simplified one-liner ListBox API here.\n" + "Refer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API."); + } + + // Testing ImGuiOnceUponAFrame helper. + //static ImGuiOnceUponAFrame once; + //for (int i = 0; i < 5; i++) + // if (once) + // ImGui::Text("This will be displayed only once."); + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsBullets() //----------------------------------------------------------------------------- From de3f68a233ac35697671c3e0dcbcd333604c3af5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 17:51:34 +0100 Subject: [PATCH 505/548] Demo: (Refactor) Moved code into DemoWindowWidgetsTooltips(), DemoWindowWidgetsTreeNodes() sections. --- imgui_demo.cpp | 447 +++++++++++++++++++++++++------------------------ 1 file changed, 228 insertions(+), 219 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 1e43ea3c4f9e..479aa53d54d4 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -252,6 +252,8 @@ static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgetsBasic(); static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data); +static void DemoWindowWidgetsTooltips(); +static void DemoWindowWidgetsTreeNodes(); static void DemoWindowLayout(); static void DemoWindowPopups(); static void DemoWindowTables(); @@ -809,225 +811,8 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::BeginDisabled(); DemoWindowWidgetsBasic(); - - - IMGUI_DEMO_MARKER("Widgets/Tooltips"); - if (ImGui::TreeNode("Tooltips")) - { - // Tooltips are windows following the mouse. They do not take focus away. - ImGui::SeparatorText("General"); - - // Typical use cases: - // - Short-form (text only): SetItemTooltip("Hello"); - // - Short-form (any contents): if (BeginItemTooltip()) { Text("Hello"); EndTooltip(); } - - // - Full-form (text only): if (IsItemHovered(...)) { SetTooltip("Hello"); } - // - Full-form (any contents): if (IsItemHovered(...) && BeginTooltip()) { Text("Hello"); EndTooltip(); } - - HelpMarker( - "Tooltip are typically created by using a IsItemHovered() + SetTooltip() sequence.\n\n" - "We provide a helper SetItemTooltip() function to perform the two with standards flags."); - - ImVec2 sz = ImVec2(-FLT_MIN, 0.0f); - - ImGui::Button("Basic", sz); - ImGui::SetItemTooltip("I am a tooltip"); - - ImGui::Button("Fancy", sz); - if (ImGui::BeginItemTooltip()) - { - ImGui::Text("I am a fancy tooltip"); - static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; - ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr)); - ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime())); - ImGui::EndTooltip(); - } - - ImGui::SeparatorText("Always On"); - - // Showcase NOT relying on a IsItemHovered() to emit a tooltip. - // Here the tooltip is always emitted when 'always_on == true'. - static int always_on = 0; - ImGui::RadioButton("Off", &always_on, 0); - ImGui::SameLine(); - ImGui::RadioButton("Always On (Simple)", &always_on, 1); - ImGui::SameLine(); - ImGui::RadioButton("Always On (Advanced)", &always_on, 2); - if (always_on == 1) - ImGui::SetTooltip("I am following you around."); - else if (always_on == 2 && ImGui::BeginTooltip()) - { - ImGui::ProgressBar(sinf((float)ImGui::GetTime()) * 0.5f + 0.5f, ImVec2(ImGui::GetFontSize() * 25, 0.0f)); - ImGui::EndTooltip(); - } - - ImGui::SeparatorText("Custom"); - - HelpMarker( - "Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() is the preferred way to standardize " - "tooltip activation details across your application. You may however decide to use custom " - "flags for a specific tooltip instance."); - - // The following examples are passed for documentation purpose but may not be useful to most users. - // Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() will pull ImGuiHoveredFlags flags values from - // 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or keyboard/gamepad is being used. - // With default settings, ImGuiHoveredFlags_ForTooltip is equivalent to ImGuiHoveredFlags_DelayShort + ImGuiHoveredFlags_Stationary. - ImGui::Button("Manual", sz); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip)) - ImGui::SetTooltip("I am a manually emitted tooltip."); - - ImGui::Button("DelayNone", sz); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNone)) - ImGui::SetTooltip("I am a tooltip with no delay."); - - ImGui::Button("DelayShort", sz); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_NoSharedDelay)) - ImGui::SetTooltip("I am a tooltip with a short delay (%0.2f sec).", ImGui::GetStyle().HoverDelayShort); - - ImGui::Button("DelayLong", sz); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay)) - ImGui::SetTooltip("I am a tooltip with a long delay (%0.2f sec).", ImGui::GetStyle().HoverDelayNormal); - - ImGui::Button("Stationary", sz); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary)) - ImGui::SetTooltip("I am a tooltip requiring mouse to be stationary before activating."); - - // Using ImGuiHoveredFlags_ForTooltip will pull flags from 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav', - // which default value include the ImGuiHoveredFlags_AllowWhenDisabled flag. - ImGui::BeginDisabled(); - ImGui::Button("Disabled item", sz); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip)) - ImGui::SetTooltip("I am a a tooltip for a disabled item."); - ImGui::EndDisabled(); - - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Tree Nodes"); - if (ImGui::TreeNode("Tree Nodes")) - { - IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Basic trees"); - if (ImGui::TreeNode("Basic trees")) - { - for (int i = 0; i < 5; i++) - { - // Use SetNextItemOpen() so set the default state of a node to be open. We could - // also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing! - if (i == 0) - ImGui::SetNextItemOpen(true, ImGuiCond_Once); - - // Here we use PushID() to generate a unique base ID, and then the "" used as TreeNode id won't conflict. - // An alternative to using 'PushID() + TreeNode("", ...)' to generate a unique ID is to use 'TreeNode((void*)(intptr_t)i, ...)', - // aka generate a dummy pointer-sized value to be hashed. The demo below uses that technique. Both are fine. - ImGui::PushID(i); - if (ImGui::TreeNode("", "Child %d", i)) - { - ImGui::Text("blah blah"); - ImGui::SameLine(); - if (ImGui::SmallButton("button")) {} - ImGui::TreePop(); - } - ImGui::PopID(); - } - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Advanced, with Selectable nodes"); - if (ImGui::TreeNode("Advanced, with Selectable nodes")) - { - HelpMarker( - "This is a more typical looking tree with selectable nodes.\n" - "Click to select, CTRL+Click to toggle, click on arrows or double-click to open."); - static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; - static bool align_label_with_current_x_position = false; - static bool test_drag_and_drop = false; - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", &base_flags, ImGuiTreeNodeFlags_OpenOnArrow); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node."); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanLabelWidth", &base_flags, ImGuiTreeNodeFlags_SpanLabelWidth); ImGui::SameLine(); HelpMarker("Reduce hit area to the text label and a bit of margin."); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only."); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap", &base_flags, ImGuiTreeNodeFlags_AllowOverlap); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed", &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)"); - ImGui::CheckboxFlags("ImGuiTreeNodeFlags_NavLeftJumpsBackHere", &base_flags, ImGuiTreeNodeFlags_NavLeftJumpsBackHere); - ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position); - ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop); - ImGui::Text("Hello!"); - if (align_label_with_current_x_position) - ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); - - // 'selection_mask' is dumb representation of what may be user-side selection state. - // You may retain selection state inside or outside your objects in whatever format you see fit. - // 'node_clicked' is temporary storage of what node we have clicked to process selection at the end - /// of the loop. May be a pointer to your own node type, etc. - static int selection_mask = (1 << 2); - int node_clicked = -1; - for (int i = 0; i < 6; i++) - { - // Disable the default "open on single-click behavior" + set Selected flag according to our selection. - // To alter selection we use IsItemClicked() && !IsItemToggledOpen(), so clicking on an arrow doesn't alter selection. - ImGuiTreeNodeFlags node_flags = base_flags; - const bool is_selected = (selection_mask & (1 << i)) != 0; - if (is_selected) - node_flags |= ImGuiTreeNodeFlags_Selected; - if (i < 3) - { - // Items 0..2 are Tree Node - bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i); - if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) - node_clicked = i; - if (test_drag_and_drop && ImGui::BeginDragDropSource()) - { - ImGui::SetDragDropPayload("_TREENODE", NULL, 0); - ImGui::Text("This is a drag and drop source"); - ImGui::EndDragDropSource(); - } - if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanLabelWidth)) - { - // Item 2 has an additional inline button to help demonstrate SpanLabelWidth. - ImGui::SameLine(); - if (ImGui::SmallButton("button")) {} - } - if (node_open) - { - ImGui::BulletText("Blah blah\nBlah Blah"); - ImGui::SameLine(); - ImGui::SmallButton("Button"); - ImGui::TreePop(); - } - } - else - { - // Items 3..5 are Tree Leaves - // The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can - // use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text(). - node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet - ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); - if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) - node_clicked = i; - if (test_drag_and_drop && ImGui::BeginDragDropSource()) - { - ImGui::SetDragDropPayload("_TREENODE", NULL, 0); - ImGui::Text("This is a drag and drop source"); - ImGui::EndDragDropSource(); - } - } - } - if (node_clicked != -1) - { - // Update selection state - // (process outside of tree loop to avoid visual inconsistencies during the clicking frame) - if (ImGui::GetIO().KeyCtrl) - selection_mask ^= (1 << node_clicked); // CTRL+click to toggle - else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection - selection_mask = (1 << node_clicked); // Click to single-select - } - if (align_label_with_current_x_position) - ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing()); - ImGui::TreePop(); - } - ImGui::TreePop(); - } + DemoWindowWidgetsTooltips(); + DemoWindowWidgetsTreeNodes(); IMGUI_DEMO_MARKER("Widgets/Collapsing Headers"); if (ImGui::TreeNode("Collapsing Headers")) @@ -4067,10 +3852,234 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d // [SECTION] DemoWindowWidgetsTooltips() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsTooltips() +{ + IMGUI_DEMO_MARKER("Widgets/Tooltips"); + if (ImGui::TreeNode("Tooltips")) + { + // Tooltips are windows following the mouse. They do not take focus away. + ImGui::SeparatorText("General"); + + // Typical use cases: + // - Short-form (text only): SetItemTooltip("Hello"); + // - Short-form (any contents): if (BeginItemTooltip()) { Text("Hello"); EndTooltip(); } + + // - Full-form (text only): if (IsItemHovered(...)) { SetTooltip("Hello"); } + // - Full-form (any contents): if (IsItemHovered(...) && BeginTooltip()) { Text("Hello"); EndTooltip(); } + + HelpMarker( + "Tooltip are typically created by using a IsItemHovered() + SetTooltip() sequence.\n\n" + "We provide a helper SetItemTooltip() function to perform the two with standards flags."); + + ImVec2 sz = ImVec2(-FLT_MIN, 0.0f); + + ImGui::Button("Basic", sz); + ImGui::SetItemTooltip("I am a tooltip"); + + ImGui::Button("Fancy", sz); + if (ImGui::BeginItemTooltip()) + { + ImGui::Text("I am a fancy tooltip"); + static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; + ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr)); + ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime())); + ImGui::EndTooltip(); + } + + ImGui::SeparatorText("Always On"); + + // Showcase NOT relying on a IsItemHovered() to emit a tooltip. + // Here the tooltip is always emitted when 'always_on == true'. + static int always_on = 0; + ImGui::RadioButton("Off", &always_on, 0); + ImGui::SameLine(); + ImGui::RadioButton("Always On (Simple)", &always_on, 1); + ImGui::SameLine(); + ImGui::RadioButton("Always On (Advanced)", &always_on, 2); + if (always_on == 1) + ImGui::SetTooltip("I am following you around."); + else if (always_on == 2 && ImGui::BeginTooltip()) + { + ImGui::ProgressBar(sinf((float)ImGui::GetTime()) * 0.5f + 0.5f, ImVec2(ImGui::GetFontSize() * 25, 0.0f)); + ImGui::EndTooltip(); + } + + ImGui::SeparatorText("Custom"); + + HelpMarker( + "Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() is the preferred way to standardize " + "tooltip activation details across your application. You may however decide to use custom " + "flags for a specific tooltip instance."); + + // The following examples are passed for documentation purpose but may not be useful to most users. + // Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() will pull ImGuiHoveredFlags flags values from + // 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or keyboard/gamepad is being used. + // With default settings, ImGuiHoveredFlags_ForTooltip is equivalent to ImGuiHoveredFlags_DelayShort + ImGuiHoveredFlags_Stationary. + ImGui::Button("Manual", sz); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip)) + ImGui::SetTooltip("I am a manually emitted tooltip."); + + ImGui::Button("DelayNone", sz); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNone)) + ImGui::SetTooltip("I am a tooltip with no delay."); + + ImGui::Button("DelayShort", sz); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_NoSharedDelay)) + ImGui::SetTooltip("I am a tooltip with a short delay (%0.2f sec).", ImGui::GetStyle().HoverDelayShort); + + ImGui::Button("DelayLong", sz); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay)) + ImGui::SetTooltip("I am a tooltip with a long delay (%0.2f sec).", ImGui::GetStyle().HoverDelayNormal); + + ImGui::Button("Stationary", sz); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary)) + ImGui::SetTooltip("I am a tooltip requiring mouse to be stationary before activating."); + + // Using ImGuiHoveredFlags_ForTooltip will pull flags from 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav', + // which default value include the ImGuiHoveredFlags_AllowWhenDisabled flag. + ImGui::BeginDisabled(); + ImGui::Button("Disabled item", sz); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip)) + ImGui::SetTooltip("I am a a tooltip for a disabled item."); + ImGui::EndDisabled(); + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsTreeNodes() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsTreeNodes() +{ + IMGUI_DEMO_MARKER("Widgets/Tree Nodes"); + if (ImGui::TreeNode("Tree Nodes")) + { + IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Basic trees"); + if (ImGui::TreeNode("Basic trees")) + { + for (int i = 0; i < 5; i++) + { + // Use SetNextItemOpen() so set the default state of a node to be open. We could + // also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing! + if (i == 0) + ImGui::SetNextItemOpen(true, ImGuiCond_Once); + + // Here we use PushID() to generate a unique base ID, and then the "" used as TreeNode id won't conflict. + // An alternative to using 'PushID() + TreeNode("", ...)' to generate a unique ID is to use 'TreeNode((void*)(intptr_t)i, ...)', + // aka generate a dummy pointer-sized value to be hashed. The demo below uses that technique. Both are fine. + ImGui::PushID(i); + if (ImGui::TreeNode("", "Child %d", i)) + { + ImGui::Text("blah blah"); + ImGui::SameLine(); + if (ImGui::SmallButton("button")) {} + ImGui::TreePop(); + } + ImGui::PopID(); + } + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Advanced, with Selectable nodes"); + if (ImGui::TreeNode("Advanced, with Selectable nodes")) + { + HelpMarker( + "This is a more typical looking tree with selectable nodes.\n" + "Click to select, CTRL+Click to toggle, click on arrows or double-click to open."); + static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth; + static bool align_label_with_current_x_position = false; + static bool test_drag_and_drop = false; + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", &base_flags, ImGuiTreeNodeFlags_OpenOnArrow); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node."); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanLabelWidth", &base_flags, ImGuiTreeNodeFlags_SpanLabelWidth); ImGui::SameLine(); HelpMarker("Reduce hit area to the text label and a bit of margin."); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only."); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap", &base_flags, ImGuiTreeNodeFlags_AllowOverlap); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed", &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)"); + ImGui::CheckboxFlags("ImGuiTreeNodeFlags_NavLeftJumpsBackHere", &base_flags, ImGuiTreeNodeFlags_NavLeftJumpsBackHere); + ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position); + ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop); + ImGui::Text("Hello!"); + if (align_label_with_current_x_position) + ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing()); + + // 'selection_mask' is dumb representation of what may be user-side selection state. + // You may retain selection state inside or outside your objects in whatever format you see fit. + // 'node_clicked' is temporary storage of what node we have clicked to process selection at the end + /// of the loop. May be a pointer to your own node type, etc. + static int selection_mask = (1 << 2); + int node_clicked = -1; + for (int i = 0; i < 6; i++) + { + // Disable the default "open on single-click behavior" + set Selected flag according to our selection. + // To alter selection we use IsItemClicked() && !IsItemToggledOpen(), so clicking on an arrow doesn't alter selection. + ImGuiTreeNodeFlags node_flags = base_flags; + const bool is_selected = (selection_mask & (1 << i)) != 0; + if (is_selected) + node_flags |= ImGuiTreeNodeFlags_Selected; + if (i < 3) + { + // Items 0..2 are Tree Node + bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i); + if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) + node_clicked = i; + if (test_drag_and_drop && ImGui::BeginDragDropSource()) + { + ImGui::SetDragDropPayload("_TREENODE", NULL, 0); + ImGui::Text("This is a drag and drop source"); + ImGui::EndDragDropSource(); + } + if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanLabelWidth)) + { + // Item 2 has an additional inline button to help demonstrate SpanLabelWidth. + ImGui::SameLine(); + if (ImGui::SmallButton("button")) {} + } + if (node_open) + { + ImGui::BulletText("Blah blah\nBlah Blah"); + ImGui::SameLine(); + ImGui::SmallButton("Button"); + ImGui::TreePop(); + } + } + else + { + // Items 3..5 are Tree Leaves + // The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can + // use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text(). + node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet + ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i); + if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) + node_clicked = i; + if (test_drag_and_drop && ImGui::BeginDragDropSource()) + { + ImGui::SetDragDropPayload("_TREENODE", NULL, 0); + ImGui::Text("This is a drag and drop source"); + ImGui::EndDragDropSource(); + } + } + } + if (node_clicked != -1) + { + // Update selection state + // (process outside of tree loop to avoid visual inconsistencies during the clicking frame) + if (ImGui::GetIO().KeyCtrl) + selection_mask ^= (1 << node_clicked); // CTRL+click to toggle + else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection + selection_mask = (1 << node_clicked); // Click to single-select + } + if (align_label_with_current_x_position) + ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing()); + ImGui::TreePop(); + } + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsVerticalSliders() //----------------------------------------------------------------------------- From 94877a137d6aac1aba010bcace0f5730c2f153fc Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 17:56:15 +0100 Subject: [PATCH 506/548] Demo: (Refactor) Moved code into DemoWindowWidgetsBullets(), DemoWindowWidgetsCollapsingHeaders(), DemoWindowWidgetsCollapsingText() sections. --- imgui_demo.cpp | 243 ++++++++++++++++++++++++++----------------------- 1 file changed, 129 insertions(+), 114 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 479aa53d54d4..f40f5ddaec3b 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -251,7 +251,10 @@ static void ShowExampleMenuFile(); static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgetsBasic(); +static void DemoWindowWidgetsBullets(); +static void DemoWindowWidgetsCollapsingHeaders(); static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data); +static void DemoWindowWidgetsText(); static void DemoWindowWidgetsTooltips(); static void DemoWindowWidgetsTreeNodes(); static void DemoWindowLayout(); @@ -811,123 +814,12 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::BeginDisabled(); DemoWindowWidgetsBasic(); + DemoWindowWidgetsBullets(); + DemoWindowWidgetsCollapsingHeaders(); + DemoWindowWidgetsText(); DemoWindowWidgetsTooltips(); DemoWindowWidgetsTreeNodes(); - IMGUI_DEMO_MARKER("Widgets/Collapsing Headers"); - if (ImGui::TreeNode("Collapsing Headers")) - { - static bool closable_group = true; - ImGui::Checkbox("Show 2nd header", &closable_group); - if (ImGui::CollapsingHeader("Header", ImGuiTreeNodeFlags_None)) - { - ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); - for (int i = 0; i < 5; i++) - ImGui::Text("Some content %d", i); - } - if (ImGui::CollapsingHeader("Header with a close button", &closable_group)) - { - ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); - for (int i = 0; i < 5; i++) - ImGui::Text("More content %d", i); - } - /* - if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet)) - ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); - */ - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Bullets"); - if (ImGui::TreeNode("Bullets")) - { - ImGui::BulletText("Bullet point 1"); - ImGui::BulletText("Bullet point 2\nOn multiple lines"); - if (ImGui::TreeNode("Tree node")) - { - ImGui::BulletText("Another bullet point"); - ImGui::TreePop(); - } - ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)"); - ImGui::Bullet(); ImGui::SmallButton("Button"); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Text"); - if (ImGui::TreeNode("Text")) - { - IMGUI_DEMO_MARKER("Widgets/Text/Colored Text"); - if (ImGui::TreeNode("Colorful Text")) - { - // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility. - ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink"); - ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow"); - ImGui::TextDisabled("Disabled"); - ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle."); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Text/Word Wrapping"); - if (ImGui::TreeNode("Word Wrapping")) - { - // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility. - ImGui::TextWrapped( - "This text should automatically wrap on the edge of the window. The current implementation " - "for text wrapping follows simple rules suitable for English and possibly other languages."); - ImGui::Spacing(); - - static float wrap_width = 200.0f; - ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f"); - - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - for (int n = 0; n < 2; n++) - { - ImGui::Text("Test paragraph %d:", n); - ImVec2 pos = ImGui::GetCursorScreenPos(); - ImVec2 marker_min = ImVec2(pos.x + wrap_width, pos.y); - ImVec2 marker_max = ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()); - ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width); - if (n == 0) - ImGui::Text("The lazy dog is a good dog. This paragraph should fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width); - else - ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh"); - - // Draw actual text bounding box, following by marker of our expected limit (should not overlap!) - draw_list->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255)); - draw_list->AddRectFilled(marker_min, marker_max, IM_COL32(255, 0, 255, 255)); - ImGui::PopTextWrapPos(); - } - - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Text/UTF-8 Text"); - if (ImGui::TreeNode("UTF-8 Text")) - { - // UTF-8 test with Japanese characters - // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.) - // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8 - // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you - // can save your source files as 'UTF-8 without signature'). - // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8 - // CHARACTERS IN THIS SOURCE FILE. Instead we are encoding a few strings with hexadecimal constants. - // Don't do this in your application! Please use u8"text in any language" in your application! - // Note that characters values are preserved even by InputText() if the font cannot be displayed, - // so you can safely copy & paste garbled characters into another application. - ImGui::TextWrapped( - "CJK text will only appear if the font was loaded with the appropriate CJK character ranges. " - "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. " - "Read docs/FONTS.md for details."); - ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); - ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)"); - static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; - //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis - ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf)); - ImGui::TreePop(); - } - ImGui::TreePop(); - } - IMGUI_DEMO_MARKER("Widgets/Images"); if (ImGui::TreeNode("Images")) { @@ -2809,10 +2701,55 @@ static void DemoWindowWidgetsBasic() // [SECTION] DemoWindowWidgetsBullets() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsBullets() +{ + IMGUI_DEMO_MARKER("Widgets/Bullets"); + if (ImGui::TreeNode("Bullets")) + { + ImGui::BulletText("Bullet point 1"); + ImGui::BulletText("Bullet point 2\nOn multiple lines"); + if (ImGui::TreeNode("Tree node")) + { + ImGui::BulletText("Another bullet point"); + ImGui::TreePop(); + } + ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)"); + ImGui::Bullet(); ImGui::SmallButton("Button"); + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsCollapsingHeaders() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsCollapsingHeaders() +{ + IMGUI_DEMO_MARKER("Widgets/Collapsing Headers"); + if (ImGui::TreeNode("Collapsing Headers")) + { + static bool closable_group = true; + ImGui::Checkbox("Show 2nd header", &closable_group); + if (ImGui::CollapsingHeader("Header", ImGuiTreeNodeFlags_None)) + { + ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); + for (int i = 0; i < 5; i++) + ImGui::Text("Some content %d", i); + } + if (ImGui::CollapsingHeader("Header with a close button", &closable_group)) + { + ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); + for (int i = 0; i < 5; i++) + ImGui::Text("More content %d", i); + } + /* + if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet)) + ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered()); + */ + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsColorAndPickers() //----------------------------------------------------------------------------- @@ -3840,6 +3777,84 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d // [SECTION] DemoWindowWidgetsText() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsText() +{ + IMGUI_DEMO_MARKER("Widgets/Text"); + if (ImGui::TreeNode("Text")) + { + IMGUI_DEMO_MARKER("Widgets/Text/Colored Text"); + if (ImGui::TreeNode("Colorful Text")) + { + // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility. + ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink"); + ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow"); + ImGui::TextDisabled("Disabled"); + ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle."); + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Text/Word Wrapping"); + if (ImGui::TreeNode("Word Wrapping")) + { + // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility. + ImGui::TextWrapped( + "This text should automatically wrap on the edge of the window. The current implementation " + "for text wrapping follows simple rules suitable for English and possibly other languages."); + ImGui::Spacing(); + + static float wrap_width = 200.0f; + ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f"); + + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + for (int n = 0; n < 2; n++) + { + ImGui::Text("Test paragraph %d:", n); + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImVec2 marker_min = ImVec2(pos.x + wrap_width, pos.y); + ImVec2 marker_max = ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()); + ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width); + if (n == 0) + ImGui::Text("The lazy dog is a good dog. This paragraph should fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width); + else + ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh"); + + // Draw actual text bounding box, following by marker of our expected limit (should not overlap!) + draw_list->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255)); + draw_list->AddRectFilled(marker_min, marker_max, IM_COL32(255, 0, 255, 255)); + ImGui::PopTextWrapPos(); + } + + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Text/UTF-8 Text"); + if (ImGui::TreeNode("UTF-8 Text")) + { + // UTF-8 test with Japanese characters + // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.) + // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8 + // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you + // can save your source files as 'UTF-8 without signature'). + // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8 + // CHARACTERS IN THIS SOURCE FILE. Instead we are encoding a few strings with hexadecimal constants. + // Don't do this in your application! Please use u8"text in any language" in your application! + // Note that characters values are preserved even by InputText() if the font cannot be displayed, + // so you can safely copy & paste garbled characters into another application. + ImGui::TextWrapped( + "CJK text will only appear if the font was loaded with the appropriate CJK character ranges. " + "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. " + "Read docs/FONTS.md for details."); + ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); + ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)"); + static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; + //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis + ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf)); + ImGui::TreePop(); + } + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsTextFilter() //----------------------------------------------------------------------------- From 22baec494bfec2df120c0acb491eb0a7b643cf40 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 17:57:43 +0100 Subject: [PATCH 507/548] Demo: (Refactor) Moved code into DemoWindowWidgetsComboBoxes(), DemoWindowWidgetsImages(), DemoWindowWidgetsListBoxes() sections. --- imgui_demo.cpp | 475 +++++++++++++++++++++++++------------------------ 1 file changed, 245 insertions(+), 230 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index f40f5ddaec3b..3b08b152f73f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -253,6 +253,9 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgetsBasic(); static void DemoWindowWidgetsBullets(); static void DemoWindowWidgetsCollapsingHeaders(); +static void DemoWindowWidgetsComboBoxes(); +static void DemoWindowWidgetsImages(); +static void DemoWindowWidgetsListBoxes(); static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgetsText(); static void DemoWindowWidgetsTooltips(); @@ -816,240 +819,13 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsBasic(); DemoWindowWidgetsBullets(); DemoWindowWidgetsCollapsingHeaders(); + DemoWindowWidgetsComboBoxes(); + DemoWindowWidgetsImages(); + DemoWindowWidgetsListBoxes(); DemoWindowWidgetsText(); DemoWindowWidgetsTooltips(); DemoWindowWidgetsTreeNodes(); - IMGUI_DEMO_MARKER("Widgets/Images"); - if (ImGui::TreeNode("Images")) - { - ImGuiIO& io = ImGui::GetIO(); - ImGui::TextWrapped( - "Below we are displaying the font texture (which is the only texture we have access to in this demo). " - "Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. " - "Hover the texture for a zoomed view!"); - - // Below we are displaying the font texture because it is the only texture we have access to inside the demo! - // Remember that ImTextureID is just storage for whatever you want it to be. It is essentially a value that - // will be passed to the rendering backend via the ImDrawCmd structure. - // If you use one of the default imgui_impl_XXXX.cpp rendering backend, they all have comments at the top - // of their respective source file to specify what they expect to be stored in ImTextureID, for example: - // - The imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer - // - The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier, etc. - // More: - // - If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers - // to ImGui::Image(), and gather width/height through your own functions, etc. - // - You can use ShowMetricsWindow() to inspect the draw data that are being passed to your renderer, - // it will help you debug issues if you are confused about it. - // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage(). - // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md - // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples - ImTextureID my_tex_id = io.Fonts->TexID; - float my_tex_w = (float)io.Fonts->TexWidth; - float my_tex_h = (float)io.Fonts->TexHeight; - { - ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h); - ImVec2 pos = ImGui::GetCursorScreenPos(); - ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left - ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right - ImGui::PushStyleVar(ImGuiStyleVar_ImageBorderSize, IM_MAX(1.0f, ImGui::GetStyle().ImageBorderSize)); - ImGui::ImageWithBg(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); - if (ImGui::BeginItemTooltip()) - { - float region_sz = 32.0f; - float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; - float region_y = io.MousePos.y - pos.y - region_sz * 0.5f; - float zoom = 4.0f; - if (region_x < 0.0f) { region_x = 0.0f; } - else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; } - if (region_y < 0.0f) { region_y = 0.0f; } - else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; } - ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y); - ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz); - ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h); - ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h); - ImGui::ImageWithBg(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); - ImGui::EndTooltip(); - } - ImGui::PopStyleVar(); - } - - IMGUI_DEMO_MARKER("Widgets/Images/Textured buttons"); - ImGui::TextWrapped("And now some textured buttons.."); - static int pressed_count = 0; - for (int i = 0; i < 8; i++) - { - // UV coordinates are often (0.0f, 0.0f) and (1.0f, 1.0f) to display an entire textures. - // Here are trying to display only a 32x32 pixels area of the texture, hence the UV computation. - // Read about UV coordinates here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples - ImGui::PushID(i); - if (i > 0) - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(i - 1.0f, i - 1.0f)); - ImVec2 size = ImVec2(32.0f, 32.0f); // Size of the image we want to make visible - ImVec2 uv0 = ImVec2(0.0f, 0.0f); // UV coordinates for lower-left - ImVec2 uv1 = ImVec2(32.0f / my_tex_w, 32.0f / my_tex_h); // UV coordinates for (32,32) in our texture - ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); // Black background - ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint - if (ImGui::ImageButton("", my_tex_id, size, uv0, uv1, bg_col, tint_col)) - pressed_count += 1; - if (i > 0) - ImGui::PopStyleVar(); - ImGui::PopID(); - ImGui::SameLine(); - } - ImGui::NewLine(); - ImGui::Text("Pressed %d times.", pressed_count); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Combo"); - if (ImGui::TreeNode("Combo")) - { - // Combo Boxes are also called "Dropdown" in other systems - // Expose flags as checkbox for the demo - static ImGuiComboFlags flags = 0; - ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft); - ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo"); - if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton)) - flags &= ~ImGuiComboFlags_NoPreview; // Clear incompatible flags - if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview)) - flags &= ~(ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_WidthFitPreview); // Clear incompatible flags - if (ImGui::CheckboxFlags("ImGuiComboFlags_WidthFitPreview", &flags, ImGuiComboFlags_WidthFitPreview)) - flags &= ~ImGuiComboFlags_NoPreview; - - // Override default popup height - if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightSmall", &flags, ImGuiComboFlags_HeightSmall)) - flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightSmall); - if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightRegular", &flags, ImGuiComboFlags_HeightRegular)) - flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightRegular); - if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightLargest", &flags, ImGuiComboFlags_HeightLargest)) - flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightLargest); - - // Using the generic BeginCombo() API, you have full control over how to display the combo contents. - // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively - // stored in the object itself, etc.) - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; - static int item_selected_idx = 0; // Here we store our selection data as an index. - - // Pass in the preview value visible before opening the combo (it could technically be different contents or not pulled from items[]) - const char* combo_preview_value = items[item_selected_idx]; - if (ImGui::BeginCombo("combo 1", combo_preview_value, flags)) - { - for (int n = 0; n < IM_ARRAYSIZE(items); n++) - { - const bool is_selected = (item_selected_idx == n); - if (ImGui::Selectable(items[n], is_selected)) - item_selected_idx = n; - - // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndCombo(); - } - - // Show case embedding a filter using a simple trick: displaying the filter inside combo contents. - // See https://github.com/ocornut/imgui/issues/718 for advanced/esoteric alternatives. - if (ImGui::BeginCombo("combo 2 (w/ filter)", combo_preview_value, flags)) - { - static ImGuiTextFilter filter; - if (ImGui::IsWindowAppearing()) - { - ImGui::SetKeyboardFocusHere(); - filter.Clear(); - } - ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F); - filter.Draw("##Filter", -FLT_MIN); - - for (int n = 0; n < IM_ARRAYSIZE(items); n++) - { - const bool is_selected = (item_selected_idx == n); - if (filter.PassFilter(items[n])) - if (ImGui::Selectable(items[n], is_selected)) - item_selected_idx = n; - } - ImGui::EndCombo(); - } - - ImGui::Spacing(); - ImGui::SeparatorText("One-liner variants"); - HelpMarker("The Combo() function is not greatly useful apart from cases were you want to embed all options in a single strings.\nFlags above don't apply to this section."); - - // Simplified one-liner Combo() API, using values packed in a single constant string - // This is a convenience for when the selection set is small and known at compile-time. - static int item_current_2 = 0; - ImGui::Combo("combo 3 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); - - // Simplified one-liner Combo() using an array of const char* - // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control. - static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview - ImGui::Combo("combo 4 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); - - // Simplified one-liner Combo() using an accessor function - static int item_current_4 = 0; - ImGui::Combo("combo 5 (function)", &item_current_4, [](void* data, int n) { return ((const char**)data)[n]; }, items, IM_ARRAYSIZE(items)); - - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/List Boxes"); - if (ImGui::TreeNode("List boxes")) - { - // BeginListBox() is essentially a thin wrapper to using BeginChild()/EndChild() - // using the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. - // You may be tempted to simply use BeginChild() directly. However note that BeginChild() requires EndChild() - // to always be called (inconsistent with BeginListBox()/EndListBox()). - - // Using the generic BeginListBox() API, you have full control over how to display the combo contents. - // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively - // stored in the object itself, etc.) - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; - static int item_selected_idx = 0; // Here we store our selected data as an index. - - static bool item_highlight = false; - int item_highlighted_idx = -1; // Here we store our highlighted data as an index. - ImGui::Checkbox("Highlight hovered item in second listbox", &item_highlight); - - if (ImGui::BeginListBox("listbox 1")) - { - for (int n = 0; n < IM_ARRAYSIZE(items); n++) - { - const bool is_selected = (item_selected_idx == n); - if (ImGui::Selectable(items[n], is_selected)) - item_selected_idx = n; - - if (item_highlight && ImGui::IsItemHovered()) - item_highlighted_idx = n; - - // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndListBox(); - } - ImGui::SameLine(); HelpMarker("Here we are sharing selection state between both boxes."); - - // Custom size: use all width, 5 items tall - ImGui::Text("Full-width:"); - if (ImGui::BeginListBox("##listbox 2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing()))) - { - for (int n = 0; n < IM_ARRAYSIZE(items); n++) - { - bool is_selected = (item_selected_idx == n); - ImGuiSelectableFlags flags = (item_highlighted_idx == n) ? ImGuiSelectableFlags_Highlight : 0; - if (ImGui::Selectable(items[n], is_selected, flags)) - item_selected_idx = n; - - // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) - if (is_selected) - ImGui::SetItemDefaultFocus(); - } - ImGui::EndListBox(); - } - - ImGui::TreePop(); - } - IMGUI_DEMO_MARKER("Widgets/Selectables"); //ImGui::SetNextItemOpen(true, ImGuiCond_Once); if (ImGui::TreeNode("Selectables")) @@ -2758,6 +2534,99 @@ static void DemoWindowWidgetsCollapsingHeaders() // [SECTION] DemoWindowWidgetsComboBoxes() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsComboBoxes() +{ + IMGUI_DEMO_MARKER("Widgets/Combo"); + if (ImGui::TreeNode("Combo")) + { + // Combo Boxes are also called "Dropdown" in other systems + // Expose flags as checkbox for the demo + static ImGuiComboFlags flags = 0; + ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft); + ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo"); + if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton)) + flags &= ~ImGuiComboFlags_NoPreview; // Clear incompatible flags + if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview)) + flags &= ~(ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_WidthFitPreview); // Clear incompatible flags + if (ImGui::CheckboxFlags("ImGuiComboFlags_WidthFitPreview", &flags, ImGuiComboFlags_WidthFitPreview)) + flags &= ~ImGuiComboFlags_NoPreview; + + // Override default popup height + if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightSmall", &flags, ImGuiComboFlags_HeightSmall)) + flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightSmall); + if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightRegular", &flags, ImGuiComboFlags_HeightRegular)) + flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightRegular); + if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightLargest", &flags, ImGuiComboFlags_HeightLargest)) + flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightLargest); + + // Using the generic BeginCombo() API, you have full control over how to display the combo contents. + // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively + // stored in the object itself, etc.) + const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; + static int item_selected_idx = 0; // Here we store our selection data as an index. + + // Pass in the preview value visible before opening the combo (it could technically be different contents or not pulled from items[]) + const char* combo_preview_value = items[item_selected_idx]; + if (ImGui::BeginCombo("combo 1", combo_preview_value, flags)) + { + for (int n = 0; n < IM_ARRAYSIZE(items); n++) + { + const bool is_selected = (item_selected_idx == n); + if (ImGui::Selectable(items[n], is_selected)) + item_selected_idx = n; + + // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + // Show case embedding a filter using a simple trick: displaying the filter inside combo contents. + // See https://github.com/ocornut/imgui/issues/718 for advanced/esoteric alternatives. + if (ImGui::BeginCombo("combo 2 (w/ filter)", combo_preview_value, flags)) + { + static ImGuiTextFilter filter; + if (ImGui::IsWindowAppearing()) + { + ImGui::SetKeyboardFocusHere(); + filter.Clear(); + } + ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F); + filter.Draw("##Filter", -FLT_MIN); + + for (int n = 0; n < IM_ARRAYSIZE(items); n++) + { + const bool is_selected = (item_selected_idx == n); + if (filter.PassFilter(items[n])) + if (ImGui::Selectable(items[n], is_selected)) + item_selected_idx = n; + } + ImGui::EndCombo(); + } + + ImGui::Spacing(); + ImGui::SeparatorText("One-liner variants"); + HelpMarker("The Combo() function is not greatly useful apart from cases were you want to embed all options in a single strings.\nFlags above don't apply to this section."); + + // Simplified one-liner Combo() API, using values packed in a single constant string + // This is a convenience for when the selection set is small and known at compile-time. + static int item_current_2 = 0; + ImGui::Combo("combo 3 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); + + // Simplified one-liner Combo() using an array of const char* + // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control. + static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview + ImGui::Combo("combo 4 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); + + // Simplified one-liner Combo() using an accessor function + static int item_current_4 = 0; + ImGui::Combo("combo 5 (function)", &item_current_4, [](void* data, int n) { return ((const char**)data)[n]; }, items, IM_ARRAYSIZE(items)); + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsDataTypes() //----------------------------------------------------------------------------- @@ -2778,10 +2647,156 @@ static void DemoWindowWidgetsCollapsingHeaders() // [SECTION] DemoWindowWidgetsImages() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsImages() +{ + IMGUI_DEMO_MARKER("Widgets/Images"); + if (ImGui::TreeNode("Images")) + { + ImGuiIO& io = ImGui::GetIO(); + ImGui::TextWrapped( + "Below we are displaying the font texture (which is the only texture we have access to in this demo). " + "Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. " + "Hover the texture for a zoomed view!"); + + // Below we are displaying the font texture because it is the only texture we have access to inside the demo! + // Remember that ImTextureID is just storage for whatever you want it to be. It is essentially a value that + // will be passed to the rendering backend via the ImDrawCmd structure. + // If you use one of the default imgui_impl_XXXX.cpp rendering backend, they all have comments at the top + // of their respective source file to specify what they expect to be stored in ImTextureID, for example: + // - The imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer + // - The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier, etc. + // More: + // - If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers + // to ImGui::Image(), and gather width/height through your own functions, etc. + // - You can use ShowMetricsWindow() to inspect the draw data that are being passed to your renderer, + // it will help you debug issues if you are confused about it. + // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage(). + // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md + // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples + ImTextureID my_tex_id = io.Fonts->TexID; + float my_tex_w = (float)io.Fonts->TexWidth; + float my_tex_h = (float)io.Fonts->TexHeight; + { + ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h); + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left + ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right + ImGui::PushStyleVar(ImGuiStyleVar_ImageBorderSize, IM_MAX(1.0f, ImGui::GetStyle().ImageBorderSize)); + ImGui::ImageWithBg(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + if (ImGui::BeginItemTooltip()) + { + float region_sz = 32.0f; + float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; + float region_y = io.MousePos.y - pos.y - region_sz * 0.5f; + float zoom = 4.0f; + if (region_x < 0.0f) { region_x = 0.0f; } + else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; } + if (region_y < 0.0f) { region_y = 0.0f; } + else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; } + ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y); + ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz); + ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h); + ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h); + ImGui::ImageWithBg(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImVec4(0.0f, 0.0f, 0.0f, 1.0f)); + ImGui::EndTooltip(); + } + ImGui::PopStyleVar(); + } + + IMGUI_DEMO_MARKER("Widgets/Images/Textured buttons"); + ImGui::TextWrapped("And now some textured buttons.."); + static int pressed_count = 0; + for (int i = 0; i < 8; i++) + { + // UV coordinates are often (0.0f, 0.0f) and (1.0f, 1.0f) to display an entire textures. + // Here are trying to display only a 32x32 pixels area of the texture, hence the UV computation. + // Read about UV coordinates here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples + ImGui::PushID(i); + if (i > 0) + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(i - 1.0f, i - 1.0f)); + ImVec2 size = ImVec2(32.0f, 32.0f); // Size of the image we want to make visible + ImVec2 uv0 = ImVec2(0.0f, 0.0f); // UV coordinates for lower-left + ImVec2 uv1 = ImVec2(32.0f / my_tex_w, 32.0f / my_tex_h); // UV coordinates for (32,32) in our texture + ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); // Black background + ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint + if (ImGui::ImageButton("", my_tex_id, size, uv0, uv1, bg_col, tint_col)) + pressed_count += 1; + if (i > 0) + ImGui::PopStyleVar(); + ImGui::PopID(); + ImGui::SameLine(); + } + ImGui::NewLine(); + ImGui::Text("Pressed %d times.", pressed_count); + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsListBoxes() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsListBoxes() +{ + IMGUI_DEMO_MARKER("Widgets/List Boxes"); + if (ImGui::TreeNode("List boxes")) + { + // BeginListBox() is essentially a thin wrapper to using BeginChild()/EndChild() + // using the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. + // You may be tempted to simply use BeginChild() directly. However note that BeginChild() requires EndChild() + // to always be called (inconsistent with BeginListBox()/EndListBox()). + + // Using the generic BeginListBox() API, you have full control over how to display the combo contents. + // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively + // stored in the object itself, etc.) + const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; + static int item_selected_idx = 0; // Here we store our selected data as an index. + + static bool item_highlight = false; + int item_highlighted_idx = -1; // Here we store our highlighted data as an index. + ImGui::Checkbox("Highlight hovered item in second listbox", &item_highlight); + + if (ImGui::BeginListBox("listbox 1")) + { + for (int n = 0; n < IM_ARRAYSIZE(items); n++) + { + const bool is_selected = (item_selected_idx == n); + if (ImGui::Selectable(items[n], is_selected)) + item_selected_idx = n; + + if (item_highlight && ImGui::IsItemHovered()) + item_highlighted_idx = n; + + // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndListBox(); + } + ImGui::SameLine(); HelpMarker("Here we are sharing selection state between both boxes."); + + // Custom size: use all width, 5 items tall + ImGui::Text("Full-width:"); + if (ImGui::BeginListBox("##listbox 2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing()))) + { + for (int n = 0; n < IM_ARRAYSIZE(items); n++) + { + bool is_selected = (item_selected_idx == n); + ImGuiSelectableFlags flags = (item_highlighted_idx == n) ? ImGuiSelectableFlags_Highlight : 0; + if (ImGui::Selectable(items[n], is_selected, flags)) + item_selected_idx = n; + + // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndListBox(); + } + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsMultiComponents() //----------------------------------------------------------------------------- From 4450d61ac25771bd0116754607a33a5eb1da33b3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 18:01:41 +0100 Subject: [PATCH 508/548] Demo: (Refactor) Moved code into DemoWindowWidgetsSelectables(), DemoWindowWidgetsTextFilter(), DemoWindowWidgetsTextInputs() sections. --- imgui_demo.cpp | 779 +++++++++++++++++++++++++------------------------ 1 file changed, 397 insertions(+), 382 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3b08b152f73f..56688d4c4879 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -256,8 +256,11 @@ static void DemoWindowWidgetsCollapsingHeaders(); static void DemoWindowWidgetsComboBoxes(); static void DemoWindowWidgetsImages(); static void DemoWindowWidgetsListBoxes(); +static void DemoWindowWidgetsSelectables(); static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgetsText(); +static void DemoWindowWidgetsTextFilter(); +static void DemoWindowWidgetsTextInput(); static void DemoWindowWidgetsTooltips(); static void DemoWindowWidgetsTreeNodes(); static void DemoWindowLayout(); @@ -822,347 +825,14 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsComboBoxes(); DemoWindowWidgetsImages(); DemoWindowWidgetsListBoxes(); + DemoWindowWidgetsSelectables(); + DemoWindowWidgetsSelectionAndMultiSelect(demo_data); DemoWindowWidgetsText(); + DemoWindowWidgetsTextFilter(); + DemoWindowWidgetsTextInput(); DemoWindowWidgetsTooltips(); DemoWindowWidgetsTreeNodes(); - IMGUI_DEMO_MARKER("Widgets/Selectables"); - //ImGui::SetNextItemOpen(true, ImGuiCond_Once); - if (ImGui::TreeNode("Selectables")) - { - // Selectable() has 2 overloads: - // - The one taking "bool selected" as a read-only selection information. - // When Selectable() has been clicked it returns true and you can alter selection state accordingly. - // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases) - // The earlier is more flexible, as in real application your selection may be stored in many different ways - // and not necessarily inside a bool value (e.g. in flags within objects, as an external list, etc). - IMGUI_DEMO_MARKER("Widgets/Selectables/Basic"); - if (ImGui::TreeNode("Basic")) - { - static bool selection[5] = { false, true, false, false }; - ImGui::Selectable("1. I am selectable", &selection[0]); - ImGui::Selectable("2. I am selectable", &selection[1]); - ImGui::Selectable("3. I am selectable", &selection[2]); - if (ImGui::Selectable("4. I am double clickable", selection[3], ImGuiSelectableFlags_AllowDoubleClick)) - if (ImGui::IsMouseDoubleClicked(0)) - selection[3] = !selection[3]; - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Selectables/Rendering more items on the same line"); - if (ImGui::TreeNode("Rendering more items on the same line")) - { - // (1) Using SetNextItemAllowOverlap() - // (2) Using the Selectable() override that takes "bool* p_selected" parameter, the bool value is toggled automatically. - static bool selected[3] = { false, false, false }; - ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(); ImGui::SmallButton("Link 1"); - ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(); ImGui::SmallButton("Link 2"); - ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(); ImGui::SmallButton("Link 3"); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Selectables/In Tables"); - if (ImGui::TreeNode("In Tables")) - { - static bool selected[10] = {}; - - if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) - { - for (int i = 0; i < 10; i++) - { - char label[32]; - sprintf(label, "Item %d", i); - ImGui::TableNextColumn(); - ImGui::Selectable(label, &selected[i]); // FIXME-TABLE: Selection overlap - } - ImGui::EndTable(); - } - ImGui::Spacing(); - if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) - { - for (int i = 0; i < 10; i++) - { - char label[32]; - sprintf(label, "Item %d", i); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Selectable(label, &selected[i], ImGuiSelectableFlags_SpanAllColumns); - ImGui::TableNextColumn(); - ImGui::Text("Some other contents"); - ImGui::TableNextColumn(); - ImGui::Text("123456"); - } - ImGui::EndTable(); - } - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Selectables/Grid"); - if (ImGui::TreeNode("Grid")) - { - static char selected[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; - - // Add in a bit of silly fun... - const float time = (float)ImGui::GetTime(); - const bool winning_state = memchr(selected, 0, sizeof(selected)) == NULL; // If all cells are selected... - if (winning_state) - ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f + 0.5f * cosf(time * 2.0f), 0.5f + 0.5f * sinf(time * 3.0f))); - - for (int y = 0; y < 4; y++) - for (int x = 0; x < 4; x++) - { - if (x > 0) - ImGui::SameLine(); - ImGui::PushID(y * 4 + x); - if (ImGui::Selectable("Sailor", selected[y][x] != 0, 0, ImVec2(50, 50))) - { - // Toggle clicked cell + toggle neighbors - selected[y][x] ^= 1; - if (x > 0) { selected[y][x - 1] ^= 1; } - if (x < 3) { selected[y][x + 1] ^= 1; } - if (y > 0) { selected[y - 1][x] ^= 1; } - if (y < 3) { selected[y + 1][x] ^= 1; } - } - ImGui::PopID(); - } - - if (winning_state) - ImGui::PopStyleVar(); - ImGui::TreePop(); - } - IMGUI_DEMO_MARKER("Widgets/Selectables/Alignment"); - if (ImGui::TreeNode("Alignment")) - { - HelpMarker( - "By default, Selectables uses style.SelectableTextAlign but it can be overridden on a per-item " - "basis using PushStyleVar(). You'll probably want to always keep your default situation to " - "left-align otherwise it becomes difficult to layout multiple items on a same line"); - static bool selected[3 * 3] = { true, false, true, false, true, false, true, false, true }; - for (int y = 0; y < 3; y++) - { - for (int x = 0; x < 3; x++) - { - ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f); - char name[32]; - sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y); - if (x > 0) ImGui::SameLine(); - ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment); - ImGui::Selectable(name, &selected[3 * y + x], ImGuiSelectableFlags_None, ImVec2(80, 80)); - ImGui::PopStyleVar(); - } - } - ImGui::TreePop(); - } - ImGui::TreePop(); - } - - DemoWindowWidgetsSelectionAndMultiSelect(demo_data); - - // To wire InputText() with std::string or any other custom string type, - // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. - IMGUI_DEMO_MARKER("Widgets/Text Input"); - if (ImGui::TreeNode("Text Input")) - { - IMGUI_DEMO_MARKER("Widgets/Text Input/Multi-line Text Input"); - if (ImGui::TreeNode("Multi-line Text Input")) - { - // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize - // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings. - static char text[1024 * 16] = - "/*\n" - " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n" - " the hexadecimal encoding of one offending instruction,\n" - " more formally, the invalid operand with locked CMPXCHG8B\n" - " instruction bug, is a design flaw in the majority of\n" - " Intel Pentium, Pentium MMX, and Pentium OverDrive\n" - " processors (all in the P5 microarchitecture).\n" - "*/\n\n" - "label:\n" - "\tlock cmpxchg8b eax\n"; - - static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput; - HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include in here)"); - ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); - ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput); - ImGui::SameLine(); HelpMarker("When _AllowTabInput is set, passing through the widget with Tabbing doesn't automatically activate it, in order to also cycling through subsequent widgets."); - ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine); - ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Text Input/Filtered Text Input"); - if (ImGui::TreeNode("Filtered Text Input")) - { - struct TextFilters - { - // Modify character input by altering 'data->Eventchar' (ImGuiInputTextFlags_CallbackCharFilter callback) - static int FilterCasingSwap(ImGuiInputTextCallbackData* data) - { - if (data->EventChar >= 'a' && data->EventChar <= 'z') { data->EventChar -= 'a' - 'A'; } // Lowercase becomes uppercase - else if (data->EventChar >= 'A' && data->EventChar <= 'Z') { data->EventChar += 'a' - 'A'; } // Uppercase becomes lowercase - return 0; - } - - // Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i', otherwise return 1 (filter out) - static int FilterImGuiLetters(ImGuiInputTextCallbackData* data) - { - if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) - return 0; - return 1; - } - }; - - static char buf1[32] = ""; ImGui::InputText("default", buf1, 32); - static char buf2[32] = ""; ImGui::InputText("decimal", buf2, 32, ImGuiInputTextFlags_CharsDecimal); - static char buf3[32] = ""; ImGui::InputText("hexadecimal", buf3, 32, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); - static char buf4[32] = ""; ImGui::InputText("uppercase", buf4, 32, ImGuiInputTextFlags_CharsUppercase); - static char buf5[32] = ""; ImGui::InputText("no blank", buf5, 32, ImGuiInputTextFlags_CharsNoBlank); - static char buf6[32] = ""; ImGui::InputText("casing swap", buf6, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterCasingSwap); // Use CharFilter callback to replace characters. - static char buf7[32] = ""; ImGui::InputText("\"imgui\"", buf7, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); // Use CharFilter callback to disable some characters. - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Text Input/Password input"); - if (ImGui::TreeNode("Password Input")) - { - static char password[64] = "password123"; - ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password); - ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n"); - ImGui::InputTextWithHint("password (w/ hint)", "", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password); - ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password)); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Text Input/Completion, History, Edit Callbacks"); - if (ImGui::TreeNode("Completion, History, Edit Callbacks")) - { - struct Funcs - { - static int MyCallback(ImGuiInputTextCallbackData* data) - { - if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion) - { - data->InsertChars(data->CursorPos, ".."); - } - else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory) - { - if (data->EventKey == ImGuiKey_UpArrow) - { - data->DeleteChars(0, data->BufTextLen); - data->InsertChars(0, "Pressed Up!"); - data->SelectAll(); - } - else if (data->EventKey == ImGuiKey_DownArrow) - { - data->DeleteChars(0, data->BufTextLen); - data->InsertChars(0, "Pressed Down!"); - data->SelectAll(); - } - } - else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit) - { - // Toggle casing of first character - char c = data->Buf[0]; - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) data->Buf[0] ^= 32; - data->BufDirty = true; - - // Increment a counter - int* p_int = (int*)data->UserData; - *p_int = *p_int + 1; - } - return 0; - } - }; - static char buf1[64]; - ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback); - ImGui::SameLine(); HelpMarker( - "Here we append \"..\" each time Tab is pressed. " - "See 'Examples>Console' for a more meaningful demonstration of using this callback."); - - static char buf2[64]; - ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback); - ImGui::SameLine(); HelpMarker( - "Here we replace and select text each time Up/Down are pressed. " - "See 'Examples>Console' for a more meaningful demonstration of using this callback."); - - static char buf3[64]; - static int edit_count = 0; - ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count); - ImGui::SameLine(); HelpMarker( - "Here we toggle the casing of the first character on every edit + count edits."); - ImGui::SameLine(); ImGui::Text("(%d)", edit_count); - - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Text Input/Resize Callback"); - if (ImGui::TreeNode("Resize Callback")) - { - // To wire InputText() with std::string or any other custom string type, - // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper - // using your preferred type. See misc/cpp/imgui_stdlib.h for an implementation of this using std::string. - HelpMarker( - "Using ImGuiInputTextFlags_CallbackResize to wire your custom string type to InputText().\n\n" - "See misc/cpp/imgui_stdlib.h for an implementation of this for std::string."); - struct Funcs - { - static int MyResizeCallback(ImGuiInputTextCallbackData* data) - { - if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) - { - ImVector* my_str = (ImVector*)data->UserData; - IM_ASSERT(my_str->begin() == data->Buf); - my_str->resize(data->BufSize); // NB: On resizing calls, generally data->BufSize == data->BufTextLen + 1 - data->Buf = my_str->begin(); - } - return 0; - } - - // Note: Because ImGui:: is a namespace you would typically add your own function into the namespace. - // For example, you code may declare a function 'ImGui::InputText(const char* label, MyString* my_str)' - static bool MyInputTextMultiline(const char* label, ImVector* my_str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0) - { - IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); - return ImGui::InputTextMultiline(label, my_str->begin(), (size_t)my_str->size(), size, flags | ImGuiInputTextFlags_CallbackResize, Funcs::MyResizeCallback, (void*)my_str); - } - }; - - // For this demo we are using ImVector as a string container. - // Note that because we need to store a terminating zero character, our size/capacity are 1 more - // than usually reported by a typical string class. - static ImVector my_str; - if (my_str.empty()) - my_str.push_back(0); - Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16)); - ImGui::Text("Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity()); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Text Input/Eliding, Alignment"); - if (ImGui::TreeNode("Eliding, Alignment")) - { - static char buf1[128] = "/path/to/some/folder/with/long/filename.cpp"; - static ImGuiInputTextFlags flags = ImGuiInputTextFlags_ElideLeft; - ImGui::CheckboxFlags("ImGuiInputTextFlags_ElideLeft", &flags, ImGuiInputTextFlags_ElideLeft); - ImGui::InputText("Path", buf1, IM_ARRAYSIZE(buf1), flags); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Text Input/Miscellaneous"); - if (ImGui::TreeNode("Miscellaneous")) - { - static char buf1[16]; - static ImGuiInputTextFlags flags = ImGuiInputTextFlags_EscapeClearsAll; - ImGui::CheckboxFlags("ImGuiInputTextFlags_EscapeClearsAll", &flags, ImGuiInputTextFlags_EscapeClearsAll); - ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); - ImGui::CheckboxFlags("ImGuiInputTextFlags_NoUndoRedo", &flags, ImGuiInputTextFlags_NoUndoRedo); - ImGui::InputText("Hello", buf1, IM_ARRAYSIZE(buf1), flags); - ImGui::TreePop(); - } - - ImGui::TreePop(); - } - // Tabs IMGUI_DEMO_MARKER("Widgets/Tabs"); if (ImGui::TreeNode("Tabs")) @@ -2240,26 +1910,6 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::SameLine(); HelpMarker("Demonstrate using BeginDisabled()/EndDisabled() across this section."); ImGui::TreePop(); } - - IMGUI_DEMO_MARKER("Widgets/Text Filter"); - if (ImGui::TreeNode("Text Filter")) - { - // Helper class to easy setup a text filter. - // You may want to implement a more feature-full filtering scheme in your own application. - HelpMarker("Not a widget per-se, but ImGuiTextFilter is a helper to perform simple filtering on text strings."); - static ImGuiTextFilter filter; - ImGui::Text("Filter usage:\n" - " \"\" display all lines\n" - " \"xxx\" display lines containing \"xxx\"\n" - " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n" - " \"-xxx\" hide lines containing \"xxx\""); - filter.Draw(); - const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" }; - for (int i = 0; i < IM_ARRAYSIZE(lines); i++) - if (filter.PassFilter(lines[i])) - ImGui::BulletText("%s", lines[i]); - ImGui::TreePop(); - } } //----------------------------------------------------------------------------- @@ -2790,31 +2440,171 @@ static void DemoWindowWidgetsListBoxes() if (is_selected) ImGui::SetItemDefaultFocus(); } - ImGui::EndListBox(); + ImGui::EndListBox(); + } + + ImGui::TreePop(); + } +} + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsMultiComponents() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsPlotting() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsProgressBars() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsQueryingStatuses() +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgetsSelectables() +//----------------------------------------------------------------------------- + +static void DemoWindowWidgetsSelectables() +{ + IMGUI_DEMO_MARKER("Widgets/Selectables"); + //ImGui::SetNextItemOpen(true, ImGuiCond_Once); + if (ImGui::TreeNode("Selectables")) + { + // Selectable() has 2 overloads: + // - The one taking "bool selected" as a read-only selection information. + // When Selectable() has been clicked it returns true and you can alter selection state accordingly. + // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases) + // The earlier is more flexible, as in real application your selection may be stored in many different ways + // and not necessarily inside a bool value (e.g. in flags within objects, as an external list, etc). + IMGUI_DEMO_MARKER("Widgets/Selectables/Basic"); + if (ImGui::TreeNode("Basic")) + { + static bool selection[5] = { false, true, false, false }; + ImGui::Selectable("1. I am selectable", &selection[0]); + ImGui::Selectable("2. I am selectable", &selection[1]); + ImGui::Selectable("3. I am selectable", &selection[2]); + if (ImGui::Selectable("4. I am double clickable", selection[3], ImGuiSelectableFlags_AllowDoubleClick)) + if (ImGui::IsMouseDoubleClicked(0)) + selection[3] = !selection[3]; + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Selectables/Rendering more items on the same line"); + if (ImGui::TreeNode("Rendering more items on the same line")) + { + // (1) Using SetNextItemAllowOverlap() + // (2) Using the Selectable() override that takes "bool* p_selected" parameter, the bool value is toggled automatically. + static bool selected[3] = { false, false, false }; + ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(); ImGui::SmallButton("Link 1"); + ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(); ImGui::SmallButton("Link 2"); + ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(); ImGui::SmallButton("Link 3"); + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Selectables/In Tables"); + if (ImGui::TreeNode("In Tables")) + { + static bool selected[10] = {}; + + if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) + { + for (int i = 0; i < 10; i++) + { + char label[32]; + sprintf(label, "Item %d", i); + ImGui::TableNextColumn(); + ImGui::Selectable(label, &selected[i]); // FIXME-TABLE: Selection overlap + } + ImGui::EndTable(); + } + ImGui::Spacing(); + if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders)) + { + for (int i = 0; i < 10; i++) + { + char label[32]; + sprintf(label, "Item %d", i); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Selectable(label, &selected[i], ImGuiSelectableFlags_SpanAllColumns); + ImGui::TableNextColumn(); + ImGui::Text("Some other contents"); + ImGui::TableNextColumn(); + ImGui::Text("123456"); + } + ImGui::EndTable(); + } + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Selectables/Grid"); + if (ImGui::TreeNode("Grid")) + { + static char selected[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } }; + + // Add in a bit of silly fun... + const float time = (float)ImGui::GetTime(); + const bool winning_state = memchr(selected, 0, sizeof(selected)) == NULL; // If all cells are selected... + if (winning_state) + ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f + 0.5f * cosf(time * 2.0f), 0.5f + 0.5f * sinf(time * 3.0f))); + + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + { + if (x > 0) + ImGui::SameLine(); + ImGui::PushID(y * 4 + x); + if (ImGui::Selectable("Sailor", selected[y][x] != 0, 0, ImVec2(50, 50))) + { + // Toggle clicked cell + toggle neighbors + selected[y][x] ^= 1; + if (x > 0) { selected[y][x - 1] ^= 1; } + if (x < 3) { selected[y][x + 1] ^= 1; } + if (y > 0) { selected[y - 1][x] ^= 1; } + if (y < 3) { selected[y + 1][x] ^= 1; } + } + ImGui::PopID(); + } + + if (winning_state) + ImGui::PopStyleVar(); + ImGui::TreePop(); + } + IMGUI_DEMO_MARKER("Widgets/Selectables/Alignment"); + if (ImGui::TreeNode("Alignment")) + { + HelpMarker( + "By default, Selectables uses style.SelectableTextAlign but it can be overridden on a per-item " + "basis using PushStyleVar(). You'll probably want to always keep your default situation to " + "left-align otherwise it becomes difficult to layout multiple items on a same line"); + static bool selected[3 * 3] = { true, false, true, false, true, false, true, false, true }; + for (int y = 0; y < 3; y++) + { + for (int x = 0; x < 3; x++) + { + ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f); + char name[32]; + sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y); + if (x > 0) ImGui::SameLine(); + ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment); + ImGui::Selectable(name, &selected[3 * y + x], ImGuiSelectableFlags_None, ImVec2(80, 80)); + ImGui::PopStyleVar(); + } + } + ImGui::TreePop(); } - ImGui::TreePop(); } } //----------------------------------------------------------------------------- -// [SECTION] DemoWindowWidgetsMultiComponents() -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// [SECTION] DemoWindowWidgetsPlotting() -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// [SECTION] DemoWindowWidgetsProgressBars() -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// [SECTION] DemoWindowWidgetsQueryingStatuses() -//----------------------------------------------------------------------------- - +// [SECTION] DemoWindowWidgetsSelectionAndMultiSelect() //----------------------------------------------------------------------------- -// [SECTION] DemoWindowWidgetsSelectables() +// Multi-selection demos +// Also read: https://github.com/ocornut/imgui/wiki/Multi-Select //----------------------------------------------------------------------------- static const char* ExampleNames[] = @@ -3042,13 +2832,6 @@ struct ExampleDualListBox } }; -//----------------------------------------------------------------------------- -// [SECTION] DemoWindowWidgetsSelectionAndMultiSelect() -//----------------------------------------------------------------------------- -// Multi-selection demos -// Also read: https://github.com/ocornut/imgui/wiki/Multi-Select -//----------------------------------------------------------------------------- - static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data) { IMGUI_DEMO_MARKER("Widgets/Selection State & Multi-Select"); @@ -3874,10 +3657,242 @@ static void DemoWindowWidgetsText() // [SECTION] DemoWindowWidgetsTextFilter() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsTextFilter() +{ + IMGUI_DEMO_MARKER("Widgets/Text Filter"); + if (ImGui::TreeNode("Text Filter")) + { + // Helper class to easy setup a text filter. + // You may want to implement a more feature-full filtering scheme in your own application. + HelpMarker("Not a widget per-se, but ImGuiTextFilter is a helper to perform simple filtering on text strings."); + static ImGuiTextFilter filter; + ImGui::Text("Filter usage:\n" + " \"\" display all lines\n" + " \"xxx\" display lines containing \"xxx\"\n" + " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n" + " \"-xxx\" hide lines containing \"xxx\""); + filter.Draw(); + const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" }; + for (int i = 0; i < IM_ARRAYSIZE(lines); i++) + if (filter.PassFilter(lines[i])) + ImGui::BulletText("%s", lines[i]); + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsTextInput() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsTextInput() +{ + // To wire InputText() with std::string or any other custom string type, + // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file. + IMGUI_DEMO_MARKER("Widgets/Text Input"); + if (ImGui::TreeNode("Text Input")) + { + IMGUI_DEMO_MARKER("Widgets/Text Input/Multi-line Text Input"); + if (ImGui::TreeNode("Multi-line Text Input")) + { + // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize + // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings. + static char text[1024 * 16] = + "/*\n" + " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n" + " the hexadecimal encoding of one offending instruction,\n" + " more formally, the invalid operand with locked CMPXCHG8B\n" + " instruction bug, is a design flaw in the majority of\n" + " Intel Pentium, Pentium MMX, and Pentium OverDrive\n" + " processors (all in the P5 microarchitecture).\n" + "*/\n\n" + "label:\n" + "\tlock cmpxchg8b eax\n"; + + static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput; + HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include in here)"); + ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); + ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput); + ImGui::SameLine(); HelpMarker("When _AllowTabInput is set, passing through the widget with Tabbing doesn't automatically activate it, in order to also cycling through subsequent widgets."); + ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine); + ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags); + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Text Input/Filtered Text Input"); + if (ImGui::TreeNode("Filtered Text Input")) + { + struct TextFilters + { + // Modify character input by altering 'data->Eventchar' (ImGuiInputTextFlags_CallbackCharFilter callback) + static int FilterCasingSwap(ImGuiInputTextCallbackData* data) + { + if (data->EventChar >= 'a' && data->EventChar <= 'z') { data->EventChar -= 'a' - 'A'; } // Lowercase becomes uppercase + else if (data->EventChar >= 'A' && data->EventChar <= 'Z') { data->EventChar += 'a' - 'A'; } // Uppercase becomes lowercase + return 0; + } + + // Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i', otherwise return 1 (filter out) + static int FilterImGuiLetters(ImGuiInputTextCallbackData* data) + { + if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) + return 0; + return 1; + } + }; + + static char buf1[32] = ""; ImGui::InputText("default", buf1, 32); + static char buf2[32] = ""; ImGui::InputText("decimal", buf2, 32, ImGuiInputTextFlags_CharsDecimal); + static char buf3[32] = ""; ImGui::InputText("hexadecimal", buf3, 32, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase); + static char buf4[32] = ""; ImGui::InputText("uppercase", buf4, 32, ImGuiInputTextFlags_CharsUppercase); + static char buf5[32] = ""; ImGui::InputText("no blank", buf5, 32, ImGuiInputTextFlags_CharsNoBlank); + static char buf6[32] = ""; ImGui::InputText("casing swap", buf6, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterCasingSwap); // Use CharFilter callback to replace characters. + static char buf7[32] = ""; ImGui::InputText("\"imgui\"", buf7, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); // Use CharFilter callback to disable some characters. + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Text Input/Password input"); + if (ImGui::TreeNode("Password Input")) + { + static char password[64] = "password123"; + ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password); + ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n"); + ImGui::InputTextWithHint("password (w/ hint)", "", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password); + ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password)); + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Text Input/Completion, History, Edit Callbacks"); + if (ImGui::TreeNode("Completion, History, Edit Callbacks")) + { + struct Funcs + { + static int MyCallback(ImGuiInputTextCallbackData* data) + { + if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion) + { + data->InsertChars(data->CursorPos, ".."); + } + else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory) + { + if (data->EventKey == ImGuiKey_UpArrow) + { + data->DeleteChars(0, data->BufTextLen); + data->InsertChars(0, "Pressed Up!"); + data->SelectAll(); + } + else if (data->EventKey == ImGuiKey_DownArrow) + { + data->DeleteChars(0, data->BufTextLen); + data->InsertChars(0, "Pressed Down!"); + data->SelectAll(); + } + } + else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit) + { + // Toggle casing of first character + char c = data->Buf[0]; + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) data->Buf[0] ^= 32; + data->BufDirty = true; + + // Increment a counter + int* p_int = (int*)data->UserData; + *p_int = *p_int + 1; + } + return 0; + } + }; + static char buf1[64]; + ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback); + ImGui::SameLine(); HelpMarker( + "Here we append \"..\" each time Tab is pressed. " + "See 'Examples>Console' for a more meaningful demonstration of using this callback."); + + static char buf2[64]; + ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback); + ImGui::SameLine(); HelpMarker( + "Here we replace and select text each time Up/Down are pressed. " + "See 'Examples>Console' for a more meaningful demonstration of using this callback."); + + static char buf3[64]; + static int edit_count = 0; + ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count); + ImGui::SameLine(); HelpMarker( + "Here we toggle the casing of the first character on every edit + count edits."); + ImGui::SameLine(); ImGui::Text("(%d)", edit_count); + + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Text Input/Resize Callback"); + if (ImGui::TreeNode("Resize Callback")) + { + // To wire InputText() with std::string or any other custom string type, + // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper + // using your preferred type. See misc/cpp/imgui_stdlib.h for an implementation of this using std::string. + HelpMarker( + "Using ImGuiInputTextFlags_CallbackResize to wire your custom string type to InputText().\n\n" + "See misc/cpp/imgui_stdlib.h for an implementation of this for std::string."); + struct Funcs + { + static int MyResizeCallback(ImGuiInputTextCallbackData* data) + { + if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) + { + ImVector* my_str = (ImVector*)data->UserData; + IM_ASSERT(my_str->begin() == data->Buf); + my_str->resize(data->BufSize); // NB: On resizing calls, generally data->BufSize == data->BufTextLen + 1 + data->Buf = my_str->begin(); + } + return 0; + } + + // Note: Because ImGui:: is a namespace you would typically add your own function into the namespace. + // For example, you code may declare a function 'ImGui::InputText(const char* label, MyString* my_str)' + static bool MyInputTextMultiline(const char* label, ImVector* my_str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0) + { + IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); + return ImGui::InputTextMultiline(label, my_str->begin(), (size_t)my_str->size(), size, flags | ImGuiInputTextFlags_CallbackResize, Funcs::MyResizeCallback, (void*)my_str); + } + }; + + // For this demo we are using ImVector as a string container. + // Note that because we need to store a terminating zero character, our size/capacity are 1 more + // than usually reported by a typical string class. + static ImVector my_str; + if (my_str.empty()) + my_str.push_back(0); + Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16)); + ImGui::Text("Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity()); + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Text Input/Eliding, Alignment"); + if (ImGui::TreeNode("Eliding, Alignment")) + { + static char buf1[128] = "/path/to/some/folder/with/long/filename.cpp"; + static ImGuiInputTextFlags flags = ImGuiInputTextFlags_ElideLeft; + ImGui::CheckboxFlags("ImGuiInputTextFlags_ElideLeft", &flags, ImGuiInputTextFlags_ElideLeft); + ImGui::InputText("Path", buf1, IM_ARRAYSIZE(buf1), flags); + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Text Input/Miscellaneous"); + if (ImGui::TreeNode("Miscellaneous")) + { + static char buf1[16]; + static ImGuiInputTextFlags flags = ImGuiInputTextFlags_EscapeClearsAll; + ImGui::CheckboxFlags("ImGuiInputTextFlags_EscapeClearsAll", &flags, ImGuiInputTextFlags_EscapeClearsAll); + ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); + ImGui::CheckboxFlags("ImGuiInputTextFlags_NoUndoRedo", &flags, ImGuiInputTextFlags_NoUndoRedo); + ImGui::InputText("Hello", buf1, IM_ARRAYSIZE(buf1), flags); + ImGui::TreePop(); + } + + ImGui::TreePop(); + } + +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsTooltips() //----------------------------------------------------------------------------- From 4d0c776a8089ccaa272f1cf51097e1d606f66d99 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 18:08:22 +0100 Subject: [PATCH 509/548] Demo: (Refactor) Moved code into DemoWindowWidgetsPlotting(), DemoWindowWidgetsProgressBars(), DemoWindowWidgetsTabs() sections. --- imgui_demo.cpp | 505 +++++++++++++++++++++++++------------------------ 1 file changed, 259 insertions(+), 246 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 56688d4c4879..468e32b598d9 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -256,8 +256,11 @@ static void DemoWindowWidgetsCollapsingHeaders(); static void DemoWindowWidgetsComboBoxes(); static void DemoWindowWidgetsImages(); static void DemoWindowWidgetsListBoxes(); +static void DemoWindowWidgetsPlotting(); +static void DemoWindowWidgetsProgressBars(); static void DemoWindowWidgetsSelectables(); static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data); +static void DemoWindowWidgetsTabs(); static void DemoWindowWidgetsText(); static void DemoWindowWidgetsTextFilter(); static void DemoWindowWidgetsTextInput(); @@ -825,260 +828,17 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsComboBoxes(); DemoWindowWidgetsImages(); DemoWindowWidgetsListBoxes(); + DemoWindowWidgetsPlotting(); + DemoWindowWidgetsProgressBars(); DemoWindowWidgetsSelectables(); DemoWindowWidgetsSelectionAndMultiSelect(demo_data); + DemoWindowWidgetsTabs(); DemoWindowWidgetsText(); DemoWindowWidgetsTextFilter(); DemoWindowWidgetsTextInput(); DemoWindowWidgetsTooltips(); DemoWindowWidgetsTreeNodes(); - // Tabs - IMGUI_DEMO_MARKER("Widgets/Tabs"); - if (ImGui::TreeNode("Tabs")) - { - IMGUI_DEMO_MARKER("Widgets/Tabs/Basic"); - if (ImGui::TreeNode("Basic")) - { - ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None; - if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) - { - if (ImGui::BeginTabItem("Avocado")) - { - ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah"); - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("Broccoli")) - { - ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah"); - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("Cucumber")) - { - ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah"); - ImGui::EndTabItem(); - } - ImGui::EndTabBar(); - } - ImGui::Separator(); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Tabs/Advanced & Close Button"); - if (ImGui::TreeNode("Advanced & Close Button")) - { - // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0). - static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable; - ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", &tab_bar_flags, ImGuiTabBarFlags_Reorderable); - ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", &tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs); - ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); - ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton); - ImGui::CheckboxFlags("ImGuiTabBarFlags_DrawSelectedOverline", &tab_bar_flags, ImGuiTabBarFlags_DrawSelectedOverline); - if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0) - tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_; - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown); - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll); - - // Tab Bar - ImGui::AlignTextToFramePadding(); - ImGui::Text("Opened:"); - const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" }; - static bool opened[4] = { true, true, true, true }; // Persistent user state - for (int n = 0; n < IM_ARRAYSIZE(opened); n++) - { - ImGui::SameLine(); - ImGui::Checkbox(names[n], &opened[n]); - } - - // Passing a bool* to BeginTabItem() is similar to passing one to Begin(): - // the underlying bool will be set to false when the tab is closed. - if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) - { - for (int n = 0; n < IM_ARRAYSIZE(opened); n++) - if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None)) - { - ImGui::Text("This is the %s tab!", names[n]); - if (n & 1) - ImGui::Text("I am an odd tab."); - ImGui::EndTabItem(); - } - ImGui::EndTabBar(); - } - ImGui::Separator(); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Tabs/TabItemButton & Leading-Trailing flags"); - if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags")) - { - static ImVector active_tabs; - static int next_tab_id = 0; - if (next_tab_id == 0) // Initialize with some default tabs - for (int i = 0; i < 3; i++) - active_tabs.push_back(next_tab_id++); - - // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together. - // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags... - // but they tend to make more sense together) - static bool show_leading_button = true; - static bool show_trailing_button = true; - ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button); - ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button); - - // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs - static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown; - ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown); - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll); - - if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) - { - // Demo a Leading TabItemButton(): click the "?" button to open a menu - if (show_leading_button) - if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip)) - ImGui::OpenPopup("MyHelpMenu"); - if (ImGui::BeginPopup("MyHelpMenu")) - { - ImGui::Selectable("Hello!"); - ImGui::EndPopup(); - } - - // Demo Trailing Tabs: click the "+" button to add a new tab. - // (In your app you may want to use a font icon instead of the "+") - // We submit it before the regular tabs, but thanks to the ImGuiTabItemFlags_Trailing flag it will always appear at the end. - if (show_trailing_button) - if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip)) - active_tabs.push_back(next_tab_id++); // Add new tab - - // Submit our regular tabs - for (int n = 0; n < active_tabs.Size; ) - { - bool open = true; - char name[16]; - snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]); - if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None)) - { - ImGui::Text("This is the %s tab!", name); - ImGui::EndTabItem(); - } - - if (!open) - active_tabs.erase(active_tabs.Data + n); - else - n++; - } - - ImGui::EndTabBar(); - } - ImGui::Separator(); - ImGui::TreePop(); - } - ImGui::TreePop(); - } - - // Plot/Graph widgets are not very good. - // Consider using a third-party library such as ImPlot: https://github.com/epezent/implot - // (see others https://github.com/ocornut/imgui/wiki/Useful-Extensions) - IMGUI_DEMO_MARKER("Widgets/Plotting"); - if (ImGui::TreeNode("Plotting")) - { - static bool animate = true; - ImGui::Checkbox("Animate", &animate); - - // Plot as lines and plot as histogram - static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; - ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr)); - ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f)); - //ImGui::SameLine(); HelpMarker("Consider using ImPlot instead!"); - - // Fill an array of contiguous float values to plot - // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float - // and the sizeof() of your structure in the "stride" parameter. - static float values[90] = {}; - static int values_offset = 0; - static double refresh_time = 0.0; - if (!animate || refresh_time == 0.0) - refresh_time = ImGui::GetTime(); - while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo - { - static float phase = 0.0f; - values[values_offset] = cosf(phase); - values_offset = (values_offset + 1) % IM_ARRAYSIZE(values); - phase += 0.10f * values_offset; - refresh_time += 1.0f / 60.0f; - } - - // Plots can display overlay texts - // (in this example, we will display an average value) - { - float average = 0.0f; - for (int n = 0; n < IM_ARRAYSIZE(values); n++) - average += values[n]; - average /= (float)IM_ARRAYSIZE(values); - char overlay[32]; - sprintf(overlay, "avg %f", average); - ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f)); - } - - // Use functions to generate output - // FIXME: This is actually VERY awkward because current plot API only pass in indices. - // We probably want an API passing floats and user provide sample rate/count. - struct Funcs - { - static float Sin(void*, int i) { return sinf(i * 0.1f); } - static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; } - }; - static int func_type = 0, display_count = 70; - ImGui::SeparatorText("Functions"); - ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); - ImGui::Combo("func", &func_type, "Sin\0Saw\0"); - ImGui::SameLine(); - ImGui::SliderInt("Sample count", &display_count, 1, 400); - float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw; - ImGui::PlotLines("Lines##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); - ImGui::PlotHistogram("Histogram##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); - ImGui::Separator(); - - ImGui::Text("Need better plotting and graphing? Consider using ImPlot:"); - ImGui::TextLinkOpenURL("https://github.com/epezent/implot"); - ImGui::Separator(); - - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Progress Bars"); - if (ImGui::TreeNode("Progress Bars")) - { - // Animate a simple progress bar - static float progress = 0.0f, progress_dir = 1.0f; - progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime; - if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; } - if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } - - // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width, - // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. - ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f)); - ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); - ImGui::Text("Progress Bar"); - - float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f); - char buf[32]; - sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753); - ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf); - - // Pass an animated negative value, e.g. -1.0f * (float)ImGui::GetTime() is the recommended value. - // Adjust the factor if you want to adjust the animation speed. - ImGui::ProgressBar(-1.0f * (float)ImGui::GetTime(), ImVec2(0.0f, 0.0f), "Searching.."); - ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); - ImGui::Text("Indeterminate"); - - ImGui::TreePop(); - } - IMGUI_DEMO_MARKER("Widgets/Color"); if (ImGui::TreeNode("Color/Picker Widgets")) { @@ -2455,10 +2215,114 @@ static void DemoWindowWidgetsListBoxes() // [SECTION] DemoWindowWidgetsPlotting() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsPlotting() +{ + // Plot/Graph widgets are not very good. +// Consider using a third-party library such as ImPlot: https://github.com/epezent/implot +// (see others https://github.com/ocornut/imgui/wiki/Useful-Extensions) + IMGUI_DEMO_MARKER("Widgets/Plotting"); + if (ImGui::TreeNode("Plotting")) + { + ImGui::Text("Need better plotting and graphing? Consider using ImPlot:"); + ImGui::TextLinkOpenURL("https://github.com/epezent/implot"); + ImGui::Separator(); + + static bool animate = true; + ImGui::Checkbox("Animate", &animate); + + // Plot as lines and plot as histogram + static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f }; + ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr)); + ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f)); + //ImGui::SameLine(); HelpMarker("Consider using ImPlot instead!"); + + // Fill an array of contiguous float values to plot + // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float + // and the sizeof() of your structure in the "stride" parameter. + static float values[90] = {}; + static int values_offset = 0; + static double refresh_time = 0.0; + if (!animate || refresh_time == 0.0) + refresh_time = ImGui::GetTime(); + while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo + { + static float phase = 0.0f; + values[values_offset] = cosf(phase); + values_offset = (values_offset + 1) % IM_ARRAYSIZE(values); + phase += 0.10f * values_offset; + refresh_time += 1.0f / 60.0f; + } + + // Plots can display overlay texts + // (in this example, we will display an average value) + { + float average = 0.0f; + for (int n = 0; n < IM_ARRAYSIZE(values); n++) + average += values[n]; + average /= (float)IM_ARRAYSIZE(values); + char overlay[32]; + sprintf(overlay, "avg %f", average); + ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f)); + } + + // Use functions to generate output + // FIXME: This is actually VERY awkward because current plot API only pass in indices. + // We probably want an API passing floats and user provide sample rate/count. + struct Funcs + { + static float Sin(void*, int i) { return sinf(i * 0.1f); } + static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; } + }; + static int func_type = 0, display_count = 70; + ImGui::SeparatorText("Functions"); + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); + ImGui::Combo("func", &func_type, "Sin\0Saw\0"); + ImGui::SameLine(); + ImGui::SliderInt("Sample count", &display_count, 1, 400); + float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw; + ImGui::PlotLines("Lines##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); + ImGui::PlotHistogram("Histogram##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80)); + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsProgressBars() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsProgressBars() +{ + IMGUI_DEMO_MARKER("Widgets/Progress Bars"); + if (ImGui::TreeNode("Progress Bars")) + { + // Animate a simple progress bar + static float progress = 0.0f, progress_dir = 1.0f; + progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime; + if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; } + if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; } + + // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width, + // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth. + ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f)); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::Text("Progress Bar"); + + float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f); + char buf[32]; + sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753); + ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf); + + // Pass an animated negative value, e.g. -1.0f * (float)ImGui::GetTime() is the recommended value. + // Adjust the factor if you want to adjust the animation speed. + ImGui::ProgressBar(-1.0f * (float)ImGui::GetTime(), ImVec2(0.0f, 0.0f), "Searching.."); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::Text("Indeterminate"); + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsQueryingStatuses() //----------------------------------------------------------------------------- @@ -3571,6 +3435,155 @@ static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_d // [SECTION] DemoWindowWidgetsTabs() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsTabs() +{ + IMGUI_DEMO_MARKER("Widgets/Tabs"); + if (ImGui::TreeNode("Tabs")) + { + IMGUI_DEMO_MARKER("Widgets/Tabs/Basic"); + if (ImGui::TreeNode("Basic")) + { + ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None; + if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) + { + if (ImGui::BeginTabItem("Avocado")) + { + ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah"); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Broccoli")) + { + ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah"); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Cucumber")) + { + ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah"); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + ImGui::Separator(); + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Tabs/Advanced & Close Button"); + if (ImGui::TreeNode("Advanced & Close Button")) + { + // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0). + static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable; + ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", &tab_bar_flags, ImGuiTabBarFlags_Reorderable); + ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", &tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs); + ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); + ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton); + ImGui::CheckboxFlags("ImGuiTabBarFlags_DrawSelectedOverline", &tab_bar_flags, ImGuiTabBarFlags_DrawSelectedOverline); + if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0) + tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_; + if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown)) + tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown); + if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll)) + tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll); + + // Tab Bar + ImGui::AlignTextToFramePadding(); + ImGui::Text("Opened:"); + const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" }; + static bool opened[4] = { true, true, true, true }; // Persistent user state + for (int n = 0; n < IM_ARRAYSIZE(opened); n++) + { + ImGui::SameLine(); + ImGui::Checkbox(names[n], &opened[n]); + } + + // Passing a bool* to BeginTabItem() is similar to passing one to Begin(): + // the underlying bool will be set to false when the tab is closed. + if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) + { + for (int n = 0; n < IM_ARRAYSIZE(opened); n++) + if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None)) + { + ImGui::Text("This is the %s tab!", names[n]); + if (n & 1) + ImGui::Text("I am an odd tab."); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + ImGui::Separator(); + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Tabs/TabItemButton & Leading-Trailing flags"); + if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags")) + { + static ImVector active_tabs; + static int next_tab_id = 0; + if (next_tab_id == 0) // Initialize with some default tabs + for (int i = 0; i < 3; i++) + active_tabs.push_back(next_tab_id++); + + // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together. + // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags... + // but they tend to make more sense together) + static bool show_leading_button = true; + static bool show_trailing_button = true; + ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button); + ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button); + + // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs + static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown; + ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); + if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown)) + tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown); + if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll)) + tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll); + + if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) + { + // Demo a Leading TabItemButton(): click the "?" button to open a menu + if (show_leading_button) + if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip)) + ImGui::OpenPopup("MyHelpMenu"); + if (ImGui::BeginPopup("MyHelpMenu")) + { + ImGui::Selectable("Hello!"); + ImGui::EndPopup(); + } + + // Demo Trailing Tabs: click the "+" button to add a new tab. + // (In your app you may want to use a font icon instead of the "+") + // We submit it before the regular tabs, but thanks to the ImGuiTabItemFlags_Trailing flag it will always appear at the end. + if (show_trailing_button) + if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip)) + active_tabs.push_back(next_tab_id++); // Add new tab + + // Submit our regular tabs + for (int n = 0; n < active_tabs.Size; ) + { + bool open = true; + char name[16]; + snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]); + if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None)) + { + ImGui::Text("This is the %s tab!", name); + ImGui::EndTabItem(); + } + + if (!open) + active_tabs.erase(active_tabs.Data + n); + else + n++; + } + + ImGui::EndTabBar(); + } + ImGui::Separator(); + ImGui::TreePop(); + } + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsText() //----------------------------------------------------------------------------- From 510a9a77d6ad5f2ab017ea7d13979e80a5a53989 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 18:11:16 +0100 Subject: [PATCH 510/548] Demo: (Refactor) Moved code into DemoWindowWidgetsDataTypes() section. --- imgui_demo.cpp | 261 +++++++++++++++++++++++++------------------------ 1 file changed, 133 insertions(+), 128 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 468e32b598d9..692f67af4b7c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -254,6 +254,7 @@ static void DemoWindowWidgetsBasic(); static void DemoWindowWidgetsBullets(); static void DemoWindowWidgetsCollapsingHeaders(); static void DemoWindowWidgetsComboBoxes(); +static void DemoWindowWidgetsDataTypes(); static void DemoWindowWidgetsImages(); static void DemoWindowWidgetsListBoxes(); static void DemoWindowWidgetsPlotting(); @@ -826,6 +827,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsBullets(); DemoWindowWidgetsCollapsingHeaders(); DemoWindowWidgetsComboBoxes(); + DemoWindowWidgetsDataTypes(); DemoWindowWidgetsImages(); DemoWindowWidgetsListBoxes(); DemoWindowWidgetsPlotting(); @@ -1087,134 +1089,6 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::TreePop(); } - IMGUI_DEMO_MARKER("Widgets/Data Types"); - if (ImGui::TreeNode("Data Types")) - { - // DragScalar/InputScalar/SliderScalar functions allow various data types - // - signed/unsigned - // - 8/16/32/64-bits - // - integer/float/double - // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum - // to pass the type, and passing all arguments by pointer. - // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each type. - // In practice, if you frequently use a given type that is not covered by the normal API entry points, - // you can wrap it yourself inside a 1 line function which can take typed argument as value instead of void*, - // and then pass their address to the generic function. For example: - // bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld") - // { - // return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format); - // } - - // Setup limits (as helper variables so we can take their address, as explained above) - // Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2. - #ifndef LLONG_MIN - ImS64 LLONG_MIN = -9223372036854775807LL - 1; - ImS64 LLONG_MAX = 9223372036854775807LL; - ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1); - #endif - const char s8_zero = 0, s8_one = 1, s8_fifty = 50, s8_min = -128, s8_max = 127; - const ImU8 u8_zero = 0, u8_one = 1, u8_fifty = 50, u8_min = 0, u8_max = 255; - const short s16_zero = 0, s16_one = 1, s16_fifty = 50, s16_min = -32768, s16_max = 32767; - const ImU16 u16_zero = 0, u16_one = 1, u16_fifty = 50, u16_min = 0, u16_max = 65535; - const ImS32 s32_zero = 0, s32_one = 1, s32_fifty = 50, s32_min = INT_MIN/2, s32_max = INT_MAX/2, s32_hi_a = INT_MAX/2 - 100, s32_hi_b = INT_MAX/2; - const ImU32 u32_zero = 0, u32_one = 1, u32_fifty = 50, u32_min = 0, u32_max = UINT_MAX/2, u32_hi_a = UINT_MAX/2 - 100, u32_hi_b = UINT_MAX/2; - const ImS64 s64_zero = 0, s64_one = 1, s64_fifty = 50, s64_min = LLONG_MIN/2, s64_max = LLONG_MAX/2, s64_hi_a = LLONG_MAX/2 - 100, s64_hi_b = LLONG_MAX/2; - const ImU64 u64_zero = 0, u64_one = 1, u64_fifty = 50, u64_min = 0, u64_max = ULLONG_MAX/2, u64_hi_a = ULLONG_MAX/2 - 100, u64_hi_b = ULLONG_MAX/2; - const float f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f; - const double f64_zero = 0., f64_one = 1., f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0; - - // State - static char s8_v = 127; - static ImU8 u8_v = 255; - static short s16_v = 32767; - static ImU16 u16_v = 65535; - static ImS32 s32_v = -1; - static ImU32 u32_v = (ImU32)-1; - static ImS64 s64_v = -1; - static ImU64 u64_v = (ImU64)-1; - static float f32_v = 0.123f; - static double f64_v = 90000.01234567890123456789; - - const float drag_speed = 0.2f; - static bool drag_clamp = false; - IMGUI_DEMO_MARKER("Widgets/Data Types/Drags"); - ImGui::SeparatorText("Drags"); - ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp); - ImGui::SameLine(); HelpMarker( - "As with every widget in dear imgui, we never modify values unless there is a user interaction.\n" - "You can override the clamping limits by using CTRL+Click to input a value."); - ImGui::DragScalar("drag s8", ImGuiDataType_S8, &s8_v, drag_speed, drag_clamp ? &s8_zero : NULL, drag_clamp ? &s8_fifty : NULL); - ImGui::DragScalar("drag u8", ImGuiDataType_U8, &u8_v, drag_speed, drag_clamp ? &u8_zero : NULL, drag_clamp ? &u8_fifty : NULL, "%u ms"); - ImGui::DragScalar("drag s16", ImGuiDataType_S16, &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL); - ImGui::DragScalar("drag u16", ImGuiDataType_U16, &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms"); - ImGui::DragScalar("drag s32", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL); - ImGui::DragScalar("drag s32 hex", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL, "0x%08X"); - ImGui::DragScalar("drag u32", ImGuiDataType_U32, &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms"); - ImGui::DragScalar("drag s64", ImGuiDataType_S64, &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL); - ImGui::DragScalar("drag u64", ImGuiDataType_U64, &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL); - ImGui::DragScalar("drag float", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f"); - ImGui::DragScalar("drag float log", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", ImGuiSliderFlags_Logarithmic); - ImGui::DragScalar("drag double", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL, "%.10f grams"); - ImGui::DragScalar("drag double log",ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", ImGuiSliderFlags_Logarithmic); - - IMGUI_DEMO_MARKER("Widgets/Data Types/Sliders"); - ImGui::SeparatorText("Sliders"); - ImGui::SliderScalar("slider s8 full", ImGuiDataType_S8, &s8_v, &s8_min, &s8_max, "%d"); - ImGui::SliderScalar("slider u8 full", ImGuiDataType_U8, &u8_v, &u8_min, &u8_max, "%u"); - ImGui::SliderScalar("slider s16 full", ImGuiDataType_S16, &s16_v, &s16_min, &s16_max, "%d"); - ImGui::SliderScalar("slider u16 full", ImGuiDataType_U16, &u16_v, &u16_min, &u16_max, "%u"); - ImGui::SliderScalar("slider s32 low", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty,"%d"); - ImGui::SliderScalar("slider s32 high", ImGuiDataType_S32, &s32_v, &s32_hi_a, &s32_hi_b, "%d"); - ImGui::SliderScalar("slider s32 full", ImGuiDataType_S32, &s32_v, &s32_min, &s32_max, "%d"); - ImGui::SliderScalar("slider s32 hex", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty, "0x%04X"); - ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32, &u32_v, &u32_zero, &u32_fifty,"%u"); - ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32, &u32_v, &u32_hi_a, &u32_hi_b, "%u"); - ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32, &u32_v, &u32_min, &u32_max, "%u"); - ImGui::SliderScalar("slider s64 low", ImGuiDataType_S64, &s64_v, &s64_zero, &s64_fifty,"%" PRId64); - ImGui::SliderScalar("slider s64 high", ImGuiDataType_S64, &s64_v, &s64_hi_a, &s64_hi_b, "%" PRId64); - ImGui::SliderScalar("slider s64 full", ImGuiDataType_S64, &s64_v, &s64_min, &s64_max, "%" PRId64); - ImGui::SliderScalar("slider u64 low", ImGuiDataType_U64, &u64_v, &u64_zero, &u64_fifty,"%" PRIu64 " ms"); - ImGui::SliderScalar("slider u64 high", ImGuiDataType_U64, &u64_v, &u64_hi_a, &u64_hi_b, "%" PRIu64 " ms"); - ImGui::SliderScalar("slider u64 full", ImGuiDataType_U64, &u64_v, &u64_min, &u64_max, "%" PRIu64 " ms"); - ImGui::SliderScalar("slider float low", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one); - ImGui::SliderScalar("slider float low log", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one, "%.10f", ImGuiSliderFlags_Logarithmic); - ImGui::SliderScalar("slider float high", ImGuiDataType_Float, &f32_v, &f32_lo_a, &f32_hi_a, "%e"); - ImGui::SliderScalar("slider double low", ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f grams"); - ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f", ImGuiSliderFlags_Logarithmic); - ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams"); - - ImGui::SeparatorText("Sliders (reverse)"); - ImGui::SliderScalar("slider s8 reverse", ImGuiDataType_S8, &s8_v, &s8_max, &s8_min, "%d"); - ImGui::SliderScalar("slider u8 reverse", ImGuiDataType_U8, &u8_v, &u8_max, &u8_min, "%u"); - ImGui::SliderScalar("slider s32 reverse", ImGuiDataType_S32, &s32_v, &s32_fifty, &s32_zero, "%d"); - ImGui::SliderScalar("slider u32 reverse", ImGuiDataType_U32, &u32_v, &u32_fifty, &u32_zero, "%u"); - ImGui::SliderScalar("slider s64 reverse", ImGuiDataType_S64, &s64_v, &s64_fifty, &s64_zero, "%" PRId64); - ImGui::SliderScalar("slider u64 reverse", ImGuiDataType_U64, &u64_v, &u64_fifty, &u64_zero, "%" PRIu64 " ms"); - - IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs"); - static bool inputs_step = true; - static ImGuiInputTextFlags flags = ImGuiInputTextFlags_None; - ImGui::SeparatorText("Inputs"); - ImGui::Checkbox("Show step buttons", &inputs_step); - ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); - ImGui::CheckboxFlags("ImGuiInputTextFlags_ParseEmptyRefVal", &flags, ImGuiInputTextFlags_ParseEmptyRefVal); - ImGui::CheckboxFlags("ImGuiInputTextFlags_DisplayEmptyRefVal", &flags, ImGuiInputTextFlags_DisplayEmptyRefVal); - ImGui::InputScalar("input s8", ImGuiDataType_S8, &s8_v, inputs_step ? &s8_one : NULL, NULL, "%d", flags); - ImGui::InputScalar("input u8", ImGuiDataType_U8, &u8_v, inputs_step ? &u8_one : NULL, NULL, "%u", flags); - ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d", flags); - ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u", flags); - ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d", flags); - ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%04X", flags); - ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u", flags); - ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", flags); - ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL, NULL, NULL, flags); - ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL, NULL, NULL, flags); - ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL, NULL, NULL, flags); - ImGui::InputScalar("input double", ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL, NULL, NULL, flags); - - ImGui::TreePop(); - } - IMGUI_DEMO_MARKER("Widgets/Multi-component Widgets"); if (ImGui::TreeNode("Multi-component Widgets")) { @@ -2041,6 +1915,137 @@ static void DemoWindowWidgetsComboBoxes() // [SECTION] DemoWindowWidgetsDataTypes() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsDataTypes() +{ + IMGUI_DEMO_MARKER("Widgets/Data Types"); + if (ImGui::TreeNode("Data Types")) + { + // DragScalar/InputScalar/SliderScalar functions allow various data types + // - signed/unsigned + // - 8/16/32/64-bits + // - integer/float/double + // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum + // to pass the type, and passing all arguments by pointer. + // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each type. + // In practice, if you frequently use a given type that is not covered by the normal API entry points, + // you can wrap it yourself inside a 1 line function which can take typed argument as value instead of void*, + // and then pass their address to the generic function. For example: + // bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld") + // { + // return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format); + // } + + // Setup limits (as helper variables so we can take their address, as explained above) + // Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2. + #ifndef LLONG_MIN + ImS64 LLONG_MIN = -9223372036854775807LL - 1; + ImS64 LLONG_MAX = 9223372036854775807LL; + ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1); + #endif + const char s8_zero = 0, s8_one = 1, s8_fifty = 50, s8_min = -128, s8_max = 127; + const ImU8 u8_zero = 0, u8_one = 1, u8_fifty = 50, u8_min = 0, u8_max = 255; + const short s16_zero = 0, s16_one = 1, s16_fifty = 50, s16_min = -32768, s16_max = 32767; + const ImU16 u16_zero = 0, u16_one = 1, u16_fifty = 50, u16_min = 0, u16_max = 65535; + const ImS32 s32_zero = 0, s32_one = 1, s32_fifty = 50, s32_min = INT_MIN/2, s32_max = INT_MAX/2, s32_hi_a = INT_MAX/2 - 100, s32_hi_b = INT_MAX/2; + const ImU32 u32_zero = 0, u32_one = 1, u32_fifty = 50, u32_min = 0, u32_max = UINT_MAX/2, u32_hi_a = UINT_MAX/2 - 100, u32_hi_b = UINT_MAX/2; + const ImS64 s64_zero = 0, s64_one = 1, s64_fifty = 50, s64_min = LLONG_MIN/2, s64_max = LLONG_MAX/2, s64_hi_a = LLONG_MAX/2 - 100, s64_hi_b = LLONG_MAX/2; + const ImU64 u64_zero = 0, u64_one = 1, u64_fifty = 50, u64_min = 0, u64_max = ULLONG_MAX/2, u64_hi_a = ULLONG_MAX/2 - 100, u64_hi_b = ULLONG_MAX/2; + const float f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f; + const double f64_zero = 0., f64_one = 1., f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0; + + // State + static char s8_v = 127; + static ImU8 u8_v = 255; + static short s16_v = 32767; + static ImU16 u16_v = 65535; + static ImS32 s32_v = -1; + static ImU32 u32_v = (ImU32)-1; + static ImS64 s64_v = -1; + static ImU64 u64_v = (ImU64)-1; + static float f32_v = 0.123f; + static double f64_v = 90000.01234567890123456789; + + const float drag_speed = 0.2f; + static bool drag_clamp = false; + IMGUI_DEMO_MARKER("Widgets/Data Types/Drags"); + ImGui::SeparatorText("Drags"); + ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp); + ImGui::SameLine(); HelpMarker( + "As with every widget in dear imgui, we never modify values unless there is a user interaction.\n" + "You can override the clamping limits by using CTRL+Click to input a value."); + ImGui::DragScalar("drag s8", ImGuiDataType_S8, &s8_v, drag_speed, drag_clamp ? &s8_zero : NULL, drag_clamp ? &s8_fifty : NULL); + ImGui::DragScalar("drag u8", ImGuiDataType_U8, &u8_v, drag_speed, drag_clamp ? &u8_zero : NULL, drag_clamp ? &u8_fifty : NULL, "%u ms"); + ImGui::DragScalar("drag s16", ImGuiDataType_S16, &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL); + ImGui::DragScalar("drag u16", ImGuiDataType_U16, &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms"); + ImGui::DragScalar("drag s32", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL); + ImGui::DragScalar("drag s32 hex", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL, "0x%08X"); + ImGui::DragScalar("drag u32", ImGuiDataType_U32, &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms"); + ImGui::DragScalar("drag s64", ImGuiDataType_S64, &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL); + ImGui::DragScalar("drag u64", ImGuiDataType_U64, &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL); + ImGui::DragScalar("drag float", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f"); + ImGui::DragScalar("drag float log", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", ImGuiSliderFlags_Logarithmic); + ImGui::DragScalar("drag double", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL, "%.10f grams"); + ImGui::DragScalar("drag double log",ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", ImGuiSliderFlags_Logarithmic); + + IMGUI_DEMO_MARKER("Widgets/Data Types/Sliders"); + ImGui::SeparatorText("Sliders"); + ImGui::SliderScalar("slider s8 full", ImGuiDataType_S8, &s8_v, &s8_min, &s8_max, "%d"); + ImGui::SliderScalar("slider u8 full", ImGuiDataType_U8, &u8_v, &u8_min, &u8_max, "%u"); + ImGui::SliderScalar("slider s16 full", ImGuiDataType_S16, &s16_v, &s16_min, &s16_max, "%d"); + ImGui::SliderScalar("slider u16 full", ImGuiDataType_U16, &u16_v, &u16_min, &u16_max, "%u"); + ImGui::SliderScalar("slider s32 low", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty,"%d"); + ImGui::SliderScalar("slider s32 high", ImGuiDataType_S32, &s32_v, &s32_hi_a, &s32_hi_b, "%d"); + ImGui::SliderScalar("slider s32 full", ImGuiDataType_S32, &s32_v, &s32_min, &s32_max, "%d"); + ImGui::SliderScalar("slider s32 hex", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty, "0x%04X"); + ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32, &u32_v, &u32_zero, &u32_fifty,"%u"); + ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32, &u32_v, &u32_hi_a, &u32_hi_b, "%u"); + ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32, &u32_v, &u32_min, &u32_max, "%u"); + ImGui::SliderScalar("slider s64 low", ImGuiDataType_S64, &s64_v, &s64_zero, &s64_fifty,"%" PRId64); + ImGui::SliderScalar("slider s64 high", ImGuiDataType_S64, &s64_v, &s64_hi_a, &s64_hi_b, "%" PRId64); + ImGui::SliderScalar("slider s64 full", ImGuiDataType_S64, &s64_v, &s64_min, &s64_max, "%" PRId64); + ImGui::SliderScalar("slider u64 low", ImGuiDataType_U64, &u64_v, &u64_zero, &u64_fifty,"%" PRIu64 " ms"); + ImGui::SliderScalar("slider u64 high", ImGuiDataType_U64, &u64_v, &u64_hi_a, &u64_hi_b, "%" PRIu64 " ms"); + ImGui::SliderScalar("slider u64 full", ImGuiDataType_U64, &u64_v, &u64_min, &u64_max, "%" PRIu64 " ms"); + ImGui::SliderScalar("slider float low", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one); + ImGui::SliderScalar("slider float low log", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one, "%.10f", ImGuiSliderFlags_Logarithmic); + ImGui::SliderScalar("slider float high", ImGuiDataType_Float, &f32_v, &f32_lo_a, &f32_hi_a, "%e"); + ImGui::SliderScalar("slider double low", ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f grams"); + ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f", ImGuiSliderFlags_Logarithmic); + ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams"); + + ImGui::SeparatorText("Sliders (reverse)"); + ImGui::SliderScalar("slider s8 reverse", ImGuiDataType_S8, &s8_v, &s8_max, &s8_min, "%d"); + ImGui::SliderScalar("slider u8 reverse", ImGuiDataType_U8, &u8_v, &u8_max, &u8_min, "%u"); + ImGui::SliderScalar("slider s32 reverse", ImGuiDataType_S32, &s32_v, &s32_fifty, &s32_zero, "%d"); + ImGui::SliderScalar("slider u32 reverse", ImGuiDataType_U32, &u32_v, &u32_fifty, &u32_zero, "%u"); + ImGui::SliderScalar("slider s64 reverse", ImGuiDataType_S64, &s64_v, &s64_fifty, &s64_zero, "%" PRId64); + ImGui::SliderScalar("slider u64 reverse", ImGuiDataType_U64, &u64_v, &u64_fifty, &u64_zero, "%" PRIu64 " ms"); + + IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs"); + static bool inputs_step = true; + static ImGuiInputTextFlags flags = ImGuiInputTextFlags_None; + ImGui::SeparatorText("Inputs"); + ImGui::Checkbox("Show step buttons", &inputs_step); + ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); + ImGui::CheckboxFlags("ImGuiInputTextFlags_ParseEmptyRefVal", &flags, ImGuiInputTextFlags_ParseEmptyRefVal); + ImGui::CheckboxFlags("ImGuiInputTextFlags_DisplayEmptyRefVal", &flags, ImGuiInputTextFlags_DisplayEmptyRefVal); + ImGui::InputScalar("input s8", ImGuiDataType_S8, &s8_v, inputs_step ? &s8_one : NULL, NULL, "%d", flags); + ImGui::InputScalar("input u8", ImGuiDataType_U8, &u8_v, inputs_step ? &u8_one : NULL, NULL, "%u", flags); + ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d", flags); + ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u", flags); + ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d", flags); + ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%04X", flags); + ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u", flags); + ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", flags); + ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL, NULL, NULL, flags); + ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL, NULL, NULL, flags); + ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL, NULL, NULL, flags); + ImGui::InputScalar("input double", ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL, NULL, NULL, flags); + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsDisableBlocks() //----------------------------------------------------------------------------- From caf3faa054d02e0cc569aaa62cf6cec2e30f5e36 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 18:14:23 +0100 Subject: [PATCH 511/548] Demo: (Refactor) Moved code into DemoWindowWidgetsColorAndPickers() section. --- imgui_demo.cpp | 391 +++++++++++++++++++++++++------------------------ 1 file changed, 198 insertions(+), 193 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 692f67af4b7c..cc0427231164 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -254,6 +254,7 @@ static void DemoWindowWidgetsBasic(); static void DemoWindowWidgetsBullets(); static void DemoWindowWidgetsCollapsingHeaders(); static void DemoWindowWidgetsComboBoxes(); +static void DemoWindowWidgetsColorAndPickers(); static void DemoWindowWidgetsDataTypes(); static void DemoWindowWidgetsImages(); static void DemoWindowWidgetsListBoxes(); @@ -827,6 +828,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsBullets(); DemoWindowWidgetsCollapsingHeaders(); DemoWindowWidgetsComboBoxes(); + DemoWindowWidgetsColorAndPickers(); DemoWindowWidgetsDataTypes(); DemoWindowWidgetsImages(); DemoWindowWidgetsListBoxes(); @@ -841,199 +843,6 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsTooltips(); DemoWindowWidgetsTreeNodes(); - IMGUI_DEMO_MARKER("Widgets/Color"); - if (ImGui::TreeNode("Color/Picker Widgets")) - { - static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f); - static ImGuiColorEditFlags base_flags = ImGuiColorEditFlags_None; - - ImGui::SeparatorText("Options"); - ImGui::CheckboxFlags("ImGuiColorEditFlags_NoAlpha", &base_flags, ImGuiColorEditFlags_NoAlpha); - ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaOpaque", &base_flags, ImGuiColorEditFlags_AlphaOpaque); - ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaNoBg", &base_flags, ImGuiColorEditFlags_AlphaNoBg); - ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaPreviewHalf", &base_flags, ImGuiColorEditFlags_AlphaPreviewHalf); - ImGui::CheckboxFlags("ImGuiColorEditFlags_NoDragDrop", &base_flags, ImGuiColorEditFlags_NoDragDrop); - ImGui::CheckboxFlags("ImGuiColorEditFlags_NoOptions", &base_flags, ImGuiColorEditFlags_NoOptions); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options."); - ImGui::CheckboxFlags("ImGuiColorEditFlags_HDR", &base_flags, ImGuiColorEditFlags_HDR); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets."); - - IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit"); - ImGui::SeparatorText("Inline color editor"); - ImGui::Text("Color widget:"); - ImGui::SameLine(); HelpMarker( - "Click on the color square to open a color picker.\n" - "CTRL+click on individual component to input value.\n"); - ImGui::ColorEdit3("MyColor##1", (float*)&color, base_flags); - - IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (HSV, with Alpha)"); - ImGui::Text("Color widget HSV with Alpha:"); - ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | base_flags); - - IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (float display)"); - ImGui::Text("Color widget with Float Display:"); - ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | base_flags); - - IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with Picker)"); - ImGui::Text("Color button with Picker:"); - ImGui::SameLine(); HelpMarker( - "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n" - "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only " - "be used for the tooltip and picker popup."); - ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | base_flags); - - IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with custom Picker popup)"); - ImGui::Text("Color button with Custom Picker Popup:"); - - // Generate a default palette. The palette will persist and can be edited. - static bool saved_palette_init = true; - static ImVec4 saved_palette[32] = {}; - if (saved_palette_init) - { - for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) - { - ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, - saved_palette[n].x, saved_palette[n].y, saved_palette[n].z); - saved_palette[n].w = 1.0f; // Alpha - } - saved_palette_init = false; - } - - static ImVec4 backup_color; - bool open_popup = ImGui::ColorButton("MyColor##3b", color, base_flags); - ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); - open_popup |= ImGui::Button("Palette"); - if (open_popup) - { - ImGui::OpenPopup("mypicker"); - backup_color = color; - } - if (ImGui::BeginPopup("mypicker")) - { - ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!"); - ImGui::Separator(); - ImGui::ColorPicker4("##picker", (float*)&color, base_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview); - ImGui::SameLine(); - - ImGui::BeginGroup(); // Lock X position - ImGui::Text("Current"); - ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)); - ImGui::Text("Previous"); - if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40))) - color = backup_color; - ImGui::Separator(); - ImGui::Text("Palette"); - for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) - { - ImGui::PushID(n); - if ((n % 8) != 0) - ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); - - ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip; - if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20))) - color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha! - - // Allow user to drop colors into each palette entry. Note that ColorButton() is already a - // drag source by default, unless specifying the ImGuiColorEditFlags_NoDragDrop flag. - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) - memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3); - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) - memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4); - ImGui::EndDragDropTarget(); - } - - ImGui::PopID(); - } - ImGui::EndGroup(); - ImGui::EndPopup(); - } - - IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (simple)"); - ImGui::Text("Color button only:"); - static bool no_border = false; - ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border); - ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, base_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80)); - - IMGUI_DEMO_MARKER("Widgets/Color/ColorPicker"); - ImGui::SeparatorText("Color picker"); - - static bool ref_color = false; - static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f); - static int picker_mode = 0; - static int display_mode = 0; - static ImGuiColorEditFlags color_picker_flags = ImGuiColorEditFlags_AlphaBar; - - ImGui::PushID("Color picker"); - ImGui::CheckboxFlags("ImGuiColorEditFlags_NoAlpha", &color_picker_flags, ImGuiColorEditFlags_NoAlpha); - ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaBar", &color_picker_flags, ImGuiColorEditFlags_AlphaBar); - ImGui::CheckboxFlags("ImGuiColorEditFlags_NoSidePreview", &color_picker_flags, ImGuiColorEditFlags_NoSidePreview); - if (color_picker_flags & ImGuiColorEditFlags_NoSidePreview) - { - ImGui::SameLine(); - ImGui::Checkbox("With Ref Color", &ref_color); - if (ref_color) - { - ImGui::SameLine(); - ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | base_flags); - } - } - - ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0ImGuiColorEditFlags_PickerHueBar\0ImGuiColorEditFlags_PickerHueWheel\0"); - ImGui::SameLine(); HelpMarker("When not specified explicitly, user can right-click the picker to change mode."); - - ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0ImGuiColorEditFlags_NoInputs\0ImGuiColorEditFlags_DisplayRGB\0ImGuiColorEditFlags_DisplayHSV\0ImGuiColorEditFlags_DisplayHex\0"); - ImGui::SameLine(); HelpMarker( - "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, " - "but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex " - "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions()."); - - ImGuiColorEditFlags flags = base_flags | color_picker_flags; - if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar; - if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel; - if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs; // Disable all RGB/HSV/Hex displays - if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB; // Override display mode - if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV; - if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex; - ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL); - - ImGui::Text("Set defaults in code:"); - ImGui::SameLine(); HelpMarker( - "SetColorEditOptions() is designed to allow you to set boot-time default.\n" - "We don't have Push/Pop functions because you can force options on a per-widget basis if needed, " - "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid " - "encouraging you to persistently save values that aren't forward-compatible."); - if (ImGui::Button("Default: Uint8 + HSV + Hue Bar")) - ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar); - if (ImGui::Button("Default: Float + HDR + Hue Wheel")) - ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel); - - // Always display a small version of both types of pickers - // (that's in order to make it more visible in the demo to people who are skimming quickly through it) - ImGui::Text("Both types:"); - float w = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.y) * 0.40f; - ImGui::SetNextItemWidth(w); - ImGui::ColorPicker3("##MyColor##5", (float*)&color, ImGuiColorEditFlags_PickerHueBar | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha); - ImGui::SameLine(); - ImGui::SetNextItemWidth(w); - ImGui::ColorPicker3("##MyColor##6", (float*)&color, ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha); - ImGui::PopID(); - - // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0) - static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV! - ImGui::Spacing(); - ImGui::Text("HSV encoded colors"); - ImGui::SameLine(); HelpMarker( - "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV " - "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the " - "added benefit that you can manipulate hue values with the picker even when saturation or value are zero."); - ImGui::Text("Color widget with InputHSV:"); - ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float); - ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float); - ImGui::DragFloat4("Raw HSV values", (float*)&color_hsv, 0.01f, 0.0f, 1.0f); - - ImGui::TreePop(); - } - IMGUI_DEMO_MARKER("Widgets/Drag and Slider Flags"); if (ImGui::TreeNode("Drag/Slider Flags")) { @@ -1814,6 +1623,202 @@ static void DemoWindowWidgetsCollapsingHeaders() // [SECTION] DemoWindowWidgetsColorAndPickers() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsColorAndPickers() +{ + IMGUI_DEMO_MARKER("Widgets/Color"); + if (ImGui::TreeNode("Color/Picker Widgets")) + { + static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f); + static ImGuiColorEditFlags base_flags = ImGuiColorEditFlags_None; + + ImGui::SeparatorText("Options"); + ImGui::CheckboxFlags("ImGuiColorEditFlags_NoAlpha", &base_flags, ImGuiColorEditFlags_NoAlpha); + ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaOpaque", &base_flags, ImGuiColorEditFlags_AlphaOpaque); + ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaNoBg", &base_flags, ImGuiColorEditFlags_AlphaNoBg); + ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaPreviewHalf", &base_flags, ImGuiColorEditFlags_AlphaPreviewHalf); + ImGui::CheckboxFlags("ImGuiColorEditFlags_NoDragDrop", &base_flags, ImGuiColorEditFlags_NoDragDrop); + ImGui::CheckboxFlags("ImGuiColorEditFlags_NoOptions", &base_flags, ImGuiColorEditFlags_NoOptions); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options."); + ImGui::CheckboxFlags("ImGuiColorEditFlags_HDR", &base_flags, ImGuiColorEditFlags_HDR); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets."); + + IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit"); + ImGui::SeparatorText("Inline color editor"); + ImGui::Text("Color widget:"); + ImGui::SameLine(); HelpMarker( + "Click on the color square to open a color picker.\n" + "CTRL+click on individual component to input value.\n"); + ImGui::ColorEdit3("MyColor##1", (float*)&color, base_flags); + + IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (HSV, with Alpha)"); + ImGui::Text("Color widget HSV with Alpha:"); + ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | base_flags); + + IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (float display)"); + ImGui::Text("Color widget with Float Display:"); + ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | base_flags); + + IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with Picker)"); + ImGui::Text("Color button with Picker:"); + ImGui::SameLine(); HelpMarker( + "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n" + "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only " + "be used for the tooltip and picker popup."); + ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | base_flags); + + IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with custom Picker popup)"); + ImGui::Text("Color button with Custom Picker Popup:"); + + // Generate a default palette. The palette will persist and can be edited. + static bool saved_palette_init = true; + static ImVec4 saved_palette[32] = {}; + if (saved_palette_init) + { + for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) + { + ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, + saved_palette[n].x, saved_palette[n].y, saved_palette[n].z); + saved_palette[n].w = 1.0f; // Alpha + } + saved_palette_init = false; + } + + static ImVec4 backup_color; + bool open_popup = ImGui::ColorButton("MyColor##3b", color, base_flags); + ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); + open_popup |= ImGui::Button("Palette"); + if (open_popup) + { + ImGui::OpenPopup("mypicker"); + backup_color = color; + } + if (ImGui::BeginPopup("mypicker")) + { + ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!"); + ImGui::Separator(); + ImGui::ColorPicker4("##picker", (float*)&color, base_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview); + ImGui::SameLine(); + + ImGui::BeginGroup(); // Lock X position + ImGui::Text("Current"); + ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)); + ImGui::Text("Previous"); + if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40))) + color = backup_color; + ImGui::Separator(); + ImGui::Text("Palette"); + for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) + { + ImGui::PushID(n); + if ((n % 8) != 0) + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); + + ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip; + if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20))) + color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha! + + // Allow user to drop colors into each palette entry. Note that ColorButton() is already a + // drag source by default, unless specifying the ImGuiColorEditFlags_NoDragDrop flag. + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) + memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3); + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) + memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4); + ImGui::EndDragDropTarget(); + } + + ImGui::PopID(); + } + ImGui::EndGroup(); + ImGui::EndPopup(); + } + + IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (simple)"); + ImGui::Text("Color button only:"); + static bool no_border = false; + ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border); + ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, base_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80)); + + IMGUI_DEMO_MARKER("Widgets/Color/ColorPicker"); + ImGui::SeparatorText("Color picker"); + + static bool ref_color = false; + static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f); + static int picker_mode = 0; + static int display_mode = 0; + static ImGuiColorEditFlags color_picker_flags = ImGuiColorEditFlags_AlphaBar; + + ImGui::PushID("Color picker"); + ImGui::CheckboxFlags("ImGuiColorEditFlags_NoAlpha", &color_picker_flags, ImGuiColorEditFlags_NoAlpha); + ImGui::CheckboxFlags("ImGuiColorEditFlags_AlphaBar", &color_picker_flags, ImGuiColorEditFlags_AlphaBar); + ImGui::CheckboxFlags("ImGuiColorEditFlags_NoSidePreview", &color_picker_flags, ImGuiColorEditFlags_NoSidePreview); + if (color_picker_flags & ImGuiColorEditFlags_NoSidePreview) + { + ImGui::SameLine(); + ImGui::Checkbox("With Ref Color", &ref_color); + if (ref_color) + { + ImGui::SameLine(); + ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | base_flags); + } + } + + ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0ImGuiColorEditFlags_PickerHueBar\0ImGuiColorEditFlags_PickerHueWheel\0"); + ImGui::SameLine(); HelpMarker("When not specified explicitly, user can right-click the picker to change mode."); + + ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0ImGuiColorEditFlags_NoInputs\0ImGuiColorEditFlags_DisplayRGB\0ImGuiColorEditFlags_DisplayHSV\0ImGuiColorEditFlags_DisplayHex\0"); + ImGui::SameLine(); HelpMarker( + "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, " + "but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex " + "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions()."); + + ImGuiColorEditFlags flags = base_flags | color_picker_flags; + if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar; + if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel; + if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs; // Disable all RGB/HSV/Hex displays + if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB; // Override display mode + if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV; + if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex; + ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL); + + ImGui::Text("Set defaults in code:"); + ImGui::SameLine(); HelpMarker( + "SetColorEditOptions() is designed to allow you to set boot-time default.\n" + "We don't have Push/Pop functions because you can force options on a per-widget basis if needed, " + "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid " + "encouraging you to persistently save values that aren't forward-compatible."); + if (ImGui::Button("Default: Uint8 + HSV + Hue Bar")) + ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar); + if (ImGui::Button("Default: Float + HDR + Hue Wheel")) + ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel); + + // Always display a small version of both types of pickers + // (that's in order to make it more visible in the demo to people who are skimming quickly through it) + ImGui::Text("Both types:"); + float w = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.y) * 0.40f; + ImGui::SetNextItemWidth(w); + ImGui::ColorPicker3("##MyColor##5", (float*)&color, ImGuiColorEditFlags_PickerHueBar | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha); + ImGui::SameLine(); + ImGui::SetNextItemWidth(w); + ImGui::ColorPicker3("##MyColor##6", (float*)&color, ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha); + ImGui::PopID(); + + // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0) + static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV! + ImGui::Spacing(); + ImGui::Text("HSV encoded colors"); + ImGui::SameLine(); HelpMarker( + "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV " + "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the " + "added benefit that you can manipulate hue values with the picker even when saturation or value are zero."); + ImGui::Text("Color widget with InputHSV:"); + ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float); + ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float); + ImGui::DragFloat4("Raw HSV values", (float*)&color_hsv, 0.01f, 0.0f, 1.0f); + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsComboBoxes() //----------------------------------------------------------------------------- From 9b486e47fef41c506941151dc586c4ad75bb784a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 18:40:14 +0100 Subject: [PATCH 512/548] Demo: (Refactor) Moved code into DemoWindowWidgetsDragsAndSliders(), DemoWindowWidgetsMultiComponents(), DemoWindowWidgetsVerticalSliders() sections. --- imgui_demo.cpp | 317 +++++++++++++++++++++++++------------------------ 1 file changed, 164 insertions(+), 153 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index cc0427231164..9d9cf112b913 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -256,9 +256,11 @@ static void DemoWindowWidgetsCollapsingHeaders(); static void DemoWindowWidgetsComboBoxes(); static void DemoWindowWidgetsColorAndPickers(); static void DemoWindowWidgetsDataTypes(); +static void DemoWindowWidgetsDragsAndSliders(); static void DemoWindowWidgetsImages(); static void DemoWindowWidgetsListBoxes(); static void DemoWindowWidgetsPlotting(); +static void DemoWindowWidgetsMultiComponents(); static void DemoWindowWidgetsProgressBars(); static void DemoWindowWidgetsSelectables(); static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data); @@ -268,6 +270,7 @@ static void DemoWindowWidgetsTextFilter(); static void DemoWindowWidgetsTextInput(); static void DemoWindowWidgetsTooltips(); static void DemoWindowWidgetsTreeNodes(); +static void DemoWindowWidgetsVerticalSliders(); static void DemoWindowLayout(); static void DemoWindowPopups(); static void DemoWindowTables(); @@ -830,8 +833,10 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsComboBoxes(); DemoWindowWidgetsColorAndPickers(); DemoWindowWidgetsDataTypes(); + DemoWindowWidgetsDragsAndSliders(); DemoWindowWidgetsImages(); DemoWindowWidgetsListBoxes(); + DemoWindowWidgetsMultiComponents(); DemoWindowWidgetsPlotting(); DemoWindowWidgetsProgressBars(); DemoWindowWidgetsSelectables(); @@ -842,159 +847,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsTextInput(); DemoWindowWidgetsTooltips(); DemoWindowWidgetsTreeNodes(); - - IMGUI_DEMO_MARKER("Widgets/Drag and Slider Flags"); - if (ImGui::TreeNode("Drag/Slider Flags")) - { - // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same! - static ImGuiSliderFlags flags = ImGuiSliderFlags_None; - ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", &flags, ImGuiSliderFlags_AlwaysClamp); - ImGui::CheckboxFlags("ImGuiSliderFlags_ClampOnInput", &flags, ImGuiSliderFlags_ClampOnInput); - ImGui::SameLine(); HelpMarker("Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds."); - ImGui::CheckboxFlags("ImGuiSliderFlags_ClampZeroRange", &flags, ImGuiSliderFlags_ClampZeroRange); - ImGui::SameLine(); HelpMarker("Clamp even if min==max==0.0f. Otherwise DragXXX functions don't clamp."); - ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", &flags, ImGuiSliderFlags_Logarithmic); - ImGui::SameLine(); HelpMarker("Enable logarithmic editing (more precision for small values)."); - ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", &flags, ImGuiSliderFlags_NoRoundToFormat); - ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits)."); - ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput); - ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget."); - ImGui::CheckboxFlags("ImGuiSliderFlags_NoSpeedTweaks", &flags, ImGuiSliderFlags_NoSpeedTweaks); - ImGui::SameLine(); HelpMarker("Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic."); - ImGui::CheckboxFlags("ImGuiSliderFlags_WrapAround", &flags, ImGuiSliderFlags_WrapAround); - ImGui::SameLine(); HelpMarker("Enable wrapping around from max to min and from min to max (only supported by DragXXX() functions)"); - - // Drags - static float drag_f = 0.5f; - static int drag_i = 50; - ImGui::Text("Underlying float value: %f", drag_f); - ImGui::DragFloat("DragFloat (0 -> 1)", &drag_f, 0.005f, 0.0f, 1.0f, "%.3f", flags); - ImGui::DragFloat("DragFloat (0 -> +inf)", &drag_f, 0.005f, 0.0f, FLT_MAX, "%.3f", flags); - ImGui::DragFloat("DragFloat (-inf -> 1)", &drag_f, 0.005f, -FLT_MAX, 1.0f, "%.3f", flags); - ImGui::DragFloat("DragFloat (-inf -> +inf)", &drag_f, 0.005f, -FLT_MAX, +FLT_MAX, "%.3f", flags); - //ImGui::DragFloat("DragFloat (0 -> 0)", &drag_f, 0.005f, 0.0f, 0.0f, "%.3f", flags); // To test ClampZeroRange - //ImGui::DragFloat("DragFloat (100 -> 100)", &drag_f, 0.005f, 100.0f, 100.0f, "%.3f", flags); - ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags); - - // Sliders - static float slider_f = 0.5f; - static int slider_i = 50; - const ImGuiSliderFlags flags_for_sliders = flags & ~ImGuiSliderFlags_WrapAround; - ImGui::Text("Underlying float value: %f", slider_f); - ImGui::SliderFloat("SliderFloat (0 -> 1)", &slider_f, 0.0f, 1.0f, "%.3f", flags_for_sliders); - ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%d", flags_for_sliders); - - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Range Widgets"); - if (ImGui::TreeNode("Range Widgets")) - { - static float begin = 10, end = 90; - static int begin_i = 100, end_i = 1000; - ImGui::DragFloatRange2("range float", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%", ImGuiSliderFlags_AlwaysClamp); - ImGui::DragIntRange2("range int", &begin_i, &end_i, 5, 0, 1000, "Min: %d units", "Max: %d units"); - ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units"); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Multi-component Widgets"); - if (ImGui::TreeNode("Multi-component Widgets")) - { - static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; - static int vec4i[4] = { 1, 5, 100, 255 }; - - ImGui::SeparatorText("2-wide"); - ImGui::InputFloat2("input float2", vec4f); - ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f); - ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f); - ImGui::InputInt2("input int2", vec4i); - ImGui::DragInt2("drag int2", vec4i, 1, 0, 255); - ImGui::SliderInt2("slider int2", vec4i, 0, 255); - - ImGui::SeparatorText("3-wide"); - ImGui::InputFloat3("input float3", vec4f); - ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f); - ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f); - ImGui::InputInt3("input int3", vec4i); - ImGui::DragInt3("drag int3", vec4i, 1, 0, 255); - ImGui::SliderInt3("slider int3", vec4i, 0, 255); - - ImGui::SeparatorText("4-wide"); - ImGui::InputFloat4("input float4", vec4f); - ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f); - ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f); - ImGui::InputInt4("input int4", vec4i); - ImGui::DragInt4("drag int4", vec4i, 1, 0, 255); - ImGui::SliderInt4("slider int4", vec4i, 0, 255); - - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Vertical Sliders"); - if (ImGui::TreeNode("Vertical Sliders")) - { - const float spacing = 4; - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing)); - - static int int_value = 0; - ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5); - ImGui::SameLine(); - - static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f }; - ImGui::PushID("set1"); - for (int i = 0; i < 7; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::PushID(i); - ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f)); - ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f)); - ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, ""); - if (ImGui::IsItemActive() || ImGui::IsItemHovered()) - ImGui::SetTooltip("%.3f", values[i]); - ImGui::PopStyleColor(4); - ImGui::PopID(); - } - ImGui::PopID(); - - ImGui::SameLine(); - ImGui::PushID("set2"); - static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f }; - const int rows = 3; - const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows)); - for (int nx = 0; nx < 4; nx++) - { - if (nx > 0) ImGui::SameLine(); - ImGui::BeginGroup(); - for (int ny = 0; ny < rows; ny++) - { - ImGui::PushID(nx * rows + ny); - ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, ""); - if (ImGui::IsItemActive() || ImGui::IsItemHovered()) - ImGui::SetTooltip("%.3f", values2[nx]); - ImGui::PopID(); - } - ImGui::EndGroup(); - } - ImGui::PopID(); - - ImGui::SameLine(); - ImGui::PushID("set3"); - for (int i = 0; i < 4; i++) - { - if (i > 0) ImGui::SameLine(); - ImGui::PushID(i); - ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); - ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec"); - ImGui::PopStyleVar(); - ImGui::PopID(); - } - ImGui::PopID(); - ImGui::PopStyleVar(); - ImGui::TreePop(); - } + DemoWindowWidgetsVerticalSliders(); IMGUI_DEMO_MARKER("Widgets/Drag and drop"); if (ImGui::TreeNode("Drag and Drop")) @@ -2063,6 +1916,53 @@ static void DemoWindowWidgetsDataTypes() // [SECTION] DemoWindowWidgetsDragsAndSliders() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsDragsAndSliders() +{ + IMGUI_DEMO_MARKER("Widgets/Drag and Slider Flags"); + if (ImGui::TreeNode("Drag/Slider Flags")) + { + // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same! + static ImGuiSliderFlags flags = ImGuiSliderFlags_None; + ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", &flags, ImGuiSliderFlags_AlwaysClamp); + ImGui::CheckboxFlags("ImGuiSliderFlags_ClampOnInput", &flags, ImGuiSliderFlags_ClampOnInput); + ImGui::SameLine(); HelpMarker("Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds."); + ImGui::CheckboxFlags("ImGuiSliderFlags_ClampZeroRange", &flags, ImGuiSliderFlags_ClampZeroRange); + ImGui::SameLine(); HelpMarker("Clamp even if min==max==0.0f. Otherwise DragXXX functions don't clamp."); + ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", &flags, ImGuiSliderFlags_Logarithmic); + ImGui::SameLine(); HelpMarker("Enable logarithmic editing (more precision for small values)."); + ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", &flags, ImGuiSliderFlags_NoRoundToFormat); + ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits)."); + ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput); + ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget."); + ImGui::CheckboxFlags("ImGuiSliderFlags_NoSpeedTweaks", &flags, ImGuiSliderFlags_NoSpeedTweaks); + ImGui::SameLine(); HelpMarker("Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic."); + ImGui::CheckboxFlags("ImGuiSliderFlags_WrapAround", &flags, ImGuiSliderFlags_WrapAround); + ImGui::SameLine(); HelpMarker("Enable wrapping around from max to min and from min to max (only supported by DragXXX() functions)"); + + // Drags + static float drag_f = 0.5f; + static int drag_i = 50; + ImGui::Text("Underlying float value: %f", drag_f); + ImGui::DragFloat("DragFloat (0 -> 1)", &drag_f, 0.005f, 0.0f, 1.0f, "%.3f", flags); + ImGui::DragFloat("DragFloat (0 -> +inf)", &drag_f, 0.005f, 0.0f, FLT_MAX, "%.3f", flags); + ImGui::DragFloat("DragFloat (-inf -> 1)", &drag_f, 0.005f, -FLT_MAX, 1.0f, "%.3f", flags); + ImGui::DragFloat("DragFloat (-inf -> +inf)", &drag_f, 0.005f, -FLT_MAX, +FLT_MAX, "%.3f", flags); + //ImGui::DragFloat("DragFloat (0 -> 0)", &drag_f, 0.005f, 0.0f, 0.0f, "%.3f", flags); // To test ClampZeroRange + //ImGui::DragFloat("DragFloat (100 -> 100)", &drag_f, 0.005f, 100.0f, 100.0f, "%.3f", flags); + ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags); + + // Sliders + static float slider_f = 0.5f; + static int slider_i = 50; + const ImGuiSliderFlags flags_for_sliders = flags & ~ImGuiSliderFlags_WrapAround; + ImGui::Text("Underlying float value: %f", slider_f); + ImGui::SliderFloat("SliderFloat (0 -> 1)", &slider_f, 0.0f, 1.0f, "%.3f", flags_for_sliders); + ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%d", flags_for_sliders); + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsImages() //----------------------------------------------------------------------------- @@ -2221,6 +2121,49 @@ static void DemoWindowWidgetsListBoxes() // [SECTION] DemoWindowWidgetsMultiComponents() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsMultiComponents() +{ + IMGUI_DEMO_MARKER("Widgets/Multi-component Widgets"); + if (ImGui::TreeNode("Multi-component Widgets")) + { + static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; + static int vec4i[4] = { 1, 5, 100, 255 }; + + ImGui::SeparatorText("2-wide"); + ImGui::InputFloat2("input float2", vec4f); + ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f); + ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f); + ImGui::InputInt2("input int2", vec4i); + ImGui::DragInt2("drag int2", vec4i, 1, 0, 255); + ImGui::SliderInt2("slider int2", vec4i, 0, 255); + + ImGui::SeparatorText("3-wide"); + ImGui::InputFloat3("input float3", vec4f); + ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f); + ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f); + ImGui::InputInt3("input int3", vec4i); + ImGui::DragInt3("drag int3", vec4i, 1, 0, 255); + ImGui::SliderInt3("slider int3", vec4i, 0, 255); + + ImGui::SeparatorText("4-wide"); + ImGui::InputFloat4("input float4", vec4f); + ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f); + ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f); + ImGui::InputInt4("input int4", vec4i); + ImGui::DragInt4("drag int4", vec4i, 1, 0, 255); + ImGui::SliderInt4("slider int4", vec4i, 0, 255); + + ImGui::SeparatorText("Ranges"); + static float begin = 10, end = 90; + static int begin_i = 100, end_i = 1000; + ImGui::DragFloatRange2("range float", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%", ImGuiSliderFlags_AlwaysClamp); + ImGui::DragIntRange2("range int", &begin_i, &end_i, 5, 0, 1000, "Min: %d units", "Max: %d units"); + ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units"); + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsPlotting() //----------------------------------------------------------------------------- @@ -4152,6 +4095,74 @@ static void DemoWindowWidgetsTreeNodes() // [SECTION] DemoWindowWidgetsVerticalSliders() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsVerticalSliders() +{ + IMGUI_DEMO_MARKER("Widgets/Vertical Sliders"); + if (ImGui::TreeNode("Vertical Sliders")) + { + const float spacing = 4; + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing)); + + static int int_value = 0; + ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5); + ImGui::SameLine(); + + static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f }; + ImGui::PushID("set1"); + for (int i = 0; i < 7; i++) + { + if (i > 0) ImGui::SameLine(); + ImGui::PushID(i); + ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f)); + ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f)); + ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, ""); + if (ImGui::IsItemActive() || ImGui::IsItemHovered()) + ImGui::SetTooltip("%.3f", values[i]); + ImGui::PopStyleColor(4); + ImGui::PopID(); + } + ImGui::PopID(); + + ImGui::SameLine(); + ImGui::PushID("set2"); + static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f }; + const int rows = 3; + const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows)); + for (int nx = 0; nx < 4; nx++) + { + if (nx > 0) ImGui::SameLine(); + ImGui::BeginGroup(); + for (int ny = 0; ny < rows; ny++) + { + ImGui::PushID(nx * rows + ny); + ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, ""); + if (ImGui::IsItemActive() || ImGui::IsItemHovered()) + ImGui::SetTooltip("%.3f", values2[nx]); + ImGui::PopID(); + } + ImGui::EndGroup(); + } + ImGui::PopID(); + + ImGui::SameLine(); + ImGui::PushID("set3"); + for (int i = 0; i < 4; i++) + { + if (i > 0) ImGui::SameLine(); + ImGui::PushID(i); + ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40); + ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec"); + ImGui::PopStyleVar(); + ImGui::PopID(); + } + ImGui::PopID(); + ImGui::PopStyleVar(); + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowLayout() //----------------------------------------------------------------------------- From 0758594bd2ea56c341005911b74700cea57216a7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 18:45:59 +0100 Subject: [PATCH 513/548] Demo: (Refactor) Moved code into DemoWindowWidgetsDragAndDrop() section. --- imgui_demo.cpp | 307 +++++++++++++++++++++++++------------------------ 1 file changed, 156 insertions(+), 151 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9d9cf112b913..b2a0a5e78dec 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -256,6 +256,7 @@ static void DemoWindowWidgetsCollapsingHeaders(); static void DemoWindowWidgetsComboBoxes(); static void DemoWindowWidgetsColorAndPickers(); static void DemoWindowWidgetsDataTypes(); +static void DemoWindowWidgetsDragAndDrop(); static void DemoWindowWidgetsDragsAndSliders(); static void DemoWindowWidgetsImages(); static void DemoWindowWidgetsListBoxes(); @@ -833,6 +834,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsComboBoxes(); DemoWindowWidgetsColorAndPickers(); DemoWindowWidgetsDataTypes(); + DemoWindowWidgetsDragAndDrop(); DemoWindowWidgetsDragsAndSliders(); DemoWindowWidgetsImages(); DemoWindowWidgetsListBoxes(); @@ -849,157 +851,6 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsTreeNodes(); DemoWindowWidgetsVerticalSliders(); - IMGUI_DEMO_MARKER("Widgets/Drag and drop"); - if (ImGui::TreeNode("Drag and Drop")) - { - IMGUI_DEMO_MARKER("Widgets/Drag and drop/Standard widgets"); - if (ImGui::TreeNode("Drag and drop in standard widgets")) - { - // ColorEdit widgets automatically act as drag source and drag target. - // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F - // to allow your own widgets to use colors in their drag and drop interaction. - // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo. - HelpMarker("You can drag from the color squares."); - static float col1[3] = { 1.0f, 0.0f, 0.2f }; - static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; - ImGui::ColorEdit3("color 1", col1); - ImGui::ColorEdit4("color 2", col2); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Drag and drop/Copy-swap items"); - if (ImGui::TreeNode("Drag and drop to copy/swap items")) - { - enum Mode - { - Mode_Copy, - Mode_Move, - Mode_Swap - }; - static int mode = 0; - if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine(); - if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine(); - if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; } - static const char* names[9] = - { - "Bobby", "Beatrice", "Betty", - "Brianna", "Barry", "Bernard", - "Bibi", "Blaine", "Bryn" - }; - for (int n = 0; n < IM_ARRAYSIZE(names); n++) - { - ImGui::PushID(n); - if ((n % 3) != 0) - ImGui::SameLine(); - ImGui::Button(names[n], ImVec2(60, 60)); - - // Our buttons are both drag sources and drag targets here! - if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) - { - // Set payload to carry the index of our item (could be anything) - ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int)); - - // Display preview (could be anything, e.g. when dragging an image we could decide to display - // the filename and a small preview of the image, etc.) - if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); } - if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); } - if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); } - ImGui::EndDragDropSource(); - } - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL")) - { - IM_ASSERT(payload->DataSize == sizeof(int)); - int payload_n = *(const int*)payload->Data; - if (mode == Mode_Copy) - { - names[n] = names[payload_n]; - } - if (mode == Mode_Move) - { - names[n] = names[payload_n]; - names[payload_n] = ""; - } - if (mode == Mode_Swap) - { - const char* tmp = names[n]; - names[n] = names[payload_n]; - names[payload_n] = tmp; - } - } - ImGui::EndDragDropTarget(); - } - ImGui::PopID(); - } - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Drag to reorder items (simple)"); - if (ImGui::TreeNode("Drag to reorder items (simple)")) - { - // FIXME: there is temporary (usually single-frame) ID Conflict during reordering as a same item may be submitting twice. - // This code was always slightly faulty but in a way which was not easily noticeable. - // Until we fix this, enable ImGuiItemFlags_AllowDuplicateId to disable detecting the issue. - ImGui::PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); - - // Simple reordering - HelpMarker( - "We don't use the drag and drop api at all here! " - "Instead we query when the item is held but not hovered, and order items accordingly."); - static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" }; - for (int n = 0; n < IM_ARRAYSIZE(item_names); n++) - { - const char* item = item_names[n]; - ImGui::Selectable(item); - - if (ImGui::IsItemActive() && !ImGui::IsItemHovered()) - { - int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1); - if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names)) - { - item_names[n] = item_names[n_next]; - item_names[n_next] = item; - ImGui::ResetMouseDragDelta(); - } - } - } - - ImGui::PopItemFlag(); - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Tooltip at target location"); - if (ImGui::TreeNode("Tooltip at target location")) - { - for (int n = 0; n < 2; n++) - { - // Drop targets - ImGui::Button(n ? "drop here##1" : "drop here##0"); - if (ImGui::BeginDragDropTarget()) - { - ImGuiDragDropFlags drop_target_flags = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoPreviewTooltip; - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, drop_target_flags)) - { - IM_UNUSED(payload); - ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed); - ImGui::SetTooltip("Cannot drop here!"); - } - ImGui::EndDragDropTarget(); - } - - // Drop source - static ImVec4 col4 = { 1.0f, 0.0f, 0.2f, 1.0f }; - if (n == 0) - ImGui::ColorButton("drag me", col4); - - } - ImGui::TreePop(); - } - - ImGui::TreePop(); - } - IMGUI_DEMO_MARKER("Widgets/Querying Item Status (Edited,Active,Hovered etc.)"); if (ImGui::TreeNode("Querying Item Status (Edited/Active/Hovered etc.)")) { @@ -1912,6 +1763,160 @@ static void DemoWindowWidgetsDataTypes() // [SECTION] DemoWindowWidgetsDragAndDrop() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsDragAndDrop() +{ + IMGUI_DEMO_MARKER("Widgets/Drag and drop"); + if (ImGui::TreeNode("Drag and Drop")) + { + IMGUI_DEMO_MARKER("Widgets/Drag and drop/Standard widgets"); + if (ImGui::TreeNode("Drag and drop in standard widgets")) + { + // ColorEdit widgets automatically act as drag source and drag target. + // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F + // to allow your own widgets to use colors in their drag and drop interaction. + // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo. + HelpMarker("You can drag from the color squares."); + static float col1[3] = { 1.0f, 0.0f, 0.2f }; + static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; + ImGui::ColorEdit3("color 1", col1); + ImGui::ColorEdit4("color 2", col2); + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Drag and drop/Copy-swap items"); + if (ImGui::TreeNode("Drag and drop to copy/swap items")) + { + enum Mode + { + Mode_Copy, + Mode_Move, + Mode_Swap + }; + static int mode = 0; + if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine(); + if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine(); + if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; } + static const char* names[9] = + { + "Bobby", "Beatrice", "Betty", + "Brianna", "Barry", "Bernard", + "Bibi", "Blaine", "Bryn" + }; + for (int n = 0; n < IM_ARRAYSIZE(names); n++) + { + ImGui::PushID(n); + if ((n % 3) != 0) + ImGui::SameLine(); + ImGui::Button(names[n], ImVec2(60, 60)); + + // Our buttons are both drag sources and drag targets here! + if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) + { + // Set payload to carry the index of our item (could be anything) + ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int)); + + // Display preview (could be anything, e.g. when dragging an image we could decide to display + // the filename and a small preview of the image, etc.) + if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); } + if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); } + if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); } + ImGui::EndDragDropSource(); + } + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL")) + { + IM_ASSERT(payload->DataSize == sizeof(int)); + int payload_n = *(const int*)payload->Data; + if (mode == Mode_Copy) + { + names[n] = names[payload_n]; + } + if (mode == Mode_Move) + { + names[n] = names[payload_n]; + names[payload_n] = ""; + } + if (mode == Mode_Swap) + { + const char* tmp = names[n]; + names[n] = names[payload_n]; + names[payload_n] = tmp; + } + } + ImGui::EndDragDropTarget(); + } + ImGui::PopID(); + } + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Drag to reorder items (simple)"); + if (ImGui::TreeNode("Drag to reorder items (simple)")) + { + // FIXME: there is temporary (usually single-frame) ID Conflict during reordering as a same item may be submitting twice. + // This code was always slightly faulty but in a way which was not easily noticeable. + // Until we fix this, enable ImGuiItemFlags_AllowDuplicateId to disable detecting the issue. + ImGui::PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true); + + // Simple reordering + HelpMarker( + "We don't use the drag and drop api at all here! " + "Instead we query when the item is held but not hovered, and order items accordingly."); + static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" }; + for (int n = 0; n < IM_ARRAYSIZE(item_names); n++) + { + const char* item = item_names[n]; + ImGui::Selectable(item); + + if (ImGui::IsItemActive() && !ImGui::IsItemHovered()) + { + int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1); + if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names)) + { + item_names[n] = item_names[n_next]; + item_names[n_next] = item; + ImGui::ResetMouseDragDelta(); + } + } + } + + ImGui::PopItemFlag(); + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Tooltip at target location"); + if (ImGui::TreeNode("Tooltip at target location")) + { + for (int n = 0; n < 2; n++) + { + // Drop targets + ImGui::Button(n ? "drop here##1" : "drop here##0"); + if (ImGui::BeginDragDropTarget()) + { + ImGuiDragDropFlags drop_target_flags = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoPreviewTooltip; + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, drop_target_flags)) + { + IM_UNUSED(payload); + ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed); + ImGui::SetTooltip("Cannot drop here!"); + } + ImGui::EndDragDropTarget(); + } + + // Drop source + static ImVec4 col4 = { 1.0f, 0.0f, 0.2f, 1.0f }; + if (n == 0) + ImGui::ColorButton("drag me", col4); + + } + ImGui::TreePop(); + } + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsDragsAndSliders() //----------------------------------------------------------------------------- From 7a919e80c9dd0a39f5d3a08a19e53504795ba03f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 18:49:02 +0100 Subject: [PATCH 514/548] Demo: (Refactor) Moved code into DemoWindowWidgetsQueryingStatuses() section. --- imgui_demo.cpp | 393 +++++++++++++++++++++++++------------------------ 1 file changed, 199 insertions(+), 194 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b2a0a5e78dec..bb3f6ef7c4e1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -263,6 +263,7 @@ static void DemoWindowWidgetsListBoxes(); static void DemoWindowWidgetsPlotting(); static void DemoWindowWidgetsMultiComponents(); static void DemoWindowWidgetsProgressBars(); +static void DemoWindowWidgetsQueryingStatuses(); static void DemoWindowWidgetsSelectables(); static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgetsTabs(); @@ -841,6 +842,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsMultiComponents(); DemoWindowWidgetsPlotting(); DemoWindowWidgetsProgressBars(); + DemoWindowWidgetsQueryingStatuses(); DemoWindowWidgetsSelectables(); DemoWindowWidgetsSelectionAndMultiSelect(demo_data); DemoWindowWidgetsTabs(); @@ -851,200 +853,6 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsTreeNodes(); DemoWindowWidgetsVerticalSliders(); - IMGUI_DEMO_MARKER("Widgets/Querying Item Status (Edited,Active,Hovered etc.)"); - if (ImGui::TreeNode("Querying Item Status (Edited/Active/Hovered etc.)")) - { - // Select an item type - const char* item_names[] = - { - "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputTextMultiline", "InputFloat", - "InputFloat3", "ColorEdit4", "Selectable", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox" - }; - static int item_type = 4; - static bool item_disabled = false; - ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names)); - ImGui::SameLine(); - HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered()."); - ImGui::Checkbox("Item Disabled", &item_disabled); - - // Submit selected items so we can query their status in the code following it. - bool ret = false; - static bool b = false; - static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f }; - static char str[16] = {}; - if (item_disabled) - ImGui::BeginDisabled(true); - if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction - if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button - if (item_type == 2) { ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); ret = ImGui::Button("ITEM: Button"); ImGui::PopItemFlag(); } // Testing button (with repeater) - if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox - if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item - if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing) - if (item_type == 6) { ret = ImGui::InputTextMultiline("ITEM: InputTextMultiline", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which uses a child window) - if (item_type == 7) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); } // Testing +/- buttons on scalar input - if (item_type == 8) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) - if (item_type == 9) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) - if (item_type == 10){ ret = ImGui::Selectable("ITEM: Selectable"); } // Testing selectable item - if (item_type == 11){ ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) - if (item_type == 12){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node - if (item_type == 13){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. - if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", ¤t, items, IM_ARRAYSIZE(items)); } - if (item_type == 15){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } - - bool hovered_delay_none = ImGui::IsItemHovered(); - bool hovered_delay_stationary = ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary); - bool hovered_delay_short = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort); - bool hovered_delay_normal = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal); - bool hovered_delay_tooltip = ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip); // = Normal + Stationary - - // Display the values of IsItemHovered() and other common item state functions. - // Note that the ImGuiHoveredFlags_XXX flags can be combined. - // Because BulletText is an item itself and that would affect the output of IsItemXXX functions, - // we query every state in a single call to avoid storing them and to simplify the code. - ImGui::BulletText( - "Return value = %d\n" - "IsItemFocused() = %d\n" - "IsItemHovered() = %d\n" - "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n" - "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n" - "IsItemHovered(_AllowWhenOverlappedByItem) = %d\n" - "IsItemHovered(_AllowWhenOverlappedByWindow) = %d\n" - "IsItemHovered(_AllowWhenDisabled) = %d\n" - "IsItemHovered(_RectOnly) = %d\n" - "IsItemActive() = %d\n" - "IsItemEdited() = %d\n" - "IsItemActivated() = %d\n" - "IsItemDeactivated() = %d\n" - "IsItemDeactivatedAfterEdit() = %d\n" - "IsItemVisible() = %d\n" - "IsItemClicked() = %d\n" - "IsItemToggledOpen() = %d\n" - "GetItemRectMin() = (%.1f, %.1f)\n" - "GetItemRectMax() = (%.1f, %.1f)\n" - "GetItemRectSize() = (%.1f, %.1f)", - ret, - ImGui::IsItemFocused(), - ImGui::IsItemHovered(), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByItem), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByWindow), - ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled), - ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly), - ImGui::IsItemActive(), - ImGui::IsItemEdited(), - ImGui::IsItemActivated(), - ImGui::IsItemDeactivated(), - ImGui::IsItemDeactivatedAfterEdit(), - ImGui::IsItemVisible(), - ImGui::IsItemClicked(), - ImGui::IsItemToggledOpen(), - ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y, - ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y, - ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y - ); - ImGui::BulletText( - "with Hovering Delay or Stationary test:\n" - "IsItemHovered() = = %d\n" - "IsItemHovered(_Stationary) = %d\n" - "IsItemHovered(_DelayShort) = %d\n" - "IsItemHovered(_DelayNormal) = %d\n" - "IsItemHovered(_Tooltip) = %d", - hovered_delay_none, hovered_delay_stationary, hovered_delay_short, hovered_delay_normal, hovered_delay_tooltip); - - if (item_disabled) - ImGui::EndDisabled(); - - char buf[1] = ""; - ImGui::InputText("unused", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_ReadOnly); - ImGui::SameLine(); - HelpMarker("This widget is only here to be able to tab-out of the widgets above and see e.g. Deactivated() status."); - - ImGui::TreePop(); - } - - IMGUI_DEMO_MARKER("Widgets/Querying Window Status (Focused,Hovered etc.)"); - if (ImGui::TreeNode("Querying Window Status (Focused/Hovered etc.)")) - { - static bool embed_all_inside_a_child_window = false; - ImGui::Checkbox("Embed everything inside a child window for testing _RootWindow flag.", &embed_all_inside_a_child_window); - if (embed_all_inside_a_child_window) - ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), ImGuiChildFlags_Borders); - - // Testing IsWindowFocused() function with its various flags. - ImGui::BulletText( - "IsWindowFocused() = %d\n" - "IsWindowFocused(_ChildWindows) = %d\n" - "IsWindowFocused(_ChildWindows|_NoPopupHierarchy) = %d\n" - "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n" - "IsWindowFocused(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n" - "IsWindowFocused(_RootWindow) = %d\n" - "IsWindowFocused(_RootWindow|_NoPopupHierarchy) = %d\n" - "IsWindowFocused(_AnyWindow) = %d\n", - ImGui::IsWindowFocused(), - ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows), - ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy), - ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow), - ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy), - ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow), - ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy), - ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)); - - // Testing IsWindowHovered() function with its various flags. - ImGui::BulletText( - "IsWindowHovered() = %d\n" - "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" - "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n" - "IsWindowHovered(_ChildWindows) = %d\n" - "IsWindowHovered(_ChildWindows|_NoPopupHierarchy) = %d\n" - "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n" - "IsWindowHovered(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n" - "IsWindowHovered(_RootWindow) = %d\n" - "IsWindowHovered(_RootWindow|_NoPopupHierarchy) = %d\n" - "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n" - "IsWindowHovered(_AnyWindow) = %d\n" - "IsWindowHovered(_Stationary) = %d\n", - ImGui::IsWindowHovered(), - ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), - ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), - ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows), - ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy), - ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), - ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy), - ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow), - ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy), - ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup), - ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow), - ImGui::IsWindowHovered(ImGuiHoveredFlags_Stationary)); - - ImGui::BeginChild("child", ImVec2(0, 50), ImGuiChildFlags_Borders); - ImGui::Text("This is another child window for testing the _ChildWindows flag."); - ImGui::EndChild(); - if (embed_all_inside_a_child_window) - ImGui::EndChild(); - - // Calling IsItemHovered() after begin returns the hovered status of the title bar. - // This is useful in particular if you want to create a context menu associated to the title bar of a window. - static bool test_window = false; - ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window); - if (test_window) - { - ImGui::Begin("Title bar Hovered/Active tests", &test_window); - if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered() - { - if (ImGui::MenuItem("Close")) { test_window = false; } - ImGui::EndPopup(); - } - ImGui::Text( - "IsItemHovered() after begin = %d (== is title bar hovered)\n" - "IsItemActive() after begin = %d (== is window being clicked/moved)\n", - ImGui::IsItemHovered(), ImGui::IsItemActive()); - ImGui::End(); - } - - ImGui::TreePop(); - } - // Demonstrate BeginDisabled/EndDisabled using a checkbox located at the bottom of the section (which is a bit odd: // logically we'd have this checkbox at the top of the section, but we don't want this feature to steal that space) if (disable_all) @@ -2285,6 +2093,203 @@ static void DemoWindowWidgetsProgressBars() // [SECTION] DemoWindowWidgetsQueryingStatuses() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsQueryingStatuses() +{ + IMGUI_DEMO_MARKER("Widgets/Querying Item Status (Edited,Active,Hovered etc.)"); + if (ImGui::TreeNode("Querying Item Status (Edited/Active/Hovered etc.)")) + { + // Select an item type + const char* item_names[] = + { + "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputTextMultiline", "InputFloat", + "InputFloat3", "ColorEdit4", "Selectable", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox" + }; + static int item_type = 4; + static bool item_disabled = false; + ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names)); + ImGui::SameLine(); + HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered()."); + ImGui::Checkbox("Item Disabled", &item_disabled); + + // Submit selected items so we can query their status in the code following it. + bool ret = false; + static bool b = false; + static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f }; + static char str[16] = {}; + if (item_disabled) + ImGui::BeginDisabled(true); + if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction + if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button + if (item_type == 2) { ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); ret = ImGui::Button("ITEM: Button"); ImGui::PopItemFlag(); } // Testing button (with repeater) + if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox + if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item + if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing) + if (item_type == 6) { ret = ImGui::InputTextMultiline("ITEM: InputTextMultiline", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which uses a child window) + if (item_type == 7) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); } // Testing +/- buttons on scalar input + if (item_type == 8) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) + if (item_type == 9) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) + if (item_type == 10) { ret = ImGui::Selectable("ITEM: Selectable"); } // Testing selectable item + if (item_type == 11) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) + if (item_type == 12) { ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node + if (item_type == 13) { ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. + if (item_type == 14) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", ¤t, items, IM_ARRAYSIZE(items)); } + if (item_type == 15) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } + + bool hovered_delay_none = ImGui::IsItemHovered(); + bool hovered_delay_stationary = ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary); + bool hovered_delay_short = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort); + bool hovered_delay_normal = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal); + bool hovered_delay_tooltip = ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip); // = Normal + Stationary + + // Display the values of IsItemHovered() and other common item state functions. + // Note that the ImGuiHoveredFlags_XXX flags can be combined. + // Because BulletText is an item itself and that would affect the output of IsItemXXX functions, + // we query every state in a single call to avoid storing them and to simplify the code. + ImGui::BulletText( + "Return value = %d\n" + "IsItemFocused() = %d\n" + "IsItemHovered() = %d\n" + "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n" + "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n" + "IsItemHovered(_AllowWhenOverlappedByItem) = %d\n" + "IsItemHovered(_AllowWhenOverlappedByWindow) = %d\n" + "IsItemHovered(_AllowWhenDisabled) = %d\n" + "IsItemHovered(_RectOnly) = %d\n" + "IsItemActive() = %d\n" + "IsItemEdited() = %d\n" + "IsItemActivated() = %d\n" + "IsItemDeactivated() = %d\n" + "IsItemDeactivatedAfterEdit() = %d\n" + "IsItemVisible() = %d\n" + "IsItemClicked() = %d\n" + "IsItemToggledOpen() = %d\n" + "GetItemRectMin() = (%.1f, %.1f)\n" + "GetItemRectMax() = (%.1f, %.1f)\n" + "GetItemRectSize() = (%.1f, %.1f)", + ret, + ImGui::IsItemFocused(), + ImGui::IsItemHovered(), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByItem), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByWindow), + ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled), + ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly), + ImGui::IsItemActive(), + ImGui::IsItemEdited(), + ImGui::IsItemActivated(), + ImGui::IsItemDeactivated(), + ImGui::IsItemDeactivatedAfterEdit(), + ImGui::IsItemVisible(), + ImGui::IsItemClicked(), + ImGui::IsItemToggledOpen(), + ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y, + ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y, + ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y + ); + ImGui::BulletText( + "with Hovering Delay or Stationary test:\n" + "IsItemHovered() = = %d\n" + "IsItemHovered(_Stationary) = %d\n" + "IsItemHovered(_DelayShort) = %d\n" + "IsItemHovered(_DelayNormal) = %d\n" + "IsItemHovered(_Tooltip) = %d", + hovered_delay_none, hovered_delay_stationary, hovered_delay_short, hovered_delay_normal, hovered_delay_tooltip); + + if (item_disabled) + ImGui::EndDisabled(); + + char buf[1] = ""; + ImGui::InputText("unused", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_ReadOnly); + ImGui::SameLine(); + HelpMarker("This widget is only here to be able to tab-out of the widgets above and see e.g. Deactivated() status."); + + ImGui::TreePop(); + } + + IMGUI_DEMO_MARKER("Widgets/Querying Window Status (Focused,Hovered etc.)"); + if (ImGui::TreeNode("Querying Window Status (Focused/Hovered etc.)")) + { + static bool embed_all_inside_a_child_window = false; + ImGui::Checkbox("Embed everything inside a child window for testing _RootWindow flag.", &embed_all_inside_a_child_window); + if (embed_all_inside_a_child_window) + ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), ImGuiChildFlags_Borders); + + // Testing IsWindowFocused() function with its various flags. + ImGui::BulletText( + "IsWindowFocused() = %d\n" + "IsWindowFocused(_ChildWindows) = %d\n" + "IsWindowFocused(_ChildWindows|_NoPopupHierarchy) = %d\n" + "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n" + "IsWindowFocused(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n" + "IsWindowFocused(_RootWindow) = %d\n" + "IsWindowFocused(_RootWindow|_NoPopupHierarchy) = %d\n" + "IsWindowFocused(_AnyWindow) = %d\n", + ImGui::IsWindowFocused(), + ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows), + ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy), + ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow), + ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy), + ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow), + ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy), + ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)); + + // Testing IsWindowHovered() function with its various flags. + ImGui::BulletText( + "IsWindowHovered() = %d\n" + "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" + "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n" + "IsWindowHovered(_ChildWindows) = %d\n" + "IsWindowHovered(_ChildWindows|_NoPopupHierarchy) = %d\n" + "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n" + "IsWindowHovered(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n" + "IsWindowHovered(_RootWindow) = %d\n" + "IsWindowHovered(_RootWindow|_NoPopupHierarchy) = %d\n" + "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n" + "IsWindowHovered(_AnyWindow) = %d\n" + "IsWindowHovered(_Stationary) = %d\n", + ImGui::IsWindowHovered(), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy), + ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_Stationary)); + + ImGui::BeginChild("child", ImVec2(0, 50), ImGuiChildFlags_Borders); + ImGui::Text("This is another child window for testing the _ChildWindows flag."); + ImGui::EndChild(); + if (embed_all_inside_a_child_window) + ImGui::EndChild(); + + // Calling IsItemHovered() after begin returns the hovered status of the title bar. + // This is useful in particular if you want to create a context menu associated to the title bar of a window. + static bool test_window = false; + ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window); + if (test_window) + { + ImGui::Begin("Title bar Hovered/Active tests", &test_window); + if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered() + { + if (ImGui::MenuItem("Close")) { test_window = false; } + ImGui::EndPopup(); + } + ImGui::Text( + "IsItemHovered() after begin = %d (== is title bar hovered)\n" + "IsItemActive() after begin = %d (== is window being clicked/moved)\n", + ImGui::IsItemHovered(), ImGui::IsItemActive()); + ImGui::End(); + } + + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsSelectables() //----------------------------------------------------------------------------- From 71b160cdbb15979dd4142719a5c0ed05d10373ea Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 18:53:45 +0100 Subject: [PATCH 515/548] Demo: (Refactor) Moved code into DemoWindowWidgetsDisableBlocks() section. --- imgui.h | 2 +- imgui_demo.cpp | 34 ++++++++++++++++++++++------------ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/imgui.h b/imgui.h index 641b1ab92123..1cda94914594 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.9 WIP" -#define IMGUI_VERSION_NUM 19185 +#define IMGUI_VERSION_NUM 19186 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index bb3f6ef7c4e1..31904b1b4754 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -256,6 +256,7 @@ static void DemoWindowWidgetsCollapsingHeaders(); static void DemoWindowWidgetsComboBoxes(); static void DemoWindowWidgetsColorAndPickers(); static void DemoWindowWidgetsDataTypes(); +static void DemoWindowWidgetsDisableBlocks(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgetsDragAndDrop(); static void DemoWindowWidgetsDragsAndSliders(); static void DemoWindowWidgetsImages(); @@ -427,6 +428,7 @@ struct ImGuiDemoWindowData bool ShowAbout = false; // Other data + bool DisableSections = false; ExampleTreeNode* DemoTree = NULL; ~ImGuiDemoWindowData() { if (DemoTree) ExampleTree_DestroyNode(DemoTree); } @@ -825,7 +827,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) if (!ImGui::CollapsingHeader("Widgets")) return; - static bool disable_all = false; // The Checkbox for that is inside the "Disabled" section at the bottom + const bool disable_all = demo_data->DisableSections; // The Checkbox for that is inside the "Disabled" section at the bottom if (disable_all) ImGui::BeginDisabled(); @@ -835,6 +837,13 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsComboBoxes(); DemoWindowWidgetsColorAndPickers(); DemoWindowWidgetsDataTypes(); + + if (disable_all) + ImGui::EndDisabled(); + DemoWindowWidgetsDisableBlocks(demo_data); + if (disable_all) + ImGui::BeginDisabled(); + DemoWindowWidgetsDragAndDrop(); DemoWindowWidgetsDragsAndSliders(); DemoWindowWidgetsImages(); @@ -853,18 +862,8 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) DemoWindowWidgetsTreeNodes(); DemoWindowWidgetsVerticalSliders(); - // Demonstrate BeginDisabled/EndDisabled using a checkbox located at the bottom of the section (which is a bit odd: - // logically we'd have this checkbox at the top of the section, but we don't want this feature to steal that space) if (disable_all) ImGui::EndDisabled(); - - IMGUI_DEMO_MARKER("Widgets/Disable Block"); - if (ImGui::TreeNode("Disable block")) - { - ImGui::Checkbox("Disable entire section above", &disable_all); - ImGui::SameLine(); HelpMarker("Demonstrate using BeginDisabled()/EndDisabled() across this section."); - ImGui::TreePop(); - } } //----------------------------------------------------------------------------- @@ -1567,6 +1566,17 @@ static void DemoWindowWidgetsDataTypes() // [SECTION] DemoWindowWidgetsDisableBlocks() //----------------------------------------------------------------------------- +static void DemoWindowWidgetsDisableBlocks(ImGuiDemoWindowData* demo_data) +{ + IMGUI_DEMO_MARKER("Widgets/Disable Blocks"); + if (ImGui::TreeNode("Disable Blocks")) + { + ImGui::Checkbox("Disable entire section above", &demo_data->DisableSections); + ImGui::SameLine(); HelpMarker("Demonstrate using BeginDisabled()/EndDisabled() across other sections."); + ImGui::TreePop(); + } +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsDragAndDrop() //----------------------------------------------------------------------------- @@ -1872,7 +1882,7 @@ static void DemoWindowWidgetsImages() static void DemoWindowWidgetsListBoxes() { IMGUI_DEMO_MARKER("Widgets/List Boxes"); - if (ImGui::TreeNode("List boxes")) + if (ImGui::TreeNode("List Boxes")) { // BeginListBox() is essentially a thin wrapper to using BeginChild()/EndChild() // using the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. From df317743272165a8bda2dbe85a0f751495a1e150 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 3 Mar 2025 19:20:10 +0100 Subject: [PATCH 516/548] Disabled: Fixed an issue restoring Alpha in EndDisabled() when using nested BeginDisabled() calls with PushStyleVar(ImGuiStyleVar_DisabledAlpha) within. (#8454, #7640) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 4 +++- imgui_internal.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 390681161e0a..2df26e655e26 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -103,6 +103,8 @@ Other changes: (#8451, #7660) [@achabense] - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] +- Disabled: Fixed an issue restoring Alpha in EndDisabled() when using nested + BeginDisabled() calls with PushStyleVar(ImGuiStyleVar_DisabledAlpha) within. (#8454, #7640) - Clipper: Fixed an issue where passing an out of bound index to IncludeItemByIndex() could incorrectly offset the final cursor, even if that index was not iterated through. One case where it would manifest was calling Combo() with an out of range index. (#8450) diff --git a/imgui.cpp b/imgui.cpp index 77e3c1d36422..bae74db5f2c1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7084,6 +7084,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window_stack_data.Window = window; window_stack_data.ParentLastItemDataBackup = g.LastItemData; window_stack_data.DisabledOverrideReenable = (flags & ImGuiWindowFlags_Tooltip) && (g.CurrentItemFlags & ImGuiItemFlags_Disabled); + window_stack_data.DisabledOverrideReenableAlphaBackup = 0.0f; ErrorRecoveryStoreState(&window_stack_data.StackSizesInBegin); g.StackSizesInBeginForCurrentWindow = &window_stack_data.StackSizesInBegin; if (flags & ImGuiWindowFlags_ChildMenu) @@ -7950,6 +7951,7 @@ void ImGui::BeginDisabledOverrideReenable() { ImGuiContext& g = *GImGui; IM_ASSERT(g.CurrentItemFlags & ImGuiItemFlags_Disabled); + g.CurrentWindowStack.back().DisabledOverrideReenableAlphaBackup = g.Style.Alpha; g.Style.Alpha = g.DisabledAlphaBackup; g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled; g.ItemFlagsStack.push_back(g.CurrentItemFlags); @@ -7963,7 +7965,7 @@ void ImGui::EndDisabledOverrideReenable() IM_ASSERT(g.DisabledStackSize > 0); g.ItemFlagsStack.pop_back(); g.CurrentItemFlags = g.ItemFlagsStack.back(); - g.Style.Alpha = g.DisabledAlphaBackup * g.Style.DisabledAlpha; + g.Style.Alpha = g.CurrentWindowStack.back().DisabledOverrideReenableAlphaBackup; } void ImGui::PushTextWrapPos(float wrap_pos_x) diff --git a/imgui_internal.h b/imgui_internal.h index 4bdc6e94791c..40b854559c2c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1316,6 +1316,7 @@ struct ImGuiWindowStackData ImGuiLastItemData ParentLastItemDataBackup; ImGuiErrorRecoveryState StackSizesInBegin; // Store size of various stacks for asserting bool DisabledOverrideReenable; // Non-child window override disabled flag + float DisabledOverrideReenableAlphaBackup; }; struct ImGuiShrinkWidthItem From a7657f2ed45508bb719a8b9e2d8e7bda57eff4a0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 4 Mar 2025 14:36:00 +0100 Subject: [PATCH 517/548] Examples: SDL3: Added comments to clarify setup for users of the unfortunate SDL_MAIN_USE_CALLBACKS feature. (#8455) --- docs/CHANGELOG.txt | 2 ++ examples/example_sdl3_opengl3/main.cpp | 5 +++++ examples/example_sdl3_sdlgpu3/main.cpp | 7 ++++++- examples/example_sdl3_sdlrenderer3/main.cpp | 5 +++++ examples/example_sdl3_vulkan/main.cpp | 7 ++++++- 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2df26e655e26..78c6f09da0f7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -115,6 +115,8 @@ Other changes: - Demo: Reorganized "Widgets" section to be alphabetically ordered and split in more functions. - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) +- Examples: SDL3: Added comments to clarify setup for users of the unfortunate + SDL_MAIN_USE_CALLBACKS feature. (#8455) - Backends: GLFW: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. (#8452) - Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp index 8cd54bd4ef68..d8666061dac6 100644 --- a/examples/example_sdl3_opengl3/main.cpp +++ b/examples/example_sdl3_opengl3/main.cpp @@ -26,6 +26,7 @@ int main(int, char**) { // Setup SDL + // [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function] if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); @@ -139,6 +140,7 @@ int main(int, char**) // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. // - 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. + // [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function] SDL_Event event; while (SDL_PollEvent(&event)) { @@ -148,6 +150,8 @@ int main(int, char**) if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window)) done = true; } + + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function] if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) { SDL_Delay(10); @@ -209,6 +213,7 @@ int main(int, char**) #endif // Cleanup + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function] ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplSDL3_Shutdown(); ImGui::DestroyContext(); diff --git a/examples/example_sdl3_sdlgpu3/main.cpp b/examples/example_sdl3_sdlgpu3/main.cpp index dbc7759ba5d5..630639f3fefb 100644 --- a/examples/example_sdl3_sdlgpu3/main.cpp +++ b/examples/example_sdl3_sdlgpu3/main.cpp @@ -26,7 +26,8 @@ int main(int, char**) { // Setup SDL - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD) != 0) + // [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function] + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); return -1; @@ -105,6 +106,7 @@ int main(int, char**) // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. // - 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. + // [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function] SDL_Event event; while (SDL_PollEvent(&event)) { @@ -114,6 +116,8 @@ int main(int, char**) if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window)) done = true; } + + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function] if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) { SDL_Delay(10); @@ -199,6 +203,7 @@ int main(int, char**) } // Cleanup + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function] SDL_WaitForGPUIdle(gpu_device); ImGui_ImplSDL3_Shutdown(); ImGui_ImplSDLGPU3_Shutdown(); diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 68078eebdebd..ad05a0f919c2 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -24,6 +24,7 @@ int main(int, char**) { // Setup SDL + // [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function] if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); @@ -101,6 +102,7 @@ int main(int, char**) // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. // - 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. + // [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function] SDL_Event event; while (SDL_PollEvent(&event)) { @@ -110,6 +112,8 @@ int main(int, char**) if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window)) done = true; } + + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function] if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) { SDL_Delay(10); @@ -171,6 +175,7 @@ int main(int, char**) #endif // Cleanup + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function] ImGui_ImplSDLRenderer3_Shutdown(); ImGui_ImplSDL3_Shutdown(); ImGui::DestroyContext(); diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index 99e441d7ef4b..170eae45b01b 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -345,7 +345,8 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) int main(int, char**) { // Setup SDL - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD) != 0) + // [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function] + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); return -1; @@ -447,6 +448,7 @@ int main(int, char**) // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. // - 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. + // [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function] SDL_Event event; while (SDL_PollEvent(&event)) { @@ -456,6 +458,8 @@ int main(int, char**) if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window)) done = true; } + + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function] if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) { SDL_Delay(10); @@ -531,6 +535,7 @@ int main(int, char**) } // Cleanup + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function] err = vkDeviceWaitIdle(g_Device); check_vk_result(err); ImGui_ImplVulkan_Shutdown(); From 324172fb1f096739e81c7f9f1f29939c5781e222 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 5 Mar 2025 13:35:14 +0100 Subject: [PATCH 518/548] Demo: (Refactor) Moved DemoWindowWidgets() below the functions it calls, reducing amount of forward declarations. --- imgui_demo.cpp | 126 ++++++++++++++++++++----------------------------- 1 file changed, 51 insertions(+), 75 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 31904b1b4754..775e0c731309 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -73,7 +73,6 @@ Index of this file: // [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos) // [SECTION] Demo Window / ShowDemoWindow() // [SECTION] DemoWindowMenuBar() -// [SECTION] DemoWindowWidgets() // [SECTION] DemoWindowWidgetsBasic() // [SECTION] DemoWindowWidgetsBullets() // [SECTION] DemoWindowWidgetsCollapsingHeaders() @@ -98,6 +97,7 @@ Index of this file: // [SECTION] DemoWindowWidgetsTooltips() // [SECTION] DemoWindowWidgetsTreeNodes() // [SECTION] DemoWindowWidgetsVerticalSliders() +// [SECTION] DemoWindowWidgets() // [SECTION] DemoWindowLayout() // [SECTION] DemoWindowPopups() // [SECTION] DemoWindowTables() @@ -250,30 +250,6 @@ static void ShowExampleMenuFile(); // (because the link time of very large functions tends to grow non-linearly) static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data); static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data); -static void DemoWindowWidgetsBasic(); -static void DemoWindowWidgetsBullets(); -static void DemoWindowWidgetsCollapsingHeaders(); -static void DemoWindowWidgetsComboBoxes(); -static void DemoWindowWidgetsColorAndPickers(); -static void DemoWindowWidgetsDataTypes(); -static void DemoWindowWidgetsDisableBlocks(ImGuiDemoWindowData* demo_data); -static void DemoWindowWidgetsDragAndDrop(); -static void DemoWindowWidgetsDragsAndSliders(); -static void DemoWindowWidgetsImages(); -static void DemoWindowWidgetsListBoxes(); -static void DemoWindowWidgetsPlotting(); -static void DemoWindowWidgetsMultiComponents(); -static void DemoWindowWidgetsProgressBars(); -static void DemoWindowWidgetsQueryingStatuses(); -static void DemoWindowWidgetsSelectables(); -static void DemoWindowWidgetsSelectionAndMultiSelect(ImGuiDemoWindowData* demo_data); -static void DemoWindowWidgetsTabs(); -static void DemoWindowWidgetsText(); -static void DemoWindowWidgetsTextFilter(); -static void DemoWindowWidgetsTextInput(); -static void DemoWindowWidgetsTooltips(); -static void DemoWindowWidgetsTreeNodes(); -static void DemoWindowWidgetsVerticalSliders(); static void DemoWindowLayout(); static void DemoWindowPopups(); static void DemoWindowTables(); @@ -816,56 +792,6 @@ static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data) } } -//----------------------------------------------------------------------------- -// [SECTION] DemoWindowWidgets() -//----------------------------------------------------------------------------- - -static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) -{ - IMGUI_DEMO_MARKER("Widgets"); - //ImGui::SetNextItemOpen(true, ImGuiCond_Once); - if (!ImGui::CollapsingHeader("Widgets")) - return; - - const bool disable_all = demo_data->DisableSections; // The Checkbox for that is inside the "Disabled" section at the bottom - if (disable_all) - ImGui::BeginDisabled(); - - DemoWindowWidgetsBasic(); - DemoWindowWidgetsBullets(); - DemoWindowWidgetsCollapsingHeaders(); - DemoWindowWidgetsComboBoxes(); - DemoWindowWidgetsColorAndPickers(); - DemoWindowWidgetsDataTypes(); - - if (disable_all) - ImGui::EndDisabled(); - DemoWindowWidgetsDisableBlocks(demo_data); - if (disable_all) - ImGui::BeginDisabled(); - - DemoWindowWidgetsDragAndDrop(); - DemoWindowWidgetsDragsAndSliders(); - DemoWindowWidgetsImages(); - DemoWindowWidgetsListBoxes(); - DemoWindowWidgetsMultiComponents(); - DemoWindowWidgetsPlotting(); - DemoWindowWidgetsProgressBars(); - DemoWindowWidgetsQueryingStatuses(); - DemoWindowWidgetsSelectables(); - DemoWindowWidgetsSelectionAndMultiSelect(demo_data); - DemoWindowWidgetsTabs(); - DemoWindowWidgetsText(); - DemoWindowWidgetsTextFilter(); - DemoWindowWidgetsTextInput(); - DemoWindowWidgetsTooltips(); - DemoWindowWidgetsTreeNodes(); - DemoWindowWidgetsVerticalSliders(); - - if (disable_all) - ImGui::EndDisabled(); -} - //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsBasic() //----------------------------------------------------------------------------- @@ -4183,6 +4109,56 @@ static void DemoWindowWidgetsVerticalSliders() } } +//----------------------------------------------------------------------------- +// [SECTION] DemoWindowWidgets() +//----------------------------------------------------------------------------- + +static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data) +{ + IMGUI_DEMO_MARKER("Widgets"); + //ImGui::SetNextItemOpen(true, ImGuiCond_Once); + if (!ImGui::CollapsingHeader("Widgets")) + return; + + const bool disable_all = demo_data->DisableSections; // The Checkbox for that is inside the "Disabled" section at the bottom + if (disable_all) + ImGui::BeginDisabled(); + + DemoWindowWidgetsBasic(); + DemoWindowWidgetsBullets(); + DemoWindowWidgetsCollapsingHeaders(); + DemoWindowWidgetsComboBoxes(); + DemoWindowWidgetsColorAndPickers(); + DemoWindowWidgetsDataTypes(); + + if (disable_all) + ImGui::EndDisabled(); + DemoWindowWidgetsDisableBlocks(demo_data); + if (disable_all) + ImGui::BeginDisabled(); + + DemoWindowWidgetsDragAndDrop(); + DemoWindowWidgetsDragsAndSliders(); + DemoWindowWidgetsImages(); + DemoWindowWidgetsListBoxes(); + DemoWindowWidgetsMultiComponents(); + DemoWindowWidgetsPlotting(); + DemoWindowWidgetsProgressBars(); + DemoWindowWidgetsQueryingStatuses(); + DemoWindowWidgetsSelectables(); + DemoWindowWidgetsSelectionAndMultiSelect(demo_data); + DemoWindowWidgetsTabs(); + DemoWindowWidgetsText(); + DemoWindowWidgetsTextFilter(); + DemoWindowWidgetsTextInput(); + DemoWindowWidgetsTooltips(); + DemoWindowWidgetsTreeNodes(); + DemoWindowWidgetsVerticalSliders(); + + if (disable_all) + ImGui::EndDisabled(); +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowLayout() //----------------------------------------------------------------------------- From fcec08f7ae32656a00e5dde709ff390870a7a84b Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 5 Mar 2025 13:39:48 +0100 Subject: [PATCH 519/548] Demo: (Refactor) Moved ExampleTreeNode contents below ShowDemoWindow() so main entry point is more visible to casual reader. --- imgui_demo.cpp | 189 +++++++++++++++++++++++++------------------------ 1 file changed, 97 insertions(+), 92 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 775e0c731309..beffe618db0f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -70,9 +70,9 @@ Index of this file: // [SECTION] Forward Declarations // [SECTION] Helpers -// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos) // [SECTION] Demo Window / ShowDemoWindow() // [SECTION] DemoWindowMenuBar() +// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos) // [SECTION] DemoWindowWidgetsBasic() // [SECTION] DemoWindowWidgetsBullets() // [SECTION] DemoWindowWidgetsCollapsingHeaders() @@ -256,6 +256,11 @@ static void DemoWindowTables(); static void DemoWindowColumns(); static void DemoWindowInputs(); +// Helper tree functions used by Property Editor & Multi-Select demos +struct ExampleTreeNode; +static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, ExampleTreeNode* parent); +static void ExampleTree_DestroyNode(ExampleTreeNode* node); + //----------------------------------------------------------------------------- // [SECTION] Helpers //----------------------------------------------------------------------------- @@ -282,97 +287,6 @@ ImGuiDemoMarkerCallback GImGuiDemoMarkerCallback = NULL; void* GImGuiDemoMarkerCallbackUserData = NULL; #define IMGUI_DEMO_MARKER(section) do { if (GImGuiDemoMarkerCallback != NULL) GImGuiDemoMarkerCallback(__FILE__, __LINE__, section, GImGuiDemoMarkerCallbackUserData); } while (0) -//----------------------------------------------------------------------------- -// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor etc.) -//----------------------------------------------------------------------------- - -// Simple representation for a tree -// (this is designed to be simple to understand for our demos, not to be fancy or efficient etc.) -struct ExampleTreeNode -{ - // Tree structure - char Name[28] = ""; - int UID = 0; - ExampleTreeNode* Parent = NULL; - ImVector Childs; - unsigned short IndexInParent = 0; // Maintaining this allows us to implement linear traversal more easily - - // Leaf Data - bool HasData = false; // All leaves have data - bool DataMyBool = true; - int DataMyInt = 128; - ImVec2 DataMyVec2 = ImVec2(0.0f, 3.141592f); -}; - -// Simple representation of struct metadata/serialization data. -// (this is a minimal version of what a typical advanced application may provide) -struct ExampleMemberInfo -{ - const char* Name; // Member name - ImGuiDataType DataType; // Member type - int DataCount; // Member count (1 when scalar) - int Offset; // Offset inside parent structure -}; - -// Metadata description of ExampleTreeNode struct. -static const ExampleMemberInfo ExampleTreeNodeMemberInfos[] -{ - { "MyName", ImGuiDataType_String, 1, offsetof(ExampleTreeNode, Name) }, - { "MyBool", ImGuiDataType_Bool, 1, offsetof(ExampleTreeNode, DataMyBool) }, - { "MyInt", ImGuiDataType_S32, 1, offsetof(ExampleTreeNode, DataMyInt) }, - { "MyVec2", ImGuiDataType_Float, 2, offsetof(ExampleTreeNode, DataMyVec2) }, -}; - -static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, ExampleTreeNode* parent) -{ - ExampleTreeNode* node = IM_NEW(ExampleTreeNode); - snprintf(node->Name, IM_ARRAYSIZE(node->Name), "%s", name); - node->UID = uid; - node->Parent = parent; - node->IndexInParent = parent ? (unsigned short)parent->Childs.Size : 0; - if (parent) - parent->Childs.push_back(node); - return node; -} - -static void ExampleTree_DestroyNode(ExampleTreeNode* node) -{ - for (ExampleTreeNode* child_node : node->Childs) - ExampleTree_DestroyNode(child_node); - IM_DELETE(node); -} - -// Create example tree data -// (this allocates _many_ more times than most other code in either Dear ImGui or others demo) -static ExampleTreeNode* ExampleTree_CreateDemoTree() -{ - static const char* root_names[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pear", "Pineapple", "Strawberry", "Watermelon" }; - const size_t NAME_MAX_LEN = sizeof(ExampleTreeNode::Name); - char name_buf[NAME_MAX_LEN]; - int uid = 0; - ExampleTreeNode* node_L0 = ExampleTree_CreateNode("", ++uid, NULL); - const int root_items_multiplier = 2; - for (int idx_L0 = 0; idx_L0 < IM_ARRAYSIZE(root_names) * root_items_multiplier; idx_L0++) - { - snprintf(name_buf, IM_ARRAYSIZE(name_buf), "%s %d", root_names[idx_L0 / root_items_multiplier], idx_L0 % root_items_multiplier); - ExampleTreeNode* node_L1 = ExampleTree_CreateNode(name_buf, ++uid, node_L0); - const int number_of_childs = (int)strlen(node_L1->Name); - for (int idx_L1 = 0; idx_L1 < number_of_childs; idx_L1++) - { - snprintf(name_buf, IM_ARRAYSIZE(name_buf), "Child %d", idx_L1); - ExampleTreeNode* node_L2 = ExampleTree_CreateNode(name_buf, ++uid, node_L1); - node_L2->HasData = true; - if (idx_L1 == 0) - { - snprintf(name_buf, IM_ARRAYSIZE(name_buf), "Sub-child %d", 0); - ExampleTreeNode* node_L3 = ExampleTree_CreateNode(name_buf, ++uid, node_L2); - node_L3->HasData = true; - } - } - } - return node_L0; -} - //----------------------------------------------------------------------------- // [SECTION] Demo Window / ShowDemoWindow() //----------------------------------------------------------------------------- @@ -792,6 +706,97 @@ static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data) } } +//----------------------------------------------------------------------------- +// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos) +//----------------------------------------------------------------------------- + +// Simple representation for a tree +// (this is designed to be simple to understand for our demos, not to be fancy or efficient etc.) +struct ExampleTreeNode +{ + // Tree structure + char Name[28] = ""; + int UID = 0; + ExampleTreeNode* Parent = NULL; + ImVector Childs; + unsigned short IndexInParent = 0; // Maintaining this allows us to implement linear traversal more easily + + // Leaf Data + bool HasData = false; // All leaves have data + bool DataMyBool = true; + int DataMyInt = 128; + ImVec2 DataMyVec2 = ImVec2(0.0f, 3.141592f); +}; + +// Simple representation of struct metadata/serialization data. +// (this is a minimal version of what a typical advanced application may provide) +struct ExampleMemberInfo +{ + const char* Name; // Member name + ImGuiDataType DataType; // Member type + int DataCount; // Member count (1 when scalar) + int Offset; // Offset inside parent structure +}; + +// Metadata description of ExampleTreeNode struct. +static const ExampleMemberInfo ExampleTreeNodeMemberInfos[] +{ + { "MyName", ImGuiDataType_String, 1, offsetof(ExampleTreeNode, Name) }, + { "MyBool", ImGuiDataType_Bool, 1, offsetof(ExampleTreeNode, DataMyBool) }, + { "MyInt", ImGuiDataType_S32, 1, offsetof(ExampleTreeNode, DataMyInt) }, + { "MyVec2", ImGuiDataType_Float, 2, offsetof(ExampleTreeNode, DataMyVec2) }, +}; + +static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, ExampleTreeNode* parent) +{ + ExampleTreeNode* node = IM_NEW(ExampleTreeNode); + snprintf(node->Name, IM_ARRAYSIZE(node->Name), "%s", name); + node->UID = uid; + node->Parent = parent; + node->IndexInParent = parent ? (unsigned short)parent->Childs.Size : 0; + if (parent) + parent->Childs.push_back(node); + return node; +} + +static void ExampleTree_DestroyNode(ExampleTreeNode* node) +{ + for (ExampleTreeNode* child_node : node->Childs) + ExampleTree_DestroyNode(child_node); + IM_DELETE(node); +} + +// Create example tree data +// (this allocates _many_ more times than most other code in either Dear ImGui or others demo) +static ExampleTreeNode* ExampleTree_CreateDemoTree() +{ + static const char* root_names[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pear", "Pineapple", "Strawberry", "Watermelon" }; + const size_t NAME_MAX_LEN = sizeof(ExampleTreeNode::Name); + char name_buf[NAME_MAX_LEN]; + int uid = 0; + ExampleTreeNode* node_L0 = ExampleTree_CreateNode("", ++uid, NULL); + const int root_items_multiplier = 2; + for (int idx_L0 = 0; idx_L0 < IM_ARRAYSIZE(root_names) * root_items_multiplier; idx_L0++) + { + snprintf(name_buf, IM_ARRAYSIZE(name_buf), "%s %d", root_names[idx_L0 / root_items_multiplier], idx_L0 % root_items_multiplier); + ExampleTreeNode* node_L1 = ExampleTree_CreateNode(name_buf, ++uid, node_L0); + const int number_of_childs = (int)strlen(node_L1->Name); + for (int idx_L1 = 0; idx_L1 < number_of_childs; idx_L1++) + { + snprintf(name_buf, IM_ARRAYSIZE(name_buf), "Child %d", idx_L1); + ExampleTreeNode* node_L2 = ExampleTree_CreateNode(name_buf, ++uid, node_L1); + node_L2->HasData = true; + if (idx_L1 == 0) + { + snprintf(name_buf, IM_ARRAYSIZE(name_buf), "Sub-child %d", 0); + ExampleTreeNode* node_L3 = ExampleTree_CreateNode(name_buf, ++uid, node_L2); + node_L3->HasData = true; + } + } + } + return node_L0; +} + //----------------------------------------------------------------------------- // [SECTION] DemoWindowWidgetsBasic() //----------------------------------------------------------------------------- From 119dfbc6270cedf29e8655b296f9ca0f31cede32 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 5 Mar 2025 15:04:26 +0100 Subject: [PATCH 520/548] Debug Tools: Tweaked layout of ID Stack Tool and always display full path. (#4631) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 50 ++++++++++++++++++++++++---------------------- imgui.h | 3 ++- imgui_internal.h | 1 + 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 78c6f09da0f7..a6110cd55197 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -110,6 +110,7 @@ Other changes: One case where it would manifest was calling Combo() with an out of range index. (#8450) - Debug Tools: Added io.ConfigDebugHighlightIdConflictsShowItemPicker (defaults to true) to allow disabled Item Picker suggestion in user facing builds. (#7961, #7669) +- Debug Tools: Tweaked layout of ID Stack Tool and always display full path. (#4631) - Misc: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursors (busy/wait/hourglass shape, with or without an arrow cursor). - Demo: Reorganized "Widgets" section to be alphabetically ordered and split in more functions. diff --git a/imgui.cpp b/imgui.cpp index bae74db5f2c1..8963309133d9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16924,42 +16924,44 @@ void ImGui::ShowIDStackToolWindow(bool* p_open) // Display hovered/active status ImGuiIDStackTool* tool = &g.DebugIDStackTool; - const ImGuiID hovered_id = g.HoveredIdPreviousFrame; - const ImGuiID active_id = g.ActiveId; -#ifdef IMGUI_ENABLE_TEST_ENGINE - Text("HoveredId: 0x%08X (\"%s\"), ActiveId: 0x%08X (\"%s\")", hovered_id, hovered_id ? ImGuiTestEngine_FindItemDebugLabel(&g, hovered_id) : "", active_id, active_id ? ImGuiTestEngine_FindItemDebugLabel(&g, active_id) : ""); -#else - Text("HoveredId: 0x%08X, ActiveId: 0x%08X", hovered_id, active_id); -#endif + + // Build and display path + tool->ResultPathBuf.resize(0); + for (int stack_n = 0; stack_n < tool->Results.Size; stack_n++) + { + char level_desc[256]; + StackToolFormatLevelInfo(tool, stack_n, false, level_desc, IM_ARRAYSIZE(level_desc)); + tool->ResultPathBuf.append(stack_n == 0 ? "//" : "/"); + for (int n = 0; level_desc[n]; n++) + { + if (level_desc[n] == '/') + tool->ResultPathBuf.append("\\"); + tool->ResultPathBuf.append(level_desc + n, level_desc + n + 1); + } + } + Text("0x%08X", tool->QueryId); SameLine(); MetricsHelpMarker("Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details."); // CTRL+C to copy path const float time_since_copy = (float)g.Time - tool->CopyToClipboardLastTime; - Checkbox("Ctrl+C: copy path to clipboard", &tool->CopyToClipboardOnCtrlC); + SameLine(); + PushStyleVarY(ImGuiStyleVar_FramePadding, 0.0f); Checkbox("Ctrl+C: copy path", &tool->CopyToClipboardOnCtrlC); PopStyleVar(); SameLine(); TextColored((time_since_copy >= 0.0f && time_since_copy < 0.75f && ImFmod(time_since_copy, 0.25f) < 0.25f * 0.5f) ? ImVec4(1.f, 1.f, 0.3f, 1.f) : ImVec4(), "*COPIED*"); if (tool->CopyToClipboardOnCtrlC && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused)) { tool->CopyToClipboardLastTime = (float)g.Time; - char* p = g.TempBuffer.Data; - char* p_end = p + g.TempBuffer.Size; - for (int stack_n = 0; stack_n < tool->Results.Size && p + 3 < p_end; stack_n++) - { - *p++ = '/'; - char level_desc[256]; - StackToolFormatLevelInfo(tool, stack_n, false, level_desc, IM_ARRAYSIZE(level_desc)); - for (int n = 0; level_desc[n] && p + 2 < p_end; n++) - { - if (level_desc[n] == '/') - *p++ = '\\'; - *p++ = level_desc[n]; - } - } - *p = '\0'; - SetClipboardText(g.TempBuffer.Data); + SetClipboardText(tool->ResultPathBuf.c_str()); } + Text("- Path \"%s\"", tool->ResultPathBuf.c_str()); +#ifdef IMGUI_ENABLE_TEST_ENGINE + Text("- Label \"%s\"", tool->QueryId ? ImGuiTestEngine_FindItemDebugLabel(&g, tool->QueryId) : ""); +#endif + + Separator(); + // Display decorated stack tool->LastActiveFrame = g.FrameCount; if (tool->Results.Size > 0 && BeginTable("##table", 3, ImGuiTableFlags_Borders)) diff --git a/imgui.h b/imgui.h index 1cda94914594..2e6a67b336c3 100644 --- a/imgui.h +++ b/imgui.h @@ -2600,10 +2600,11 @@ struct ImGuiTextBuffer ImGuiTextBuffer() { } inline char operator[](int i) const { IM_ASSERT(Buf.Data != NULL); return Buf.Data[i]; } const char* begin() const { return Buf.Data ? &Buf.front() : EmptyString; } - const char* end() const { return Buf.Data ? &Buf.back() : EmptyString; } // Buf is zero-terminated, so end() will point on the zero-terminator + const char* end() const { return Buf.Data ? &Buf.back() : EmptyString; } // Buf is zero-terminated, so end() will point on the zero-terminator int size() const { return Buf.Size ? Buf.Size - 1 : 0; } bool empty() const { return Buf.Size <= 1; } void clear() { Buf.clear(); } + void resize(int size) { IM_ASSERT(size == 0); if (Buf.Size > 0) Buf.Data[0] = 0; Buf.resize(0); } // Similar to resize(0) on ImVector: empty string but don't free buffer. Only resize(0) supported for now. void reserve(int capacity) { Buf.reserve(capacity); } const char* c_str() const { return Buf.Data ? Buf.Data : EmptyString; } IMGUI_API void append(const char* str, const char* str_end = NULL); diff --git a/imgui_internal.h b/imgui_internal.h index 40b854559c2c..455a9e0664d3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2030,6 +2030,7 @@ struct ImGuiIDStackTool ImVector Results; bool CopyToClipboardOnCtrlC; float CopyToClipboardLastTime; + ImGuiTextBuffer ResultPathBuf; ImGuiIDStackTool() { memset(this, 0, sizeof(*this)); CopyToClipboardLastTime = -FLT_MAX; } }; From 9f49292b357bacdf23f7131d0fa735672912f50e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 5 Mar 2025 15:23:49 +0100 Subject: [PATCH 521/548] Internals: Menus: reworked mangling of menu windows to use "###Menu_00" etc. instead of "##Menu_00". --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 30 ++++++++++++++++++++++++------ imgui.h | 2 +- imgui_internal.h | 1 + imgui_widgets.cpp | 4 ++-- 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a6110cd55197..39d73571d3d3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -62,6 +62,9 @@ Breaking changes: - Backends: Vulkan: Added 'uint32_t api_version' argument to ImGui_ImplVulkan_LoadFunctions(). Note that it was also added to ImGui_ImplVulkan_InitInfo but for the later it is optional. (#8326, #8365, #8400) +- Internals: Menus: reworked mangling of menu windows to use "###Menu_00" etc. instead + of "##Menu_00", allowing them to also store the menu name before it. This shouldn't + affect code unless directly accessing menu window from their mangled name. Other changes: diff --git a/imgui.cpp b/imgui.cpp index 8963309133d9..b2738f1701dd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -431,6 +431,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. + - 2025/03/05 (1.91.9) - BeginMenu(): Internals: reworked mangling of menu windows to use "###Menu_00" etc. instead of "##Menu_00", allowing them to also store the menu name before it. This shouldn't affect code unless directly accessing menu window from their mangled name. - 2025/02/27 (1.91.9) - Image(): removed 'tint_col' and 'border_col' parameter from Image() function. Added ImageWithBg() replacement. (#8131, #8238) - old: void Image (ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1), ImVec4 tint_col = (1,1,1,1), ImVec4 border_col = (0,0,0,0)); - new: void Image (ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1)); @@ -7202,7 +7203,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Update stored window name when it changes (which can _only_ happen with the "###" operator, so the ID would stay unchanged). // The title bar always display the 'name' parameter, so we only update the string storage if it needs to be visible to the end-user elsewhere. bool window_title_visible_elsewhere = false; - if (g.NavWindowingListWindow != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB + if (g.NavWindowingListWindow != NULL && (flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB + window_title_visible_elsewhere = true; + if (flags & ImGuiWindowFlags_ChildMenu) window_title_visible_elsewhere = true; if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0) { @@ -11714,17 +11717,32 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags) } char name[20]; - if (extra_window_flags & ImGuiWindowFlags_ChildMenu) - ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginMenuDepth); // Recycle windows based on depth - else - ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame + IM_ASSERT((extra_window_flags & ImGuiWindowFlags_ChildMenu) == 0); // Use BeginPopupMenuEx() + ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // No recycling, so we can close/open during the same frame bool is_open = Begin(name, NULL, extra_window_flags | ImGuiWindowFlags_Popup); if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) EndPopup(); - //g.CurrentWindow->FocusRouteParentWindow = g.CurrentWindow->ParentWindowInBeginStack; + return is_open; +} +bool ImGui::BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags extra_window_flags) +{ + ImGuiContext& g = *GImGui; + if (!IsPopupOpen(id, ImGuiPopupFlags_None)) + { + g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values + return false; + } + + char name[128]; + IM_ASSERT(extra_window_flags & ImGuiWindowFlags_ChildMenu); + ImFormatString(name, IM_ARRAYSIZE(name), "%s###Menu_%02d", label, g.BeginMenuDepth); // Recycle windows based on depth + bool is_open = Begin(name, NULL, extra_window_flags | ImGuiWindowFlags_Popup); + if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) + EndPopup(); + //g.CurrentWindow->FocusRouteParentWindow = g.CurrentWindow->ParentWindowInBeginStack; return is_open; } diff --git a/imgui.h b/imgui.h index 2e6a67b336c3..f154efcb9b5f 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.9 WIP" -#define IMGUI_VERSION_NUM 19186 +#define IMGUI_VERSION_NUM 19187 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 455a9e0664d3..a78ae9827c42 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3136,6 +3136,7 @@ namespace ImGui // Popups, Modals IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags); + IMGUI_API bool BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags extra_window_flags); IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None); IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 76dabb8f9c55..b8b872b1ac8b 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8867,7 +8867,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) if (g.MenusIdSubmittedThisFrame.contains(id)) { if (menu_is_open) - menu_is_open = BeginPopupEx(id, window_flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) + menu_is_open = BeginPopupMenuEx(id, label, window_flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) else g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values return menu_is_open; @@ -9029,7 +9029,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) ImGuiLastItemData last_item_in_parent = g.LastItemData; SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: misleading: the value will serve as reference for FindBestWindowPosForPopup(), not actual pos. PushStyleVar(ImGuiStyleVar_ChildRounding, style.PopupRounding); // First level will use _PopupRounding, subsequent will use _ChildRounding - menu_is_open = BeginPopupEx(id, window_flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) + menu_is_open = BeginPopupMenuEx(id, label, window_flags); // menu_is_open may be 'false' when the popup is completely clipped (e.g. zero size display) PopStyleVar(); if (menu_is_open) { From 377a387a427f152d63596de66bbaa590234a2b1c Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 5 Mar 2025 16:23:31 +0100 Subject: [PATCH 522/548] Add proper ImGuiTextBuffer::resize() support other than 0. --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index f154efcb9b5f..2f6a18d2aa1a 100644 --- a/imgui.h +++ b/imgui.h @@ -2604,7 +2604,7 @@ struct ImGuiTextBuffer int size() const { return Buf.Size ? Buf.Size - 1 : 0; } bool empty() const { return Buf.Size <= 1; } void clear() { Buf.clear(); } - void resize(int size) { IM_ASSERT(size == 0); if (Buf.Size > 0) Buf.Data[0] = 0; Buf.resize(0); } // Similar to resize(0) on ImVector: empty string but don't free buffer. Only resize(0) supported for now. + void resize(int size) { if (Buf.Size > size) Buf.Data[size] = 0; Buf.resize(size ? size + 1 : 0, 0); } // Similar to resize(0) on ImVector: empty string but don't free buffer. void reserve(int capacity) { Buf.reserve(capacity); } const char* c_str() const { return Buf.Data ? Buf.Data : EmptyString; } IMGUI_API void append(const char* str, const char* str_end = NULL); From 1ec99f4fd3a49bcd5479b4ab1a5fd52ce5195c02 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 7 Mar 2025 11:09:02 +0100 Subject: [PATCH 523/548] Internals: added ImStrlen/ImMemchr #define to facilitate experimenting with variations. (#8421) --- imgui.cpp | 50 +++++++++++++++++++++++------------------------ imgui_draw.cpp | 13 ++++++------ imgui_internal.h | 2 ++ imgui_tables.cpp | 2 +- imgui_widgets.cpp | 42 +++++++++++++++++++-------------------- 5 files changed, 56 insertions(+), 53 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b2738f1701dd..cac29a932747 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1986,15 +1986,15 @@ void ImStrncpy(char* dst, const char* src, size_t count) char* ImStrdup(const char* str) { - size_t len = strlen(str); + size_t len = ImStrlen(str); void* buf = IM_ALLOC(len + 1); return (char*)memcpy(buf, (const void*)str, len + 1); } char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src) { - size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1; - size_t src_size = strlen(src) + 1; + size_t dst_buf_size = p_dst_size ? *p_dst_size : ImStrlen(dst) + 1; + size_t src_size = ImStrlen(src) + 1; if (dst_buf_size < src_size) { IM_FREE(dst); @@ -2007,7 +2007,7 @@ char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src) const char* ImStrchrRange(const char* str, const char* str_end, char c) { - const char* p = (const char*)memchr(str, (int)c, str_end - str); + const char* p = (const char*)ImMemchr(str, (int)c, str_end - str); return p; } @@ -2022,13 +2022,13 @@ int ImStrlenW(const ImWchar* str) // Find end-of-line. Return pointer will point to either first \n, either str_end. const char* ImStreolRange(const char* str, const char* str_end) { - const char* p = (const char*)memchr(str, '\n', str_end - str); + const char* p = (const char*)ImMemchr(str, '\n', str_end - str); return p ? p : str_end; } const char* ImStrbol(const char* buf_mid_line, const char* buf_begin) // find beginning-of-line { - IM_ASSERT_PARANOID(buf_mid_line >= buf_begin && buf_mid_line <= buf_begin + strlen(buf_begin)); + IM_ASSERT_PARANOID(buf_mid_line >= buf_begin && buf_mid_line <= buf_begin + ImStrlen(buf_begin)); while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n') buf_mid_line--; return buf_mid_line; @@ -2037,7 +2037,7 @@ const char* ImStrbol(const char* buf_mid_line, const char* buf_begin) // find be const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end) { if (!needle_end) - needle_end = needle + strlen(needle); + needle_end = needle + ImStrlen(needle); const char un0 = (char)ImToUpper(*needle); while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end)) @@ -2158,7 +2158,7 @@ void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, if (buf == NULL) buf = "(null)"; *out_buf = buf; - if (out_buf_end) { *out_buf_end = buf + strlen(buf); } + if (out_buf_end) { *out_buf_end = buf + ImStrlen(buf); } } else if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '*' && fmt[3] == 's' && fmt[4] == 0) { @@ -2567,11 +2567,11 @@ const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const cha int ImTextCountLines(const char* in_text, const char* in_text_end) { if (in_text_end == NULL) - in_text_end = in_text + strlen(in_text); // FIXME-OPT: Not optimal approach, discourage use for now. + in_text_end = in_text + ImStrlen(in_text); // FIXME-OPT: Not optimal approach, discourage use for now. int count = 0; while (in_text < in_text_end) { - const char* line_end = (const char*)memchr(in_text, '\n', in_text_end - in_text); + const char* line_end = (const char*)ImMemchr(in_text, '\n', in_text_end - in_text); in_text = line_end ? line_end + 1 : in_text_end; count++; } @@ -2852,7 +2852,7 @@ void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector 0) || (data == NULL && data_size == 0)); IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once); IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource() @@ -14378,7 +14378,7 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* } if (prefix) - LogRenderedText(ref_pos, prefix, prefix + strlen(prefix)); // Calculate end ourself to ensure "##" are included here. + LogRenderedText(ref_pos, prefix, prefix + ImStrlen(prefix)); // Calculate end ourself to ensure "##" are included here. // Re-adjust padding if we have popped out of our starting depth if (g.LogDepthRef > window->DC.TreeDepth) @@ -14411,7 +14411,7 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* } if (suffix) - LogRenderedText(ref_pos, suffix, suffix + strlen(suffix)); + LogRenderedText(ref_pos, suffix, suffix + ImStrlen(suffix)); } // Start logging/capturing text output @@ -14677,7 +14677,7 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter). // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy.. if (ini_size == 0) - ini_size = strlen(ini_data); + ini_size = ImStrlen(ini_data); g.SettingsIniData.Buf.resize((int)ini_size + 1); char* const buf = g.SettingsIniData.Buf.Data; char* const buf_end = buf + ini_size; @@ -14778,7 +14778,7 @@ ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name) if (const char* p = strstr(name, "###")) name = p; } - const size_t name_len = strlen(name); + const size_t name_len = ImStrlen(name); // Allocate chunk const size_t chunk_size = sizeof(ImGuiWindowSettings) + name_len + 1; @@ -15070,7 +15070,7 @@ static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext*, const char* t if (!main_clipboard) PasteboardCreate(kPasteboardClipboard, &main_clipboard); PasteboardClear(main_clipboard); - CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (const UInt8*)text, strlen(text)); + CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (const UInt8*)text, ImStrlen(text)); if (cf_data) { PasteboardPutItemFlavor(main_clipboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), cf_data, 0); @@ -15124,7 +15124,7 @@ static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const cha { ImGuiContext& g = *ctx; g.ClipboardHandlerData.clear(); - const char* text_end = text + strlen(text); + const char* text_end = text + ImStrlen(text); g.ClipboardHandlerData.resize((int)(text_end - text) + 1); memcpy(&g.ClipboardHandlerData[0], text, (size_t)(text_end - text)); g.ClipboardHandlerData[(int)(text_end - text)] = 0; @@ -16894,7 +16894,7 @@ void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* dat ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "%d", (int)(intptr_t)data_id); break; case ImGuiDataType_String: - ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "%.*s", data_id_end ? (int)((const char*)data_id_end - (const char*)data_id) : (int)strlen((const char*)data_id), (const char*)data_id); + ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "%.*s", data_id_end ? (int)((const char*)data_id_end - (const char*)data_id) : (int)ImStrlen((const char*)data_id), (const char*)data_id); break; case ImGuiDataType_Pointer: ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "(void*)0x%p", data_id); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 206c29ce5a06..efdddc8b1857 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -143,6 +143,7 @@ namespace IMGUI_STB_NAMESPACE #define STBTT_fabs(x) ImFabs(x) #define STBTT_ifloor(x) ((int)ImFloor(x)) #define STBTT_iceil(x) ((int)ImCeil(x)) +#define STBTT_strlen(x) ImStrlen(x) #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION #else @@ -2672,7 +2673,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, { // Store a short copy of filename into into the font name for convenience const char* p; - for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {} + for (p = filename + ImStrlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {} ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels); } return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges); @@ -2707,7 +2708,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_d ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges) { - int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4; + int compressed_ttf_size = (((int)ImStrlen(compressed_ttf_data_base85) + 4) / 5) * 4; void* compressed_ttf = IM_ALLOC((size_t)compressed_ttf_size); Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf); ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges); @@ -4029,7 +4030,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) { if (!text_end) - text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this. + text_end = text_begin + ImStrlen(text_begin); // FIXME-OPT: Need to avoid this. const float line_height = size; const float scale = size / FontSize; @@ -4129,7 +4130,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im return; if (!text_end) - text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. + text_end = text_begin + ImStrlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. const float scale = size / FontSize; const float line_height = FontSize * scale; @@ -4141,7 +4142,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im if (y + line_height < clip_rect.y) while (y + line_height < clip_rect.y && s < text_end) { - const char* line_end = (const char*)memchr(s, '\n', text_end - s); + const char* line_end = (const char*)ImMemchr(s, '\n', text_end - s); if (word_wrap_enabled) { // FIXME-OPT: This is not optimal as do first do a search for \n before calling CalcWordWrapPositionA(). @@ -4165,7 +4166,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im float y_end = y; while (y_end < clip_rect.w && s_end < text_end) { - s_end = (const char*)memchr(s_end, '\n', text_end - s_end); + s_end = (const char*)ImMemchr(s_end, '\n', text_end - s_end); s_end = s_end ? s_end + 1 : text_end; y_end += line_height; } diff --git a/imgui_internal.h b/imgui_internal.h index a78ae9827c42..b7395fcae087 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -372,6 +372,8 @@ static inline bool ImIsPowerOfTwo(ImU64 v) { return v != 0 && (v & static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } // Helpers: String +#define ImStrlen strlen +#define ImMemchr memchr IMGUI_API int ImStricmp(const char* str1, const char* str2); // Case insensitive compare. IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); // Case insensitive compare to a certain count. IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); // Copy to a certain count and always zero terminate (strncpy doesn't). diff --git a/imgui_tables.cpp b/imgui_tables.cpp index f6aff8c026fb..6c79262363f2 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1648,7 +1648,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo if (label != NULL && label[0] != 0) { column->NameOffset = (ImS16)table->ColumnsNames.size(); - table->ColumnsNames.append(label, label + strlen(label) + 1); + table->ColumnsNames.append(label, label + ImStrlen(label) + 1); } } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index b8b872b1ac8b..01e4e61872c9 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -169,7 +169,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) // Calculate length const char* text_begin = text; if (text_end == NULL) - text_end = text + strlen(text); // FIXME-OPT + text_end = text + ImStrlen(text); // FIXME-OPT const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); const float wrap_pos_x = window->DC.TextWrapPos; @@ -209,7 +209,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) int lines_skipped = 0; while (line < text_end && lines_skipped < lines_skippable) { - const char* line_end = (const char*)memchr(line, '\n', text_end - line); + const char* line_end = (const char*)ImMemchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0) @@ -230,7 +230,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) if (IsClippedEx(line_rect, 0)) break; - const char* line_end = (const char*)memchr(line, '\n', text_end - line); + const char* line_end = (const char*)ImMemchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); @@ -245,7 +245,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) int lines_skipped = 0; while (line < text_end) { - const char* line_end = (const char*)memchr(line, '\n', text_end - line); + const char* line_end = (const char*)ImMemchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0) @@ -2064,7 +2064,7 @@ static const char* Items_SingleStringGetter(void* data, int idx) { if (idx == items_count) break; - p += strlen(p) + 1; + p += ImStrlen(p) + 1; items_count++; } return *p ? p : NULL; @@ -2132,7 +2132,7 @@ bool ImGui::Combo(const char* label, int* current_item, const char* items_separa const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open while (*p) { - p += strlen(p) + 1; + p += ImStrlen(p) + 1; items_count++; } bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items); @@ -3899,7 +3899,7 @@ static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** line_count++; if (s_eol == NULL) { - s = s + strlen(s); + s = s + ImStrlen(s); break; } s = s_eol + 1; @@ -4187,7 +4187,7 @@ void ImGuiInputTextState::OnCharPressed(unsigned int c) // The changes we had to make to stb_textedit_key made it very much UTF-8 specific which is not too great. char utf8[5]; ImTextCharToUtf8(utf8, c); - stb_textedit_text(this, Stb, utf8, (int)strlen(utf8)); + stb_textedit_text(this, Stb, utf8, (int)ImStrlen(utf8)); CursorFollow = true; CursorAnimReset(); } @@ -4238,7 +4238,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons // Grow internal buffer if needed const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0; - const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text); + const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)ImStrlen(new_text); if (new_text_len + BufTextLen >= BufSize) { if (!is_resizable) @@ -4560,7 +4560,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const bool init_state = (init_make_active || user_scroll_active); if (init_reload_from_user_buf) { - int new_len = (int)strlen(buf); + int new_len = (int)ImStrlen(buf); IM_ASSERT(new_len + 1 <= buf_size && "Is your input buffer properly zero-terminated?"); state->WantReloadUserBuf = false; InputTextReconcileUndoState(state, state->TextA.Data, state->TextLen, buf, new_len); @@ -4582,7 +4582,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Take a copy of the initial buffer value. // From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode) - const int buf_len = (int)strlen(buf); + const int buf_len = (int)ImStrlen(buf); IM_ASSERT(buf_len + 1 <= buf_size && "Is your input buffer properly zero-terminated?"); state->TextToRevertTo.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string. memcpy(state->TextToRevertTo.Data, buf, buf_len + 1); @@ -4667,7 +4667,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Read-only mode always ever read from source buffer. Refresh TextLen when active. if (is_readonly && state != NULL) - state->TextLen = (int)strlen(buf); + state->TextLen = (int)ImStrlen(buf); //if (is_readonly && state != NULL) // state->TextA.clear(); // Uncomment to facilitate debugging, but we otherwise prefer to keep/amortize th allocation. } @@ -4946,7 +4946,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (const char* clipboard = GetClipboardText()) { // Filter pasted buffer - const int clipboard_len = (int)strlen(clipboard); + const int clipboard_len = (int)ImStrlen(clipboard); ImVector clipboard_filtered; clipboard_filtered.reserve(clipboard_len + 1); for (const char* s = clipboard; *s != 0; ) @@ -4958,7 +4958,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ continue; char c_utf8[5]; ImTextCharToUtf8(c_utf8, c); - int out_len = (int)strlen(c_utf8); + int out_len = (int)ImStrlen(c_utf8); clipboard_filtered.resize(clipboard_filtered.Size + out_len); memcpy(clipboard_filtered.Data + clipboard_filtered.Size - out_len, c_utf8, out_len); } @@ -5088,7 +5088,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (buf_dirty) { // Callback may update buffer and thus set buf_dirty even in read-only mode. - IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! + IM_ASSERT(callback_data.BufTextLen == (int)ImStrlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! InputTextReconcileUndoState(state, state->CallbackTextBackup.Data, state->CallbackTextBackup.Size - 1, callback_data.Buf, callback_data.BufTextLen); state->TextLen = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen() state->CursorAnimReset(); @@ -5187,7 +5187,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (is_displaying_hint) { buf_display = hint; - buf_display_end = hint + strlen(hint); + buf_display_end = hint + ImStrlen(hint); } // Render text. We currently only render selection when the widget is active or while scrolling. @@ -5220,7 +5220,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ int line_count = 1; if (is_multiline) { - for (const char* s = text_begin; (s = (const char*)memchr(s, '\n', (size_t)(text_end - s))) != NULL; s++) + for (const char* s = text_begin; (s = (const char*)ImMemchr(s, '\n', (size_t)(text_end - s))) != NULL; s++) { if (cursor_line_no == -1 && s >= cursor_ptr) { cursor_line_no = line_count; } if (selmin_line_no == -1 && s >= selmin_ptr) { selmin_line_no = line_count; } @@ -5298,7 +5298,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ break; if (rect_pos.y < clip_rect.y) { - p = (const char*)memchr((void*)p, '\n', text_selected_end - p); + p = (const char*)ImMemchr((void*)p, '\n', text_selected_end - p); p = p ? p + 1 : text_selected_end; } else @@ -5350,7 +5350,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ else if (!is_displaying_hint && g.ActiveId == id) buf_display_end = buf_display + state->TextLen; else if (!is_displaying_hint) - buf_display_end = buf_display + strlen(buf_display); + buf_display_end = buf_display + ImStrlen(buf_display); if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) { @@ -7184,7 +7184,7 @@ ImGuiTypingSelectRequest* ImGui::GetTypingSelectRequest(ImGuiTypingSelectFlags f // Append to buffer const int buffer_max_len = IM_ARRAYSIZE(data->SearchBuffer) - 1; - int buffer_len = (int)strlen(data->SearchBuffer); + int buffer_len = (int)ImStrlen(data->SearchBuffer); bool select_request = false; for (ImWchar w : g.IO.InputQueueCharacters) { @@ -10111,7 +10111,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, else { tab->NameOffset = (ImS32)tab_bar->TabsNames.size(); - tab_bar->TabsNames.append(label, label + strlen(label) + 1); + tab_bar->TabsNames.append(label, label + ImStrlen(label) + 1); } // Update selected tab From 806731e37a27dab2abae14cc26a970d37ef9cd7d Mon Sep 17 00:00:00 2001 From: TheMode Date: Sun, 9 Mar 2025 06:28:36 +0100 Subject: [PATCH 524/548] Set IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS on 3DS sdk (#8477, #8476) --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cac29a932747..73bd2581ece2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15138,11 +15138,13 @@ static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const cha #if defined(__APPLE__) && TARGET_OS_IPHONE #define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS #endif - -#if defined(_WIN32) && defined(IMGUI_DISABLE_WIN32_FUNCTIONS) +#if defined(__3DS__) #define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS #endif +#if defined(_WIN32) && defined(IMGUI_DISABLE_WIN32_FUNCTIONS) +#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS #endif +#endif // #ifndef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS #ifndef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS #ifdef _WIN32 From 3c3d943fb13c7ae2ddecbfe5f73252c4820f3a9f Mon Sep 17 00:00:00 2001 From: fdsa <14tanks999@gmail.com> Date: Sat, 8 Mar 2025 01:28:48 -0800 Subject: [PATCH 525/548] Docs: Fix some typos (#8473) --- backends/imgui_impl_opengl3.cpp | 2 +- backends/imgui_impl_osx.mm | 2 +- backends/imgui_impl_vulkan.cpp | 2 +- docs/CHANGELOG.txt | 138 ++++++++++++++++---------------- docs/FAQ.md | 4 +- docs/TODO.txt | 4 +- imgui.cpp | 10 +-- imgui.h | 2 +- imgui_demo.cpp | 6 +- imgui_internal.h | 6 +- imgui_tables.cpp | 4 +- imgui_widgets.cpp | 2 +- 12 files changed, 91 insertions(+), 91 deletions(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 1311d1bc9f0e..7d0b53621960 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -54,7 +54,7 @@ // 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state. // 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state. // 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x) -// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader. +// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre-3.3 context which have the defines set by a loader. // 2020-07-10: OpenGL: Added support for glad2 OpenGL loader. // 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX. // 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix. diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 4726462cbec5..2d72d413ebde 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -39,7 +39,7 @@ // 2024-07-02: Update for io.SetPlatformImeDataFn() -> io.PlatformSetImeDataFn() renaming in main library. // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F20 function keys. Stopped mapping F13 into PrintScreen. // 2023-04-09: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_Pen. -// 2023-02-01: Fixed scroll wheel scaling for devices emitting events with hasPreciseScrollingDeltas==false (e.g. non-Apple mices). +// 2023-02-01: Fixed scroll wheel scaling for devices emitting events with hasPreciseScrollingDeltas==false (e.g. non-Apple mice). // 2022-11-02: Fixed mouse coordinates before clicking the host window. // 2022-10-06: Fixed mouse inputs on flipped views. // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 7379e000b741..e67b74c01455 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -53,7 +53,7 @@ // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2022-10-04: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symmetry. (#914, #5738). // 2022-01-20: Vulkan: Added support for ImTextureID as VkDescriptorSet. User need to call ImGui_ImplVulkan_AddTexture(). Building for 32-bit targets requires '#define ImTextureID ImU64'. (#914). -// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame. +// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likelihood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame. // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize. // 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 39d73571d3d3..ca5ab47e386b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -101,7 +101,7 @@ Other changes: - Default for selected tabs: TabCloseButtonMinWidthSelected = -1.0f (always visible) - Default for unselected tabs: TabCloseButtonMinWidthUnselected = 0.0f (visible when hovered) - Tabs: fixed middle-mouse-button to close tab not checking that close button - is hovered, merely it's visibility. (#8399, #8387) [@nicovanbentum] + is hovered, merely its visibility. (#8399, #8387) [@nicovanbentum] - TextLink(), TextLinkOpenURL(): fixed honoring text baseline alignment. (#8451, #7660) [@achabense] - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to @@ -678,7 +678,7 @@ Other changes: by an extra pixel + rework the change so that contents doesn't overlap the bottom and right border in a scrolling table. (#6765, #3752, #7428) - Tables: fixed an issue resizing columns or querying hovered column/row when using multiple - synched instances that are layed out at different X positions. (#7933) + synced instances that are laid out at different X positions. (#7933) - Tabs: avoid queuing a refocus when tab is already focused, which would have the side-effect of e.g. closing popup on a mouse release. (#7914) - InputText: allow callback to update buffer while in read-only mode. (imgui_club/#46) @@ -911,7 +911,7 @@ Other changes: - Windows: BeginChild(): fixed a glitch when during a resize of a child window which is tightly close to the boundaries of its parent (e.g. with zero WindowPadding), the child position could have temporarily be moved around by erroneous padding application. (#7706) -- TabBar, Style: added ImGuiTabBarFlags_DrawSelectedOverline option to draw an horizontal +- TabBar, Style: added ImGuiTabBarFlags_DrawSelectedOverline option to draw a horizontal line over selected tabs to increase visibility. This is used by docking. Added corresponding ImGuiCol_TabSelectedOverline and ImGuiCol_TabDimmedSelectedOverline colors. - Tables: added TableGetHoveredColumn() to public API, as an alternative to testing for @@ -974,7 +974,7 @@ Other changes: - Scrollbar: made scrolling logic more standard: clicking above or below the grab scrolls by one page, holding mouse button repeats scrolling. (#7328, #150) - Scrollbar: fixed miscalculation of vertical scrollbar visibility when required - solely by the presence of an horizontal scrollbar. (#1574) + solely by the presence of a horizontal scrollbar. (#1574) - InputScalar, InputInt, InputFloat: added ImGuiInputTextFlags_ParseEmptyRefVal to parse an empty field as zero-value. (#7305) [@supermerill, @ocornut] - InputScalar, InputInt, InputFloat: added ImGuiInputTextFlags_DisplayEmptyRefVal @@ -1108,7 +1108,7 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v Breaking changes: -- TreeNode: Fixed a layout inconsistency when using a empty/hidden label followed +- TreeNode: Fixed a layout inconsistency when using an empty/hidden label followed by a SameLine() call. (#7505, #282) Before: TreeNode("##Hidden"); SameLine(); Text("Hello"); // This was actually incorrect! BUT appeared to look ok with the default style @@ -1207,7 +1207,7 @@ Other changes: Note that only simple polygons (no self-intersections, no holes) are supported. - DrawList: Allow AddText() to accept null ranges. (#3615, 7391) - Docs: added more wiki links to headers of imgui.h/imgui.cpp to facilitate discovery - of interesting resources, because github doesn't allow Wiki to be crawled by search engines. + of interesting resources, because GitHub doesn't allow Wiki to be crawled by search engines. - This is the main wiki: https://github.com/ocornut/imgui/wiki - This is the crawlable version: https://github-wiki-see.page/m/ocornut/imgui/wiki Adding a link to the crawlable version, even though it is not intended for humans, @@ -1359,7 +1359,7 @@ Other changes: - BeginChild(): Resize borders rendered even when ImGuiWindowFlags_NoBackground is specified. (#1710, #7194) - Fixed some auto-resizing path using style.WindowMinSize.x (instead of x/y) - for both axises since 1.90. (#7106) [@n0bodysec] + for both axes since 1.90. (#7106) [@n0bodysec] - Scrolling: internal scrolling value is rounded instead of truncated, as a way to reduce speed asymmetry when (incorrectly) attempting to scroll by non-integer amount. (#6677) - Navigation (Keyboard/gamepad): @@ -1517,7 +1517,7 @@ Other changes: - Combining this with also specifying ImGuiChildFlags_AlwaysAutoResize disables this optimization, meaning child contents will never be clipped (not recommended). - Please be considerate that child are full windows and carry significant overhead: - combining auto-resizing for both axises to create a non-scrolling child to merely draw + combining auto-resizing for both axes to create a non-scrolling child to merely draw a border would be better more optimally using BeginGroup(). (see #1496) (until we come up with new helpers for framed groups and work-rect adjustments). - BeginChild(): made it possible to use SetNextWindowSizeConstraints() rectangle, often @@ -1579,7 +1579,7 @@ Other changes: parent-menu would erroneously close the child-menu. (Regression from 1.88). (#6869) - MenuBar: Fixed an issue where layouting an item in the menu-bar would erroneously register contents size in a way that would affect the scrolling layer. - Was most often noticeable when using an horizontal scrollbar. (#6789) + Was most often noticeable when using a horizontal scrollbar. (#6789) - InputText: - InputTextMultiline: Fixed a crash pressing Down on last empty line of a multi-line buffer. (regression from 1.89.2, only happened in some states). (#6783, #6000) @@ -1785,7 +1785,7 @@ Breaking changes: - Moved io.HoverDelayShort/io.HoverDelayNormal to style.HoverDelayShort/style.HoverDelayNormal. As the fields were added in 1.89 and expected to be left unchanged by most users, or only - tweaked once during app initialisation, we are exceptionally accepting the breakage. + tweaked once during app initialization, we are exceptionally accepting the breakage. Majority of users should not even notice. - Overlapping items: (#6512, #3909, #517) - Added 'SetNextItemAllowOverlap()' (called before an item) as a replacement for using @@ -1885,7 +1885,7 @@ Breaking changes: - Commented out obsolete/redirecting functions that were marked obsolete more than two years ago: - ListBoxHeader() -> use BeginListBox() - ListBoxFooter() -> use EndListBox() - - Note how two variants of ListBoxHeader() existed. Check commented versions in imgui.h for refeence. + - Note how two variants of ListBoxHeader() existed. Check commented versions in imgui.h for reference. - Backends: SDL_Renderer: Renamed 'imgui_impl_sdlrenderer.h/cpp' to 'imgui_impl_sdlrenderer2.h/cpp', in order to accommodate for upcoming SDL3 and change in its SDL_Renderer API. (#6286) - Backends: GLUT: Removed call to ImGui::NewFrame() from ImGui_ImplGLUT_NewFrame(). @@ -2112,20 +2112,20 @@ Other changes: due to how unique table instance id was generated. (#6140) [@ocornut, @rodrigorc] - Inputs, Scrolling: Made horizontal scroll wheel and horizontal scroll direction consistent across backends/os. (#4019, #6096, #1463) [@PathogenDavid, @ocornut, @rokups] - - Clarified that 'wheel_y > 0.0f' scrolls Up, 'wheel_y > 0.0f' scrolls Down. - Clarified that 'wheel_x > 0.0f' scrolls Left, 'wheel_x > 0.0f' scrolls Right. + - Clarified that 'wheel_y > 0.0f' scrolls Up, 'wheel_y < 0.0f' scrolls Down. + Clarified that 'wheel_x > 0.0f' scrolls Left, 'wheel_x < 0.0f' scrolls Right. - Backends: Fixed horizontal scroll direction for Win32 and SDL backends. (#4019) - Shift+WheelY support on non-OSX machines was already correct. (#2424, #1463) (whereas on OSX machines Shift+WheelY turns into WheelX at the OS level). - If you use a custom backend, you should verify horizontal wheel direction. - - Axises are flipped by OSX for mouse & touch-pad when 'Natural Scrolling' is on. - - Axises are flipped by Windows for touch-pad when 'Settings->Touchpad->Down motion scrolls up' is on. + - Axes are flipped by OSX for mouse & touch-pad when 'Natural Scrolling' is on. + - Axes are flipped by Windows for touch-pad when 'Settings->Touchpad->Down motion scrolls up' is on. - You can use 'Demo->Tools->Debug Log->IO" to visualize values submitted to Dear ImGui. - Known issues remaining with Emscripten: - The magnitude of wheeling values on Emscripten was improved but isn't perfect. (#6096) - When running the Emscripten app on a Mac with a mouse, SHIFT+WheelY doesn't turn into WheelX. This is because we don't know that we are running on Mac and apply our own Shift+swapping - on top of OSX' own swapping, so wheel axises are swapped twice. Emscripten apps may need + on top of OSX's own swapping, so wheel axes are swapped twice. Emscripten apps may need to find a way to detect this and set io.ConfigMacOSXBehaviors manually (if you know a way let us know!), or offer the "OSX-style behavior" option to their user. - Window: Avoid rendering shapes for hidden resize grips. @@ -2151,7 +2151,7 @@ Other changes: values for io.DeltaTime, and browser features such as "privacy.resistFingerprinting=true" can exacerbate that. (#6114, #3644) - Backends: OSX: Fixed scroll/wheel scaling for devices emitting events with - hasPreciseScrollingDeltas==false (e.g. non-Apple mices). + hasPreciseScrollingDeltas==false (e.g. non-Apple mice). - Backends: Win32: flipping WM_MOUSEHWHEEL horizontal value to match other backends and offer consistent horizontal scrolling direction. (#4019) - Backends: SDL2: flipping SDL_MOUSEWHEEL horizontal value to match other backends and @@ -2355,7 +2355,7 @@ Other Changes: - Scrolling: Mitigated issue where multi-axis mouse-wheel inputs (usually from touch pad events) are incorrectly locking scrolling in a parent window. (#4559, #3795, #2604) - Scrolling: Exposed SetNextWindowScroll() in public API. Useful to remove a scrolling - delay in some situations where e.g. windows need to be synched. (#1526) + delay in some situations where e.g. windows need to be synced. (#1526) - InputText: added experimental io.ConfigInputTextEnterKeepActive feature to make pressing Enter keep the input active and select all text. - InputText: numerical fields automatically accept full-width characters (U+FF01..U+FF5E) @@ -2399,7 +2399,7 @@ Other Changes: - Menus: Fixed using IsItemHovered()/IsItemClicked() on BeginMenu(). (#5775) - Menus, Popups: Experimental fix for issue where clicking on an open BeginMenu() item called from a window which is neither a popup neither a menu used to incorrectly close and reopen the menu - (the fix may have side-effect and is labelld as experimental as we may need to revert). (#5775) + (the fix may have side-effect and is labelled as experimental as we may need to revert). (#5775) - Menus, Nav: Fixed keyboard/gamepad navigation occasionally erroneously landing on menu-item in parent window when the parent is not a popup. (#5730) - Menus, Nav: Fixed not being able to close a menu with Left arrow when parent is not a popup. (#5730) @@ -2537,7 +2537,7 @@ Other Changes: always lead to menu closure. Fixes using items that are not MenuItem() or BeginItem() at the root level of a popup with a child menu opened. - Menus: Menus emitted from the main/scrolling layer are not part of the same menu-set as menus emitted - from the menu-bar, avoiding accidental hovering from one to the other. (#3496, #4797) [@rokups] + from the menu-bar, avoiding accidental hovering from one to the other. (#3496, #4797) [@rokups] - Style: Adjust default value of GrabMinSize from 10.0f to 12.0f. - Stack Tool: Added option to copy item path to clipboard. (#4631) - Settings: Fixed out-of-bounds read when .ini file on disk is empty. (#5351) [@quantum5] @@ -2639,7 +2639,7 @@ Breaking Changes: io.AddKeyEvent(), io.AddKeyAnalogEvent(). - Added io.AddKeyAnalogEvent() function, obsoleting writing directly to io.NavInputs[] arrays. - Renamed ImGuiKey_KeyPadEnter to ImGuiKey_KeypadEnter to align with new symbols. Kept redirection enum. (#2625) -- Removed support for legacy arithmetic operators (+,+-,*,/) when inputing text into a slider/drag. (#4917, #3184) +- Removed support for legacy arithmetic operators (+,+-,*,/) when inputting text into a slider/drag. (#4917, #3184) This doesn't break any api/code but a feature that was accessible by end-users (which seemingly no one used). (Instead you may implement custom expression evaluators to provide a better version of this). - Backends: GLFW: backend now uses glfwSetCursorPosCallback(). @@ -2695,7 +2695,7 @@ Other Changes: - Backends: GLFW: Retrieve mouse position using glfwSetCursorPosCallback() + fallback when focused but not hovered/captured. - Backends: GLFW: Submit gamepad data using io.AddKeyEvent/AddKeyAnalogEvent() functions, stopped writing to io.NavInputs[]. (#4921) - Backends: GLFW: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing - callbacks after iniitializing backend. (#4981) + callbacks after initializing backend. (#4981) - Backends: Win32: Submit keys and key mods using io.AddKeyEvent(). (#2625, #4921) - Backends: Win32: Retrieve mouse position using WM_MOUSEMOVE/WM_MOUSELEAVE + fallback when focused but not hovered/captured. - Backends: Win32: Submit mouse data using io.AddMousePosEvent(), AddMouseButtonEvent(), AddMouseWheelEvent() functions. (#4921) @@ -2777,7 +2777,7 @@ Other Changes: - Menus: fixed sub-menu items inside a popups from closing the popup. - Menus: fixed top-level menu from not consistently using style.PopupRounding. (#4788) - InputText, Nav: fixed repeated calls to SetKeyboardFocusHere() preventing to use InputText(). (#4682) -- Inputtext, Nav: fixed using SetKeyboardFocusHere() on InputTextMultiline(). (#4761) +- InputText, Nav: fixed using SetKeyboardFocusHere() on InputTextMultiline(). (#4761) - InputText: made double-click select word, triple-line select line. Word delimitation logic differs slightly from the one used by CTRL+arrows. (#2244) - InputText: fixed ReadOnly flag preventing callbacks from receiving the text buffer. (#4762) [@actondev] @@ -2808,7 +2808,7 @@ Other Changes: - Misc: Fix MinGW DLL build issue (when IMGUI_API is defined). [@rokups] - CI: Add MinGW DLL build to test suite. [@rokups] - Backends: Vulkan: Call vkCmdSetScissor() at the end of render with a full-viewport to reduce - likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling + likelihood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame. (#4644) - Backends: OpenGL3: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers, and perhaps improve performances. (#4468, #4504, #2981, #3381) [@parbo] @@ -2884,7 +2884,7 @@ Other Changes: - Nav: Fixed vertical scoring offset when wrapping on Y in a decorated window. - Nav: Improve scrolling behavior when navigating to an item larger than view. - TreePush(): removed unnecessary/inconsistent legacy behavior where passing a NULL value to - the TreePush(const char*) and TreePush(const void*) functions would use an hard-coded replacement. + the TreePush(const char*) and TreePush(const void*) functions would use a hard-coded replacement. The only situation where that change would make a meaningful difference is TreePush((const char*)NULL) (_explicitly_ casting a null pointer to const char*), which is unlikely and will now crash. You may replace it with anything else. @@ -3007,9 +3007,9 @@ Other Changes: - Fonts: Functions with a 'float size_pixels' parameter can accept zero if it is set in ImFontSize::SizePixels. - Fonts: Prefer using U+FFFD character for fallback instead of '?', if available. (#4269) - Fonts: Use U+FF0E dot character to construct an ellipsis if U+002E '.' is not available. (#4269) -- Fonts: Added U+FFFD ("replacement character") to default asian glyphs ranges. (#4269) +- Fonts: Added U+FFFD ("replacement character") to default Asian glyphs ranges. (#4269) - Fonts: Fixed calling ClearTexData() (clearing CPU side font data) triggering an assert in NewFrame(). (#3487) -- DrawList: Fixed AddCircle/AddCircleFilled() with auto-tesselation not using accelerated paths for small circles. +- DrawList: Fixed AddCircle/AddCircleFilled() with auto-tessellation not using accelerated paths for small circles. Fixed AddCircle/AddCircleFilled() with 12 segments which had a broken edge. (#4419, #4421) [@thedmd] - Demo: Fixed requirement in 1.83 to link with imgui_demo.cpp if IMGUI_DISABLE_METRICS_WINDOW is not set. (#4171) Normally the right way to disable compiling the demo is to set IMGUI_DISABLE_DEMO_WINDOWS, but we want to avoid @@ -3053,7 +3053,7 @@ Other Changes: - Examples: OSX+OpenGL2: Fix event forwarding (fix key remaining stuck when using shortcuts with Cmd/Super key). Other OSX examples were not affected. (#4253, #1873) [@rokups] - Examples: Updated all .vcxproj to VS2015 (toolset v140) to facilitate usage with vcpkg. -- Examples: SDL2: Accommodate for vcpkg install having headers in SDL2/SDL.h vs SDL.h. +- Examples: SDL2: Accommodate for vcpkg install having headers in SDL2/SDL.h vs SDL.h. ----------------------------------------------------------------------- @@ -3175,7 +3175,7 @@ Breaking Changes: - ImDrawList: clarified that PathArcTo()/PathArcToFast() won't render with radius < 0.0f. Previously it sorts of accidentally worked but would lead to counter-clockwise paths which and have an effect on anti-aliasing. - InputText: renamed ImGuiInputTextFlags_AlwaysInsertMode to ImGuiInputTextFlags_AlwaysOverwrite, old name was an - incorrect description of behavior. Was ostly used by memory editor. Kept inline redirection function. (#2863) + incorrect description of behavior. Was mostly used by memory editor. Kept inline redirection function. (#2863) - Moved 'misc/natvis/imgui.natvis' to 'misc/debuggers/imgui.natvis' as we will provide scripts for other debuggers. - Style: renamed rarely used style.CircleSegmentMaxError (old default = 1.60f) to style.CircleTessellationMaxError (new default = 0.30f) as its meaning changed. (#3808) [@thedmd] @@ -3273,7 +3273,7 @@ Other Changes: - For a Platform Monitor, the work area is generally the full area minus space used by task-bars. - All of this has been the case in 'docking' branch for a long time. What we've done is merely merging a small chunk of the multi-viewport logic into 'master' to standardize some concepts ahead of time. -- Tables: Fixed PopItemWidth() or multi-components items not restoring per-colum ItemWidth correctly. (#3760) +- Tables: Fixed PopItemWidth() or multi-components items not restoring per-column ItemWidth correctly. (#3760) - Window: Fixed minor title bar text clipping issue when FramePadding is small/zero and there are no close button in the window. (#3731) - SliderInt: Fixed click/drag when v_min==v_max from setting the value to zero. (#3774) [@erwincoumans] @@ -3310,7 +3310,7 @@ Other Changes: User needs to call ImGui_ImplVulkan_LoadFunctions() with their custom loader prior to other functions. - Backends: Metal: Fixed texture storage mode when building on Mac Catalyst. (#3748) [@Belinsky-L-V] - Backends: OSX: Fixed mouse position not being reported when mouse buttons other than left one are down. (#3762) [@rokups] -- Backends: WebGPU: Added enderer backend for WebGPU support (imgui_impl_wgpu.cpp) (#3632) [@bfierz] +- Backends: WebGPU: Added renderer backend for WebGPU support (imgui_impl_wgpu.cpp) (#3632) [@bfierz] Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break. - Examples: WebGPU: Added Emscripten+WebGPU example. (#3632) [@bfierz] - Backends: GLFW: Added ImGui_ImplGlfw_InitForOther() initialization call to use with non OpenGL API. (#3632) @@ -3509,12 +3509,12 @@ Other Changes: - Columns: Fix inverted ClipRect being passed to renderer when using certain primitives inside of a fully clipped column. (#3475) [@szreder] - Popups, Tooltips: Fix edge cases issues with positioning popups and tooltips when they are larger than - viewport on either or both axises. [@Rokups] + viewport on either or both axes. [@Rokups] - Fonts: AddFontDefault() adjust its vertical offset based on floor(size/13) instead of always +1. Was previously done by altering DisplayOffset.y but wouldn't work for DPI scaled font. - Metrics: Various tweaks, listing windows front-to-back, greying inactive items when possible. - Demo: Add simple InputText() callbacks demo (aside from the more elaborate ones in 'Examples->Console'). -- Backends: OpenGL3: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 contexts which have +- Backends: OpenGL3: Fix to avoid compiling/calling glBindSampler() on ES or pre-3.3 contexts which have the defines set by a loader. (#3467, #1985) [@jjwebb] - Backends: Vulkan: Some internal refactor aimed at allowing multi-viewport feature to create their own render pass. (#3455, #3459) [@FunMiles] @@ -3603,7 +3603,7 @@ Other Changes: and allowed to pass them to InvisibleButton(): ImGuiButtonFlags_MouseButtonLeft/Right/Middle. This is a small but rather important change because lots of multi-button behaviors could previously only be achieved using lower-level/internal API. Now also available via high-level InvisibleButton() - with is a de-facto versatile building block to creating custom widgets with the public API. + with is a de facto versatile building block to creating custom widgets with the public API. - Fonts: Fixed ImFontConfig::GlyphExtraSpacing and ImFontConfig::PixelSnapH settings being pulled from the merged/target font settings when merging fonts, instead of being pulled from the source font settings. @@ -3750,7 +3750,7 @@ Other Changes: ImGuiListClipper as the first thing after Begin() could largely break size calculations. (#3073) - Added optional support for Unicode plane 1-16 (#2538, #2541, #2815) [@cloudwu, @samhocevar] - Compile-time enable with '#define IMGUI_USE_WCHAR32' in imconfig.h. - - More onsistent handling of unsupported code points (0xFFFD). + - More consistent handling of unsupported code points (0xFFFD). - Surrogate pairs are supported when submitting UTF-16 data via io.AddInputCharacterUTF16(), allowing for more complete CJK input. - sizeof(ImWchar) goes from 2 to 4. IM_UNICODE_CODEPOINT_MAX goes from 0xFFFF to 0x10FFFF. @@ -3834,7 +3834,7 @@ Other Changes: - Inputs: Added ImGuiMouseButton enum for convenience (e.g. ImGuiMouseButton_Right=1). We forever guarantee that the existing value will not changes so existing code is free to use 0/1/2. -- Nav: Fixed a bug where the initial CTRL-Tab press while in a child window sometimes selected +- Nav: Fixed a bug where the initial CTRL+Tab press while in a child window sometimes selected the current root window instead of always selecting the previous root window. (#787) - ColorEdit: Fix label alignment when using ImGuiColorEditFlags_NoInputs. (#2955) [@rokups] - ColorEdit: In HSV display of a RGB stored value, attempt to locally preserve Saturation @@ -4007,7 +4007,7 @@ Other Changes: mostly for consistency. (#2159, #2160) [@goran-w] - Selectable: Added ImGuiSelectableFlags_AllowItemOverlap flag in public api (was previously internal only). - Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639) -- Font: Better ellipsis ("...") drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly +- Font: Better ellipsis ("...") drawing implementation. Instead of drawing three pixely dots (which was glaringly unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set. Otherwise we render ellipsis using '.' from the font from where we trim excessive spacing to make it as narrow as possible. (#2775) [@rokups] @@ -4343,7 +4343,7 @@ Other Changes: - InputText: Fixed an edge case crash that would happen if another widget sharing the same ID is being swapped with an InputText that has yet to be activated. - InputText: Fixed various display corruption related to swapping the underlying buffer while - a input widget is active (both for writable and read-only paths). Often they would manifest + an input widget is active (both for writable and read-only paths). Often they would manifest when manipulating the scrollbar of a multi-line input text. - ColorEdit, ColorPicker, ColorButton: Added ImGuiColorEditFlags_InputHSV to manipulate color values encoded as HSV (in order to avoid HSV<>RGB round trips and associated singularities). @@ -4354,7 +4354,7 @@ Other Changes: reading the 4th float in the array (value was read and discarded). (#2384) [@haldean] - MenuItem, Selectable: Fixed disabled widget interfering with navigation (fix c2db7f63 in 1.67). - Tabs: Fixed a crash when using many BeginTabBar() recursively (didn't affect docking). (#2371) -- Tabs: Added extra mis-usage error recovery. Past the assert, common mis-usage don't lead to +- Tabs: Added extra misusage error recovery. Past the assert, common misusage don't lead to hard crashes any more, facilitating integration with scripting languages. (#1651) - Tabs: Fixed ImGuiTabItemFlags_SetSelected being ignored if the tab is not visible (with scrolling policy enabled) or if is currently appearing. @@ -4397,7 +4397,7 @@ Breaking Changes: - Removed io.DisplayVisibleMin/DisplayVisibleMax (which were marked obsolete and removed from viewport/docking branch already). - Made it illegal/assert when io.DisplayTime == 0.0f (with an exception for the first frame). - If for some reason your time step calculation gives you a zero value, replace it with a arbitrarily small value! + If for some reason your time step calculation gives you a zero value, replace it with an arbitrarily small value! Other Changes: @@ -4495,7 +4495,7 @@ Other Changes: in the parent window, so there is no mismatch between the layout in parent and the position of the child window. - InputFloat: When using ImGuiInputTextFlags_ReadOnly the step buttons are disabled. (#2257) - DragFloat: Fixed broken mouse direction change with power!=1.0. (#2174, #2206) [@Joshhua5] -- Nav: Fixed an keyboard issue where holding Activate/Space for longer than two frames on a button would unnecessary +- Nav: Fixed a keyboard issue where holding Activate/Space for longer than two frames on a button would unnecessary keep the focus on the parent window, which could steal it from newly appearing windows. (#787) - Nav: Fixed animated window titles from being updated when displayed in the CTRL+Tab list. (#787) - Error recovery: Extraneous/undesired calls to End() are now being caught by an assert in the End() function closer @@ -4647,7 +4647,7 @@ Changes: then separate your changes into several patches that can more easily be applied to 1.64 on a per-file basis. What I found worked nicely for me, was to open the diff of the old patches in an interactive merge/diff tool, search for the corresponding function in the new code and apply the chunks manually. -- As a reminder, if you have any change to imgui.cpp it is a good habit to discuss them on the github, +- As a reminder, if you have any change to imgui.cpp it is a good habit to discuss them on the GitHub, so a solution applicable on the Master branch can be found. If your company has changes that you cannot disclose you may also contact me privately. @@ -4682,7 +4682,7 @@ Other Changes: - Nav: Added a CTRL+TAB window list and changed the highlight system accordingly. The change is motivated by upcoming Docking features. (#787) - Nav: Made CTRL+TAB skip menus + skip the current navigation window if is has the ImGuiWindow_NoNavFocus set. (#787) - While it was previously possible, you won't be able to CTRL-TAB out and immediately back in a window with the + While it was previously possible, you won't be able to CTRL+TAB out and immediately back in a window with the ImGuiWindow_NoNavFocus flag. - Window: Allow menu and popups windows from ignoring the style.WindowMinSize values so short menus/popups are not padded. (#1909) - Window: Added global io.ConfigResizeWindowsFromEdges option to enable resizing windows from their edges and from @@ -4717,7 +4717,7 @@ Other Changes: - Fixed assertion when transitioning from an active ID to another within a group, affecting ColorPicker (broken in 1.62). (#2023, #820, #956, #1875). - Fixed PushID() from keeping alive the new ID Stack top value (if a previously active widget shared the ID it would be erroneously kept alive). - Fixed horizontal mouse wheel not forwarding the request to the parent window if ImGuiWindowFlags_NoScrollWithMouse is set. (#1463, #1380, #1502) -- Fixed a include build issue for Cygwin in non-POSIX (Win32) mode. (#1917, #1319, #276) +- Fixed an include build issue for Cygwin in non-POSIX (Win32) mode. (#1917, #1319, #276) - ImDrawList: Improved handling for worst-case vertices reservation policy when large amount of text (e.g. 1+ million character strings) are being submitted in a single call. It would typically have crashed InputTextMultiline(). (#200) - OS/Windows: Fixed missing ImmReleaseContext() call in the default Win32 IME handler. (#1932) [@vby] @@ -4952,7 +4952,7 @@ Other Changes: - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays. - Basic controls: arrows to navigate, Alt to enter menus, Space to activate item, Enter to edit text, - Escape to cancel/close, Ctrl-Tab to focus windows, etc. + Escape to cancel/close, Ctrl+Tab to focus windows, etc. - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag will be set. - For more advanced uses, you may want to read from io.NavActive or io.NavVisible. Read imgui.cpp for more details. @@ -5002,7 +5002,7 @@ Other Changes: - Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding, ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181) - Style: Added style.MouseCursorScale help when using the software mouse cursor facility. (#939). -- Style: Close button nows display a cross before hovering. Fixed cross positioning being a little off. Uses button colors for highlight when hovering. (#707) +- Style: Close buttons now display a cross before hovering. Fixed cross positioning being a little off. Uses button colors for highlight when hovering. (#707) - Popup: OpenPopup() Always reopen existing pop-ups. (Removed imgui_internal.h's OpenPopupEx() which was used for this.) (#1497, #1533). - Popup: BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick() all react on mouse release instead of mouse press. (~#439) - Popup: Better handling of user mistakenly calling OpenPopup() every frame (with the 'reopen_existing' option). @@ -5025,7 +5025,7 @@ Other Changes: - Drag and Drop: Increased payload type string to 32 characters instead of 8. (#143) - Drag and Drop: TreeNode as drop target displays rectangle over full frame. (#1597, #143) - DragFloat: Fix/workaround for backends which do not preserve a valid mouse position when dragged out of bounds. (#1559) -- InputFloat: Allow inputing value using scientific notation e.g. "1e+10". +- InputFloat: Allow inputting value using scientific notation e.g. "1e+10". - InputDouble: Added InputDouble() function. We use a format string instead of a 'decimal_precision' parameter to also for "%e" and variants. (#1011) - Slider, Combo: Use ImGuiCol_FrameBgHovered color when hovered. (#1456) [@stfx] @@ -5070,7 +5070,7 @@ Other Changes: - Demo: Improved Selectable() examples. (#1528) - Demo: Tweaked the Child demos, added a menu bar to the second child to test some navigation functions. - Demo: Console: Using ImGuiCol_Text to be more friendly to color changes. -- Demo: Using IM_COL32() instead of ImColor() in ImDrawList centric contexts. Trying to phase out use of the ImColor helper whenever possible. +- Demo: Using IM_COL32() instead of ImColor() in ImDrawList-centric contexts. Trying to phase out use of the ImColor helper whenever possible. - Examples: Files in examples/ now include their own changelog so it is easier to occasionally update your backends if needed. - Examples: Using Dark theme by default. (#707). Tweaked demo code. - Examples: Added support for horizontal mouse wheel for API that allows it. (#1463) [@tseeker] @@ -5188,7 +5188,7 @@ Other Changes: - Window: Added ImGuiWindowFlags_ResizeFromAnySide flag to resize from any borders or from the lower-left corner of a window. This requires your backend to honor GetMouseCursor() requests for full usability. (#822) -- Window: Sizing fixes when using SetNextWindowSize() on individual axises. +- Window: Sizing fixes when using SetNextWindowSize() on individual axes. - Window: Hide new window for one frame until they calculate their size. Also fixes SetNextWindowPos() given a non-zero pivot. (#1694) - Window: Made mouse wheel scrolling accommodate better to windows that are smaller than the scroll step. @@ -5490,7 +5490,7 @@ Other Changes: check the Demo window and comment for `ImGuiColorEditFlags_`. Some of the options it supports are: two color picker types (hue bar + sat/val rectangle, hue wheel + rotating sat/val triangle), display as u8 or float, lifting 0.0..1.0 constraints - (currently rgba only), context menus, alpha bar, background checkerboard options, preview tooltip, + (currently rgba only), context menus, alpha bar, background checkerboard options, preview tooltip, basic revert. For simple use, calling the existing `ColorEdit4()` function as you did before will be enough, as you can now open the color picker from there. - Added `SetColorEditOptions()` to set default color options (e.g. if you want HSV over RGBA, @@ -5592,7 +5592,7 @@ Other Changes: certain style settings and zero WindowMinSize). - EndGroup(): Made IsItemHovered() work when an item was activated within the group. (#849) - BulletText(): Fixed stopping to display formatted string after the '##' mark. -- Closing the focused window restore focus to the first active root window in descending z-order .(part of #727) +- Closing the focused window restore focus to the first active root window in descending z-order. (part of #727) - Word-wrapping: Fixed a bug where we never wrapped after a 1 character word. [@sronsse] - Word-wrapping: Fixed TextWrapped() overriding wrap position if one is already set. (#690) - Word-wrapping: Fixed incorrect testing for negative wrap coordinates, they are perfectly legal. (#706) @@ -5629,7 +5629,7 @@ Other Changes: - Demo: ShowStyleEditor: show font character map / grid in more details. - Demo: Console: Fixed a completion bug when multiple candidates are equals and match until the end. - Demo: Fixed 1-byte off overflow in the ShowStyleEditor() combo usage. (#783) [@bear24rw] -- Examples: Accessing ImVector fields directly, feel less stl-ey. (#810) +- Examples: Accessing ImVector fields directly, feel less stl-y. (#810) - Examples: OpenGL*: Saving/restoring existing scissor rectangle for completeness. (#807) - Examples: OpenGL*: Saving/restoring active texture number (the value modified by glActiveTexture). (#1087, #1088, #1116) - Examples: OpenGL*: Saving/restoring separate color/alpha blend functions correctly. (#1120) [@greggman] @@ -5793,7 +5793,7 @@ Other Changes: after a text input modification (e.g. "0.0" --> "0.000" would keep returning true). (#564) - DragFloat(): Always apply value when mouse is held/widget active, so that an always-resetting variable (e.g. non saved local) can be passed. -- InputText(): OS X friendly behaviors: (@zhiayang), (#473) +- InputText(): OS X friendly behaviors: (@zhiayang), (#473) - Word movement uses ALT key; - Shortcuts uses CMD key; - Double-clicking text select a single word; @@ -5918,7 +5918,7 @@ Changes: - PlotHistogram(): improved rendering of histogram with a lot of values. - Dummy(): creates an item so functions such as IsItemHovered() can be used. - BeginChildFrame() helper: added the extra_flags parameter. -- Scrollbar: fixed rounding of background + child window consistenly have ChildWindowBg color under ScrollbarBg fill. (#355). +- Scrollbar: fixed rounding of background + child window consistently have ChildWindowBg color under ScrollbarBg fill. (#355). - Scrollbar: background color less translucent in default style so it works better when changing background color. - Scrollbar: fixed minor rendering offset when borders are enabled. (#365) - ImDrawList: fixed 1 leak per ImDrawList using the ChannelsSplit() API (via Columns). (#318) @@ -5934,7 +5934,7 @@ Changes: - Internal: Extracted a EndFrame() function out of Render() but kept it internal/private + clarified some asserts. (#335) - Internal: Added missing IMGUI_API definitions in imgui_internal.h (#326) - Internal: ImLoadFileToMemory() return void\* instead of taking void*\* + allow optional int\* file_size. -- Demo: Horizontal scrollbar demo allows to enable simultanaeous scrollbars on both axises. +- Demo: Horizontal scrollbar demo allows to enable simultaneous scrollbars on both axes. - Tools: binary_to_compressed_c.cpp: added -nocompress option. - Examples: Added example for the Marmalade platform. - Examples: Added batch files to build Windows examples with VS. @@ -5979,7 +5979,7 @@ Other Changes: - ImDrawList: Added an assert on overflowing index value (#292). - ImDrawList: Fixed issues with channels split/merge. Now functional without manually adding a draw cmd. Added comments. - ImDrawData: Added ScaleClipRects() helper useful when rendering scaled. (#287). -- Fixed Bullet() inconsistent layout behaviour when clipped. +- Fixed Bullet() inconsistent layout behavior when clipped. - Fixed IsWindowHovered() not taking account of window hoverability (may be disabled because of a popup). - Fixed InvisibleButton() not honoring negative size consistently with other widgets that do so. - Fixed OpenPopup() accessing current window, effectively opening "Debug" when called from an empty window stack. @@ -5991,7 +5991,7 @@ Other Changes: the first place so it's not really a useful default. - Begin(): Minor fixes with windows main clipping rectangle (e.g. child window with border). - Begin(): Window flags are only read on the first call of the frame. Subsequent calls ignore flags, which allows - appending to a window without worryin about flags. + appending to a window without worrying about flags. - InputText(): ignore character input when ctrl/alt are held. (Normally those text input are ignored by most wrappers.) (#279). - Demo: Fixed incorrectly formed string passed to Combo (#298). - Demo: Added simple Log demo. @@ -6025,7 +6025,7 @@ Other Changes: and more natural to extend ImGui. However please note that none of the content in imgui_internal.h is guaranteed for forward-compatibility and code using those types/functions may occasionally break. (#219) - All sample code is in imgui_demo.cpp. Please keep this file in your project and consider allowing your code to call - the ShowTestWindow() function as de-facto guide to ImGui features. It will be stripped out by the linker when unused. + the ShowTestWindow() function as de facto guide to ImGui features. It will be stripped out by the linker when unused. - Added GetContentRegionAvail() helper (basically GetContentRegionMax() - GetCursorPos()). - Added ImGuiWindowFlags_NoInputs for totally input-passthru window. - Button(): honor negative size consistently with other widgets that do so (width -100 to align the button 100 pixels @@ -6390,7 +6390,7 @@ Other Changes: - IsItemHovered() return false if another widget is active, aka we can't use what we are hovering now. - Added IsItemHoveredRect() if old behavior of IsItemHovered() is needed (e.g. for implementing the drop side of a drag'n drop operation). -- IsItemhovered() include space taken by label and behave consistently for all widgets (#145) +- IsItemHovered() include space taken by label and behave consistently for all widgets (#145) - Auto-filling child window feed their content size to parent (#170) - InputText() removed the odd ~ characters when clipping. - InputText() update its width in case of resize initiated programmatically while the widget is active. @@ -6454,7 +6454,7 @@ Other Changes: - Sliders: Fixed parsing of decimal precision back from format string when using %%. - Sliders: Fixed hovering bounding test excluding padding between outer frame and grab (there was a few pixels dead-zone). - Separator() logs itself as text when passing through text log. -- Optimisation: TreeNodeV() early out if SkipItems is set without formatting. +- Optimization: TreeNodeV() early out if SkipItems is set without formatting. - Moved various static buffers into state. Increase the formatted string buffer from 1K to 3K. - Examples: Example console keeps focus on input box at all times. - Examples: Updated to GLFW 3.1. Moved to examples/libs/ folder. @@ -6583,8 +6583,8 @@ Other Changes: Callback now passed an "EventFlag" parameter. - InputText: Added ImGuiInputTextFlags_CharsUppercase and ImGuiInputTextFlags_CharsNoBlank stock filters. - PushItemWidth() can take negative value to right-align items. -- Optimisation: Columns offsets cached to avoid unnecessary binary search. -- Optimisation: Optimized CalcTextSize() function by about 25% (they are often the bottleneck when +- Optimization: Columns offsets cached to avoid unnecessary binary search. +- Optimization: Optimized CalcTextSize() function by about 25% (they are often the bottleneck when submitting thousands of clipped items). - Added ImGuiCol_ChildWindowBg, ImGuiStyleVar_ChildWindowRounding for completeness and flexibility. - Added BeginChild() variant that takes an ImGuiID. @@ -6627,7 +6627,7 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v Breaking Changes: -- Big update! Initialisation had to be changed. You don't need to load PNG data anymore. Th +- Big update! Initialization had to be changed. You don't need to load PNG data anymore. The new system gives you uncompressed texture data. - This sequence: const void* png_data; @@ -6637,7 +6637,7 @@ Breaking Changes: - Became: unsigned char* pixels; int width, height; - // io.Fonts->AddFontFromFileTTF("myfontfile.ttf", 24.0f); // Optionally load another font + // io.Fonts->AddFontFromFileTTF("myfontfile.ttf", 24.0f); // Optionally load another font io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // io.Fonts->TexID = (your_texture_identifier); @@ -6659,7 +6659,7 @@ Other Changes: - Added IsItemActive() to tell if last widget is being held / modified (as opposed to just being hovered). Useful for custom dragging behaviors. - Style: Added FrameRounding setting for a more rounded look (default to 0 for now). -- Window: Fixed using multiple Begin/End pair on the same wnidow. +- Window: Fixed using multiple Begin/End pair on the same window. - Window: Fixed style.WindowMinSize not being honored properly. - Window: Added SetCursorScreenPos() helper (WindowPos+CursorPos = ScreenPos). - ColorEdit3: clicking on color square change the edition. The toggle button is hidden by default. @@ -6690,10 +6690,10 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v - Dragging outside area of a widget while it is active doesn't trigger hover on other widgets. - Activating widget bring parent window to front if not already. - Checkbox and Radio buttons activate on click-release to be consistent with other widgets and most UI. -- InputText() nows consume input characters immediately so they cannot be reused if +- InputText() now consumes input characters immediately so they cannot be reused if ImGui::Update is called again with a call to ImGui::Render(). (fixes #105) - Examples: Console: added support for History callbacks + some cleanup. -- Various small optimisations. +- Various small optimizations. - Cleanup and other fixes. @@ -6896,7 +6896,7 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v Breaking Changes: -- The behaviour of PixelCenterOffset changed! You may need to change your value if you had set +- The behavior of PixelCenterOffset changed! You may need to change your value if you had set it to non-default in your code and/or offset your projection matrix by 0.5 pixels. It is likely that the default PixelCenterOffset value of 0.0 is now suitable unless your rendering uses some form of multisampling. @@ -6990,7 +6990,7 @@ Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v - OpenGL example now use the fixed function-pipeline + cleanups, down by 150 lines. - Added quick & dirty Makefiles for MacOSX and Linux. -- Simplified the DrawList system, ImDrawCmd include the clipping rectangle + some optimisations. +- Simplified the DrawList system, ImDrawCmd include the clipping rectangle + some optimizations. - Fixed warnings for more stringent compilation settings. diff --git a/docs/FAQ.md b/docs/FAQ.md index 6e8d6c26f7dd..5af2e9035e9e 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -543,7 +543,7 @@ The short answer is: obtain the desired DPI scale, load your fonts resized with Your application may want to detect DPI change and reload the fonts and reset style between frames. -Your ui code should avoid using hardcoded constants for size and positioning. Prefer to express values as multiple of reference values such as `ImGui::GetFontSize()` or `ImGui::GetFrameHeight()`. So e.g. instead of seeing a hardcoded height of 500 for a given item/window, you may want to use `30*ImGui::GetFontSize()` instead. +Your UI code should avoid using hardcoded constants for size and positioning. Prefer to express values as multiple of reference values such as `ImGui::GetFontSize()` or `ImGui::GetFrameHeight()`. So e.g. instead of seeing a hardcoded height of 500 for a given item/window, you may want to use `30*ImGui::GetFontSize()` instead. Down the line Dear ImGui will provide a variety of standardized reference values to facilitate using this. @@ -666,7 +666,7 @@ You may take a look at: Yes. People have written game editors, data browsers, debuggers, profilers, and all sorts of non-trivial tools with the library. In my experience, the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library. -Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient, and powerful. +Dear ImGui is very programmer-centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient, and powerful. Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization than the more typical RMGUI paradigm. diff --git a/docs/TODO.txt b/docs/TODO.txt index 14a152a4bec0..aeef17592575 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -279,7 +279,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: expose wrap around flags/logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping(). - nav: patterns to make it possible for arrows key to update selection (see JustMovedTo in range_select branch) - nav: restore/find nearest NavId when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name) - - nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem + - nav: SetItemDefaultFocus() level of priority, so widgets like Selectable when inside a popup could claim a low-priority default focus on the first selected item - nav: holding space to repeat a button doesn't show button activated during hold. - nav: NavFlattened: init requests don't work properly on flattened siblings. - nav: NavFlattened: pageup/pagedown/home/end don't work properly on flattened siblings. @@ -329,7 +329,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - backends: opengl: explicitly disable GL_STENCIL_TEST in bindings. - backends: vulkan: viewport: support for synchronized swapping of multiple swap chains. - backends: bgfx: https://gist.github.com/RichardGale/6e2b74bc42b3005e08397236e4be0fd0 - - backends: emscriptem: with refactored examples, we could provide a direct imgui_impl_emscripten platform layer (see eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42) + - backends: emscripten: with refactored examples, we could provide a direct imgui_impl_emscripten platform layer (see eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42) - bindings: ways to use clang ast dump to generate bindings or helpers for bindings? (e.g. clang++ -Xclang -ast-dump=json imgui.h) (--> use https://github.com/dearimgui/dear_bindings) diff --git a/imgui.cpp b/imgui.cpp index 73bd2581ece2..86b0d5d46b0d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -655,7 +655,7 @@ CODE - 2022/04/05 (1.88) - inputs: renamed ImGuiKeyModFlags to ImGuiModFlags. Kept inline redirection enums (will obsolete). This was never used in public API functions but technically present in imgui.h and ImGuiIO. - 2022/01/20 (1.87) - inputs: reworded gamepad IO. - Backend writing to io.NavInputs[] -> backend should call io.AddKeyEvent()/io.AddKeyAnalogEvent() with ImGuiKey_GamepadXXX values. - - 2022/01/19 (1.87) - sliders, drags: removed support for legacy arithmetic operators (+,+-,*,/) when inputing text. This doesn't break any api/code but a feature that used to be accessible by end-users (which seemingly no one used). + - 2022/01/19 (1.87) - sliders, drags: removed support for legacy arithmetic operators (+,+-,*,/) when inputting text. This doesn't break any api/code but a feature that used to be accessible by end-users (which seemingly no one used). - 2022/01/17 (1.87) - inputs: reworked mouse IO. - Backend writing to io.MousePos -> backend should call io.AddMousePosEvent() - Backend writing to io.MouseDown[] -> backend should call io.AddMouseButtonEvent() @@ -4954,7 +4954,7 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window) // Handle mouse moving window // Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing() -// FIXME: We don't have strong guarantee that g.MovingWindow stay synched with g.ActiveId == g.MovingWindow->MoveId. +// FIXME: We don't have strong guarantee that g.MovingWindow stay synced with g.ActiveId == g.MovingWindow->MoveId. // This is currently enforced by the fact that BeginDragDropSource() is setting all g.ActiveIdUsingXXXX flags to inhibit navigation inputs, // but if we should more thoroughly test cases where g.ActiveId or g.MovingWindow gets changed and not the other. void ImGui::UpdateMouseMovingWindowNewFrame() @@ -6563,7 +6563,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si { // Auto-fit when double-clicking size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit); - ret_auto_fit_mask = 0x03; // Both axises + ret_auto_fit_mask = 0x03; // Both axes ClearActiveID(); } else if (held) @@ -9701,7 +9701,7 @@ void ImGui::UpdateMouseWheel() if (g.IO.MouseWheelRequestAxisSwap) wheel = ImVec2(wheel.y, 0.0f); - // Maintain a rough average of moving magnitude on both axises + // Maintain a rough average of moving magnitude on both axes // FIXME: should by based on wall clock time rather than frame-counter g.WheelingAxisAvg.x = ImExponentialMovingAverage(g.WheelingAxisAvg.x, ImAbs(wheel.x), 30); g.WheelingAxisAvg.y = ImExponentialMovingAverage(g.WheelingAxisAvg.y, ImAbs(wheel.y), 30); @@ -9714,7 +9714,7 @@ void ImGui::UpdateMouseWheel() // Mouse wheel scrolling: find target and apply // - don't renew lock if axis doesn't apply on the window. - // - select a main axis when both axises are being moved. + // - select a main axis when both axes are being moved. if (ImGuiWindow* window = (g.WheelingWindow ? g.WheelingWindow : FindBestWheelingWindow(wheel))) if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) { diff --git a/imgui.h b/imgui.h index 2f6a18d2aa1a..4a14c82c28a1 100644 --- a/imgui.h +++ b/imgui.h @@ -544,7 +544,7 @@ namespace ImGui IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text() IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void SeparatorText(const char* label); // currently: formatted text with an horizontal line + IMGUI_API void SeparatorText(const char* label); // currently: formatted text with a horizontal line // Widgets: Main // - Most widgets return true when the value has been changed or when pressed/selected diff --git a/imgui_demo.cpp b/imgui_demo.cpp index beffe618db0f..50eeed1073f6 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8415,7 +8415,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::EndTooltip(); } ImGui::SameLine(); - HelpMarker("When drawing circle primitives with \"num_segments == 0\" tesselation will be calculated automatically."); + HelpMarker("When drawing circle primitives with \"num_segments == 0\" tessellation will be calculated automatically."); ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. ImGui::DragFloat("Disabled Alpha", &style.DisabledAlpha, 0.005f, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Additional alpha multiplier for disabled items (multiply over current value of Alpha)."); @@ -8446,7 +8446,7 @@ void ImGui::ShowUserGuide() ImGui::BulletText("CTRL+Tab to select a window."); if (io.FontAllowUserScaling) ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents."); - ImGui::BulletText("While inputing text:\n"); + ImGui::BulletText("While inputting text:\n"); ImGui::Indent(); ImGui::BulletText("CTRL+Left/Right to word jump."); ImGui::BulletText("CTRL+A or double-click to select all."); @@ -8877,7 +8877,7 @@ struct ExampleAppConsole else { // Multiple matches. Complete as much as we can.. - // So inputing "C"+Tab will complete to "CL" then display "CLEAR" and "CLASSIFY" as matches. + // So inputting "C"+Tab will complete to "CL" then display "CLEAR" and "CLASSIFY" as matches. int match_len = (int)(word_end - word_start); for (;;) { diff --git a/imgui_internal.h b/imgui_internal.h index b7395fcae087..aaa2027df944 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2801,7 +2801,7 @@ struct IMGUI_API ImGuiTable { ImGuiID ID; ImGuiTableFlags Flags; - void* RawData; // Single allocation to hold Columns[], DisplayOrderToIndex[] and RowCellData[] + void* RawData; // Single allocation to hold Columns[], DisplayOrderToIndex[], and RowCellData[] ImGuiTableTempData* TempData; // Transient data while table is active. Point within g.CurrentTableStack[] ImSpan Columns; // Point within RawData[] ImSpan DisplayOrderToIndex; // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1) @@ -2815,7 +2815,7 @@ struct IMGUI_API ImGuiTable int ColumnsCount; // Number of columns declared in BeginTable() int CurrentRow; int CurrentColumn; - ImS16 InstanceCurrent; // Count of BeginTable() calls with same ID in the same frame (generally 0). This is a little bit similar to BeginCount for a window, but multiple table with same ID look are multiple tables, they are just synched. + ImS16 InstanceCurrent; // Count of BeginTable() calls with same ID in the same frame (generally 0). This is a little bit similar to BeginCount for a window, but multiple tables with the same ID are multiple tables, they are just synced. ImS16 InstanceInteracted; // Mark which instance (generally 0) of the same ID is being interacted with float RowPosY1; float RowPosY2; @@ -2847,7 +2847,7 @@ struct IMGUI_API ImGuiTable float AngledHeadersHeight; // Set by TableAngledHeadersRow(), used in TableUpdateLayout() float AngledHeadersSlope; // Set by TableAngledHeadersRow(), used in TableUpdateLayout() ImRect OuterRect; // Note: for non-scrolling table, OuterRect.Max.y is often FLT_MAX until EndTable(), unless a height has been specified in BeginTable(). - ImRect InnerRect; // InnerRect but without decoration. As with OuterRect, for non-scrolling tables, InnerRect.Max.y is + ImRect InnerRect; // InnerRect but without decoration. As with OuterRect, for non-scrolling tables, InnerRect.Max.y is " ImRect WorkRect; ImRect InnerClipRect; ImRect BgClipRect; // We use this to cpu-clip cell background color fill, evolve during the frame as we cross frozen rows boundaries diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 6c79262363f2..bc5862ee3703 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -977,7 +977,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // [Part 4] Apply final widths based on requested widths const ImRect work_rect = table->WorkRect; const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); - const float width_removed = (table->HasScrollbarYPrev && !table->InnerWindow->ScrollbarY) ? g.Style.ScrollbarSize : 0.0f; // To synchronize decoration width of synched tables with mismatching scrollbar state (#5920) + const float width_removed = (table->HasScrollbarYPrev && !table->InnerWindow->ScrollbarY) ? g.Style.ScrollbarSize : 0.0f; // To synchronize decoration width of synced tables with mismatching scrollbar state (#5920) const float width_avail = ImMax(1.0f, (((table->Flags & ImGuiTableFlags_ScrollX) && table->InnerWidth == 0.0f) ? table->InnerClipRect.GetWidth() : work_rect.GetWidth()) - width_removed); const float width_avail_for_stretched_columns = width_avail - width_spacings - sum_width_requests; float width_remaining_for_stretched_columns = width_avail_for_stretched_columns; @@ -1390,7 +1390,7 @@ void ImGui::EndTable() // Setup inner scrolling range // FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y, - // but since the later is likely to be impossible to do we'd rather update both axises together. + // but since the later is likely to be impossible to do we'd rather update both axes together. if (table->Flags & ImGuiTableFlags_ScrollX) { const float outer_padding_for_border = (table->Flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 01e4e61872c9..9ecdbae8e610 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -8898,7 +8898,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_NoAutoClosePopups; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { - // Menu inside an horizontal menu bar + // Menu inside a horizontal menu bar // Selectable extend their highlight by half ItemSpacing in each direction. // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() popup_pos = ImVec2(pos.x - 1.0f - IM_TRUNC(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight); From 88d4827b64f0453284252b2af344d770fb52da36 Mon Sep 17 00:00:00 2001 From: Zijie Wu Date: Sun, 9 Mar 2025 13:44:26 -0700 Subject: [PATCH 526/548] Update FAQ.md for SDL3 (#8480) --- docs/FAQ.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 5af2e9035e9e..8c08b4dd7873 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -562,7 +562,8 @@ Please note that if you are not using multi-viewports with multi-monitors using On Windows, in addition to scaling the font size (make sure to round to an integer) and using `style.ScaleAllSizes()`, you will need to inform Windows that your application is DPI aware. If this is not done, Windows will scale the application window and the UI text will be blurry. Potential solutions to indicate DPI awareness on Windows are: -- For SDL: the flag `SDL_WINDOW_ALLOW_HIGHDPI` needs to be passed to `SDL_CreateWindow()``. +- For SDL2: the flag `SDL_WINDOW_ALLOW_HIGHDPI` needs to be passed to `SDL_CreateWindow()`. +- For SDL3: the flag `SDL_WINDOW_HIGH_PIXEL_DENSITY` needs to be passed to `SDL_CreateWindow()`. - For GLFW: this is done automatically. - For other Windows projects with other backends, or wrapper projects: - We provide a `ImGui_ImplWin32_EnableDpiAwareness()` helper method in the Win32 backend. From a9e53829d2753b6eb3ef763e091f430ab507c722 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Mar 2025 16:29:59 +0100 Subject: [PATCH 527/548] Backends: Win32, SDL2, SDL3, GLFW: prioritize scancodes instead of translated keycodes when dealing with OEM keys + Added ImGuiKey_Oem102. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) --- backends/imgui_impl_glfw.cpp | 3 +++ backends/imgui_impl_sdl2.cpp | 34 ++++++++++++++++++++------- backends/imgui_impl_sdl3.cpp | 34 ++++++++++++++++++++------- backends/imgui_impl_win32.cpp | 43 +++++++++++++++++++++++++++-------- docs/CHANGELOG.txt | 12 ++++++++++ imgui.cpp | 4 ++-- imgui.h | 5 ++-- 7 files changed, 105 insertions(+), 30 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 874a0a440997..baa8541b0af0 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -28,6 +28,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-03-10: Map GLFW_KEY_WORLD_1 and GLFW_KEY_WORLD_2 into ImGuiKey_Oem102. // 2025-03-03: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. // 2024-08-22: Moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: // - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn @@ -221,6 +222,8 @@ ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode) case GLFW_KEY_EQUAL: return ImGuiKey_Equal; case GLFW_KEY_LEFT_BRACKET: return ImGuiKey_LeftBracket; case GLFW_KEY_BACKSLASH: return ImGuiKey_Backslash; + case GLFW_KEY_WORLD_1: return ImGuiKey_Oem102; + case GLFW_KEY_WORLD_2: return ImGuiKey_Oem102; case GLFW_KEY_RIGHT_BRACKET: return ImGuiKey_RightBracket; case GLFW_KEY_GRAVE_ACCENT: return ImGuiKey_GraveAccent; case GLFW_KEY_CAPS_LOCK: return ImGuiKey_CapsLock; diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 6256b4dddec4..33f7fed06a2f 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) // 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650) // 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. @@ -209,17 +210,17 @@ ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode sca case SDLK_SPACE: return ImGuiKey_Space; case SDLK_RETURN: return ImGuiKey_Enter; case SDLK_ESCAPE: return ImGuiKey_Escape; - case SDLK_QUOTE: return ImGuiKey_Apostrophe; + //case SDLK_QUOTE: return ImGuiKey_Apostrophe; case SDLK_COMMA: return ImGuiKey_Comma; - case SDLK_MINUS: return ImGuiKey_Minus; + //case SDLK_MINUS: return ImGuiKey_Minus; case SDLK_PERIOD: return ImGuiKey_Period; - case SDLK_SLASH: return ImGuiKey_Slash; + //case SDLK_SLASH: return ImGuiKey_Slash; case SDLK_SEMICOLON: return ImGuiKey_Semicolon; - case SDLK_EQUALS: return ImGuiKey_Equal; - case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket; - case SDLK_BACKSLASH: return ImGuiKey_Backslash; - case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket; - case SDLK_BACKQUOTE: return ImGuiKey_GraveAccent; + //case SDLK_EQUALS: return ImGuiKey_Equal; + //case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket; + //case SDLK_BACKSLASH: return ImGuiKey_Backslash; + //case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket; + //case SDLK_BACKQUOTE: return ImGuiKey_GraveAccent; case SDLK_CAPSLOCK: return ImGuiKey_CapsLock; case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock; case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock; @@ -315,6 +316,23 @@ ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode sca case SDLK_AC_FORWARD: return ImGuiKey_AppForward; default: break; } + + // Fallback to scancode + switch (scancode) + { + case SDL_SCANCODE_GRAVE: return ImGuiKey_GraveAccent; + case SDL_SCANCODE_MINUS: return ImGuiKey_Minus; + case SDL_SCANCODE_EQUALS: return ImGuiKey_Equal; + case SDL_SCANCODE_LEFTBRACKET: return ImGuiKey_LeftBracket; + case SDL_SCANCODE_RIGHTBRACKET: return ImGuiKey_RightBracket; + case SDL_SCANCODE_NONUSBACKSLASH: return ImGuiKey_Oem102; + case SDL_SCANCODE_BACKSLASH: return ImGuiKey_Backslash; + case SDL_SCANCODE_SEMICOLON: return ImGuiKey_Semicolon; + case SDL_SCANCODE_APOSTROPHE: return ImGuiKey_Apostrophe; + case SDL_SCANCODE_COMMA: return ImGuiKey_Comma; + case SDL_SCANCODE_PERIOD: return ImGuiKey_Period; + case SDL_SCANCODE_SLASH: return ImGuiKey_Slash; + } return ImGuiKey_None; } diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 2d8027184b60..6720899ef23f 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) // 2025-02-26: Only start SDL_CaptureMouse() when mouse is being dragged, to mitigate issues with e.g.Linux debuggers not claiming capture back. (#6410, #3650) // 2025-02-24: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. @@ -207,17 +208,17 @@ ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode sca case SDLK_SPACE: return ImGuiKey_Space; case SDLK_RETURN: return ImGuiKey_Enter; case SDLK_ESCAPE: return ImGuiKey_Escape; - case SDLK_APOSTROPHE: return ImGuiKey_Apostrophe; + //case SDLK_APOSTROPHE: return ImGuiKey_Apostrophe; case SDLK_COMMA: return ImGuiKey_Comma; - case SDLK_MINUS: return ImGuiKey_Minus; + //case SDLK_MINUS: return ImGuiKey_Minus; case SDLK_PERIOD: return ImGuiKey_Period; - case SDLK_SLASH: return ImGuiKey_Slash; + //case SDLK_SLASH: return ImGuiKey_Slash; case SDLK_SEMICOLON: return ImGuiKey_Semicolon; - case SDLK_EQUALS: return ImGuiKey_Equal; - case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket; - case SDLK_BACKSLASH: return ImGuiKey_Backslash; - case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket; - case SDLK_GRAVE: return ImGuiKey_GraveAccent; + //case SDLK_EQUALS: return ImGuiKey_Equal; + //case SDLK_LEFTBRACKET: return ImGuiKey_LeftBracket; + //case SDLK_BACKSLASH: return ImGuiKey_Backslash; + //case SDLK_RIGHTBRACKET: return ImGuiKey_RightBracket; + //case SDLK_GRAVE: return ImGuiKey_GraveAccent; case SDLK_CAPSLOCK: return ImGuiKey_CapsLock; case SDLK_SCROLLLOCK: return ImGuiKey_ScrollLock; case SDLK_NUMLOCKCLEAR: return ImGuiKey_NumLock; @@ -296,6 +297,23 @@ ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode sca case SDLK_AC_FORWARD: return ImGuiKey_AppForward; default: break; } + + // Fallback to scancode + switch (scancode) + { + case SDL_SCANCODE_GRAVE: return ImGuiKey_GraveAccent; + case SDL_SCANCODE_MINUS: return ImGuiKey_Minus; + case SDL_SCANCODE_EQUALS: return ImGuiKey_Equal; + case SDL_SCANCODE_LEFTBRACKET: return ImGuiKey_LeftBracket; + case SDL_SCANCODE_RIGHTBRACKET: return ImGuiKey_RightBracket; + case SDL_SCANCODE_NONUSBACKSLASH: return ImGuiKey_Oem102; + case SDL_SCANCODE_BACKSLASH: return ImGuiKey_Backslash; + case SDL_SCANCODE_SEMICOLON: return ImGuiKey_Semicolon; + case SDL_SCANCODE_APOSTROPHE: return ImGuiKey_Apostrophe; + case SDL_SCANCODE_COMMA: return ImGuiKey_Comma; + case SDL_SCANCODE_PERIOD: return ImGuiKey_Period; + case SDL_SCANCODE_SLASH: return ImGuiKey_Slash; + } return ImGuiKey_None; } diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 49948c529441..2c749515d221 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768) // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. @@ -431,6 +432,8 @@ ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam) if ((wParam == VK_RETURN) && (HIWORD(lParam) & KF_EXTENDED)) return ImGuiKey_KeypadEnter; + const int scancode = (int)LOBYTE(HIWORD(lParam)); + //IMGUI_DEBUG_LOG("scancode %3d, keycode = 0x%02X\n", scancode, wParam); switch (wParam) { case VK_TAB: return ImGuiKey_Tab; @@ -448,17 +451,17 @@ ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam) case VK_SPACE: return ImGuiKey_Space; case VK_RETURN: return ImGuiKey_Enter; case VK_ESCAPE: return ImGuiKey_Escape; - case VK_OEM_7: return ImGuiKey_Apostrophe; + //case VK_OEM_7: return ImGuiKey_Apostrophe; case VK_OEM_COMMA: return ImGuiKey_Comma; - case VK_OEM_MINUS: return ImGuiKey_Minus; + //case VK_OEM_MINUS: return ImGuiKey_Minus; case VK_OEM_PERIOD: return ImGuiKey_Period; - case VK_OEM_2: return ImGuiKey_Slash; - case VK_OEM_1: return ImGuiKey_Semicolon; - case VK_OEM_PLUS: return ImGuiKey_Equal; - case VK_OEM_4: return ImGuiKey_LeftBracket; - case VK_OEM_5: return ImGuiKey_Backslash; - case VK_OEM_6: return ImGuiKey_RightBracket; - case VK_OEM_3: return ImGuiKey_GraveAccent; + //case VK_OEM_2: return ImGuiKey_Slash; + //case VK_OEM_1: return ImGuiKey_Semicolon; + //case VK_OEM_PLUS: return ImGuiKey_Equal; + //case VK_OEM_4: return ImGuiKey_LeftBracket; + //case VK_OEM_5: return ImGuiKey_Backslash; + //case VK_OEM_6: return ImGuiKey_RightBracket; + //case VK_OEM_3: return ImGuiKey_GraveAccent; case VK_CAPITAL: return ImGuiKey_CapsLock; case VK_SCROLL: return ImGuiKey_ScrollLock; case VK_NUMLOCK: return ImGuiKey_NumLock; @@ -550,8 +553,28 @@ ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam) case VK_F24: return ImGuiKey_F24; case VK_BROWSER_BACK: return ImGuiKey_AppBack; case VK_BROWSER_FORWARD: return ImGuiKey_AppForward; - default: return ImGuiKey_None; + default: break; } + + // Fallback to scancode + // https://handmade.network/forums/t/2011-keyboard_inputs_-_scancodes,_raw_input,_text_input,_key_names + switch (scancode) + { + case 41: return ImGuiKey_GraveAccent; // VK_OEM_8 in EN-UK, VK_OEM_3 in EN-US, VK_OEM_7 in FR, VK_OEM_5 in DE, etc. + case 12: return ImGuiKey_Minus; + case 13: return ImGuiKey_Equal; + case 26: return ImGuiKey_LeftBracket; + case 27: return ImGuiKey_RightBracket; + case 86: return ImGuiKey_Oem102; + case 43: return ImGuiKey_Backslash; + case 39: return ImGuiKey_Semicolon; + case 40: return ImGuiKey_Apostrophe; + case 51: return ImGuiKey_Comma; + case 52: return ImGuiKey_Period; + case 53: return ImGuiKey_Slash; + } + + return ImGuiKey_None; } // Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ca5ab47e386b..07a9801bc1cb 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -121,6 +121,18 @@ Other changes: by showing the filter inside the combo contents. (#718) - Examples: SDL3: Added comments to clarify setup for users of the unfortunate SDL_MAIN_USE_CALLBACKS feature. (#8455) +- IO: Added ImGuiKey_Oem102 to ImGuiKey enum. (#7136, #7201, #7206, #7306, #8468) +- Backends: reworked key handlers to use/prioritize untranslated scancodes instead of + translated keycodes when dealing with OEM keys. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) + Not that only ImGuiKey value (NOT the characters used for text input) are affected. + - Win32, SDL2, SDL3: Use scancodes for OEM keys. + - GLFW: GLFW_KEY_WORLD_1 and GLFW_KEY_WORLD_2 are emitting ImGuiKey_Oem102. + - Fixes many cases of keys not emitting a ImGuiKey value with certain keyboad layouts. + - Makes emitted ImGuiKey values more consistent regardless of keyboard mapping. + - OEM keys are: ImGuiKey_Apostrophe, ImGuiKey_Comma, ImGuiKey_Minus, ImGuiKey_Period, + ImGuiKey_Slash, ImGuiKey_Semicolon, ImGuiKey_Equal, ImGuiKey_LeftBracket, + ImGuiKey_RightBracket, ImGuiKey_Backslash, ImGuiKey_GraveAccent, which are difficult + to find a reliable translated mapping on all keyboard layouts. - Backends: GLFW: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. (#8452) - Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn diff --git a/imgui.cpp b/imgui.cpp index 86b0d5d46b0d..26d055dd21ff 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8772,7 +8772,7 @@ ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key) return &g.IO.KeysData[key - ImGuiKey_NamedKey_BEGIN]; } -// Those names a provided for debugging purpose and are not meant to be saved persistently not compared. +// Those names are provided for debugging purpose and are not meant to be saved persistently nor compared. static const char* const GKeyNames[] = { "Tab", "LeftArrow", "RightArrow", "UpArrow", "DownArrow", "PageUp", "PageDown", @@ -8787,7 +8787,7 @@ static const char* const GKeyNames[] = "Pause", "Keypad0", "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "KeypadDecimal", "KeypadDivide", "KeypadMultiply", "KeypadSubtract", "KeypadAdd", "KeypadEnter", "KeypadEqual", - "AppBack", "AppForward", + "AppBack", "AppForward", "Oem102", "GamepadStart", "GamepadBack", "GamepadFaceLeft", "GamepadFaceRight", "GamepadFaceUp", "GamepadFaceDown", "GamepadDpadLeft", "GamepadDpadRight", "GamepadDpadUp", "GamepadDpadDown", diff --git a/imgui.h b/imgui.h index 4a14c82c28a1..7cecf064a289 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.9 WIP" -#define IMGUI_VERSION_NUM 19187 +#define IMGUI_VERSION_NUM 19188 #define IMGUI_HAS_TABLE /* @@ -975,7 +975,7 @@ namespace ImGui IMGUI_API bool IsKeyReleased(ImGuiKey key); // was key released (went from Down to !Down)? IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord); // was key chord (mods + key) pressed, e.g. you can pass 'ImGuiMod_Ctrl | ImGuiKey_S' as a key-chord. This doesn't do any routing or focus check, please consider using Shortcut() function instead. IMGUI_API int GetKeyPressedAmount(ImGuiKey key, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate - IMGUI_API const char* GetKeyName(ImGuiKey key); // [DEBUG] returns English name of the key. Those names a provided for debugging purpose and are not meant to be saved persistently not compared. + IMGUI_API const char* GetKeyName(ImGuiKey key); // [DEBUG] returns English name of the key. Those names are provided for debugging purpose and are not meant to be saved persistently nor compared. IMGUI_API void SetNextFrameWantCaptureKeyboard(bool want_capture_keyboard); // Override io.WantCaptureKeyboard flag next frame (said flag is left for your application to handle, typically when true it instructs your app to ignore inputs). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard"; after the next NewFrame() call. // Inputs Utilities: Shortcut Testing & Routing [BETA] @@ -1493,6 +1493,7 @@ enum ImGuiKey : int ImGuiKey_KeypadEqual, ImGuiKey_AppBack, // Available on some keyboard/mouses. Often referred as "Browser Back" ImGuiKey_AppForward, + ImGuiKey_Oem102, // Non-US backslash. // Gamepad (some of those are analog values, 0.0f to 1.0f) // NAVIGATION ACTION // (download controller mapping PNG/PSD at http://dearimgui.com/controls_sheets) From 39585aa90d43c26a12a0d754d16b407f0c1ca62d Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Mar 2025 18:13:45 +0100 Subject: [PATCH 528/548] Amend Changelog to talk about OEM keys. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) + more consistently use Ctrl+XXX instead of Ctrl-XXX. --- docs/CHANGELOG.txt | 20 +++++++++++--------- imgui.h | 2 +- imgui_widgets.cpp | 6 +++--- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 07a9801bc1cb..5975e9155305 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -123,16 +123,18 @@ Other changes: SDL_MAIN_USE_CALLBACKS feature. (#8455) - IO: Added ImGuiKey_Oem102 to ImGuiKey enum. (#7136, #7201, #7206, #7306, #8468) - Backends: reworked key handlers to use/prioritize untranslated scancodes instead of - translated keycodes when dealing with OEM keys. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) - Not that only ImGuiKey value (NOT the characters used for text input) are affected. + translated keycodes when dealing with OEM keys which are too difficult to find a reliable + translated mapping on all systems, backends and keyboard layout. + (#7136, #7201, #7206, #7306, #7670, #7672, #8468) + - The affected keys are: ImGuiKey_Apostrophe, ImGuiKey_Comma, ImGuiKey_Minus, ImGuiKey_Period, + ImGuiKey_Slash, ImGuiKey_Semicolon, ImGuiKey_Equal, ImGuiKey_LeftBracket, ImGuiKey_RightBracket, + ImGuiKey_Backslash, ImGuiKey_GraveAccent, and newly introduced ImGuiKey_Oem102. + - This is NOT affecting characters used the text inputs. + - Fixes many cases of keys not emitting a ImGuiKey value with certain keyboad layouts. + - Makes emitted ImGuiKey values more consistent regardless of keyboard mapping, + but you may be getting different values as before. - Win32, SDL2, SDL3: Use scancodes for OEM keys. - GLFW: GLFW_KEY_WORLD_1 and GLFW_KEY_WORLD_2 are emitting ImGuiKey_Oem102. - - Fixes many cases of keys not emitting a ImGuiKey value with certain keyboad layouts. - - Makes emitted ImGuiKey values more consistent regardless of keyboard mapping. - - OEM keys are: ImGuiKey_Apostrophe, ImGuiKey_Comma, ImGuiKey_Minus, ImGuiKey_Period, - ImGuiKey_Slash, ImGuiKey_Semicolon, ImGuiKey_Equal, ImGuiKey_LeftBracket, - ImGuiKey_RightBracket, ImGuiKey_Backslash, ImGuiKey_GraveAccent, which are difficult - to find a reliable translated mapping on all keyboard layouts. - Backends: GLFW: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. (#8452) - Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn @@ -2061,7 +2063,7 @@ Other changes: - Public API: PushTabStop(false) / PopTabStop() - Internal: PushItemFlag(ImGuiItemFlags_NoTabStop, true); - Internal: Directly pass ImGuiItemFlags_NoTabStop to ItemAdd() for custom widgets. -- Nav: Tabbing/Shift-Tabbing can more reliably be used to step out of an item that is not +- Nav: Tabbing/Shift+Tabbing can more reliably be used to step out of an item that is not tab-stoppable. (#3092, #5759, #787) - Nav: Made Enter key submit the same type of Activation event as Space key, allowing to press buttons with Enter. (#5606) diff --git a/imgui.h b/imgui.h index 7cecf064a289..429bb7480b58 100644 --- a/imgui.h +++ b/imgui.h @@ -2436,7 +2436,7 @@ struct ImGuiIO bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds. bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window. bool MouseWheelRequestAxisSwap; // On a non-Mac system, holding SHIFT requests WheelY to perform the equivalent of a WheelX event. On a Mac system this is already enforced by the system. - bool MouseCtrlLeftAsRightClick; // (OSX) Set to true when the current click was a ctrl-click that spawned a simulated right click + bool MouseCtrlLeftAsRightClick; // (OSX) Set to true when the current click was a Ctrl+click that spawned a simulated right click float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) float MouseDownDurationPrev[5]; // Previous time the mouse button has been down float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 9ecdbae8e610..fef30d273781 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2642,7 +2642,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); if (!temp_input_is_active) { - // Tabbing or CTRL-clicking on Drag turns it into an InputText + // Tabbing or CTRL+click on Drag turns it into an InputText const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id); const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2 && TestKeyOwner(ImGuiKey_MouseLeft, id)); const bool make_active = (clicked || double_clicked || g.NavActivateId == id); @@ -3246,7 +3246,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); if (!temp_input_is_active) { - // Tabbing or CTRL-clicking on Slider turns it into an input box + // Tabbing or CTRL+click on Slider turns it into an input box const bool clicked = hovered && IsMouseClicked(0, ImGuiInputFlags_None, id); const bool make_active = (clicked || g.NavActivateId == id); if (make_active && clicked) @@ -5495,7 +5495,7 @@ static void ColorEditRestoreHS(const float* col, float* H, float* S, float* V) // Edit colors components (each component in 0.0f..1.0f range). // See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. -// With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item. +// With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL+Click over input fields to edit them and TAB to go to next item. bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags) { ImGuiWindow* window = GetCurrentWindow(); From 51e4cba909e7a442eed3fcb1080c7d757ea031de Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 11 Mar 2025 12:05:23 +0100 Subject: [PATCH 529/548] Backends: Fixed zealous warnings. --- backends/imgui_impl_sdl2.cpp | 2 +- backends/imgui_impl_sdl3.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 33f7fed06a2f..0be2f2c6e360 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -192,7 +192,6 @@ static void ImGui_ImplSDL2_PlatformSetImeData(ImGuiContext*, ImGuiViewport*, ImG ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode); ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode scancode) { - IM_UNUSED(scancode); switch (keycode) { case SDLK_TAB: return ImGuiKey_Tab; @@ -332,6 +331,7 @@ ImGuiKey ImGui_ImplSDL2_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode sca case SDL_SCANCODE_COMMA: return ImGuiKey_Comma; case SDL_SCANCODE_PERIOD: return ImGuiKey_Period; case SDL_SCANCODE_SLASH: return ImGuiKey_Slash; + default: break; } return ImGuiKey_None; } diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 6720899ef23f..cfe8bbd4e8b1 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -313,6 +313,7 @@ ImGuiKey ImGui_ImplSDL3_KeyEventToImGuiKey(SDL_Keycode keycode, SDL_Scancode sca case SDL_SCANCODE_COMMA: return ImGuiKey_Comma; case SDL_SCANCODE_PERIOD: return ImGuiKey_Period; case SDL_SCANCODE_SLASH: return ImGuiKey_Slash; + default: break; } return ImGuiKey_None; } From 6da230636b4cb64aa8a30c9110c5a52862a5c2c0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 11 Mar 2025 12:20:33 +0100 Subject: [PATCH 530/548] Examples: Updated all .vcxproj from VS2015 to VS2019 (toolset v140 to v142), Windows SDK 8.1 to 10. --- docs/CHANGELOG.txt | 6 ++++++ examples/example_allegro5/example_allegro5.vcxproj | 10 +++++----- .../example_glfw_opengl2.vcxproj | 10 +++++----- .../example_glfw_opengl3.vcxproj | 10 +++++----- .../example_glfw_vulkan/example_glfw_vulkan.vcxproj | 10 +++++----- .../example_glut_opengl2.vcxproj | 10 +++++----- .../example_sdl2_directx11.vcxproj | 10 +++++----- .../example_sdl2_opengl2.vcxproj | 10 +++++----- .../example_sdl2_opengl3.vcxproj | 10 +++++----- .../example_sdl2_sdlrenderer2.vcxproj | 12 ++++++------ .../example_sdl2_vulkan/example_sdl2_vulkan.vcxproj | 12 ++++++------ .../example_sdl3_opengl3.vcxproj | 10 +++++----- .../example_sdl3_sdlgpu3.vcxproj | 12 ++++++------ .../example_sdl3_sdlrenderer3.vcxproj | 10 +++++----- .../example_sdl3_vulkan/example_sdl3_vulkan.vcxproj | 10 +++++----- .../example_win32_directx10.vcxproj | 10 +++++----- .../example_win32_directx11.vcxproj | 9 +++++---- .../example_win32_directx12.vcxproj | 10 +++++----- .../example_win32_directx9.vcxproj | 10 +++++----- .../example_win32_opengl3.vcxproj | 10 +++++----- .../example_win32_vulkan.vcxproj | 9 +++++---- 21 files changed, 109 insertions(+), 101 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5975e9155305..2a55e24131bd 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,6 +68,10 @@ Breaking changes: Other changes: +- This is the last release we are thoroughly testing with VS2015 + Windows SDK 8.1. + Example projects have been transitioned to VS2019 + Windows SDK 10. The library + as of today still compiles and works fine with VS2015, but onward we may break + support more often. - Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), RadioButton(), Selectable(). Regression from 2025/01/13. (#8370) - Windows: Fixed an issue where BeginChild() inside a collapsed Begin() @@ -121,6 +125,8 @@ Other changes: by showing the filter inside the combo contents. (#718) - Examples: SDL3: Added comments to clarify setup for users of the unfortunate SDL_MAIN_USE_CALLBACKS feature. (#8455) +- Examples: Updated all .vcxproj from VS2015 to VS2019 (toolset v140 to v142), + and from Windows SDK 8.1 to Windows SDK 10 ("latest" setting). - IO: Added ImGuiKey_Oem102 to ImGuiKey enum. (#7136, #7201, #7206, #7306, #8468) - Backends: reworked key handlers to use/prioritize untranslated scancodes instead of translated keycodes when dealing with OEM keys which are too difficult to find a reliable diff --git a/examples/example_allegro5/example_allegro5.vcxproj b/examples/example_allegro5/example_allegro5.vcxproj index 02f6a4741239..220095e78eca 100644 --- a/examples/example_allegro5/example_allegro5.vcxproj +++ b/examples/example_allegro5/example_allegro5.vcxproj @@ -21,34 +21,34 @@ {73F235B5-7D31-4FC6-8682-DDC5A097B9C1} example_allegro5 - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj b/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj index 2aa25506e2f3..6d373337c01c 100644 --- a/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj +++ b/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj @@ -21,34 +21,34 @@ {9CDA7840-B7A5-496D-A527-E95571496D18} example_glfw_opengl2 - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj b/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj index 4bd503afe335..40000775720f 100644 --- a/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj +++ b/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj @@ -21,34 +21,34 @@ {4a1fb5ea-22f5-42a8-ab92-1d2df5d47fb9} example_glfw_opengl3 - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj b/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj index a81d328df976..d2ff07e9b9f2 100644 --- a/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj +++ b/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj @@ -21,34 +21,34 @@ {57E2DF5A-6FC8-45BB-99DD-91A18C646E80} example_glfw_vulkan - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_glut_opengl2/example_glut_opengl2.vcxproj b/examples/example_glut_opengl2/example_glut_opengl2.vcxproj index c56452b26c5a..5c773c8188e6 100644 --- a/examples/example_glut_opengl2/example_glut_opengl2.vcxproj +++ b/examples/example_glut_opengl2/example_glut_opengl2.vcxproj @@ -21,34 +21,34 @@ {F90D0333-5FB1-440D-918D-DD39A1B5187E} example_glut_opengl2 - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj b/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj index c23800c9e4a4..5a8daf1bd3c9 100644 --- a/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj +++ b/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj @@ -21,7 +21,7 @@ {9E1987E3-1F19-45CA-B9C9-D31E791836D8} example_sdl2_directx11 - 8.1 + 10.0 example_sdl2_directx11 @@ -29,27 +29,27 @@ Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj b/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj index 036463f96bf1..b033c322f542 100644 --- a/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj +++ b/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj @@ -21,34 +21,34 @@ {2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741} example_sdl2_opengl2 - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj b/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj index 6a81c67704bc..faf5874b3181 100644 --- a/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj +++ b/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj @@ -21,34 +21,34 @@ {BBAEB705-1669-40F3-8567-04CF6A991F4C} example_sdl2_opengl3 - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj b/examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj index cf2c890bba17..7d3cd4eb5178 100644 --- a/examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj +++ b/examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj @@ -21,7 +21,7 @@ {0C0B2BEA-311F-473C-9652-87923EF639E3} example_sdl2_sdlrenderer2 - 8.1 + 10.0 example_sdl2_sdlrenderer2 @@ -29,27 +29,27 @@ Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 @@ -184,4 +184,4 @@ - + \ No newline at end of file diff --git a/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj b/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj index bcf99a46c002..07a60ac7239a 100644 --- a/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj +++ b/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj @@ -21,34 +21,34 @@ {BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3} example_sdl2_vulkan - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 @@ -187,4 +187,4 @@ - + \ No newline at end of file diff --git a/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj b/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj index 051f87d764fc..2f14fdf80a48 100644 --- a/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj +++ b/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj @@ -21,34 +21,34 @@ {84AAA301-84FE-428B-9E3E-817BC8123C0C} example_sdl3_opengl3 - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj b/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj index 3d034f52c0a5..01a38f336701 100644 --- a/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj +++ b/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj @@ -21,34 +21,34 @@ {c22cb6f8-39a5-4dda-90ed-4aca4e81e1e5} example_sdl3_sdlgpu3 - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 @@ -186,4 +186,4 @@ - + \ No newline at end of file diff --git a/examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj b/examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj index 8b71324cc750..4793e537c5a8 100644 --- a/examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj +++ b/examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj @@ -21,34 +21,34 @@ {C0290D21-3AD2-4A35-ABBC-A2F5F48326DA} example_sdl3_opengl3 - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj b/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj index d48e4aff3051..29437778450b 100644 --- a/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj +++ b/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj @@ -21,34 +21,34 @@ {663A7E89-1E42-4222-921C-177F5B5910DF} example_sdl3_vulkan - 8.1 + 10.0 Application true MultiByte - v140 + v142 Application true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 Application false true MultiByte - v140 + v142 diff --git a/examples/example_win32_directx10/example_win32_directx10.vcxproj b/examples/example_win32_directx10/example_win32_directx10.vcxproj index d11aed88387a..8fe6d10b5622 100644 --- a/examples/example_win32_directx10/example_win32_directx10.vcxproj +++ b/examples/example_win32_directx10/example_win32_directx10.vcxproj @@ -21,34 +21,34 @@ {345A953E-A004-4648-B442-DC5F9F11068C} example_win32_directx10 - 8.1 + 10.0 Application true Unicode - v140 + v142 Application true Unicode - v140 + v142 Application false true Unicode - v140 + v142 Application false true Unicode - v140 + v142 diff --git a/examples/example_win32_directx11/example_win32_directx11.vcxproj b/examples/example_win32_directx11/example_win32_directx11.vcxproj index bace6a2c8361..79cdbaea7a0a 100644 --- a/examples/example_win32_directx11/example_win32_directx11.vcxproj +++ b/examples/example_win32_directx11/example_win32_directx11.vcxproj @@ -21,33 +21,34 @@ {9F316E83-5AE5-4939-A723-305A94F48005} example_win32_directx11 + 10.0 Application true Unicode - v140 + v142 Application true Unicode - v140 + v142 Application false true Unicode - v140 + v142 Application false true Unicode - v140 + v142 diff --git a/examples/example_win32_directx12/example_win32_directx12.vcxproj b/examples/example_win32_directx12/example_win32_directx12.vcxproj index bb98c4141ca1..c4b81e76f5fc 100644 --- a/examples/example_win32_directx12/example_win32_directx12.vcxproj +++ b/examples/example_win32_directx12/example_win32_directx12.vcxproj @@ -21,34 +21,34 @@ {b4cf9797-519d-4afe-a8f4-5141a6b521d3} example_win32_directx12 - 10.0.20348.0 + 10.0 Application true Unicode - v140 + v142 Application true Unicode - v140 + v142 Application false true Unicode - v140 + v142 Application false true Unicode - v140 + v142 diff --git a/examples/example_win32_directx9/example_win32_directx9.vcxproj b/examples/example_win32_directx9/example_win32_directx9.vcxproj index 8c3f99589bb0..346ec1efcc7f 100644 --- a/examples/example_win32_directx9/example_win32_directx9.vcxproj +++ b/examples/example_win32_directx9/example_win32_directx9.vcxproj @@ -21,34 +21,34 @@ {4165A294-21F2-44CA-9B38-E3F935ABADF5} example_win32_directx9 - 8.1 + 10.0 Application true Unicode - v140 + v142 Application true Unicode - v140 + v142 Application false true Unicode - v140 + v142 Application false true Unicode - v140 + v142 diff --git a/examples/example_win32_opengl3/example_win32_opengl3.vcxproj b/examples/example_win32_opengl3/example_win32_opengl3.vcxproj index 98fc38fd34d9..9848d62c66d9 100644 --- a/examples/example_win32_opengl3/example_win32_opengl3.vcxproj +++ b/examples/example_win32_opengl3/example_win32_opengl3.vcxproj @@ -21,34 +21,34 @@ {C624E5FF-D4FE-4D35-9164-B8A91864F98E} example_win32_opengl2 - 8.1 + 10.0 Application true Unicode - v140 + v142 Application true Unicode - v140 + v142 Application false true Unicode - v140 + v142 Application false true Unicode - v140 + v142 diff --git a/examples/example_win32_vulkan/example_win32_vulkan.vcxproj b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj index dab8afd4ed71..604f8a817137 100644 --- a/examples/example_win32_vulkan/example_win32_vulkan.vcxproj +++ b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj @@ -21,33 +21,34 @@ {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88} example_win32_directx11 + 10.0 Application true Unicode - v140 + v142 Application true Unicode - v140 + v142 Application false true Unicode - v140 + v142 Application false true Unicode - v140 + v142 From 557c77e4556a776058c099881f4b32d5416b27c6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 11 Mar 2025 18:38:45 +0100 Subject: [PATCH 531/548] Added ImGuiKey_AbntC1, ImGuiKey_AbntC2 + Backends: GLFW, Win32: added support. (#8468) --- backends/imgui_impl_glfw.cpp | 12 +++++++++--- backends/imgui_impl_win32.cpp | 6 ++++-- docs/CHANGELOG.txt | 4 +++- imgui.cpp | 2 +- imgui.h | 2 ++ 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index baa8541b0af0..d4629493261e 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -28,7 +28,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2025-03-10: Map GLFW_KEY_WORLD_1 and GLFW_KEY_WORLD_2 into ImGuiKey_Oem102. +// 2025-03-11: Added support for ImGuiKey_Oem102, ImGuiKey_AbntC1, ImGuiKey_AbntC2. // 2025-03-03: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. // 2024-08-22: Moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: // - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn @@ -195,7 +195,6 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode); ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode) { - IM_UNUSED(scancode); switch (keycode) { case GLFW_KEY_TAB: return ImGuiKey_Tab; @@ -317,8 +316,15 @@ ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode) case GLFW_KEY_F22: return ImGuiKey_F22; case GLFW_KEY_F23: return ImGuiKey_F23; case GLFW_KEY_F24: return ImGuiKey_F24; - default: return ImGuiKey_None; + default: break; + } + switch (scancode) + { + case 115: return ImGuiKey_AbntC1; + case 126: return ImGuiKey_AbntC2; + default: break; } + return ImGuiKey_None; } // X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 2c749515d221..da007c1d83ed 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -21,7 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) +// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) + Added support for ImGuiKey_Oem102, ImGuiKey_AbntC1, ImGuiKey_AbntC2. // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768) // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. @@ -565,13 +565,15 @@ ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam) case 13: return ImGuiKey_Equal; case 26: return ImGuiKey_LeftBracket; case 27: return ImGuiKey_RightBracket; - case 86: return ImGuiKey_Oem102; case 43: return ImGuiKey_Backslash; case 39: return ImGuiKey_Semicolon; case 40: return ImGuiKey_Apostrophe; case 51: return ImGuiKey_Comma; case 52: return ImGuiKey_Period; case 53: return ImGuiKey_Slash; + case 86: return ImGuiKey_Oem102; + case 115: return ImGuiKey_AbntC1; + case 126: return ImGuiKey_AbntC2; } return ImGuiKey_None; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2a55e24131bd..f5ce04a88f40 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -128,6 +128,7 @@ Other changes: - Examples: Updated all .vcxproj from VS2015 to VS2019 (toolset v140 to v142), and from Windows SDK 8.1 to Windows SDK 10 ("latest" setting). - IO: Added ImGuiKey_Oem102 to ImGuiKey enum. (#7136, #7201, #7206, #7306, #8468) +- IO: Added ImGuiKey_AbntC1, ImGuiKey_AbntC2 to ImGuiKey enum. (#8468) - Backends: reworked key handlers to use/prioritize untranslated scancodes instead of translated keycodes when dealing with OEM keys which are too difficult to find a reliable translated mapping on all systems, backends and keyboard layout. @@ -139,7 +140,8 @@ Other changes: - Fixes many cases of keys not emitting a ImGuiKey value with certain keyboad layouts. - Makes emitted ImGuiKey values more consistent regardless of keyboard mapping, but you may be getting different values as before. - - Win32, SDL2, SDL3: Use scancodes for OEM keys. + - Win32: Use scancodes for OEM keys. Added support for the 3 new keys. + - SDL2, SDL3: Use scancodes for OEM keys. Added support for the Oem102 new key. - GLFW: GLFW_KEY_WORLD_1 and GLFW_KEY_WORLD_2 are emitting ImGuiKey_Oem102. - Backends: GLFW: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. (#8452) diff --git a/imgui.cpp b/imgui.cpp index 26d055dd21ff..ae81cc64acd9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8787,7 +8787,7 @@ static const char* const GKeyNames[] = "Pause", "Keypad0", "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "KeypadDecimal", "KeypadDivide", "KeypadMultiply", "KeypadSubtract", "KeypadAdd", "KeypadEnter", "KeypadEqual", - "AppBack", "AppForward", "Oem102", + "AppBack", "AppForward", "Oem102", "AbntC1", "AbntC2", "GamepadStart", "GamepadBack", "GamepadFaceLeft", "GamepadFaceRight", "GamepadFaceUp", "GamepadFaceDown", "GamepadDpadLeft", "GamepadDpadRight", "GamepadDpadUp", "GamepadDpadDown", diff --git a/imgui.h b/imgui.h index 429bb7480b58..512e9a6c7298 100644 --- a/imgui.h +++ b/imgui.h @@ -1494,6 +1494,8 @@ enum ImGuiKey : int ImGuiKey_AppBack, // Available on some keyboard/mouses. Often referred as "Browser Back" ImGuiKey_AppForward, ImGuiKey_Oem102, // Non-US backslash. + ImGuiKey_AbntC1, // Brazil ABNT extra keys + ImGuiKey_AbntC2, // Gamepad (some of those are analog values, 0.0f to 1.0f) // NAVIGATION ACTION // (download controller mapping PNG/PSD at http://dearimgui.com/controls_sheets) From 09654f4e8caae1ae2c25f246e007ec0fd97eb6b8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 11 Mar 2025 18:42:12 +0100 Subject: [PATCH 532/548] Revert "Examples: Updated all .vcxproj from VS2015 to VS2019 (toolset v140 to v142), Windows SDK 8.1 to 10." This reverts commit 6da230636b4cb64aa8a30c9110c5a52862a5c2c0. --- docs/CHANGELOG.txt | 6 ------ examples/example_allegro5/example_allegro5.vcxproj | 10 +++++----- .../example_glfw_opengl2.vcxproj | 10 +++++----- .../example_glfw_opengl3.vcxproj | 10 +++++----- .../example_glfw_vulkan/example_glfw_vulkan.vcxproj | 10 +++++----- .../example_glut_opengl2.vcxproj | 10 +++++----- .../example_sdl2_directx11.vcxproj | 10 +++++----- .../example_sdl2_opengl2.vcxproj | 10 +++++----- .../example_sdl2_opengl3.vcxproj | 10 +++++----- .../example_sdl2_sdlrenderer2.vcxproj | 12 ++++++------ .../example_sdl2_vulkan/example_sdl2_vulkan.vcxproj | 12 ++++++------ .../example_sdl3_opengl3.vcxproj | 10 +++++----- .../example_sdl3_sdlgpu3.vcxproj | 12 ++++++------ .../example_sdl3_sdlrenderer3.vcxproj | 10 +++++----- .../example_sdl3_vulkan/example_sdl3_vulkan.vcxproj | 10 +++++----- .../example_win32_directx10.vcxproj | 10 +++++----- .../example_win32_directx11.vcxproj | 9 ++++----- .../example_win32_directx12.vcxproj | 10 +++++----- .../example_win32_directx9.vcxproj | 10 +++++----- .../example_win32_opengl3.vcxproj | 10 +++++----- .../example_win32_vulkan.vcxproj | 9 ++++----- 21 files changed, 101 insertions(+), 109 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f5ce04a88f40..cc5964f073e9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,10 +68,6 @@ Breaking changes: Other changes: -- This is the last release we are thoroughly testing with VS2015 + Windows SDK 8.1. - Example projects have been transitioned to VS2019 + Windows SDK 10. The library - as of today still compiles and works fine with VS2015, but onward we may break - support more often. - Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), RadioButton(), Selectable(). Regression from 2025/01/13. (#8370) - Windows: Fixed an issue where BeginChild() inside a collapsed Begin() @@ -125,8 +121,6 @@ Other changes: by showing the filter inside the combo contents. (#718) - Examples: SDL3: Added comments to clarify setup for users of the unfortunate SDL_MAIN_USE_CALLBACKS feature. (#8455) -- Examples: Updated all .vcxproj from VS2015 to VS2019 (toolset v140 to v142), - and from Windows SDK 8.1 to Windows SDK 10 ("latest" setting). - IO: Added ImGuiKey_Oem102 to ImGuiKey enum. (#7136, #7201, #7206, #7306, #8468) - IO: Added ImGuiKey_AbntC1, ImGuiKey_AbntC2 to ImGuiKey enum. (#8468) - Backends: reworked key handlers to use/prioritize untranslated scancodes instead of diff --git a/examples/example_allegro5/example_allegro5.vcxproj b/examples/example_allegro5/example_allegro5.vcxproj index 220095e78eca..02f6a4741239 100644 --- a/examples/example_allegro5/example_allegro5.vcxproj +++ b/examples/example_allegro5/example_allegro5.vcxproj @@ -21,34 +21,34 @@ {73F235B5-7D31-4FC6-8682-DDC5A097B9C1} example_allegro5 - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj b/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj index 6d373337c01c..2aa25506e2f3 100644 --- a/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj +++ b/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj @@ -21,34 +21,34 @@ {9CDA7840-B7A5-496D-A527-E95571496D18} example_glfw_opengl2 - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj b/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj index 40000775720f..4bd503afe335 100644 --- a/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj +++ b/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj @@ -21,34 +21,34 @@ {4a1fb5ea-22f5-42a8-ab92-1d2df5d47fb9} example_glfw_opengl3 - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj b/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj index d2ff07e9b9f2..a81d328df976 100644 --- a/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj +++ b/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj @@ -21,34 +21,34 @@ {57E2DF5A-6FC8-45BB-99DD-91A18C646E80} example_glfw_vulkan - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_glut_opengl2/example_glut_opengl2.vcxproj b/examples/example_glut_opengl2/example_glut_opengl2.vcxproj index 5c773c8188e6..c56452b26c5a 100644 --- a/examples/example_glut_opengl2/example_glut_opengl2.vcxproj +++ b/examples/example_glut_opengl2/example_glut_opengl2.vcxproj @@ -21,34 +21,34 @@ {F90D0333-5FB1-440D-918D-DD39A1B5187E} example_glut_opengl2 - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj b/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj index 5a8daf1bd3c9..c23800c9e4a4 100644 --- a/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj +++ b/examples/example_sdl2_directx11/example_sdl2_directx11.vcxproj @@ -21,7 +21,7 @@ {9E1987E3-1F19-45CA-B9C9-D31E791836D8} example_sdl2_directx11 - 10.0 + 8.1 example_sdl2_directx11 @@ -29,27 +29,27 @@ Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj b/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj index b033c322f542..036463f96bf1 100644 --- a/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj +++ b/examples/example_sdl2_opengl2/example_sdl2_opengl2.vcxproj @@ -21,34 +21,34 @@ {2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741} example_sdl2_opengl2 - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj b/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj index faf5874b3181..6a81c67704bc 100644 --- a/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj +++ b/examples/example_sdl2_opengl3/example_sdl2_opengl3.vcxproj @@ -21,34 +21,34 @@ {BBAEB705-1669-40F3-8567-04CF6A991F4C} example_sdl2_opengl3 - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj b/examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj index 7d3cd4eb5178..cf2c890bba17 100644 --- a/examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj +++ b/examples/example_sdl2_sdlrenderer2/example_sdl2_sdlrenderer2.vcxproj @@ -21,7 +21,7 @@ {0C0B2BEA-311F-473C-9652-87923EF639E3} example_sdl2_sdlrenderer2 - 10.0 + 8.1 example_sdl2_sdlrenderer2 @@ -29,27 +29,27 @@ Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 @@ -184,4 +184,4 @@ - \ No newline at end of file + diff --git a/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj b/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj index 07a60ac7239a..bcf99a46c002 100644 --- a/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj +++ b/examples/example_sdl2_vulkan/example_sdl2_vulkan.vcxproj @@ -21,34 +21,34 @@ {BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3} example_sdl2_vulkan - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 @@ -187,4 +187,4 @@ - \ No newline at end of file + diff --git a/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj b/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj index 2f14fdf80a48..051f87d764fc 100644 --- a/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj +++ b/examples/example_sdl3_opengl3/example_sdl3_opengl3.vcxproj @@ -21,34 +21,34 @@ {84AAA301-84FE-428B-9E3E-817BC8123C0C} example_sdl3_opengl3 - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj b/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj index 01a38f336701..3d034f52c0a5 100644 --- a/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj +++ b/examples/example_sdl3_sdlgpu3/example_sdl3_sdlgpu3.vcxproj @@ -21,34 +21,34 @@ {c22cb6f8-39a5-4dda-90ed-4aca4e81e1e5} example_sdl3_sdlgpu3 - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 @@ -186,4 +186,4 @@ - \ No newline at end of file + diff --git a/examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj b/examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj index 4793e537c5a8..8b71324cc750 100644 --- a/examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj +++ b/examples/example_sdl3_sdlrenderer3/example_sdl3_sdlrenderer3.vcxproj @@ -21,34 +21,34 @@ {C0290D21-3AD2-4A35-ABBC-A2F5F48326DA} example_sdl3_opengl3 - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj b/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj index 29437778450b..d48e4aff3051 100644 --- a/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj +++ b/examples/example_sdl3_vulkan/example_sdl3_vulkan.vcxproj @@ -21,34 +21,34 @@ {663A7E89-1E42-4222-921C-177F5B5910DF} example_sdl3_vulkan - 10.0 + 8.1 Application true MultiByte - v142 + v140 Application true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 Application false true MultiByte - v142 + v140 diff --git a/examples/example_win32_directx10/example_win32_directx10.vcxproj b/examples/example_win32_directx10/example_win32_directx10.vcxproj index 8fe6d10b5622..d11aed88387a 100644 --- a/examples/example_win32_directx10/example_win32_directx10.vcxproj +++ b/examples/example_win32_directx10/example_win32_directx10.vcxproj @@ -21,34 +21,34 @@ {345A953E-A004-4648-B442-DC5F9F11068C} example_win32_directx10 - 10.0 + 8.1 Application true Unicode - v142 + v140 Application true Unicode - v142 + v140 Application false true Unicode - v142 + v140 Application false true Unicode - v142 + v140 diff --git a/examples/example_win32_directx11/example_win32_directx11.vcxproj b/examples/example_win32_directx11/example_win32_directx11.vcxproj index 79cdbaea7a0a..bace6a2c8361 100644 --- a/examples/example_win32_directx11/example_win32_directx11.vcxproj +++ b/examples/example_win32_directx11/example_win32_directx11.vcxproj @@ -21,34 +21,33 @@ {9F316E83-5AE5-4939-A723-305A94F48005} example_win32_directx11 - 10.0 Application true Unicode - v142 + v140 Application true Unicode - v142 + v140 Application false true Unicode - v142 + v140 Application false true Unicode - v142 + v140 diff --git a/examples/example_win32_directx12/example_win32_directx12.vcxproj b/examples/example_win32_directx12/example_win32_directx12.vcxproj index c4b81e76f5fc..bb98c4141ca1 100644 --- a/examples/example_win32_directx12/example_win32_directx12.vcxproj +++ b/examples/example_win32_directx12/example_win32_directx12.vcxproj @@ -21,34 +21,34 @@ {b4cf9797-519d-4afe-a8f4-5141a6b521d3} example_win32_directx12 - 10.0 + 10.0.20348.0 Application true Unicode - v142 + v140 Application true Unicode - v142 + v140 Application false true Unicode - v142 + v140 Application false true Unicode - v142 + v140 diff --git a/examples/example_win32_directx9/example_win32_directx9.vcxproj b/examples/example_win32_directx9/example_win32_directx9.vcxproj index 346ec1efcc7f..8c3f99589bb0 100644 --- a/examples/example_win32_directx9/example_win32_directx9.vcxproj +++ b/examples/example_win32_directx9/example_win32_directx9.vcxproj @@ -21,34 +21,34 @@ {4165A294-21F2-44CA-9B38-E3F935ABADF5} example_win32_directx9 - 10.0 + 8.1 Application true Unicode - v142 + v140 Application true Unicode - v142 + v140 Application false true Unicode - v142 + v140 Application false true Unicode - v142 + v140 diff --git a/examples/example_win32_opengl3/example_win32_opengl3.vcxproj b/examples/example_win32_opengl3/example_win32_opengl3.vcxproj index 9848d62c66d9..98fc38fd34d9 100644 --- a/examples/example_win32_opengl3/example_win32_opengl3.vcxproj +++ b/examples/example_win32_opengl3/example_win32_opengl3.vcxproj @@ -21,34 +21,34 @@ {C624E5FF-D4FE-4D35-9164-B8A91864F98E} example_win32_opengl2 - 10.0 + 8.1 Application true Unicode - v142 + v140 Application true Unicode - v142 + v140 Application false true Unicode - v142 + v140 Application false true Unicode - v142 + v140 diff --git a/examples/example_win32_vulkan/example_win32_vulkan.vcxproj b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj index 604f8a817137..dab8afd4ed71 100644 --- a/examples/example_win32_vulkan/example_win32_vulkan.vcxproj +++ b/examples/example_win32_vulkan/example_win32_vulkan.vcxproj @@ -21,34 +21,33 @@ {0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88} example_win32_directx11 - 10.0 Application true Unicode - v142 + v140 Application true Unicode - v142 + v140 Application false true Unicode - v142 + v140 Application false true Unicode - v142 + v140 From de4f77b0ac9a41fa4a77ffc5d3a2c4a106880068 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Mar 2025 15:47:37 +0100 Subject: [PATCH 533/548] Backends: DX12: comment about using SrvDescriptorAllocFn/SrvDescriptorFreeFn. Amend 40b2286d16e92ea017347a62cb91e63f378ff455 --- backends/imgui_impl_dx12.cpp | 2 +- backends/imgui_impl_dx12.h | 2 +- examples/example_win32_directx12/main.cpp | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index e9a2c119c4b6..202bac3b09d9 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -748,7 +748,7 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info) init_info->SrvDescriptorAllocFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_handle) { ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData(); - IM_ASSERT(bd->LegacySingleDescriptorUsed == false); + IM_ASSERT(bd->LegacySingleDescriptorUsed == false && "Only 1 simultaneous texture allowed with legacy ImGui_ImplDX12_Init() signature!"); *out_cpu_handle = bd->InitInfo.LegacySingleSrvCpuDescriptor; *out_gpu_handle = bd->InitInfo.LegacySingleSrvGpuDescriptor; bd->LegacySingleDescriptorUsed = true; diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h index 736e9f5c2e3e..a79de7b13565 100644 --- a/backends/imgui_impl_dx12.h +++ b/backends/imgui_impl_dx12.h @@ -34,7 +34,7 @@ struct ImGui_ImplDX12_InitInfo void* UserData; // Allocating SRV descriptors for textures is up to the application, so we provide callbacks. - // (current version of the backend will only allocate one descriptor, future versions will need to allocate more) + // (current version of the backend will only allocate one descriptor, from 1.92 the backend will need to allocate more) ID3D12DescriptorHeap* SrvDescriptorHeap; void (*SrvDescriptorAllocFn)(ImGui_ImplDX12_InitInfo* info, D3D12_CPU_DESCRIPTOR_HANDLE* out_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE* out_gpu_desc_handle); void (*SrvDescriptorFreeFn)(ImGui_ImplDX12_InitInfo* info, D3D12_CPU_DESCRIPTOR_HANDLE cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE gpu_desc_handle); diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index e83ce7dcbbc9..5f6cd51dd845 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -154,6 +154,9 @@ int main(int, char**) init_info.SrvDescriptorFreeFn = [](ImGui_ImplDX12_InitInfo*, D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle, D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle) { return g_pd3dSrvDescHeapAlloc.Free(cpu_handle, gpu_handle); }; ImGui_ImplDX12_Init(&init_info); + // Before 1.91.6: our signature was using a single descriptor. From 1.92, specifying SrvDescriptorAllocFn/SrvDescriptorFreeFn will be required to benefit from new features. + //ImGui_ImplDX12_Init(g_pd3dDevice, APP_NUM_FRAMES_IN_FLIGHT, DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap, g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. From 6e30c4210181aebb6137f6c10fdfc572ea1202f2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Mar 2025 19:29:41 +0100 Subject: [PATCH 534/548] Tables: fixed an issue with TableSetupColumn() overriding ini data. (#7934) Amend 05742f9b6f --- imgui_tables.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index bc5862ee3703..5464ba688f28 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1637,7 +1637,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo if (table->IsInitializing) { ImGuiTableFlags init_flags = ~0; - if (column->WidthRequest >= 0.0f && column->StretchWeight >= 0.0f) + if (column->WidthRequest >= 0.0f || column->StretchWeight >= 0.0f) init_flags &= ~ImGuiTableFlags_Resizable; TableInitColumnDefaults(table, column, init_flags); } From d9dad2f4a15aa49c7464b9b3eef2588f14437e22 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Mar 2025 14:15:51 +0100 Subject: [PATCH 535/548] Scrollbar: stabilize visibility of ScrollbarX when detecting a feedback loop. (#8488, #3285, #4539) --- docs/CHANGELOG.txt | 8 ++++++++ imgui.cpp | 14 ++++++++++++++ imgui_internal.h | 9 ++++++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cc5964f073e9..bbf9255c34d8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -82,6 +82,14 @@ Other changes: visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut] - Scrollbar: Rework logic that fades-out scrollbar when it becomes too small, which amusingly made it disappear when using very big font/frame size. +- Scrollbar: Automatically stabilize ScrollbarX visibility when detecting a + feedback loop manifesting with ScrollbarX visibility toggling on and off + repeatedly. (#8488, #3285, #4539) + (feedback loops of this sort can manifest in various situations, but combining + horizontal + vertical scrollbar + using a clipper with varying width items is + one frequent cause. The better solution is to, either: (1) enforce visibility + by using ImGuiWindowFlags_AlwaysHorizontalScrollbar or (2) declare stable + contents width with SetNextWindowContentSize(), if you can compute it.) - Tables: fixed calling SetNextWindowScroll() on clipped scrolling table to not leak the value into a subsequent window. (#8196) - Tables: fixed an issue where Columns Visible/Width state wouldn't be correctly diff --git a/imgui.cpp b/imgui.cpp index ae81cc64acd9..093ba637528d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7456,9 +7456,23 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f; float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x; float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y; + bool scrollbar_x_prev = window->ScrollbarX; //bool scrollbar_y_from_last_frame = window->ScrollbarY; // FIXME: May want to use that in the ScrollbarX expression? How many pros vs cons? window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar)); window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + + // Track when ScrollbarX visibility keeps toggling, which is a sign of a feedback loop, and stabilize by enforcing visibility (#3285, #8488) + // (Feedback loops of this sort can manifest in various situations, but combining horizontal + vertical scrollbar + using a clipper with varying width items is one frequent cause. + // The better solution is to, either (1) enforce visibility by using ImGuiWindowFlags_AlwaysHorizontalScrollbar or (2) declare stable contents width with SetNextWindowContentSize(), if you can compute it) + window->ScrollbarXStabilizeToggledHistory <<= 1; + window->ScrollbarXStabilizeToggledHistory |= (scrollbar_x_prev != window->ScrollbarX) ? 0x01 : 0x00; + const bool scrollbar_x_stabilize = (window->ScrollbarXStabilizeToggledHistory != 0) && ImCountSetBits(window->ScrollbarXStabilizeToggledHistory) >= 4; // 4 == half of bits in our U8 history. + if (scrollbar_x_stabilize) + window->ScrollbarX = true; + //if (scrollbar_x_stabilize && !window->ScrollbarXStabilizeEnabled) + // IMGUI_DEBUG_LOG("[scroll] Stabilize ScrollbarX for Window '%s'\n", window->Name); + window->ScrollbarXStabilizeEnabled = scrollbar_x_stabilize; + if (window->ScrollbarX && !window->ScrollbarY) window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); diff --git a/imgui_internal.h b/imgui_internal.h index aaa2027df944..6d9120a9e007 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -367,9 +367,10 @@ static inline void ImQsort(void* base, size_t count, size_t size_of_element IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b); // Helpers: Bit manipulation -static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; } -static inline bool ImIsPowerOfTwo(ImU64 v) { return v != 0 && (v & (v - 1)) == 0; } -static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } +static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; } +static inline bool ImIsPowerOfTwo(ImU64 v) { return v != 0 && (v & (v - 1)) == 0; } +static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } +static inline unsigned int ImCountSetBits(unsigned int v) { unsigned int count = 0; while (v > 0) { v = v & (v - 1); count++; } return count; } // Helpers: String #define ImStrlen strlen @@ -2514,6 +2515,8 @@ struct IMGUI_API ImGuiWindow ImVec2 ScrollTargetEdgeSnapDist; // 0.0f = no snapping, >0.0f snapping threshold ImVec2 ScrollbarSizes; // Size taken by each scrollbars on their smaller axis. Pay attention! ScrollbarSizes.x == width of the vertical scrollbar, ScrollbarSizes.y = height of the horizontal scrollbar. bool ScrollbarX, ScrollbarY; // Are scrollbars visible? + bool ScrollbarXStabilizeEnabled; // Was ScrollbarX previously auto-stabilized? + ImU8 ScrollbarXStabilizeToggledHistory; // Used to stabilize scrollbar visibility in case of feedback loops bool Active; // Set to true on Begin(), unless Collapsed bool WasActive; bool WriteAccessed; // Set to true when any widget access the current window From 79bba34c5f453640bf6f4a17741ad2e3e7b5abfe Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 13 Mar 2025 16:32:50 +0100 Subject: [PATCH 536/548] Revert "Added ImGuiKey_AbntC1, ImGuiKey_AbntC2 + Backends: GLFW, Win32: added support. (#8468)" This reverts commit 557c77e4556a776058c099881f4b32d5416b27c6. --- backends/imgui_impl_glfw.cpp | 12 +++--------- backends/imgui_impl_win32.cpp | 6 ++---- docs/CHANGELOG.txt | 4 +--- imgui.cpp | 2 +- imgui.h | 2 -- 5 files changed, 7 insertions(+), 19 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index d4629493261e..baa8541b0af0 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -28,7 +28,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2025-03-11: Added support for ImGuiKey_Oem102, ImGuiKey_AbntC1, ImGuiKey_AbntC2. +// 2025-03-10: Map GLFW_KEY_WORLD_1 and GLFW_KEY_WORLD_2 into ImGuiKey_Oem102. // 2025-03-03: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. // 2024-08-22: Moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: // - io.GetClipboardTextFn -> platform_io.Platform_GetClipboardTextFn @@ -195,6 +195,7 @@ static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode); ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode) { + IM_UNUSED(scancode); switch (keycode) { case GLFW_KEY_TAB: return ImGuiKey_Tab; @@ -316,15 +317,8 @@ ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int keycode, int scancode) case GLFW_KEY_F22: return ImGuiKey_F22; case GLFW_KEY_F23: return ImGuiKey_F23; case GLFW_KEY_F24: return ImGuiKey_F24; - default: break; - } - switch (scancode) - { - case 115: return ImGuiKey_AbntC1; - case 126: return ImGuiKey_AbntC2; - default: break; + default: return ImGuiKey_None; } - return ImGuiKey_None; } // X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index da007c1d83ed..2c749515d221 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -21,7 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) + Added support for ImGuiKey_Oem102, ImGuiKey_AbntC1, ImGuiKey_AbntC2. +// 2025-03-10: When dealing with OEM keys, use scancodes instead of translated keycodes to choose ImGuiKey values. (#7136, #7201, #7206, #7306, #7670, #7672, #8468) // 2025-02-18: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursor support. // 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768) // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. @@ -565,15 +565,13 @@ ImGuiKey ImGui_ImplWin32_KeyEventToImGuiKey(WPARAM wParam, LPARAM lParam) case 13: return ImGuiKey_Equal; case 26: return ImGuiKey_LeftBracket; case 27: return ImGuiKey_RightBracket; + case 86: return ImGuiKey_Oem102; case 43: return ImGuiKey_Backslash; case 39: return ImGuiKey_Semicolon; case 40: return ImGuiKey_Apostrophe; case 51: return ImGuiKey_Comma; case 52: return ImGuiKey_Period; case 53: return ImGuiKey_Slash; - case 86: return ImGuiKey_Oem102; - case 115: return ImGuiKey_AbntC1; - case 126: return ImGuiKey_AbntC2; } return ImGuiKey_None; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bbf9255c34d8..f184ddc8f785 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -130,7 +130,6 @@ Other changes: - Examples: SDL3: Added comments to clarify setup for users of the unfortunate SDL_MAIN_USE_CALLBACKS feature. (#8455) - IO: Added ImGuiKey_Oem102 to ImGuiKey enum. (#7136, #7201, #7206, #7306, #8468) -- IO: Added ImGuiKey_AbntC1, ImGuiKey_AbntC2 to ImGuiKey enum. (#8468) - Backends: reworked key handlers to use/prioritize untranslated scancodes instead of translated keycodes when dealing with OEM keys which are too difficult to find a reliable translated mapping on all systems, backends and keyboard layout. @@ -142,8 +141,7 @@ Other changes: - Fixes many cases of keys not emitting a ImGuiKey value with certain keyboad layouts. - Makes emitted ImGuiKey values more consistent regardless of keyboard mapping, but you may be getting different values as before. - - Win32: Use scancodes for OEM keys. Added support for the 3 new keys. - - SDL2, SDL3: Use scancodes for OEM keys. Added support for the Oem102 new key. + - Win32, SDL2, SDL3: Use scancodes for OEM keys. - GLFW: GLFW_KEY_WORLD_1 and GLFW_KEY_WORLD_2 are emitting ImGuiKey_Oem102. - Backends: GLFW: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. (#8452) diff --git a/imgui.cpp b/imgui.cpp index 093ba637528d..a2d90caeda6e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8801,7 +8801,7 @@ static const char* const GKeyNames[] = "Pause", "Keypad0", "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "KeypadDecimal", "KeypadDivide", "KeypadMultiply", "KeypadSubtract", "KeypadAdd", "KeypadEnter", "KeypadEqual", - "AppBack", "AppForward", "Oem102", "AbntC1", "AbntC2", + "AppBack", "AppForward", "Oem102", "GamepadStart", "GamepadBack", "GamepadFaceLeft", "GamepadFaceRight", "GamepadFaceUp", "GamepadFaceDown", "GamepadDpadLeft", "GamepadDpadRight", "GamepadDpadUp", "GamepadDpadDown", diff --git a/imgui.h b/imgui.h index 512e9a6c7298..429bb7480b58 100644 --- a/imgui.h +++ b/imgui.h @@ -1494,8 +1494,6 @@ enum ImGuiKey : int ImGuiKey_AppBack, // Available on some keyboard/mouses. Often referred as "Browser Back" ImGuiKey_AppForward, ImGuiKey_Oem102, // Non-US backslash. - ImGuiKey_AbntC1, // Brazil ABNT extra keys - ImGuiKey_AbntC2, // Gamepad (some of those are analog values, 0.0f to 1.0f) // NAVIGATION ACTION // (download controller mapping PNG/PSD at http://dearimgui.com/controls_sheets) From b758b8223fc789c8f1962be08ce234aaa4ccd4f4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 13 Mar 2025 19:30:42 +0100 Subject: [PATCH 537/548] InputText: Pasting a multi-line buffer into a single-line edit replaces carriage return by spaces. (#8459) --- docs/CHANGELOG.txt | 2 ++ imgui_widgets.cpp | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f184ddc8f785..8d4f0bec7579 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -77,6 +77,8 @@ Other changes: inner/outer padding applied to hit-testing of windows borders and detection of hovered window. - InputText: Allow CTRL+Shift+Z to redo even outside of OSX. (#8389) [@tanksdude] +- InputText: Pasting a multi-line buffer into a single-line edit replaces + carriage return by spaces. (#8459) - InputTextWithHint(): Fixed buffer-overflow (luckily often with no visible effect) when a user callback modified the buffer contents in a way that altered the visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index fef30d273781..602bdb9e1c9d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4294,7 +4294,13 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, Im if (c < 0x20) { bool pass = false; - 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 == '\n') && (flags & ImGuiInputTextFlags_Multiline) != 0; // Note that an Enter KEY will emit \r and be ignored (we poll for KEY in InputText() code) + if (c == '\n' && input_source_is_clipboard && (flags & ImGuiInputTextFlags_Multiline) == 0) // In single line mode, replace \n with a space + { + c = *p_char = ' '; + pass = true; + } + pass |= (c == '\n') && (flags & ImGuiInputTextFlags_Multiline) != 0; pass |= (c == '\t') && (flags & ImGuiInputTextFlags_AllowTabInput) != 0; if (!pass) return false; From ea2a12112df50975f3582b121c63d65fcdebd330 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 14 Mar 2025 17:13:04 +0100 Subject: [PATCH 538/548] Misc: Various zealous warning fixes for newer version of Clang. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 4 +++- imgui_demo.cpp | 2 ++ imgui_draw.cpp | 1 + imgui_tables.cpp | 2 ++ imgui_widgets.cpp | 2 ++ 6 files changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8d4f0bec7579..3c6c4f234960 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -124,6 +124,7 @@ Other changes: - Debug Tools: Added io.ConfigDebugHighlightIdConflictsShowItemPicker (defaults to true) to allow disabled Item Picker suggestion in user facing builds. (#7961, #7669) - Debug Tools: Tweaked layout of ID Stack Tool and always display full path. (#4631) +- Misc: Various zealous warning fixes for newer version of Clang. - Misc: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursors (busy/wait/hourglass shape, with or without an arrow cursor). - Demo: Reorganized "Widgets" section to be alphabetically ordered and split in more functions. diff --git a/imgui.cpp b/imgui.cpp index a2d90caeda6e..60340c022423 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1145,17 +1145,19 @@ CODE #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. +#pragma clang diagnostic ignored "-Wformat" // warning: format specifies type 'int' but the argument has type 'unsigned int' #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. +#pragma clang diagnostic ignored "-Wformat-pedantic" // warning: format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic. #pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is. #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness -#pragma clang diagnostic ignored "-Wformat-pedantic" // warning: format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic. #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type 'int' #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type +#pragma clang diagnostic ignored "-Wswitch-default" // warning: 'switch' missing 'default' label #elif defined(__GNUC__) // We disable -Wpragmas because GCC doesn't provide a has_warning equivalent and some forks/patches may not follow the warning/version association. #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 50eeed1073f6..0423c49f27e0 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -159,6 +159,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. #pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning: 'xx' is deprecated: The POSIX name for this.. // for strdup used in demo code (so user can copy & paste the code) #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type +#pragma clang diagnostic ignored "-Wformat" // warning: format specifies type 'int' but the argument has type 'unsigned int' #pragma clang diagnostic ignored "-Wformat-security" // warning: format string is not a string literal #pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. #pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used // we define snprintf/vsnprintf on Windows so they are available, but not always used. @@ -167,6 +168,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access +#pragma clang diagnostic ignored "-Wswitch-default" // warning: 'switch' missing 'default' label #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe diff --git a/imgui_draw.cpp b/imgui_draw.cpp index efdddc8b1857..a1111b08fbed 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -68,6 +68,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type #pragma clang diagnostic ignored "-Wcast-qual" // warning: cast from 'const xxxx *' to 'xxx *' drops const qualifier +#pragma clang diagnostic ignored "-Wswitch-default" // warning: 'switch' missing 'default' label #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 5464ba688f28..5cdee0433e3b 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -221,6 +221,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. +#pragma clang diagnostic ignored "-Wformat" // warning: format specifies type 'int' but the argument has type 'unsigned int' #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 @@ -230,6 +231,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type +#pragma clang diagnostic ignored "-Wswitch-default" // warning: 'switch' missing 'default' label #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 602bdb9e1c9d..880232965036 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -70,6 +70,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. +#pragma clang diagnostic ignored "-Wformat" // warning: format specifies type 'int' but the argument has type 'unsigned int' #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness #pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used // we define snprintf/vsnprintf on Windows so they are available, but not always used. @@ -80,6 +81,7 @@ Index of this file: #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access #pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type +#pragma clang diagnostic ignored "-Wswitch-default" // warning: 'switch' missing 'default' label #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wfloat-equal" // warning: comparing floating-point with '==' or '!=' is unsafe From 97428e8ac99e339ce05eee531cf55b77b29ea709 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 14 Mar 2025 16:30:39 +0100 Subject: [PATCH 539/548] Version 1.91.9 --- docs/CHANGELOG.txt | 11 +++++++---- 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, 16 insertions(+), 13 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3c6c4f234960..c9a68c7b2cf1 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,9 +36,11 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.91.9 WIP (In Progress) + VERSION 1.91.9 (Released 2025-03-14) ----------------------------------------------------------------------- +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.9 + Breaking changes: - Image: removed 'tint_col' and 'border_col' parameter from Image() function. (#8131, #8238) @@ -72,7 +74,7 @@ Other changes: RadioButton(), Selectable(). Regression from 2025/01/13. (#8370) - Windows: Fixed an issue where BeginChild() inside a collapsed Begin() wouldn't inherit the SkipItems flag, resulting in missing coarse clipping - opportunity for code not checking the BeginChild() return value. + opportunities for code not checking the BeginChild() return value. - Windows, Style: Added style.WindowBorderHoverPadding setting to configure inner/outer padding applied to hit-testing of windows borders and detection of hovered window. @@ -141,7 +143,7 @@ Other changes: ImGuiKey_Slash, ImGuiKey_Semicolon, ImGuiKey_Equal, ImGuiKey_LeftBracket, ImGuiKey_RightBracket, ImGuiKey_Backslash, ImGuiKey_GraveAccent, and newly introduced ImGuiKey_Oem102. - This is NOT affecting characters used the text inputs. - - Fixes many cases of keys not emitting a ImGuiKey value with certain keyboad layouts. + - Fixes many cases of keys not emitting a ImGuiKey value with certain keyboard layouts. - Makes emitted ImGuiKey values more consistent regardless of keyboard mapping, but you may be getting different values as before. - Win32, SDL2, SDL3: Use scancodes for OEM keys. @@ -155,7 +157,8 @@ Other changes: - Backends: SDL2, SDL3: Avoid calling SDL_GetGlobalMouseState() when mouse is in relative mode. (#8425, #8407) [@TheMode] - Backends: SDL2, SDL3: Only start SDL_CaptureMouse() when mouse is being dragged, - to mitigate issues with e.g. Linux debuggers not claiming capture back. (#6410, #3650) + to mitigate issues with e.g. Linux debuggers not claiming capture back on debug + break. (#6410, #3650) - Backends: OpenGL3: Lazily reinitialize embedded GL loader for when calling backend from e.g. other DLL boundaries. (#8406) - Backends: DirectX12: Fixed an issue where pre-1.91.5 legacy ImGui_ImplDX12_Init() diff --git a/imgui.cpp b/imgui.cpp index 60340c022423..8ec001178734 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 WIP +// dear imgui, v1.91.9 // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 429bb7480b58..4ca9c83724dc 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 WIP +// dear imgui, v1.91.9 // (headers) // Help: @@ -28,8 +28,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.9 WIP" -#define IMGUI_VERSION_NUM 19188 +#define IMGUI_VERSION "1.91.9" +#define IMGUI_VERSION_NUM 19190 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0423c49f27e0..ead800f4b639 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 WIP +// dear imgui, v1.91.9 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index a1111b08fbed..aa0a7feec1bd 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 WIP +// dear imgui, v1.91.9 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 6d9120a9e007..6cb9be406c32 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 WIP +// dear imgui, v1.91.9 // (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 5cdee0433e3b..e67a8364978a 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 WIP +// dear imgui, v1.91.9 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 880232965036..fc358534eaa8 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 WIP +// dear imgui, v1.91.9 // (widgets code) /* From d6493aab028139538c9bcf2141ae02574b12aa75 Mon Sep 17 00:00:00 2001 From: Wizard <74285801+wizard00000@users.noreply.github.com> Date: Sun, 16 Mar 2025 18:56:59 -0400 Subject: [PATCH 540/548] Fix typo in comment (#8494) --- imgui_widgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index fc358534eaa8..d671cbbda950 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6207,7 +6207,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl if (g.Style.FrameBorderSize > 0.0f) RenderFrameBorder(bb.Min, bb.Max, rounding); else - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color buttons are often in need of some sort of border } // Drag and Drop Source From 4d4f1fd364ebb770766a6fd4dd0d17c39865e7b2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Mar 2025 11:50:32 +0100 Subject: [PATCH 541/548] Docs: retroactively document ConfigData->Sources renaming. (#8495) Amend 4c0604e --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c9a68c7b2cf1..36ceb7cdbdeb 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,8 @@ Breaking changes: - Backends: Vulkan: Added 'uint32_t api_version' argument to ImGui_ImplVulkan_LoadFunctions(). Note that it was also added to ImGui_ImplVulkan_InitInfo but for the later it is optional. (#8326, #8365, #8400) +- Internals: Fonts: ImFontAtlas::ConfigData[] has been renamed to ImFontAtlas::Sources[], +- Internals: Fonts: ImFont::ConfigData[], ConfigDataCount has been renamed to Sources[], SourceCount. - Internals: Menus: reworked mangling of menu windows to use "###Menu_00" etc. instead of "##Menu_00", allowing them to also store the menu name before it. This shouldn't affect code unless directly accessing menu window from their mangled name. diff --git a/imgui.cpp b/imgui.cpp index 8ec001178734..af7ce4ce7667 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -441,6 +441,7 @@ CODE - old behavior altered border size (and therefore layout) based on border color's alpha, which caused variety of problems + old behavior a fixed 1.0f for border size which was not tweakable. - kept legacy signature (will obsolete), which mimics the old behavior, but uses Max(1.0f, style.ImageBorderSize) when border_col is specified. - added ImageWithBg() function which has both 'bg_col' (which was missing) and 'tint_col'. It was impossible to add 'bg_col' to Image() with a parameter order consistent with other functions, so we decided to remove 'tint_col' and introduce ImageWithBg(). + - 2025/02/25 (1.91.9) - internals: fonts: ImFontAtlas::ConfigData[] has been renamed to ImFontAtlas::Sources[]. ImFont::ConfigData[], ConfigDataCount has been renamed to Sources[], SourceCount. - 2025/02/06 (1.91.9) - renamed ImFontConfig::GlyphExtraSpacing.x to ImFontConfig::GlyphExtraAdvanceX. - 2025/01/22 (1.91.8) - removed ImGuiColorEditFlags_AlphaPreview (made value 0): it is now the default behavior. prior to 1.91.8: alpha was made opaque in the preview by default _unless_ using ImGuiColorEditFlags_AlphaPreview. We now display the preview as transparent by default. You can use ImGuiColorEditFlags_AlphaOpaque to use old behavior. From 2737dbb1e1cd206fc874a5ca17ee672a68523182 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Mar 2025 11:51:57 +0100 Subject: [PATCH 542/548] Docs: Fixed typo. Very oops. (#8495) --- docs/CHANGELOG.txt | 2 +- imgui.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 36ceb7cdbdeb..e369f1957760 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -65,7 +65,7 @@ Breaking changes: Note that it was also added to ImGui_ImplVulkan_InitInfo but for the later it is optional. (#8326, #8365, #8400) - Internals: Fonts: ImFontAtlas::ConfigData[] has been renamed to ImFontAtlas::Sources[], -- Internals: Fonts: ImFont::ConfigData[], ConfigDataCount has been renamed to Sources[], SourceCount. +- Internals: Fonts: ImFont::ConfigData[], ConfigDataCount has been renamed to Sources[], SourcesCount. - Internals: Menus: reworked mangling of menu windows to use "###Menu_00" etc. instead of "##Menu_00", allowing them to also store the menu name before it. This shouldn't affect code unless directly accessing menu window from their mangled name. diff --git a/imgui.cpp b/imgui.cpp index af7ce4ce7667..78774c2b48ea 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -441,7 +441,7 @@ CODE - old behavior altered border size (and therefore layout) based on border color's alpha, which caused variety of problems + old behavior a fixed 1.0f for border size which was not tweakable. - kept legacy signature (will obsolete), which mimics the old behavior, but uses Max(1.0f, style.ImageBorderSize) when border_col is specified. - added ImageWithBg() function which has both 'bg_col' (which was missing) and 'tint_col'. It was impossible to add 'bg_col' to Image() with a parameter order consistent with other functions, so we decided to remove 'tint_col' and introduce ImageWithBg(). - - 2025/02/25 (1.91.9) - internals: fonts: ImFontAtlas::ConfigData[] has been renamed to ImFontAtlas::Sources[]. ImFont::ConfigData[], ConfigDataCount has been renamed to Sources[], SourceCount. + - 2025/02/25 (1.91.9) - internals: fonts: ImFontAtlas::ConfigData[] has been renamed to ImFontAtlas::Sources[]. ImFont::ConfigData[], ConfigDataCount has been renamed to Sources[], SourcesCount. - 2025/02/06 (1.91.9) - renamed ImFontConfig::GlyphExtraSpacing.x to ImFontConfig::GlyphExtraAdvanceX. - 2025/01/22 (1.91.8) - removed ImGuiColorEditFlags_AlphaPreview (made value 0): it is now the default behavior. prior to 1.91.8: alpha was made opaque in the preview by default _unless_ using ImGuiColorEditFlags_AlphaPreview. We now display the preview as transparent by default. You can use ImGuiColorEditFlags_AlphaOpaque to use old behavior. From bfaef8ca1783a26aa7eba766dacf87a85ed13ede Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Mar 2025 19:08:58 +0100 Subject: [PATCH 543/548] Version 1.92.0 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 e369f1957760..62c7c548a9c4 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.92.0 WIP (In Progress) +----------------------------------------------------------------------- + +Breaking changes: + +Other changes: + + ----------------------------------------------------------------------- VERSION 1.91.9 (Released 2025-03-14) ----------------------------------------------------------------------- diff --git a/imgui.cpp b/imgui.cpp index 78774c2b48ea..932f433fdc5c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 +// dear imgui, v1.92.0 WIP // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 4ca9c83724dc..7bbdf8225583 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 +// dear imgui, v1.92.0 WIP // (headers) // Help: @@ -28,8 +28,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.9" -#define IMGUI_VERSION_NUM 19190 +#define IMGUI_VERSION "1.92.0 WIP" +#define IMGUI_VERSION_NUM 19191 #define IMGUI_HAS_TABLE /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ead800f4b639..996694268739 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 +// dear imgui, v1.92.0 WIP // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index aa0a7feec1bd..1404b8d61fcf 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 +// dear imgui, v1.92.0 WIP // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 6cb9be406c32..870360264922 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 +// dear imgui, v1.92.0 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 e67a8364978a..0ac6ec89661d 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 +// dear imgui, v1.92.0 WIP // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d671cbbda950..0aa121e774a2 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.91.9 +// dear imgui, v1.92.0 WIP // (widgets code) /* From a7dc1847728171e8940671d8e34a8ecb050f00fa Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Mar 2025 19:07:24 +0100 Subject: [PATCH 544/548] Moved ImDrawIdx definition lower in imgui.h. Moved ImTextureID slightly below in its own section. --- imgui.h | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/imgui.h b/imgui.h index 7bbdf8225583..0db50aec1825 100644 --- a/imgui.h +++ b/imgui.h @@ -37,6 +37,7 @@ Index of this file: // [SECTION] Header mess // [SECTION] Forward declarations and basic types +// [SECTION] Texture identifier (ImTextureID) // [SECTION] Dear ImGui end-user API functions // [SECTION] Flags & Enumerations // [SECTION] Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs) @@ -250,22 +251,6 @@ typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: f typedef int ImGuiViewportFlags; // -> enum ImGuiViewportFlags_ // Flags: for ImGuiViewport typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin(), BeginChild() -// ImTexture: user data for renderer backend to identify a texture [Compile-time configurable type] -// - To use something else than an opaque void* pointer: override with e.g. '#define ImTextureID MyTextureType*' in your imconfig.h file. -// - This can be whatever to you want it to be! read the FAQ about ImTextureID for details. -// - You can make this a structure with various constructors if you need. You will have to implement ==/!= operators. -// - (note: before v1.91.4 (2024/10/08) the default type for ImTextureID was void*. Use intermediary intptr_t cast and read FAQ if you have casting warnings) -#ifndef ImTextureID -typedef ImU64 ImTextureID; // Default: store a pointer or an integer fitting in a pointer (most renderer backends are ok with that) -#endif - -// ImDrawIdx: vertex index. [Compile-time configurable type] -// - To use 16-bit indices + allow large meshes: backend need to set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset (recommended). -// - To use 32-bit indices: override with '#define ImDrawIdx unsigned int' in your imconfig.h file. -#ifndef ImDrawIdx -typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibility with renderer backends) -#endif - // Character types // (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display) typedef unsigned int ImWchar32; // A single decoded U32 character/code point. We encode them as multi bytes UTF-8 when used in strings. @@ -315,6 +300,19 @@ struct ImVec4 }; IM_MSVC_RUNTIME_CHECKS_RESTORE +//----------------------------------------------------------------------------- +// [SECTION] Texture identifier (ImTextureID) +//----------------------------------------------------------------------------- + +// ImTexture: user data for renderer backend to identify a texture [Compile-time configurable type] +// - To use something else than an opaque void* pointer: override with e.g. '#define ImTextureID MyTextureType*' in your imconfig.h file. +// - This can be whatever to you want it to be! read the FAQ about ImTextureID for details. +// - You can make this a structure with various constructors if you need. You will have to implement ==/!= operators. +// - (note: before v1.91.4 (2024/10/08) the default type for ImTextureID was void*. Use intermediary intptr_t cast and read FAQ if you have casting warnings) +#ifndef ImTextureID +typedef ImU64 ImTextureID; // Default: store a pointer or an integer fitting in a pointer (most renderer backends are ok with that) +#endif + //----------------------------------------------------------------------------- // [SECTION] Dear ImGui end-user API functions // (Note that ImGui:: being a namespace, you can add extra ImGui:: functions in your own separate file. Please don't modify imgui source files!) @@ -2957,6 +2955,13 @@ struct ImGuiSelectionExternalStorage #define IM_DRAWLIST_TEX_LINES_WIDTH_MAX (32) #endif +// ImDrawIdx: vertex index. [Compile-time configurable type] +// - To use 16-bit indices + allow large meshes: backend need to set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset (recommended). +// - To use 32-bit indices: override with '#define ImDrawIdx unsigned int' in your imconfig.h file. +#ifndef ImDrawIdx +typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibility with renderer backends) +#endif + // ImDrawCallback: Draw callbacks for advanced uses [configurable type: override in imconfig.h] // NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering, // you can poke into the draw list for that! Draw callback may be useful for example to: From 93b446a96281ceec9b226ef624cdc428efd44c60 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Mar 2025 19:39:52 +0100 Subject: [PATCH 545/548] Backtrack of version tagging 1.92.0 > 1.91.9b for publishing a hotfix (#8496) --- docs/CHANGELOG.txt | 2 +- imgui.cpp | 2 +- imgui.h | 4 ++-- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 62c7c548a9c4..a2a55e1f2bd2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,7 +36,7 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.92.0 WIP (In Progress) + VERSION 1.91.9b WIP (In Progress) ----------------------------------------------------------------------- Breaking changes: diff --git a/imgui.cpp b/imgui.cpp index 932f433fdc5c..7ec192278971 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.0 WIP +// dear imgui, v1.91.9b // (main code and documentation) // Help: diff --git a/imgui.h b/imgui.h index 0db50aec1825..75750ae10904 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.0 WIP +// dear imgui, v1.91.9b // (headers) // Help: @@ -28,7 +28,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') -#define IMGUI_VERSION "1.92.0 WIP" +#define IMGUI_VERSION "1.91.9b" #define IMGUI_VERSION_NUM 19191 #define IMGUI_HAS_TABLE diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 996694268739..10fa434dca7f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.0 WIP +// dear imgui, v1.91.9b // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 1404b8d61fcf..273101529189 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.0 WIP +// dear imgui, v1.91.9b // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 870360264922..ddf9ea3e9afd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.0 WIP +// dear imgui, v1.91.9b // (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 0ac6ec89661d..74eec5797078 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.0 WIP +// dear imgui, v1.91b // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 0aa121e774a2..c997e17b61c6 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.0 WIP +// dear imgui, v1.91b // (widgets code) /* From cfed7a3a5446cd6b36a161d02e89fc816deab69b Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Mar 2025 19:51:46 +0100 Subject: [PATCH 546/548] Tables: fixed assert/issues loading settings. (#8496, #7934) Not sure what I did with 05742f9b6ff but I missed on the primary filter. --- docs/CHANGELOG.txt | 4 ++++ imgui_tables.cpp | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a2a55e1f2bd2..d32fa1c43fa9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,10 @@ Breaking changes: Other changes: +- Tables: Fixed assert when loading .ini settings of reordered columns. (#8496, #7934) +- Tables: Fixed issues when loading .ini settings for a table with columns using + ImGuiTableColumnFlags_DefaultHide or ImGuiTableColumnFlags_DefaultSort. (#8496, #7934) + ----------------------------------------------------------------------- VERSION 1.91.9 (Released 2025-03-14) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 74eec5797078..c98aea2d1cc7 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1638,9 +1638,9 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo column->InitStretchWeightOrWidth = init_width_or_weight; if (table->IsInitializing) { - ImGuiTableFlags init_flags = ~0; - if (column->WidthRequest >= 0.0f || column->StretchWeight >= 0.0f) - init_flags &= ~ImGuiTableFlags_Resizable; + ImGuiTableFlags init_flags = ~table->SettingsLoadedFlags; + if (column->WidthRequest < 0.0f && column->StretchWeight < 0.0f) + init_flags |= ImGuiTableFlags_Resizable; TableInitColumnDefaults(table, column, init_flags); } From f5befd2d29e66809cd1110a152e375a7f1981f06 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 17 Mar 2025 20:17:26 +0100 Subject: [PATCH 547/548] Version 1.91.9b --- docs/CHANGELOG.txt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d32fa1c43fa9..db1fb0cea5ab 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,14 +36,12 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.91.9b WIP (In Progress) + VERSION 1.91.9b (Released 2025-03-17) ----------------------------------------------------------------------- -Breaking changes: - -Other changes: +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.91.9b -- Tables: Fixed assert when loading .ini settings of reordered columns. (#8496, #7934) +- Tables: Fixed assert when loading .ini settings with reordered columns. (#8496, #7934) - Tables: Fixed issues when loading .ini settings for a table with columns using ImGuiTableColumnFlags_DefaultHide or ImGuiTableColumnFlags_DefaultSort. (#8496, #7934) From cc35200431567ea7b1565a79f705c840b95bb524 Mon Sep 17 00:00:00 2001 From: lapinozz Date: Thu, 1 May 2025 13:57:16 -0400 Subject: [PATCH 548/548] Removed asserts --- imgui.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index aab7404a42e9..132a7b2e9e4f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10318,12 +10318,14 @@ static void ImGui::ErrorCheckEndFrameSanityChecks() IM_ASSERT(g.CurrentWindowStack.Size == 1); IM_ASSERT(g.CurrentWindowStack[0].Window->IsFallbackWindow); - + + /* Not sure how/where to integrate this // Window stacks // NOT checking: DC.ItemWidth, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) IM_ASSERT(SizeOfIDStack == window->IDStack.Size && "PushID/PopID or TreeNode/TreePop Mismatch!"); IM_ASSERT(0 == window->DC.LayoutStack.Size && (!window->DC.LayoutStack.Size || window->DC.LayoutStack.back()->Type == ImGuiLayoutType_Horizontal) && "BeginHorizontal/EndHorizontal Mismatch!"); IM_ASSERT(0 == window->DC.LayoutStack.Size && (!window->DC.LayoutStack.Size || window->DC.LayoutStack.back()->Type == ImGuiLayoutType_Vertical) && "BeginVertical/EndVertical Mismatch!"); + */ } // Save current stack sizes. Called e.g. by NewFrame() and by Begin() but may be called for manual recovery.