Extracted a EndFrame() function out of Render() but kept it internal/private + clarified some asserts (#335)

This commit is contained in:
ocornut 2015-09-16 23:48:42 +01:00
parent 0a1d6b6b74
commit 3b01b0a2f2
2 changed files with 79 additions and 65 deletions

View File

@ -2262,16 +2262,15 @@ static void PopClipRect()
window->ClipRect = window->DrawList->_ClipRectStack.back(); window->ClipRect = window->DrawList->_ClipRectStack.back();
} }
void ImGui::Render() // This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal.
void ImGui::EndFrame()
{ {
ImGuiState& g = *GImGui; ImGuiState& g = *GImGui;
IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame()
IM_ASSERT(g.FrameCountEnded != g.FrameCount); // ImGui::EndFrame() called multiple times, or forgot to call ImGui::NewFrame() again
const bool first_render_of_the_frame = (g.FrameCountRendered != g.FrameCount); g.FrameCountEnded = g.FrameCount;
g.FrameCountRendered = g.FrameCount;
if (first_render_of_the_frame)
{
// Hide implicit "Debug" window if it hasn't been used // Hide implicit "Debug" window if it hasn't been used
IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin/End IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin/End
if (g.CurrentWindow && !g.CurrentWindow->Accessed) if (g.CurrentWindow && !g.CurrentWindow->Accessed)
@ -2322,8 +2321,17 @@ void ImGui::Render()
memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
} }
void ImGui::Render()
{
ImGuiState& g = *GImGui;
IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame()
if (g.FrameCountEnded != g.FrameCount)
ImGui::EndFrame();
g.FrameCountRendered = g.FrameCount;
// Skip render altogether if alpha is 0.0 // Skip render altogether if alpha is 0.0
// Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or respond to Begin() returning false. // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or consistently respond to Begin() returning false.
if (g.Style.Alpha > 0.0f) if (g.Style.Alpha > 0.0f)
{ {
// Render tooltip // Render tooltip
@ -2363,13 +2371,13 @@ void ImGui::Render()
for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)
{ {
ImVector<ImDrawList*>& layer = g.RenderDrawLists[i]; ImVector<ImDrawList*>& layer = g.RenderDrawLists[i];
if (!layer.empty()) if (layer.empty())
{ continue;
memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));
n += layer.Size; n += layer.Size;
} }
}
// Draw software mouse cursor if requested
if (g.IO.MouseDrawCursor) if (g.IO.MouseDrawCursor)
{ {
const ImGuiMouseCursorData& cursor_data = g.MouseCursorData[g.MouseCursor]; const ImGuiMouseCursorData& cursor_data = g.MouseCursorData[g.MouseCursor];
@ -2395,11 +2403,9 @@ void ImGui::Render()
// Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData()
if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL)
{
g.IO.RenderDrawListsFn(&g.RenderDrawData); g.IO.RenderDrawListsFn(&g.RenderDrawData);
} }
} }
}
// Find the optional ## from which we stop displaying text. // Find the optional ## from which we stop displaying text.
static const char* FindTextDisplayEnd(const char* text, const char* text_end) static const char* FindTextDisplayEnd(const char* text, const char* text_end)
@ -3433,8 +3439,9 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
{ {
ImGuiState& g = *GImGui; ImGuiState& g = *GImGui;
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
IM_ASSERT(name != NULL); // Window name required
IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame()
IM_ASSERT(name != NULL); // Must pass a name IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet
if (flags & ImGuiWindowFlags_NoInputs) if (flags & ImGuiWindowFlags_NoInputs)
flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;

View File

@ -331,6 +331,7 @@ struct ImGuiState
float Time; float Time;
int FrameCount; int FrameCount;
int FrameCountEnded;
int FrameCountRendered; int FrameCountRendered;
ImVector<ImGuiWindow*> Windows; ImVector<ImGuiWindow*> Windows;
ImVector<ImGuiWindow*> WindowsSortBuffer; ImVector<ImGuiWindow*> WindowsSortBuffer;
@ -416,7 +417,7 @@ struct ImGuiState
Time = 0.0f; Time = 0.0f;
FrameCount = 0; FrameCount = 0;
FrameCountRendered = -1; FrameCountEnded = FrameCountRendered = -1;
CurrentWindow = NULL; CurrentWindow = NULL;
FocusedWindow = NULL; FocusedWindow = NULL;
HoveredWindow = NULL; HoveredWindow = NULL;
@ -631,7 +632,11 @@ public:
namespace ImGui namespace ImGui
{ {
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiState& g = *GImGui; return g.CurrentWindow; } // If this ever crash it means that ImGui::NewFrame() has never been called (which is illegal). We should always have a CurrentWindow in the stack (there is an implicit "Debug" window) // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
// If this ever crash because g.CurrentWindow is NULL it means that either
// - ImGui::NewFrame() has never been called, which is illegal.
// - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
inline ImGuiWindow* GetCurrentWindowRead() { ImGuiState& g = *GImGui; return g.CurrentWindow; }
inline ImGuiWindow* GetCurrentWindow() { ImGuiState& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; } inline ImGuiWindow* GetCurrentWindow() { ImGuiState& g = *GImGui; g.CurrentWindow->Accessed = true; return g.CurrentWindow; }
IMGUI_API ImGuiWindow* GetParentWindow(); IMGUI_API ImGuiWindow* GetParentWindow();
IMGUI_API void FocusWindow(ImGuiWindow* window); IMGUI_API void FocusWindow(ImGuiWindow* window);
@ -639,6 +644,8 @@ namespace ImGui
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void KeepAliveID(ImGuiID id); IMGUI_API void KeepAliveID(ImGuiID id);
IMGUI_API void EndFrame(); // This automatically called by Render()
IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f);
IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id); IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id);