mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 13:11:05 +01:00 
			
		
		
		
	Docking: Builder: Added DockBuilderSetNodePos, DockBuilderSetNodeSize, allow DockBuilderAddNode creating floating node (dockspace requires ImGuiDockNodeFlags_Dockspace) (#2109)
This commit is contained in:
		
							
								
								
									
										109
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -10367,7 +10367,6 @@ static ImGuiDockNode* ImGui::DockContextAddNode(ImGuiContext* ctx, ImGuiID id) | ||||
|     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); | ||||
|     return node; | ||||
| } | ||||
| @@ -10719,9 +10718,9 @@ void ImGui::DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node) | ||||
|         int index_in_parent = (node->ParentNode->ChildNodes[0] == node) ? 0 : 1; | ||||
|         node->ParentNode->ChildNodes[index_in_parent] = NULL; | ||||
|         DockNodeTreeMerge(ctx, node->ParentNode, node->ParentNode->ChildNodes[index_in_parent ^ 1]); | ||||
|         node->ParentNode->InitFromFirstWindowViewport = true; // The node that stays in place keeps the viewport, so our newly dragged out node will create a new viewport | ||||
|         node->ParentNode->AutorityForViewport = ImGuiDataAutority_Window; // The node that stays in place keeps the viewport, so our newly dragged out node will create a new viewport | ||||
|         node->ParentNode = NULL; | ||||
|         node->InitFromFirstWindowPosSize = true; | ||||
|         node->AutorityForPos = node->AutorityForSize = ImGuiDataAutority_Window; | ||||
|         node->WantMouseMove = true; | ||||
|     } | ||||
|     MarkIniSettingsDirty(); | ||||
| @@ -10745,7 +10744,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id) | ||||
|     LastFocusedNodeID = 0; | ||||
|     SelectedTabID = 0; | ||||
|     WantCloseTabID = 0; | ||||
|     InitFromFirstWindowPosSize = InitFromFirstWindowViewport = false; | ||||
|     AutorityForPos = AutorityForSize = AutorityForViewport = ImGuiDataAutority_Auto; | ||||
|     IsVisible = true; | ||||
|     IsFocused = IsCentralNode = IsHiddenTabBar = HasCloseButton = HasCollapseButton = false; | ||||
|     WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle = false; | ||||
| @@ -10796,7 +10795,14 @@ static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window, b | ||||
|     // 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; | ||||
|     { | ||||
|         if (node->AutorityForPos == ImGuiDataAutority_Auto) | ||||
|             node->AutorityForPos = ImGuiDataAutority_Window; | ||||
|         if (node->AutorityForSize == ImGuiDataAutority_Auto) | ||||
|             node->AutorityForSize = ImGuiDataAutority_Window; | ||||
|         if (node->AutorityForViewport == ImGuiDataAutority_Auto) | ||||
|             node->AutorityForViewport = ImGuiDataAutority_Window; | ||||
|     } | ||||
|  | ||||
|     // Add to tab bar if requested | ||||
|     if (add_to_tab_bar) | ||||
| @@ -11138,7 +11144,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node) | ||||
|         } | ||||
|  | ||||
|         DockNodeHideHostWindow(node); | ||||
|         node->InitFromFirstWindowPosSize = node->InitFromFirstWindowViewport = false; | ||||
|         node->AutorityForPos = node->AutorityForSize = node->AutorityForViewport = ImGuiDataAutority_Auto; | ||||
|         node->WantCloseAll = false; | ||||
|         node->WantCloseTabID = 0; | ||||
|         node->HasCloseButton = node->HasCollapseButton = false; | ||||
| @@ -11174,20 +11180,28 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node) | ||||
|  | ||||
|         if (node->IsRootNode() && node->IsVisible) | ||||
|         { | ||||
|             if (node->InitFromFirstWindowPosSize && node->Windows.Size > 0) | ||||
|             { | ||||
|                 ImGuiWindow* init_window = node->Windows[0]; | ||||
|                 SetNextWindowPos(init_window->Pos); | ||||
|                 SetNextWindowSize(init_window->SizeFull); | ||||
|                 SetNextWindowCollapsed(init_window->Collapsed); | ||||
|             } | ||||
|             else if (node->HostWindow == NULL) | ||||
|             { | ||||
|             ImGuiWindow* ref_window = (node->Windows.Size > 0) ? node->Windows[0] : NULL; | ||||
|  | ||||
|             // Sync Pos | ||||
|             if (node->AutorityForPos == ImGuiDataAutority_Window && ref_window) | ||||
|                 SetNextWindowPos(ref_window->Pos); | ||||
|             else if (node->AutorityForPos == ImGuiDataAutority_DockNode) | ||||
|                 SetNextWindowPos(node->Pos); | ||||
|  | ||||
|             // Sync Size | ||||
|             if (node->AutorityForSize == ImGuiDataAutority_Window && ref_window) | ||||
|                 SetNextWindowSize(ref_window->SizeFull); | ||||
|             else if (node->AutorityForSize == ImGuiDataAutority_DockNode) | ||||
|                 SetNextWindowSize(node->Size); | ||||
|             } | ||||
|             if (node->InitFromFirstWindowViewport && node->Windows.Size > 0) | ||||
|                 SetNextWindowViewport(node->Windows[0]->ViewportId); | ||||
|  | ||||
|             // Sync Collapsed | ||||
|             if (node->AutorityForSize == ImGuiDataAutority_Window && ref_window) | ||||
|                 SetNextWindowCollapsed(ref_window->Collapsed); | ||||
|  | ||||
|             // Sync Viewport | ||||
|             if (node->AutorityForViewport == ImGuiDataAutority_Window && ref_window) | ||||
|                 SetNextWindowViewport(ref_window->ViewportId); | ||||
|  | ||||
|             SetNextWindowClass(&node->WindowClass); | ||||
|  | ||||
|             // Begin into the host window | ||||
| @@ -11222,7 +11236,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node) | ||||
|         { | ||||
|             node->HostWindow = host_window = node->ParentNode->HostWindow; | ||||
|         } | ||||
|         node->InitFromFirstWindowPosSize = node->InitFromFirstWindowViewport = false; | ||||
|         node->AutorityForPos = node->AutorityForSize = node->AutorityForViewport = ImGuiDataAutority_Auto; | ||||
|         if (node->WantMouseMove && node->HostWindow) | ||||
|             DockNodeStartMouseMovingWindow(node, node->HostWindow); | ||||
|     } | ||||
| @@ -11950,7 +11964,7 @@ void ImGui::DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImG | ||||
|         DockSettingsRenameNodeReferences(child_1->ID, parent_node->ID); | ||||
|     } | ||||
|     DockNodeApplyPosSizeToWindows(parent_node); | ||||
|     parent_node->InitFromFirstWindowPosSize = parent_node->InitFromFirstWindowViewport = false; | ||||
|     parent_node->AutorityForPos = parent_node->AutorityForSize = parent_node->AutorityForViewport = ImGuiDataAutority_Auto; | ||||
|     parent_node->VisibleWindow = merge_lead_child->VisibleWindow; | ||||
|     parent_node->IsCentralNode = (child_0 && child_0->IsCentralNode) || (child_1 && child_1->IsCentralNode); | ||||
|     parent_node->IsHiddenTabBar = merge_lead_child->IsHiddenTabBar; | ||||
| @@ -12359,11 +12373,13 @@ ImGuiID ImGui::DockSpaceOverViewport(ImGuiViewport* viewport, ImGuiDockNodeFlags | ||||
|  | ||||
| void ImGui::DockBuilderDockWindow(const char* window_name, ImGuiID node_id) | ||||
| { | ||||
|     // We don't preserve relative order of multiple docked windows (by clearing DockOrder back to -1) | ||||
|     ImGuiID window_id = ImHashStr(window_name, 0); | ||||
|     if (ImGuiWindow* window = FindWindowByID(window_id)) | ||||
|     { | ||||
|         // Apply to created window | ||||
|         SetWindowDock(window, node_id, ImGuiCond_Always); | ||||
|         window->DockOrder = -1; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
| @@ -12372,6 +12388,7 @@ void ImGui::DockBuilderDockWindow(const char* window_name, ImGuiID node_id) | ||||
|         if (settings == NULL) | ||||
|             settings = CreateNewWindowSettings(window_name); | ||||
|         settings->DockId = node_id; | ||||
|         settings->DockOrder = -1; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -12381,13 +12398,47 @@ ImGuiDockNode* ImGui::DockBuilderGetNode(ImGuiID node_id) | ||||
|     return DockContextFindNodeByID(ctx, node_id); | ||||
| } | ||||
|  | ||||
| void ImGui::DockBuilderAddNode(ImGuiID id, ImVec2 ref_size, ImGuiDockNodeFlags flags) | ||||
| void ImGui::DockBuilderSetNodePos(ImGuiID node_id, ImVec2 pos) | ||||
| { | ||||
|     ImGuiContext* ctx = GImGui; | ||||
|     DockSpace(id, ImVec2(0,0), flags | ImGuiDockNodeFlags_KeepAliveOnly); | ||||
|     ImGuiDockNode* node = DockContextFindNodeByID(ctx, id); | ||||
|     node->SizeRef = node->Size = ref_size; | ||||
|     node->LastFrameAlive = -1; | ||||
|     ImGuiDockNode* node = DockContextFindNodeByID(ctx, node_id); | ||||
|     if (node == NULL) | ||||
|         return; | ||||
|     node->Pos = pos; | ||||
|     node->AutorityForPos = ImGuiDataAutority_DockNode; | ||||
| } | ||||
|  | ||||
| void ImGui::DockBuilderSetNodeSize(ImGuiID node_id, ImVec2 size) | ||||
| { | ||||
|     ImGuiContext* ctx = GImGui; | ||||
|     ImGuiDockNode* node = DockContextFindNodeByID(ctx, node_id); | ||||
|     if (node == NULL) | ||||
|         return; | ||||
|     node->Size = node->SizeRef = size; | ||||
|     node->AutorityForSize = ImGuiDataAutority_DockNode; | ||||
| } | ||||
|  | ||||
| // If you create a regular node, both ref_pos/ref_size will position the window. | ||||
| // If you create a dockspace node: ref_pos won't be used, ref_size is useful on the first frame to... | ||||
| ImGuiID ImGui::DockBuilderAddNode(ImGuiID id, ImGuiDockNodeFlags flags) | ||||
| { | ||||
|     ImGuiContext* ctx = GImGui; | ||||
|     ImGuiDockNode* node = NULL; | ||||
|     if (flags & ImGuiDockNodeFlags_Dockspace) | ||||
|     { | ||||
|         DockSpace(id, ImVec2(0, 0), flags | ImGuiDockNodeFlags_KeepAliveOnly); | ||||
|         node = DockContextFindNodeByID(ctx, id); | ||||
|         node->LastFrameAlive = -1; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if (id != 0) | ||||
|             node = DockContextFindNodeByID(ctx, id); | ||||
|         if (!node) | ||||
|             node = DockContextAddNode(ctx, id); | ||||
|         node->LastFrameAlive = ctx->FrameCount; | ||||
|     } | ||||
|     return node->ID; | ||||
| } | ||||
|  | ||||
| void ImGui::DockBuilderRemoveNode(ImGuiID node_id) | ||||
| @@ -12413,6 +12464,9 @@ void ImGui::DockBuilderRemoveNodeChildNodes(ImGuiID root_id) | ||||
|         return; | ||||
|     bool has_document_root = false; | ||||
|  | ||||
|     ImGuiDataAutority backup_root_node_autority_for_pos = root_node ? root_node->AutorityForPos : ImGuiDataAutority_Auto; | ||||
|     ImGuiDataAutority backup_root_node_autority_for_size = root_node ? root_node->AutorityForSize : ImGuiDataAutority_Auto; | ||||
|  | ||||
|     // Process active windows | ||||
|     ImVector<ImGuiDockNode*> nodes_to_remove; | ||||
|     for (int n = 0; n < dc->Nodes.Data.Size; n++) | ||||
| @@ -12434,7 +12488,10 @@ void ImGui::DockBuilderRemoveNodeChildNodes(ImGuiID root_id) | ||||
|     // DockNodeMoveWindows->DockNodeAddWindow will normally set those when reaching two windows (which is only adequate during interactive merge) | ||||
|     // Make sure we don't lose our current pos/size. (FIXME-DOCK: Consider tidying up that code in DockNodeAddWindow instead) | ||||
|     if (root_node) | ||||
|         root_node->InitFromFirstWindowPosSize = false; | ||||
|     { | ||||
|         root_node->AutorityForPos = backup_root_node_autority_for_pos; | ||||
|         root_node->AutorityForSize = backup_root_node_autority_for_size; | ||||
|     } | ||||
|  | ||||
|     // Apply to settings | ||||
|     for (int settings_n = 0; settings_n < ctx->SettingsWindows.Size; settings_n++) | ||||
|   | ||||
| @@ -818,6 +818,13 @@ enum ImGuiDockNodeFlagsPrivate_ | ||||
|     ImGuiDockNodeFlags_Dockspace  = 1 << 10 | ||||
| }; | ||||
|  | ||||
| enum ImGuiDataAutority | ||||
| { | ||||
|     ImGuiDataAutority_Auto, | ||||
|     ImGuiDataAutority_DockNode, | ||||
|     ImGuiDataAutority_Window | ||||
| }; | ||||
|  | ||||
| // sizeof() 116~160 | ||||
| struct ImGuiDockNode | ||||
| { | ||||
| @@ -843,8 +850,9 @@ struct ImGuiDockNode | ||||
|     ImGuiID                 LastFocusedNodeID;          // [Root node only] Which of our child docking node (any ancestor in the hierarchy) was last focused. | ||||
|     ImGuiID                 SelectedTabID;              // [Tab node only] Which of our tab is selected. | ||||
|     ImGuiID                 WantCloseTabID;             // [Tab node only] Set when closing a specific tab. | ||||
|     bool                    InitFromFirstWindowPosSize  :1; | ||||
|     bool                    InitFromFirstWindowViewport :1; | ||||
|     ImGuiDataAutority       AutorityForPos          :3; | ||||
|     ImGuiDataAutority       AutorityForSize         :3; | ||||
|     ImGuiDataAutority       AutorityForViewport     :3; | ||||
|     bool                    IsVisible               :1; // Set to false when the node is hidden (usually disabled as it has no active window) | ||||
|     bool                    IsFocused               :1; | ||||
|     bool                    IsCentralNode           :1; | ||||
| @@ -1577,10 +1585,12 @@ namespace ImGui | ||||
|     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 ImGuiID       DockBuilderAddNode(ImGuiID node_id, 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); | ||||
|     IMGUI_API void          DockBuilderRemoveNodeChildNodes(ImGuiID node_id);       // Remove all split/hierarchy. All remaining docked windows will be re-docked to the root. | ||||
|     IMGUI_API void          DockBuilderSetNodePos(ImGuiID node_id, ImVec2 pos); | ||||
|     IMGUI_API void          DockBuilderSetNodeSize(ImGuiID node_id, ImVec2 size); | ||||
|     IMGUI_API ImGuiID       DockBuilderSplitNode(ImGuiID node_id, ImGuiDir split_dir, float size_ratio_for_node_at_dir, ImGuiID* out_id_dir, ImGuiID* out_id_other); | ||||
|     IMGUI_API void          DockBuilderCopyDockspace(ImGuiID src_dockspace_id, ImGuiID dst_dockspace_id, ImVector<const char*>* in_window_remap_pairs); | ||||
|     IMGUI_API void          DockBuilderCopyNode(ImGuiID src_node_id, ImGuiID dst_node_id, ImVector<ImGuiID>* out_node_remap_pairs); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user