From 0320e7257babeac02337771e1249317b44664a85 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 6 Jun 2020 20:25:56 +0200 Subject: [PATCH] ImDrawList: Small refactor to create empty command when beginning the frame, allowing to simplify some functions. + Missing clearing two fields in ClearFreeMemory() (was hamrless) --- imgui.cpp | 6 +++--- imgui.h | 5 +++-- imgui_draw.cpp | 18 +++++++++++------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 01ceafe9..07a832c4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3777,11 +3777,11 @@ void ImGui::NewFrame() if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; - g.BackgroundDrawList.Clear(); + g.BackgroundDrawList.ResetForNewFrame(); g.BackgroundDrawList.PushTextureID(g.IO.Fonts->TexID); g.BackgroundDrawList.PushClipRectFullScreen(); - g.ForegroundDrawList.Clear(); + g.ForegroundDrawList.ResetForNewFrame(); g.ForegroundDrawList.PushTextureID(g.IO.Fonts->TexID); g.ForegroundDrawList.PushClipRectFullScreen(); @@ -5860,7 +5860,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // DRAWING // Setup draw list and outer clipping rectangle - window->DrawList->Clear(); + window->DrawList->ResetForNewFrame(); window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); PushClipRect(host_rect.Min, host_rect.Max, false); diff --git a/imgui.h b/imgui.h index ebad93cb..7906ae07 100644 --- a/imgui.h +++ b/imgui.h @@ -1987,7 +1987,8 @@ struct ImDrawList ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!) // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui) - ImDrawList(const ImDrawListSharedData* shared_data) { _Data = shared_data; _OwnerName = NULL; Clear(); } + ImDrawList(const ImDrawListSharedData* shared_data) { _Data = shared_data; Flags = ImDrawListFlags_None; _VtxCurrentOffset = _VtxCurrentIdx = 0; _VtxWritePtr = NULL; _IdxWritePtr = NULL; _OwnerName = NULL; } + ~ImDrawList() { ClearFreeMemory(); } IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) IMGUI_API void PushClipRectFullScreen(); @@ -2056,7 +2057,7 @@ struct ImDrawList // [Internal helpers] // NB: all primitives needs to be reserved via PrimReserve() beforehand! - IMGUI_API void Clear(); + IMGUI_API void ResetForNewFrame(); IMGUI_API void ClearFreeMemory(); IMGUI_API void PrimReserve(int idx_count, int vtx_count); IMGUI_API void PrimUnreserve(int idx_count, int vtx_count); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 91de2ae6..d5844dbe 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -376,12 +376,13 @@ void ImDrawListSharedData::SetCircleSegmentMaxError(float max_error) } } -void ImDrawList::Clear() +// Initialize before use in a new frame. We always have a command ready in the buffer. +void ImDrawList::ResetForNewFrame() { CmdBuffer.resize(0); IdxBuffer.resize(0); VtxBuffer.resize(0); - Flags = _Data ? _Data->InitialFlags : ImDrawListFlags_None; + Flags = _Data->InitialFlags; _VtxCurrentOffset = 0; _VtxCurrentIdx = 0; _VtxWritePtr = NULL; @@ -390,6 +391,7 @@ void ImDrawList::Clear() _TextureIdStack.resize(0); _Path.resize(0); _Splitter.Clear(); + CmdBuffer.push_back(ImDrawCmd()); } void ImDrawList::ClearFreeMemory() @@ -397,6 +399,8 @@ void ImDrawList::ClearFreeMemory() CmdBuffer.clear(); IdxBuffer.clear(); VtxBuffer.clear(); + Flags = ImDrawListFlags_None; + _VtxCurrentOffset = 0; _VtxCurrentIdx = 0; _VtxWritePtr = NULL; _IdxWritePtr = NULL; @@ -434,8 +438,8 @@ void ImDrawList::AddDrawCmd() void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data) { - ImDrawCmd* curr_cmd = CmdBuffer.Size > 0 ? &CmdBuffer.Data[CmdBuffer.Size - 1] : NULL; - if (!curr_cmd || curr_cmd->ElemCount != 0 || curr_cmd->UserCallback != NULL) + ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; + if (curr_cmd->ElemCount != 0 || curr_cmd->UserCallback != NULL) { AddDrawCmd(); curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; @@ -452,8 +456,8 @@ void ImDrawList::UpdateClipRect() { // If current command is used with different settings we need to add a new command const ImVec4 curr_clip_rect = GetCurrentClipRect(); - ImDrawCmd* curr_cmd = CmdBuffer.Size > 0 ? &CmdBuffer.Data[CmdBuffer.Size - 1] : NULL; - if (!curr_cmd || (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) != 0) || curr_cmd->UserCallback != NULL) + ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; + if ((curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) != 0) || curr_cmd->UserCallback != NULL) { AddDrawCmd(); return; @@ -477,7 +481,7 @@ void ImDrawList::UpdateTextureID() { // If current command is used with different settings we need to add a new command const ImTextureID curr_texture_id = GetCurrentTextureId(); - ImDrawCmd* curr_cmd = CmdBuffer.Size > 0 ? &CmdBuffer.Data[CmdBuffer.Size - 1] : NULL; + ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; if (!curr_cmd || (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != curr_texture_id) || curr_cmd->UserCallback != NULL) { AddDrawCmd();