From cd4cc9ff0d2995b683129fb77c05a856110141a9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 7 Jul 2021 16:18:11 +0200 Subject: [PATCH] Docking: Fixed crash issues using DockBuilderRemoveNode() in some situations. (#3111, #3179, #3203, #4295) If the deleted root node isn't part of a dockspace with a central node, it won't be "protected" but removed when last window gets removed. --- docs/CHANGELOG.txt | 1 + imgui.cpp | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 546907b34..b1647740d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -144,6 +144,7 @@ Docking+Viewports Branch: - Docking: Clicking on the right-most close button of a docking node closes all windows. (#4186) - Docking: Fix IsWindowAppearing() and ImGuiCond_Appearing on docked windows. (#4177, #3982, #1497, #1061) +- Docking: Fix crash issues using DockBuilderRemoveNode() in some situations. (#3111, #3179, #3203, #4295) [@hsimyu] - Docking: Reworked node flags saving/inheritance so that flags enforced by docked windows via the DockNodeFlagsOverrideSet mechanism are are not left in empty dockspace nodes once the windows gets undocked. (#4292, #3834, #3633, #3521, #3492, #3335, #2999, #2648) diff --git a/imgui.cpp b/imgui.cpp index 5de5f63e1..4a1f51929 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12617,7 +12617,8 @@ static ImGuiDockNode* ImGui::DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID ImGuiID ImGui::DockContextGenNodeID(ImGuiContext* ctx) { // Generate an ID for new node (the exact ID value doesn't matter as long as it is not already used) - // FIXME-OPT FIXME-DOCK: This is suboptimal, even if the node count is small enough not to be a worry. We should poke in ctx->Nodes to find a suitable ID faster. + // FIXME-OPT FIXME-DOCK: This is suboptimal, even if the node count is small enough not to be a worry.0 + // We should poke in ctx->Nodes to find a suitable ID faster. Even more so trivial that ctx->Nodes lookup is already sorted. ImGuiID id = 0x0001; while (DockContextFindNodeByID(ctx, id) != NULL) id++; @@ -15125,11 +15126,11 @@ void ImGui::DockBuilderSetNodeSize(ImGuiID node_id, ImVec2 size) ImGuiID ImGui::DockBuilderAddNode(ImGuiID id, ImGuiDockNodeFlags flags) { ImGuiContext* ctx = GImGui; - ImGuiDockNode* node = NULL; if (id != 0) DockBuilderRemoveNode(id); + ImGuiDockNode* node = NULL; if (flags & ImGuiDockNodeFlags_DockSpace) { DockSpace(id, ImVec2(0, 0), (flags & ~ImGuiDockNodeFlags_DockSpace) | ImGuiDockNodeFlags_KeepAliveOnly); @@ -15152,6 +15153,10 @@ void ImGui::DockBuilderRemoveNode(ImGuiID node_id) return; DockBuilderRemoveNodeDockedWindows(node_id, true); DockBuilderRemoveNodeChildNodes(node_id); + // Node may have moved or deleted if e.g. any merge happened + node = DockContextFindNodeByID(ctx, node_id); + if (node == NULL) + return; if (node->IsCentralNode() && node->ParentNode) node->ParentNode->SetLocalFlags(node->ParentNode->LocalFlags | ImGuiDockNodeFlags_CentralNode); DockContextRemoveNode(ctx, node, true); @@ -15334,11 +15339,12 @@ void ImGui::DockBuilderCopyNode(ImGuiID src_node_id, ImGuiID dst_node_id, ImVect IM_ASSERT(dst_node_id != 0); IM_ASSERT(out_node_remap_pairs != NULL); + DockBuilderRemoveNode(dst_node_id); + ImGuiDockNode* src_node = DockContextFindNodeByID(ctx, src_node_id); IM_ASSERT(src_node != NULL); out_node_remap_pairs->clear(); - DockBuilderRemoveNode(dst_node_id); DockBuilderCopyNodeRec(src_node, dst_node_id, out_node_remap_pairs); IM_ASSERT((out_node_remap_pairs->Size % 2) == 0);