|
@@ -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))
|
|
|
+ // 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_));
|
|
|
+
|
|
|
+ // 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 (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);
|
|
|
+ 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);
|
|
|
+ }
|
|
|
|
|
|
- ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
|
|
|
- delta_scroll = next_scroll - window->Scroll;
|
|
|
+ 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
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|