ImGuiNET / ImGui.NET

An ImGui wrapper for .NET.
MIT License
1.9k stars 304 forks source link

Issues/help with TreeNode [SOLVED] #392

Open tingspain opened 1 year ago

tingspain commented 1 year ago

Hi,

I would like to ask to the community for some help/hint with some issues I am having with the TreeNodes. I am sure I missing something conceptually, so I am sorry if my questions are too trivial.

1.- Buttons are only working for the first child node of the tree (ImGui.Selectable() widget). As I shown in the first part of the video, the buttons of the right side of each child node only work for the first node. As you can see in the video, the buttons for Object 1 node can be triggered, but the buttons for Object 2 or Object 3 nodes can not be triggered. I don't know what I am doing wrong.

2.- I would like to know how i can detect/handle when a click is made outside the Tree to clean the selection. I have tried ImGui.IsItemClicked() with the Window (ImGui.Begin()), with the Child Window (ImGui.BeginChild()) and Child Window Frame (ImGui.BeginChildFrame()) widgets but none of them worked. In the second part of the video, I show how I click outside the tree widget but not callbacks have been triggered. Any idea?

Thanks in advance for your time and help!!

VIDEO

https://user-images.githubusercontent.com/1858083/226227425-94dd758b-1d87-45b8-9fd5-a4814273b738.mov

CODE


if( ImGui.Begin("Scene") )
{

    bool win = ImGui.BeginChildFrame( ImGui.GetID("scene"), new System.Numerics.Vector2(0, 0) );

    // NOT WORKING
    if (ImGui.IsItemClicked())
    {
        ConsoleLogger.Debug("Clicking in the Window");
        selectedMesh = null;
    }

    if (win)
    {

        bool root = ImGui.TreeNodeEx("Scene", ImGuiTreeNodeFlags.DefaultOpen | ImGuiTreeNodeFlags.AllowItemOverlap);

        if (ImGui.IsItemClicked())
        {
            ConsoleLogger.Debug("Unselecting " + selectedMesh?.Name);
            selectedMesh = null;
        }

        ImGui.SameLine();

        ImGui.Dummy(new System.Numerics.Vector2(ImGui.GetContentRegionAvail().X - 50, 0));

        ImGui.SameLine();

        if (ImGui.SmallButton("+"))
            ImGui.OpenPopup("ElementList");

        if(ImGui.IsItemHovered())
            ImGui.SetTooltip("Create new Element");

        if (ImGui.BeginPopup("ElementList"))
        {
            ImGui.MenuItem("element 1");
            ImGui.MenuItem("element 2");
            ImGui.EndPopup();
        }

        ImGui.SameLine();

        if (ImGui.SmallButton("S"))
        {
            ConsoleLogger.Warn("Opening Settings");
        }

        if (root)
        {

            foreach (SimpleMesh curMesh in myscene)
            {
                bool curSelector = ImGui.Selectable(curMesh.Name, curMesh == selectedMesh ? true : false, ImGuiSelectableFlags.DontClosePopups | ImGuiSelectableFlags.AllowItemOverlap);

                ImGui.SameLine();

                ImGui.Dummy(new System.Numerics.Vector2(ImGui.GetContentRegionAvail().X - 50, 0));

                ImGui.SameLine();

                bool curBttnE = ImGui.Button("E");

                ImGui.SameLine();

                bool curBttnD = ImGui.Button("D");

                if (curSelector)
                {
                    selectedMesh = curMesh;
                    ConsoleLogger.Debug("Selecting " + selectedMesh?.Name);
                }

                if (curBttnE)
                    ConsoleLogger.Debug("Show/Hide Object " + curMesh.Name);

                if (curBttnD)
                    ConsoleLogger.Debug("Delete Object " + curMesh.Name);

            }

            ImGui.TreePop();

        }

        ImGui.EndChildFrame();
    }

    ImGui.End();
}
tingspain commented 1 year ago

Solutions for Problem 2:

I solved the issue with problem 2 by using ImGui.IsMouseDown() and ImGui.IsWindowHovered() at Window level.

Here you have the code:

