mirror of https://github.com/ocornut/imgui
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 ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags);
|
||||||
static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window);
|
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);
|
static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
|
||||||
|
|
||||||
// Settings
|
// 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)
|
static void AddWindowToDrawData(ImGuiWindow* window, int layer)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiViewportP* viewport = g.Viewports[0];
|
ImGuiViewportP* viewport = g.Viewports[0];
|
||||||
g.IO.MetricsRenderWindows++;
|
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++)
|
for (int i = 0; i < window->DC.ChildWindows.Size; i++)
|
||||||
{
|
{
|
||||||
ImGuiWindow* child = window->DC.ChildWindows[i];
|
ImGuiWindow* child = window->DC.ChildWindows[i];
|
||||||
|
@ -4844,42 +4808,41 @@ static inline void AddRootWindowToDrawData(ImGuiWindow* window)
|
||||||
AddWindowToDrawData(window, GetWindowDisplayLayer(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;
|
int full_size = n;
|
||||||
for (int i = 1; i < IM_ARRAYSIZE(Layers); i++)
|
for (int i = 1; i < IM_ARRAYSIZE(builder->Layers); i++)
|
||||||
full_size += Layers[i]->Size;
|
full_size += builder->Layers[i]->Size;
|
||||||
Layers[0]->resize(full_size);
|
builder->Layers[0]->resize(full_size);
|
||||||
for (int layer_n = 1; layer_n < IM_ARRAYSIZE(Layers); layer_n++)
|
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())
|
if (layer->empty())
|
||||||
continue;
|
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;
|
n += layer->Size;
|
||||||
layer->resize(0);
|
layer->resize(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetupViewportDrawData(ImGuiViewportP* viewport)
|
static void InitViewportDrawData(ImGuiViewportP* viewport)
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
ImDrawData* draw_data = &viewport->DrawDataP;
|
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->Valid = true;
|
||||||
draw_data->CmdListsCount = draw_data->CmdLists.Size;
|
draw_data->CmdListsCount = 0;
|
||||||
draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
|
draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
|
||||||
draw_data->DisplayPos = viewport->Pos;
|
draw_data->DisplayPos = viewport->Pos;
|
||||||
draw_data->DisplaySize = viewport->Size;
|
draw_data->DisplaySize = viewport->Size;
|
||||||
draw_data->FramebufferScale = io.DisplayFramebufferScale;
|
draw_data->FramebufferScale = io.DisplayFramebufferScale;
|
||||||
draw_data->OwnerViewport = viewport;
|
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.
|
// 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++)
|
for (int n = 0; n != g.Viewports.Size; n++)
|
||||||
{
|
{
|
||||||
ImGuiViewportP* viewport = g.Viewports[n];
|
ImGuiViewportP* viewport = g.Viewports[n];
|
||||||
viewport->DrawDataBuilder.Setup(&viewport->DrawDataP);
|
InitViewportDrawData(viewport);
|
||||||
if (viewport->DrawLists[0] != NULL)
|
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
|
// Draw modal/window whitening backgrounds
|
||||||
|
@ -5133,14 +5096,14 @@ void ImGui::Render()
|
||||||
for (int n = 0; n < g.Viewports.Size; n++)
|
for (int n = 0; n < g.Viewports.Size; n++)
|
||||||
{
|
{
|
||||||
ImGuiViewportP* viewport = g.Viewports[n];
|
ImGuiViewportP* viewport = g.Viewports[n];
|
||||||
viewport->DrawDataBuilder.FlattenIntoSingleLayer();
|
FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
|
||||||
|
|
||||||
// Add foreground ImDrawList (for each active viewport)
|
// Add foreground ImDrawList (for each active viewport)
|
||||||
if (viewport->DrawLists[1] != NULL)
|
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;
|
ImDrawData* draw_data = &viewport->DrawDataP;
|
||||||
|
IM_ASSERT(draw_data->CmdLists.Size == draw_data->CmdListsCount);
|
||||||
g.IO.MetricsRenderVertices += draw_data->TotalVtxCount;
|
g.IO.MetricsRenderVertices += draw_data->TotalVtxCount;
|
||||||
g.IO.MetricsRenderIndices += draw_data->TotalIdxCount;
|
g.IO.MetricsRenderIndices += draw_data->TotalIdxCount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1817,15 +1817,52 @@ void ImDrawData::Clear()
|
||||||
OwnerViewport = NULL;
|
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)
|
void ImDrawData::AddDrawList(ImDrawList* draw_list)
|
||||||
{
|
{
|
||||||
IM_ASSERT(Valid);
|
|
||||||
IM_ASSERT(CmdLists.Size == CmdListsCount);
|
IM_ASSERT(CmdLists.Size == CmdListsCount);
|
||||||
draw_list->_PopUnusedDrawCmd();
|
ImGui::AddDrawListToDrawDataEx(this, &CmdLists, draw_list);
|
||||||
CmdLists.push_back(draw_list);
|
|
||||||
CmdListsCount++;
|
|
||||||
TotalVtxCount += draw_list->VtxBuffer.Size;
|
|
||||||
TotalIdxCount += draw_list->IdxBuffer.Size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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!
|
// 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;
|
ImVector<ImDrawList*> LayerData1;
|
||||||
|
|
||||||
ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); }
|
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.
|
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* 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 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
|
// Init
|
||||||
IMGUI_API void Initialize();
|
IMGUI_API void Initialize();
|
||||||
|
|
Loading…
Reference in New Issue