mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-03 22:51:06 +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