diff --git a/imgui.cpp b/imgui.cpp index e0634995d..3fd666d86 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9818,6 +9818,7 @@ namespace ImGui { // ImGuiDockContext static ImGuiDockNode* DockContextAddNode(ImGuiContext* ctx, ImGuiID id); + static ImGuiID DockContextGenNodeID(ImGuiContext* ctx); static void DockContextRemoveNode(ImGuiContext* ctx, ImGuiDockNode* node, bool merge_sibling_into_parent_node); static void DockContextQueueDock(ImGuiContext* ctx, ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir, float split_ratio, bool split_outer); static void DockContextQueueNotifyRemovedNode(ImGuiContext* ctx, ImGuiDockNode* node); @@ -10008,17 +10009,23 @@ static ImGuiDockNode* ImGui::DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID return (ImGuiDockNode*)ctx->DockContext->Nodes.GetVoidPtr(id); } +static 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: 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. + ImGuiID id = 0x0001; + while (DockContextFindNodeByID(ctx, id) != NULL) + id++; + return id; +} + static ImGuiDockNode* ImGui::DockContextAddNode(ImGuiContext* ctx, ImGuiID id) { // Generate an ID for the new node (the exact ID value doesn't matter as long as it is not already used) and add the first window. if (id == 0) - { - // FIXME-OPT: This is suboptimal, even if the node count is small enough not to be a worry. We could poke in ctx->Nodes to find a suitable ID faster. - id = 0x0001; - while (DockContextFindNodeByID(ctx, id) != NULL) - id++; - } - IM_ASSERT(DockContextFindNodeByID(ctx, id) == NULL); + id = DockContextGenNodeID(ctx); + else + IM_ASSERT(DockContextFindNodeByID(ctx, id) == NULL); ImGuiDockNode* node = IM_NEW(ImGuiDockNode)(id); node->InitFromFirstWindowPosSize = node->InitFromFirstWindowViewport = true; ctx->DockContext->Nodes.SetVoidPtr(node->ID, node); @@ -10436,14 +10443,15 @@ static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window, b // If 2+ windows appeared on the same frame, creating a new DockNode+TabBar from the second window, // then we need to hide the first one after the fact otherwise it would be visible as a standalone window for one frame. - if (node->Windows.Size == 2 && node->HostWindow == NULL && node->Windows[0]->WasActive == false) + if (node->HostWindow == NULL && node->Windows.Size == 2 && node->Windows[0]->WasActive == false) { node->Windows[0]->Hidden = true; node->Windows[0]->HiddenFramesRegular = 1; } - // When reactivating a node from two loose window, the target window pos/size are authoritative - if (node->Windows.Size == 2 && !node->IsDockSpace) + // When reactivating a node with one or two loose window, the window pos/size/viewport are authoritative over the node storage. + // In particular it is important we init the viewport from the first window so we don't create two viewports and drop one. + if (node->HostWindow == NULL && !node->IsDockSpace && node->IsRootNode()) node->InitFromFirstWindowPosSize = node->InitFromFirstWindowViewport = true; // Add to tab bar if requested @@ -10817,7 +10825,6 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node) } else if (node->HostWindow == NULL) { - // Leaf SetNextWindowPos(node->Pos); SetNextWindowSize(node->Size); }