Internals: fixed iterating ImPool, fix after use of TableRemove() (was only used by TestEngine)

Merge metrics bits from 646c87359
This commit is contained in:
ocornut 2021-06-03 17:37:35 +02:00
parent a640d8a6d2
commit c6c82b9f1d
4 changed files with 43 additions and 27 deletions

View File

@ -11023,10 +11023,10 @@ void ImGui::ShowMetricsWindow(bool* p_open)
cfg->ShowTablesRects |= Combo("##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count); cfg->ShowTablesRects |= Combo("##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count);
if (cfg->ShowTablesRects && g.NavWindow != NULL) if (cfg->ShowTablesRects && g.NavWindow != NULL)
{ {
for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++) for (int table_n = 0; table_n < g.Tables.GetBufSize(); table_n++)
{ {
ImGuiTable* table = g.Tables.GetByIndex(table_n); ImGuiTable* table = g.Tables.TryGetBufData(table_n);
if (table->LastFrameActive < g.FrameCount - 1 || (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow)) if (table == NULL || table->LastFrameActive < g.FrameCount - 1 || (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow))
continue; continue;
BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name); BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
@ -11108,18 +11108,24 @@ void ImGui::ShowMetricsWindow(bool* p_open)
} }
// Details for TabBars // Details for TabBars
if (TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetSize())) if (TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetAliveCount()))
{ {
for (int n = 0; n < g.TabBars.GetSize(); n++) for (int n = 0; n < g.TabBars.GetBufSize(); n++)
DebugNodeTabBar(g.TabBars.GetByIndex(n), "TabBar"); if (ImGuiTabBar* tab_bar = g.TabBars.TryGetBufData(n))
{
PushID(tab_bar);
DebugNodeTabBar(tab_bar, "TabBar");
PopID();
}
TreePop(); TreePop();
} }
// Details for Tables // Details for Tables
if (TreeNode("Tables", "Tables (%d)", g.Tables.GetSize())) if (TreeNode("Tables", "Tables (%d)", g.Tables.GetAliveCount()))
{ {
for (int n = 0; n < g.Tables.GetSize(); n++) for (int n = 0; n < g.Tables.GetBufSize(); n++)
DebugNodeTable(g.Tables.GetByIndex(n)); if (ImGuiTable* table = g.Tables.TryGetBufData(n))
DebugNodeTable(table);
TreePop(); TreePop();
} }
@ -11253,10 +11259,10 @@ void ImGui::ShowMetricsWindow(bool* p_open)
// Overlay: Display Tables Rectangles // Overlay: Display Tables Rectangles
if (cfg->ShowTablesRects) if (cfg->ShowTablesRects)
{ {
for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++) for (int table_n = 0; table_n < g.Tables.GetBufSize(); table_n++)
{ {
ImGuiTable* table = g.Tables.GetByIndex(table_n); ImGuiTable* table = g.Tables.TryGetBufData(table_n);
if (table->LastFrameActive < g.FrameCount - 1) if (table == NULL || table->LastFrameActive < g.FrameCount - 1)
continue; continue;
ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow); ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow);
if (cfg->ShowTablesRectsType >= TRT_ColumnsRect) if (cfg->ShowTablesRectsType >= TRT_ColumnsRect)
@ -11560,7 +11566,7 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*"); p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*");
IM_UNUSED(p); IM_UNUSED(p);
if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
bool open = TreeNode(tab_bar, "%s", buf); bool open = TreeNode(label, "%s", buf);
if (!is_active) { PopStyleColor(); } if (!is_active) { PopStyleColor(); }
if (is_active && IsItemHovered()) if (is_active && IsItemHovered())
{ {

View File

@ -61,7 +61,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.84 WIP" #define IMGUI_VERSION "1.84 WIP"
#define IMGUI_VERSION_NUM 18302 #define IMGUI_VERSION_NUM 18303
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE

View File

@ -612,20 +612,29 @@ struct IMGUI_API ImPool
ImVector<T> Buf; // Contiguous data ImVector<T> Buf; // Contiguous data
ImGuiStorage Map; // ID->Index ImGuiStorage Map; // ID->Index
ImPoolIdx FreeIdx; // Next free idx to use ImPoolIdx FreeIdx; // Next free idx to use
ImPoolIdx AliveCount; // Number of active/alive items (for display purpose only)
ImPool() { FreeIdx = 0; } ImPool() { FreeIdx = AliveCount = 0; }
~ImPool() { Clear(); } ~ImPool() { Clear(); }
T* GetByKey(ImGuiID key) { int idx = Map.GetInt(key, -1); return (idx != -1) ? &Buf[idx] : NULL; } T* GetByKey(ImGuiID key) { int idx = Map.GetInt(key, -1); return (idx != -1) ? &Buf[idx] : NULL; }
T* GetByIndex(ImPoolIdx n) { return &Buf[n]; } T* GetByIndex(ImPoolIdx n) { return &Buf[n]; }
ImPoolIdx GetIndex(const T* p) const { IM_ASSERT(p >= Buf.Data && p < Buf.Data + Buf.Size); return (ImPoolIdx)(p - Buf.Data); } ImPoolIdx GetIndex(const T* p) const { IM_ASSERT(p >= Buf.Data && p < Buf.Data + Buf.Size); return (ImPoolIdx)(p - Buf.Data); }
T* GetOrAddByKey(ImGuiID key) { int* p_idx = Map.GetIntRef(key, -1); if (*p_idx != -1) return &Buf[*p_idx]; *p_idx = FreeIdx; return Add(); } T* GetOrAddByKey(ImGuiID key) { int* p_idx = Map.GetIntRef(key, -1); if (*p_idx != -1) return &Buf[*p_idx]; *p_idx = FreeIdx; return Add(); }
bool Contains(const T* p) const { return (p >= Buf.Data && p < Buf.Data + Buf.Size); } bool Contains(const T* p) const { return (p >= Buf.Data && p < Buf.Data + Buf.Size); }
void Clear() { for (int n = 0; n < Map.Data.Size; n++) { int idx = Map.Data[n].val_i; if (idx != -1) Buf[idx].~T(); } Map.Clear(); Buf.clear(); FreeIdx = 0; } void Clear() { for (int n = 0; n < Map.Data.Size; n++) { int idx = Map.Data[n].val_i; if (idx != -1) Buf[idx].~T(); } Map.Clear(); Buf.clear(); FreeIdx = AliveCount = 0; }
T* Add() { int idx = FreeIdx; if (idx == Buf.Size) { Buf.resize(Buf.Size + 1); FreeIdx++; } else { FreeIdx = *(int*)&Buf[idx]; } IM_PLACEMENT_NEW(&Buf[idx]) T(); return &Buf[idx]; } T* Add() { int idx = FreeIdx; if (idx == Buf.Size) { Buf.resize(Buf.Size + 1); FreeIdx++; } else { FreeIdx = *(int*)&Buf[idx]; } IM_PLACEMENT_NEW(&Buf[idx]) T(); AliveCount++; return &Buf[idx]; }
void Remove(ImGuiID key, const T* p) { Remove(key, GetIndex(p)); } void Remove(ImGuiID key, const T* p) { Remove(key, GetIndex(p)); }
void Remove(ImGuiID key, ImPoolIdx idx) { Buf[idx].~T(); *(int*)&Buf[idx] = FreeIdx; FreeIdx = idx; Map.SetInt(key, -1); } void Remove(ImGuiID key, ImPoolIdx idx) { Buf[idx].~T(); *(int*)&Buf[idx] = FreeIdx; FreeIdx = idx; Map.SetInt(key, -1); AliveCount--; }
void Reserve(int capacity) { Buf.reserve(capacity); Map.Data.reserve(capacity); } void Reserve(int capacity) { Buf.reserve(capacity); Map.Data.reserve(capacity); }
int GetSize() const { return Buf.Size; }
// To iterate a ImPool: for (int n = 0; n < pool.GetBufSize(); n++) if (T* t = pool.TryGetBufData(n)) { ... }
// Can be avoided if you know .Remove() has never been called on the pool, or AliveCount == GetBufSize()
int GetAliveCount() const { return AliveCount; } // Number of active/alive items in the pool (for display purpose only)
int GetBufSize() const { IM_ASSERT(Buf.Size == Map.Data.Size); return Buf.Size; }
T* TryGetBufData(ImPoolIdx n) { int idx = Map.Data[n].val_i; if (idx == -1) return NULL; return GetByIndex(idx); }
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
int GetSize() { return GetBufSize(); } // For ImPlot: should use GetMapSize() from (IMGUI_VERSION_NUM >= 18303)
#endif
}; };
// Helper: ImChunkStream<> // Helper: ImChunkStream<>

View File

@ -3298,8 +3298,9 @@ void ImGui::TableLoadSettings(ImGuiTable* table)
static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*) static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
for (int i = 0; i != g.Tables.GetSize(); i++) for (int i = 0; i != g.Tables.GetBufSize(); i++)
g.Tables.GetByIndex(i)->SettingsOffset = -1; if (ImGuiTable* table = g.Tables.TryGetBufData(i))
table->SettingsOffset = -1;
g.SettingsTables.clear(); g.SettingsTables.clear();
} }
@ -3307,9 +3308,9 @@ static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandle
static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*) static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
{ {
ImGuiContext& g = *ctx; ImGuiContext& g = *ctx;
for (int i = 0; i != g.Tables.GetSize(); i++) for (int i = 0; i != g.Tables.GetBufSize(); i++)
if (ImGuiTable* table = g.Tables.TryGetBufData(i))
{ {
ImGuiTable* table = g.Tables.GetByIndex(i);
table->IsSettingsRequestLoad = true; table->IsSettingsRequestLoad = true;
table->SettingsOffset = -1; table->SettingsOffset = -1;
} }