Merge branch 'master' into docking

# Conflicts:
#	imgui.cpp
#	imgui_internal.h
features/sdl_renderer3_multiviewports
ocornut ago%!(EXTRA string=2 years)
commit b7c250925f
  1. 9
      docs/CHANGELOG.txt
  2. 2
      docs/FAQ.md
  3. 2
      imconfig.h
  4. 111
      imgui.cpp
  5. 14
      imgui.h
  6. 8
      imgui_demo.cpp
  7. 34
      imgui_internal.h
  8. 2
      imgui_widgets.cpp

@ -42,6 +42,10 @@ HOW TO UPDATE?
Breaking changes: Breaking changes:
- Debug Tools: Renamed ShowStackToolWindow() ("Stack Tool") to ShowIdStackToolWindow() ("ID Stack Tool"),
as earlier name was misleading. Kept inline redirection function. (#4631)
- IO: Removed io.MetricsActiveAllocations introduced in 1.63, was displayed in Metrics and unlikely to
be accessed by end-user. Value still visible in the UI and easily to recompute from a delta.
- ListBox, Combo: Changed signature of "name getter" callback in old one-liner ListBox()/Combo() apis. - ListBox, Combo: Changed signature of "name getter" callback in old one-liner ListBox()/Combo() apis.
Before: Before:
getter type: bool (*getter)(void* user_data, int idx, const char** out_text) getter type: bool (*getter)(void* user_data, int idx, const char** out_text)
@ -91,12 +95,17 @@ Other changes:
(regression from 1.89.2, only happened in some states). (#6783, #6000) (regression from 1.89.2, only happened in some states). (#6783, #6000)
- InputTextMultiline: Fixed Tabbing cycle leading to a situation where Enter key wouldn't - InputTextMultiline: Fixed Tabbing cycle leading to a situation where Enter key wouldn't
be accepted by the widget when navigation highlight is visible. (#6802, #3092, #5759, #787) be accepted by the widget when navigation highlight is visible. (#6802, #3092, #5759, #787)
- BeginGroup(): Fixed a bug pushing line lower extent too far down when called after a call
to SameLine() followed by manual cursor manipulation.
- BeginListBox(): Fixed not consuming SetNextWindowXXX data when returning false. - BeginListBox(): Fixed not consuming SetNextWindowXXX data when returning false.
- Menus: Fixed a bug where activating an item in a child-menu and dragging mouse over the
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 - 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. register contents size in a way that would affect the scrolling layer.
Was most often noticable when using an horizontal scrollbar. (#6789) Was most often noticable when using an horizontal scrollbar. (#6789)
- Misc: Most text functions also treat "%.*s" (along with "%s") specially to avoid formatting. (#3466, #6846) - Misc: Most text functions also treat "%.*s" (along with "%s") specially to avoid formatting. (#3466, #6846)
- IO: Setting io.WantSetMousePos ignores incoming MousePos events. (#6837, #228) [@bertaye] - IO: Setting io.WantSetMousePos ignores incoming MousePos events. (#6837, #228) [@bertaye]
- Debug Tools: Metrics: Added log recent alloc/free calls.
- ImDrawList: Added AddEllipse(), AddEllipseFilled(), PathEllipticalArcTo(). (#2743) [@Doohl] - ImDrawList: Added AddEllipse(), AddEllipseFilled(), PathEllipticalArcTo(). (#2743) [@Doohl]
- ImVector: Added find_index() helper. - ImVector: Added find_index() helper.
- Backends: GLFW: Clear emscripten's MouseWheel callback before shutdown. (#6790, #6096, #4019) [@halx99] - Backends: GLFW: Clear emscripten's MouseWheel callback before shutdown. (#6790, #6096, #4019) [@halx99]

@ -217,7 +217,7 @@ Interactive widgets (such as calls to Button buttons) need a unique ID.
**Unique IDs are used internally to track active widgets and occasionally associate state to widgets.<BR> **Unique IDs are used internally to track active widgets and occasionally associate state to widgets.<BR>
Unique IDs are implicitly built from the hash of multiple elements that identify the "path" to the UI element.** Unique IDs are implicitly built from the hash of multiple elements that identify the "path" to the UI element.**
Since Dear ImGui 1.85, you can use `Demo>Tools>Stack Tool` or call `ImGui::ShowStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand. Since Dear ImGui 1.85, you can use `Demo>Tools>Stack Tool` or call `ImGui::ShowIdStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand.
![Stack tool](https://user-images.githubusercontent.com/8225057/136235657-a0ea5665-dcd1-423f-9be6-dc3f8ced8f12.png) ![Stack tool](https://user-images.githubusercontent.com/8225057/136235657-a0ea5665-dcd1-423f-9be6-dc3f8ced8f12.png)

@ -34,7 +34,7 @@
// 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. // 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.
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty.
//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowStackToolWindow() will be empty (this was called IMGUI_DISABLE_METRICS_WINDOW before 1.88). //#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIdStackToolWindow() will be empty.
//---- Don't implement some functions to reduce linkage requirements. //---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)

@ -89,7 +89,7 @@ CODE
// [SECTION] PLATFORM DEPENDENT HELPERS // [SECTION] PLATFORM DEPENDENT HELPERS
// [SECTION] METRICS/DEBUGGER WINDOW // [SECTION] METRICS/DEBUGGER WINDOW
// [SECTION] DEBUG LOG WINDOW // [SECTION] DEBUG LOG WINDOW
// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, STACK TOOL) // [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL)
*/ */
@ -432,6 +432,8 @@ CODE
- likewise io.MousePos and GetMousePos() will use OS coordinates. - likewise io.MousePos and GetMousePos() will use OS coordinates.
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos. If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
- 2023/09/27 (1.90.0) - io: removed io.MetricsActiveAllocations introduced in 1.63. Same as 'g.DebugMemAllocCount - g.DebugMemFreeCount' (still displayed in Metrics, unlikely to be accessed by end-user).
- 2023/09/26 (1.90.0) - debug tools: Renamed ShowStackToolWindow() ("Stack Tool") to ShowIdStackToolWindow() ("ID Stack Tool"), as earlier name was misleading. Kept inline redirection function. (#4631)
- 2023/09/15 (1.90.0) - ListBox, Combo: changed signature of "name getter" callback in old one-liner ListBox()/Combo() apis. kept inline redirection function (will obsolete). - 2023/09/15 (1.90.0) - ListBox, Combo: changed signature of "name getter" callback in old one-liner ListBox()/Combo() apis. kept inline redirection function (will obsolete).
- old: bool Combo(const char* label, int* current_item, bool (*getter)(void* user_data, int idx, const char** out_text), ...) - old: bool Combo(const char* label, int* current_item, bool (*getter)(void* user_data, int idx, const char** out_text), ...)
- new: bool Combo(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), ...); - new: bool Combo(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), ...);
@ -4320,24 +4322,48 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
void* ImGui::MemAlloc(size_t size) void* ImGui::MemAlloc(size_t size)
{ {
void* ptr = (*GImAllocatorAllocFunc)(size, GImAllocatorUserData); void* ptr = (*GImAllocatorAllocFunc)(size, GImAllocatorUserData);
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
if (ImGuiContext* ctx = GImGui) if (ImGuiContext* ctx = GImGui)
{ DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, size);
ctx->IO.MetricsActiveAllocations++; #endif
//printf("[%05d] MemAlloc(%d) -> 0x%p\n", ctx->FrameCount, size, ptr);
}
return ptr; return ptr;
} }
// IM_FREE() == ImGui::MemFree() // IM_FREE() == ImGui::MemFree()
void ImGui::MemFree(void* ptr) void ImGui::MemFree(void* ptr)
{ {
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
if (ptr != NULL) if (ptr != NULL)
if (ImGuiContext* ctx = GImGui) if (ImGuiContext* ctx = GImGui)
DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, (size_t)-1);
#endif
return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
}
// We record the number of allocation in recent frames, as a way to audit/sanitize our guiding principles of "no allocations on idle/repeating frames"
void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size)
{
ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[info->LastEntriesIdx];
IM_UNUSED(ptr);
if (entry->FrameCount != frame_count)
{ {
ctx->IO.MetricsActiveAllocations--; info->LastEntriesIdx = (info->LastEntriesIdx + 1) % IM_ARRAYSIZE(info->LastEntriesBuf);
//printf("[%05d] MemFree(0x%p)\n", ctx->FrameCount, ptr); entry = &info->LastEntriesBuf[info->LastEntriesIdx];
entry->FrameCount = frame_count;
entry->AllocCount = entry->FreeCount = 0;
}
if (size != (size_t)-1)
{
entry->AllocCount++;
info->TotalAllocCount++;
//printf("[%05d] MemAlloc(%d) -> 0x%p\n", frame_count, size, ptr);
}
else
{
entry->FreeCount++;
info->TotalFreeCount++;
//printf("[%05d] MemFree(0x%p)\n", frame_count, ptr);
} }
return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
} }
const char* ImGui::GetClipboardText() const char* ImGui::GetClipboardText()
@ -5478,12 +5504,8 @@ static void FindHoveredWindow()
continue; continue;
// Using the clipped AABB, a child window will typically be clipped by its parent (not always) // Using the clipped AABB, a child window will typically be clipped by its parent (not always)
ImRect bb(window->OuterRectClipped); ImVec2 hit_padding = (window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) ? padding_regular : padding_for_resize;
if (window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) if (!window->OuterRectClipped.ContainsWithPad(g.IO.MousePos, hit_padding))
bb.Expand(padding_regular);
else
bb.Expand(padding_for_resize);
if (!bb.Contains(g.IO.MousePos))
continue; continue;
// Support for one rectangular hole in any given window // Support for one rectangular hole in any given window
@ -8408,7 +8430,7 @@ void ImGui::PushOverrideID(ImGuiID id)
} }
// Helper to avoid a common series of PushOverrideID -> GetID() -> PopID() call // Helper to avoid a common series of PushOverrideID -> GetID() -> PopID() call
// (note that when using this pattern, TestEngine's "Stack Tool" will tend to not display the intermediate stack level. // (note that when using this pattern, ID Stack Tool will tend to not display the intermediate stack level.
// for that to work we would need to do PushOverrideID() -> ItemAdd() -> PopID() which would alter widget code a little more) // for that to work we would need to do PushOverrideID() -> ItemAdd() -> PopID() which would alter widget code a little more)
ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed) ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed)
{ {
@ -8993,9 +9015,8 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c
if (clip) if (clip)
rect_clipped.ClipWith(g.CurrentWindow->ClipRect); rect_clipped.ClipWith(g.CurrentWindow->ClipRect);
// Expand for touch input // Hit testing, expanded for touch input
const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding); if (!rect_clipped.ContainsWithPad(g.IO.MousePos, g.Style.TouchExtraPadding))
if (!rect_for_touch.Contains(g.IO.MousePos))
return false; return false;
if (!g.MouseViewport->GetMainRect().Overlaps(rect_clipped)) if (!g.MouseViewport->GetMainRect().Overlaps(rect_clipped))
return false; return false;
@ -10506,6 +10527,7 @@ void ImGui::BeginGroup()
ImGuiGroupData& group_data = g.GroupStack.back(); ImGuiGroupData& group_data = g.GroupStack.back();
group_data.WindowID = window->ID; group_data.WindowID = window->ID;
group_data.BackupCursorPos = window->DC.CursorPos; group_data.BackupCursorPos = window->DC.CursorPos;
group_data.BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
group_data.BackupCursorMaxPos = window->DC.CursorMaxPos; group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
group_data.BackupIndent = window->DC.Indent; group_data.BackupIndent = window->DC.Indent;
group_data.BackupGroupOffset = window->DC.GroupOffset; group_data.BackupGroupOffset = window->DC.GroupOffset;
@ -10513,6 +10535,7 @@ void ImGui::BeginGroup()
group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset; group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive; group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0; group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
group_data.BackupIsSameLine = window->DC.IsSameLine;
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive; group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
group_data.EmitItem = true; group_data.EmitItem = true;
@ -10539,11 +10562,13 @@ void ImGui::EndGroup()
ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos)); ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos));
window->DC.CursorPos = 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, window->DC.CursorMaxPos);
window->DC.Indent = group_data.BackupIndent; window->DC.Indent = group_data.BackupIndent;
window->DC.GroupOffset = group_data.BackupGroupOffset; window->DC.GroupOffset = group_data.BackupGroupOffset;
window->DC.CurrLineSize = group_data.BackupCurrLineSize; window->DC.CurrLineSize = group_data.BackupCurrLineSize;
window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset; window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
window->DC.IsSameLine = group_data.BackupIsSameLine;
if (g.LogEnabled) if (g.LogEnabled)
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
@ -19300,8 +19325,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig; ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
if (cfg->ShowDebugLog) if (cfg->ShowDebugLog)
ShowDebugLogWindow(&cfg->ShowDebugLog); ShowDebugLogWindow(&cfg->ShowDebugLog);
if (cfg->ShowStackTool) if (cfg->ShowIdStackTool)
ShowStackToolWindow(&cfg->ShowStackTool); ShowIdStackToolWindow(&cfg->ShowIdStackTool);
if (!Begin("Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1) if (!Begin("Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1)
{ {
@ -19313,7 +19338,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text("Dear ImGui %s", GetVersion()); Text("Dear ImGui %s", GetVersion());
Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3); Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
Text("%d visible windows, %d active allocations", io.MetricsRenderWindows, io.MetricsActiveAllocations); Text("%d visible windows, %d current allocations", io.MetricsRenderWindows, g.DebugAllocInfo.TotalAllocCount - g.DebugAllocInfo.TotalFreeCount);
//SameLine(); if (SmallButton("GC")) { g.GcCompactAll = true; } //SameLine(); if (SmallButton("GC")) { g.GcCompactAll = true; }
Separator(); Separator();
@ -19387,15 +19412,13 @@ void ImGui::ShowMetricsWindow(bool* p_open)
SameLine(); SameLine();
MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash."); MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash.");
// Stack Tool is your best friend!
Checkbox("Show Debug Log", &cfg->ShowDebugLog); Checkbox("Show Debug Log", &cfg->ShowDebugLog);
SameLine(); SameLine();
MetricsHelpMarker("You can also call ImGui::ShowDebugLogWindow() from your code."); MetricsHelpMarker("You can also call ImGui::ShowDebugLogWindow() from your code.");
// Stack Tool is your best friend! Checkbox("Show ID Stack Tool", &cfg->ShowIdStackTool);
Checkbox("Show Stack Tool", &cfg->ShowStackTool);
SameLine(); SameLine();
MetricsHelpMarker("You can also call ImGui::ShowStackToolWindow() from your code."); MetricsHelpMarker("You can also call ImGui::ShowIdStackToolWindow() from your code.");
Checkbox("Show windows begin order", &cfg->ShowWindowsBeginOrder); Checkbox("Show windows begin order", &cfg->ShowWindowsBeginOrder);
Checkbox("Show windows rectangles", &cfg->ShowWindowsRects); Checkbox("Show windows rectangles", &cfg->ShowWindowsRects);
@ -19703,6 +19726,20 @@ void ImGui::ShowMetricsWindow(bool* p_open)
TreePop(); TreePop();
} }
// Settings
if (TreeNode("Memory allocations"))
{
ImGuiDebugAllocInfo* info = &g.DebugAllocInfo;
Text("%d current allocations", info->TotalAllocCount - info->TotalFreeCount);
int buf_size = IM_ARRAYSIZE(info->LastEntriesBuf);
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 )", entry->FrameCount, entry->AllocCount - entry->FreeCount, entry->AllocCount, entry->FreeCount);
}
TreePop();
}
if (TreeNode("Inputs")) if (TreeNode("Inputs"))
{ {
Text("KEYBOARD/GAMEPAD/MOUSE KEYS"); Text("KEYBOARD/GAMEPAD/MOUSE KEYS");
@ -20517,7 +20554,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, STACK TOOL) // [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Draw a small cross at current CursorPos in current window's DrawList // Draw a small cross at current CursorPos in current window's DrawList
@ -20618,13 +20655,13 @@ void ImGui::UpdateDebugToolItemPicker()
EndTooltip(); EndTooltip();
} }
// [DEBUG] Stack Tool: update queries. Called by NewFrame() // [DEBUG] ID Stack Tool: update queries. Called by NewFrame()
void ImGui::UpdateDebugToolStackQueries() void ImGui::UpdateDebugToolStackQueries()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiStackTool* tool = &g.DebugStackTool; ImGuiIdStackTool* tool = &g.DebugIdStackTool;
// Clear hook when stack tool is not visible // Clear hook when id stack tool is not visible
g.DebugHookIdInfo = 0; g.DebugHookIdInfo = 0;
if (g.FrameCount != tool->LastActiveFrame + 1) if (g.FrameCount != tool->LastActiveFrame + 1)
return; return;
@ -20658,12 +20695,12 @@ void ImGui::UpdateDebugToolStackQueries()
} }
} }
// [DEBUG] Stack tool: hooks called by GetID() family functions // [DEBUG] ID Stack tool: hooks called by GetID() family functions
void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end) void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
ImGuiStackTool* tool = &g.DebugStackTool; ImGuiIdStackTool* tool = &g.DebugIdStackTool;
// Step 0: stack query // Step 0: stack query
// This assumes that the ID was computed with the current ID stack, which tends to be the case for our widget. // This assumes that the ID was computed with the current ID stack, which tends to be the case for our widget.
@ -20706,7 +20743,7 @@ void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* dat
info->DataType = data_type; info->DataType = data_type;
} }
static int StackToolFormatLevelInfo(ImGuiStackTool* tool, int n, bool format_for_ui, char* buf, size_t buf_size) static int StackToolFormatLevelInfo(ImGuiIdStackTool* tool, int n, bool format_for_ui, char* buf, size_t buf_size)
{ {
ImGuiStackLevelInfo* info = &tool->Results[n]; ImGuiStackLevelInfo* info = &tool->Results[n];
ImGuiWindow* window = (info->Desc[0] == 0 && n == 0) ? ImGui::FindWindowByID(info->ID) : NULL; ImGuiWindow* window = (info->Desc[0] == 0 && n == 0) ? ImGui::FindWindowByID(info->ID) : NULL;
@ -20723,20 +20760,20 @@ static int StackToolFormatLevelInfo(ImGuiStackTool* tool, int n, bool format_for
return ImFormatString(buf, buf_size, "???"); return ImFormatString(buf, buf_size, "???");
} }
// Stack Tool: Display UI // ID Stack Tool: Display UI
void ImGui::ShowStackToolWindow(bool* p_open) void ImGui::ShowIdStackToolWindow(bool* p_open)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (!(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)) if (!(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize))
SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver); SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver);
if (!Begin("Dear ImGui Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1) if (!Begin("Dear ImGui ID Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1)
{ {
End(); End();
return; return;
} }
// Display hovered/active status // Display hovered/active status
ImGuiStackTool* tool = &g.DebugStackTool; ImGuiIdStackTool* tool = &g.DebugIdStackTool;
const ImGuiID hovered_id = g.HoveredIdPreviousFrame; const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
const ImGuiID active_id = g.ActiveId; const ImGuiID active_id = g.ActiveId;
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
@ -20818,7 +20855,7 @@ void ImGui::DebugNodeViewport(ImGuiViewportP*) {}
void ImGui::DebugLog(const char*, ...) {} void ImGui::DebugLog(const char*, ...) {}
void ImGui::DebugLogV(const char*, va_list) {} void ImGui::DebugLogV(const char*, va_list) {}
void ImGui::ShowDebugLogWindow(bool*) {} void ImGui::ShowDebugLogWindow(bool*) {}
void ImGui::ShowStackToolWindow(bool*) {} void ImGui::ShowIdStackToolWindow(bool*) {}
void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {} void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {}
void ImGui::UpdateDebugToolItemPicker() {} void ImGui::UpdateDebugToolItemPicker() {}
void ImGui::UpdateDebugToolStackQueries() {} void ImGui::UpdateDebugToolStackQueries() {}

@ -313,7 +313,7 @@ namespace ImGui
IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create Demo window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create Demo window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application!
IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create Metrics/Debugger window. display Dear ImGui internals: windows, draw commands, various internal state, etc. IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create Metrics/Debugger window. display Dear ImGui internals: windows, draw commands, various internal state, etc.
IMGUI_API void ShowDebugLogWindow(bool* p_open = NULL); // create Debug Log window. display a simplified log of important dear imgui events. IMGUI_API void ShowDebugLogWindow(bool* p_open = NULL); // create Debug Log window. display a simplified log of important dear imgui events.
IMGUI_API void ShowStackToolWindow(bool* p_open = NULL); // create Stack Tool window. hover items with mouse to query information about the source of their unique ID. IMGUI_API void ShowIdStackToolWindow(bool* p_open = NULL); // create Stack Tool window. hover items with mouse to query information about the source of their unique ID.
IMGUI_API void ShowAboutWindow(bool* p_open = NULL); // create About window. display Dear ImGui version, credits and build/system information. IMGUI_API void ShowAboutWindow(bool* p_open = NULL); // create About window. display Dear ImGui version, credits and build/system information.
IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style)
IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles. IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles.
@ -2134,11 +2134,6 @@ struct ImGuiIO
// 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) // 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) // (default to use native imm32 api on Windows)
void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data); void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
void* ImeWindowHandle; // = NULL // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
#else
void* _UnusedPadding; // Unused field to keep data structure the same size.
#endif
// Optional: Platform locale // 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 ImWchar PlatformLocaleDecimalPoint; // '.' // [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point
@ -2186,7 +2181,6 @@ struct ImGuiIO
int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3
int MetricsRenderWindows; // Number of visible windows int MetricsRenderWindows; // Number of visible windows
int MetricsActiveWindows; // Number of active windows int MetricsActiveWindows; // Number of active windows
int MetricsActiveAllocations; // Number of active allocations, updated by MemAlloc/MemFree based on current context. May be off if you have multiple imgui contexts.
ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta. ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta.
// Legacy: before 1.87, we required backend to fill io.KeyMap[] (imgui->native map) during initialization and io.KeysDown[] (native indices) every frame. // Legacy: before 1.87, we required backend to fill io.KeyMap[] (imgui->native map) during initialization and io.KeysDown[] (native indices) every frame.
@ -2197,6 +2191,11 @@ struct ImGuiIO
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. 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. 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.
#endif #endif
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
void* ImeWindowHandle; // = NULL // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
#else
void* _UnusedPadding;
#endif
//------------------------------------------------------------------ //------------------------------------------------------------------
// [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed! // [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed!
@ -3366,6 +3365,7 @@ namespace ImGui
namespace ImGui namespace ImGui
{ {
// OBSOLETED in 1.90.0 (from September 2023) // OBSOLETED in 1.90.0 (from September 2023)
static inline void ShowStackToolWindow(bool* p_open = NULL) { ShowIdStackToolWindow(p_open); }
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); 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);
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 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);
// OBSOLETED in 1.89.7 (from June 2023) // OBSOLETED in 1.89.7 (from June 2023)

