Docking: Renamed ImGuiDockNodeFlags_PassthruDockspace to ImGuiDockNodeFlags_PassthruCentralNode. + Comments, shallow tweaks. (#2109)

This commit is contained in:
omar 2019-03-27 15:34:02 +01:00
parent 87883abd86
commit 04a9ce3a18
5 changed files with 39 additions and 32 deletions

View File

@ -133,7 +133,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- dock: A~ Unreal style document system (requires low-level controls of dockspace serialization fork/copy/delete). this is mostly working but the DockBuilderXXX api are not exposed/finished.
- dock: B: when docking outer, perform size locking on neighbors nodes the same way we do it with splitters, so other nodes are not resized.
- dock: B~ central node resizing behavior incorrect.
- dock: B~ central node ID retrieval API?
- dock: B: changing title font/style per-window is not supported as dock nodes are created in NewFrame.
- dock: B- dock node inside its own viewports creates 1 temporary viewport per window on startup before ditching them (doesn't affect the user nor request platform windows to be created, but unnecessary)
- dock: B- resize sibling locking behavior may be less desirable if we merged same-axis sibling in a same node level?

View File

@ -2605,7 +2605,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
DockNode = DockNodeAsHost = NULL;
DockId = 0;
DockTabItemStatusFlags = 0;
DockTabItemStatusFlags = ImGuiItemStatusFlags_None;
DockOrder = -1;
DockIsActive = DockTabIsVisible = DockTabWantClose = false;
}
@ -11343,7 +11343,7 @@ void ImGui::DockContextProcessUndockNode(ImGuiContext* ctx, ImGuiDockNode* node)
ImGuiDockNode::ImGuiDockNode(ImGuiID id)
{
ID = id;
Flags = 0;
Flags = ImGuiDockNodeFlags_None;
ParentNode = ChildNodes[0] = ChildNodes[1] = NULL;
TabBar = NULL;
SplitAxis = ImGuiAxis_None;
@ -11613,7 +11613,7 @@ static void ImGui::DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* nod
IM_ASSERT(node->ParentNode == NULL || node->ParentNode->ChildNodes[0] == node || node->ParentNode->ChildNodes[1] == node);
// Inherit most flags
ImGuiDockNodeFlags flags_to_inherit = ~0 & ~ImGuiDockNodeFlags_Dockspace;
ImGuiDockNodeFlags flags_to_inherit = ~ImGuiDockNodeFlags_Dockspace;
if (node->ParentNode)
node->Flags = node->ParentNode->Flags & flags_to_inherit;
@ -11854,9 +11854,9 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
if (g.NavWindow && g.NavWindow->RootWindowDockStop->DockNode && g.NavWindow->RootWindowDockStop->ParentWindow == host_window)
node->LastFocusedNodeID = g.NavWindow->RootWindowDockStop->DockNode->ID;
// We need to draw a background if requested by ImGuiDockNodeFlags_PassthruDockspace, but we will only know the correct pos/size after
// We need to draw a background at the root level if requested by ImGuiDockNodeFlags_PassthruCentralNode, but we will only know the correct pos/size after
// processing the resizing splitters. So we are using the DrawList channel splitting facility to submit drawing primitives out of order!
const bool render_dockspace_bg = node->IsRootNode() && host_window && (node->Flags & ImGuiDockNodeFlags_PassthruDockspace) != 0;
const bool render_dockspace_bg = node->IsRootNode() && host_window && (node->Flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0;
if (render_dockspace_bg)
{
host_window->DrawList->ChannelsSplit(2);
@ -11865,7 +11865,7 @@ 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
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();
const bool central_node_hole = node->IsRootNode() && host_window && (node->Flags & ImGuiDockNodeFlags_PassthruCentralNode) != 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())
@ -11892,10 +11892,10 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
}
// Draw empty node background (currently can only be the Central Node)
if (host_window && node->IsEmpty() && node->IsVisible && !(node->Flags & ImGuiDockNodeFlags_PassthruDockspace))
if (host_window && node->IsEmpty() && node->IsVisible && !(node->Flags & ImGuiDockNodeFlags_PassthruCentralNode))
host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, GetColorU32(ImGuiCol_DockingEmptyBg));
// Draw whole dockspace background if ImGuiDockNodeFlags_PassthruDockspace if set.
// Draw whole dockspace background if ImGuiDockNodeFlags_PassthruCentralNode if set.
if (render_dockspace_bg && node->IsVisible)
{
host_window->DrawList->ChannelsSetCurrent(0);
@ -12566,6 +12566,7 @@ void ImGui::DockNodeTreeSplit(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImG
DockNodeMoveWindows(parent_node->ChildNodes[split_inheritor_child_idx], parent_node);
DockNodeTreeUpdatePosSize(parent_node, parent_node->Pos, parent_node->Size);
// Flags transfer
child_inheritor->IsCentralNode = parent_node->IsCentralNode;
child_inheritor->IsHiddenTabBar = parent_node->IsHiddenTabBar;
parent_node->IsCentralNode = false;
@ -12599,9 +12600,11 @@ void ImGui::DockNodeTreeMerge(ImGuiContext* ctx, ImGuiDockNode* parent_node, ImG
DockNodeApplyPosSizeToWindows(parent_node);
parent_node->AutorityForPos = parent_node->AutorityForSize = parent_node->AutorityForViewport = ImGuiDataAutority_Auto;
parent_node->VisibleWindow = merge_lead_child->VisibleWindow;
parent_node->SizeRef = backup_last_explicit_size;
// Flags transfer
parent_node->IsCentralNode = (child_0 && child_0->IsCentralNode) || (child_1 && child_1->IsCentralNode);
parent_node->IsHiddenTabBar = merge_lead_child->IsHiddenTabBar;
parent_node->SizeRef = backup_last_explicit_size;
if (child_0)
{
@ -12961,7 +12964,7 @@ void ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags fla
End();
}
// Tips: Use with ImGuiDockNodeFlags_PassthruDockspace!
// Tips: Use with ImGuiDockNodeFlags_PassthruCentralNode!
// The limitation with this call is that your window won't have a menu bar.
// Even though we could pass window flags, it would also require the user to be able to call BeginMenuBar() somehow meaning we can't Begin/End in a single function.
// So if you want a menu bar you need to repeat this code manually ourselves. As with advanced other Docking API, we may change this function signature.
@ -12977,7 +12980,7 @@ ImGuiID ImGui::DockSpaceOverViewport(ImGuiViewport* viewport, ImGuiDockNodeFlags
ImGuiWindowFlags host_window_flags = 0;
host_window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking;
host_window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
if (dockspace_flags & ImGuiDockNodeFlags_PassthruDockspace)
if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
host_window_flags |= ImGuiWindowFlags_NoBackground;
char label[32];
@ -14186,6 +14189,7 @@ void ImGui::ShowDockingDebug()
{
static void NodeDockNode(ImGuiDockNode* node, const char* label)
{
ImGuiContext& g = *GImGui;
ImGui::SetNextTreeNodeOpen(true, ImGuiCond_Once);
bool open;
if (node->Windows.Size > 0)
@ -14203,7 +14207,7 @@ void ImGui::ShowDockingDebug()
ImGui::BulletText("LastFocusedNodeID: 0x%08X", node->LastFocusedNodeID);
ImGui::BulletText("Flags 0x%02X%s%s%s%s",
node->Flags, node->IsDockSpace() ? ", IsDockSpace" : "", node->IsCentralNode ? ", IsCentralNode" : "",
(GImGui->FrameCount - node->LastFrameAlive < 2) ? ", IsAlive" : "", (GImGui->FrameCount - node->LastFrameActive < 2) ? ", IsActive" : "");
(g.FrameCount - node->LastFrameAlive < 2) ? ", IsAlive" : "", (g.FrameCount - node->LastFrameActive < 2) ? ", IsActive" : "");
if (node->ChildNodes[0])
NodeDockNode(node->ChildNodes[0], "Child[0]");
if (node->ChildNodes[1])

16
imgui.h
View File

@ -591,7 +591,8 @@ namespace ImGui
// Docking
// [BETA API] Enable with io.ConfigFlags |= ImGuiConfigFlags_DockingEnable.
// Note: you DO NOT need to call DockSpace() to use most Docking facilities!
// To dock windows: hold SHIFT anywhere while moving windows (if io.ConfigDockingWithShift == true) or drag windows from their title bar (if io.ConfigDockingWithShift = false)
// To dock windows: if io.ConfigDockingWithShift == false: drag window from their title bar.
// To dock windows: if io.ConfigDockingWithShift == true: hold SHIFT anywhere while moving windows.
// Use DockSpace() to create an explicit dock node _within_ an existing window. See Docking demo for details.
IMGUI_API void DockSpace(ImGuiID id, const ImVec2& size = ImVec2(0, 0), ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL);
IMGUI_API ImGuiID DockSpaceOverViewport(ImGuiViewport* viewport = NULL, ImGuiDockNodeFlags flags = 0, const ImGuiWindowClass* window_class = NULL);
@ -882,13 +883,12 @@ enum ImGuiDockNodeFlags_
{
ImGuiDockNodeFlags_None = 0,
ImGuiDockNodeFlags_KeepAliveOnly = 1 << 0, // Don't display the dockspace node but keep it alive. Windows docked into this dockspace node won't be undocked.
ImGuiDockNodeFlags_NoSplit = 1 << 1, // Disable splitting the node into smaller nodes. Useful e.g. when embedding dockspaces into a main root one (the root one may have splitting disabled to reduce confusion). Note: when turned off, existing splits will be preserved.
//ImGuiDockNodeFlags_NoCentralNode = 1 << 2, // Disable Central Node (the node which can stay empty)
ImGuiDockNodeFlags_NoDockingInCentralNode = 1 << 3, // Disable docking inside the Central Node, which will be always kept empty. Note: when turned off, existing docked nodes will be preserved.
//ImGuiDockNodeFlags_NoLayoutChanges = 1 << 4, // Disable adding/removing nodes interactively. Useful with programatically setup dockspaces.
ImGuiDockNodeFlags_NoResize = 1 << 5, // Disable resizing child nodes using the splitter/separators. Useful with programatically setup dockspaces.
ImGuiDockNodeFlags_PassthruDockspace = 1 << 6, // Enable passthru dockspace: 1) DockSpace() will render a ImGuiCol_WindowBg background covering everything excepted the Central Node when empty. Meaning the host window should probably use SetNextWindowBgAlpha(0.0f) prior to Begin() when using this. 2) When Central Node is empty: let inputs pass-through + won't display a DockingEmptyBg background.
ImGuiDockNodeFlags_AutoHideTabBar = 1 << 7 // Tab bar will automatically hide when there is a single window in the dock node.
//ImGuiDockNodeFlags_NoCentralNode = 1 << 1, // Disable Central Node (the node which can stay empty)
ImGuiDockNodeFlags_NoDockingInCentralNode = 1 << 2, // Disable docking inside the Central Node, which will be always kept empty. Note: when turned off, existing docked nodes will be preserved.
ImGuiDockNodeFlags_NoSplit = 1 << 3, // Disable splitting the node into smaller nodes. Useful e.g. when embedding dockspaces into a main root one (the root one may have splitting disabled to reduce confusion). Note: when turned off, existing splits will be preserved.
ImGuiDockNodeFlags_NoResize = 1 << 4, // Disable resizing child nodes using the splitter/separators. Useful with programatically setup dockspaces.
ImGuiDockNodeFlags_PassthruCentralNode = 1 << 5, // Enable passthru dockspace: 1) DockSpace() will render a ImGuiCol_WindowBg background covering everything excepted the Central Node when empty. Meaning the host window should probably use SetNextWindowBgAlpha(0.0f) prior to Begin() when using this. 2) When Central Node is empty: let inputs pass-through + won't display a DockingEmptyBg background. See demo for details.
ImGuiDockNodeFlags_AutoHideTabBar = 1 << 6 // Tab bar will automatically hide when there is a single window in the dock node.
};
// Flags for ImGui::IsWindowFocused()

View File

@ -4259,8 +4259,8 @@ void ShowExampleAppDockSpace(bool* p_open)
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
}
// When using ImGuiDockNodeFlags_PassthruDockspace, DockSpace() will render our background and handle the pass-thru hole, so we ask Begin() to not render a background.
if (dockspace_flags & ImGuiDockNodeFlags_PassthruDockspace)
// When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background and handle the pass-thru hole, so we ask Begin() to not render a background.
if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
window_flags |= ImGuiWindowFlags_NoBackground;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
@ -4291,9 +4291,9 @@ void ShowExampleAppDockSpace(bool* p_open)
//ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen_persistant);
if (ImGui::MenuItem("Flag: NoSplit", "", (dockspace_flags & ImGuiDockNodeFlags_NoSplit) != 0)) dockspace_flags ^= ImGuiDockNodeFlags_NoSplit;
if (ImGui::MenuItem("Flag: NoDockingInCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingInCentralNode) != 0)) dockspace_flags ^= ImGuiDockNodeFlags_NoDockingInCentralNode;
if (ImGui::MenuItem("Flag: NoResize", "", (dockspace_flags & ImGuiDockNodeFlags_NoResize) != 0)) dockspace_flags ^= ImGuiDockNodeFlags_NoResize;
if (ImGui::MenuItem("Flag: PassthruDockspace", "", (dockspace_flags & ImGuiDockNodeFlags_PassthruDockspace) != 0)) dockspace_flags ^= ImGuiDockNodeFlags_PassthruDockspace;
if (ImGui::MenuItem("Flag: NoDockingInCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingInCentralNode) != 0)) dockspace_flags ^= ImGuiDockNodeFlags_NoDockingInCentralNode;
if (ImGui::MenuItem("Flag: PassthruCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0)) dockspace_flags ^= ImGuiDockNodeFlags_PassthruCentralNode;
if (ImGui::MenuItem("Flag: AutoHideTabBar", "", (dockspace_flags & ImGuiDockNodeFlags_AutoHideTabBar) != 0)) dockspace_flags ^= ImGuiDockNodeFlags_AutoHideTabBar;
ImGui::Separator();
if (ImGui::MenuItem("Close DockSpace", NULL, false, p_open != NULL))
@ -4301,7 +4301,11 @@ void ShowExampleAppDockSpace(bool* p_open)
ImGui::EndMenu();
}
HelpMarker(
"You can _always_ dock _any_ window into another by holding the SHIFT key while moving a window. Try it now!" "\n"
"When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n\n"
" > if io.ConfigDockingWithShift==false (default):" "\n"
" drag windows from title bar to dock" "\n"
" > if io.ConfigDockingWithShift==true:" "\n"
" drag windows from anywhere and hold Shift to dock" "\n\n"
"This demo app has nothing to do with it!" "\n\n"
"This demo app only demonstrate the use of ImGui::DockSpace() which allows you to manually create a docking node _within_ another window. This is useful so you can decorate your main application window (e.g. with a menu bar)." "\n\n"
"ImGui::DockSpace() comes with one hard constraint: it needs to be submitted _before_ any window which may be docked into it. Therefore, if you use a dock spot as the central point of your application, you'll probably want it to be part of the very first window you are submitting to imgui every frame." "\n\n"

View File

@ -903,12 +903,12 @@ struct ImGuiDockNode
ImGuiDockNode(ImGuiID id);
~ImGuiDockNode();
bool IsRootNode() const { return ParentNode == NULL; }
bool IsDockSpace() const { return (Flags & ImGuiDockNodeFlags_Dockspace) != 0; }
bool IsSplitNode() const { return ChildNodes[0] != NULL; }
bool IsLeafNode() const { return ChildNodes[0] == NULL; }
bool IsEmpty() const { return ChildNodes[0] == NULL && Windows.Size == 0; }
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
bool IsRootNode() const { return ParentNode == NULL; }
bool IsDockSpace() const { return (Flags & ImGuiDockNodeFlags_Dockspace) != 0; }
bool IsSplitNode() const { return ChildNodes[0] != NULL; }
bool IsLeafNode() const { return ChildNodes[0] == NULL; }
bool IsEmpty() const { return ChildNodes[0] == NULL && Windows.Size == 0; }
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
};
//-----------------------------------------------------------------------------