imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Alternate rendering mode with lines in a tree view?

Open BurgerBob opened this issue 6 years ago • 15 comments

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: Tree view

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 : image

Tentative : image

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.

BurgerBob avatar Dec 05 '19 22:12 BurgerBob

It looks possible to implement, the problem being that it would be harder to combine with clipping nodes.

ocornut avatar Dec 17 '19 13:12 ocornut

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:

image

image

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?

szreder avatar Apr 17 '20 10:04 szreder

Looks a lot nicer when the treelines are drawn with ImColor(128, 128, 128, 255):

image

szreder avatar Apr 17 '20 10:04 szreder

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.)

ocornut avatar Apr 18 '20 09:04 ocornut

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?

szreder avatar Apr 25 '20 20:04 szreder

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.

Sage-of-Mirrors avatar Oct 11 '23 03:10 Sage-of-Mirrors

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.

ocornut avatar Jun 27 '24 09:06 ocornut

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

image

We would a nicer version that takes account of childs etc, but we now should have enough data for it.

ocornut avatar Jul 03 '24 17:07 ocornut

Looking great so far! Really looking forward to this.. our designers have complained about this kind of thing a few times already.

n00bmind avatar Jul 08 '24 14:07 n00bmind

Here's a better version: Image

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 avatar Apr 03 '25 18:04 ocornut

@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.

inobelar avatar Apr 04 '25 19:04 inobelar

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.

ocornut avatar Apr 08 '25 18:04 ocornut

Pushed several fixes to this (4 commits linked above).

ocornut avatar Apr 09 '25 17:04 ocornut

Pushed more fixes (5 commits above).

ocornut avatar Apr 10 '25 15:04 ocornut

@ocornut once again, great work! Thank you very much. I am looking forward for the next release of imgui. ^___^

tingspain avatar Apr 14 '25 13:04 tingspain

Closing this as solved.

Image

ocornut avatar Jun 25 '25 16:06 ocornut