@ -4528,6 +4528,8 @@ static void AddWindowToDrawData(ImGuiWindow* window, int layer)
ImGuiContext & g = * GImGui ;
ImGuiContext & g = * GImGui ;
ImGuiViewportP * viewport = window - > Viewport ;
ImGuiViewportP * viewport = window - > Viewport ;
g . IO . MetricsRenderWindows + + ;
g . IO . MetricsRenderWindows + + ;
if ( window - > Flags & ImGuiWindowFlags_DockNodeHost )
window - > DrawList - > ChannelsMerge ( ) ;
AddDrawListToDrawData ( & viewport - > DrawDataBuilder . Layers [ layer ] , window - > DrawList ) ;
AddDrawListToDrawData ( & viewport - > DrawDataBuilder . Layers [ layer ] , window - > DrawList ) ;
for ( int i = 0 ; i < window - > DC . ChildWindows . Size ; i + + )
for ( int i = 0 ; i < window - > DC . ChildWindows . Size ; i + + )
{
{
@ -4709,6 +4711,9 @@ void ImGui::EndFrame()
// Update navigation: CTRL+Tab, wrap-around requests
// Update navigation: CTRL+Tab, wrap-around requests
NavEndFrame ( ) ;
NavEndFrame ( ) ;
// Update docking
DockContextEndFrame ( & g ) ;
SetCurrentViewport ( NULL , NULL ) ;
SetCurrentViewport ( NULL , NULL ) ;
// Drag and Drop: Elapse payload (if delivered, or if source stops being submitted)
// 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 ;
return size_final ;
}
}
static ImGuiCol GetWindowBgColorIdx FromFlags( ImGuiWindowFlags flags )
static ImGuiCol GetWindowBgColorIdx ( ImGuiWindow * window )
{
{
if ( f lags & ( ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup ) )
if ( window- > F lags & ( ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup ) )
return ImGuiCol_PopupBg ;
return ImGuiCol_PopupBg ;
if ( f lags & ImGuiWindowFlags_ChildWindow )
if ( ( window - > F lags & ImGuiWindowFlags_ChildWindow ) & & ! window - > DockIsActive )
return ImGuiCol_ChildBg ;
return ImGuiCol_ChildBg ;
return ImGuiCol_WindowBg ;
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 )
if ( g . DragDropPayload . IsDataType ( IMGUI_PAYLOAD_TYPE_WINDOW ) & & * ( ImGuiWindow * * ) g . DragDropPayload . Data = = window )
is_docking_transparent_payload = true ;
is_docking_transparent_payload = true ;
ImU32 bg_col = GetColorU32 ( GetWindowBgColorIdx FromFlags( flags ) ) ;
ImU32 bg_col = GetColorU32 ( GetWindowBgColorIdx ( window ) ) ;
if ( window - > ViewportOwned )
if ( window - > ViewportOwned )
{
{
// No alpha
// No alpha
@ -5976,8 +5981,21 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
if ( override_alpha )
if ( override_alpha )
bg_col = ( bg_col & ~ IM_COL32_A_MASK ) | ( IM_F32_TO_INT8_SAT ( alpha ) < < IM_COL32_A_SHIFT ) ;
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
// Title bar
// (when docked, DockNode are drawing their own title bar. Individual windows however do NOT set the _NoTitleBar flag,
// (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 - > IDStack . resize ( 1 ) ;
window - > DrawList - > _ResetForNewFrame ( ) ;
window - > DrawList - > _ResetForNewFrame ( ) ;
window - > DC . CurrentTableIdx = - 1 ;
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
// Restore buffer capacity when woken from a compacted state, to avoid
if ( window - > MemoryCompacted )
if ( window - > MemoryCompacted )
@ -12786,6 +12809,9 @@ void ImGui::DestroyPlatformWindows()
// | BeginDockableDragDropTarget()
// | BeginDockableDragDropTarget()
// | - DockNodePreviewDockRender()
// | - DockNodePreviewDockRender()
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// - EndFrame()
// | DockContextEndFrame()
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Docking: Internal Types
// Docking: Internal Types
@ -12940,6 +12966,7 @@ namespace ImGui
// - DockContextRebuildNodes()
// - DockContextRebuildNodes()
// - DockContextNewFrameUpdateUndocking()
// - DockContextNewFrameUpdateUndocking()
// - DockContextNewFrameUpdateDocking()
// - DockContextNewFrameUpdateDocking()
// - DockContextEndFrame()
// - DockContextFindNodeByID()
// - DockContextFindNodeByID()
// - DockContextBindNodeToWindow()
// - DockContextBindNodeToWindow()
// - DockContextGenNodeID()
// - DockContextGenNodeID()
@ -13075,6 +13102,22 @@ void ImGui::DockContextNewFrameUpdateDocking(ImGuiContext* ctx)
DockNodeUpdate ( node ) ;
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 )
static ImGuiDockNode * ImGui : : DockContextFindNodeByID ( ImGuiContext * ctx , ImGuiID id )
{
{
return ( ImGuiDockNode * ) ctx - > DockContext . Nodes . GetVoidPtr ( id ) ;
return ( ImGuiDockNode * ) ctx - > DockContext . Nodes . GetVoidPtr ( id ) ;
@ -13592,6 +13635,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id)
SplitAxis = ImGuiAxis_None ;
SplitAxis = ImGuiAxis_None ;
State = ImGuiDockNodeState_Unknown ;
State = ImGuiDockNodeState_Unknown ;
LastBgColor = IM_COL32_WHITE ;
HostWindow = VisibleWindow = NULL ;
HostWindow = VisibleWindow = NULL ;
CentralNode = OnlyNodeWithWindows = NULL ;
CentralNode = OnlyNodeWithWindows = NULL ;
CountNodeWithWindows = 0 ;
CountNodeWithWindows = 0 ;
@ -13603,6 +13647,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id)
AuthorityForViewport = ImGuiDataAuthority_Auto ;
AuthorityForViewport = ImGuiDataAuthority_Auto ;
IsVisible = true ;
IsVisible = true ;
IsFocused = HasCloseButton = HasWindowMenuButton = HasCentralNodeChild = false ;
IsFocused = HasCloseButton = HasWindowMenuButton = HasCentralNodeChild = false ;
IsBgDrawnThisFrame = false ;
WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle = false ;
WantCloseAll = WantLockSizeOnce = WantMouseMove = WantHiddenTabBarUpdate = WantHiddenTabBarToggle = false ;
}
}
@ -14044,6 +14089,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
ImGuiContext & g = * GImGui ;
ImGuiContext & g = * GImGui ;
IM_ASSERT ( node - > LastFrameActive ! = g . FrameCount ) ;
IM_ASSERT ( node - > LastFrameActive ! = g . FrameCount ) ;
node - > LastFrameAlive = g . FrameCount ;
node - > LastFrameAlive = g . FrameCount ;
node - > IsBgDrawnThisFrame = false ;
node - > CentralNode = node - > OnlyNodeWithWindows = NULL ;
node - > CentralNode = node - > OnlyNodeWithWindows = NULL ;
if ( node - > IsRootNode ( ) )
if ( node - > IsRootNode ( ) )
@ -14186,6 +14232,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
window_flags | = ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoCollapse ;
window_flags | = ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoCollapse ;
window_flags | = ImGuiWindowFlags_NoTitleBar ;
window_flags | = ImGuiWindowFlags_NoTitleBar ;
SetNextWindowBgAlpha ( 0.0f ) ; // Don't set ImGuiWindowFlags_NoBackground because it disables borders
PushStyleVar ( ImGuiStyleVar_WindowPadding , ImVec2 ( 0 , 0 ) ) ;
PushStyleVar ( ImGuiStyleVar_WindowPadding , ImVec2 ( 0 , 0 ) ) ;
Begin ( window_label , NULL , window_flags ) ;
Begin ( window_label , NULL , window_flags ) ;
PopStyleVar ( ) ;
PopStyleVar ( ) ;
@ -14224,15 +14271,6 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
if ( g . NavWindow & & g . NavWindow - > RootWindow - > DockNode & & g . NavWindow - > RootWindow - > ParentWindow = = host_window )
if ( g . NavWindow & & g . NavWindow - > RootWindow - > DockNode & & g . NavWindow - > RootWindow - > ParentWindow = = host_window )
node - > LastFocusedNodeId = g . NavWindow - > RootWindow - > DockNode - > ID ;
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
// 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 ;
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 ( ) ;
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
// Update position/size, process and draw resizing splitters
if ( node - > IsRootNode ( ) & & host_window )
if ( node - > IsRootNode ( ) & & host_window )
{
{
host_window - > DrawList - > ChannelsSetCurrent ( 1 ) ;
DockNodeTreeUpdatePosSize ( node , host_window - > Pos , host_window - > Size ) ;
DockNodeTreeUpdatePosSize ( node , host_window - > Pos , host_window - > Size ) ;
DockNodeTreeUpdateSplitter ( node ) ;
DockNodeTreeUpdateSplitter ( node ) ;
}
}
// Draw empty node background (currently can only be the Central Node)
// Draw empty node background (currently can only be the Central Node)
if ( host_window & & node - > IsEmpty ( ) & & node - > IsVisible & & ! ( node_flags & ImGuiDockNodeFlags_PassthruCentralNode ) )
if ( host_window & & node - > IsEmpty ( ) & & node - > IsVisible )
host_window - > DrawList - > AddRectFilled ( node - > Pos , node - > Pos + node - > Size , GetColorU32 ( ImGuiCol_DockingEmptyBg ) ) ;
{
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.
// 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 )
if ( render_dockspace_bg & & node - > IsVisible )
{
{
host_window - > DrawList - > ChannelsSetCurrent ( 0 ) ;
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 ) ;
RenderRectFilledWithHole ( host_window - > DrawList , node - > Rect ( ) , central_node - > Rect ( ) , GetColorU32 ( ImGuiCol_WindowBg ) , 0.0f ) ;
else
else
host_window - > DrawList - > AddRectFilled ( node - > Pos , node - > Pos + node - > Size , GetColorU32 ( ImGuiCol_WindowBg ) , 0.0f ) ;
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 )
host_window - > DrawList - > ChannelsSetCurrent ( 1 ) ;
if ( host_window & & node - > Windows . Size > 0 )
if ( host_window & & node - > Windows . Size > 0 )
{
{
DockNodeUpdateTabBar ( node , host_window ) ;
DockNodeUpdateTabBar ( node , host_window ) ;
@ -14319,9 +14368,15 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
// Render outer borders last (after the tab bar)
// Render outer borders last (after the tab bar)
if ( node - > IsRootNode ( ) )
if ( node - > IsRootNode ( ) )
{
host_window - > DrawList - > ChannelsSetCurrent ( 1 ) ;
RenderWindowOuterBorders ( host_window ) ;
RenderWindowOuterBorders ( host_window ) ;
}
}
// Further rendering (= hosted windows background) will be drawn on layer 0
host_window - > DrawList - > ChannelsSetCurrent ( 0 ) ;
}
// End host window
// End host window
if ( beginned_into_host_window ) //-V1020
if ( beginned_into_host_window ) //-V1020
End ( ) ;
End ( ) ;
@ -15330,7 +15385,8 @@ void ImGui::DockNodeTreeUpdateSplitter(ImGuiDockNode* node)
float cur_size_1 = child_1 - > Size [ axis ] ;
float cur_size_1 = child_1 - > Size [ axis ] ;
float min_size_0 = resize_limits [ 0 ] - child_0 - > Pos [ 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 ] ;
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 )
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
// Add window to node
bool node_was_visible = node - > IsVisible ;
DockNodeAddWindow ( node , window , true ) ;
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 ) ;
IM_ASSERT ( node = = window - > DockNode ) ;
return node ;
return node ;
}
}