From 9943137d1e926d4e4901c5721fea249c8ee4355f Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 10 Apr 2025 17:25:06 +0200 Subject: [PATCH] TreeNode: fixed non-opened clipped child node not moving Y2 marker. (#2920) --- imgui.cpp | 2 +- imgui_internal.h | 3 ++- imgui_widgets.cpp | 8 ++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b32874ec5..c7566494b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7649,7 +7649,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.MenuBarAppending = false; window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user); window->DC.TreeDepth = 0; - window->DC.TreeHasStackDataDepthMask = 0x00; + window->DC.TreeHasStackDataDepthMask = window->DC.TreeRecordsClippedNodesY2Mask = 0x00; window->DC.ChildWindows.resize(0); window->DC.StateStorage = &window->StateStorage; window->DC.CurrentColumns = NULL; diff --git a/imgui_internal.h b/imgui_internal.h index d5155e425..65de255f5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2474,7 +2474,8 @@ struct IMGUI_API ImGuiWindowTempData ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs. ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement int TreeDepth; // Current tree depth. - ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary. + ImU32 TreeHasStackDataDepthMask; // Store whether given depth has ImGuiTreeNodeStackData data. Could be turned into a ImU64 if necessary. + ImU32 TreeRecordsClippedNodesY2Mask; // Store whether we should keep recording Y2. Cleared when passing clip max. Equivalent TreeHasStackDataDepthMask value should always be set. ImVector ChildWindows; ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state) ImGuiOldColumns* CurrentColumns; // Current columns set diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 13c1362b1..140ceb9e1 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6564,9 +6564,11 @@ static void TreeNodeStoreStackData(ImGuiTreeNodeFlags flags, float x1) // Initially I tried to latch value for GetColorU32(ImGuiCol_TreeLines) but it's not a good trade-off for very large trees. const bool draw_lines = (flags & (ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DrawLinesToNodes)) != 0; tree_node_data->DrawLinesX1 = draw_lines ? (x1 + g.FontSize * 0.5f + g.Style.FramePadding.x) : +FLT_MAX; - tree_node_data->DrawLinesTableColumn = draw_lines && g.CurrentTable ? (ImGuiTableColumnIdx)g.CurrentTable->CurrentColumn : -1; + tree_node_data->DrawLinesTableColumn = (draw_lines && g.CurrentTable) ? (ImGuiTableColumnIdx)g.CurrentTable->CurrentColumn : -1; tree_node_data->DrawLinesToNodesY2 = -FLT_MAX; window->DC.TreeHasStackDataDepthMask |= (1 << window->DC.TreeDepth); + if (flags & ImGuiTreeNodeFlags_DrawLinesToNodes) + window->DC.TreeRecordsClippedNodesY2Mask |= (1 << window->DC.TreeDepth); } // When using public API, currently 'id == storage_id' is always true, but we separate the values to facilitate advanced user code doing storage queries outside of UI loop. @@ -6656,10 +6658,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; if (!is_visible) { - if (draw_tree_lines && (flags & ImGuiTreeNodeFlags_DrawLinesToNodes) && (window->DC.TreeHasStackDataDepthMask & (1 << window->DC.TreeDepth))) + if ((flags & ImGuiTreeNodeFlags_DrawLinesToNodes) && (window->DC.TreeRecordsClippedNodesY2Mask & (1 << (window->DC.TreeDepth - 1)))) { ImGuiTreeNodeStackData* parent_data = &g.TreeNodeStack.Data[g.TreeNodeStack.Size - 1]; parent_data->DrawLinesToNodesY2 = ImMax(parent_data->DrawLinesToNodesY2, window->DC.CursorPos.y); // Don't need to aim to mid Y position as we are clipped anyway. + if (frame_bb.Min.y >= window->ClipRect.Max.y) + window->DC.TreeRecordsClippedNodesY2Mask &= ~(1 << (window->DC.TreeDepth - 1)); // Done } if (is_open && store_tree_node_stack_data) TreeNodeStoreStackData(flags, text_pos.x - text_offset_x); // Call before TreePushOverrideID()