mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-03 22:51:06 +01:00 
			
		
		
		
	Merge branch 'master' into docking
# Conflicts: # imgui.cpp
This commit is contained in:
		
							
								
								
									
										400
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										400
									
								
								imgui.cpp
									
									
									
									
									
								
							@@ -83,6 +83,7 @@ CODE
 | 
			
		||||
// [SECTION] DOCKING
 | 
			
		||||
// [SECTION] PLATFORM DEPENDENT HELPERS
 | 
			
		||||
// [SECTION] METRICS/DEBUGGER WINDOW
 | 
			
		||||
// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, STACK TOOL)
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
@@ -937,16 +938,17 @@ static ImGuiWindow*     NavRestoreLastChildNavWindow(ImGuiWindow* window);
 | 
			
		||||
static void             NavRestoreLayer(ImGuiNavLayer layer);
 | 
			
		||||
static int              FindWindowFocusIndex(ImGuiWindow* window);
 | 
			
		||||
 | 
			
		||||
// Error Checking
 | 
			
		||||
// Error Checking and Debug Tools
 | 
			
		||||
static void             ErrorCheckNewFrameSanityChecks();
 | 
			
		||||
static void             ErrorCheckEndFrameSanityChecks();
 | 
			
		||||
static void             UpdateDebugToolItemPicker();
 | 
			
		||||
static void             UpdateDebugToolStackQueries();
 | 
			
		||||
 | 
			
		||||
// Misc
 | 
			
		||||
static void             UpdateSettings();
 | 
			
		||||
static void             UpdateMouseInputs();
 | 
			
		||||
static void             UpdateMouseWheel();
 | 
			
		||||
static void             UpdateTabFocus();
 | 
			
		||||
static void             UpdateDebugToolItemPicker();
 | 
			
		||||
static bool             UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect);
 | 
			
		||||
static void             RenderWindowOuterBorders(ImGuiWindow* window);
 | 
			
		||||
static void             RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, bool handle_borders_and_resize_grips, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size);
 | 
			
		||||
@@ -3013,10 +3015,9 @@ ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
 | 
			
		||||
    ImGuiID seed = IDStack.back();
 | 
			
		||||
    ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
 | 
			
		||||
    ImGui::KeepAliveID(id);
 | 
			
		||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    IMGUI_TEST_ENGINE_ID_INFO2(id, ImGuiDataType_String, str, str_end);
 | 
			
		||||
#endif
 | 
			
		||||
    if (g.DebugHookIdInfo == id)
 | 
			
		||||
        ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end);
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3025,10 +3026,9 @@ ImGuiID ImGuiWindow::GetID(const void* ptr)
 | 
			
		||||
    ImGuiID seed = IDStack.back();
 | 
			
		||||
    ImGuiID id = ImHashData(&ptr, sizeof(void*), seed);
 | 
			
		||||
    ImGui::KeepAliveID(id);
 | 
			
		||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_Pointer, ptr);
 | 
			
		||||
#endif
 | 
			
		||||
    if (g.DebugHookIdInfo == id)
 | 
			
		||||
        ImGui::DebugHookIdInfo(id, ImGuiDataType_Pointer, ptr, NULL);
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3037,10 +3037,9 @@ ImGuiID ImGuiWindow::GetID(int n)
 | 
			
		||||
    ImGuiID seed = IDStack.back();
 | 
			
		||||
    ImGuiID id = ImHashData(&n, sizeof(n), seed);
 | 
			
		||||
    ImGui::KeepAliveID(id);
 | 
			
		||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_S32, (intptr_t)n);
 | 
			
		||||
#endif
 | 
			
		||||
    if (g.DebugHookIdInfo == id)
 | 
			
		||||
        ImGui::DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL);
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3048,10 +3047,9 @@ ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiID seed = IDStack.back();
 | 
			
		||||
    ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
 | 
			
		||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    IMGUI_TEST_ENGINE_ID_INFO2(id, ImGuiDataType_String, str, str_end);
 | 
			
		||||
#endif
 | 
			
		||||
    if (g.DebugHookIdInfo == id)
 | 
			
		||||
        ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end);
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3059,10 +3057,9 @@ ImGuiID ImGuiWindow::GetIDNoKeepAlive(const void* ptr)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiID seed = IDStack.back();
 | 
			
		||||
    ImGuiID id = ImHashData(&ptr, sizeof(void*), seed);
 | 
			
		||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_Pointer, ptr);
 | 
			
		||||
#endif
 | 
			
		||||
    if (g.DebugHookIdInfo == id)
 | 
			
		||||
        ImGui::DebugHookIdInfo(id, ImGuiDataType_Pointer, ptr, NULL);
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3070,10 +3067,9 @@ ImGuiID ImGuiWindow::GetIDNoKeepAlive(int n)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiID seed = IDStack.back();
 | 
			
		||||
    ImGuiID id = ImHashData(&n, sizeof(n), seed);
 | 
			
		||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    IMGUI_TEST_ENGINE_ID_INFO(id, ImGuiDataType_S32, (intptr_t)n);
 | 
			
		||||
