Docking: Added ImGuiDockNodeFlags_PassthruDockspace mode (subdivided in three flags: ImGuiDockNodeFlags_NoDockingInCentralNode, ImGuiDockNodeFlags_PassthruInEmptyNodes, ImGuiDockNodeFlags_RenderWindowBg). Added internal facility for register a rectangular hit-test hole in window. Updated DockSpace demo accordingly. (#2109)

This commit is contained in:
omar 2018-10-03 22:32:23 +02:00
parent 2dd8338e7d
commit 4e30698706
5 changed files with 166 additions and 85 deletions

View File

@ -33,25 +33,27 @@ HOW TO UPDATE?
DOCKING BRANCH (In Progress) DOCKING BRANCH (In Progress)
----------------------------------------------------------------------- -----------------------------------------------------------------------
- Added ImGuiConfigFlags_DockingEnable flag to enable Docking. [BETA] - Added Docking system: [BETA] (#2109, #351)
- Added ImGuiConfigFlags_DockingEnable flag to enable Docking.
Set with `io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;`. Set with `io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;`.
- Added BeginTabBar(), EndTabBar(), BeginTabItem(), EndTabItem(), SetTabItemClosed() API. (#261, #351) - Added DockSpace() API.
- Added ImGuiTabBarFlags flags for BeginTabBar(). - Added ImGuiDockNodeFlags flags for DockSpace().
- Added ImGuiTabItemFlags flags for BeginTabItem(). - Added SetNextWindowDock(), SetNextWindowDockFamily() API.
- Added DockSpace() API. (#351) - Added GetWindowDockId(), IsWindowDocked() API.
- Added ImGuiDockNodeFlags flags for DockSpace(). - Added ImGuiWindowFlags_NoDocking window flag to disable the possibility for a window to be docked.
- Added SetNextWindowDock(), SetNextWindowDockFamily() API. (#351) Popup, Menu and Child windows always have the ImGuiWindowFlags_NoDocking flag set.
- Added GetWindowDockId(), IsWindowDocked() API. (#351) - Added io.ConfigDockingWithShift option to configure docking mode.
- Added ImGuiWindowFlags_NoDocking window flag to disable the possibility for a window to be docked. - Style: Added ImGuiCol_DockingPreview, ImGuiCol_DockingEmptyBg colors.
Popup, Menu and Child windows always have the ImGuiWindowFlags_NoDocking flag set. (#351) - Demo: Added "DockSpace" example app showcasing use of explicit dockspace nodes.
- Added ImGuiWindowFlags_UnsavedDocument window flag to append '*' to title without altering the ID, - Added Tab Bar/Tabs widgets: (#261, #351)
as a convenience to avoid using the ### operator. - Added BeginTabBar(), EndTabBar(), BeginTabItem(), EndTabItem(), SetTabItemClosed() API.
- Added io.ConfigDockingWithShift option to configure docking mode. - Added ImGuiTabBarFlags flags for BeginTabBar().
- Style: Added ImGuiCol_DockingPreview, ImGuiCol_DockingEmptyBg colors. (#351) - Added ImGuiTabItemFlags flags for BeginTabItem().
- Style: Added ImGuiCol_Tab, ImGuiCol_TabHovered, ImGuiCol_TabActive, ImGuiCol_TabUnfocused, ImGuiCol_TabUnfocusedActive colors. (#261, #351) - Style: Added ImGuiCol_Tab, ImGuiCol_TabHovered, ImGuiCol_TabActive, ImGuiCol_TabUnfocused, ImGuiCol_TabUnfocusedActive colors.
- Demo: Added Layout->Tabs demo code. (#261, #351) - Demo: Added Layout->Tabs demo code.
- Demo: Added "Documents" example app showcasing possible use for tabs. (#261, #351) - Demo: Added "Documents" example app showcasing possible use for tabs.
- Demo: Added "DockSpace" example app showcasing use of explicit dockspace nodes. (#351) - Added ImGuiWindowFlags_UnsavedDocument window flag to append '*' to title without altering
the ID, as a convenience to avoid using the ### operator.
----------------------------------------------------------------------- -----------------------------------------------------------------------

127
imgui.cpp
View File

@ -918,6 +918,7 @@ static void SetCurrentWindow(ImGuiWindow* window);
static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond); static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond);
static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond); static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond);
static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond); static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond);
static void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size);
static void FindHoveredWindow(); static void FindHoveredWindow();
static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags); static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);
static void CheckStacksSize(ImGuiWindow* window, bool write); static void CheckStacksSize(ImGuiWindow* window, bool write);
@ -4003,6 +4004,15 @@ static void FindHoveredWindow()
if (!bb.Contains(g.IO.MousePos)) if (!bb.Contains(g.IO.MousePos))
continue; continue;
if (window->HitTestHoleSize.x != 0)
{
// FIXME: Consider generalizing hit-testing override (with more generic data, callback, etc.) (#1512)
ImRect hole_bb((float)(window->HitTestHoleOffset.x), (float)(window->HitTestHoleOffset.y),
(float)(window->HitTestHoleOffset.x + window->HitTestHoleSize.x), (float)(window->HitTestHoleOffset.y + window->HitTestHoleSize.y));
if (hole_bb.Contains(g.IO.MousePos - window->Pos))
continue;
}
if (hovered_window == NULL) if (hovered_window == NULL)
hovered_window = window; hovered_window = window;
if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow)) if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow))
@ -5501,6 +5511,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
} }
} }
// Clear hit test shape every frame
window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0;
// Save clipped aabb so we can access it in constant-time in FindHoveredWindow() // Save clipped aabb so we can access it in constant-time in FindHoveredWindow()
window->OuterRectClipped = window->Rect(); window->OuterRectClipped = window->Rect();
if (window->DockIsActive) if (window->DockIsActive)
@ -6271,6 +6284,13 @@ static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond co
window->Collapsed = collapsed; window->Collapsed = collapsed;
} }
static void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size)
{
IM_ASSERT(window->HitTestHoleSize.x == 0); // We don't support multiple holes/hit test filters
window->HitTestHoleSize = ImVec2ih((short)size.x, (short)size.y);
window->HitTestHoleOffset = ImVec2ih((short)(pos.x - window->Pos.x), (short)(pos.y - window->Pos.y));
}
void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond) void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond)
{ {
SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond); SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond);
@ -10430,20 +10450,35 @@ static void ImGui::DockNodeHideHostWindow(ImGuiDockNode* node)
} }
} }
static void DockNodeUpdateFindOnlyNodeWithWindowsRec(ImGuiDockNode* node, int* p_count, ImGuiDockNode** p_first_node_with_windows) struct ImGuiDockNodeUpdateScanResults
{
ImGuiDockNode* CentralNode;
ImGuiDockNode* FirstNodeWithWindows;
int CountNodesWithWindows;
ImGuiDockFamily DockFamilyForMerges;
ImGuiDockNodeUpdateScanResults() { CentralNode = FirstNodeWithWindows = NULL; CountNodesWithWindows = 0; }
};
static void DockNodeUpdateScanRec(ImGuiDockNode* node, ImGuiDockNodeUpdateScanResults* results)
{ {
if (node->Windows.Size > 0) if (node->Windows.Size > 0)
{ {
if (*p_first_node_with_windows == NULL) if (results->FirstNodeWithWindows == NULL)
*p_first_node_with_windows = node; results->FirstNodeWithWindows = node;
(*p_count)++; results->CountNodesWithWindows++;
} }
if (*p_count > 1) if (node->IsCentralNode)
{
IM_ASSERT(results->CentralNode == NULL); // Should be only one
results->CentralNode = node;
}
if (results->CountNodesWithWindows > 1 && results->CentralNode != NULL)
return; return;
if (node->ChildNodes[0]) if (node->ChildNodes[0])
DockNodeUpdateFindOnlyNodeWithWindowsRec(node->ChildNodes[0], p_count, p_first_node_with_windows); DockNodeUpdateScanRec(node->ChildNodes[0], results);
if (node->ChildNodes[1]) if (node->ChildNodes[1])
DockNodeUpdateFindOnlyNodeWithWindowsRec(node->ChildNodes[1], p_count, p_first_node_with_windows); DockNodeUpdateScanRec(node->ChildNodes[1], results);
} }
static void ImGui::DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* node) static void ImGui::DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* node)
@ -10519,23 +10554,23 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
IM_ASSERT(node->LastFrameActive != g.FrameCount); IM_ASSERT(node->LastFrameActive != g.FrameCount);
node->LastFrameAlive = g.FrameCount; node->LastFrameAlive = g.FrameCount;
ImGuiDockNode* central_node = NULL;
if (node->IsRootNode()) if (node->IsRootNode())
{ {
DockNodeUpdateVisibleFlagAndInactiveChilds(node); DockNodeUpdateVisibleFlagAndInactiveChilds(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!) // 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!)
if (!node->IsDockSpace) ImGuiDockNodeUpdateScanResults results;
{ DockNodeUpdateScanRec(node, &results);
int count = 0; node->OnlyNodeWithWindows = (results.CountNodesWithWindows == 1 ? results.FirstNodeWithWindows : NULL);
ImGuiDockNode* first_node_with_windows = NULL; if (node->LastFocusedNodeID == 0 && results.FirstNodeWithWindows != NULL)
DockNodeUpdateFindOnlyNodeWithWindowsRec(node, &count, &first_node_with_windows); node->LastFocusedNodeID = results.FirstNodeWithWindows->ID;
node->OnlyNodeWithWindows = (count == 1 ? first_node_with_windows : NULL); central_node = results.CentralNode;
if (node->LastFocusedNodeID == 0 && first_node_with_windows != NULL)
node->LastFocusedNodeID = first_node_with_windows->ID;
// Copy the dock family from of our window so it can be used for proper dock filtering. // 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. // When node has mixed windows, prioritize the family with the most constraint (CompatibleWithNeutral = false) as the reference to copy.
if (first_node_with_windows) // FIXME-DOCK: We don't recurse properly, this code could be reworked to work from DockNodeUpdateScanRec.
if (ImGuiDockNode* first_node_with_windows = results.FirstNodeWithWindows)
{ {
node->DockFamily = first_node_with_windows->Windows[0]->DockFamily; node->DockFamily = first_node_with_windows->Windows[0]->DockFamily;
for (int n = 1; n < first_node_with_windows->Windows.Size; n++) for (int n = 1; n < first_node_with_windows->Windows.Size; n++)
@ -10546,7 +10581,6 @@ 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->IsRootNode() && node->IsLeafNode() && node->Windows.Size <= 1 && !node->IsDockSpace) if (node->IsRootNode() && node->IsLeafNode() && node->Windows.Size <= 1 && !node->IsDockSpace)
@ -10660,6 +10694,35 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
if (g.NavWindow && g.NavWindow->RootWindowDockStop->DockNode && g.NavWindow->RootWindowDockStop->ParentWindow == host_window) if (g.NavWindow && g.NavWindow->RootWindowDockStop->DockNode && g.NavWindow->RootWindowDockStop->ParentWindow == host_window)
node->LastFocusedNodeID = g.NavWindow->RootWindowDockStop->DockNode->ID; node->LastFocusedNodeID = g.NavWindow->RootWindowDockStop->DockNode->ID;
// We need to draw a background if requested by ImGuiDockNodeFlags_RenderWindowBg, 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_RenderWindowBg) != 0;
if (render_dockspace_bg)
{
host_window->DrawList->ChannelsSplit(2);
host_window->DrawList->ChannelsSetCurrent(1);
}
// Register a hit-test hole in the window unless we are currently dragging a window that is compatible our dockspace
bool central_node_hole = node->IsRootNode() && host_window && (node->Flags & ImGuiDockNodeFlags_PassthruInEmptyNodes) != 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())
if (payload->IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) && DockNodeIsDropAllowed(host_window, *(ImGuiWindow**)payload->Data))
central_node_hole_register_hit_test_hole = false;
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.
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);
central_hole.Expand(ImVec2(-RESIZE_WINDOWS_FROM_EDGES_HALF_THICKNESS, -RESIZE_WINDOWS_FROM_EDGES_HALF_THICKNESS));
if (central_node_hole && !central_hole.IsInverted())
{
SetWindowHitTestHole(host_window, central_hole.Min, central_hole.Max - central_hole.Min);
SetWindowHitTestHole(host_window->ParentWindow, central_hole.Min, central_hole.Max - central_hole.Min);
}
}
// Update position/size, process and draw resizing splitters // Update position/size, process and draw resizing splitters
if (node->IsRootNode() && host_window) if (node->IsRootNode() && host_window)
{ {
@ -10667,6 +10730,21 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
DockNodeTreeUpdateSplitter(node); DockNodeTreeUpdateSplitter(node);
} }
// Draw empty node background (currently can only be the Central Node)
if (host_window && node->IsEmpty() && node->IsVisible && !(node->Flags & ImGuiDockNodeFlags_PassthruInEmptyNodes))
host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, GetColorU32(ImGuiCol_DockingEmptyBg));
// Draw whole dockspace background if ImGuiDockNodeFlags_RenderWindowBg if set.
if (render_dockspace_bg && node->IsVisible)
{
host_window->DrawList->ChannelsSetCurrent(0);
if (central_node_hole)
RenderRectFilledWithHole(host_window->DrawList, node->Rect(), central_node->Rect(), GetColorU32(ImGuiCol_WindowBg), 0.0f);
else
host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, GetColorU32(ImGuiCol_WindowBg), 0.0f);
host_window->DrawList->ChannelsMerge();
}
// Draw and populate Tab Bar // Draw and populate Tab Bar
if (host_window && node->Windows.Size > 0) if (host_window && node->Windows.Size > 0)
{ {
@ -10681,16 +10759,11 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
if (node->Windows.Size > 0) if (node->Windows.Size > 0)
node->SelectedTabID = node->Windows[0]->ID; node->SelectedTabID = node->Windows[0]->ID;
} }
if (host_window && node->IsVisible)
{
// Background for empty nodes
if (node->Windows.Size == 0 && !node->IsSplitNode())
host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, GetColorU32(ImGuiCol_DockingEmptyBg));
// Draw drop target // Draw payload drop target
if (host_window && node->IsVisible)
if (node->IsRootNode() && (g.MovingWindow == NULL || g.MovingWindow->RootWindow != host_window)) if (node->IsRootNode() && (g.MovingWindow == NULL || g.MovingWindow->RootWindow != host_window))
BeginAsDockableDragDropTarget(host_window); BeginAsDockableDragDropTarget(host_window);
}
node->LastFrameActive = g.FrameCount; node->LastFrameActive = g.FrameCount;
@ -11060,7 +11133,7 @@ static bool ImGui::DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNo
data->IsCenterAvailable = !is_outer_docking; data->IsCenterAvailable = !is_outer_docking;
if (src_is_visibly_splitted && (!host_node || !host_node->IsEmpty())) if (src_is_visibly_splitted && (!host_node || !host_node->IsEmpty()))
data->IsCenterAvailable = false; data->IsCenterAvailable = false;
if (host_node && (host_node->Flags & ImGuiDockNodeFlags_NoDockingInsideCentralNode) && host_node->IsCentralNode) if (host_node && (host_node->Flags & ImGuiDockNodeFlags_NoDockingInCentralNode) && host_node->IsCentralNode)
data->IsCenterAvailable = false; data->IsCenterAvailable = false;
data->IsSidesAvailable = true; data->IsSidesAvailable = true;
@ -11568,10 +11641,8 @@ void ImGui::DockSpace(ImGuiID id, const ImVec2& size_arg, ImGuiDockNodeFlags doc
if (node->Windows.Size > 0 || node->IsSplitNode()) if (node->Windows.Size > 0 || node->IsSplitNode())
PushStyleColor(ImGuiCol_ChildBg, IM_COL32(0, 0, 0, 0)); PushStyleColor(ImGuiCol_ChildBg, IM_COL32(0, 0, 0, 0));
if (dockspace_flags & ImGuiDockNodeFlags_NoOuterBorder)
PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.0f); PushStyleVar(ImGuiStyleVar_ChildBorderSize, 0.0f);
Begin(title, NULL, window_flags); Begin(title, NULL, window_flags);
if (dockspace_flags & ImGuiDockNodeFlags_NoOuterBorder)
PopStyleVar(); PopStyleVar();
if (node->Windows.Size > 0 || node->IsSplitNode()) if (node->Windows.Size > 0 || node->IsSplitNode())
PopStyleColor(); PopStyleColor();
@ -11953,7 +12024,7 @@ void ImGui::BeginDocked(ImGuiWindow* window, bool* p_open)
} }
// Undock if the ImGuiDockNodeFlags_NoDockingInCentralNode got set // Undock if the ImGuiDockNodeFlags_NoDockingInCentralNode got set
if (dock_node->IsCentralNode && (dock_node->Flags & ImGuiDockNodeFlags_NoDockingInsideCentralNode)) if (dock_node->IsCentralNode && (dock_node->Flags & ImGuiDockNodeFlags_NoDockingInCentralNode))
{ {
DockContextProcessUndockWindow(ctx, window); DockContextProcessUndockWindow(ctx, window);
return; return;

View File

@ -798,8 +798,12 @@ enum ImGuiDockNodeFlags_
ImGuiDockNodeFlags_None = 0, 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_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) 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)
ImGuiDockNodeFlags_NoOuterBorder = 1 << 2, // Disable outer border on a DockSpace() node. //ImGuiDockNodeFlags_NoCentralNode = 1 << 2, // Disable Central Node (the node which can stay empty)
ImGuiDockNodeFlags_NoDockingInsideCentralNode = 1 << 3 // Disable docking inside the central node (which can stay empty). Useful if it is kept empty and invisible. //ImGuiDockNodeFlags_NoOuterBorder = 1 << 3, // Disable outer border on a DockSpace() node.
ImGuiDockNodeFlags_NoDockingInCentralNode = 1 << 4, // Disable docking inside the Central Node, which will be always kept empty.
ImGuiDockNodeFlags_PassthruInEmptyNodes = 1 << 5, // When Central Node is empty: let inputs pass-through + won't display a DockingEmptyBg background.
ImGuiDockNodeFlags_RenderWindowBg = 1 << 6, // DockSpace() will render a ImGuiCol_WindowBg background covering everything excepted the Central Node (when empty). Meaning the host window should properly use SetNextWindowBgAlpha(0.0f) + ImGuiDockNodeFlags_NoOuterBorder prior to Begin() when using this.
ImGuiDockNodeFlags_PassthruDockspace = ImGuiDockNodeFlags_NoDockingInCentralNode | ImGuiDockNodeFlags_RenderWindowBg | ImGuiDockNodeFlags_PassthruInEmptyNodes
}; };
// Flags for ImGui::IsWindowFocused() // Flags for ImGui::IsWindowFocused()

