mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-11-04 09:44:29 +00:00 
			
		
		
		
	Error handling: Assert if user mistakenly calls End() instead of EndChild() on a child window. (#1651)
Internals: Moved some error handling code.
This commit is contained in:
		@@ -74,6 +74,7 @@ Other Changes:
 | 
				
			|||||||
  interactions with custom multi-selections patterns. (#1896, #1861)
 | 
					  interactions with custom multi-selections patterns. (#1896, #1861)
 | 
				
			||||||
- DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data
 | 
					- DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data
 | 
				
			||||||
  to clarify how they are used, and more comments redirecting to the demo code. (#2844)
 | 
					  to clarify how they are used, and more comments redirecting to the demo code. (#2844)
 | 
				
			||||||
 | 
					- Error handling: Assert if user mistakenly calls End() instead of EndChild() on a child window. (#1651)
 | 
				
			||||||
- Misc: Optimized storage of window settings data (reducing allocation count).
 | 
					- Misc: Optimized storage of window settings data (reducing allocation count).
 | 
				
			||||||
- Misc: Windows: Do not use _wfopen() if IMGUI_DISABLE_WIN32_FUNCTIONS is defined. (#2815)
 | 
					- Misc: Windows: Do not use _wfopen() if IMGUI_DISABLE_WIN32_FUNCTIONS is defined. (#2815)
 | 
				
			||||||
- Docs: Improved and moved FAQ to docs/FAQ.md so it can be readable on the web. [@ButternCream, @ocornut]
 | 
					- Docs: Improved and moved FAQ to docs/FAQ.md so it can be readable on the web. [@ButternCream, @ocornut]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										118
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								imgui.cpp
									
									
									
									
									
								
							@@ -54,6 +54,7 @@ CODE
 | 
				
			|||||||
// [SECTION] ImGuiListClipper
 | 
					// [SECTION] ImGuiListClipper
 | 
				
			||||||
// [SECTION] RENDER HELPERS
 | 
					// [SECTION] RENDER HELPERS
 | 
				
			||||||
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
 | 
					// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
 | 
				
			||||||
 | 
					// [SECTION] ERROR CHECKING
 | 
				
			||||||
// [SECTION] SCROLLING
 | 
					// [SECTION] SCROLLING
 | 
				
			||||||
// [SECTION] TOOLTIPS
 | 
					// [SECTION] TOOLTIPS
 | 
				
			||||||
// [SECTION] POPUPS
 | 
					// [SECTION] POPUPS
 | 
				
			||||||
@@ -838,7 +839,6 @@ static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER    = 2.00f;    // Lock
 | 
				
			|||||||
static void             SetCurrentWindow(ImGuiWindow* window);
 | 
					static void             SetCurrentWindow(ImGuiWindow* window);
 | 
				
			||||||
static void             FindHoveredWindow();
 | 
					static void             FindHoveredWindow();
 | 
				
			||||||
static ImGuiWindow*     CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);
 | 
					static ImGuiWindow*     CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);
 | 
				
			||||||
static void             CheckStacksSize(ImGuiWindow* window, bool write);
 | 
					 | 
				
			||||||
static ImVec2           CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges);
 | 
					static ImVec2           CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void             AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
 | 
					static void             AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
 | 
				
			||||||
@@ -874,6 +874,10 @@ static void             NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_win
 | 
				
			|||||||
static ImGuiWindow*     NavRestoreLastChildNavWindow(ImGuiWindow* window);
 | 
					static ImGuiWindow*     NavRestoreLastChildNavWindow(ImGuiWindow* window);
 | 
				
			||||||
static int              FindWindowFocusIndex(ImGuiWindow* window);
 | 
					static int              FindWindowFocusIndex(ImGuiWindow* window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Error Checking
 | 
				
			||||||
 | 
					static void             ErrorCheckEndFrame();
 | 
				
			||||||
 | 
					static void             ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Misc
 | 
					// Misc
 | 
				
			||||||
static void             UpdateMouseInputs();
 | 
					static void             UpdateMouseInputs();
 | 
				
			||||||
static void             UpdateMouseWheel();
 | 
					static void             UpdateMouseWheel();
 | 
				
			||||||
@@ -3539,7 +3543,7 @@ void ImGui::NewFrame()
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g.Time += g.IO.DeltaTime;
 | 
					    g.Time += g.IO.DeltaTime;
 | 
				
			||||||
    g.FrameScopeActive = true;
 | 
					    g.WithinFrameScope = true;
 | 
				
			||||||
    g.FrameCount += 1;
 | 
					    g.FrameCount += 1;
 | 
				
			||||||
    g.TooltipOverrideCount = 0;
 | 
					    g.TooltipOverrideCount = 0;
 | 
				
			||||||
    g.WindowsActiveCount = 0;
 | 
					    g.WindowsActiveCount = 0;
 | 
				
			||||||
@@ -3713,7 +3717,7 @@ void ImGui::NewFrame()
 | 
				
			|||||||
    // This fallback is particularly important as it avoid ImGui:: calls from crashing.
 | 
					    // This fallback is particularly important as it avoid ImGui:: calls from crashing.
 | 
				
			||||||
    SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver);
 | 
					    SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver);
 | 
				
			||||||
    Begin("Debug##Default");
 | 
					    Begin("Debug##Default");
 | 
				
			||||||
    g.FrameScopePushedImplicitWindow = true;
 | 
					    g.WithinFrameScopeWithImplicitWindow = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
					#ifdef IMGUI_ENABLE_TEST_ENGINE
 | 
				
			||||||
    ImGuiTestEngineHook_PostNewFrame(&g);
 | 
					    ImGuiTestEngineHook_PostNewFrame(&g);
 | 
				
			||||||
@@ -3982,7 +3986,7 @@ void ImGui::EndFrame()
 | 
				
			|||||||
    IM_ASSERT(g.Initialized);
 | 
					    IM_ASSERT(g.Initialized);
 | 
				
			||||||
    if (g.FrameCountEnded == g.FrameCount)          // Don't process EndFrame() multiple times.
 | 
					    if (g.FrameCountEnded == g.FrameCount)          // Don't process EndFrame() multiple times.
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    IM_ASSERT(g.FrameScopeActive && "Forgot to call ImGui::NewFrame()?");
 | 
					    IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
 | 
					    // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
 | 
				
			||||||
    if (g.IO.ImeSetInputScreenPosFn && (g.PlatformImeLastPos.x == FLT_MAX || ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f))
 | 
					    if (g.IO.ImeSetInputScreenPosFn && (g.PlatformImeLastPos.x == FLT_MAX || ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f))
 | 
				
			||||||
@@ -3991,24 +3995,10 @@ void ImGui::EndFrame()
 | 
				
			|||||||
        g.PlatformImeLastPos = g.PlatformImePos;
 | 
					        g.PlatformImeLastPos = g.PlatformImePos;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you
 | 
					    ErrorCheckEndFrame();
 | 
				
			||||||
    // 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)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
 | 
					 | 
				
			||||||
            while (g.CurrentWindowStack.Size > 1) // FIXME-ERRORHANDLING
 | 
					 | 
				
			||||||
                End();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Hide implicit/fallback "Debug" window if it hasn't been used
 | 
					    // Hide implicit/fallback "Debug" window if it hasn't been used
 | 
				
			||||||
    g.FrameScopePushedImplicitWindow = false;
 | 
					    g.WithinFrameScopeWithImplicitWindow = false;
 | 
				
			||||||
    if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed)
 | 
					    if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed)
 | 
				
			||||||
        g.CurrentWindow->Active = false;
 | 
					        g.CurrentWindow->Active = false;
 | 
				
			||||||
    End();
 | 
					    End();
 | 
				
			||||||
@@ -4035,7 +4025,7 @@ void ImGui::EndFrame()
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // End frame
 | 
					    // End frame
 | 
				
			||||||
    g.FrameScopeActive = false;
 | 
					    g.WithinFrameScope = false;
 | 
				
			||||||
    g.FrameCountEnded = g.FrameCount;
 | 
					    g.FrameCountEnded = g.FrameCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Initiate moving window + handle left-click and right-click focus
 | 
					    // Initiate moving window + handle left-click and right-click focus
 | 
				
			||||||
@@ -4602,7 +4592,10 @@ void ImGui::EndChild()
 | 
				
			|||||||
    ImGuiContext& g = *GImGui;
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
    ImGuiWindow* window = g.CurrentWindow;
 | 
					    ImGuiWindow* window = g.CurrentWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IM_ASSERT(g.WithinEndChild == false);
 | 
				
			||||||
    IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);   // Mismatched BeginChild()/EndChild() callss
 | 
					    IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow);   // Mismatched BeginChild()/EndChild() callss
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g.WithinEndChild = true;
 | 
				
			||||||
    if (window->BeginCount > 1)
 | 
					    if (window->BeginCount > 1)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        End();
 | 
					        End();
 | 
				
			||||||