#endif
 | 
			
		||||
    if (g.DebugHookIdInfo == id)
 | 
			
		||||
        ImGui::DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL);
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3251,7 +3247,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
 | 
			
		||||
    ImGuiItemStatusFlags status_flags = g.LastItemData.StatusFlags;
 | 
			
		||||
    if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
 | 
			
		||||
        return false;
 | 
			
		||||
    IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0);   // Flags not supported by this function
 | 
			
		||||
    IM_ASSERT((flags & (ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy | ImGuiHoveredFlags_DockHierarchy)) == 0);   // Flags not supported by this function
 | 
			
		||||
 | 
			
		||||
    // Test if we are hovering the right window (our window could be behind another window)
 | 
			
		||||
    // [2021/03/02] Reworked / reverted the revert, finally. Note we want e.g. BeginGroup/ItemAdd/EndGroup to work as well. (#3851)
 | 
			
		||||
@@ -3380,7 +3376,7 @@ void ImGui::ItemInputable(ImGuiWindow* window, ImGuiID id)
 | 
			
		||||
 | 
			
		||||
    // Process TAB/Shift-TAB to tab *OUT* of the currently focused item.
 | 
			
		||||
    // (Note that we can always TAB out of a widget that doesn't allow tabbing in)
 | 
			
		||||
    if (g.ActiveId == id && g.TabFocusPressed && !IsActiveIdUsingKey(ImGuiKey_Tab) && g.TabFocusRequestNextWindow == NULL)
 | 
			
		||||
    if (g.ActiveId == id && g.TabFocusPressed && g.TabFocusRequestNextWindow == NULL)
 | 
			
		||||
    {
 | 
			
		||||
        g.TabFocusRequestNextWindow = window;
 | 
			
		||||
        g.TabFocusRequestNextCounterTabStop = window->DC.FocusCounterTabStop + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
 | 
			
		||||
@@ -3981,7 +3977,7 @@ void ImGui::UpdateTabFocus()
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
 | 
			
		||||
    // Pressing TAB activate widget focus
 | 
			
		||||
    g.TabFocusPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
 | 
			
		||||
    g.TabFocusPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && !IsActiveIdUsingKey(ImGuiKey_Tab));
 | 
			
		||||
    if (g.ActiveId == 0 && g.TabFocusPressed)
 | 
			
		||||
    {
 | 
			
		||||
        // - This path is only taken when no widget are active/tabbed-into yet.
 | 
			
		||||
@@ -4314,8 +4310,9 @@ void ImGui::NewFrame()
 | 
			
		||||
    // Docking
 | 
			
		||||
    DockContextNewFrameUpdateDocking(&g);
 | 
			
		||||
 | 
			
		||||
    // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack.
 | 
			
		||||
    // [DEBUG] Update debug features
 | 
			
		||||
    UpdateDebugToolItemPicker();
 | 
			
		||||
    UpdateDebugToolStackQueries();
 | 
			
		||||
 | 
			
		||||
    // Create implicit/fallback window - which we will only render it if the user has added something to it.
 | 
			
		||||
    // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
 | 
			
		||||
@@ -4328,31 +4325,6 @@ void ImGui::NewFrame()
 | 
			
		||||
    CallContextHooks(&g, ImGuiContextHookType_NewFramePost);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack.
 | 
			
		||||
void ImGui::UpdateDebugToolItemPicker()
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    g.DebugItemPickerBreakId = 0;
 | 
			
		||||
    if (g.DebugItemPickerActive)
 | 
			
		||||
    {
 | 
			
		||||
        const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
 | 
			
		||||
        SetMouseCursor(ImGuiMouseCursor_Hand);
 | 
			
		||||
        if (IsKeyPressedMap(ImGuiKey_Escape))
 | 
			
		||||
            g.DebugItemPickerActive = false;
 | 
			
		||||
        if (IsMouseClicked(0) && hovered_id)
 | 
			
		||||
        {
 | 
			
		||||
            g.DebugItemPickerBreakId = hovered_id;
 | 
			
		||||
            g.DebugItemPickerActive = false;
 | 
			
		||||
        }
 | 
			
		||||
        SetNextWindowBgAlpha(0.60f);
 | 
			
		||||
        BeginTooltip();
 | 
			
		||||
        Text("HoveredId: 0x%08X", hovered_id);
 | 
			
		||||
        Text("Press ESC to abort picking.");
 | 
			
		||||
        TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!");
 | 
			
		||||
        EndTooltip();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImGui::Initialize(ImGuiContext* context)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *context;
 | 
			
		||||
@@ -7312,7 +7284,7 @@ bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_b
 | 
			
		||||
 | 
			
		||||
bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
 | 
			
		||||
{
 | 
			
		||||
    IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0);   // Flags not supported by this function
 | 
			
		||||
    IM_ASSERT((flags & (ImGuiHoveredFlags_AllowWhenOverlapped | ImGuiHoveredFlags_AllowWhenDisabled)) == 0);   // Flags not supported by this function
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    ImGuiWindow* ref_window = g.HoveredWindow;
 | 
			
		||||
    ImGuiWindow* cur_window = g.CurrentWindow;
 | 
			
		||||
@@ -7779,6 +7751,8 @@ void ImGui::PushOverrideID(ImGuiID id)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    ImGuiWindow* window = g.CurrentWindow;
 | 
			
		||||
    if (g.DebugHookIdInfo == id)
 | 
			
		||||
        DebugHookIdInfo(id, ImGuiDataType_ID, NULL, NULL);
 | 
			
		||||
    window->IDStack.push_back(id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -7788,11 +7762,10 @@ void ImGui::PushOverrideID(ImGuiID id)
 | 
			
		||||
ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
 | 
			
		||||
    ImGui::KeepAliveID(id);
 | 
			
		||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
			
		||||
    KeepAliveID(id);
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    IMGUI_TEST_ENGINE_ID_INFO2(id, ImGuiDataType_String, str, str_end);
 | 
			
		||||
#endif
 | 
			
		||||
    if (g.DebugHookIdInfo == id)
 | 
			
		||||
        DebugHookIdInfo(id, ImGuiDataType_String, str, str_end);
 | 
			
		||||
    return id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -8643,32 +8616,80 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)
 | 
			
		||||
    return scroll;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImGui::ScrollToItem(ImGuiScrollFlags flags)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    ImGuiWindow* window = g.CurrentWindow;
 | 
			
		||||
    ScrollToRectEx(window, g.LastItemData.NavRect, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImGui::ScrollToRect(ImGuiWindow* window, const ImRect& item_rect, ImGuiScrollFlags flags)
 | 
			
		||||
{
 | 
			
		||||
    ScrollToRectEx(window, item_rect, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Scroll to keep newly navigated item fully into view
 | 
			
		||||
ImVec2 ImGui::ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_rect)
 | 
			
		||||
ImVec2 ImGui::ScrollToRectEx(ImGuiWindow* window, const ImRect& item_rect, ImGuiScrollFlags flags)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    ImRect window_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1));
 | 
			
		||||
    //GetForegroundDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG]
 | 
			
		||||
 | 
			
		||||
    ImVec2 delta_scroll;
 | 
			
		||||
    if (!window_rect.Contains(item_rect))
 | 
			
		||||
    {
 | 
			
		||||
        if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x)
 | 
			
		||||
            SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x - g.Style.ItemSpacing.x, 0.0f);
 | 
			
		||||
        else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x)
 | 
			
		||||
            SetScrollFromPosX(window, item_rect.Max.x - window->Pos.x + g.Style.ItemSpacing.x, 1.0f);
 | 
			
		||||
        if (item_rect.Min.y < window_rect.Min.y)
 | 
			
		||||
            SetScrollFromPosY(window, item_rect.Min.y - window->Pos.y - g.Style.ItemSpacing.y, 0.0f);
 | 
			
		||||
        else if (item_rect.Max.y >= window_rect.Max.y)
 | 
			
		||||
            SetScrollFromPosY(window, item_rect.Max.y - window->Pos.y + g.Style.ItemSpacing.y, 1.0f);
 | 
			
		||||
    // Check that only one behavior is selected per axis
 | 
			
		||||
    IM_ASSERT((flags & ImGuiScrollFlags_MaskX_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskX_));
 | 
			
		||||
    IM_ASSERT((flags & ImGuiScrollFlags_MaskY_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskY_));
 | 
			
		||||
 | 
			
		||||
        ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
 | 
			
		||||
        delta_scroll = next_scroll - window->Scroll;
 | 
			
		||||
    // Defaults
 | 
			
		||||
    ImGuiScrollFlags in_flags = flags;
 | 
			
		||||
    if ((flags & ImGuiScrollFlags_MaskX_) == 0 && window->ScrollbarX)
 | 
			
		||||
        flags |= ImGuiScrollFlags_KeepVisibleEdgeX;
 | 
			
		||||
    if ((flags & ImGuiScrollFlags_MaskY_) == 0)
 | 
			
		||||
        flags |= window->Appearing ? ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeY;
 | 
			
		||||
 | 
			
		||||
    const bool fully_visible_x = item_rect.Min.x >= window_rect.Min.x && item_rect.Max.x <= window_rect.Max.x;
 | 
			
		||||
    const bool fully_visible_y = item_rect.Min.y >= window_rect.Min.y && item_rect.Max.y <= window_rect.Max.y;
 | 
			
		||||
    const bool can_be_fully_visible_x = item_rect.GetWidth() <= window_rect.GetWidth();
 | 
			
		||||
    const bool can_be_fully_visible_y = item_rect.GetHeight() <= window_rect.GetHeight();
 | 
			
		||||
 | 
			
		||||
    if ((flags & ImGuiScrollFlags_KeepVisibleEdgeX) && !fully_visible_x)
 | 
			
		||||
    {
 | 
			
		||||
        if (item_rect.Min.x < window_rect.Min.x || !can_be_fully_visible_x)
 | 
			
		||||
            SetScrollFromPosX(window, item_rect.Min.x - g.Style.ItemSpacing.x - window->Pos.x, 0.0f);
 | 
			
		||||
        else if (item_rect.Max.x >= window_rect.Max.x)
 | 
			
		||||
            SetScrollFromPosX(window, item_rect.Max.x + g.Style.ItemSpacing.x - window->Pos.x, 1.0f);
 | 
			
		||||
    }
 | 
			
		||||
    else if (((flags & ImGuiScrollFlags_KeepVisibleCenterX) && !fully_visible_x) || (flags & ImGuiScrollFlags_AlwaysCenterX))
 | 
			
		||||
    {
 | 
			
		||||
        float target_x = can_be_fully_visible_x ? ImFloor((item_rect.Min.x + item_rect.Max.x - window->InnerRect.GetWidth()) * 0.5f) : item_rect.Min.x;
 | 
			
		||||
        SetScrollFromPosX(window, target_x - window->Pos.x, 0.0f);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((flags & ImGuiScrollFlags_KeepVisibleEdgeY) && !fully_visible_y)
 | 
			
		||||
    {
 | 
			
		||||
        if (item_rect.Min.y < window_rect.Min.y || !can_be_fully_visible_y)
 | 
			
		||||
            SetScrollFromPosY(window, item_rect.Min.y - g.Style.ItemSpacing.y - window->Pos.y, 0.0f);
 | 
			
		||||
        else if (item_rect.Max.y >= window_rect.Max.y)
 | 
			
		||||
            SetScrollFromPosY(window, item_rect.Max.y + g.Style.ItemSpacing.y - window->Pos.y, 1.0f);
 | 
			
		||||
    }
 | 
			
		||||
    else if (((flags & ImGuiScrollFlags_KeepVisibleCenterY) && !fully_visible_y) || (flags & ImGuiScrollFlags_AlwaysCenterY))
 | 
			
		||||
    {
 | 
			
		||||
        float target_y = can_be_fully_visible_y ? ImFloor((item_rect.Min.y + item_rect.Max.y - window->InnerRect.GetHeight()) * 0.5f) : item_rect.Min.y;
 | 
			
		||||
        SetScrollFromPosY(window, target_y - window->Pos.y, 0.0f);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
 | 
			
		||||
    ImVec2 delta_scroll = next_scroll - window->Scroll;
 | 
			
		||||
 | 
			
		||||
    // Also scroll parent window to keep us into view if necessary
 | 
			
		||||
    if (window->Flags & ImGuiWindowFlags_ChildWindow)
 | 
			
		||||
        delta_scroll += ScrollToBringRectIntoView(window->ParentWindow, ImRect(item_rect.Min - delta_scroll, item_rect.Max - delta_scroll));
 | 
			
		||||
    if (!(flags & ImGuiScrollFlags_NoScrollParent) && (window->Flags & ImGuiWindowFlags_ChildWindow))
 | 
			
		||||
    {
 | 
			
		||||
        // FIXME-SCROLL: May be an option?
 | 
			
		||||
        if ((in_flags & (ImGuiScrollFlags_AlwaysCenterX | ImGuiScrollFlags_KeepVisibleCenterX)) != 0)
 | 
			
		||||
            in_flags = (in_flags & ~ImGuiScrollFlags_MaskX_) | ImGuiScrollFlags_KeepVisibleEdgeX;
 | 
			
		||||
        if ((in_flags & (ImGuiScrollFlags_AlwaysCenterY | ImGuiScrollFlags_KeepVisibleCenterY)) != 0)
 | 
			
		||||
            in_flags = (in_flags & ~ImGuiScrollFlags_MaskY_) | ImGuiScrollFlags_KeepVisibleEdgeY;
 | 
			
		||||
        delta_scroll += ScrollToRectEx(window->ParentWindow, ImRect(item_rect.Min - delta_scroll, item_rect.Max - delta_scroll), in_flags);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return delta_scroll;
 | 
			
		||||
}
 | 
			
		||||
@@ -9671,7 +9692,7 @@ bool ImGui::NavMoveRequestButNoResultYet()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME: ScoringRect is not set
 | 
			
		||||
void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags)
 | 
			
		||||
void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    IM_ASSERT(g.NavWindow != NULL);
 | 
			
		||||
@@ -9680,6 +9701,7 @@ void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavM
 | 
			
		||||
    g.NavMoveDirForDebug = move_dir;
 | 
			
		||||
    g.NavMoveClipDir = clip_dir;
 | 
			
		||||
    g.NavMoveFlags = move_flags;
 | 
			
		||||
    g.NavMoveScrollFlags = scroll_flags;
 | 
			
		||||
    g.NavMoveForwardToNextFrame = false;
 | 
			
		||||
    g.NavMoveKeyMods = g.IO.KeyMods;
 | 
			
		||||
    g.NavMoveResultLocal.Clear();
 | 
			
		||||
@@ -9696,7 +9718,7 @@ void ImGui::NavMoveRequestCancel()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Forward will reuse the move request again on the next frame (generally with modifications done to it)
 | 
			
		||||
void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags)
 | 
			
		||||
