|
@@ -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)
|
|
|
|
|
|
*/
|
|
|
|
|
@@ -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), ...);
|
|
@@ -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;
|
|
@@ -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
|
|
@@ -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)
|
|
|
{
|
|
@@ -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;
|
|
@@ -10506,6 +10527,7 @@ 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;
|
|
@@ -10513,6 +10535,7 @@ void ImGui::BeginGroup()
|
|
|
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;
|
|
|
|
|
@@ -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
|
|
|
|
|
@@ -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)
|
|
|
{
|
|
@@ -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();
|
|
@@ -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);
|
|
@@ -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");
|
|
@@ -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
|
|
@@ -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;
|
|
@@ -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.
|
|
@@ -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;
|
|
@@ -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
|
|
@@ -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() {}
|