if( ImGui.Begin("Scene") )
{

    bool win = ImGui.BeginChildFrame( ImGui.GetID("SceneFrame"), new System.Numerics.Vector2(0, 0) );

    // [SOLUTION PROBLEM 2] 
    // Reset selection when it is clicked outside the tree widget
    if (ImGui.IsMouseDown(ImGuiMouseButton.Left) && ImGui.IsWindowHovered() )
         selectedMesh = null;

    if (win)
    {

        bool root = ImGui.TreeNodeEx("Scene", ImGuiTreeNodeFlags.DefaultOpen | ImGuiTreeNodeFlags.AllowItemOverlap);

        if (ImGui.IsItemClicked())
        {
            ConsoleLogger.Debug("Unselecting " + selectedMesh?.Name);
            selectedMesh = null;
        }

        ImGui.SameLine();

        ImGui.Dummy(new System.Numerics.Vector2(ImGui.GetContentRegionAvail().X - 50, 0));

        ImGui.SameLine();

        if (ImGui.SmallButton("+"))
            ImGui.OpenPopup("ElementList");

        if(ImGui.IsItemHovered())
            ImGui.SetTooltip("Create new Element");

        if (ImGui.BeginPopup("ElementList"))
        {
            ImGui.MenuItem("element 1");
            ImGui.MenuItem("element 2");
            ImGui.EndPopup();
        }

        ImGui.SameLine();

        if (ImGui.SmallButton("S"))
        {
            ConsoleLogger.Warn("Opening Settings");
        }

        if (root)
        {

            foreach (SimpleMesh curMesh in myscene)
            {
                bool curSelector = ImGui.Selectable(curMesh.Name, curMesh == selectedMesh ? true : false, ImGuiSelectableFlags.DontClosePopups | ImGuiSelectableFlags.AllowItemOverlap);

                ImGui.SameLine();

                ImGui.Dummy(new System.Numerics.Vector2(ImGui.GetContentRegionAvail().X - 50, 0));

                ImGui.SameLine();

                bool curBttnE = ImGui.Button("E");

                ImGui.SameLine();

                bool curBttnD = ImGui.Button("D");

                if (curSelector)
                {
                    selectedMesh = curMesh;
                    ConsoleLogger.Debug("Selecting " + selectedMesh?.Name);
                }

                if (curBttnE)
                    ConsoleLogger.Debug("Show/Hide Object " + curMesh.Name);

                if (curBttnD)
                    ConsoleLogger.Debug("Delete Object " + curMesh.Name);

            }

            ImGui.TreePop();

        }

        ImGui.EndChildFrame();
    }

    ImGui.End();
}
tingspain commented 1 year ago

I managed to solve my two issues. I dont know if it is the most optimal way, but It is working fine. just in case, anyone want to achieve the same I pasted my solution.

SOLUTION

VIDEO

https://user-images.githubusercontent.com/1858083/226493048-9683eb01-e28b-4ed4-9f11-373dcc9771a7.mov

CODE


if( ImGui.Begin("Scene") )
{

    bool win = ImGui.BeginChildFrame( ImGui.GetID("SceneFrame"), new System.Numerics.Vector2(0, 0) );

    // [SOLUTION PROBLEM 2 AND PARTIALLY PROBLEM 1] 
    // Reset selection when it is clicked outside the tree widget
    if (ImGui.IsMouseDown(ImGuiMouseButton.Left) && ImGui.IsWindowHovered() && !ImGui.IsAnyItemHovered())
        selectedMesh = null;

    if (win)
    {

        bool root = ImGui.TreeNodeEx("Scene", ImGuiTreeNodeFlags.DefaultOpen | ImGuiTreeNodeFlags.AllowItemOverlap);

        if (ImGui.IsItemClicked())
        {
            ConsoleLogger.Debug("Unselecting " + selectedMesh?.Name);
            selectedMesh = null;
        }

        ImGui.SameLine();

        ImGui.Dummy(new System.Numerics.Vector2(ImGui.GetContentRegionAvail().X - 50, 0));

        ImGui.SameLine();

        if (ImGui.SmallButton("+"))
            ImGui.OpenPopup("ElementList");

        if(ImGui.IsItemHovered())
            ImGui.SetTooltip("Create new Element");

        if (ImGui.BeginPopup("ElementList"))
        {
            ImGui.MenuItem("element 1");
            ImGui.MenuItem("element 2");
            ImGui.EndPopup();
        }

        ImGui.SameLine();

        if (ImGui.SmallButton("S"))
            ConsoleLogger.Warn("Opening Settings");

        if (root)
        {

            ImGui.Unindent(ImGui.GetTreeNodeToLabelSpacing());

            foreach (SimpleMesh curMesh in myscene)
            {
                // [SOLUTION PROBLEM 1] 
                ImGui.TreePush(curMesh.Name);

                bool curSelector = ImGui.Selectable(curMesh.Name, curMesh == selectedMesh ? true : false, ImGuiSelectableFlags.AllowItemOverlap );

                ImGui.SameLine();

                ImGui.Dummy(new System.Numerics.Vector2(ImGui.GetContentRegionAvail().X - 50, 0));

                ImGui.SameLine();

                if (ImGui.SmallButton("E"))
                    ConsoleLogger.Debug("Show/Hide Object " + curMesh.Name);

                ImGui.SameLine();

                if (ImGui.SmallButton("D"))
                    ConsoleLogger.Debug("Delete Object " + curMesh.Name);

                if (curSelector)
                    selectedMesh = curMesh;

                // [SOLUTION PROBLEM 1] 
                ImGui.TreePop();
            }

            ImGui.Indent(ImGui.GetTreeNodeToLabelSpacing());

            ImGui.TreePop();

        }

        ImGui.EndChildFrame();
    }

    ImGui.End();
}