diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a9b943436..bd25fe4ef 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -36,12 +36,12 @@ HOW TO UPDATE? - Please report any issue! ----------------------------------------------------------------------- - VERSION 1.92.1 WIP (In Progress) + VERSION 1.92.1 (Released 2025-07-09) ----------------------------------------------------------------------- -Breaking changes: +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.1 -Other changes: +Changes: - Fonts: added ImFontAtlas::SetFontLoader() to dynamically change font loader at runtime without using internal API. (#8752, #8465) @@ -61,6 +61,9 @@ Other changes: - Demo: Added "Text -> Font Size" demo section. (#8738) [@Demonese] - CI: Fixed dllimport/dllexport tests. (#8757) [@AidanSun05] - CI: Updated to use latest Windows image + VS2022. +- Debug Tools: added IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS to detect + id conflicts _before_ hovering. This is very slow and should only be used + temporarily. (#8651, #7961, #7669) - Examples: GLFW+OpenGL3, GLFW+WGPU: Emscripten Makefiles uses GLFW port 'contrib.glfw3' which offers better HiDPI support. (#8742) [@pthom] - Backends: GLFW, SDL2 made ImGui_ImplGLFW_GetContentScaleXXX() and @@ -87,7 +90,7 @@ Docking+Viewports Branch: VERSION 1.92.0 (Released 2025-06-25) ----------------------------------------------------------------------- -Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92 +Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.0 THIS VERSION CONTAINS THE LARGEST AMOUNT OF BREAKING CHANGES SINCE 2015! I TRIED REALLY HARD TO KEEP THEM TO A MINIMUM, REDUCE THE AMOUNT OF INTERFERENCE, @@ -554,7 +557,7 @@ Docking+Viewports Branch: user code is discarding the 'bool *p_open=false output' from Begin(). Because we allowed the Win32 window to close early, Windows destroyed it and our imgui window became not visible even though user code was - still submitting it. + still submitting it. (#8670) - Backends: Win32: Viewports: handle WM_DPICHANGED in backend when ImGuiConfigFlags_DpiEnableScaleViewports is enabled. - Backends: GLFW, SDL2, SDL3, Apple: provide Platform_GetWindowFramebufferScale handler, diff --git a/imconfig.h b/imconfig.h index a1e29e849..4dab1b604 100644 --- a/imconfig.h +++ b/imconfig.h @@ -129,6 +129,10 @@ //#define IM_DEBUG_BREAK IM_ASSERT(0) //#define IM_DEBUG_BREAK __debugbreak() +//---- Debug Tools: Enable highlight ID conflicts _before_ hovering items. When io.ConfigDebugHighlightIdConflicts is set. +// (THIS WILL SLOW DOWN DEAR IMGUI. Only use occasionally and disable after use) +//#define IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS + //---- Debug Tools: Enable slower asserts //#define IMGUI_DEBUG_PARANOID diff --git a/imgui.cpp b/imgui.cpp index 35c5ee64f..ae4ad95aa 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.1 WIP +// dear imgui, v1.92.1 // (main code and documentation) // Help: @@ -4107,7 +4107,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas) WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1; WheelingWindowReleaseTimer = 0.0f; - DebugDrawIdConflicts = 0; + DebugDrawIdConflictsId = 0; DebugHookIdInfo = 0; HoveredId = HoveredIdPreviousFrame = 0; HoveredIdPreviousFrameItemCount = 0; @@ -4354,6 +4354,12 @@ void ImGui::Initialize() DockContextInitialize(&g); #endif + // Print a debug message when running with debug feature IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS because it is very slow. + // DO NOT COMMENT OUT THIS MESSAGE. IT IS DESIGNED TO REMIND YOU THAT IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS SHOULD ONLY BE TEMPORARILY ENABLED. +#ifdef IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS + DebugLog("IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS is enabled.\nMust disable after use! Otherwise Dear ImGui will run slower.\n"); +#endif + // ImDrawList/ImFontAtlas are designed to function without ImGui, and 99% of it works without an ImGui context. // But this link allows us to facilitate/handle a few edge cases better. ImFontAtlas* atlas = g.IO.Fonts; @@ -4839,7 +4845,8 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) return true; } -// Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered(). +// Internal facing ItemHoverable() used when submitting widgets. THIS IS A SUBMISSION NOT A HOVER CHECK. +// Returns whether the item was hovered, logic differs slightly from IsItemHovered(). // (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: @@ -4851,11 +4858,12 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag ImGuiWindow* window = g.CurrentWindow; // Detect ID conflicts + // (this is specifically done here by comparing on hover because it allows us a detection of duplicates that is algorithmically extra cheap, 1 u32 compare per item. No O(log N) lookup whatsoever) #ifndef IMGUI_DISABLE_DEBUG_TOOLS if (id != 0 && g.HoveredIdPreviousFrame == id && (item_flags & ImGuiItemFlags_AllowDuplicateId) == 0) { g.HoveredIdPreviousFrameItemCount++; - if (g.DebugDrawIdConflicts == id) + if (g.DebugDrawIdConflictsId == 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 @@ -5560,9 +5568,9 @@ void ImGui::NewFrame() // [DEBUG] if (!g.IO.ConfigDebugHighlightIdConflicts || !g.IO.KeyCtrl) // Count is locked while holding CTRL - g.DebugDrawIdConflicts = 0; + g.DebugDrawIdConflictsId = 0; if (g.IO.ConfigDebugHighlightIdConflicts && g.HoveredIdPreviousFrameItemCount > 1) - g.DebugDrawIdConflicts = g.HoveredIdPreviousFrame; + g.DebugDrawIdConflictsId = g.HoveredIdPreviousFrame; // Update HoveredId data if (!g.HoveredIdPreviousFrame) @@ -11509,9 +11517,9 @@ void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip() { #ifndef IMGUI_DISABLE_DEBUG_TOOLS ImGuiContext& g = *GImGui; - if (g.DebugDrawIdConflicts != 0 && g.IO.KeyCtrl == false) + if (g.DebugDrawIdConflictsId != 0 && g.IO.KeyCtrl == false) g.DebugDrawIdConflictsCount = g.HoveredIdPreviousFrameItemCount; - if (g.DebugDrawIdConflicts != 0 && g.DebugItemPickerActive == false && BeginErrorTooltip()) + if (g.DebugDrawIdConflictsId != 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!"); @@ -11680,6 +11688,21 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu // Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something". // READ THE FAQ: https://dearimgui.com/faq IM_ASSERT(id != window->ID && "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!"); + + // [DEBUG] Highlight all conflicts WITHOUT needing to hover. THIS WILL SLOW DOWN DEAR IMGUI. DON'T KEEP ACTIVATED. + // This will only work for items submitted with ItemAdd(). Some very rare/odd/unrecommended code patterns are calling ButtonBehavior() without ItemAdd(). +#ifdef IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS + if ((g.LastItemData.ItemFlags & ImGuiItemFlags_AllowDuplicateId) == 0) + { + int* p_alive = g.DebugDrawIdConflictsAliveCount.GetIntRef(id, -1); // Could halve lookups if we knew ImGuiStorage can store 64-bit, or by storing FrameCount as 30-bits + highlight as 2-bits. But the point is that we should not pretend that this is fast. + int* p_highlight = g.DebugDrawIdConflictsHighlightSet.GetIntRef(id, -1); + if (*p_alive == g.FrameCount) + *p_highlight = g.FrameCount; + *p_alive = g.FrameCount; + if (*p_highlight >= g.FrameCount - 1) + 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.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] //if ((g.LastItemData.ItemFlags & ImGuiItemFlags_NoNav) == 0) @@ -21786,6 +21809,10 @@ void ImGui::ShowMetricsWindow(bool* p_open) } }; +#ifdef IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS + TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS is enabled.\nMust disable after use! Otherwise Dear ImGui will run slower.\n"); +#endif + // Tools if (TreeNode("Tools")) { diff --git a/imgui.h b/imgui.h index db60dba1c..fe0938867 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.1 WIP +// dear imgui, v1.92.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.92.1 WIP" -#define IMGUI_VERSION_NUM 19202 +#define IMGUI_VERSION "1.92.1" +#define IMGUI_VERSION_NUM 19210 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 #define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 88b35a3c6..1785c13ad 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.1 WIP +// dear imgui, v1.92.1 // (demo code) // Help: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 86dc67e38..f4d544d78 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.1 WIP +// dear imgui, v1.92.1 // (drawing and font code) /* diff --git a/imgui_internal.h b/imgui_internal.h index 1085c8eee..c7c282b91 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.92.1 WIP +// dear imgui, v1.92.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. @@ -987,6 +987,7 @@ enum ImGuiItemStatusFlags_ ImGuiItemStatusFlags_Visible = 1 << 8, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()). ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid. ImGuiItemStatusFlags_HasShortcut = 1 << 10, // g.LastItemData.Shortcut valid. Set by SetNextItemShortcut() -> ItemAdd(). + //ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Removed IN 1.90.1 (Dec 2023). The trigger is part of g.NavActivateId. See commit 54c1bdeceb. // Additional status + semantic for ImGuiTestEngine #ifdef IMGUI_ENABLE_TEST_ENGINE @@ -1039,6 +1040,7 @@ enum ImGuiButtonFlagsPrivate_ ImGuiButtonFlags_NoFocus = 1 << 22, // [EXPERIMENTAL: Not very well specced]. Don't focus parent window when clicking. ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold, ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease, + //ImGuiButtonFlags_NoKeyModifiers = ImGuiButtonFlags_NoKeyModsAllowed, // Renamed in 1.91.4 }; // Extend ImGuiComboFlags_ @@ -1700,6 +1702,7 @@ enum ImGuiNavRenderCursorFlags_ 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 + //ImGuiNavHighlightFlags_TypeThin = ImGuiNavRenderCursorFlags_Compact, // Renamed in 1.90.2 #endif }; @@ -2385,7 +2388,7 @@ struct ImGuiContext ImVec2 WheelingAxisAvg; // Item/widgets state and tracking information - ImGuiID DebugDrawIdConflicts; // Set when we detect multiple items with the same identifier + ImGuiID DebugDrawIdConflictsId; // 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; @@ -2474,18 +2477,19 @@ struct ImGuiContext 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() + ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItemByID() ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0 ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat) ImGuiActivateFlags NavActivateFlags; ImVector NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain. ImGuiID NavHighlightActivatedId; float NavHighlightActivatedTimer; - ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. + ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame. 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; + //ImGuiID NavActivateInputId; // Removed in 1.89.4 (July 2023). This is now part of g.NavActivateId and sets g.NavActivateFlags |= ImGuiActivateFlags_PreferInput. See commit c9a53aa74, issue #5606. // Navigation: Init & Move Requests bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd() @@ -2699,6 +2703,10 @@ struct ImGuiContext ImGuiIDStackTool DebugIDStackTool; ImGuiDebugAllocInfo DebugAllocInfo; ImGuiDockNode* DebugHoveredDockNode; // Hovered dock node. +#if defined(IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS) && !defined(IMGUI_DISABLE_DEBUG_TOOLS) + ImGuiStorage DebugDrawIdConflictsAliveCount; + ImGuiStorage DebugDrawIdConflictsHighlightSet; +#endif // Misc float FramerateSecPerFrame[60]; // Calculate estimate of framerate for user over the last 60 frames.. @@ -2707,7 +2715,7 @@ struct ImGuiContext float FramerateSecPerFrameAccum; int WantCaptureMouseNextFrame; // Explicit capture override via SetNextFrameWantCaptureMouse()/SetNextFrameWantCaptureKeyboard(). Default to -1. int WantCaptureKeyboardNextFrame; // " - int WantTextInputNextFrame; // Copied in EndFrame() from g.PlatformImeData.WanttextInput. Needs to be set for some backends (SDL3) to emit character inputs. + int WantTextInputNextFrame; // Copied in EndFrame() from g.PlatformImeData.WantTextInput. Needs to be set for some backends (SDL3) to emit character inputs. ImVector TempBuffer; // Temporary text buffer char TempKeychordName[64]; @@ -3518,7 +3526,7 @@ namespace ImGui // This should be part of a larger set of API: FocusItem(offset = -1), FocusItemByID(id), ActivateItem(offset = -1), ActivateItemByID(id) etc. which are // much harder to design and implement than expected. I have a couple of private branches on this matter but it's not simple. For now implementing the easy ones. IMGUI_API void FocusItem(); // Focus last item (no selection/activation). - IMGUI_API void ActivateItemByID(ImGuiID id); // Activate an item by ID (button, checkbox, tree node etc.). Activation is queued and processed on the next frame when the item is encountered again. + IMGUI_API void ActivateItemByID(ImGuiID id); // Activate an item by ID (button, checkbox, tree node etc.). Activation is queued and processed on the next frame when the item is encountered again. Was called 'ActivateItem()' before 1.89.7. // Inputs // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. @@ -3961,6 +3969,7 @@ namespace ImGui //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(): // Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister(): // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)' // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0' diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 069c72995..119fe7bcc 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.1 WIP +// dear imgui, v1.92.1 // (tables and columns code) /* diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a1281bc72..d3c769c92 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.92.1 WIP +// dear imgui, v1.92.1 // (widgets code) /* @@ -573,7 +573,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool bool pressed = false; bool hovered = ItemHoverable(bb, id, item_flags); - // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button + // Special mode for Drag and Drop used by openables (tree nodes, tabs etc.) + // where holding the button pressed for a long time while drag a payload item triggers the button. if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {