1
0
mirror of https://github.com/Drezil/imgui.git synced 2025-04-02 09:22:44 +00:00

Docking: Fix for node created at the same time as windows that are still resizing (typically with io.ConfigDockingAlwaysTabBar) to not be zero/min sized. ()

The fix delay their visibility by one frame, which is not ideal but not very problematic as the .ini data gets populated after that
This commit is contained in:
omar 2019-08-21 15:07:28 +02:00
parent a01d149369
commit 9e294be5c5
2 changed files with 50 additions and 0 deletions

@ -11206,6 +11206,7 @@ namespace ImGui
static void DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window, bool add_to_tab_bar);
static void DockNodeMoveWindows(ImGuiDockNode* dst_node, ImGuiDockNode* src_node);
static void DockNodeMoveChildNodes(ImGuiDockNode* dst_node, ImGuiDockNode* src_node);
static ImGuiWindow* DockNodeFindWindowByID(ImGuiDockNode* node, ImGuiID id);
static void DockNodeApplyPosSizeToWindows(ImGuiDockNode* node);
static void DockNodeRemoveWindow(ImGuiDockNode* node, ImGuiWindow* window, ImGuiID save_dock_id);
static void DockNodeHideHostWindow(ImGuiDockNode* node);
@ -11846,6 +11847,7 @@ bool ImGui::DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode*
// - DockNodeHideHostWindow()
// - ImGuiDockNodeFindInfoResults
// - DockNodeFindInfo()
// - DockNodeFindWindowByID()
// - DockNodeUpdateVisibleFlagAndInactiveChilds()
// - DockNodeUpdateVisibleFlag()
// - DockNodeStartMouseMovingWindow()
@ -11871,6 +11873,7 @@ ImGuiDockNode::ImGuiDockNode(ImGuiID id)
TabBar = NULL;
SplitAxis = ImGuiAxis_None;
State = ImGuiDockNodeState_Unknown;
HostWindow = VisibleWindow = NULL;
CentralNode = OnlyNodeWithWindows = NULL;
LastFrameAlive = LastFrameActive = LastFrameFocused = -1;
@ -12131,6 +12134,15 @@ static void DockNodeFindInfo(ImGuiDockNode* node, ImGuiDockNodeFindInfoResults*
DockNodeFindInfo(node->ChildNodes[1], results);
}
static ImGuiWindow* ImGui::DockNodeFindWindowByID(ImGuiDockNode* node, ImGuiID id)
{
IM_ASSERT(id != 0);
for (int n = 0; n < node->Windows.Size; n++)
if (node->Windows[n]->ID == id)
return node->Windows[n];
return NULL;
}
// - Remove inactive windows/nodes.
// - Update visibility flag.
static void ImGui::DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* node)
@ -12169,6 +12181,7 @@ static void ImGui::DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* nod
if (node->Windows.Size == 1 && !node->IsCentralNode())
{
DockNodeHideHostWindow(node);
node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
DockNodeRemoveWindow(node, window, node->ID); // Will delete the node so it'll be invalid on return
return;
}
@ -12285,6 +12298,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
}
DockNodeHideHostWindow(node);
node->State = ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow;
node->WantCloseAll = false;
node->WantCloseTabID = 0;
node->HasCloseButton = node->HasWindowMenuButton = node->EnableCloseButton = false;
@ -12295,6 +12309,31 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
return;
}
// In some circumstance we will defer creating the host window (so everything will be kept hidden),
// while the expected visible window is resizing itself.
// This is important for first-time (no ini settings restored) single window when io.ConfigDockingAlwaysTabBar is enabled,
// otherwise the node ends up using the minimum window size. Effectively those windows will take an extra frame to show up:
// N+0: Begin(): window created (with no known size), node is created
// N+1: DockNodeUpdate(): node skip creating host window / Begin(): window size applied, not visible
// N+2: DockNodeUpdate(): node can create host window / Begin(): window becomes visible
// We could remove this frame if we could reliably calculate the expected window size during node update, before the Begin() code.
// It would require a generalization of CalcWindowExpectedSize(), probably extracting code away from Begin().
// In reality it isn't very important as user quickly ends up with size data in .ini file.
if (node->IsVisible && node->HostWindow == NULL && node->IsFloatingNode() && node->IsLeafNode())
{
IM_ASSERT(node->Windows.Size > 0);
ImGuiWindow* ref_window = NULL;
if (node->SelectedTabID != 0) // Note that we prune single-window-node settings on .ini loading, so this is generally 0 for them!
ref_window = DockNodeFindWindowByID(node, node->SelectedTabID);
if (ref_window == NULL)
ref_window = node->Windows[0];
if (ref_window->AutoFitFramesX > 0 || ref_window->AutoFitFramesY > 0)
{
node->State = ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing;
return;
}
}
const ImGuiDockNodeFlags node_flags = node->GetMergedFlags();
// Bind or create host window
@ -14161,6 +14200,7 @@ void ImGui::BeginDocked(ImGuiWindow* window, bool* p_open)
// FIXME-DOCK: replace ->HostWindow NULL compare with something more explicit (~was initially intended as a first frame test)
if (node->HostWindow == NULL)
{
window->DockIsActive = (node->State == ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing);
window->DockTabIsVisible = false;
return;
}
@ -14168,6 +14208,7 @@ void ImGui::BeginDocked(ImGuiWindow* window, bool* p_open)
IM_ASSERT(node->HostWindow);
IM_ASSERT(node->IsLeafNode());
IM_ASSERT(node->Size.x > 0.0f && node->Size.y > 0.0f);
node->State = ImGuiDockNodeState_HostWindowVisible;
// Undock if we are submitted earlier than the host window
if (window->BeginOrderWithinContext < node->HostWindow->BeginOrderWithinContext)

@ -929,6 +929,14 @@ enum ImGuiDataAuthority_
ImGuiDataAuthority_Window
};
enum ImGuiDockNodeState
{
ImGuiDockNodeState_Unknown,
ImGuiDockNodeState_HostWindowHiddenBecauseSingleWindow,
ImGuiDockNodeState_HostWindowHiddenBecauseWindowsAreResizing,
ImGuiDockNodeState_HostWindowVisible
};
// sizeof() 116~160
struct ImGuiDockNode
{
@ -945,6 +953,7 @@ struct ImGuiDockNode
int SplitAxis; // [Split node only] Split axis (X or Y)
ImGuiWindowClass WindowClass;
ImGuiDockNodeState State;
ImGuiWindow* HostWindow;
ImGuiWindow* VisibleWindow; // Generally point to window which is ID is == SelectedTabID, but when CTRL+Tabbing this can be a different window.
ImGuiDockNode* CentralNode; // [Root node only] Pointer to central node.