Docking: Reworked DockContextPruneUnusedSettingsNodes() to prune entire unused trees.

This commit is contained in:
omar 2018-09-26 22:18:07 +02:00
parent c0a89f8f4e
commit 18ffb7dd86
2 changed files with 42 additions and 24 deletions

View File

@ -125,6 +125,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- dock: A~ Unreal style document system (requires low-level controls of dockspace serialization fork/copy/delete) - dock: A~ Unreal style document system (requires low-level controls of dockspace serialization fork/copy/delete)
- dock: A- implicit, invisible per-viewport dockspace to dock to. - dock: A- implicit, invisible per-viewport dockspace to dock to.
- dock: B: when docking outer, perform size locking on neighbors nodes the same way we do it with splitters, so other nodes are not resized
- dock: B~ document root node resizing behavior incorrect - dock: B~ document root node resizing behavior incorrect
- dock: B~ document root node retrieval of ID ? - dock: B~ document root node retrieval of ID ?
- dock: B- full rebuild loses viewport of floating dock nodes - dock: B- full rebuild loses viewport of floating dock nodes

View File

@ -9866,38 +9866,54 @@ static void ImGui::DockContextPruneUnusedSettingsNodes(ImGuiContext* ctx)
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = ctx->DockContext;
IM_ASSERT(g.Windows.Size == 0); IM_ASSERT(g.Windows.Size == 0);
// Count reference to dock ids from window settings struct NodeData
ImGuiStorage ref_count_map; // Map dock_id -> counter {
ref_count_map.Data.reserve(dc->SettingsNodes.Size); int CountWindows, CountChildWindows, CountChildNodes;
for (int settings_n = 0; settings_n < g.SettingsWindows.Size; settings_n++) ImGuiID RootID;
if (g.SettingsWindows[settings_n].DockId != 0) NodeData() { CountWindows = CountChildWindows = CountChildNodes = 0; RootID = 0; }
(*ref_count_map.GetIntRef(g.SettingsWindows[settings_n].DockId, 0))++; };
ImPool<NodeData> pool;
pool.Reserve(dc->SettingsNodes.Size);
// Mark nodes that are parents // Count child nodes and compute RootID
ImGuiStorage is_parent_map;
is_parent_map.Data.reserve(dc->SettingsNodes.Size);
for (int settings_n = 0; settings_n < dc->SettingsNodes.Size; settings_n++)
if (dc->SettingsNodes[settings_n].ParentID)
is_parent_map.SetInt(dc->SettingsNodes[settings_n].ParentID, 1);
// If a root node has only 1 reference in window settings we clear it
// FIXME-DOCK: We should be able to merge unused nodes as well.
for (int settings_n = 0; settings_n < dc->SettingsNodes.Size; settings_n++) for (int settings_n = 0; settings_n < dc->SettingsNodes.Size; settings_n++)
{ {
ImGuiDockNodeSettings* settings = &dc->SettingsNodes[settings_n]; ImGuiDockNodeSettings* settings = &dc->SettingsNodes[settings_n];
int ref_count = ref_count_map.GetInt(settings->ID, 0); NodeData* parent_data = settings->ParentID ? pool.GetByKey(settings->ParentID) : 0;
if (ref_count <= 1) pool.GetOrAddByKey(settings->ID)->RootID = parent_data ? parent_data->RootID : settings->ID;
if (settings->ParentID)
pool.GetOrAddByKey(settings->ParentID)->CountChildNodes++;
}
// Count reference to dock ids from window settings
for (int settings_n = 0; settings_n < g.SettingsWindows.Size; settings_n++)
if (ImGuiID dock_id = g.SettingsWindows[settings_n].DockId)
if (NodeData* data = pool.GetByKey(dock_id))
{ {
NodeData* data_root = (data->RootID == dock_id) ? data : pool.GetByKey(data->RootID);
data->CountWindows++;
data_root->CountChildWindows++;
}
// Prune
for (int settings_n = 0; settings_n < dc->SettingsNodes.Size; settings_n++)
{
ImGuiDockNodeSettings* settings = &dc->SettingsNodes[settings_n];
NodeData* data = pool.GetByKey(settings->ID);
if (data->CountWindows > 1)
continue;
NodeData* data_root = (data->RootID == settings->ID) ? data : pool.GetByKey(data->RootID);
bool remove = false; bool remove = false;
remove |= (ref_count == 1 && settings->ParentID == 0 && !settings->IsDocumentRoot); // Root node with only 1 window remove |= (data->CountWindows == 1 && settings->ParentID == 0 && data->CountChildNodes == 0 && !settings->IsDocumentRoot); // Floating root node with only 1 window
remove |= (ref_count == 0 && settings->ParentID == 0 && is_parent_map.GetInt(settings->ID, 0) == 0); // Leaf nodes with 0 window remove |= (data->CountWindows == 0 && settings->ParentID == 0 && data->CountChildNodes == 0); // Leaf nodes with 0 window
remove |= (data_root->CountChildWindows == 0);
if (remove) if (remove)
{ {
DockSettingsRemoveReferencesToNodes(&settings->ID, 1); DockSettingsRemoveReferencesToNodes(&settings->ID, 1);
settings->ID = 0; settings->ID = 0;
} }
} }
}
} }
static void ImGui::DockContextBuildNodesFromSettings(ImGuiContext* ctx, ImGuiDockNodeSettings* node_settings_array, int node_settings_count) static void ImGui::DockContextBuildNodesFromSettings(ImGuiContext* ctx, ImGuiDockNodeSettings* node_settings_array, int node_settings_count)
@ -11953,6 +11969,7 @@ static void ImGui::DockSettingsRemoveReferencesToNodes(ImGuiID* node_ids, int no
static ImGuiDockNodeSettings* ImGui::DockSettingsFindNodeSettings(ImGuiContext* ctx, ImGuiID id) static ImGuiDockNodeSettings* ImGui::DockSettingsFindNodeSettings(ImGuiContext* ctx, ImGuiID id)
{ {
// FIXME-OPT
ImGuiDockContext* dc = ctx->DockContext; ImGuiDockContext* dc = ctx->DockContext;
for (int n = 0; n < dc->SettingsNodes.Size; n++) for (int n = 0; n < dc->SettingsNodes.Size; n++)
if (dc->SettingsNodes[n].ID == id) if (dc->SettingsNodes[n].ID == id)