update Dear ImGui to 1.90.8

This commit is contained in:
tildearrow 2025-08-10 04:38:15 -05:00
parent 3aecf2f065
commit d50ec1726d
8 changed files with 385 additions and 265 deletions

View file

@ -1,4 +1,4 @@
// dear imgui, v1.90.7
// dear imgui, v1.90.8
// (main code and documentation)
// Help:
@ -438,6 +438,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.
- 2024/06/06 (1.90.8) - reordered ImGuiInputTextFlags values. This should not be breaking unless you are using generated headers that have values not matching the main library.
- 2024/06/06 (1.90.8) - removed 'ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft', was mostly unused and misleading.
- 2024/05/27 (1.90.7) - commented out obsolete symbols marked obsolete in 1.88 (May 2022):
- old: CaptureKeyboardFromApp(bool)
- new: SetNextFrameWantCaptureKeyboard(bool)
@ -4459,7 +4461,7 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id)
ImGuiWindow* window = g.CurrentWindow;
if (!bb.Overlaps(window->ClipRect))
if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId))
if (!g.LogEnabled)
if (!g.ItemUnclipByLog)
return true;
return false;
}
@ -6208,7 +6210,7 @@ static inline ImVec2 CalcWindowMinSize(ImGuiWindow* window)
// Reduce artifacts with very small windows
ImGuiWindow* window_for_height = GetWindowForTitleAndMenuHeight(window);
size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f));
size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight + window_for_height->MenuBarHeight + ImMax(0.0f, g.Style.WindowRounding - 1.0f));
return size_min;
}
@ -6422,7 +6424,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
ImRect clamp_rect = visibility_rect;
const bool window_move_from_title_bar = g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar);
if (window_move_from_title_bar)
clamp_rect.Min.y -= window->TitleBarHeight();
clamp_rect.Min.y -= window->TitleBarHeight;
ImVec2 pos_target(FLT_MAX, FLT_MAX);
ImVec2 size_target(FLT_MAX, FLT_MAX);
@ -6634,8 +6636,10 @@ static inline void ClampWindowPos(ImGuiWindow* window, const ImRect& visibility_
{
ImGuiContext& g = *GImGui;
ImVec2 size_for_clamping = window->Size;
if (g.IO.ConfigWindowsMoveFromTitleBarOnly && (!(window->Flags & ImGuiWindowFlags_NoTitleBar) || window->DockNodeAsHost))
if (g.IO.ConfigWindowsMoveFromTitleBarOnly && window->DockNodeAsHost)
size_for_clamping.y = ImGui::GetFrameHeight(); // Not using window->TitleBarHeight() as DockNodeAsHost will report 0.0f here.
else if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
size_for_clamping.y = window->TitleBarHeight;
window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
}
@ -6671,7 +6675,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
}
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
{
float y = window->Pos.y + window->TitleBarHeight() - 1;
float y = window->Pos.y + window->TitleBarHeight - 1;
window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), border_col, g.Style.FrameBorderSize);
}
}
@ -6745,7 +6749,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
ImDrawList* bg_draw_list = window->DockIsActive ? window->DockNode->HostWindow->DrawList : window->DrawList;
if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_BG);
bg_draw_list->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
bg_draw_list->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
bg_draw_list->ChannelsSetCurrent(DOCKING_HOST_DRAW_CHANNEL_FG);
}
@ -7110,6 +7114,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags, const
window_stack_data.Window = window;
window_stack_data.ParentLastItemDataBackup = g.LastItemData;
window_stack_data.StackSizesOnBegin.SetToContextState(&g);
window_stack_data.DisabledOverrideReenable = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
g.CurrentWindowStack.push_back(window_stack_data);
if (flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuDepth++;
@ -7209,6 +7214,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags, const
// [EXPERIMENTAL] Skip Refresh mode
UpdateWindowSkipRefresh(window);
// Nested root windows (typically tooltips) override disabled state
if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
BeginDisabledOverrideReenable();
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
g.CurrentWindow = NULL;
@ -7321,6 +7330,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags, const
// Lock menu offset so size calculation can use it as menu-bar windows need a minimum size.
window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
window->TitleBarHeight = (flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : g.FontSize + g.Style.FramePadding.y * 2.0f;
window->MenuBarHeight = (flags & ImGuiWindowFlags_MenuBar) ? window->DC.MenuBarOffset.y + g.FontSize + g.Style.FramePadding.y * 2.0f : 0.0f;
// Depending on condition we use previous or current window size to compare against contents size to decide if a scrollbar should be visible.
// Those flags will be altered further down in the function depending on more conditions.
@ -7361,7 +7372,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags, const
const ImVec2 scrollbar_sizes_from_last_frame = window->ScrollbarSizes;
window->DecoOuterSizeX1 = 0.0f;
window->DecoOuterSizeX2 = 0.0f;
window->DecoOuterSizeY1 = window->TitleBarHeight() + window->MenuBarHeight();
window->DecoOuterSizeY1 = window->TitleBarHeight + window->MenuBarHeight;
window->DecoOuterSizeY2 = 0.0f;
window->ScrollbarSizes = ImVec2(0.0f, 0.0f);
@ -7570,7 +7581,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags, const
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
if (window->ScrollbarX && !window->ScrollbarY)
window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar);
window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
// Amend the partially filled window->DecorationXXX values.
@ -7592,7 +7603,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags, const
const ImRect title_bar_rect = window->TitleBarRect();
window->OuterRectClipped = outer_rect;
if (window->DockIsActive)
window->OuterRectClipped.Min.y += window->TitleBarHeight();
window->OuterRectClipped.Min.y += window->TitleBarHeight;
window->OuterRectClipped.ClipWith(host_rect);
// Inner rectangle
@ -8018,7 +8029,7 @@ void ImGui::End()
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size > 1, "Calling End() too many times!");
return;
}
IM_ASSERT(g.CurrentWindowStack.Size > 0);
ImGuiWindowStackData& window_stack_data = g.CurrentWindowStack.back();
// Error checking: verify that user doesn't directly call End() on a child window.
if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_DockNodeHost) && !window->DockIsActive)
@ -8030,6 +8041,8 @@ void ImGui::End()
if (!(window->Flags & ImGuiWindowFlags_DockNodeHost) && !window->SkipRefresh) // Pop inner window clip rectangle
PopClipRect();
PopFocusScope();
if (window_stack_data.DisabledOverrideReenable && window->RootWindow == window)
EndDisabledOverrideReenable();
if (window->SkipRefresh)
{
@ -8050,12 +8063,12 @@ void ImGui::End()
host_window->DC.CursorMaxPos = window->DC.CursorMaxPos + window->WindowPadding - host_window->WindowPadding;
// Pop from window stack
g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup;
g.LastItemData = window_stack_data.ParentLastItemDataBackup;
if (window->Flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuDepth--;
if (window->Flags & ImGuiWindowFlags_Popup)
g.BeginPopupStack.pop_back();
g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&g);
window_stack_data.StackSizesOnBegin.CompareWithContextState(&g);
g.CurrentWindowStack.pop_back();
SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
if (g.CurrentWindow)
@ -8149,9 +8162,13 @@ void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window)) // Early out in common case.
if (ImGuiWindow* blocking_modal = FindBlockingModal(window))
{
// This block would typically be reached in two situations:
// - API call to FocusWindow() with a window under a modal and ImGuiFocusRequestFlags_UnlessBelowModal flag.
// - User clicking on void or anything behind a modal while a modal is open (window == NULL)
IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "<NULL>", blocking_modal->Name);
if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
BringWindowToDisplayBehind(window, blocking_modal); // Still bring to right below modal.
BringWindowToDisplayBehind(window, blocking_modal); // Still bring right under modal. (FIXME: Could move in focus list too?)
ClosePopupsOverWindow(GetTopMostPopupModal(), false); // Note how we need to use GetTopMostPopupModal() aad NOT blocking_modal, to handle nested modals
return;
}
@ -8316,7 +8333,7 @@ void ImGui::BeginDisabled(bool disabled)
}
if (was_disabled || disabled)
g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
g.ItemFlagsStack.push_back(g.CurrentItemFlags);
g.ItemFlagsStack.push_back(g.CurrentItemFlags); // FIXME-OPT: can we simply skip this and use DisabledStackSize?
g.DisabledStackSize++;
}
@ -8362,6 +8379,29 @@ void ImGui::InhibitInertialScroll()
g.InertialScrollInhibited=true;
}
// Could have been called BeginDisabledDisable() but it didn't want to be award nominated for most awkward function name.
// Ideally we would use a shared e.g. BeginDisabled()->BeginDisabledEx() but earlier needs to be optimal.
// The whole code for this is awkward, will reevaluate if we find a way to implement SetNextItemDisabled().
void ImGui::BeginDisabledOverrideReenable()
{
ImGuiContext& g = *GImGui;
IM_ASSERT(g.CurrentItemFlags & ImGuiItemFlags_Disabled);
g.Style.Alpha = g.DisabledAlphaBackup;
g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled;
g.ItemFlagsStack.push_back(g.CurrentItemFlags);
g.DisabledStackSize++;
}
void ImGui::EndDisabledOverrideReenable()
{
ImGuiContext& g = *GImGui;
g.DisabledStackSize--;
IM_ASSERT(g.DisabledStackSize > 0);
g.ItemFlagsStack.pop_back();
g.CurrentItemFlags = g.ItemFlagsStack.back();
g.Style.Alpha = g.DisabledAlphaBackup * g.Style.DisabledAlpha;
}
void ImGui::PushTabStop(bool tab_stop)
{
PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop);
@ -9746,7 +9786,7 @@ bool ImGui::IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id)
bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat)
{
return IsMouseClicked(button, ImGuiKeyOwner_Any, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None);
return IsMouseClicked(button, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
}
bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id)
@ -10604,7 +10644,7 @@ void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
// This is the only public API until we expose owner_id versions of the API as replacements.
bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord)
{
return IsKeyChordPressed(key_chord, 0, ImGuiInputFlags_None);
return IsKeyChordPressed(key_chord, ImGuiInputFlags_None, ImGuiKeyOwner_Any);
}
// This is equivalent to comparing KeyMods + doing a IsKeyPressed()
@ -10943,7 +10983,13 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
{
if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name);
EndDisabled();
if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
EndDisabled();
else
{
EndDisabledOverrideReenable();
g.CurrentWindowStack.back().DisabledOverrideReenable = false;
}
}
while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
{
@ -11032,6 +11078,7 @@ void ImGui::KeepAliveID(ImGuiID id)
// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction.
// THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN)
IM_MSVC_RUNTIME_CHECKS_OFF
bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags)
{
ImGuiContext& g = *GImGui;
@ -11084,15 +11131,12 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
#endif
// Clipping test
// (this is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value)
//const bool is_clipped = IsClippedEx(bb, id);
//if (is_clipped)
// return false;
// (this is an inline copy of IsClippedEx() so we can reuse the is_rect_visible value, otherwise we'd do 'if (IsClippedEx(bb, id)) return false')
// g.NavActivateId is not necessarily == g.NavId, in the case of remote activation (e.g. shortcuts)
const bool is_rect_visible = bb.Overlaps(window->ClipRect);
if (!is_rect_visible)
if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId))
if (!g.LogEnabled)
if (!g.ItemUnclipByLog)
return false;
// [DEBUG]
@ -11119,7 +11163,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
return true;
}
IM_MSVC_RUNTIME_CHECKS_RESTORE
//-----------------------------------------------------------------------------
// [SECTION] LAYOUT
@ -11156,6 +11200,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
// Register minimum needed size so it can extend the bounding box used for auto-fit calculation.
// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different.
// THIS IS IN THE PERFORMANCE CRITICAL PATH.
IM_MSVC_RUNTIME_CHECKS_OFF
void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
{
ImGuiContext& g = *GImGui;
@ -11191,6 +11236,7 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
SameLine();
}
IM_MSVC_RUNTIME_CHECKS_RESTORE
// Gets back to previous line and continue with horizontal layout
// offset_from_start_x == 0 : follow right after previous item
@ -14069,6 +14115,8 @@ bool ImGui::IsDragDropActive()
void ImGui::ClearDragDrop()
{
ImGuiContext& g = *GImGui;
if (g.DragDropActive)
IMGUI_DEBUG_LOG_ACTIVEID("[dragdrop] ClearDragDrop()\n");
g.DragDropActive = false;
g.DragDropPayload.Clear();
g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
@ -14107,7 +14155,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
bool source_drag_active = false;
ImGuiID source_id = 0;
ImGuiID source_parent_id = 0;
if (!(flags & ImGuiDragDropFlags_SourceExtern))
if ((flags & ImGuiDragDropFlags_SourceExtern) == 0)
{
source_id = g.LastItemData.ID;
if (source_id != 0)
@ -14169,43 +14217,44 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
}
IM_ASSERT(g.DragDropWithinTarget == false); // Can't nest BeginDragDropSource() and BeginDragDropTarget()
if (source_drag_active)
if (!source_drag_active)
return false;
// Activate drag and drop
if (!g.DragDropActive)
{
if (!g.DragDropActive)
{
IM_ASSERT(source_id != 0);
ClearDragDrop();
ImGuiPayload& payload = g.DragDropPayload;
payload.SourceId = source_id;
payload.SourceParentId = source_parent_id;
g.DragDropActive = true;
g.DragDropSourceFlags = flags;
g.DragDropMouseButton = mouse_button;
if (payload.SourceId == g.ActiveId)
g.ActiveIdNoClearOnFocusLoss = true;
}
g.DragDropSourceFrameCount = g.FrameCount;
g.DragDropWithinSource = true;
if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
{
// Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
// We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
bool ret;
if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
ret = BeginTooltipHidden();
else
ret = BeginTooltip();
IM_ASSERT(ret); // FIXME-NEWBEGIN: If this ever becomes false, we need to Begin("##Hidden", NULL, ImGuiWindowFlags_NoSavedSettings) + SetWindowHiddendAndSkipItemsForCurrentFrame().
IM_UNUSED(ret);
}
if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
return true;
IM_ASSERT(source_id != 0);
ClearDragDrop();
IMGUI_DEBUG_LOG_ACTIVEID("[dragdrop] BeginDragDropSource() DragDropActive = true, source_id = %08X\n", source_id);
ImGuiPayload& payload = g.DragDropPayload;
payload.SourceId = source_id;
payload.SourceParentId = source_parent_id;
g.DragDropActive = true;
g.DragDropSourceFlags = flags;
g.DragDropMouseButton = mouse_button;
if (payload.SourceId == g.ActiveId)
g.ActiveIdNoClearOnFocusLoss = true;
}
return false;
g.DragDropSourceFrameCount = g.FrameCount;
g.DragDropWithinSource = true;
if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
{
// Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
// We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
bool ret;
if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
ret = BeginTooltipHidden();
else
ret = BeginTooltip();
IM_ASSERT(ret); // FIXME-NEWBEGIN: If this ever becomes false, we need to Begin("##Hidden", NULL, ImGuiWindowFlags_NoSavedSettings) + SetWindowHiddendAndSkipItemsForCurrentFrame().
IM_UNUSED(ret);
}
if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
return true;
}
void ImGui::EndDragDropSource()
@ -14516,7 +14565,7 @@ void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth)
IM_ASSERT(g.LogEnabled == false);
IM_ASSERT(g.LogFile == NULL);
IM_ASSERT(g.LogBuffer.empty());
g.LogEnabled = true;
g.LogEnabled = g.ItemUnclipByLog = true;
g.LogType = type;
g.LogNextPrefix = g.LogNextSuffix = NULL;
g.LogDepthRef = window->DC.TreeDepth;
@ -14615,7 +14664,7 @@ void ImGui::LogFinish()
break;
}
g.LogEnabled = false;
g.LogEnabled = g.ItemUnclipByLog = false;
g.LogType = ImGuiLogType_None;
g.LogFile = NULL;
g.LogBuffer.clear();
@ -21755,8 +21804,11 @@ void ImGui::DebugLogV(const char* fmt, va_list args)
if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY)
IMGUI_DEBUG_PRINTF("%s", g.DebugLogBuf.begin() + old_size);
#ifdef IMGUI_ENABLE_TEST_ENGINE
// IMGUI_TEST_ENGINE_LOG() adds a trailing \n automatically
const int new_size = g.DebugLogBuf.size();
const bool trailing_carriage_return = (g.DebugLogBuf[new_size - 1] == '\n');
if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTestEngine)
IMGUI_TEST_ENGINE_LOG("%s", g.DebugLogBuf.begin() + old_size);
IMGUI_TEST_ENGINE_LOG("%.*s", new_size - old_size - (trailing_carriage_return ? 1 : 0), g.DebugLogBuf.begin() + old_size);
#endif
}
@ -21826,25 +21878,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
clipper.Begin(g.DebugLogIndex.size());
while (clipper.Step())
for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
{
const char* line_begin = g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no);
const char* line_end = g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no);
TextUnformatted(line_begin, line_end); // Display line
ImRect text_rect = g.LastItemData.Rect;
if (IsItemHovered())
for (const char* p = line_begin; p <= line_end - 10; p++) // Search for 0x???????? identifiers
{
ImGuiID id = 0;
if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1)
continue;
ImVec2 p0 = CalcTextSize(line_begin, p);
ImVec2 p1 = CalcTextSize(p, p + 10);
g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true))
DebugLocateItemOnHover(id);
p += 10;
}
}
DebugTextUnformattedWithLocateItem(g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no), g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no));
g.DebugLogFlags = backup_log_flags;
if (GetScrollY() >= GetScrollMaxY())
SetScrollHereY(1.0f);
@ -21853,6 +21887,28 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
End();
}
// Display line, search for 0xXXXXXXXX identifiers and call DebugLocateItemOnHover() when hovered.
void ImGui::DebugTextUnformattedWithLocateItem(const char* line_begin, const char* line_end)
{
TextUnformatted(line_begin, line_end);
if (!IsItemHovered())
return;
ImGuiContext& g = *GImGui;
ImRect text_rect = g.LastItemData.Rect;
for (const char* p = line_begin; p <= line_end - 10; p++)
{
ImGuiID id = 0;
if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1)
continue;
ImVec2 p0 = CalcTextSize(line_begin, p);
ImVec2 p1 = CalcTextSize(p, p + 10);
g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y));
if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true))
DebugLocateItemOnHover(id);
p += 10;
}
}
//-----------------------------------------------------------------------------
// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL)
//-----------------------------------------------------------------------------