mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-30 18:34:34 +01:00
ImDrawData: Slight refactor so internal logic uses same logic as AddDrawList(). (#6406, #4879, #1878)
# Conflicts: # imgui.cpp # imgui_internal.h
This commit is contained in:
parent
1a9ddd2396
commit
dbeeeae593
81
imgui.cpp
81
imgui.cpp
@ -1012,7 +1012,6 @@ static void FindHoveredWindow();
|
||||
static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags);
|
||||
static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window);
|
||||
|
||||
static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
|
||||
static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
|
||||
|
||||
// Settings
|
||||
@ -4784,47 +4783,12 @@ static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, Im
|
||||
}
|
||||
}
|
||||
|
||||
static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list)
|
||||
{
|
||||
if (draw_list->CmdBuffer.Size == 0)
|
||||
return;
|
||||
if (draw_list->CmdBuffer.Size == 1 && draw_list->CmdBuffer[0].ElemCount == 0 && draw_list->CmdBuffer[0].UserCallback == NULL)
|
||||
return;
|
||||
|
||||
// Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
|
||||
// May trigger for you if you are using PrimXXX functions incorrectly.
|
||||
IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
|
||||
IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
|
||||
if (!(draw_list->Flags & ImDrawListFlags_AllowVtxOffset))
|
||||
IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);
|
||||
|
||||
// Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
|
||||
// If this assert triggers because you are drawing lots of stuff manually:
|
||||
// - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
|
||||
// Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics/Debugger window to inspect draw list contents.
|
||||
// - If you want large meshes with more than 64K vertices, you can either:
|
||||
// (A) Handle the ImDrawCmd::VtxOffset value in your renderer backend, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'.
|
||||
// Most example backends already support this from 1.71. Pre-1.71 backends won't.
|
||||
// Some graphics API such as GL ES 1/2 don't have a way to offset the starting vertex so it is not supported for them.
|
||||
// (B) Or handle 32-bit indices in your renderer backend, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h.
|
||||
// Most example backends already support this. For example, the OpenGL example code detect index size at compile-time:
|
||||
// glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
// Your own engine or render API may use different parameters or function calls to specify index sizes.
|
||||
// 2 and 4 bytes indices are generally supported by most graphics API.
|
||||
// - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching
|
||||
// the 64K limit to split your draw commands in multiple draw lists.
|
||||
if (sizeof(ImDrawIdx) == 2)
|
||||
IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
|
||||
|
||||
out_list->push_back(draw_list);
|
||||
}
|
||||
|
||||
static void AddWindowToDrawData(ImGuiWindow* window, int layer)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiViewportP* viewport = g.Viewports[0];
|
||||
g.IO.MetricsRenderWindows++;
|
||||
AddDrawListToDrawData(viewport->DrawDataBuilder.Layers[layer], window->DrawList);
|
||||
ImGui::AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[layer], window->DrawList);
|
||||
for (int i = 0; i < window->DC.ChildWindows.Size; i++)
|
||||
{
|
||||
ImGuiWindow* child = window->DC.ChildWindows[i];
|
||||
@ -4844,42 +4808,41 @@ static inline void AddRootWindowToDrawData(ImGuiWindow* window)
|
||||
AddWindowToDrawData(window, GetWindowDisplayLayer(window));
|
||||
}
|
||||
|
||||
void ImDrawDataBuilder::FlattenIntoSingleLayer()
|
||||
static void FlattenDrawDataIntoSingleLayer(ImDrawDataBuilder* builder)
|
||||
{
|
||||
int n = Layers[0]->Size;
|
||||
int n = builder->Layers[0]->Size;
|
||||
int full_size = n;
|
||||
for (int i = 1; i < IM_ARRAYSIZE(Layers); i++)
|
||||
full_size += Layers[i]->Size;
|
||||
Layers[0]->resize(full_size);
|
||||
for (int layer_n = 1; layer_n < IM_ARRAYSIZE(Layers); layer_n++)
|
||||
for (int i = 1; i < IM_ARRAYSIZE(builder->Layers); i++)
|
||||
full_size += builder->Layers[i]->Size;
|
||||
builder->Layers[0]->resize(full_size);
|
||||
for (int layer_n = 1; layer_n < IM_ARRAYSIZE(builder->Layers); layer_n++)
|
||||
{
|
||||
ImVector<ImDrawList*>* layer = Layers[layer_n];
|
||||
ImVector<ImDrawList*>* layer = builder->Layers[layer_n];
|
||||
if (layer->empty())
|
||||
continue;
|
||||
memcpy(Layers[0]->Data + n, layer->Data, layer->Size * sizeof(ImDrawList*));
|
||||
memcpy(builder->Layers[0]->Data + n, layer->Data, layer->Size * sizeof(ImDrawList*));
|
||||
n += layer->Size;
|
||||
layer->resize(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetupViewportDrawData(ImGuiViewportP* viewport)
|
||||
static void InitViewportDrawData(ImGuiViewportP* viewport)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImDrawData* draw_data = &viewport->DrawDataP;
|
||||
|
||||
viewport->DrawDataBuilder.Layers[0] = &draw_data->CmdLists;
|
||||
viewport->DrawDataBuilder.Layers[1] = &viewport->DrawDataBuilder.LayerData1;
|
||||
viewport->DrawDataBuilder.Layers[0]->resize(0);
|
||||
viewport->DrawDataBuilder.Layers[1]->resize(0);
|
||||
|
||||
draw_data->Valid = true;
|
||||
draw_data->CmdListsCount = draw_data->CmdLists.Size;
|
||||
draw_data->CmdListsCount = 0;
|
||||
draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
|
||||
draw_data->DisplayPos = viewport->Pos;
|
||||
draw_data->DisplaySize = viewport->Size;
|
||||
draw_data->FramebufferScale = io.DisplayFramebufferScale;
|
||||
draw_data->OwnerViewport = viewport;
|
||||
for (int n = 0; n < draw_data->CmdLists.Size; n++) // Similar to AddDrawList() but we are already added in the array
|
||||
{
|
||||
ImDrawList* draw_list = draw_data->CmdLists[n];
|
||||
draw_list->_PopUnusedDrawCmd();
|
||||
draw_data->TotalVtxCount += draw_list->VtxBuffer.Size;
|
||||
draw_data->TotalIdxCount += draw_list->IdxBuffer.Size;
|
||||
}
|
||||
}
|
||||
|
||||
// Push a clipping rectangle for both ImGui logic (hit-testing etc.) and low-level ImDrawList rendering.
|
||||
@ -5100,9 +5063,9 @@ void ImGui::Render()
|
||||
for (int n = 0; n != g.Viewports.Size; n++)
|
||||
{
|
||||
ImGuiViewportP* viewport = g.Viewports[n];
|
||||
viewport->DrawDataBuilder.Setup(&viewport->DrawDataP);
|
||||
InitViewportDrawData(viewport);
|
||||
if (viewport->DrawLists[0] != NULL)
|
||||
AddDrawListToDrawData(viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
|
||||
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
|
||||
}
|
||||
|
||||
// Draw modal/window whitening backgrounds
|
||||
@ -5133,14 +5096,14 @@ void ImGui::Render()
|
||||
for (int n = 0; n < g.Viewports.Size; n++)
|
||||
{
|
||||
ImGuiViewportP* viewport = g.Viewports[n];
|
||||
viewport->DrawDataBuilder.FlattenIntoSingleLayer();
|
||||
FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
|
||||
|
||||
// Add foreground ImDrawList (for each active viewport)
|
||||
if (viewport->DrawLists[1] != NULL)
|
||||
AddDrawListToDrawData(viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
|
||||
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
|
||||
|
||||
SetupViewportDrawData(viewport);
|
||||
ImDrawData* draw_data = &viewport->DrawDataP;
|
||||
IM_ASSERT(draw_data->CmdLists.Size == draw_data->CmdListsCount);
|
||||
g.IO.MetricsRenderVertices += draw_data->TotalVtxCount;
|
||||
g.IO.MetricsRenderIndices += draw_data->TotalIdxCount;
|
||||
}
|
||||
|
@ -1817,15 +1817,52 @@ void ImDrawData::Clear()
|
||||
OwnerViewport = NULL;
|
||||
}
|
||||
|
||||
// Important: 'out_list' is generally going to be draw_data->CmdLists, but may be another temporary list
|
||||
// as long at it is expected that the result will be later merged into draw_data->CmdLists[].
|
||||
void ImGui::AddDrawListToDrawDataEx(ImDrawData* draw_data, ImVector<ImDrawList*>* out_list, ImDrawList* draw_list)
|
||||
{
|
||||
if (draw_list->CmdBuffer.Size == 0)
|
||||
return;
|
||||
if (draw_list->CmdBuffer.Size == 1 && draw_list->CmdBuffer[0].ElemCount == 0 && draw_list->CmdBuffer[0].UserCallback == NULL)
|
||||
return;
|
||||
|
||||
// Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
|
||||
// May trigger for you if you are using PrimXXX functions incorrectly.
|
||||
IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
|
||||
IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
|
||||
if (!(draw_list->Flags & ImDrawListFlags_AllowVtxOffset))
|
||||
IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);
|
||||
|
||||
// Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
|
||||
// If this assert triggers because you are drawing lots of stuff manually:
|
||||
// - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
|
||||
// Be mindful that the lower-level ImDrawList API doesn't filter vertices. Use the Metrics/Debugger window to inspect draw list contents.
|
||||
// - If you want large meshes with more than 64K vertices, you can either:
|
||||
// (A) Handle the ImDrawCmd::VtxOffset value in your renderer backend, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'.
|
||||
// Most example backends already support this from 1.71. Pre-1.71 backends won't.
|
||||
// Some graphics API such as GL ES 1/2 don't have a way to offset the starting vertex so it is not supported for them.
|
||||
// (B) Or handle 32-bit indices in your renderer backend, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h.
|
||||
// Most example backends already support this. For example, the OpenGL example code detect index size at compile-time:
|
||||
// glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
// Your own engine or render API may use different parameters or function calls to specify index sizes.
|
||||
// 2 and 4 bytes indices are generally supported by most graphics API.
|
||||
// - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching
|
||||
// the 64K limit to split your draw commands in multiple draw lists.
|
||||
if (sizeof(ImDrawIdx) == 2)
|
||||
IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
|
||||
|
||||
// Add to output list + records state in ImDrawData
|
||||
out_list->push_back(draw_list);
|
||||
draw_list->_PopUnusedDrawCmd();
|
||||
draw_data->CmdListsCount++;
|
||||
draw_data->TotalVtxCount += draw_list->VtxBuffer.Size;
|
||||
draw_data->TotalIdxCount += draw_list->IdxBuffer.Size;
|
||||
}
|
||||
|
||||
void ImDrawData::AddDrawList(ImDrawList* draw_list)
|
||||
{
|
||||
IM_ASSERT(Valid);
|
||||
IM_ASSERT(CmdLists.Size == CmdListsCount);
|
||||
draw_list->_PopUnusedDrawCmd();
|
||||
CmdLists.push_back(draw_list);
|
||||
CmdListsCount++;
|
||||
TotalVtxCount += draw_list->VtxBuffer.Size;
|
||||
TotalIdxCount += draw_list->IdxBuffer.Size;
|
||||
ImGui::AddDrawListToDrawDataEx(this, &CmdLists, draw_list);
|
||||
}
|
||||
|
||||
// For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering!
|
||||
|
@ -776,8 +776,6 @@ struct ImDrawDataBuilder
|
||||
ImVector<ImDrawList*> LayerData1;
|
||||
|
||||
ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); }
|
||||
void Setup(ImDrawData* draw_data) { Layers[0] = &draw_data->CmdLists; Layers[1] = &LayerData1; for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n]->resize(0); }
|
||||
IMGUI_API void FlattenIntoSingleLayer();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -2802,6 +2800,7 @@ namespace ImGui
|
||||
inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); return GetForegroundDrawList(); } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches.
|
||||
IMGUI_API ImDrawList* GetBackgroundDrawList(ImGuiViewport* viewport); // get background draw list for the given viewport. this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents.
|
||||
IMGUI_API ImDrawList* GetForegroundDrawList(ImGuiViewport* viewport); // get foreground draw list for the given viewport. this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents.
|
||||
IMGUI_API void AddDrawListToDrawDataEx(ImDrawData* draw_data, ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
|
||||
|
||||
// Init
|
||||
IMGUI_API void Initialize();
|
||||
|
Loading…
Reference in New Issue
Block a user