void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    IM_ASSERT(g.NavMoveForwardToNextFrame == false);
 | 
			
		||||
@@ -9705,6 +9727,7 @@ void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNav
 | 
			
		||||
    g.NavMoveDir = move_dir;
 | 
			
		||||
    g.NavMoveClipDir = clip_dir;
 | 
			
		||||
    g.NavMoveFlags = move_flags | ImGuiNavMoveFlags_Forwarded;
 | 
			
		||||
    g.NavMoveScrollFlags = scroll_flags;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Navigation wrap-around logic is delayed to the end of the frame because this operation is only valid after entire
 | 
			
		||||
@@ -10071,6 +10094,7 @@ void ImGui::NavUpdateCreateMoveRequest()
 | 
			
		||||
        // Initiate directional inputs request
 | 
			
		||||
        g.NavMoveDir = ImGuiDir_None;
 | 
			
		||||
        g.NavMoveFlags = ImGuiNavMoveFlags_None;
 | 
			
		||||
        g.NavMoveScrollFlags = ImGuiScrollFlags_None;
 | 
			
		||||
        if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
 | 
			
		||||
        {
 | 
			
		||||
            const ImGuiInputReadMode read_mode = ImGuiInputReadMode_Repeat;
 | 
			
		||||
@@ -10103,7 +10127,7 @@ void ImGui::NavUpdateCreateMoveRequest()
 | 
			
		||||
    // Submit
 | 
			
		||||
    g.NavMoveForwardToNextFrame = false;
 | 
			
		||||
    if (g.NavMoveDir != ImGuiDir_None)
 | 
			
		||||
        NavMoveRequestSubmit(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags);
 | 
			
		||||
        NavMoveRequestSubmit(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags);
 | 
			
		||||
 | 
			
		||||
    // Moving with no reference triggers a init request (will be used as a fallback if the direction fails to find a match)
 | 
			
		||||
    if (g.NavMoveSubmitted && g.NavId == 0)
 | 
			
		||||
@@ -10183,8 +10207,9 @@ void ImGui::NavMoveRequestApplyResult()
 | 
			
		||||
    if (g.NavLayer == ImGuiNavLayer_Main)
 | 
			
		||||
    {
 | 
			
		||||
        ImVec2 delta_scroll;
 | 
			
		||||
        if (g.NavMoveFlags & ImGuiNavMoveFlags_ScrollToEdge)
 | 
			
		||||
        if (g.NavMoveFlags & ImGuiNavMoveFlags_ScrollToEdgeY)
 | 
			
		||||
        {
 | 
			
		||||
            // FIXME: Should remove this
 | 
			
		||||
            float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
 | 
			
		||||
            delta_scroll.y = result->Window->Scroll.y - scroll_target;
 | 
			
		||||
            SetScrollY(result->Window, scroll_target);
 | 
			
		||||
@@ -10192,7 +10217,7 @@ void ImGui::NavMoveRequestApplyResult()
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
 | 
			
		||||
            delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs);
 | 
			
		||||
            delta_scroll = ScrollToRectEx(result->Window, rect_abs, g.NavMoveScrollFlags);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Offset our result position so mouse position can be applied immediately after in NavUpdate()
 | 
			
		||||
@@ -10319,13 +10344,13 @@ static float ImGui::NavUpdatePageUpPageDown()
 | 
			
		||||
        else if (home_pressed)
 | 
			
		||||
        {
 | 
			
		||||
            // FIXME-NAV: handling of Home/End is assuming that the top/bottom most item will be visible with Scroll.y == 0/ScrollMax.y
 | 
			
		||||
            // Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdge flag, we don't scroll immediately to avoid scrolling happening before nav result.
 | 
			
		||||
            // Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdgeY flag, we don't scroll immediately to avoid scrolling happening before nav result.
 | 
			
		||||
            // Preserve current horizontal position if we have any.
 | 
			
		||||
            nav_rect_rel.Min.y = nav_rect_rel.Max.y = -window->Scroll.y;
 | 
			
		||||
            if (nav_rect_rel.IsInverted())
 | 
			
		||||
                nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
 | 
			
		||||
            g.NavMoveDir = ImGuiDir_Down;
 | 
			
		||||
            g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
 | 
			
		||||
            g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
 | 
			
		||||
            // FIXME-NAV: MoveClipDir left to _None, intentional?
 | 
			
		||||
        }
 | 
			
		||||
        else if (end_pressed)
 | 
			
		||||
@@ -10334,7 +10359,7 @@ static float ImGui::NavUpdatePageUpPageDown()
 | 
			
		||||
            if (nav_rect_rel.IsInverted())
 | 
			
		||||
                nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
 | 
			
		||||
            g.NavMoveDir = ImGuiDir_Up;
 | 
			
		||||
            g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
 | 
			
		||||
            g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
 | 
			
		||||
            // FIXME-NAV: MoveClipDir left to _None, intentional?
 | 
			
		||||
        }
 | 
			
		||||
        return nav_scoring_rect_offset_y;
 | 
			
		||||
@@ -10405,7 +10430,7 @@ static void ImGui::NavEndFrame()
 | 
			
		||||
        if (do_forward)
 | 
			
		||||
        {
 | 
			
		||||
            window->NavRectRel[g.NavLayer] = bb_rel;
 | 
			
		||||
            NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags);
 | 
			
		||||
            NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -16543,22 +16568,23 @@ namespace ImGui { void ShowFontAtlas(ImFontAtlas* atlas); }
 | 
			
		||||
 | 
			
		||||
void ImGui::ShowMetricsWindow(bool* p_open)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    ImGuiIO& io = g.IO;
 | 
			
		||||
    ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
 | 
			
		||||
    if (cfg->ShowStackTool)
 | 
			
		||||
        ShowStackToolWindow(&cfg->ShowStackTool);
 | 
			
		||||
 | 
			
		||||
    if (!Begin("Dear ImGui Metrics/Debugger", p_open))
 | 
			
		||||
    {
 | 
			
		||||
        End();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    ImGuiIO& io = g.IO;
 | 
			
		||||
    ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
 | 
			
		||||
 | 
			
		||||
    // Basic info
 | 
			
		||||
    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 active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows);
 | 
			
		||||
    Text("%d active allocations", io.MetricsActiveAllocations);
 | 
			
		||||
    Text("%d visible windows, %d active allocations", io.MetricsRenderWindows, io.MetricsActiveAllocations);
 | 
			
		||||
    //SameLine(); if (SmallButton("GC")) { g.GcCompactAll = true; }
 | 
			
		||||
 | 
			
		||||
    Separator();
 | 
			
		||||
@@ -16612,11 +16638,10 @@ void ImGui::ShowMetricsWindow(bool* p_open)
 | 
			
		||||
    // Tools
 | 
			
		||||
    if (TreeNode("Tools"))
 | 
			
		||||
    {
 | 
			
		||||
        // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted.
 | 
			
		||||
        if (Button("Item Picker.."))
 | 
			
		||||
            DebugStartItemPicker();
 | 
			
		||||
        // Stack Tool is your best friend!
 | 
			
		||||
        Checkbox("Show stack tool", &cfg->ShowStackTool);
 | 
			
		||||
        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("You can also call ImGui::ShowStackToolWindow() from your code.");
 | 
			
		||||
 | 
			
		||||
        Checkbox("Show windows begin order", &cfg->ShowWindowsBeginOrder);
 | 
			
		||||
        Checkbox("Show windows rectangles", &cfg->ShowWindowsRects);
 | 
			
		||||
@@ -16634,8 +16659,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
 | 
			
		||||
            }
 | 
			
		||||
            Unindent();
 | 
			
		||||
        }
 | 
			
		||||
        Checkbox("Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh);
 | 
			
		||||
        Checkbox("Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes);
 | 
			
		||||
 | 
			
		||||
        Checkbox("Show tables rectangles", &cfg->ShowTablesRects);
 | 
			
		||||
        SameLine();
 | 
			
		||||
@@ -16682,6 +16705,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted.
 | 
			
		||||
        if (Button("Item Picker.."))
 | 
			
		||||
            DebugStartItemPicker();
 | 
			
		||||
        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.");
 | 
			
		||||
 | 
			
		||||
        TreePop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -16695,6 +16724,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
 | 
			
		||||
        drawlist_count += g.Viewports[viewport_i]->DrawDataBuilder.GetDrawListCount();
 | 
			
		||||
    if (TreeNode("DrawLists", "DrawLists (%d)", drawlist_count))
 | 
			
		||||
    {
 | 
			
		||||
        Checkbox("Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh);
 | 
			
		||||
        Checkbox("Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes);
 | 
			
		||||
        for (int viewport_i = 0; viewport_i < g.Viewports.Size; viewport_i++)
 | 
			
		||||
        {
 | 
			
		||||
            ImGuiViewportP* viewport = g.Viewports[viewport_i];
 | 
			
		||||
@@ -17508,6 +17539,186 @@ void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* la
 | 
			
		||||
    TreePop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, STACK TOOL)
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
// [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack.
 | 
			
		||||
void ImGui::UpdateDebugToolItemPicker()
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    g.DebugItemPickerBreakId = 0;
 | 
			
		||||
    if (!g.DebugItemPickerActive)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
 | 
			
		||||
    SetMouseCursor(ImGuiMouseCursor_Hand);
 | 
			
		||||
    if (IsKeyPressedMap(ImGuiKey_Escape))
 | 
			
		||||
        g.DebugItemPickerActive = false;
 | 
			
		||||
    if (IsMouseClicked(0) && hovered_id)
 | 
			
		||||
    {
 | 
			
		||||
        g.DebugItemPickerBreakId = hovered_id;
 | 
			
		||||
        g.DebugItemPickerActive = false;
 | 
			
		||||
    }
 | 
			
		||||
    SetNextWindowBgAlpha(0.60f);
 | 
			
		||||
    BeginTooltip();
 | 
			
		||||
    Text("HoveredId: 0x%08X", hovered_id);
 | 
			
		||||
    Text("Press ESC to abort picking.");
 | 
			
		||||
    TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!");
 | 
			
		||||
    EndTooltip();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// [DEBUG] Stack Tool: update queries. Called by NewFrame()
 | 
			
		||||
void ImGui::UpdateDebugToolStackQueries()
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    ImGuiStackTool* tool = &g.DebugStackTool;
 | 
			
		||||
 | 
			
		||||
    // Clear hook when stack tool is not visible
 | 
			
		||||
    g.DebugHookIdInfo = 0;
 | 
			
		||||
    if (g.FrameCount != tool->LastActiveFrame + 1)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // Update queries. The steps are: -1: query Stack, >= 0: query each stack item
 | 
			
		||||
    // We can only perform 1 ID Info query every frame. This is designed so the GetID() tests are cheap and constant-time
 | 
			
		||||
    const ImGuiID query_id = g.ActiveId ? g.ActiveId : g.HoveredIdPreviousFrame;
 | 
			
		||||
    if (tool->QueryId != query_id)
 | 
			
		||||
    {
 | 
			
		||||
        tool->QueryId = query_id;
 | 
			
		||||
        tool->StackLevel = -1;
 | 
			
		||||
        tool->Results.resize(0);
 | 
			
		||||
    }
 | 
			
		||||
    if (query_id == 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // Advance to next stack level when we got our result, or after 2 frames (in case we never get a result)
 | 
			
		||||
    int stack_level = tool->StackLevel;
 | 
			
		||||
    if (stack_level >= 0 && stack_level < tool->Results.Size)
 | 
			
		||||
        if (tool->Results[stack_level].QuerySuccess || tool->Results[stack_level].QueryFrameCount > 2)
 | 
			
		||||
            tool->StackLevel++;
 | 
			
		||||
 | 
			
		||||
    // Update hook
 | 
			
		||||
    stack_level = tool->StackLevel;
 | 
			
		||||
    if (stack_level == -1)
 | 
			
		||||
        g.DebugHookIdInfo = query_id;
 | 
			
		||||
    if (stack_level >= 0 && stack_level < tool->Results.Size)
 | 
			
		||||
    {
 | 
			
		||||
        g.DebugHookIdInfo = tool->Results[stack_level].ID;
 | 
			
		||||
        tool->Results[stack_level].QueryFrameCount++;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// [DEBUG] 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;
 | 
			
		||||
 | 
			
		||||
    // Step 0: stack query
 | 
			
		||||
    // This assume that the ID was computed with the current ID stack, which tends to be the case for our widget.
 | 
			
		||||
    if (tool->StackLevel == -1)
 | 
			
		||||
    {
 | 
			
		||||
        tool->StackLevel++;
 | 
			
		||||
        tool->Results.resize(window->IDStack.Size + 1, ImGuiStackLevelInfo());
 | 
			
		||||
        for (int n = 0; n < window->IDStack.Size + 1; n++)
 | 
			
		||||
            tool->Results[n].ID = (n < window->IDStack.Size) ? window->IDStack[n] : id;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Step 1+: query for individual level
 | 
			
		||||
    IM_ASSERT(tool->StackLevel >= 0);
 | 
			
		||||
    if (tool->StackLevel != window->IDStack.Size)
 | 
			
		||||
        return;
 | 
			
		||||
    ImGuiStackLevelInfo* info = &tool->Results[tool->StackLevel];
 | 
			
		||||
    IM_ASSERT(info->ID == id && info->QueryFrameCount > 0);
 | 
			
		||||
 | 
			
		||||
    int data_len;
 | 
			
		||||
    switch (data_type)
 | 
			
		||||
    {
 | 
			
		||||
    case ImGuiDataType_S32:
 | 
			
		||||
        ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "%d", (int)(intptr_t)data_id);
 | 
			
		||||
        break;
 | 
			
		||||
    case ImGuiDataType_String:
 | 
			
		||||
        data_len = data_id_end ? (int)((const char*)data_id_end - (const char*)data_id) : (int)strlen((const char*)data_id);
 | 
			
		||||
        ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "\"%.*s\"", data_len, (const char*)data_id);
 | 
			
		||||
        break;
 | 
			
		||||
    case ImGuiDataType_Pointer:
 | 
			
		||||
        ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "(void*)0x%p", data_id);
 | 
			
		||||
        break;
 | 
			
		||||
    case ImGuiDataType_ID:
 | 
			
		||||
        if (info->Desc[0] == 0) // PushOverrideID() is often used to avoid hashing twice, which would lead to 2 calls to DebugHookIdInfo(). We prioritize the first one.
 | 
			
		||||
            ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "0x%08X [override]", id);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        IM_ASSERT(0);
 | 
			
		||||
    }
 | 
			
		||||
    info->QuerySuccess = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Stack Tool: Display UI
 | 
			
		||||
void ImGui::ShowStackToolWindow(bool* p_open)
 | 
			
		||||
{
 | 
			
		||||
    if (!Begin("Dear ImGui Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1)
 | 
			
		||||
    {
 | 
			
		||||
        End();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Display hovered/active status
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
 | 
			
		||||
    const ImGuiID active_id = g.ActiveId;
 | 
			
		||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
			
		||||
    Text("HoveredId: 0x%08X (\"%s\"), ActiveId:  0x%08X (\"%s\")", hovered_id, hovered_id ? ImGuiTestEngine_FindItemDebugLabel(&g, hovered_id) : "", active_id, active_id ? ImGuiTestEngine_FindItemDebugLabel(&g, active_id) : "");
 | 
			
		||||
#else
 | 
			
		||||
    Text("HoveredId: 0x%08X, ActiveId:  0x%08X", hovered_id, active_id);
 | 
			
		||||
#endif
 | 
			
		||||
    SameLine();
 | 
			
		||||
    MetricsHelpMarker("Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details.");
 | 
			
		||||
 | 
			
		||||
    // Display decorated stack
 | 
			
		||||
    ImGuiStackTool* tool = &g.DebugStackTool;
 | 
			
		||||
    tool->LastActiveFrame = g.FrameCount;
 | 
			
		||||
    if (tool->Results.Size > 0 && BeginTable("##table", 3, ImGuiTableFlags_Borders))
 | 
			
		||||
    {
 | 
			
		||||
        const float id_width = CalcTextSize("0xDDDDDDDD").x;
 | 
			
		||||
        TableSetupColumn("Seed", ImGuiTableColumnFlags_WidthFixed, id_width);
 | 
			
		||||
        TableSetupColumn("PushID", ImGuiTableColumnFlags_WidthStretch);
 | 
			
		||||
        TableSetupColumn("Result", ImGuiTableColumnFlags_WidthFixed, id_width);
 | 
			
		||||
        TableHeadersRow();
 | 
			
		||||
        for (int n = 0; n < tool->Results.Size; n++)
 | 
			
		||||
        {
 | 
			
		||||
            ImGuiStackLevelInfo* info = &tool->Results[n];
 | 
			
		||||
            TableNextColumn();
 | 
			
		||||
            Text("0x%08X", (n > 0) ? tool->Results[n - 1].ID : 0);
 | 
			
		||||
 | 
			
		||||
            TableNextColumn();
 | 
			
		||||
            ImGuiWindow* window = (info->Desc[0] == 0 && n == 0) ? FindWindowByID(info->ID) : NULL;
 | 
			
		||||
            if (window)                                         // Source: window name (because the root ID don't call GetID() and so doesn't get hooked)
 | 
			
		||||
                Text("\"%s\" [window]", window->Name);
 | 
			
		||||
            else if (info->QuerySuccess)                        // Source: GetID() hooks (prioritize over ItemInfo() because we frequently use patterns like: PushID(str), Button("") where they both have same id)
 | 
			
		||||
                TextUnformatted(info->Desc);
 | 
			
		||||
            else if (tool->StackLevel >= tool->Results.Size)    // Only start using fallback below when all queries are done, so during queries we don't flickering ??? markers.
 | 
			
		||||
            {
 | 
			
		||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
			
		||||
                if (const char* label = ImGuiTestEngine_FindItemDebugLabel(&g, info->ID))    // Source: ImGuiTestEngine's ItemInfo()
 | 
			
		||||
                    Text("??? \"%s\"", label);
 | 
			
		||||
                else
 | 
			
		||||
#endif
 | 
			
		||||
                    TextUnformatted("???");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            TableNextColumn();
 | 
			
		||||
            Text("0x%08X", info->ID);
 | 
			
		||||
            if (n == tool->Results.Size - 1)
 | 
			
		||||
                TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_Header));
 | 
			
		||||
        }
 | 
			
		||||
        EndTable();
 | 
			
		||||
    }
 | 
			
		||||
    End();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
void ImGui::ShowMetricsWindow(bool*) {}
 | 
			
		||||
@@ -17523,7 +17734,12 @@ void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {}
 | 
			
		||||
void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>*, const char*) {}
 | 
			
		||||
void ImGui::DebugNodeViewport(ImGuiViewportP*) {}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
void ImGui::ShowStackToolWindow(bool*) {}
 | 
			
		||||
void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {}
 | 
			
		||||
void ImGui::UpdateDebugToolItemPicker() {}
 | 
			
		||||
void ImGui::UpdateDebugToolStackQueries() {}
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef IMGUI_DISABLE_METRICS_WINDOW
 | 
			
		||||
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user