Skip to content

Commit

Permalink
Merge branch 'master' into docking
Browse files Browse the repository at this point in the history
# Conflicts:
#	imgui.cpp
#	imgui_internal.h
  • Loading branch information
ocornut committed Sep 27, 2023
2 parents bb2fb74 + 2f431a9 commit b7c2509
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 58 deletions.
9 changes: 9 additions & 0 deletions docs/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ HOW TO UPDATE?

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.
Before:
getter type: bool (*getter)(void* user_data, int idx, const char** out_text)
Expand Down Expand Up @@ -91,12 +95,17 @@ Other changes:
(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
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.
- 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
register contents size in a way that would affect the scrolling layer.
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)
- 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]
- ImVector: Added find_index() helper.
- Backends: GLFW: Clear emscripten's MouseWheel callback before shutdown. (#6790, #6096, #4019) [@halx99]
Expand Down
2 changes: 1 addition & 1 deletion docs/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 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)

Expand Down
2 changes: 1 addition & 1 deletion imconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//#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_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.
//#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)
Expand Down
113 changes: 75 additions & 38 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ CODE
// [SECTION] PLATFORM DEPENDENT HELPERS
// [SECTION] METRICS/DEBUGGER WINDOW
// [SECTION] DEBUG LOG WINDOW
// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, STACK TOOL)
// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL)

*/

Expand Down Expand Up @@ -432,6 +432,8 @@ CODE
- 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.

- 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).
- 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), ...);
Expand Down Expand Up @@ -4320,26 +4322,50 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
void* ImGui::MemAlloc(size_t size)
{
void* ptr = (*GImAllocatorAllocFunc)(size, GImAllocatorUserData);
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
if (ImGuiContext* ctx = GImGui)
{
ctx->IO.MetricsActiveAllocations++;
//printf("[%05d] MemAlloc(%d) -> 0x%p\n", ctx->FrameCount, size, ptr);
}
DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, size);
#endif
return ptr;
}

// IM_FREE() == ImGui::MemFree()
void ImGui::MemFree(void* ptr)
{
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
if (ptr != NULL)
if (ImGuiContext* ctx = GImGui)
{
ctx->IO.MetricsActiveAllocations--;
//printf("[%05d] MemFree(0x%p)\n", ctx->FrameCount, ptr);
}
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)
{
info->LastEntriesIdx = (info->LastEntriesIdx + 1) % IM_ARRAYSIZE(info->LastEntriesBuf);
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);
}
}

const char* ImGui::GetClipboardText()
{
ImGuiContext& g = *GImGui;
Expand Down Expand Up @@ -5478,12 +5504,8 @@ static void FindHoveredWindow()
continue;

// Using the clipped AABB, a child window will typically be clipped by its parent (not always)
ImRect bb(window->OuterRectClipped);
if (window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize))
bb.Expand(padding_regular);
else
bb.Expand(padding_for_resize);
if (!bb.Contains(g.IO.MousePos))
ImVec2 hit_padding = (window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) ? padding_regular : padding_for_resize;
if (!window->OuterRectClipped.ContainsWithPad(g.IO.MousePos, hit_padding))
continue;

// Support for one rectangular hole in any given window
Expand Down Expand Up @@ -8408,7 +8430,7 @@ void ImGui::PushOverrideID(ImGuiID id)
}

// 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)
ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed)
{
Expand Down Expand Up @@ -8993,9 +9015,8 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c
if (clip)
rect_clipped.ClipWith(g.CurrentWindow->ClipRect);

// Expand for touch input
const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding);
if (!rect_for_touch.Contains(g.IO.MousePos))
// Hit testing, expanded for touch input
if (!rect_clipped.ContainsWithPad(g.IO.MousePos, g.Style.TouchExtraPadding))
return false;
if (!g.MouseViewport->GetMainRect().Overlaps(rect_clipped))
return false;
Expand Down Expand Up @@ -10506,13 +10527,15 @@ void ImGui::BeginGroup()
ImGuiGroupData& group_data = g.GroupStack.back();
group_data.WindowID = window->ID;
group_data.BackupCursorPos = window->DC.CursorPos;
group_data.BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
group_data.BackupIndent = window->DC.Indent;
group_data.BackupGroupOffset = window->DC.GroupOffset;
group_data.BackupCurrLineSize = window->DC.CurrLineSize;
group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
group_data.BackupIsSameLine = window->DC.IsSameLine;
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
group_data.EmitItem = true;

