Docking: Added ImGuiDockNodeFlags_Dockspace instead of node internal IsDockspace toward allowing the DockBuilder API to create non-dockspace nodes.

This commit is contained in:
omar 2019-01-23 11:29:44 +01:00
parent bfacbac7c4
commit 9f96fcff3c
3 changed files with 33 additions and 29 deletions

View File

@ -10292,7 +10292,7 @@ void ImGui::DockContextNewFrameUpdateDocking(ImGuiContext* ctx)
// We can have NULL pointers when we delete nodes, but because ID are recycled this should amortize nicely (and our node count will never be very high) // We can have NULL pointers when we delete nodes, but because ID are recycled this should amortize nicely (and our node count will never be very high)
for (int n = 0; n < dc->Nodes.Data.Size; n++) for (int n = 0; n < dc->Nodes.Data.Size; n++)
if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p) if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
if (!node->IsDockSpace && node->IsRootNode()) if (node->IsRootNode() && !node->IsDockSpace())
DockNodeUpdate(node); DockNodeUpdate(node);
} }
@ -10440,7 +10440,8 @@ static void ImGui::DockContextBuildNodesFromSettings(ImGuiContext* ctx, ImGuiDoc
node->ParentNode->ChildNodes[1] = node; node->ParentNode->ChildNodes[1] = node;
node->SelectedTabID = node_settings->SelectedTabID; node->SelectedTabID = node_settings->SelectedTabID;
node->SplitAxis = node_settings->SplitAxis; node->SplitAxis = node_settings->SplitAxis;
node->IsDockSpace = node_settings->IsDockSpace != 0; if (node_settings->IsDockSpace)
node->Flags |= ImGuiDockNodeFlags_Dockspace;
node->IsCentralNode = node_settings->IsCentralNode != 0; node->IsCentralNode = node_settings->IsCentralNode != 0;
node->IsHiddenTabBar = node_settings->IsHiddenTabBar != 0; node->IsHiddenTabBar = node_settings->IsHiddenTabBar != 0;
@ -10703,7 +10704,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id)
WantCloseTabID = 0; WantCloseTabID = 0;
InitFromFirstWindowPosSize = InitFromFirstWindowViewport = false; InitFromFirstWindowPosSize = InitFromFirstWindowViewport = false;
IsVisible = true; IsVisible = true;
IsFocused = IsDockSpace = IsCentralNode = IsHiddenTabBar = HasCloseButton = HasCollapseButton = false; IsFocused = IsCentralNode = IsHiddenTabBar = HasCloseButton = HasCollapseButton = false;
WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarToggle = false; WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarToggle = false;
} }
@ -10750,7 +10751,7 @@ 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. // 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. // 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()) if (node->HostWindow == NULL && !node->IsDockSpace() && node->IsRootNode())
node->InitFromFirstWindowPosSize = node->InitFromFirstWindowViewport = true; node->InitFromFirstWindowPosSize = node->InitFromFirstWindowViewport = true;
// Add to tab bar if requested // Add to tab bar if requested
@ -10956,9 +10957,10 @@ static void ImGui::DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* nod
IM_ASSERT(node->ParentNode == NULL || node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node); IM_ASSERT(node->ParentNode == NULL || node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node);
// Inherit flags // Inherit most flags
ImGuiDockNodeFlags flags_to_inherit = ~0 & ~ImGuiDockNodeFlags_Dockspace;
if (node->ParentNode) if (node->ParentNode)
node->Flags = node->ParentNode->Flags; node->Flags = node->ParentNode->Flags & flags_to_inherit;
// Recurse into children // Recurse into children
// There is the possibility that one of our child becoming empty will delete itself and moving its sibling contents into 'node'. // There is the possibility that one of our child becoming empty will delete itself and moving its sibling contents into 'node'.
@ -11006,7 +11008,7 @@ static void ImGui::DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* nod
static void ImGui::DockNodeUpdateVisibleFlag(ImGuiDockNode* node) static void ImGui::DockNodeUpdateVisibleFlag(ImGuiDockNode* node)
{ {
// Update visibility flag // Update visibility flag
bool is_visible = (node->ParentNode == 0) ? node->IsDockSpace : node->IsCentralNode; bool is_visible = (node->ParentNode == 0) ? node->IsDockSpace() : node->IsCentralNode;
is_visible |= (node->Windows.Size > 0); is_visible |= (node->Windows.Size > 0);
is_visible |= (node->ChildNodes[0] && node->ChildNodes[0]->IsVisible); is_visible |= (node->ChildNodes[0] && node->ChildNodes[0]->IsVisible);
is_visible |= (node->ChildNodes[1] && node->ChildNodes[1]->IsVisible); is_visible |= (node->ChildNodes[1] && node->ChildNodes[1]->IsVisible);
@ -11061,7 +11063,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
} }
// Early out for hidden root dock nodes (when all DockId references are in inactive windows, or there is only 1 floating window holding on the DockId) // Early out for hidden root dock nodes (when all DockId references are in inactive windows, or there is only 1 floating window holding on the DockId)
if (node->Windows.Size <= 1 && node->IsRootNode() && node->IsLeafNode() && !node->IsDockSpace && !g.IO.ConfigDockingTabBarOnSingleWindows) if (node->Windows.Size <= 1 && node->IsRootNode() && node->IsLeafNode() && !node->IsDockSpace() && !g.IO.ConfigDockingTabBarOnSingleWindows)
{ {
if (node->Windows.Size == 1) if (node->Windows.Size == 1)
{ {
@ -11099,7 +11101,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
ImGuiWindow* host_window = NULL; ImGuiWindow* host_window = NULL;
bool beginned_into_host_window = false; bool beginned_into_host_window = false;
if (node->IsDockSpace) if (node->IsDockSpace())
{ {
// [Explicit root dockspace node] // [Explicit root dockspace node]
IM_ASSERT(node->HostWindow); IM_ASSERT(node->HostWindow);
@ -11202,7 +11204,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
if (central_node_hole_register_hit_test_hole) if (central_node_hole_register_hit_test_hole)
{ {
// Add a little padding to match the "resize from edges" behavior and allow grabbing the splitter easily. // Add a little padding to match the "resize from edges" behavior and allow grabbing the splitter easily.
IM_ASSERT(node->IsDockSpace); // We cannot pass this flag without the DockSpace() api. Testing this because we also setup the hole in host_window->ParentNode IM_ASSERT(node->IsDockSpace()); // We cannot pass this flag without the DockSpace() api. Testing this because we also setup the hole in host_window->ParentNode
ImRect central_hole(central_node->Pos, central_node->Pos + central_node->Size); ImRect central_hole(central_node->Pos, central_node->Pos + central_node->Size);
central_hole.Expand(ImVec2(-WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS, -WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS)); central_hole.Expand(ImVec2(-WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS, -WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS));
if (central_node_hole && !central_hole.IsInverted()) if (central_node_hole && !central_hole.IsInverted())
@ -11321,7 +11323,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
// Move ourselves to the Menu layer (so we can be accessed by tapping Alt) + undo SkipItems flag in order to draw over the title bar even if the window is collapsed // Move ourselves to the Menu layer (so we can be accessed by tapping Alt) + undo SkipItems flag in order to draw over the title bar even if the window is collapsed
bool backup_skip_item = host_window->SkipItems; bool backup_skip_item = host_window->SkipItems;
if (!node->IsDockSpace) if (!node->IsDockSpace())
{ {
host_window->SkipItems = false; host_window->SkipItems = false;
host_window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; host_window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
@ -11411,8 +11413,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
// Begin tab bar // Begin tab bar
const ImRect tab_bar_rect = DockNodeCalcTabBarRect(node); const ImRect tab_bar_rect = DockNodeCalcTabBarRect(node);
ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_NoTabListPopupButton;// | ImGuiTabBarFlags_NoTabListScrollingButtons); ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_NoTabListPopupButton;// | ImGuiTabBarFlags_NoTabListScrollingButtons);
tab_bar_flags |= ImGuiTabBarFlags_SaveSettings; tab_bar_flags |= ImGuiTabBarFlags_SaveSettings | ImGuiTabBarFlags_DockNode;
tab_bar_flags |= ImGuiTabBarFlags_DockNode | (node->IsDockSpace ? ImGuiTabBarFlags_DockNodeIsDockSpace : 0);
if (!host_window->Collapsed && is_focused) if (!host_window->Collapsed && is_focused)
tab_bar_flags |= ImGuiTabBarFlags_IsFocused; tab_bar_flags |= ImGuiTabBarFlags_IsFocused;
BeginTabBarEx(tab_bar, tab_bar_rect, tab_bar_flags, node); BeginTabBarEx(tab_bar, tab_bar_rect, tab_bar_flags, node);
@ -11512,7 +11513,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
PopID(); PopID();
// Restore SkipItems flag // Restore SkipItems flag
if (!node->IsDockSpace) if (!node->IsDockSpace())
{ {
host_window->DC.NavLayerCurrent = ImGuiNavLayer_Main; host_window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
host_window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main); host_window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
@ -11522,7 +11523,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
static bool DockNodeIsDropAllowedOne(ImGuiWindow* payload, ImGuiWindow* host_window) static bool DockNodeIsDropAllowedOne(ImGuiWindow* payload, ImGuiWindow* host_window)
{ {
if (host_window->DockNodeAsHost && host_window->DockNodeAsHost->IsDockSpace && payload->BeginOrderWithinContext < host_window->BeginOrderWithinContext) if (host_window->DockNodeAsHost && host_window->DockNodeAsHost->IsDockSpace() && payload->BeginOrderWithinContext < host_window->BeginOrderWithinContext)
return false; return false;
ImGuiWindowClass* host_class = host_window->DockNodeAsHost ? &host_window->DockNodeAsHost->WindowClass : &host_window->WindowClass; ImGuiWindowClass* host_class = host_window->DockNodeAsHost ? &host_window->DockNodeAsHost->WindowClass : &host_window->WindowClass;
@ -12134,7 +12135,7 @@ ImGuiDockNode* ImGui::DockNodeTreeFindNodeByPos(ImGuiDockNode* node, ImVec2 pos)
// There is an edge case when docking into a dockspace which only has inactive nodes (because none of the windows are active) // There is an edge case when docking into a dockspace which only has inactive nodes (because none of the windows are active)
// In this case we need to fallback into any leaf mode, possibly the central node. // In this case we need to fallback into any leaf mode, possibly the central node.
if (node->IsDockSpace && node->IsRootNode()) if (node->IsDockSpace() && node->IsRootNode())
{ {
if (node->CentralNode && node->IsLeafNode()) // FIXME-20181220: We should not have to test for IsLeafNode() here but we have another bug to fix first. if (node->CentralNode && node->IsLeafNode()) // FIXME-20181220: We should not have to test for IsLeafNode() here but we have another bug to fix first.
return node->CentralNode; return node->CentralNode;
@ -12202,11 +12203,11 @@ void ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags doc
// It is possible that the node has already been claimed by a docked window which appeared before the DockSpace() node, so we overwrite IsDockSpace again. // It is possible that the node has already been claimed by a docked window which appeared before the DockSpace() node, so we overwrite IsDockSpace again.
if (node->LastFrameActive == g.FrameCount && !(dockspace_flags & ImGuiDockNodeFlags_KeepAliveOnly)) if (node->LastFrameActive == g.FrameCount && !(dockspace_flags & ImGuiDockNodeFlags_KeepAliveOnly))
{ {
IM_ASSERT(node->IsDockSpace == false && "Cannot call DockSpace() twice a frame with the same ID"); IM_ASSERT(node->IsDockSpace() == false && "Cannot call DockSpace() twice a frame with the same ID");
node->IsDockSpace = true; node->Flags |= ImGuiDockNodeFlags_Dockspace;
return; return;
} }
node->IsDockSpace = true; node->Flags |= ImGuiDockNodeFlags_Dockspace;
// Keep alive mode, this is allow windows docked into this node so stay docked even if they are not visible // Keep alive mode, this is allow windows docked into this node so stay docked even if they are not visible
if (dockspace_flags & ImGuiDockNodeFlags_KeepAliveOnly) if (dockspace_flags & ImGuiDockNodeFlags_KeepAliveOnly)
@ -12480,7 +12481,6 @@ static ImGuiDockNode* DockBuilderCopyNodeRec(ImGuiDockNode* src_node, ImGuiID ds
dst_node->Size = src_node->Size; dst_node->Size = src_node->Size;
dst_node->SizeRef = src_node->SizeRef; dst_node->SizeRef = src_node->SizeRef;
dst_node->SplitAxis = src_node->SplitAxis; dst_node->SplitAxis = src_node->SplitAxis;
dst_node->IsDockSpace = src_node->IsDockSpace;
dst_node->IsCentralNode = src_node->IsCentralNode; dst_node->IsCentralNode = src_node->IsCentralNode;
out_node_remap_pairs->push_back(src_node->ID); out_node_remap_pairs->push_back(src_node->ID);
@ -12955,7 +12955,7 @@ static void DockSettingsHandler_DockNodeToSettings(ImGuiDockContext* dc, ImGuiDo
node_settings.SelectedTabID = node->SelectedTabID; node_settings.SelectedTabID = node->SelectedTabID;
node_settings.SplitAxis = node->IsSplitNode() ? (char)node->SplitAxis : ImGuiAxis_None; node_settings.SplitAxis = node->IsSplitNode() ? (char)node->SplitAxis : ImGuiAxis_None;
node_settings.Depth = (char)depth; node_settings.Depth = (char)depth;
node_settings.IsDockSpace = (char)node->IsDockSpace; node_settings.IsDockSpace = (char)node->IsDockSpace();
node_settings.IsCentralNode = (char)node->IsCentralNode; node_settings.IsCentralNode = (char)node->IsCentralNode;
node_settings.IsHiddenTabBar = (char)node->IsHiddenTabBar; node_settings.IsHiddenTabBar = (char)node->IsHiddenTabBar;
node_settings.Pos = ImVec2ih((short)node->Pos.x, (short)node->Pos.y); node_settings.Pos = ImVec2ih((short)node->Pos.x, (short)node->Pos.y);
@ -13871,7 +13871,7 @@ void ImGui::ShowDockingDebug()
ImGui::BulletText("SelectedTabID: 0x%08X", node->SelectedTabID); ImGui::BulletText("SelectedTabID: 0x%08X", node->SelectedTabID);
ImGui::BulletText("LastFocusedNodeID: 0x%08X", node->LastFocusedNodeID); ImGui::BulletText("LastFocusedNodeID: 0x%08X", node->LastFocusedNodeID);
ImGui::BulletText("Flags 0x%02X%s%s%s%s", ImGui::BulletText("Flags 0x%02X%s%s%s%s",
node->Flags, node->IsDockSpace ? ", IsDockSpace" : "", node->IsCentralNode ? ", IsCentralNode" : "", node->Flags, node->IsDockSpace() ? ", IsDockSpace" : "", node->IsCentralNode ? ", IsCentralNode" : "",
(GImGui->FrameCount - node->LastFrameAlive < 2) ? ", IsAlive" : "", (GImGui->FrameCount - node->LastFrameActive < 2) ? ", IsActive" : ""); (GImGui->FrameCount - node->LastFrameAlive < 2) ? ", IsAlive" : "", (GImGui->FrameCount - node->LastFrameActive < 2) ? ", IsActive" : "");
if (node->ChildNodes[0]) if (node->ChildNodes[0])
NodeDockNode(node->ChildNodes[0], "Child[0]"); NodeDockNode(node->ChildNodes[0], "Child[0]");

View File

@ -813,6 +813,11 @@ struct ImGuiTabBarSortItem
float Width; float Width;
}; };
enum ImGuiDockNodeFlagsPrivate_
{
ImGuiDockNodeFlags_Dockspace = 1 << 10
};
// sizeof() 116~160 // sizeof() 116~160
struct ImGuiDockNode struct ImGuiDockNode
{ {
@ -842,7 +847,6 @@ struct ImGuiDockNode
bool InitFromFirstWindowViewport :1; bool InitFromFirstWindowViewport :1;
bool IsVisible :1; // Set to false when the node is hidden (usually disabled as it has no active window) bool IsVisible :1; // Set to false when the node is hidden (usually disabled as it has no active window)
bool IsFocused :1; bool IsFocused :1;
bool IsDockSpace :1; // Root node was created by a DockSpace() call.
bool IsCentralNode :1; bool IsCentralNode :1;
bool IsHiddenTabBar :1; bool IsHiddenTabBar :1;
bool HasCloseButton :1; bool HasCloseButton :1;
@ -855,6 +859,7 @@ struct ImGuiDockNode
ImGuiDockNode(ImGuiID id); ImGuiDockNode(ImGuiID id);
~ImGuiDockNode(); ~ImGuiDockNode();
bool IsRootNode() const { return ParentNode == NULL; } bool IsRootNode() const { return ParentNode == NULL; }
bool IsDockSpace() const { return (Flags & ImGuiDockNodeFlags_Dockspace) != 0; }
bool IsSplitNode() const { return ChildNodes[0] != NULL; } bool IsSplitNode() const { return ChildNodes[0] != NULL; }
bool IsLeafNode() const { return ChildNodes[0] == NULL; } bool IsLeafNode() const { return ChildNodes[0] == NULL; }
bool IsEmpty() const { return ChildNodes[0] == NULL && Windows.Size == 0; } bool IsEmpty() const { return ChildNodes[0] == NULL && Windows.Size == 0; }
@ -1384,9 +1389,8 @@ struct ImGuiItemHoveredDataBackup
enum ImGuiTabBarFlagsPrivate_ enum ImGuiTabBarFlagsPrivate_
{ {
ImGuiTabBarFlags_DockNode = 1 << 20, // Part of a dock node ImGuiTabBarFlags_DockNode = 1 << 20, // Part of a dock node
ImGuiTabBarFlags_DockNodeIsDockSpace = 1 << 21, // Part of an explicit dockspace node node ImGuiTabBarFlags_IsFocused = 1 << 21,
ImGuiTabBarFlags_IsFocused = 1 << 22, ImGuiTabBarFlags_SaveSettings = 1 << 22 // FIXME: Settings are handled by the docking system, this only request the tab bar to mark settings dirty when reordering tabs
ImGuiTabBarFlags_SaveSettings = 1 << 23 // FIXME: Settings are handled by the docking system, this only request the tab bar to mark settings dirty when reordering tabs
}; };
enum ImGuiTabItemFlagsPrivate_ enum ImGuiTabItemFlagsPrivate_

View File

@ -5937,8 +5937,8 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
} }
else else
{ {
const float separator_min_x = tab_bar->BarRect.Min.x - ((flags & ImGuiTabBarFlags_DockNodeIsDockSpace) ? 0.0f : window->WindowPadding.x); const float separator_min_x = tab_bar->BarRect.Min.x - window->WindowPadding.x;
const float separator_max_x = tab_bar->BarRect.Max.x + ((flags & ImGuiTabBarFlags_DockNodeIsDockSpace) ? 0.0f : window->WindowPadding.x); const float separator_max_x = tab_bar->BarRect.Max.x + window->WindowPadding.x;
window->DrawList->AddLine(ImVec2(separator_min_x, y), ImVec2(separator_max_x, y), col, 1.0f); window->DrawList->AddLine(ImVec2(separator_min_x, y), ImVec2(separator_max_x, y), col, 1.0f);
} }
return true; return true;
@ -6497,7 +6497,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// FIXME-DOCK: In theory we shouldn't test for the ConfigDockingNodifySingleWindows flag here. // FIXME-DOCK: In theory we shouldn't test for the ConfigDockingNodifySingleWindows flag here.
// When our single window node and OnlyNodeWithWindows are working properly we may remove this check here. // When our single window node and OnlyNodeWithWindows are working properly we may remove this check here.
ImGuiDockNode* node = docked_window ? docked_window->DockNode : NULL; ImGuiDockNode* node = docked_window ? docked_window->DockNode : NULL;
const bool single_floating_window_node = node && node->IsRootNode() && !node->IsDockSpace && node->Windows.Size == 1 && g.IO.ConfigDockingTabBarOnSingleWindows; const bool single_floating_window_node = node && node->IsRootNode() && !node->IsDockSpace() && node->Windows.Size == 1 && g.IO.ConfigDockingTabBarOnSingleWindows;
if (held && single_floating_window_node && IsMouseDragging(0, 0.0f)) if (held && single_floating_window_node && IsMouseDragging(0, 0.0f))
{ {
// Move // Move