From 3f51c831def4c99ce704bbea4bfc62844ff7b0be Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 26 Nov 2018 22:18:55 +0100 Subject: [PATCH] Docking: Added internal DockBuilderGetCentralNode(). Fixed being unable to undock whole node from dock button in DockSpace with a central node. (#2109) --- imgui.cpp | 11 ++++++----- imgui_internal.h | 4 +++- imgui_widgets.cpp | 10 +++++++++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f88f2a2c..5c60c4d9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10350,7 +10350,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id) SplitAxis = ImGuiAxis_None; HostWindow = VisibleWindow = NULL; - OnlyNodeWithWindows = NULL; + CentralNode = OnlyNodeWithWindows = NULL; LastFrameAlive = LastFrameActive = -1; LastFocusedNodeID = 0; SelectedTabID = 0; @@ -10674,7 +10674,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node) IM_ASSERT(node->LastFrameActive != g.FrameCount); node->LastFrameAlive = g.FrameCount; - ImGuiDockNode* central_node = NULL; + node->CentralNode = node->OnlyNodeWithWindows = NULL; if (node->IsRootNode()) { DockNodeUpdateVisibleFlagAndInactiveChilds(node); @@ -10682,10 +10682,10 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node) // Find if there's only a single visible window in the hierarchy (in which case we need to display a regular title bar -> FIXME-DOCK: that last part is not done yet!) ImGuiDockNodeUpdateScanResults results; DockNodeUpdateScanRec(node, &results); - node->OnlyNodeWithWindows = (results.CountNodesWithWindows == 1 ? results.FirstNodeWithWindows : NULL); + node->CentralNode = results.CentralNode; + node->OnlyNodeWithWindows = (results.CountNodesWithWindows == 1) ? results.FirstNodeWithWindows : NULL; if (node->LastFocusedNodeID == 0 && results.FirstNodeWithWindows != NULL) node->LastFocusedNodeID = results.FirstNodeWithWindows->ID; - central_node = results.CentralNode; // Copy the dock family from of our window so it can be used for proper dock filtering. // When node has mixed windows, prioritize the family with the most constraint (CompatibleWithNeutral = false) as the reference to copy. @@ -10825,7 +10825,8 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node) } // Register a hit-test hole in the window unless we are currently dragging a window that is compatible with our dockspace - bool central_node_hole = node->IsRootNode() && host_window && (node->Flags & ImGuiDockNodeFlags_PassthruDockspace) != 0 && central_node != NULL && central_node->IsEmpty(); + const ImGuiDockNode* central_node = node->CentralNode; + const bool central_node_hole = node->IsRootNode() && host_window && (node->Flags & ImGuiDockNodeFlags_PassthruDockspace) != 0 && central_node != NULL && central_node->IsEmpty(); bool central_node_hole_register_hit_test_hole = central_node_hole; if (central_node_hole) if (const ImGuiPayload* payload = ImGui::GetDragDropPayload()) diff --git a/imgui_internal.h b/imgui_internal.h index 42f86248..67927949 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -769,7 +769,8 @@ struct ImGuiDockNode ImGuiWindow* HostWindow; ImGuiWindow* VisibleWindow; - ImGuiDockNode* OnlyNodeWithWindows; // [Root node only] Set when there is a single visible node within the hierarchy + ImGuiDockNode* CentralNode; // [Root node only] Pointer to central node. + ImGuiDockNode* OnlyNodeWithWindows; // [Root node only] Set when there is a single visible node within the hierarchy. int LastFrameAlive; // Last frame number the node was updated or kept alive explicitly with DockSpace() + ImGuiDockNodeFlags_KeepAliveOnly int LastFrameActive; // Last frame number the node was updated. ImGuiID LastFocusedNodeID; // [Root node only] Which of our child node (any ancestor in the hierarchy) was last focused. @@ -1505,6 +1506,7 @@ namespace ImGui // Docking - Builder function needs to be generally called before the DockSpace() node is submitted. IMGUI_API void DockBuilderDockWindow(const char* window_name, ImGuiID node_id); IMGUI_API ImGuiDockNode*DockBuilderGetNode(ImGuiID node_id); // Warning: DO NOT HOLD ON ImGuiDockNode* pointer, will be invalided by any split/merge/remove operation. + inline ImGuiDockNode* DockBuilderGetCentralNode(ImGuiID node_id) { ImGuiDockNode* node = DockBuilderGetNode(node_id); if (!node) return NULL; return DockNodeGetRootNode(node)->CentralNode; } IMGUI_API void DockBuilderAddNode(ImGuiID node_id, ImVec2 ref_size, ImGuiDockNodeFlags flags = 0); IMGUI_API void DockBuilderRemoveNode(ImGuiID node_id); // Remove node and all its child, undock all windows IMGUI_API void DockBuilderRemoveNodeDockedWindows(ImGuiID node_id, bool clear_persistent_docking_references = true); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d9d3e34f..a638eb68 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -671,6 +671,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) return pressed; } +// The Collapse button also functions as a Dock Menu button. bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_node) { ImGuiContext& g = *GImGui; @@ -695,7 +696,14 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_no // Switch to moving the window after mouse is moved beyond the initial drag threshold if (IsItemActive() && IsMouseDragging(0)) { - if (dock_node != NULL && DockNodeGetRootNode(dock_node)->OnlyNodeWithWindows != dock_node) + bool can_extract_dock_node = false; + if (dock_node != NULL) + { + ImGuiDockNode* root_node = DockNodeGetRootNode(dock_node); + if (root_node->OnlyNodeWithWindows != dock_node || (root_node->CentralNode != NULL)) + can_extract_dock_node = true; + } + if (can_extract_dock_node) { float threshold_base = g.FontSize; float threshold_x = (threshold_base * 2.2f);