mirror of
https://github.com/ocornut/imgui.git
synced 2025-12-28 00:54:34 +00:00
Merge branch 'master' into docking
# Conflicts: # imgui.cpp # imgui_internal.h
This commit is contained in:
476
imgui.cpp
476
imgui.cpp
@@ -1440,6 +1440,11 @@ ImGuiIO::ImGuiIO()
|
||||
ConfigDebugBeginReturnValueOnce = false;
|
||||
ConfigDebugBeginReturnValueLoop = false;
|
||||
|
||||
ConfigErrorRecovery = true;
|
||||
ConfigErrorRecoveryEnableAssert = true;
|
||||
ConfigErrorRecoveryEnableDebugLog = true;
|
||||
ConfigErrorRecoveryEnableTooltip = true;
|
||||
|
||||
// Inputs Behaviors
|
||||
MouseDoubleClickTime = 0.30f;
|
||||
MouseDoubleClickMaxDist = 6.0f;
|
||||
@@ -3333,7 +3338,7 @@ void ImGui::PopStyleColor(int count)
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.ColorStack.Size < count)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(g.ColorStack.Size > count, "Calling PopStyleColor() too many times!");
|
||||
IM_ASSERT_USER_ERROR(0, "Calling PopStyleColor() too many times!");
|
||||
count = g.ColorStack.Size;
|
||||
}
|
||||
while (count > 0)
|
||||
@@ -3456,7 +3461,7 @@ void ImGui::PopStyleVar(int count)
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.StyleVarStack.Size < count)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(g.StyleVarStack.Size > count, "Calling PopStyleVar() too many times!");
|
||||
IM_ASSERT_USER_ERROR(0, "Calling PopStyleVar() too many times!");
|
||||
count = g.StyleVarStack.Size;
|
||||
}
|
||||
while (count > 0)
|
||||
@@ -4059,8 +4064,16 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
||||
LogDepthRef = 0;
|
||||
LogDepthToExpand = LogDepthToExpandDefault = 2;
|
||||
|
||||
DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY;
|
||||
ErrorCallback = NULL;
|
||||
ErrorCallbackUserData = NULL;
|
||||
ErrorFirst = true;
|
||||
ErrorCountCurrentFrame = 0;
|
||||
StackSizesInBeginForCurrentWindow = NULL;
|
||||
|
||||
DebugDrawIdConflictsCount = 0;
|
||||
DebugLogFlags = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_OutputToTTY;
|
||||
DebugLocateId = 0;
|
||||
DebugLogSkippedErrors = 0;
|
||||
DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None;
|
||||
DebugLogAutoDisableFrames = 0;
|
||||
DebugLocateFrames = 0;
|
||||
@@ -4311,6 +4324,7 @@ static void SetCurrentWindow(ImGuiWindow* window)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.CurrentWindow = window;
|
||||
g.StackSizesInBeginForCurrentWindow = g.CurrentWindow ? &g.CurrentWindowStack.back().StackSizesInBegin : NULL;
|
||||
g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
|
||||
if (window)
|
||||
{
|
||||
@@ -5236,7 +5250,8 @@ void ImGui::NewFrame()
|
||||
KeepAliveID(g.DragDropPayload.SourceId);
|
||||
|
||||
// [DEBUG]
|
||||
g.DebugDrawIdConflicts = 0;
|
||||
if (!g.IO.ConfigDebugHighlightIdConflicts || !g.IO.KeyCtrl) // Count is locked while holding CTRL
|
||||
g.DebugDrawIdConflicts = 0;
|
||||
if (g.IO.ConfigDebugHighlightIdConflicts && g.HoveredIdPreviousFrameItemCount > 1)
|
||||
g.DebugDrawIdConflicts = g.HoveredIdPreviousFrame;
|
||||
|
||||
@@ -5342,8 +5357,25 @@ void ImGui::NewFrame()
|
||||
// (needs to be before UpdateMouseMovingWindowNewFrame so the window is already offset and following the mouse on the detaching frame)
|
||||
DockContextNewFrameUpdateUndocking(&g);
|
||||
|
||||
// Mark all windows as not visible and compact unused memory.
|
||||
IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
|
||||
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
|
||||
for (ImGuiWindow* window : g.Windows)
|
||||
{
|
||||
window->WasActive = window->Active;
|
||||
window->Active = false;
|
||||
window->WriteAccessed = false;
|
||||
window->BeginCountPreviousFrame = window->BeginCount;
|
||||
window->BeginCount = 0;
|
||||
|
||||
// Garbage collect transient buffers of recently unused windows
|
||||
if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
|
||||
GcCompactTransientWindowBuffers(window);
|
||||
}
|
||||
|
||||
// Find hovered window
|
||||
// (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredWindowUnderMovingWindow on the mouse release frame)
|
||||
// (currently needs to be done after the WasActive=Active loop and FindHoveredWindowEx uses ->Active)
|
||||
UpdateHoveredWindowAndCaptureFlags();
|
||||
|
||||
// Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering)
|
||||
@@ -5365,22 +5397,6 @@ void ImGui::NewFrame()
|
||||
// Mouse wheel scrolling, scale
|
||||
UpdateMouseWheel();
|
||||
|
||||
// Mark all windows as not visible and compact unused memory.
|
||||
IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
|
||||
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
|
||||
for (ImGuiWindow* window : g.Windows)
|
||||
{
|
||||
window->WasActive = window->Active;
|
||||
window->Active = false;
|
||||
window->WriteAccessed = false;
|
||||
window->BeginCountPreviousFrame = window->BeginCount;
|
||||
window->BeginCount = 0;
|
||||
|
||||
// Garbage collect transient buffers of recently unused windows
|
||||
if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
|
||||
GcCompactTransientWindowBuffers(window);
|
||||
}
|
||||
|
||||
// Garbage collect transient buffers of recently unused tables
|
||||
for (int i = 0; i < g.TablesLastTimeActive.Size; i++)
|
||||
if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time)
|
||||
@@ -5434,6 +5450,10 @@ void ImGui::NewFrame()
|
||||
Begin("Debug##Default");
|
||||
IM_ASSERT(g.CurrentWindow->IsFallbackWindow == true);
|
||||
|
||||
// Store stack sizes
|
||||
g.ErrorCountCurrentFrame = 0;
|
||||
ErrorRecoveryStoreState(&g.StackSizesInNewFrame);
|
||||
|
||||
// [DEBUG] When io.ConfigDebugBeginReturnValue is set, we make Begin()/BeginChild() return false at different level of the window-stack,
|
||||
// allowing to validate correct Begin/End behavior in user code.
|
||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||
@@ -5700,32 +5720,13 @@ void ImGui::EndFrame()
|
||||
return;
|
||||
IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?");
|
||||
|
||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||
if (g.DebugDrawIdConflicts != 0)
|
||||
{
|
||||
PushStyleColor(ImGuiCol_PopupBg, ImLerp(g.Style.Colors[ImGuiCol_PopupBg], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.10f));
|
||||
if (g.DebugItemPickerActive == false && BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None))
|
||||
{
|
||||
SeparatorText("MESSAGE FROM DEAR IMGUI");
|
||||
Text("Programmer error: %d visible items with conflicting ID!", g.HoveredIdPreviousFrameItemCount);
|
||||
BulletText("Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
|
||||
BulletText("Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
|
||||
BulletText("Press F1 to open \"FAQ -> About the ID Stack System\" and read details.");
|
||||
BulletText("Press CTRL+P to activate Item Picker and debug-break in item call-stack.");
|
||||
BulletText("Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
|
||||
EndTooltip();
|
||||
}
|
||||
PopStyleColor();
|
||||
if (Shortcut(ImGuiMod_Ctrl | ImGuiKey_P, ImGuiInputFlags_RouteGlobal))
|
||||
DebugStartItemPicker();
|
||||
if (Shortcut(ImGuiKey_F1, ImGuiInputFlags_RouteGlobal) && g.PlatformIO.Platform_OpenInShellFn != NULL)
|
||||
g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
|
||||
}
|
||||
#endif
|
||||
|
||||
CallContextHooks(&g, ImGuiContextHookType_EndFramePre);
|
||||
|
||||
// [EXPERIMENTAL] Recover from errors
|
||||
if (g.IO.ConfigErrorRecovery)
|
||||
ErrorRecoveryTryToRecoverState(&g.StackSizesInNewFrame);
|
||||
ErrorCheckEndFrameSanityChecks();
|
||||
ErrorCheckEndFrameFinalizeErrorTooltip();
|
||||
|
||||
// Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
|
||||
ImGuiPlatformImeData* ime_data = &g.PlatformImeData;
|
||||
@@ -5936,7 +5937,7 @@ void ImGui::FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_vi
|
||||
{
|
||||
ImGuiWindow* window = g.Windows[i];
|
||||
IM_MSVC_WARNING_SUPPRESS(28182); // [Static Analyzer] Dereferencing NULL pointer.
|
||||
if (!window->Active || window->Hidden)
|
||||
if (!window->WasActive || window->Hidden)
|
||||
continue;
|
||||
if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
|
||||
continue;
|
||||
@@ -6205,18 +6206,35 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I
|
||||
window_flags |= ImGuiWindowFlags_NoMove;
|
||||
}
|
||||
|
||||
// Forward child flags
|
||||
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
|
||||
g.NextWindowData.ChildFlags = child_flags;
|
||||
|
||||
// Forward size
|
||||
// Important: Begin() has special processing to switch condition to ImGuiCond_FirstUseEver for a given axis when ImGuiChildFlags_ResizeXXX is set.
|
||||
// (the alternative would to store conditional flags per axis, which is possible but more code)
|
||||
const ImVec2 size_avail = GetContentRegionAvail();
|
||||
const ImVec2 size_default((child_flags & ImGuiChildFlags_AutoResizeX) ? 0.0f : size_avail.x, (child_flags & ImGuiChildFlags_AutoResizeY) ? 0.0f : size_avail.y);
|
||||
const ImVec2 size = CalcItemSize(size_arg, size_default.x, size_default.y);
|
||||
ImVec2 size = CalcItemSize(size_arg, size_default.x, size_default.y);
|
||||
|
||||
// A SetNextWindowSize() call always has priority (#8020)
|
||||
// (since the code in Begin() never supported SizeVal==0.0f aka auto-resize via SetNextWindowSize() call, we don't support it here for now)
|
||||
// FIXME: We only support ImGuiCond_Always in this path. Supporting other paths would requires to obtain window pointer.
|
||||
if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) != 0 && (g.NextWindowData.SizeCond & ImGuiCond_Always) != 0)
|
||||
{
|
||||
if (g.NextWindowData.SizeVal.x > 0.0f)
|
||||
{
|
||||
size.x = g.NextWindowData.SizeVal.x;
|
||||
child_flags &= ~ImGuiChildFlags_ResizeX;
|
||||
}
|
||||
if (g.NextWindowData.SizeVal.y > 0.0f)
|
||||
{
|
||||
size.y = g.NextWindowData.SizeVal.y;
|
||||
child_flags &= ~ImGuiChildFlags_ResizeY;
|
||||
}
|
||||
}
|
||||
SetNextWindowSize(size);
|
||||
|
||||
// Forward child flags
|
||||
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
|
||||
g.NextWindowData.ChildFlags = child_flags;
|
||||
|
||||
// Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value.
|
||||
// FIXME: 2023/11/14: commented out shorted version. We had an issue with multiple ### in child window path names, which the trailing hash helped workaround.
|
||||
// e.g. "ParentName###ParentIdentifier/ChildName###ChildIdentifier" would get hashed incorrectly by ImHashStr(), trailing _%08X somehow fixes it.
|
||||
@@ -7372,12 +7390,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
|
||||
// Add to stack
|
||||
g.CurrentWindow = window;
|
||||
ImGuiWindowStackData window_stack_data;
|
||||
g.CurrentWindowStack.resize(g.CurrentWindowStack.Size + 1);
|
||||
ImGuiWindowStackData& window_stack_data = g.CurrentWindowStack.back();
|
||||
window_stack_data.Window = window;
|
||||
window_stack_data.ParentLastItemDataBackup = g.LastItemData;
|
||||
window_stack_data.StackSizesOnBegin.SetToContextState(&g);
|
||||
window_stack_data.DisabledOverrideReenable = (flags & ImGuiWindowFlags_Tooltip) && (g.CurrentItemFlags & ImGuiItemFlags_Disabled);
|
||||
g.CurrentWindowStack.push_back(window_stack_data);
|
||||
ErrorRecoveryStoreState(&window_stack_data.StackSizesInBegin);
|
||||
g.StackSizesInBeginForCurrentWindow = &window_stack_data.StackSizesInBegin;
|
||||
if (flags & ImGuiWindowFlags_ChildMenu)
|
||||
g.BeginMenuDepth++;
|
||||
|
||||
@@ -8251,7 +8270,11 @@ void ImGui::End()
|
||||
g.BeginMenuDepth--;
|
||||
if (window->Flags & ImGuiWindowFlags_Popup)
|
||||
g.BeginPopupStack.pop_back();
|
||||
window_stack_data.StackSizesOnBegin.CompareWithContextState(&g);
|
||||
|
||||
// Error handling, state recovery
|
||||
if (g.IO.ConfigErrorRecovery)
|
||||
ErrorRecoveryTryToRecoverWindowState(&window_stack_data.StackSizesInBegin);
|
||||
|
||||
g.CurrentWindowStack.pop_back();
|
||||
SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
|
||||
if (g.CurrentWindow)
|
||||
@@ -8482,7 +8505,11 @@ void ImGui::PushFont(ImFont* font)
|
||||
void ImGui::PopFont()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(g.FontStack.Size > 0);
|
||||
if (g.FontStack.Size <= 0)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(0, "Calling PopFont() too many times!");
|
||||
return;
|
||||
}
|
||||
g.FontStack.pop_back();
|
||||
ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
|
||||
SetCurrentFont(font);
|
||||
@@ -8505,7 +8532,11 @@ void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
|
||||
void ImGui::PopItemFlag()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(g.ItemFlagsStack.Size > 1); // Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack.
|
||||
if (g.ItemFlagsStack.Size <= 1)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(0, "Calling PopItemFlag() too many times!");
|
||||
return;
|
||||
}
|
||||
g.ItemFlagsStack.pop_back();
|
||||
g.CurrentItemFlags = g.ItemFlagsStack.back();
|
||||
}
|
||||
@@ -8535,7 +8566,11 @@ void ImGui::BeginDisabled(bool disabled)
|
||||
void ImGui::EndDisabled()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(g.DisabledStackSize > 0);
|
||||
if (g.DisabledStackSize <= 0)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(0, "Calling EndDisabled() too many times!");
|
||||
return;
|
||||
}
|
||||
g.DisabledStackSize--;
|
||||
bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
|
||||
//PopItemFlag();
|
||||
@@ -8570,14 +8605,21 @@ void ImGui::EndDisabledOverrideReenable()
|
||||
|
||||
void ImGui::PushTextWrapPos(float wrap_pos_x)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos);
|
||||
window->DC.TextWrapPos = wrap_pos_x;
|
||||
}
|
||||
|
||||
void ImGui::PopTextWrapPos()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (window->DC.TextWrapPosStack.Size <= 0)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(0, "Calling PopTextWrapPos() too many times!");
|
||||
return;
|
||||
}
|
||||
window->DC.TextWrapPos = window->DC.TextWrapPosStack.back();
|
||||
window->DC.TextWrapPosStack.pop_back();
|
||||
}
|
||||
@@ -9064,9 +9106,9 @@ void ImGui::PushFocusScope(ImGuiID id)
|
||||
void ImGui::PopFocusScope()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.FocusScopeStack.Size == 0)
|
||||
if (g.FocusScopeStack.Size <= g.StackSizesInBeginForCurrentWindow->SizeOfFocusScopeStack)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(g.FocusScopeStack.Size > 0, "Calling PopFocusScope() too many times!");
|
||||
IM_ASSERT_USER_ERROR(0, "Calling PopFocusScope() too many times!");
|
||||
return;
|
||||
}
|
||||
g.FocusScopeStack.pop_back();
|
||||
@@ -9337,7 +9379,11 @@ ImGuiID ImGui::GetIDWithSeed(int n, ImGuiID seed)
|
||||
void ImGui::PopID()
|
||||
{
|
||||
ImGuiWindow* window = GImGui->CurrentWindow;
|
||||
IM_ASSERT(window->IDStack.Size > 1); // Too many PopID(), or could be popping in a wrong/different window?
|
||||
if (window->IDStack.Size <= 1)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(0, "Calling PopID() too many times!");
|
||||
return;
|
||||
}
|
||||
window->IDStack.pop_back();
|
||||
}
|
||||
|
||||
@@ -10919,9 +10965,10 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own
|
||||
// - ErrorCheckUsingSetCursorPosToExtendParentBoundaries()
|
||||
// - ErrorCheckNewFrameSanityChecks()
|
||||
// - ErrorCheckEndFrameSanityChecks()
|
||||
// - ErrorCheckEndFrameRecover()
|
||||
// - ErrorCheckEndWindowRecover()
|
||||
// - ImGuiStackSizes
|
||||
// - ErrorRecoveryStoreState()
|
||||
// - ErrorRecoveryTryToRecoverState()
|
||||
// - ErrorRecoveryTryToRecoverWindowState()
|
||||
// - ErrorLog()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues.
|
||||
@@ -11020,6 +11067,10 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
|
||||
IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
|
||||
#endif
|
||||
|
||||
// Error handling: we do not accept 100% silent recovery! Please contact me if you feel this is getting in your way.
|
||||
if (g.IO.ConfigErrorRecovery)
|
||||
IM_ASSERT(g.IO.ConfigErrorRecoveryEnableAssert || g.IO.ConfigErrorRecoveryEnableDebugLog || g.IO.ConfigErrorRecoveryEnableTooltip || g.ErrorCallback != NULL);
|
||||
|
||||
// Remap legacy clipboard handlers (OBSOLETED in 1.91.1, August 2024)
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
if (g.IO.GetClipboardTextFn != NULL && (g.PlatformIO.Platform_GetClipboardTextFn == NULL || g.PlatformIO.Platform_GetClipboardTextFn == Platform_GetClipboardTextFn_DefaultImpl))
|
||||
@@ -11070,126 +11121,113 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
|
||||
|
||||
static void ImGui::ErrorCheckEndFrameSanityChecks()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
// Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame()
|
||||
// One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame().
|
||||
// It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will
|
||||
// send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs.
|
||||
// We silently accommodate for this case by ignoring the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0),
|
||||
// while still correctly asserting on mid-frame key press events.
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiKeyChord key_mods = GetMergedModsFromKeys();
|
||||
IM_ASSERT((key_mods == 0 || g.IO.KeyMods == key_mods) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
|
||||
IM_UNUSED(key_mods);
|
||||
|
||||
// [EXPERIMENTAL] Recover from errors: You may call this yourself before EndFrame().
|
||||
//ErrorCheckEndFrameRecover();
|
||||
|
||||
// Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you
|
||||
// to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API).
|
||||
if (g.CurrentWindowStack.Size != 1)
|
||||
{
|
||||
if (g.CurrentWindowStack.Size > 1)
|
||||
{
|
||||
ImGuiWindow* window = g.CurrentWindowStack.back().Window; // <-- This window was not Ended!
|
||||
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
|
||||
IM_UNUSED(window);
|
||||
while (g.CurrentWindowStack.Size > 1)
|
||||
End();
|
||||
}
|
||||
else
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
|
||||
}
|
||||
}
|
||||
|
||||
IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!");
|
||||
IM_ASSERT(g.CurrentWindowStack.Size == 1);
|
||||
IM_ASSERT(g.CurrentWindowStack[0].Window->IsFallbackWindow);
|
||||
}
|
||||
|
||||
// Default implementation of ImGuiErrorLogCallback that pipe errors to DebugLog: appears in tty + Tools->DebugLog
|
||||
void ImGui::ErrorLogCallbackToDebugLog(void*, const char* fmt, ...)
|
||||
// Save current stack sizes. Called e.g. by NewFrame() and by Begin() but may be called for manual recovery.
|
||||
void ImGui::ErrorRecoveryStoreState(ImGuiErrorRecoveryState* state_out)
|
||||
{
|
||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
DebugLogV(fmt, args);
|
||||
va_end(args);
|
||||
#else
|
||||
IM_UNUSED(fmt);
|
||||
#endif
|
||||
ImGuiContext& g = *GImGui;
|
||||
state_out->SizeOfWindowStack = (short)g.CurrentWindowStack.Size;
|
||||
state_out->SizeOfIDStack = (short)g.CurrentWindow->IDStack.Size;
|
||||
state_out->SizeOfTreeStack = (short)g.CurrentWindow->DC.TreeDepth; // NOT g.TreeNodeStack.Size which is a partial stack!
|
||||
state_out->SizeOfColorStack = (short)g.ColorStack.Size;
|
||||
state_out->SizeOfStyleVarStack = (short)g.StyleVarStack.Size;
|
||||
state_out->SizeOfFontStack = (short)g.FontStack.Size;
|
||||
state_out->SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size;
|
||||
state_out->SizeOfGroupStack = (short)g.GroupStack.Size;
|
||||
state_out->SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size;
|
||||
state_out->SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size;
|
||||
state_out->SizeOfDisabledStack = (short)g.DisabledStackSize;
|
||||
}
|
||||
|
||||
// Experimental recovery from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls.
|
||||
// Must be called during or before EndFrame().
|
||||
// This is generally flawed as we are not necessarily End/Popping things in the right order.
|
||||
// FIXME: Can't recover from inside BeginTabItem/EndTabItem yet.
|
||||
void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data)
|
||||
// Chosen name "Try to recover" over e.g. "Restore" to suggest this is not a 100% guaranteed recovery.
|
||||
// Called by e.g. EndFrame() but may be called for manual recovery.
|
||||
// Attempt to recover full window stack.
|
||||
void ImGui::ErrorRecoveryTryToRecoverState(const ImGuiErrorRecoveryState* state_in)
|
||||
{
|
||||
// PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations"
|
||||
ImGuiContext& g = *GImGui;
|
||||
while (g.CurrentWindowStack.Size > 0) //-V1044
|
||||
while (g.CurrentWindowStack.Size > state_in->SizeOfWindowStack) //-V1044
|
||||
{
|
||||
ErrorCheckEndWindowRecover(log_callback, user_data);
|
||||
// Recap:
|
||||
// - Begin()/BeginChild() return false to indicate the window is collapsed or fully clipped.
|
||||
// - Always call a matching End() for each Begin() call, regardless of its return value!
|
||||
// - Begin/End and BeginChild/EndChild logic is KNOWN TO BE INCONSISTENT WITH ALL OTHER BEGIN/END FUNCTIONS.
|
||||
// - We will fix that in a future major update.
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (g.CurrentWindowStack.Size == 1)
|
||||
{
|
||||
IM_ASSERT(window->IsFallbackWindow);
|
||||
break;
|
||||
}
|
||||
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing EndChild()");
|
||||
EndChild();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing End()");
|
||||
End();
|
||||
}
|
||||
}
|
||||
if (g.CurrentWindowStack.Size == state_in->SizeOfWindowStack)
|
||||
ErrorRecoveryTryToRecoverWindowState(state_in);
|
||||
}
|
||||
|
||||
// Must be called before End()/EndChild()
|
||||
void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data)
|
||||
// Called by e.g. End() but may be called for manual recovery.
|
||||
// Read '// Error Handling [BETA]' block in imgui_internal.h for details.
|
||||
// Attempt to recover from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls.
|
||||
void ImGui::ErrorRecoveryTryToRecoverWindowState(const ImGuiErrorRecoveryState* state_in)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
while (g.CurrentTable != NULL && g.CurrentTable->InnerWindow == g.CurrentWindow)
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'\n", g.CurrentTable->OuterWindow->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing EndTable()");
|
||||
EndTable();
|
||||
}
|
||||
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiStackSizes* stack_sizes = &g.CurrentWindowStack.back().StackSizesOnBegin;
|
||||
IM_ASSERT(window != NULL);
|
||||
|
||||
// FIXME: Can't recover from inside BeginTabItem/EndTabItem yet.
|
||||
while (g.CurrentTabBar != NULL && g.CurrentTabBar->Window == window) //-V1044
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing EndTabBar()");
|
||||
EndTabBar();
|
||||
}
|
||||
while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window)
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing EndMultiSelect() in '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing EndMultiSelect()");
|
||||
EndMultiSelect();
|
||||
}
|
||||
while (window->DC.TreeDepth > 0)
|
||||
while (window->DC.TreeDepth > state_in->SizeOfTreeStack) //-V1044
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing TreePop()");
|
||||
TreePop();
|
||||
}
|
||||
while (g.GroupStack.Size > stack_sizes->SizeOfGroupStack) //-V1044
|
||||
while (g.GroupStack.Size > state_in->SizeOfGroupStack) //-V1044
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing EndGroup()");
|
||||
EndGroup();
|
||||
}
|
||||
while (window->IDStack.Size > 1)
|
||||
IM_ASSERT(g.GroupStack.Size == state_in->SizeOfGroupStack);
|
||||
while (window->IDStack.Size > state_in->SizeOfIDStack) //-V1044
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing PopID()");
|
||||
PopID();
|
||||
}
|
||||
while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
|
||||
while (g.DisabledStackSize > state_in->SizeOfDisabledStack) //-V1044
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing EndDisabled()");
|
||||
if (g.CurrentItemFlags & ImGuiItemFlags_Disabled)
|
||||
EndDisabled();
|
||||
else
|
||||
@@ -11198,70 +11236,150 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
|
||||
g.CurrentWindowStack.back().DisabledOverrideReenable = false;
|
||||
}
|
||||
}
|
||||
while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
|
||||
IM_ASSERT(g.DisabledStackSize == state_in->SizeOfDisabledStack);
|
||||
while (g.ColorStack.Size > state_in->SizeOfColorStack)
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s\n", window->Name, GetStyleColorName(g.ColorStack.back().Col));
|
||||
IM_ASSERT_USER_ERROR(0, "Missing PopStyleColor()");
|
||||
PopStyleColor();
|
||||
}
|
||||
while (g.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack) //-V1044
|
||||
while (g.ItemFlagsStack.Size > state_in->SizeOfItemFlagsStack) //-V1044
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing PopItemFlag()");
|
||||
PopItemFlag();
|
||||
}
|
||||
while (g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack) //-V1044
|
||||
while (g.StyleVarStack.Size > state_in->SizeOfStyleVarStack) //-V1044
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing PopStyleVar()");
|
||||
PopStyleVar();
|
||||
}
|
||||
while (g.FontStack.Size > stack_sizes->SizeOfFontStack) //-V1044
|
||||
while (g.FontStack.Size > state_in->SizeOfFontStack) //-V1044
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing PopFont() in '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing PopFont()");
|
||||
PopFont();
|
||||
}
|
||||
while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack + 1) //-V1044
|
||||
while (g.FocusScopeStack.Size > state_in->SizeOfFocusScopeStack) //-V1044
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'\n", window->Name);
|
||||
IM_ASSERT_USER_ERROR(0, "Missing PopFocusScope()");
|
||||
PopFocusScope();
|
||||
}
|
||||
//IM_ASSERT(g.FocusScopeStack.Size == state_in->SizeOfFocusScopeStack);
|
||||
}
|
||||
|
||||
// Save current stack sizes for later compare
|
||||
void ImGuiStackSizes::SetToContextState(ImGuiContext* ctx)
|
||||
bool ImGui::ErrorLog(const char* msg)
|
||||
{
|
||||
ImGuiContext& g = *ctx;
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
// Output to debug log
|
||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
SizeOfIDStack = (short)window->IDStack.Size;
|
||||
SizeOfColorStack = (short)g.ColorStack.Size;
|
||||
SizeOfStyleVarStack = (short)g.StyleVarStack.Size;
|
||||
SizeOfFontStack = (short)g.FontStack.Size;
|
||||
SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size;
|
||||
SizeOfGroupStack = (short)g.GroupStack.Size;
|
||||
SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size;
|
||||
SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size;
|
||||
SizeOfDisabledStack = (short)g.DisabledStackSize;
|
||||
|
||||
if (g.IO.ConfigErrorRecoveryEnableDebugLog)
|
||||
{
|
||||
if (g.ErrorFirst)
|
||||
IMGUI_DEBUG_LOG_ERROR("[imgui-error] (current settings: Assert=%d, Log=%d, Tooltip=%d)\n",
|
||||
g.IO.ConfigErrorRecoveryEnableAssert, g.IO.ConfigErrorRecoveryEnableDebugLog, g.IO.ConfigErrorRecoveryEnableTooltip);
|
||||
IMGUI_DEBUG_LOG_ERROR("[imgui-error] In window '%s': %s\n", window ? window->Name : "NULL", msg);
|
||||
}
|
||||
g.ErrorFirst = false;
|
||||
|
||||
// Output to tooltip
|
||||
if (g.IO.ConfigErrorRecoveryEnableTooltip)
|
||||
{
|
||||
if (BeginErrorTooltip())
|
||||
{
|
||||
if (g.ErrorCountCurrentFrame < 20)
|
||||
{
|
||||
Text("In window '%s': %s", window ? window->Name : "NULL", msg);
|
||||
if (window && (!window->IsFallbackWindow || window->WasActive))
|
||||
GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 0, 0, 255));
|
||||
}
|
||||
if (g.ErrorCountCurrentFrame == 20)
|
||||
Text("(and more errors)");
|
||||
// EndFrame() will amend debug buttons to this window, after all errors have been submitted.
|
||||
EndErrorTooltip();
|
||||
}
|
||||
g.ErrorCountCurrentFrame++;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Output to callback
|
||||
if (g.ErrorCallback != NULL)
|
||||
g.ErrorCallback(&g, g.ErrorCallbackUserData, msg);
|
||||
|
||||
// Return whether we should assert
|
||||
return g.IO.ConfigErrorRecoveryEnableAssert;
|
||||
}
|
||||
|
||||
// Compare to detect usage errors
|
||||
void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx)
|
||||
void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
|
||||
{
|
||||
ImGuiContext& g = *ctx;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
IM_UNUSED(window);
|
||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.DebugDrawIdConflicts != 0 && g.IO.KeyCtrl == false)
|
||||
g.DebugDrawIdConflictsCount = g.HoveredIdPreviousFrameItemCount;
|
||||
if (g.DebugDrawIdConflicts != 0 && g.DebugItemPickerActive == false && BeginErrorTooltip())
|
||||
{
|
||||
Text("Programmer error: %d visible items with conflicting ID!", g.DebugDrawIdConflictsCount);
|
||||
BulletText("Code should use PushID()/PopID() in loops, or append \"##xx\" to same-label identifiers!");
|
||||
BulletText("Empty label e.g. Button(\"\") == same ID as parent widget/node. Use Button(\"##xx\") instead!");
|
||||
BulletText("Set io.ConfigDebugDetectIdConflicts=false to disable this warning in non-programmers builds.");
|
||||
Separator();
|
||||
Text("(Hold CTRL and: use");
|
||||
SameLine();
|
||||
if (SmallButton("Item Picker"))
|
||||
DebugStartItemPicker();
|
||||
SameLine();
|
||||
Text("to break in item call-stack, or");
|
||||
SameLine();
|
||||
if (SmallButton("Open FAQ->About ID Stack System") && g.PlatformIO.Platform_OpenInShellFn != NULL)
|
||||
g.PlatformIO.Platform_OpenInShellFn(&g, "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#qa-usage");
|
||||
EndErrorTooltip();
|
||||
}
|
||||
|
||||
// Window stacks
|
||||
// NOT checking: DC.ItemWidth, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
|
||||
IM_ASSERT(SizeOfIDStack == window->IDStack.Size && "PushID/PopID or TreeNode/TreePop Mismatch!");
|
||||
if (g.ErrorCountCurrentFrame > 0 && BeginErrorTooltip()) // Amend at end of frame
|
||||
{
|
||||
Separator();
|
||||
Text("(Hold CTRL and:");
|
||||
SameLine();
|
||||
if (SmallButton("Enable Asserts"))
|
||||
g.IO.ConfigErrorRecoveryEnableAssert = true;
|
||||
//SameLine();
|
||||
//if (SmallButton("Hide Error Tooltips"))
|
||||
// g.IO.ConfigErrorRecoveryEnableTooltip = false; // Too dangerous
|
||||
SameLine(0, 0);
|
||||
Text(")");
|
||||
EndErrorTooltip();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Global stacks
|
||||
// For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them.
|
||||
IM_ASSERT(SizeOfGroupStack == g.GroupStack.Size && "BeginGroup/EndGroup Mismatch!");
|
||||
IM_ASSERT(SizeOfBeginPopupStack == g.BeginPopupStack.Size && "BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!");
|
||||
IM_ASSERT(SizeOfDisabledStack == g.DisabledStackSize && "BeginDisabled/EndDisabled Mismatch!");
|
||||
IM_ASSERT(SizeOfItemFlagsStack >= g.ItemFlagsStack.Size && "PushItemFlag/PopItemFlag Mismatch!");
|
||||
IM_ASSERT(SizeOfColorStack >= g.ColorStack.Size && "PushStyleColor/PopStyleColor Mismatch!");
|
||||
IM_ASSERT(SizeOfStyleVarStack >= g.StyleVarStack.Size && "PushStyleVar/PopStyleVar Mismatch!");
|
||||
IM_ASSERT(SizeOfFontStack >= g.FontStack.Size && "PushFont/PopFont Mismatch!");
|
||||
IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size && "PushFocusScope/PopFocusScope Mismatch!");
|
||||
// Pseudo-tooltip. Follow mouse until CTRL is held. When CTRL is held we lock position, allowing to click it.
|
||||
bool ImGui::BeginErrorTooltip()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = FindWindowByName("##Tooltip_Error");
|
||||
const bool use_locked_pos = (g.IO.KeyCtrl && window && window->WasActive);
|
||||
PushStyleColor(ImGuiCol_PopupBg, ImLerp(g.Style.Colors[ImGuiCol_PopupBg], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.15f));
|
||||
if (use_locked_pos)
|
||||
SetNextWindowPos(g.ErrorTooltipLockedPos);
|
||||
bool is_visible = Begin("##Tooltip_Error", NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize);
|
||||
PopStyleColor();
|
||||
if (is_visible && g.CurrentWindow->BeginCount == 1)
|
||||
{
|
||||
SeparatorText("MESSAGE FROM DEAR IMGUI");
|
||||
BringWindowToDisplayFront(g.CurrentWindow);
|
||||
BringWindowToFocusFront(g.CurrentWindow);
|
||||
g.ErrorTooltipLockedPos = GetWindowPos();
|
||||
}
|
||||
else if (!is_visible)
|
||||
{
|
||||
End();
|
||||
}
|
||||
return is_visible;
|
||||
}
|
||||
|
||||
void ImGui::EndErrorTooltip()
|
||||
{
|
||||
End();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -11593,7 +11711,13 @@ void ImGui::PushMultiItemsWidths(int components, float w_full)
|
||||
|
||||
void ImGui::PopItemWidth()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (window->DC.ItemWidthStack.Size <= 0)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(0, "Calling PopItemWidth() too many times!");
|
||||
return;
|
||||
}
|
||||
window->DC.ItemWidth = window->DC.ItemWidthStack.back();
|
||||
window->DC.ItemWidthStack.pop_back();
|
||||
}
|
||||
@@ -22092,12 +22216,24 @@ static void ShowDebugLogFlag(const char* name, ImGuiDebugLogFlags flags)
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImVec2 size(ImGui::GetFrameHeight() + g.Style.ItemInnerSpacing.x + ImGui::CalcTextSize(name).x, ImGui::GetFrameHeight());
|
||||
SameLineOrWrap(size); // FIXME-LAYOUT: To be done automatically once we rework ItemSize/ItemAdd into ItemLayout.
|
||||
|
||||
bool highlight_errors = (flags == ImGuiDebugLogFlags_EventError && g.DebugLogSkippedErrors > 0);
|
||||
if (highlight_errors)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImLerp(g.Style.Colors[ImGuiCol_Text], ImVec4(1.0f, 0.0f, 0.0f, 1.0f), 0.30f));
|
||||
if (ImGui::CheckboxFlags(name, &g.DebugLogFlags, flags) && g.IO.KeyShift && (g.DebugLogFlags & flags) != 0)
|
||||
{
|
||||
g.DebugLogAutoDisableFrames = 2;
|
||||
g.DebugLogAutoDisableFlags |= flags;
|
||||
}
|
||||
ImGui::SetItemTooltip("Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)");
|
||||
if (highlight_errors)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::SetItemTooltip("%d past errors skipped.", g.DebugLogSkippedErrors);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::SetItemTooltip("Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)");
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::ShowDebugLogWindow(bool* p_open)
|
||||
@@ -22115,6 +22251,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
|
||||
CheckboxFlags("All", &g.DebugLogFlags, all_enable_flags);
|
||||
SetItemTooltip("(except InputRouting which is spammy)");
|
||||
|
||||
ShowDebugLogFlag("Errors", ImGuiDebugLogFlags_EventError);
|
||||
ShowDebugLogFlag("ActiveId", ImGuiDebugLogFlags_EventActiveId);
|
||||
ShowDebugLogFlag("Clipper", ImGuiDebugLogFlags_EventClipper);
|
||||
ShowDebugLogFlag("Docking", ImGuiDebugLogFlags_EventDocking);
|
||||
@@ -22130,6 +22267,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
|
||||
{
|
||||
g.DebugLogBuf.clear();
|
||||
g.DebugLogIndex.clear();
|
||||
g.DebugLogSkippedErrors = 0;
|
||||
}
|
||||
SameLine();
|
||||
if (SmallButton("Copy"))
|
||||
|
||||
Reference in New Issue
Block a user