|
@@ -4528,6 +4528,8 @@ static void AddWindowToDrawData(ImGuiWindow* window, int layer)
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiViewportP* viewport = window->Viewport;
|
|
|
g.IO.MetricsRenderWindows++;
|
|
|
+ if (window->Flags & ImGuiWindowFlags_DockNodeHost)
|
|
|
+ window->DrawList->ChannelsMerge();
|
|
|
AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[layer], window->DrawList);
|
|
|
for (int i = 0; i < window->DC.ChildWindows.Size; i++)
|
|
|
{
|
|
@@ -4709,6 +4711,9 @@ void ImGui::EndFrame()
|
|
|
// Update navigation: CTRL+Tab, wrap-around requests
|
|
|
NavEndFrame();
|
|
|
|
|
|
+ // Update docking
|
|
|
+ DockContextEndFrame(&g);
|
|
|
+
|
|
|
SetCurrentViewport(NULL, NULL);
|
|
|
|
|
|
// Drag and Drop: Elapse payload (if delivered, or if source stops being submitted)
|
|
@@ -5653,11 +5658,11 @@ ImVec2 ImGui::CalcWindowNextAutoFitSize(ImGuiWindow* window)
|
|
|
return size_final;
|
|
|
}
|
|
|
|
|
|
-static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags)
|
|
|
+static ImGuiCol GetWindowBgColorIdx(ImGuiWindow* window)
|
|
|
{
|
|
|
- if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
|
|
|
+ if (window->Flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
|
|
|
return ImGuiCol_PopupBg;
|
|
|
- if (flags & ImGuiWindowFlags_ChildWindow)
|
|
|
+ if ((window->Flags & ImGuiWindowFlags_ChildWindow) && !window->DockIsActive)
|
|
|
return ImGuiCol_ChildBg;
|
|
|
return ImGuiCol_WindowBg;
|
|
|
}
|
|
@@ -5950,7 +5955,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
|
|
if (g.DragDropPayload.IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) && *(ImGuiWindow**)g.DragDropPayload.Data == window)
|
|
|
is_docking_transparent_payload = true;
|
|
|
|
|
|
- ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags));
|
|
|
+ ImU32 bg_col = GetColorU32(GetWindowBgColorIdx(window));
|
|
|
if (window->ViewportOwned)
|
|
|
{
|
|
|
// No alpha
|
|
@@ -5976,8 +5981,21 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
|
|
if (override_alpha)
|
|
|
bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
|
|
|
}
|
|
|
- window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
|
|
|
+
|
|
|
+ // Render, for docked windows and host windows we ensure bg goes before decorations
|
|
|
+ ImDrawList* bg_draw_list = window->DockIsActive ? window->DockNode->HostWindow->DrawList : window->DrawList;
|
|
|
+ if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
|
|
|
+ bg_draw_list->ChannelsSetCurrent(0);
|
|
|
+ if (window->DockIsActive)
|
|
|
+ window->DockNode->LastBgColor = bg_col;
|
|
|
+
|
|
|
+ bg_draw_list->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
|
|
|
+
|
|
|
+ if (window->DockIsActive || (flags & ImGuiWindowFlags_DockNodeHost))
|
|
|
+ bg_draw_list->ChannelsSetCurrent(1);
|
|
|
}
|
|
|
+ if (window->DockIsActive)
|
|
|
+ window->DockNode->IsBgDrawnThisFrame = true;
|
|
|
|
|
|
// Title bar
|
|
|
// (when docked, DockNode are drawing their own title bar. Individual windows however do NOT set the _NoTitleBar flag,
|
|
@@ -6346,6 +6364,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
window->IDStack.resize(1);
|
|
|
window->DrawList->_ResetForNewFrame();
|
|
|
window->DC.CurrentTableIdx = -1;
|
|
|
+ if (flags & ImGuiWindowFlags_DockNodeHost)
|
|
|
+ {
|
|
|
+ window->DrawList->ChannelsSplit(2);
|
|
|
+ window->DrawList->ChannelsSetCurrent(1); // Render decorations on channel 1 as we will render the backgrounds manually later
|
|
|
+ }
|
|
|
|
|
|
// Restore buffer capacity when woken from a compacted state, to avoid
|
|
|
if (window->MemoryCompacted)
|
|
@@ -12786,6 +12809,9 @@ void ImGui::DestroyPlatformWindows()
|
|
|
// | BeginDockableDragDropTarget()
|
|
|
// | - DockNodePreviewDockRender()
|
|
|
//-----------------------------------------------------------------------------
|
|
|
+// - EndFrame()
|
|
|
+// | DockContextEndFrame()
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// Docking: Internal Types
|
|
@@ -12940,6 +12966,7 @@ namespace ImGui
|
|
|
// - DockContextRebuildNodes()
|
|
|
// - DockContextNewFrameUpdateUndocking()
|
|
|
// - DockContextNewFrameUpdateDocking()
|
|
|
+// - DockContextEndFrame()
|
|
|
// - DockContextFindNodeByID()
|
|
|
// - DockContextBindNodeToWindow()
|
|
|
// - DockContextGenNodeID()
|
|
@@ -13075,6 +13102,22 @@ void ImGui::DockContextNewFrameUpdateDocking(ImGuiContext* ctx)
|
|
|
DockNodeUpdate(node);
|
|
|
}
|
|
|
|
|
|
+void ImGui::DockContextEndFrame(ImGuiContext* ctx)
|
|
|
+{
|
|
|
+ // Draw backgrounds of node missing their window
|
|
|
+ ImGuiContext& g = *ctx;
|
|
|
+ ImGuiDockContext* dc = &g.DockContext;
|
|
|
+ for (int n = 0; n < dc->Nodes.Data.Size; n++)
|
|
|
+ if (ImGuiDockNode* node = (ImGuiDockNode*)dc->Nodes.Data[n].val_p)
|
|
|
+ if (node->LastFrameActive == g.FrameCount && node->IsVisible && node->HostWindow && node->IsLeafNode() && !node->IsBgDrawnThisFrame)
|
|
|
+ {
|
|
|
+ ImRect bg_rect(node->Pos + ImVec2(0.0f, GetFrameHeight()), node->Pos + node->Size);
|
|
|
+ ImDrawFlags bg_rounding_flags = CalcRoundingFlagsForRectInRect(bg_rect, node->HostWindow->Rect(), DOCKING_SPLITTER_SIZE);
|
|
|
+ node->HostWindow->DrawList->ChannelsSetCurrent(0);
|
|
|
+ node->HostWindow->DrawList->AddRectFilled(bg_rect.Min, bg_rect.Max, node->LastBgColor, node->HostWindow->WindowRounding, bg_rounding_flags);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static ImGuiDockNode* ImGui::DockContextFindNodeByID(ImGuiContext* ctx, ImGuiID id)
|
|
|
{
|
|
|
return (ImGuiDockNode*)ctx->DockContext.Nodes.GetVoidPtr(id);
|
|
@@ -13592,6 +13635,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id)
|
|
|
SplitAxis = ImGuiAxis_None;
|
|
|
|
|
|
State = ImGuiDockNodeState_Unknown;
|
|
|
+ LastBgColor = IM_COL32_WHITE;
|
|
|
HostWindow = VisibleWindow = NULL;
|
|
|
CentralNode = OnlyNodeWithWindows = NULL;
|
|
|
CountNodeWithWindows = 0;
|
|
@@ -13603,6 +13647,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id)
|
|
|
AuthorityForViewport = ImGuiDataAuthority_Auto;
|
|
|
IsVisible = true;
|
|
|
IsFocused = HasCloseButton = HasWindowMenuButton = HasCentralNodeChild = false;
|
|
|
+ IsBgDrawnThisFrame = false;
|
|
|
WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle = false;
|
|
|
}
|
|
|
|
|
@@ -14044,6 +14089,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
IM_ASSERT(node->LastFrameActive != g.FrameCount);
|
|
|
node->LastFrameAlive = g.FrameCount;
|
|
|
+ node->IsBgDrawnThisFrame = false;
|
|
|
|
|
|
node->CentralNode = node->OnlyNodeWithWindows = NULL;
|
|
|
if (node->IsRootNode())
|
|
@@ -14186,6 +14232,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
|
|
window_flags |= ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoCollapse;
|
|
|
window_flags |= ImGuiWindowFlags_NoTitleBar;
|
|
|
|
|
|
+ SetNextWindowBgAlpha(0.0f); // Don't set ImGuiWindowFlags_NoBackground because it disables borders
|
|
|
PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
|
|
Begin(window_label, NULL, window_flags);
|
|
|
PopStyleVar();
|
|
@@ -14224,15 +14271,6 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
|
|
if (g.NavWindow && g.NavWindow->RootWindow->DockNode && g.NavWindow->RootWindow->ParentWindow == host_window)
|
|
|
node->LastFocusedNodeId = g.NavWindow->RootWindow->DockNode->ID;
|
|
|
|
|
|
- // 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_PassthruCentralNode) != 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 with our dockspace
|
|
|
ImGuiDockNode* central_node = node->CentralNode;
|
|
|
const bool central_node_hole = node->IsRootNode() && host_window && (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0 && central_node != NULL && central_node->IsEmpty();
|
|
@@ -14265,15 +14303,25 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
|
|
// Update position/size, process and draw resizing splitters
|
|
|
if (node->IsRootNode() && host_window)
|
|
|
{
|
|
|
+ host_window->DrawList->ChannelsSetCurrent(1);
|
|
|
DockNodeTreeUpdatePosSize(node, host_window->Pos, host_window->Size);
|
|
|
DockNodeTreeUpdateSplitter(node);
|
|
|
}
|
|
|
|
|
|
// Draw empty node background (currently can only be the Central Node)
|
|
|
- if (host_window && node->IsEmpty() && node->IsVisible && !(node_flags & ImGuiDockNodeFlags_PassthruCentralNode))
|
|
|
- host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, GetColorU32(ImGuiCol_DockingEmptyBg));
|
|
|
+ if (host_window && node->IsEmpty() && node->IsVisible)
|
|
|
+ {
|
|
|
+ host_window->DrawList->ChannelsSetCurrent(0);
|
|
|
+ node->LastBgColor = (node_flags & ImGuiDockNodeFlags_PassthruCentralNode) ? 0 : GetColorU32(ImGuiCol_DockingEmptyBg);
|
|
|
+ if (node->LastBgColor != 0)
|
|
|
+ host_window->DrawList->AddRectFilled(node->Pos, node->Pos + node->Size, node->LastBgColor);
|
|
|
+ node->IsBgDrawnThisFrame = true;
|
|
|
+ }
|
|
|
|
|
|
// Draw whole dockspace background if ImGuiDockNodeFlags_PassthruCentralNode if set.
|
|
|
+ // 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_PassthruCentralNode) != 0;
|
|
|
if (render_dockspace_bg && node->IsVisible)
|
|
|
{
|
|
|
host_window->DrawList->ChannelsSetCurrent(0);
|
|
@@ -14281,10 +14329,11 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
|
|
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
|
|
|
+ if (host_window)
|
|
|
+ host_window->DrawList->ChannelsSetCurrent(1);
|
|
|
if (host_window && node->Windows.Size > 0)
|
|
|
{
|
|
|
DockNodeUpdateTabBar(node, host_window);
|
|
@@ -14319,7 +14368,13 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
|
|
|
|
|
|
// Render outer borders last (after the tab bar)
|
|
|
if (node->IsRootNode())
|
|
|
+ {
|
|
|
+ host_window->DrawList->ChannelsSetCurrent(1);
|
|
|
RenderWindowOuterBorders(host_window);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Further rendering (= hosted windows background) will be drawn on layer 0
|
|
|
+ host_window->DrawList->ChannelsSetCurrent(0);
|
|
|
}
|
|
|
|
|
|
// End host window
|
|
@@ -15330,7 +15385,8 @@ void ImGui::DockNodeTreeUpdateSplitter(ImGuiDockNode* node)
|
|
|
float cur_size_1 = child_1->Size[axis];
|
|
|
float min_size_0 = resize_limits[0] - child_0->Pos[axis];
|
|
|
float min_size_1 = child_1->Pos[axis] + child_1->Size[axis] - resize_limits[1];
|
|
|
- if (SplitterBehavior(bb, GetID("##Splitter"), axis, &cur_size_0, &cur_size_1, min_size_0, min_size_1, WINDOWS_HOVER_PADDING, WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER))
|
|
|
+ ImU32 bg_col = GetColorU32(ImGuiCol_WindowBg);
|
|
|
+ if (SplitterBehavior(bb, GetID("##Splitter"), axis, &cur_size_0, &cur_size_1, min_size_0, min_size_1, WINDOWS_HOVER_PADDING, WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER, bg_col))
|
|
|
{
|
|
|
if (touching_nodes[0].Size > 0 && touching_nodes[1].Size > 0)
|
|
|
{
|
|
@@ -16061,7 +16117,9 @@ static ImGuiDockNode* ImGui::DockContextBindNodeToWindow(ImGuiContext* ctx, ImGu
|
|
|
}
|
|
|
|
|
|
// Add window to node
|
|
|
+ bool node_was_visible = node->IsVisible;
|
|
|
DockNodeAddWindow(node, window, true);
|
|
|
+ node->IsVisible = node_was_visible; // Don't mark visible right away (so DockContextEndFrame() doesn't render it, maybe other side effects? will see)
|
|
|
IM_ASSERT(node == window->DockNode);
|
|
|
return node;
|
|
|
}
|