Skip to content

Commit 130b449

Browse files
committed
Debug, Metrics: Added "Tools->Item Picker" tool which allow clicking on a widget to break in the debugger within the item code. The tool calls IM_DEBUG_BREAK() which can be redefined in imconfig.h if needed.
1 parent e6a286b commit 130b449

File tree

4 files changed

+62
-5
lines changed

4 files changed

+62
-5
lines changed

docs/CHANGELOG.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ Other Changes:
6161
- Style: Added style.ColorButtonButton (left/right, defaults to ImGuiDir_Right) to move the color button
6262
of ColorEdit3/ColorEdit4 functions to either side of the inputs.
6363
- Misc: Added IMGUI_DISABLE_METRICS_WINDOW imconfig.h setting to explicitly compile out ShowMetricsWindow().
64+
- Debug, Metrics: Added "Tools->Item Picker" tool which allow clicking on a widget to break in the debugger
65+
within the item code. The tool calls IM_DEBUG_BREAK() which can be redefined in imconfig.h if needed.
6466
- ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot]
6567
- ImDrawList::ChannelsSplit(), ImDrawListSplitter: Fixed an issue with merging draw commands between
6668
channel 0 and 1. (#2624)

imconfig.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@
7676
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
7777
//#define ImDrawCallback MyImDrawCallback
7878

79+
//---- Debug Tools
80+
// Use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.
81+
//#define IM_DEBUG_BREAK IM_ASSERT(0)
82+
//#define IM_DEBUG_BREAK __debugbreak()
83+
7984
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
8085
/*
8186
namespace ImGui

imgui.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2862,6 +2862,16 @@ void ImGui::SetHoveredID(ImGuiID id)
28622862
g.HoveredIdAllowOverlap = false;
28632863
if (id != 0 && g.HoveredIdPreviousFrame != id)
28642864
g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f;
2865+
2866+
// [DEBUG] Item Picker tool!
2867+
// We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making
2868+
// the cost of this tool near-zero. We would get slightly better call-stack if we made the test in ItemAdd()
2869+
// but that would incur a slightly higher cost and may require us to hide this feature behind a define.
2870+
if (id != 0 && id == g.DebugBreakItemId)
2871+
{
2872+
IM_DEBUG_BREAK();
2873+
g.DebugBreakItemId = 0;
2874+
}
28652875
}
28662876

28672877
ImGuiID ImGui::GetHoveredID()
@@ -10180,6 +10190,28 @@ void ImGui::ShowMetricsWindow(bool* p_open)
1018010190

1018110191
if (ImGui::TreeNode("Tools"))
1018210192
{
10193+
static bool picking_enabled = false;
10194+
if (ImGui::Button("Item Picker.."))
10195+
picking_enabled = true;
10196+
if (picking_enabled)
10197+
{
10198+
const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
10199+
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
10200+
if (ImGui::IsKeyPressedMap(ImGuiKey_Escape))
10201+
picking_enabled = false;
10202+
if (ImGui::IsMouseClicked(0) && hovered_id)
10203+
{
10204+
g.DebugBreakItemId = hovered_id;
10205+
picking_enabled = false;
10206+
}
10207+
ImGui::SetNextWindowBgAlpha(0.5f);
10208+
ImGui::BeginTooltip();
10209+
ImGui::Text("HoveredId: 0x%08X", hovered_id);
10210+
ImGui::Text("Press ESC to abort picking.");
10211+
ImGui::TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!");
10212+
ImGui::EndTooltip();
10213+
}
10214+
1018310215
ImGui::Checkbox("Show windows begin order", &show_windows_begin_order);
1018410216
ImGui::Checkbox("Show windows rectangles", &show_windows_rects);
1018510217
ImGui::SameLine();
@@ -10225,10 +10257,11 @@ void ImGui::ShowMetricsWindow(bool* p_open)
1022510257
}
1022610258
ImGui::End();
1022710259
}
10260+
1022810261
#else
10229-
void ImGui::ShowMetricsWindow(bool*)
10230-
{
10231-
}
10262+
10263+
void ImGui::ShowMetricsWindow(bool*) { }
10264+
1023210265
#endif
1023310266

1023410267
//-----------------------------------------------------------------------------

imgui_internal.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ enum ImGuiItemStatusFlags_
401401
ImGuiItemStatusFlags_Deactivated = 1 << 5 // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
402402

403403
#ifdef IMGUI_ENABLE_TEST_ENGINE
404-
, // [imgui-test only]
404+
, // [imgui_tests only]
405405
ImGuiItemStatusFlags_Openable = 1 << 10, //
406406
ImGuiItemStatusFlags_Opened = 1 << 11, //
407407
ImGuiItemStatusFlags_Checkable = 1 << 12, //
@@ -1028,6 +1028,9 @@ struct ImGuiContext
10281028
int LogDepthToExpand;
10291029
int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call.
10301030

1031+
// Debug Tools
1032+
ImGuiID DebugBreakItemId;
1033+
10311034
// Misc
10321035
float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds.
10331036
int FramerateSecPerFrameIdx;
@@ -1153,6 +1156,8 @@ struct ImGuiContext
11531156
LogDepthRef = 0;
11541157
LogDepthToExpand = LogDepthToExpandDefault = 2;
11551158

1159+
DebugBreakItemId = 0;
1160+
11561161
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
11571162
FramerateSecPerFrameIdx = 0;
11581163
FramerateSecPerFrameAccum = 0.0f;
@@ -1662,7 +1667,19 @@ IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas);
16621667
IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor);
16631668
IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride);
16641669

1665-
// Test engine hooks (imgui-test)
1670+
// Debug Tools
1671+
// Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item.
1672+
#ifndef IM_DEBUG_BREAK
1673+
#if defined(__clang__)
1674+
#define IM_DEBUG_BREAK() __builtin_debugtrap()
1675+
#elif defined (_MSC_VER)
1676+
#define IM_DEBUG_BREAK() __debugbreak()
1677+
#else
1678+
#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger!
1679+
#endif
1680+
#endif // #ifndef IM_DEBUG_BREAK
1681+
1682+
// Test Engine Hooks (imgui_tests)
16661683
//#define IMGUI_ENABLE_TEST_ENGINE
16671684
#ifdef IMGUI_ENABLE_TEST_ENGINE
16681685
extern void ImGuiTestEngineHook_PreNewFrame(ImGuiContext* ctx);

0 commit comments

Comments
 (0)