Expand All @@ -10539,11 +10562,13 @@ void ImGui::EndGroup()
ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, 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.Indent = group_data.BackupIndent;
window->DC.GroupOffset = group_data.BackupGroupOffset;
window->DC.CurrLineSize = group_data.BackupCurrLineSize;
window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
window->DC.IsSameLine = group_data.BackupIsSameLine;
if (g.LogEnabled)
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return

Expand Down Expand Up @@ -19300,8 +19325,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
if (cfg->ShowDebugLog)
ShowDebugLogWindow(&cfg->ShowDebugLog);
if (cfg->ShowStackTool)
ShowStackToolWindow(&cfg->ShowStackTool);
if (cfg->ShowIdStackTool)
ShowIdStackToolWindow(&cfg->ShowIdStackTool);

if (!Begin("Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1)
{
Expand All @@ -19313,7 +19338,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text("Dear ImGui %s", GetVersion());
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 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; }

Separator();
Expand Down Expand Up @@ -19387,15 +19412,13 @@ void ImGui::ShowMetricsWindow(bool* p_open)
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.");

// Stack Tool is your best friend!
Checkbox("Show Debug Log", &cfg->ShowDebugLog);
SameLine();
MetricsHelpMarker("You can also call ImGui::ShowDebugLogWindow() from your code.");

// Stack Tool is your best friend!
Checkbox("Show Stack Tool", &cfg->ShowStackTool);
Checkbox("Show ID Stack Tool", &cfg->ShowIdStackTool);
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 rectangles", &cfg->ShowWindowsRects);
Expand Down Expand Up @@ -19703,6 +19726,20 @@ void ImGui::ShowMetricsWindow(bool* p_open)
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"))
{
Text("KEYBOARD/GAMEPAD/MOUSE KEYS");
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -20618,13 +20655,13 @@ void ImGui::UpdateDebugToolItemPicker()
EndTooltip();
}

// [DEBUG] Stack Tool: update queries. Called by NewFrame()
// [DEBUG] ID Stack Tool: update queries. Called by NewFrame()
void ImGui::UpdateDebugToolStackQueries()
{
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;
if (g.FrameCount != tool->LastActiveFrame + 1)
return;
Expand Down Expand Up @@ -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)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiStackTool* tool = &g.DebugStackTool;
ImGuiIdStackTool* tool = &g.DebugIdStackTool;

// 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.
Expand Down Expand Up @@ -20706,7 +20743,7 @@ void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* dat
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];
ImGuiWindow* window = (info->Desc[0] == 0 && n == 0) ? ImGui::FindWindowByID(info->ID) : NULL;
Expand All @@ -20723,20 +20760,20 @@ static int StackToolFormatLevelInfo(ImGuiStackTool* tool, int n, bool format_for
return ImFormatString(buf, buf_size, "???");
}

// Stack Tool: Display UI
void ImGui::ShowStackToolWindow(bool* p_open)
// ID Stack Tool: Display UI
void ImGui::ShowIdStackToolWindow(bool* p_open)
{
ImGuiContext& g = *GImGui;
if (!(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize))
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();
return;
}

// Display hovered/active status
ImGuiStackTool* tool = &g.DebugStackTool;
ImGuiIdStackTool* tool = &g.DebugIdStackTool;
const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
const ImGuiID active_id = g.ActiveId;
#ifdef IMGUI_ENABLE_TEST_ENGINE
Expand Down Expand Up @@ -20818,7 +20855,7 @@ void ImGui::DebugNodeViewport(ImGuiViewportP*) {}
void ImGui::DebugLog(const char*, ...) {}
void ImGui::DebugLogV(const char*, va_list) {}
void ImGui::ShowDebugLogWindow(bool*) {}
void ImGui::ShowStackToolWindow(bool*) {}
void ImGui::ShowIdStackToolWindow(bool*) {}
void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {}
void ImGui::UpdateDebugToolItemPicker() {}
void ImGui::UpdateDebugToolStackQueries() {}
Expand Down
Loading

0 comments on commit b7c2509

Please sign in to comment.