@ -304,7 +304,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
// Dear ImGui Tools (accessible from the "Tools" menu) // Dear ImGui Tools (accessible from the "Tools" menu)
static bool show_tool_metrics = false; static bool show_tool_metrics = false;
static bool show_tool_debug_log = false; static bool show_tool_debug_log = false;
static bool show_tool_stack_tool = false; static bool show_tool_id_stack_tool = false;
static bool show_tool_style_editor = false; static bool show_tool_style_editor = false;
static bool show_tool_about = false; static bool show_tool_about = false;
@ -312,8 +312,8 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::ShowMetricsWindow(&show_tool_metrics); ImGui::ShowMetricsWindow(&show_tool_metrics);
if (show_tool_debug_log) if (show_tool_debug_log)
ImGui::ShowDebugLogWindow(&show_tool_debug_log); ImGui::ShowDebugLogWindow(&show_tool_debug_log);
if (show_tool_stack_tool) if (show_tool_id_stack_tool)
ImGui::ShowStackToolWindow(&show_tool_stack_tool); ImGui::ShowIdStackToolWindow(&show_tool_id_stack_tool);
if (show_tool_style_editor) if (show_tool_style_editor)
{ {
ImGui::Begin("Dear ImGui Style Editor", &show_tool_style_editor); ImGui::Begin("Dear ImGui Style Editor", &show_tool_style_editor);
@ -415,7 +415,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
#endif #endif
ImGui::MenuItem("Metrics/Debugger", NULL, &show_tool_metrics, has_debug_tools); ImGui::MenuItem("Metrics/Debugger", NULL, &show_tool_metrics, has_debug_tools);
ImGui::MenuItem("Debug Log", NULL, &show_tool_debug_log, has_debug_tools); ImGui::MenuItem("Debug Log", NULL, &show_tool_debug_log, has_debug_tools);
ImGui::MenuItem("Stack Tool", NULL, &show_tool_stack_tool, has_debug_tools); ImGui::MenuItem("ID Stack Tool", NULL, &show_tool_id_stack_tool, has_debug_tools);
ImGui::MenuItem("Style Editor", NULL, &show_tool_style_editor); ImGui::MenuItem("Style Editor", NULL, &show_tool_style_editor);
ImGui::MenuItem("About Dear ImGui", NULL, &show_tool_about); ImGui::MenuItem("About Dear ImGui", NULL, &show_tool_about);
ImGui::EndMenu(); ImGui::EndMenu();

@ -554,6 +554,7 @@ struct IMGUI_API ImRect
ImVec2 GetBR() const { return Max; } // Bottom-right ImVec2 GetBR() const { return Max; } // Bottom-right
bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; } bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; }
bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x <= Max.x && r.Max.y <= Max.y; } bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x <= Max.x && r.Max.y <= Max.y; }
bool ContainsWithPad(const ImVec2& p, const ImVec2& pad) const { return p.x >= Min.x - pad.x && p.y >= Min.y - pad.y && p.x < Max.x + pad.x && p.y < Max.y + pad.y; }
bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; } bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; } void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; }
void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; } void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; }
@ -1073,6 +1074,7 @@ struct IMGUI_API ImGuiGroupData
ImGuiID WindowID; ImGuiID WindowID;
ImVec2 BackupCursorPos; ImVec2 BackupCursorPos;
ImVec2 BackupCursorMaxPos; ImVec2 BackupCursorMaxPos;
ImVec2 BackupCursorPosPrevLine;
ImVec1 BackupIndent; ImVec1 BackupIndent;
ImVec1 BackupGroupOffset; ImVec1 BackupGroupOffset;
ImVec2 BackupCurrLineSize; ImVec2 BackupCurrLineSize;
@ -1080,6 +1082,7 @@ struct IMGUI_API ImGuiGroupData
ImGuiID BackupActiveIdIsAlive; ImGuiID BackupActiveIdIsAlive;
bool BackupActiveIdPreviousFrameIsAlive; bool BackupActiveIdPreviousFrameIsAlive;
bool BackupHoveredIdIsAlive; bool BackupHoveredIdIsAlive;
bool BackupIsSameLine;
bool EmitItem; bool EmitItem;
}; };
@ -1964,10 +1967,27 @@ enum ImGuiDebugLogFlags_
ImGuiDebugLogFlags_OutputToTestEngine = 1 << 11,// Also send output to Test Engine ImGuiDebugLogFlags_OutputToTestEngine = 1 << 11,// Also send output to Test Engine
}; };
struct ImGuiDebugAllocEntry
{
int FrameCount;
ImS16 AllocCount;
ImS16 FreeCount;
};
struct ImGuiDebugAllocInfo
{
int TotalAllocCount; // Number of call to MemAlloc().
int TotalFreeCount;
ImS16 LastEntriesIdx; // Current index in buffer
ImGuiDebugAllocEntry LastEntriesBuf[6]; // Track last 6 frames that had allocations
ImGuiDebugAllocInfo() { memset(this, 0, sizeof(*this)); }
};
struct ImGuiMetricsConfig struct ImGuiMetricsConfig
{ {
bool ShowDebugLog = false; bool ShowDebugLog = false;
bool ShowStackTool = false; bool ShowIdStackTool = false;
bool ShowWindowsRects = false; bool ShowWindowsRects = false;
bool ShowWindowsBeginOrder = false; bool ShowWindowsBeginOrder = false;
bool ShowTablesRects = false; bool ShowTablesRects = false;
@ -1990,8 +2010,8 @@ struct ImGuiStackLevelInfo
ImGuiStackLevelInfo() { memset(this, 0, sizeof(*this)); } ImGuiStackLevelInfo() { memset(this, 0, sizeof(*this)); }
}; };
// State for Stack tool queries // State for ID Stack tool queries
struct ImGuiStackTool struct ImGuiIdStackTool
{ {
int LastActiveFrame; int LastActiveFrame;
int StackLevel; // -1: query stack and resize Results, >= 0: individual stack level int StackLevel; // -1: query stack and resize Results, >= 0: individual stack level
@ -2000,7 +2020,7 @@ struct ImGuiStackTool
bool CopyToClipboardOnCtrlC; bool CopyToClipboardOnCtrlC;
float CopyToClipboardLastTime; float CopyToClipboardLastTime;
ImGuiStackTool() { memset(this, 0, sizeof(*this)); CopyToClipboardLastTime = -FLT_MAX; } ImGuiIdStackTool() { memset(this, 0, sizeof(*this)); CopyToClipboardLastTime = -FLT_MAX; }
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2076,7 +2096,7 @@ struct ImGuiContext
ImVec2 WheelingAxisAvg; ImVec2 WheelingAxisAvg;
// Item/widgets state and tracking information // Item/widgets state and tracking information
ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line] 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 HoveredId; // Hovered widget, filled during the frame
ImGuiID HoveredIdPreviousFrame; ImGuiID HoveredIdPreviousFrame;
bool HoveredIdAllowOverlap; bool HoveredIdAllowOverlap;
@ -2333,7 +2353,8 @@ struct ImGuiContext
ImU8 DebugItemPickerMouseButton; ImU8 DebugItemPickerMouseButton;
ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID
ImGuiMetricsConfig DebugMetricsConfig; ImGuiMetricsConfig DebugMetricsConfig;
ImGuiStackTool DebugStackTool; ImGuiIdStackTool DebugIdStackTool;
ImGuiDebugAllocInfo DebugAllocInfo;
ImGuiDockNode* DebugHoveredDockNode; // Hovered dock node. ImGuiDockNode* DebugHoveredDockNode; // Hovered dock node.
// Misc // Misc
@ -3629,6 +3650,7 @@ namespace ImGui
// Debug Log // Debug Log
IMGUI_API void DebugLog(const char* fmt, ...) IM_FMTARGS(1); IMGUI_API void DebugLog(const char* fmt, ...) IM_FMTARGS(1);
IMGUI_API void DebugLogV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void DebugLogV(const char* fmt, va_list args) IM_FMTLIST(1);
IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
// Debug Tools // Debug Tools
IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);

@ -7508,7 +7508,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) // 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. // 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.) // (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) if (menu_is_open && !hovered && g.HoveredWindow == window && !moving_toward_child_menu && !g.NavDisableMouseHover && g.ActiveId == 0)
want_close = true; want_close = true;
// Open // Open

Loading…
Cancel
Save