diff --git a/imgui.cpp b/imgui.cpp index e82826792..45f6ce36d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -79,7 +79,7 @@ CODE // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) // [SECTION] ID STACK // [SECTION] INPUTS -// [SECTION] ERROR CHECKING +// [SECTION] ERROR CHECKING, STATE RECOVERY // [SECTION] ITEM SUBMISSION // [SECTION] LAYOUT // [SECTION] SCROLLING @@ -7734,7 +7734,8 @@ void ImGui::PopItemFlag() // - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled) // - Visually this is currently altering alpha, but it is expected that in a future styling system this would work differently. // - Feedback welcome at https://github.com/ocornut/imgui/issues/211 -// - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it. +// - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. +// (as a micro-optimisation if you can avoid calling BeginDisabled(false)/EndDisabled() tens of thousands of times by doing a local check, it won't hurt) // - Optimized shortcuts instead of PushStyleVar() + PushItemFlag() // - Note: mixing up BeginDisabled() and PushItemFlag(ImGuiItemFlags_Disabled) is currently NOT SUPPORTED. void ImGui::BeginDisabled(bool disabled) @@ -10069,7 +10070,15 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own //----------------------------------------------------------------------------- -// [SECTION] ERROR CHECKING +// [SECTION] ERROR CHECKING, STATE RECOVERY +//----------------------------------------------------------------------------- +// - DebugCheckVersionAndDataLayout() (called via IMGUI_CHECKVERSION() macros) +// - ErrorCheckUsingSetCursorPosToExtendParentBoundaries() +// - ErrorCheckNewFrameSanityChecks() +// - ErrorCheckEndFrameSanityChecks() +// - ErrorCheckEndFrameRecover() +// - ErrorCheckEndWindowRecover() +// - ImGuiStackSizes //----------------------------------------------------------------------------- // Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues. @@ -10215,6 +10224,15 @@ static void ImGui::ErrorCheckEndFrameSanityChecks() IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!"); } +// Default implementation of ImGuiErrorLogCallback that pipe errors to DebugLog: appears in tty + Tools->DebugLog +void ImGui::ErrorLogCallbackToDebugLog(void*, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + ImGui::DebugLogV(fmt, args); + va_end(args); +} + // 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. @@ -10235,12 +10253,12 @@ void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi } if (window->Flags & ImGuiWindowFlags_ChildWindow) { - if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'\n", window->Name); EndChild(); } else { - if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'\n", window->Name); End(); } } @@ -10252,7 +10270,7 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo ImGuiContext& g = *GImGui; while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow)) { - if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name); + if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'\n", g.CurrentTable->OuterWindow->Name); EndTable(); } @@ -10261,32 +10279,32 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo IM_ASSERT(window != NULL); while (g.CurrentTabBar != NULL) //-V1044 { - if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'\n", window->Name); EndTabBar(); } while (g.CurrentMultiSelect != NULL && g.CurrentMultiSelect->Storage->Window == window) { - if (log_callback) log_callback(user_data, "Recovered from missing EndMultiSelect() in '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing EndMultiSelect() in '%s'\n", window->Name); EndMultiSelect(); } while (window->DC.TreeDepth > 0) { - if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'\n", window->Name); TreePop(); } while (g.GroupStack.Size > stack_sizes->SizeOfGroupStack) //-V1044 { - if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'\n", window->Name); EndGroup(); } while (window->IDStack.Size > 1) { - if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'\n", window->Name); PopID(); } while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044 { - if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'\n", window->Name); if (g.CurrentItemFlags & ImGuiItemFlags_Disabled) EndDisabled(); else @@ -10297,27 +10315,27 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo } while (g.ColorStack.Size > stack_sizes->SizeOfColorStack) { - if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(g.ColorStack.back().Col)); + if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s\n", window->Name, GetStyleColorName(g.ColorStack.back().Col)); PopStyleColor(); } while (g.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack) //-V1044 { - if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'\n", window->Name); PopItemFlag(); } while (g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack) //-V1044 { - if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'\n", window->Name); PopStyleVar(); } while (g.FontStack.Size > stack_sizes->SizeOfFontStack) //-V1044 { - if (log_callback) log_callback(user_data, "Recovered from missing PopFont() in '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing PopFont() in '%s'\n", window->Name); PopFont(); } while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack + 1) //-V1044 { - if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name); + if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'\n", window->Name); PopFocusScope(); } } diff --git a/imgui_internal.h b/imgui_internal.h index cb4046457..14b56e8a0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1259,6 +1259,7 @@ struct ImGuiTreeNodeStackData ImRect NavRect; // Used for nav landing }; +// sizeof() = 18 struct IMGUI_API ImGuiStackSizes { short SizeOfIDStack; @@ -3606,11 +3607,14 @@ namespace ImGui IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window); IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window); - // Debug Tools - IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free + // Error Checking, State Recovery + IMGUI_API void ErrorLogCallbackToDebugLog(void* user_data, const char* fmt, ...); IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); + + // Debug Tools + IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free IMGUI_API void DebugDrawCursorPos(ImU32 col = IM_COL32(255, 0, 0, 255)); IMGUI_API void DebugDrawLineExtents(ImU32 col = IM_COL32(255, 0, 0, 255)); IMGUI_API void DebugDrawItemRect(ImU32 col = IM_COL32(255, 0, 0, 255));