View File

@ -3715,13 +3715,12 @@ static void ShowExampleAppCustomRendering(bool* p_open)
void ShowExampleAppDockSpace(bool* p_open) void ShowExampleAppDockSpace(bool* p_open)
{ {
static bool opt_fullscreen_persistant = true; static bool opt_fullscreen_persistant = true;
static ImGuiDockNodeFlags opt_flags = ImGuiDockNodeFlags_None;
bool opt_fullscreen = opt_fullscreen_persistant; bool opt_fullscreen = opt_fullscreen_persistant;
// We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into. // We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
// Because 1) it would be confusing to have two docking targets within each others. // because it would be confusing to have two docking targets within each others.
// and 2) we want our main DockSpace node to always be visible (never hidden within a tab bar): if the DockSpace node disappear its child windows will be orphaned. ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
ImGuiWindowFlags flags = ImGuiWindowFlags_MenuBar;
flags |= ImGuiWindowFlags_NoDocking;
if (opt_fullscreen) if (opt_fullscreen)
{ {
ImGuiViewport* viewport = ImGui::GetMainViewport(); ImGuiViewport* viewport = ImGui::GetMainViewport();
@ -3729,14 +3728,20 @@ void ShowExampleAppDockSpace(bool* p_open)
ImGui::SetNextWindowSize(viewport->Size); ImGui::SetNextWindowSize(viewport->Size);
ImGui::SetNextWindowViewport(viewport->ID); ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
} }
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; // When using ImGuiDockNodeFlags_RenderWindowBg or ImGuiDockNodeFlags_InvisibleDockspace, DockSpace() will render our background and handle the pass-thru hole, so we ask Begin() to not render a background.
if (opt_flags & ImGuiDockNodeFlags_RenderWindowBg)
ImGui::SetNextWindowBgAlpha(0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); ImGui::Begin("DockSpace Demo", p_open, window_flags);
ImGui::Begin("DockSpace Demo", p_open, flags); ImGui::PopStyleVar();
if (opt_fullscreen)
ImGui::PopStyleVar(2); ImGui::PopStyleVar(2);
// Dockspace // Dockspace
@ -3744,7 +3749,7 @@ void ShowExampleAppDockSpace(bool* p_open)
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
{ {
ImGuiID dockspace_id = ImGui::GetID("MyDockspace"); ImGuiID dockspace_id = ImGui::GetID("MyDockspace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags | ImGuiDockNodeFlags_NoOuterBorder); ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), opt_flags);
} }
else else
{ {
@ -3753,21 +3758,21 @@ void ShowExampleAppDockSpace(bool* p_open)
if (ImGui::BeginMenuBar()) if (ImGui::BeginMenuBar())
{ {
if (ImGui::BeginMenu("Options")) if (ImGui::BeginMenu("Docking"))
{ {
if (ImGui::MenuItem("Remove DockSpace", NULL, false, p_open != NULL))
*p_open = false;
ImGui::Separator();
// Disabling fullscreen would allow the window to be moved to the front of other windows, // Disabling fullscreen would allow the window to be moved to the front of other windows,
// which we can't undo at the moment without finer window depth/z control. // which we can't undo at the moment without finer window depth/z control.
//ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen_persistant); //ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen_persistant);
if (ImGui::MenuItem("Flag: NoSplit", "", (dockspace_flags & ImGuiDockNodeFlags_NoSplit) != 0)) if (ImGui::MenuItem("Flag: NoSplit", "", (opt_flags & ImGuiDockNodeFlags_NoSplit) != 0)) opt_flags ^= ImGuiDockNodeFlags_NoSplit;
dockspace_flags ^= ImGuiDockNodeFlags_NoSplit; if (ImGui::MenuItem("Flag: NoDockingInCentralNode", "", (opt_flags & ImGuiDockNodeFlags_NoDockingInCentralNode) != 0)) opt_flags ^= ImGuiDockNodeFlags_NoDockingInCentralNode;
if (ImGui::MenuItem("Flag: NoDockingInsideCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingInsideCentralNode) != 0)) if (ImGui::MenuItem("Flag: PassthruInEmptyNodes", "", (opt_flags & ImGuiDockNodeFlags_PassthruInEmptyNodes) != 0)) opt_flags ^= ImGuiDockNodeFlags_PassthruInEmptyNodes;
dockspace_flags ^= ImGuiDockNodeFlags_NoDockingInsideCentralNode; if (ImGui::MenuItem("Flag: RenderWindowBg", "", (opt_flags & ImGuiDockNodeFlags_RenderWindowBg) != 0)) opt_flags ^= ImGuiDockNodeFlags_RenderWindowBg;
if (ImGui::MenuItem("Flag: PassthruDockspace (all 3 above)", "", (opt_flags & ImGuiDockNodeFlags_PassthruDockspace) == ImGuiDockNodeFlags_PassthruDockspace))
opt_flags = (opt_flags & ~ImGuiDockNodeFlags_PassthruDockspace) | ((opt_flags & ImGuiDockNodeFlags_PassthruDockspace) == ImGuiDockNodeFlags_PassthruDockspace) ? 0 : ImGuiDockNodeFlags_PassthruDockspace;
ImGui::Separator();
if (ImGui::MenuItem("Close DockSpace", NULL, false, p_open != NULL))
*p_open = false;
ImGui::EndMenu(); ImGui::EndMenu();
} }
ShowHelpMarker( ShowHelpMarker(
@ -3782,8 +3787,6 @@ void ShowExampleAppDockSpace(bool* p_open)
} }
ImGui::End(); ImGui::End();
if (opt_fullscreen)
ImGui::PopStyleVar();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -1218,6 +1218,7 @@ struct IMGUI_API ImGuiWindow
ImRect ClipRect; // Current clipping rectangle. = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. ImRect ClipRect; // Current clipping rectangle. = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2.
ImRect OuterRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. ImRect OuterRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window.
ImRect InnerMainRect, InnerClipRect; ImRect InnerMainRect, InnerClipRect;
ImVec2ih HitTestHoleSize, HitTestHoleOffset;
ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. Maximum visible content position ~~ Pos + (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. Maximum visible content position ~~ Pos + (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis
int LastFrameActive; // Last frame number the window was Active. int LastFrameActive; // Last frame number the window was Active.
float ItemWidthDefault; float ItemWidthDefault;