@@ -4634,6 +4627,7 @@ void ImGui::EndChild()
 | 
				
			|||||||
            ItemAdd(bb, 0);
 | 
					            ItemAdd(bb, 0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    g.WithinEndChild = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Helper to create a child window / scrolling region that looks like a normal widget frame.
 | 
					// Helper to create a child window / scrolling region that looks like a normal widget frame.
 | 
				
			||||||
@@ -4656,22 +4650,6 @@ void ImGui::EndChildFrame()
 | 
				
			|||||||
    EndChild();
 | 
					    EndChild();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Save and compare stack sizes on Begin()/End() to detect usage errors
 | 
					 | 
				
			||||||
static void CheckStacksSize(ImGuiWindow* window, bool write)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
 | 
					 | 
				
			||||||
    ImGuiContext& g = *GImGui;
 | 
					 | 
				
			||||||
    short* p_backup = &window->DC.StackSizesBackup[0];
 | 
					 | 
				
			||||||
    { int current = window->IDStack.Size;       if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "PushID/PopID or TreeNode/TreePop Mismatch!");   p_backup++; }    // Too few or too many PopID()/TreePop()
 | 
					 | 
				
			||||||
    { int current = window->DC.GroupStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!");                p_backup++; }    // Too few or too many EndGroup()
 | 
					 | 
				
			||||||
    { int current = g.BeginPopupStack.Size;     if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch"); p_backup++;}// Too few or too many EndMenu()/EndPopup()
 | 
					 | 
				
			||||||
    // 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.
 | 
					 | 
				
			||||||
    { int current = g.ColorModifiers.Size;      if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushStyleColor/PopStyleColor Mismatch!");       p_backup++; }    // Too few or too many PopStyleColor()
 | 
					 | 
				
			||||||
    { int current = g.StyleModifiers.Size;      if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushStyleVar/PopStyleVar Mismatch!");           p_backup++; }    // Too few or too many PopStyleVar()
 | 
					 | 
				
			||||||
    { int current = g.FontStack.Size;           if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushFont/PopFont Mismatch!");                   p_backup++; }    // Too few or too many PopFont()
 | 
					 | 
				
			||||||
    IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled)
 | 
					static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    window->SetWindowPosAllowFlags       = enabled ? (window->SetWindowPosAllowFlags       | flags) : (window->SetWindowPosAllowFlags       & ~flags);
 | 
					    window->SetWindowPosAllowFlags       = enabled ? (window->SetWindowPosAllowFlags       | flags) : (window->SetWindowPosAllowFlags       & ~flags);
 | 
				
			||||||
@@ -5238,7 +5216,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
 | 
				
			|||||||
    ImGuiContext& g = *GImGui;
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
    const ImGuiStyle& style = g.Style;
 | 
					    const ImGuiStyle& style = g.Style;
 | 
				
			||||||
    IM_ASSERT(name != NULL && name[0] != '\0');     // Window name required
 | 
					    IM_ASSERT(name != NULL && name[0] != '\0');     // Window name required
 | 
				
			||||||
    IM_ASSERT(g.FrameScopeActive);                  // Forgot to call ImGui::NewFrame()
 | 
					    IM_ASSERT(g.WithinFrameScope);                  // Forgot to call ImGui::NewFrame()
 | 
				
			||||||
    IM_ASSERT(g.FrameCountEnded != g.FrameCount);   // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet
 | 
					    IM_ASSERT(g.FrameCountEnded != g.FrameCount);   // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Find or create
 | 
					    // Find or create
 | 
				
			||||||
@@ -5300,7 +5278,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
 | 
				
			|||||||
    // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
 | 
					    // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
 | 
				
			||||||
    g.CurrentWindowStack.push_back(window);
 | 
					    g.CurrentWindowStack.push_back(window);
 | 
				
			||||||
    g.CurrentWindow = NULL;
 | 
					    g.CurrentWindow = NULL;
 | 
				
			||||||
    CheckStacksSize(window, true);
 | 
					    ErrorCheckBeginEndCompareStacksSize(window, true);
 | 
				
			||||||
    if (flags & ImGuiWindowFlags_Popup)
 | 
					    if (flags & ImGuiWindowFlags_Popup)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
 | 
					        ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
 | 
				
			||||||
@@ -5839,16 +5817,22 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
 | 
				
			|||||||
void ImGui::End()
 | 
					void ImGui::End()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ImGuiContext& g = *GImGui;
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
 | 
					    ImGuiWindow* window = g.CurrentWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (g.CurrentWindowStack.Size <= 1 && g.FrameScopePushedImplicitWindow)
 | 
					    // Error checking: verify that user hasn't called End() too many times!
 | 
				
			||||||
 | 
					    // FIXME-ERRORHANDLING
 | 
				
			||||||
 | 
					    if (g.CurrentWindowStack.Size <= 1 && g.WithinFrameScopeWithImplicitWindow)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        IM_ASSERT(g.CurrentWindowStack.Size > 1 && "Calling End() too many times!");
 | 
					        IM_ASSERT(g.CurrentWindowStack.Size > 1 && "Calling End() too many times!");
 | 
				
			||||||
        return; // FIXME-ERRORHANDLING
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    IM_ASSERT(g.CurrentWindowStack.Size > 0);
 | 
					    IM_ASSERT(g.CurrentWindowStack.Size > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImGuiWindow* window = g.CurrentWindow;
 | 
					    // Error checking: verify that user doesn't directly call End() on a child window.
 | 
				
			||||||
 | 
					    if (window->Flags & ImGuiWindowFlags_ChildWindow)
 | 
				
			||||||
 | 
					        IM_ASSERT(g.WithinEndChild && "Must call EndChild() and not End()!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Close anything that is open
 | 
				
			||||||
    if (window->DC.CurrentColumns)
 | 
					    if (window->DC.CurrentColumns)
 | 
				
			||||||
        EndColumns();
 | 
					        EndColumns();
 | 
				
			||||||
    PopClipRect();   // Inner window clip rectangle
 | 
					    PopClipRect();   // Inner window clip rectangle
 | 
				
			||||||
@@ -5861,7 +5845,7 @@ void ImGui::End()
 | 
				
			|||||||
    g.CurrentWindowStack.pop_back();
 | 
					    g.CurrentWindowStack.pop_back();
 | 
				
			||||||
    if (window->Flags & ImGuiWindowFlags_Popup)
 | 
					    if (window->Flags & ImGuiWindowFlags_Popup)
 | 
				
			||||||
        g.BeginPopupStack.pop_back();
 | 
					        g.BeginPopupStack.pop_back();
 | 
				
			||||||
    CheckStacksSize(window, false);
 | 
					    ErrorCheckBeginEndCompareStacksSize(window, false);
 | 
				
			||||||
    SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back());
 | 
					    SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -7007,6 +6991,54 @@ void ImGui::Unindent(float indent_w)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					// [SECTION] ERROR CHECKING
 | 
				
			||||||
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ImGui::ErrorCheckEndFrame()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // 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).
 | 
				
			||||||
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
 | 
					    if (g.CurrentWindowStack.Size != 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (g.CurrentWindowStack.Size > 1)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
 | 
				
			||||||
 | 
					            while (g.CurrentWindowStack.Size > 1) // FIXME-ERRORHANDLING
 | 
				
			||||||
 | 
					                End();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Save and compare stack sizes on Begin()/End() to detect usage errors
 | 
				
			||||||
 | 
					// Begin() calls this with write=true
 | 
				
			||||||
 | 
					// End() calls this with write=false
 | 
				
			||||||
 | 
					static void ImGui::ErrorCheckBeginEndCompareStacksSize(ImGuiWindow* window, bool write)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
 | 
					    short* p = &window->DC.StackSizesBackup[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Window stacks
 | 
				
			||||||
 | 
					    // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
 | 
				
			||||||
 | 
					    { int n = window->IDStack.Size;       if (write) *p = (short)n; else IM_ASSERT(*p == n && "PushID/PopID or TreeNode/TreePop Mismatch!");   p++; }    // Too few or too many PopID()/TreePop()
 | 
				
			||||||
 | 
					    { int n = window->DC.GroupStack.Size; if (write) *p = (short)n; else IM_ASSERT(*p == n && "BeginGroup/EndGroup Mismatch!");                p++; }    // Too few or too many EndGroup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 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.
 | 
				
			||||||
 | 
					    { int n = g.BeginPopupStack.Size;     if (write) *p = (short)n; else IM_ASSERT(*p == n && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch!"); p++; }// Too few or too many EndMenu()/EndPopup()
 | 
				
			||||||
 | 
					    { int n = g.ColorModifiers.Size;      if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleColor/PopStyleColor Mismatch!");       p++; }    // Too few or too many PopStyleColor()
 | 
				
			||||||
 | 
					    { int n = g.StyleModifiers.Size;      if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushStyleVar/PopStyleVar Mismatch!");           p++; }    // Too few or too many PopStyleVar()
 | 
				
			||||||
 | 
					    { int n = g.FontStack.Size;           if (write) *p = (short)n; else IM_ASSERT(*p >= n && "PushFont/PopFont Mismatch!");                   p++; }    // Too few or too many PopFont()
 | 
				
			||||||
 | 
					    IM_ASSERT(p == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//-----------------------------------------------------------------------------
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||||
// [SECTION] SCROLLING
 | 
					// [SECTION] SCROLLING
 | 
				
			||||||
//-----------------------------------------------------------------------------
 | 
					//-----------------------------------------------------------------------------
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -903,9 +903,7 @@ struct ImGuiPtrOrIndex
 | 
				
			|||||||
struct ImGuiContext
 | 
					struct ImGuiContext
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bool                    Initialized;
 | 
					    bool                    Initialized;
 | 
				
			||||||
    bool                    FrameScopeActive;                   // Set by NewFrame(), cleared by EndFrame()
 | 
					    bool                    FontAtlasOwnedByContext;            // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
 | 
				
			||||||
    bool                    FrameScopePushedImplicitWindow;     // Set by NewFrame(), cleared by EndFrame()
 | 
					 | 
				
			||||||
    bool                    FontAtlasOwnedByContext;            // Io.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
 | 
					 | 
				
			||||||
    ImGuiIO                 IO;
 | 
					    ImGuiIO                 IO;
 | 
				
			||||||
    ImGuiStyle              Style;
 | 
					    ImGuiStyle              Style;
 | 
				
			||||||
    ImFont*                 Font;                               // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
 | 
					    ImFont*                 Font;                               // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
 | 
				
			||||||
@@ -916,19 +914,22 @@ struct ImGuiContext
 | 
				
			|||||||
    int                     FrameCount;
 | 
					    int                     FrameCount;
 | 
				
			||||||
    int                     FrameCountEnded;
 | 
					    int                     FrameCountEnded;
 | 
				
			||||||
    int                     FrameCountRendered;
 | 
					    int                     FrameCountRendered;
 | 
				
			||||||
 | 
					    bool                    WithinFrameScope;                   // Set by NewFrame(), cleared by EndFrame()
 | 
				
			||||||
 | 
					    bool                    WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed
 | 
				
			||||||
 | 
					    bool                    WithinEndChild;                     // Set within EndChild()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Windows state
 | 
					    // Windows state
 | 
				
			||||||
    ImVector<ImGuiWindow*>  Windows;                            // Windows, sorted in display order, back to front
 | 
					    ImVector<ImGuiWindow*>  Windows;                            // Windows, sorted in display order, back to front
 | 
				
			||||||
    ImVector<ImGuiWindow*>  WindowsFocusOrder;                  // Windows, sorted in focus order, back to front
 | 
					    ImVector<ImGuiWindow*>  WindowsFocusOrder;                  // Windows, sorted in focus order, back to front
 | 
				
			||||||
    ImVector<ImGuiWindow*>  WindowsSortBuffer;
 | 
					    ImVector<ImGuiWindow*>  WindowsSortBuffer;
 | 
				
			||||||
    ImVector<ImGuiWindow*>  CurrentWindowStack;
 | 
					    ImVector<ImGuiWindow*>  CurrentWindowStack;
 | 
				
			||||||
    ImGuiStorage            WindowsById;
 | 
					    ImGuiStorage            WindowsById;                        // Map window's ImGuiID to ImGuiWindow*
 | 
				
			||||||
    int                     WindowsActiveCount;
 | 
					    int                     WindowsActiveCount;                 // Number of unique windows submitted by frame
 | 
				
			||||||
    ImGuiWindow*            CurrentWindow;                      // Being drawn into
 | 
					    ImGuiWindow*            CurrentWindow;                      // Window being drawn into
 | 
				
			||||||
    ImGuiWindow*            HoveredWindow;                      // Will catch mouse inputs
 | 
					    ImGuiWindow*            HoveredWindow;                      // Will catch mouse inputs
 | 
				
			||||||
    ImGuiWindow*            HoveredRootWindow;                  // Will catch mouse inputs (for focus/move only)
 | 
					    ImGuiWindow*            HoveredRootWindow;                  // Will catch mouse inputs (for focus/move only)
 | 
				
			||||||
    ImGuiWindow*            MovingWindow;                       // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow.
 | 
					    ImGuiWindow*            MovingWindow;                       // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow.
 | 
				
			||||||
    ImGuiWindow*            WheelingWindow;
 | 
					    ImGuiWindow*            WheelingWindow;                     // Track the window we started mouse-wheeling on. Until a timer elapse or mouse has moved, generally keep scrolling the same window even if during the course of scrolling the mouse ends up hovering a child window.
 | 
				
			||||||
    ImVec2                  WheelingWindowRefMousePos;
 | 
					    ImVec2                  WheelingWindowRefMousePos;
 | 
				
			||||||
    float                   WheelingWindowTimer;
 | 
					    float                   WheelingWindowTimer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1057,9 +1058,9 @@ struct ImGuiContext
 | 
				
			|||||||
    ImFont                  InputTextPasswordFont;
 | 
					    ImFont                  InputTextPasswordFont;
 | 
				
			||||||
    ImGuiID                 TempInputTextId;                    // Temporary text input when CTRL+clicking on a slider, etc.
 | 
					    ImGuiID                 TempInputTextId;                    // Temporary text input when CTRL+clicking on a slider, etc.
 | 
				
			||||||
    ImGuiColorEditFlags     ColorEditOptions;                   // Store user options for color edit widgets
 | 
					    ImGuiColorEditFlags     ColorEditOptions;                   // Store user options for color edit widgets
 | 
				
			||||||
    float                   ColorEditLastHue;
 | 
					    float                   ColorEditLastHue;                   // Backup of last Hue associated to LastColor[3], so we can restore Hue in lossy RGB<>HSV round trips
 | 
				
			||||||
    float                   ColorEditLastColor[3];
 | 
					    float                   ColorEditLastColor[3];
 | 
				
			||||||
    ImVec4                  ColorPickerRef;
 | 
					    ImVec4                  ColorPickerRef;                     // Initial/reference color at the time of opening the color picker.
 | 
				
			||||||
    bool                    DragCurrentAccumDirty;
 | 
					    bool                    DragCurrentAccumDirty;
 | 
				
			||||||
    float                   DragCurrentAccum;                   // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings
 | 
					    float                   DragCurrentAccum;                   // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings
 | 
				
			||||||
    float                   DragSpeedDefaultRatio;              // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
 | 
					    float                   DragSpeedDefaultRatio;              // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
 | 
				
			||||||
@@ -1082,7 +1083,7 @@ struct ImGuiContext
 | 
				
			|||||||
    ImVector<ImGuiSettingsHandler>      SettingsHandlers;       // List of .ini settings handlers
 | 
					    ImVector<ImGuiSettingsHandler>      SettingsHandlers;       // List of .ini settings handlers
 | 
				
			||||||
    ImChunkStream<ImGuiWindowSettings>  SettingsWindows;        // ImGuiWindow .ini settings entries
 | 
					    ImChunkStream<ImGuiWindowSettings>  SettingsWindows;        // ImGuiWindow .ini settings entries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Logging
 | 
					    // Capture/Logging
 | 
				
			||||||
    bool                    LogEnabled;
 | 
					    bool                    LogEnabled;
 | 
				
			||||||
    ImGuiLogType            LogType;
 | 
					    ImGuiLogType            LogType;
 | 
				
			||||||
    FILE*                   LogFile;                            // If != NULL log to stdout/ file
 | 
					    FILE*                   LogFile;                            // If != NULL log to stdout/ file
 | 
				
			||||||
@@ -1109,7 +1110,6 @@ struct ImGuiContext
 | 
				
			|||||||
    ImGuiContext(ImFontAtlas* shared_font_atlas) : BackgroundDrawList(&DrawListSharedData), ForegroundDrawList(&DrawListSharedData)
 | 
					    ImGuiContext(ImFontAtlas* shared_font_atlas) : BackgroundDrawList(&DrawListSharedData), ForegroundDrawList(&DrawListSharedData)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Initialized = false;
 | 
					        Initialized = false;
 | 
				
			||||||
        FrameScopeActive = FrameScopePushedImplicitWindow = false;
 | 
					 | 
				
			||||||
        Font = NULL;
 | 
					        Font = NULL;
 | 
				
			||||||
        FontSize = FontBaseSize = 0.0f;
 | 
					        FontSize = FontBaseSize = 0.0f;
 | 
				
			||||||
        FontAtlasOwnedByContext = shared_font_atlas ? false : true;
 | 
					        FontAtlasOwnedByContext = shared_font_atlas ? false : true;
 | 
				
			||||||
@@ -1117,6 +1117,7 @@ struct ImGuiContext
 | 
				
			|||||||
        Time = 0.0f;
 | 
					        Time = 0.0f;
 | 
				
			||||||
        FrameCount = 0;
 | 
					        FrameCount = 0;
 | 
				
			||||||
        FrameCountEnded = FrameCountRendered = -1;
 | 
					        FrameCountEnded = FrameCountRendered = -1;
 | 
				
			||||||
 | 
					        WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        WindowsActiveCount = 0;
 | 
					        WindowsActiveCount = 0;
 | 
				
			||||||
        CurrentWindow = NULL;
 | 
					        CurrentWindow = NULL;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user