Alternate rendering mode with lines in a tree view?
Version/Branch of Dear ImGui:
Version: 1.75 Branch: master
Complex trees can be hard to read
When editing complex trees, it is often hard to figure out which node a node is the child of.
Here is an example with a behavior tree:

Here, it is difficult to tell at first glance that the parent of the node called "do JumpSafeFastAntiAir" is the "Parallel Selector".
In that case, an alternate rendering mode à là old school windows would be useful :

Tentative :

Here I am imagining a version that detects when the lines are usefull (only when there are several levels under a node, or one or several a nodes at the end). It may be a little bit tricky to implement in immediate mode.
It looks possible to implement, the problem being that it would be harder to combine with clipping nodes.
Hello @ocornut, I've implemented a simple tree line rendering in my application with the following algorithm (not the actual code, just an approximation/pseudocode):
//returns the node's rectangle
ImRect RenderTree(Node* n)
{
const bool recurse = ImGui::TreeNode(...);
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if (recurse)
{
const ImColor TreeLineColor = ImGui::GetColorU32(ImGuiCol_Text);
const float SmallOffsetX = 11.0f; //for now, a hardcoded value; should take into account tree indent size
ImDrawList* drawList = ImGui::GetWindowDrawList();
ImVec2 verticalLineStart = ImGui::GetCursorScreenPos();
verticalLineStart.x += SmallOffsetX; //to nicely line up with the arrow symbol
ImVec2 verticalLineEnd = verticalLineStart;
for (Node* child : *n)
{
const float HorizontalTreeLineSize = 8.0f; //chosen arbitrarily
const ImRect childRect = RenderTree(child);
const float midpoint = (childRect.Min.y + childRect.Max.y) / 2.0f;
drawList->AddLine(ImVec2(verticalLineStart.x, midpoint), ImVec(verticalLineStart.x + HorizontalTreeLineSize, midpoint), TreeLineColor);
verticalLineEnd.y = midpoint;
}
drawList->AddLine(verticalLineStart, verticalLineEnd, TreeLineColor);
}
return nodeRect;
}
Attaching screenshots from the app with and without bulleted leaf nodes:


I can implement it directly in the library if it's OK for you, though I'd need some suggestions about any API changes that would have to be introduced. I imagine that not everyone wants to have the treelines drawn, so maybe there should be a flag exposed for this. And/or another color in ImGuiCol_ enum?
Looks a lot nicer when the treelines are drawn with ImColor(128, 128, 128, 255):

I would imagine
- Make it optional with a flag.
- Another color in ImGuiStyle.
- Making it work with TreeNode/TreePop will require some custom internal storage
- As mentioned, figuring out how to handle clipping patterns would be good (TreeNode not visible, or using of ImGuiListClipper leading to not submit TreeNode - even if today tree nodes are not frequently clipped.)
Hello @ocornut, I need some advice on implementing this feature.
What I wanted to do is to add a ImGuiTreeNodeFlags_IndentLines flag that, when turned on, would indicate the need to draw the tree indent lines. Also, I would add a ImVector<ImVec2> field to the struct ImGuiWindowTempData, where I can store the coordinates of the stack of tree elements. Each TreePush() pushes a coordinate, TreePop() pops the coordinate and draws the vertical line.
Unfortunately, TreePop() has no knowledge about flags used for drawing the corresponding tree node, therefore it cannot decide whether to draw the vertical lines or not. I can extend the aforementioned stack in ImGuiWindowTempData with such information, though I need your thoughts on this idea. Is extending ImGuiWindowTempData in such way is acceptable?
I know this issue is pretty old, but did anything come of it? I am looking to do the same thing - draw lines to indicate the relationships between tree nodes.
Unfortunately, TreePop() has no knowledge about flags used for drawing the corresponding tree node, therefore it cannot decide whether to draw the vertical lines or not. I can extend the aforementioned stack in ImGuiWindowTempData with such information, though I need your thoughts on this idea. Is extending ImGuiWindowTempData in such way is acceptable?
The flag ImGuiTreeNodeFlags_NavLeftJumpsBackHere to use left arrow to jump back to parent had similar issue/requirement, which I implemented as the ImVector<ImGuiNavTreeNodeData> NavTreeNodeStack array in context (doesn't need to be per window). But I was careful that this would only be used when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is used. For the purpose of TreePop() the information of whether this is available is stored in TreeJumpToParentOnPopMask. So I guess we can extend this data/struct to be a more general mask storing if the ImGuiNavTreeNodeData data was pushed, and add tree flags into it.
I'll see if I can tackle this sometimes.
I have pushed some minor rework to facilitate implementing this.
Here's a very quick proof of concept implemented in <10 lines of code: imgui-19c05ac-WIP TreeNode todying with experimental ImGuiTreeNodeFlags_DrawTreeLines() (#2920).patch
We would a nicer version that takes account of childs etc, but we now should have enough data for it.
Looking great so far! Really looking forward to this.. our designers have complained about this kind of thing a few times already.
Here's a better version:
It's a rather small patch: imgui-4405c5e-WIP TreeNode todying with experimental ImGuiTreeNodeFlags_DrawTreeLines() (#2920).patch
I'll try to polish tomorrow (probably add style variables) before pushing. It's always on in this patch, as a test. Feedback of edge cases welcome.
@ocornut both tree styles looks awesome! I think its one of the most wanted feature, when we use tree view in any kind of custom editors. Its looks really as tree view, not as nested collapsible items.
I have published a version of this now: e5b218e6d1e1943ca211522be322cbcf57db4477
- TreeNode: added flags to draw tree hierarchy outlines linking parent and tree nodes: (#2920)
- ImGuiTreeNodeFlags_DrawLinesNone: No lines drawn. (default)
- ImGuiTreeNodeFlags_DrawLinesFull: Horizontal lines to child nodes. Vertical line drawn down to TreePop() position: cover full contents.
- ImGuiTreeNodeFlags_DrawLinesToNodes: Horizontal lines to child nodes. Vertical line drawn down to bottom-most child node.
- Added style.TreeLinesFlags which stores the default setting, which may be overriden in individual TreeNode() calls.
- Added style.TreeLinesSize (default to 1.0f).
- Added ImGuiCol_TreeLines (in default style this is the same as ImGuiCol_Border).
- The feature adds a little cost as extra data needs to be stored.
The default shared style is None but it'd be tempted to change it if this works well enough.
I had to iterate quite a bit on design and performances, and ended up with the default setting being a shared style thing, but nodes can override it.
Also gave up on latching the color value as it adds too much overhead on very large trees since it has to be conservatively done on many clipped node.
Pushed several fixes to this (4 commits linked above).
Pushed more fixes (5 commits above).
@ocornut once again, great work! Thank you very much. I am looking forward for the next release of imgui. ^___^
Closing this as solved.